| 1 | /******************************************************************************* |
|---|
| 2 | * |
|---|
| 3 | * McStas, neutron ray-tracing package |
|---|
| 4 | * Copyright (C) 1997-2009, All rights reserved |
|---|
| 5 | * Risoe National Laboratory, Roskilde, Denmark |
|---|
| 6 | * Institut Laue Langevin, Grenoble, France |
|---|
| 7 | * |
|---|
| 8 | * Instrument: mcformat, McStas format converter |
|---|
| 9 | * |
|---|
| 10 | * %Identification |
|---|
| 11 | * Written by: <a href="mailto:farhi@ill.fr">Emmanuel Farhi</a> |
|---|
| 12 | * Date: 1st Feb 2001. |
|---|
| 13 | * Origin: <a href="http://www.ill.fr">ILL (France)</a> |
|---|
| 14 | * Release: McStas 1.12b |
|---|
| 15 | * Version: $Revision: 1.36 $ |
|---|
| 16 | * |
|---|
| 17 | * A McStas format converter to merge/convert data files. |
|---|
| 18 | * |
|---|
| 19 | * %Description |
|---|
| 20 | * |
|---|
| 21 | * A McStas format converter to merge convert data files. |
|---|
| 22 | * Parameters are the files/directories to process, and option flags. |
|---|
| 23 | * May be used to: |
|---|
| 24 | * 1- continue an interupted simulation, and then add (--merge option) the similar |
|---|
| 25 | * data files. |
|---|
| 26 | * 2- generate complex data formats to be used using different viewer from |
|---|
| 27 | * original simple text format (--format=...). |
|---|
| 28 | * 3- catenate list files |
|---|
| 29 | * 4- reconstruct parameter scan sumulations (--scan) |
|---|
| 30 | * |
|---|
| 31 | * Limitations: can not convert from binary files; Conversion from HTML/VRML |
|---|
| 32 | * may fail; does not handle event files. |
|---|
| 33 | * |
|---|
| 34 | * %Parameters |
|---|
| 35 | * INPUT PARAMETERS: |
|---|
| 36 | * files [string]: list of files/directories to convert, separated by spaces |
|---|
| 37 | * |
|---|
| 38 | * %Link |
|---|
| 39 | * |
|---|
| 40 | * %End |
|---|
| 41 | *******************************************************************************/ |
|---|
| 42 | |
|---|
| 43 | #ifndef MCFORMAT |
|---|
| 44 | #define MCFORMAT "$Revision: 1.36 $" /* avoid memory.c to define Pool functions */ |
|---|
| 45 | #endif |
|---|
| 46 | |
|---|
| 47 | #ifdef USE_MPI |
|---|
| 48 | #undef USE_MPI |
|---|
| 49 | #endif |
|---|
| 50 | |
|---|
| 51 | #ifdef USE_THREADS |
|---|
| 52 | #undef USE_THREADS |
|---|
| 53 | #endif |
|---|
| 54 | |
|---|
| 55 | #ifndef MCSTAS_VERSION |
|---|
| 56 | #define MCSTAS_VERSION "1.12b - June 2010" |
|---|
| 57 | #endif |
|---|
| 58 | |
|---|
| 59 | /* Instead of including mcstas.h file, which would then require to link most |
|---|
| 60 | of the functions of the mcstas executable, we just put there some parts of |
|---|
| 61 | the mcstas.h file. |
|---|
| 62 | Build: cc -o mcformat mcformat.c -lm |
|---|
| 63 | */ |
|---|
| 64 | |
|---|
| 65 | #define fatal_error printf /* remove debug.c dependency */ |
|---|
| 66 | #define debug(msg) |
|---|
| 67 | |
|---|
| 68 | #define MCSTAS_H /* avoids memory.c to import mcstas.h */ |
|---|
| 69 | typedef struct Pool_header *Pool; /* allows memory to be included */ |
|---|
| 70 | #include "memory.c" |
|---|
| 71 | |
|---|
| 72 | #include "lib/share/mcstas-r.h" /* with decl of MC_PATHSEP */ |
|---|
| 73 | |
|---|
| 74 | #ifdef USE_NEXUS |
|---|
| 75 | #include "lib/share/nexus-lib.h" |
|---|
| 76 | #endif |
|---|
| 77 | |
|---|
| 78 | #include "lib/share/mcstas-r.c" |
|---|
| 79 | |
|---|
| 80 | /* end of parts copied from mcstas.h */ |
|---|
| 81 | |
|---|
| 82 | #include "lib/share/read_table-lib.h" /* independent library */ |
|---|
| 83 | #include "lib/share/read_table-lib.c" |
|---|
| 84 | |
|---|
| 85 | #include <dirent.h> |
|---|
| 86 | #include <errno.h> |
|---|
| 87 | |
|---|
| 88 | /* Functions defined in memory.c */ |
|---|
| 89 | |
|---|
| 90 | void *mem(size_t); /* Allocate memory. */ |
|---|
| 91 | void memfree(void *); /* Free memory. */ |
|---|
| 92 | char *str_dup(char *); /* Allocate new copy of string. */ |
|---|
| 93 | char *str_dup_n(char *string, int n); /* Copies only first N chars. */ |
|---|
| 94 | char *str_cat(char *first, ...);/* Concatenate strings to allocated string. */ |
|---|
| 95 | char *str_quote(char *string); /* Quote string for inclusion in C code */ |
|---|
| 96 | void str_free(char *); /* Free memory for string. */ |
|---|
| 97 | |
|---|
| 98 | /* default global variables required by mcstas-r (usually generated in cogen) */ |
|---|
| 99 | int mcdefaultmain = 1; |
|---|
| 100 | int mctraceenabled = 0; |
|---|
| 101 | char mcinstrument_name[CHAR_BUF_LENGTH]; |
|---|
| 102 | char mcinstrument_source[CHAR_BUF_LENGTH]; |
|---|
| 103 | int mcnumipar = 0; |
|---|
| 104 | struct mcinputtable_struct mcinputtable[CHAR_BUF_LENGTH]; |
|---|
| 105 | mcstatic FILE *mcsiminfo_file = NULL; |
|---|
| 106 | |
|---|
| 107 | #ifdef USE_NEXUS |
|---|
| 108 | #include "lib/share/nexus-lib.c" |
|---|
| 109 | #endif |
|---|
| 110 | |
|---|
| 111 | |
|---|
| 112 | /* default global variables for mcformat converter */ |
|---|
| 113 | int files_to_convert_NB = 0; /* nb of files to convert */ |
|---|
| 114 | int files_to_convert_Array[CHAR_BUF_LENGTH]; /* index of argv[] for these files */ |
|---|
| 115 | char mcforcemode =0; |
|---|
| 116 | char mcverbose =0; |
|---|
| 117 | char mctestmode =0; |
|---|
| 118 | char mcmergemode =0; |
|---|
| 119 | char mcscanmode =0; |
|---|
| 120 | char mcmergesamedir=0; |
|---|
| 121 | int mcdircount =0; /* number of directories scanned */ |
|---|
| 122 | int mcnbconvert =0; /* index of current file */ |
|---|
| 123 | FILE **mcsimfiles; |
|---|
| 124 | char **mcdirnames; |
|---|
| 125 | char **mcinstrnames; |
|---|
| 126 | char **mcsources; |
|---|
| 127 | char *mcoutputdir=NULL; |
|---|
| 128 | int ipar_var =0; /* column index of scan variable (used in mcformat_scan_compare) */ |
|---|
| 129 | |
|---|
| 130 | struct fileparts_struct { |
|---|
| 131 | char *FullName; |
|---|
| 132 | char *Path; |
|---|
| 133 | char *Name; |
|---|
| 134 | char *Extension; |
|---|
| 135 | }; |
|---|
| 136 | |
|---|
| 137 | /* list of functions ******************************************************** */ |
|---|
| 138 | /* |
|---|
| 139 | char *str_dup_numeric(char *orig) |
|---|
| 140 | char *str_dup_name(char *orig, int length) |
|---|
| 141 | char *str_dup_label(char *orig) |
|---|
| 142 | char *str_last_word(char *orig) |
|---|
| 143 | struct fileparts_struct fileparts_init(void) |
|---|
| 144 | struct fileparts_struct fileparts(char *name) |
|---|
| 145 | void fileparts_free(struct fileparts_struct parts) |
|---|
| 146 | struct McStas_file_format mcformat_init_mcstas_struct(void) |
|---|
| 147 | void mcformat_print_mcstas_struct(struct McStas_file_format McStasStruct) |
|---|
| 148 | struct McStas_file_format mcformat_free_mcstas_struct(struct McStas_file_format McStasStruct) |
|---|
| 149 | struct McStas_file_format mcformat_read_mcstas(char *filename) |
|---|
| 150 | int mcformat_dirwalk(char *dir, int (*fcn)(char *)) |
|---|
| 151 | static void mcformat_usedir(char *dir) |
|---|
| 152 | int mcformat_output(struct McStas_file_format McStasStruct) |
|---|
| 153 | int mcformat_convert(char *name) |
|---|
| 154 | int mcformat_count(char *name) |
|---|
| 155 | int mcformat_merge_compare(int nb) |
|---|
| 156 | void mcformat_scan_compare(int nb) |
|---|
| 157 | int mcformat_merge_output(int nb) |
|---|
| 158 | void mcformat_usage(char *pgmname) |
|---|
| 159 | void mcformat_parseoptions(int argc, char *argv[]) |
|---|
| 160 | int main(int argc, char *argv[]) |
|---|
| 161 | */ |
|---|
| 162 | |
|---|
| 163 | /******************************************************************************* |
|---|
| 164 | * str_dup_numeric: makes a clean copy of a string and allocate as numeric |
|---|
| 165 | *******************************************************************************/ |
|---|
| 166 | char *str_dup_numeric(char *orig) |
|---|
| 167 | { |
|---|
| 168 | long i; |
|---|
| 169 | char *valid; |
|---|
| 170 | |
|---|
| 171 | if (!orig || !strlen(orig)) return(NULL); |
|---|
| 172 | |
|---|
| 173 | for (i=0; i < strlen(orig); i++) |
|---|
| 174 | { |
|---|
| 175 | if ( (orig[i] > 122) |
|---|
| 176 | || (orig[i] < 32) |
|---|
| 177 | || (strchr("!\"#$%&'()*,:;<=>?@[\\]^`/ ", orig[i]) != NULL) ) |
|---|
| 178 | { |
|---|
| 179 | orig[i] = ' '; |
|---|
| 180 | } |
|---|
| 181 | } |
|---|
| 182 | orig[i] = '\0'; |
|---|
| 183 | /* now skip spaces */ |
|---|
| 184 | for (i=0; i < strlen(orig); i++) { |
|---|
| 185 | if (*orig == ' ') orig++; |
|---|
| 186 | else break; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | valid=str_dup(orig); |
|---|
| 190 | |
|---|
| 191 | return(valid); |
|---|
| 192 | } /* str_dup_numeric */ |
|---|
| 193 | |
|---|
| 194 | /******************************************************************************* |
|---|
| 195 | * str_dup_name: makes a clean copy of a string and allocate as name |
|---|
| 196 | *******************************************************************************/ |
|---|
| 197 | char *str_dup_name(char *orig, int length) |
|---|
| 198 | { |
|---|
| 199 | char *valid; |
|---|
| 200 | |
|---|
| 201 | if (!orig || !strlen(orig)) return(NULL); |
|---|
| 202 | |
|---|
| 203 | valid=str_dup_n(orig, length > 0 ? length : strlen(orig)); |
|---|
| 204 | mcvalid_name(valid, orig, 0); |
|---|
| 205 | |
|---|
| 206 | return(valid); |
|---|
| 207 | } /* str_dup_name */ |
|---|
| 208 | |
|---|
| 209 | /******************************************************************************* |
|---|
| 210 | * str_dup_label: makes a clean copy of a string and allocate as label/title |
|---|
| 211 | *******************************************************************************/ |
|---|
| 212 | char *str_dup_label(char *orig) |
|---|
| 213 | { |
|---|
| 214 | long i; |
|---|
| 215 | char *valid; |
|---|
| 216 | int length=0; |
|---|
| 217 | |
|---|
| 218 | if (!orig || !strlen(orig)) return(NULL); |
|---|
| 219 | |
|---|
| 220 | for (i=0; i < strlen(orig); i++) |
|---|
| 221 | { |
|---|
| 222 | if ( (orig[i] > 122) |
|---|
| 223 | || (orig[i] < 32) |
|---|
| 224 | || (strchr("\"'=:;", orig[i]) != NULL) ) |
|---|
| 225 | { |
|---|
| 226 | orig[i] = ' '; |
|---|
| 227 | } |
|---|
| 228 | } |
|---|
| 229 | orig[i] = '\0'; |
|---|
| 230 | /* now skip spaces at begining */ |
|---|
| 231 | for (i=0; i < strlen(orig); i++) { |
|---|
| 232 | if (*orig == ' ') orig++; |
|---|
| 233 | else break; |
|---|
| 234 | } |
|---|
| 235 | length = strlen(orig); |
|---|
| 236 | /* skip trailing blanks */ |
|---|
| 237 | for (i=strlen(orig)-1; i > 0; i--) { |
|---|
| 238 | if (orig[i] == ' ') length--; |
|---|
| 239 | else break; |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | valid=str_dup_n(orig, length); |
|---|
| 243 | |
|---|
| 244 | return(valid); |
|---|
| 245 | } /* str_dup_label */ |
|---|
| 246 | |
|---|
| 247 | /******************************************************************************* |
|---|
| 248 | * str_last_word: points to last word of string |
|---|
| 249 | *******************************************************************************/ |
|---|
| 250 | char *str_last_word(char *orig) |
|---|
| 251 | { |
|---|
| 252 | char *pos_end =NULL; |
|---|
| 253 | char *pos_begin=NULL; |
|---|
| 254 | char separators[]= MC_PATHSEP_S " !\"#$%&'()*,:;<=>?@[\\]^`/."; |
|---|
| 255 | |
|---|
| 256 | /* first skip trailing separators */ |
|---|
| 257 | pos_end = orig+strlen(orig); |
|---|
| 258 | while (pos_end > orig) { |
|---|
| 259 | if (strchr(separators, *pos_end)) pos_end--; /* pass separators at the end */ |
|---|
| 260 | else break; |
|---|
| 261 | } |
|---|
| 262 | pos_begin = pos_end-1; |
|---|
| 263 | /* search for non separators (pass word) */ |
|---|
| 264 | while (pos_begin >= orig) { |
|---|
| 265 | if (!strchr(separators, *pos_begin)) pos_begin--; /* pass non separators */ |
|---|
| 266 | else break; |
|---|
| 267 | } |
|---|
| 268 | pos_begin++; |
|---|
| 269 | |
|---|
| 270 | if (pos_begin < orig) pos_begin=orig; |
|---|
| 271 | |
|---|
| 272 | return(pos_begin); |
|---|
| 273 | } /* str_last_word */ |
|---|
| 274 | |
|---|
| 275 | |
|---|
| 276 | /******************************************************************************* |
|---|
| 277 | * fileparts_init: Initialize a zero fileparts structure |
|---|
| 278 | *******************************************************************************/ |
|---|
| 279 | struct fileparts_struct fileparts_init(void) |
|---|
| 280 | { |
|---|
| 281 | struct fileparts_struct parts; |
|---|
| 282 | |
|---|
| 283 | parts.FullName = NULL; |
|---|
| 284 | parts.Path = NULL; |
|---|
| 285 | parts.Name = NULL; |
|---|
| 286 | parts.Extension = NULL; |
|---|
| 287 | |
|---|
| 288 | return(parts); |
|---|
| 289 | } /* fileparts_init */ |
|---|
| 290 | |
|---|
| 291 | /******************************************************************************* |
|---|
| 292 | * fileparts: Split a fully qualified file name/path into pieces |
|---|
| 293 | * Returns a zero structure if called with NULL argument. |
|---|
| 294 | * Returns: fields are non NULL if they exist |
|---|
| 295 | * Path is NULL if no Path |
|---|
| 296 | * Name is NULL if just a Path |
|---|
| 297 | * Extension is "" if just a dot |
|---|
| 298 | *******************************************************************************/ |
|---|
| 299 | struct fileparts_struct fileparts(char *name) |
|---|
| 300 | { |
|---|
| 301 | struct fileparts_struct parts; |
|---|
| 302 | |
|---|
| 303 | parts = fileparts_init(); |
|---|
| 304 | |
|---|
| 305 | if (name) { |
|---|
| 306 | char *dot_pos = NULL; |
|---|
| 307 | char *path_pos = NULL; |
|---|
| 308 | char *end_pos = NULL; |
|---|
| 309 | char *name_pos = NULL; |
|---|
| 310 | long dot_length = 0; |
|---|
| 311 | long path_length= 0; |
|---|
| 312 | long name_length= 0; |
|---|
| 313 | |
|---|
| 314 | parts.FullName = str_dup(name); |
|---|
| 315 | /* extract path+filename+extension from full filename */ |
|---|
| 316 | |
|---|
| 317 | if (strlen(name) == 0) return(parts); |
|---|
| 318 | |
|---|
| 319 | end_pos = name+strlen(name); /* end of file name */ |
|---|
| 320 | |
|---|
| 321 | /* extract path: searches for last file separator */ |
|---|
| 322 | path_pos= strrchr(name, MC_PATHSEP_C); /* last PATHSEP */ |
|---|
| 323 | |
|---|
| 324 | if (!path_pos) { |
|---|
| 325 | path_pos =name; |
|---|
| 326 | path_length=0; |
|---|
| 327 | name_pos =name; |
|---|
| 328 | parts.Path = str_dup(""); |
|---|
| 329 | } else { |
|---|
| 330 | name_pos = path_pos+1; |
|---|
| 331 | path_length = name_pos - name; /* from start to path+sep */ |
|---|
| 332 | if (path_length) { |
|---|
| 333 | parts.Path = str_cat(name, MC_PATHSEP_S, NULL); |
|---|
| 334 | strncpy(parts.Path, name, path_length); |
|---|
| 335 | parts.Path[path_length]='\0'; |
|---|
| 336 | } else parts.Path = str_dup(""); |
|---|
| 337 | } |
|---|
| 338 | |
|---|
| 339 | /* extract ext: now looks for the 'dot' */ |
|---|
| 340 | dot_pos = strrchr(name_pos, '.'); /* last dot */ |
|---|
| 341 | if (dot_pos > name_pos) { |
|---|
| 342 | dot_length = end_pos - dot_pos; |
|---|
| 343 | if (dot_length > 0) { |
|---|
| 344 | parts.Extension = str_dup(name); |
|---|
| 345 | strncpy(parts.Extension, dot_pos+1, dot_length); /* skip the dot */ |
|---|
| 346 | parts.Extension[dot_length]='\0'; |
|---|
| 347 | } |
|---|
| 348 | } else dot_pos = end_pos; |
|---|
| 349 | |
|---|
| 350 | /* extract Name (without extension) */ |
|---|
| 351 | name_length = dot_pos - name_pos; /* from path to dot */ |
|---|
| 352 | if (name_length) { |
|---|
| 353 | parts.Name = str_dup(name); |
|---|
| 354 | strncpy(parts.Name, name_pos, name_length); |
|---|
| 355 | parts.Name[name_length]='\0'; |
|---|
| 356 | } |
|---|
| 357 | } /* if (name) */ |
|---|
| 358 | return (parts); |
|---|
| 359 | } /* fileparts */ |
|---|
| 360 | |
|---|
| 361 | /******************************************************************************* |
|---|
| 362 | * fileparts_free: Free a fileparts_struct fields |
|---|
| 363 | *******************************************************************************/ |
|---|
| 364 | void fileparts_free(struct fileparts_struct parts) |
|---|
| 365 | { |
|---|
| 366 | str_free(parts.FullName); |
|---|
| 367 | str_free(parts.Path); |
|---|
| 368 | str_free(parts.Name); |
|---|
| 369 | str_free(parts.Extension); |
|---|
| 370 | } /* fileparts_free */ |
|---|
| 371 | |
|---|
| 372 | struct McStas_file_format { |
|---|
| 373 | char *Source; |
|---|
| 374 | char *Creator; |
|---|
| 375 | char *Editor; |
|---|
| 376 | char *InstrName; |
|---|
| 377 | char *filename; |
|---|
| 378 | char *Format; |
|---|
| 379 | char *Date; |
|---|
| 380 | char *EndDate; |
|---|
| 381 | double Ncount; |
|---|
| 382 | char *component; |
|---|
| 383 | char *type; |
|---|
| 384 | char *title; |
|---|
| 385 | char *xlabel; |
|---|
| 386 | char *ylabel; |
|---|
| 387 | char *zlabel; |
|---|
| 388 | char *xvar; |
|---|
| 389 | char *yvar; |
|---|
| 390 | char *zvar; |
|---|
| 391 | char *xylimits; |
|---|
| 392 | char *position; |
|---|
| 393 | char *gravitation; |
|---|
| 394 | char *outputname; |
|---|
| 395 | char *Ncount_str; |
|---|
| 396 | |
|---|
| 397 | t_Table *Data; |
|---|
| 398 | |
|---|
| 399 | long m, n, p; |
|---|
| 400 | double x1, x2, y1, y2, z1, z2; |
|---|
| 401 | char *ratio; |
|---|
| 402 | double RunNum; |
|---|
| 403 | double *p0, *p1, *p2; |
|---|
| 404 | double Nsum, Psum, P2sum; |
|---|
| 405 | Coords POSITION; |
|---|
| 406 | |
|---|
| 407 | int mcnumipar; |
|---|
| 408 | struct mcinputtable_struct *mcinputtable; |
|---|
| 409 | char *mcdirname; |
|---|
| 410 | double Scan_ipar_value; |
|---|
| 411 | int Scan_ipar_index; |
|---|
| 412 | double Scan_mon_distance; |
|---|
| 413 | int Scan_mon_index; |
|---|
| 414 | }; /* McStas_file_format */ |
|---|
| 415 | |
|---|
| 416 | struct McStas_file_format *Files_to_Merge=NULL; |
|---|
| 417 | int *Scans_to_merge=NULL; |
|---|
| 418 | |
|---|
| 419 | /******************************************************************************* |
|---|
| 420 | * mcformat_init_mcstas_struct: Init an empty McStas data structure |
|---|
| 421 | *******************************************************************************/ |
|---|
| 422 | struct McStas_file_format mcformat_init_mcstas_struct(void) |
|---|
| 423 | { |
|---|
| 424 | struct McStas_file_format McStasStruct; |
|---|
| 425 | |
|---|
| 426 | McStasStruct.Format = NULL; |
|---|
| 427 | McStasStruct.Creator = NULL; |
|---|
| 428 | McStasStruct.Editor = NULL; |
|---|
| 429 | McStasStruct.Date = NULL; |
|---|
| 430 | McStasStruct.EndDate = NULL; |
|---|
| 431 | McStasStruct.Ncount = 0; |
|---|
| 432 | McStasStruct.type = NULL; |
|---|
| 433 | McStasStruct.Source = NULL; |
|---|
| 434 | McStasStruct.InstrName = NULL; |
|---|
| 435 | McStasStruct.component = NULL; |
|---|
| 436 | McStasStruct.title = NULL; |
|---|
| 437 | McStasStruct.ratio = NULL; |
|---|
| 438 | McStasStruct.filename = NULL; |
|---|
| 439 | McStasStruct.xvar = NULL; |
|---|
| 440 | McStasStruct.yvar = NULL; |
|---|
| 441 | McStasStruct.xlabel = NULL; |
|---|
| 442 | McStasStruct.ylabel = NULL; |
|---|
| 443 | McStasStruct.zvar = NULL; |
|---|
| 444 | McStasStruct.zlabel = NULL; |
|---|
| 445 | McStasStruct.xylimits = NULL; |
|---|
| 446 | McStasStruct.position = NULL; |
|---|
| 447 | McStasStruct.outputname = NULL; |
|---|
| 448 | McStasStruct.Ncount_str = NULL; |
|---|
| 449 | |
|---|
| 450 | McStasStruct.Data = NULL; |
|---|
| 451 | McStasStruct.p0 = NULL; |
|---|
| 452 | McStasStruct.p1 = NULL; |
|---|
| 453 | McStasStruct.p2 = NULL; |
|---|
| 454 | McStasStruct.Nsum = 0; |
|---|
| 455 | McStasStruct.Psum = 0; |
|---|
| 456 | McStasStruct.P2sum = 0; |
|---|
| 457 | McStasStruct.POSITION.x=McStasStruct.POSITION.y=McStasStruct.POSITION.z=0; |
|---|
| 458 | |
|---|
| 459 | McStasStruct.RunNum = 0; |
|---|
| 460 | McStasStruct.m = 0; |
|---|
| 461 | McStasStruct.n = 0; |
|---|
| 462 | McStasStruct.p = 0; |
|---|
| 463 | McStasStruct.x1 = 0; |
|---|
| 464 | McStasStruct.x2 = 0; |
|---|
| 465 | McStasStruct.y1 = 0; |
|---|
| 466 | McStasStruct.y2 = 0; |
|---|
| 467 | McStasStruct.z1 = 0; |
|---|
| 468 | McStasStruct.z2 = 0; |
|---|
| 469 | |
|---|
| 470 | McStasStruct.gravitation= NULL; |
|---|
| 471 | |
|---|
| 472 | McStasStruct.mcnumipar =0; |
|---|
| 473 | McStasStruct.mcinputtable =NULL; |
|---|
| 474 | McStasStruct.mcdirname =NULL; |
|---|
| 475 | |
|---|
| 476 | McStasStruct.Scan_ipar_value =0; |
|---|
| 477 | McStasStruct.Scan_ipar_index =0; |
|---|
| 478 | McStasStruct.Scan_mon_distance=0; |
|---|
| 479 | McStasStruct.Scan_mon_index =0; |
|---|
| 480 | |
|---|
| 481 | return(McStasStruct); |
|---|
| 482 | } /* mcformat_init_mcstas_struct */ |
|---|
| 483 | |
|---|
| 484 | |
|---|
| 485 | void mcformat_print_mcstas_struct(struct McStas_file_format McStasStruct) |
|---|
| 486 | { |
|---|
| 487 | printf("Structure from file %s\n", McStasStruct.filename); |
|---|
| 488 | printf(" Format = %s\n", McStasStruct.Format ); |
|---|
| 489 | printf(" Creator = %s\n", McStasStruct.Creator ); |
|---|
| 490 | printf(" Editor = %s\n", McStasStruct.Editor ); |
|---|
| 491 | printf(" Date = %s\n", McStasStruct.Date ); |
|---|
| 492 | printf(" EndDate = %s\n", McStasStruct.EndDate ); |
|---|
| 493 | printf(" type = %s\n", McStasStruct.type ); |
|---|
| 494 | printf(" Source = %s\n", McStasStruct.Source ); |
|---|
| 495 | printf(" InstrName = %s\n", McStasStruct.InstrName ); |
|---|
| 496 | printf(" component = %s\n", McStasStruct.component ); |
|---|
| 497 | printf(" title = %s\n", McStasStruct.title ); |
|---|
| 498 | printf(" ratio = %s\n", McStasStruct.ratio ); |
|---|
| 499 | printf(" xvar = %s\n", McStasStruct.xvar ); |
|---|
| 500 | printf(" yvar = %s\n", McStasStruct.yvar ); |
|---|
| 501 | printf(" xlabel = %s\n", McStasStruct.xlabel ); |
|---|
| 502 | printf(" ylabel = %s\n", McStasStruct.ylabel ); |
|---|
| 503 | printf(" zvar = %s\n", McStasStruct.zvar ); |
|---|
| 504 | printf(" zlabel = %s\n", McStasStruct.zlabel ); |
|---|
| 505 | printf(" xylimits = %s\n", McStasStruct.xylimits ); |
|---|
| 506 | printf(" position = %s\n", McStasStruct.position ); |
|---|
| 507 | printf(" outputname = %s\n", McStasStruct.outputname ); |
|---|
| 508 | printf(" Ncount_str = %s\n", McStasStruct.Ncount_str ); |
|---|
| 509 | printf(" mcdirname = %s\n", McStasStruct.mcdirname ); |
|---|
| 510 | |
|---|
| 511 | printf(" gravitation= %s\n", McStasStruct.gravitation ); |
|---|
| 512 | printf(" Ncount = %g\n", McStasStruct.Ncount); |
|---|
| 513 | printf(" RunNum = %g\n", McStasStruct.RunNum); |
|---|
| 514 | |
|---|
| 515 | printf(" x1 = %g\n", McStasStruct.x1); |
|---|
| 516 | printf(" x2 = %g\n", McStasStruct.x2); |
|---|
| 517 | printf(" y1 = %g\n", McStasStruct.y1); |
|---|
| 518 | printf(" y2 = %g\n", McStasStruct.y2); |
|---|
| 519 | printf(" z1 = %g\n", McStasStruct.z1); |
|---|
| 520 | printf(" z2 = %g\n", McStasStruct.z2); |
|---|
| 521 | |
|---|
| 522 | printf(" Data = %s\n", McStasStruct.Data ? "OK" : "NULL"); |
|---|
| 523 | |
|---|
| 524 | printf(" m = %ld\n", McStasStruct.m); |
|---|
| 525 | printf(" n = %ld\n", McStasStruct.n); |
|---|
| 526 | printf(" p = %ld\n", McStasStruct.p); |
|---|
| 527 | |
|---|
| 528 | printf(" p0 = %s\n", McStasStruct.p0 ? "OK": "NULL"); |
|---|
| 529 | printf(" p1 = %s\n", McStasStruct.p1 ? "OK": "NULL"); |
|---|
| 530 | printf(" p2 = %s\n", McStasStruct.p2 ? "OK": "NULL"); |
|---|
| 531 | printf(" POSITION = %g %g %g\n", McStasStruct.POSITION.x, McStasStruct.POSITION.y, McStasStruct.POSITION.z); |
|---|
| 532 | printf(" mcnumipar = %d\n", McStasStruct.mcnumipar); |
|---|
| 533 | printf(" inputtable = %s\n", McStasStruct.mcinputtable ? "OK": "NULL"); |
|---|
| 534 | } |
|---|
| 535 | |
|---|
| 536 | |
|---|
| 537 | /******************************************************************************* |
|---|
| 538 | * mcformat_free_mcstas_struct: Free a McStas data structure |
|---|
| 539 | *******************************************************************************/ |
|---|
| 540 | struct McStas_file_format mcformat_free_mcstas_struct(struct McStas_file_format McStasStruct) |
|---|
| 541 | { |
|---|
| 542 | memfree(McStasStruct.Format ); |
|---|
| 543 | memfree(McStasStruct.Date ); |
|---|
| 544 | memfree(McStasStruct.EndDate ); |
|---|
| 545 | memfree(McStasStruct.Creator ); |
|---|
| 546 | memfree(McStasStruct.Editor ); |
|---|
| 547 | memfree(McStasStruct.type ); |
|---|
| 548 | memfree(McStasStruct.Source ); |
|---|
| 549 | memfree(McStasStruct.InstrName); |
|---|
| 550 | memfree(McStasStruct.component); |
|---|
| 551 | memfree(McStasStruct.gravitation); |
|---|
| 552 | memfree(McStasStruct.title ); |
|---|
| 553 | memfree(McStasStruct.ratio ); |
|---|
| 554 | memfree(McStasStruct.filename ); |
|---|
| 555 | memfree(McStasStruct.xvar ); |
|---|
| 556 | memfree(McStasStruct.yvar ); |
|---|
| 557 | memfree(McStasStruct.xlabel ); |
|---|
| 558 | memfree(McStasStruct.ylabel ); |
|---|
| 559 | memfree(McStasStruct.zvar ); |
|---|
| 560 | memfree(McStasStruct.zlabel ); |
|---|
| 561 | memfree(McStasStruct.xylimits ); |
|---|
| 562 | memfree(McStasStruct.position ); |
|---|
| 563 | memfree(McStasStruct.outputname ); |
|---|
| 564 | memfree(McStasStruct.Ncount_str ); |
|---|
| 565 | |
|---|
| 566 | if (McStasStruct.Data) Table_Free_Array(McStasStruct.Data); |
|---|
| 567 | if (McStasStruct.p0) memfree(McStasStruct.p0 ); |
|---|
| 568 | if (McStasStruct.p1) memfree(McStasStruct.p1 ); |
|---|
| 569 | if (McStasStruct.p2) memfree(McStasStruct.p2 ); |
|---|
| 570 | |
|---|
| 571 | memfree(McStasStruct.mcdirname ); |
|---|
| 572 | |
|---|
| 573 | /* free mcinputtable */ |
|---|
| 574 | int i; |
|---|
| 575 | for (i=0; i<McStasStruct.mcnumipar; i++) { |
|---|
| 576 | memfree(McStasStruct.mcinputtable[i].name); |
|---|
| 577 | memfree(McStasStruct.mcinputtable[i].val); |
|---|
| 578 | } |
|---|
| 579 | memfree(McStasStruct.mcinputtable ); |
|---|
| 580 | |
|---|
| 581 | return(McStasStruct); |
|---|
| 582 | } /* mcformat_free_mcstas_struct */ |
|---|
| 583 | |
|---|
| 584 | /******************************************************************************* |
|---|
| 585 | * mcformat_read_mcstas: Reads filename and checks for McStas format |
|---|
| 586 | * extracts header and data and return structure |
|---|
| 587 | * structure.p1 is NULL in case of failure |
|---|
| 588 | *******************************************************************************/ |
|---|
| 589 | struct McStas_file_format mcformat_read_mcstas(char *filename) |
|---|
| 590 | { |
|---|
| 591 | struct McStas_file_format McStasStruct; |
|---|
| 592 | int m=1,n=1,p=1, i,j; |
|---|
| 593 | long array_length=0; |
|---|
| 594 | char flag_abort=0; |
|---|
| 595 | char flag_pgplot1d=0; |
|---|
| 596 | |
|---|
| 597 | /* init default empty return value */ |
|---|
| 598 | McStasStruct = mcformat_init_mcstas_struct(); |
|---|
| 599 | |
|---|
| 600 | /* opens the file as a t_Table */ |
|---|
| 601 | t_Table *rTable=NULL; |
|---|
| 602 | |
|---|
| 603 | /* gets header and block 1 */ |
|---|
| 604 | rTable = Table_Read_Array(filename, &array_length); /* reads all data */ |
|---|
| 605 | if (!rTable) { if (mcverbose) fprintf(stderr, "mcformat: file %s not found\n", filename); |
|---|
| 606 | return(McStasStruct); |
|---|
| 607 | } |
|---|
| 608 | |
|---|
| 609 | /* returns if this is not a McStas format file, or invalid */ |
|---|
| 610 | if (!rTable[0].data || (array_length != 1 && array_length != 3)) { |
|---|
| 611 | if (mcverbose) fprintf(stderr, "mcformat: file %s is invalid (%ld blocks)\n", |
|---|
| 612 | filename, array_length); |
|---|
| 613 | flag_abort=1; |
|---|
| 614 | } else if (!rTable[0].header) { |
|---|
| 615 | if (mcverbose) fprintf(stderr, "mcformat: Can not read header from file %s\n" |
|---|
| 616 | " Data is [%ld x %ld]\n", filename, rTable[0].rows, rTable[0].columns); |
|---|
| 617 | flag_abort=1; |
|---|
| 618 | } |
|---|
| 619 | |
|---|
| 620 | if (array_length == 3) |
|---|
| 621 | for (i=1; i<=2; i++) |
|---|
| 622 | if (rTable[0].rows != rTable[i].rows || rTable[0].columns != rTable[i].columns) { |
|---|
| 623 | if (mcverbose) fprintf(stderr, "mcformat: file %s Data dimensions are not consistent\n" |
|---|
| 624 | " Data[%i] is [%ld x %ld]\n", |
|---|
| 625 | filename, i, rTable[i].rows, rTable[i].columns); |
|---|
| 626 | flag_abort=1; |
|---|
| 627 | } |
|---|
| 628 | if (flag_abort) { |
|---|
| 629 | Table_Free_Array(rTable); |
|---|
| 630 | return(McStasStruct); |
|---|
| 631 | } |
|---|
| 632 | |
|---|
| 633 | /* analyze content of file : use read-table:Table_ParseHeader ********** */ |
|---|
| 634 | char **parsing; |
|---|
| 635 | parsing = Table_ParseHeader(rTable[0].header, |
|---|
| 636 | "Format", /* original Format */ |
|---|
| 637 | "Editor", |
|---|
| 638 | "Creator", |
|---|
| 639 | "Date", |
|---|
| 640 | "EndDate", |
|---|
| 641 | "File", /* original filename */ |
|---|
| 642 | "Source","Instrument-source", |
|---|
| 643 | "instrument", |
|---|
| 644 | "Ncount", |
|---|
| 645 | "Gravitation", |
|---|
| 646 | "type", |
|---|
| 647 | "component","parent", |
|---|
| 648 | "position", |
|---|
| 649 | "title", |
|---|
| 650 | "ratio", |
|---|
| 651 | "xlabel", |
|---|
| 652 | "ylabel", |
|---|
| 653 | "zlabel", |
|---|
| 654 | "xvar", |
|---|
| 655 | "yvar", |
|---|
| 656 | "zvar", |
|---|
| 657 | "xlimits", "xylimits", |
|---|
| 658 | NULL); |
|---|
| 659 | |
|---|
| 660 | if (parsing) { |
|---|
| 661 | if (parsing[0]) McStasStruct.Format = str_dup_label(parsing[0]); |
|---|
| 662 | if (parsing[1]) McStasStruct.Editor = str_dup_label(parsing[1]); |
|---|
| 663 | if (parsing[2]) McStasStruct.Creator = str_dup_label(parsing[2]); |
|---|
| 664 | if (parsing[3]) McStasStruct.Date = str_dup_numeric(parsing[3]); /* mcstartdate */ |
|---|
| 665 | if (parsing[4]) McStasStruct.EndDate = str_dup_numeric(parsing[4]); /* DATL */ |
|---|
| 666 | /* if (parsing[5]) McStasStruct.filename = str_dup(parsing[5]); */ |
|---|
| 667 | if (parsing[6]) McStasStruct.Source = str_dup_label(parsing[6]); /* mcinstrument_source */ |
|---|
| 668 | if (parsing[7] && !McStasStruct.Source) |
|---|
| 669 | McStasStruct.Source = str_dup_label(parsing[7]); |
|---|
| 670 | if (parsing[8]) McStasStruct.InstrName = str_dup_label(parsing[8]); /* mcinstrument_name */ |
|---|
| 671 | if (parsing[9]) McStasStruct.Ncount_str = str_dup_numeric(parsing[9]); |
|---|
| 672 | if (parsing[10]) McStasStruct.gravitation= str_dup_numeric(parsing[10]);/* mcgravitation */ |
|---|
| 673 | if (parsing[11]) McStasStruct.type = str_dup_label(parsing[11]); /* array_Xd */ |
|---|
| 674 | if (parsing[12]) McStasStruct.component = str_dup_label(parsing[12]); /* NAME_CURRENT_COMP */ |
|---|
| 675 | if (parsing[13] && !McStasStruct.component) |
|---|
| 676 | McStasStruct.component = str_dup_label(parsing[13]); |
|---|
| 677 | if (parsing[14]) McStasStruct.position = str_dup_numeric(parsing[14]); /* string(POS_A_CURRENT_COMP) */ |
|---|
| 678 | if (parsing[15]) McStasStruct.title = str_dup_label(parsing[15]); |
|---|
| 679 | if (parsing[16]) McStasStruct.ratio = str_dup_numeric(parsing[16]); /* -> RunNum */ |
|---|
| 680 | if (parsing[17]) McStasStruct.xlabel = str_dup_label(parsing[17]); |
|---|
| 681 | if (parsing[18]) McStasStruct.ylabel = str_dup_label(parsing[18]); |
|---|
| 682 | if (parsing[19]) McStasStruct.zlabel = str_dup_label(parsing[19]); |
|---|
| 683 | if (parsing[20]) McStasStruct.xvar = str_dup_label(parsing[20]); |
|---|
| 684 | if (parsing[21]) McStasStruct.yvar = str_dup_label(parsing[21]); |
|---|
| 685 | if (parsing[22]) McStasStruct.zvar = str_dup_label(parsing[22]); |
|---|
| 686 | if (parsing[23]) McStasStruct.xylimits = str_dup_numeric(parsing[23]); /* x/y min/max */ |
|---|
| 687 | if (parsing[24] && !McStasStruct.xylimits) |
|---|
| 688 | McStasStruct.xylimits = str_dup_numeric(parsing[24]); |
|---|
| 689 | for (i=0; i<=24; i++) { |
|---|
| 690 | if (parsing[i]) free(parsing[i]); |
|---|
| 691 | } |
|---|
| 692 | free(parsing); |
|---|
| 693 | } |
|---|
| 694 | |
|---|
| 695 | /* will be determined over original values when writting new data file: |
|---|
| 696 | filename |
|---|
| 697 | format |
|---|
| 698 | statistics |
|---|
| 699 | signal |
|---|
| 700 | values |
|---|
| 701 | */ |
|---|
| 702 | if (!McStasStruct.InstrName && !McStasStruct.Source) |
|---|
| 703 | McStasStruct.Source = str_dup("McStas_Instrument"); |
|---|
| 704 | else if (!McStasStruct.InstrName && McStasStruct.Source) { |
|---|
| 705 | char *ext=NULL; /* if not found, use instr file name without extension */ |
|---|
| 706 | ext = strstr(McStasStruct.Source, ".ins"); |
|---|
| 707 | if (!ext) ext = strstr(McStasStruct.Source, " ins"); |
|---|
| 708 | if (ext) McStasStruct.InstrName = str_dup_n(McStasStruct.Source, (ext-McStasStruct.Source)); |
|---|
| 709 | else McStasStruct.InstrName = str_dup(McStasStruct.Source); |
|---|
| 710 | } else if (McStasStruct.InstrName && !McStasStruct.Source) { |
|---|
| 711 | char *ext=NULL; /* if not found, use instr name without extension */ |
|---|
| 712 | ext = strstr(McStasStruct.InstrName, ".ins"); |
|---|
| 713 | if (!ext) ext = strstr(McStasStruct.InstrName, " ins"); |
|---|
| 714 | if (ext) McStasStruct.Source = str_dup_n(McStasStruct.InstrName, (ext-McStasStruct.InstrName)); |
|---|
| 715 | else McStasStruct.Source = str_dup(McStasStruct.InstrName); |
|---|
| 716 | } |
|---|
| 717 | |
|---|
| 718 | if (McStasStruct.Ncount_str) McStasStruct.Ncount=atof(McStasStruct.Ncount_str); |
|---|
| 719 | |
|---|
| 720 | /* header analysis: general keywords */ |
|---|
| 721 | if (McStasStruct.ratio) { /* extracts RunNum and Ncount values separated by '/' */ |
|---|
| 722 | double runnum=0, ncount=0; |
|---|
| 723 | int i; |
|---|
| 724 | i = sscanf(McStasStruct.ratio, "%lg %lg", &runnum, &ncount); |
|---|
| 725 | if (i) McStasStruct.RunNum = runnum; |
|---|
| 726 | if (i>1) { |
|---|
| 727 | if (!McStasStruct.Ncount && ncount) McStasStruct.Ncount = ncount; |
|---|
| 728 | else if (ncount && McStasStruct.Ncount != ncount) |
|---|
| 729 | fprintf(stderr, "Warning: %s: conflicting Ncount %f value with 'ratio' one %f\n", |
|---|
| 730 | filename, McStasStruct.Ncount, ncount); |
|---|
| 731 | } else if (!McStasStruct.Ncount) /* no Ncount and ratio is a single value: Ncount == runnum */ |
|---|
| 732 | McStasStruct.Ncount = McStasStruct.RunNum; |
|---|
| 733 | } |
|---|
| 734 | if (!McStasStruct.Ncount) { |
|---|
| 735 | McStasStruct.Ncount = 1e6; |
|---|
| 736 | fprintf(stderr, "Warning: %s: can not extract Ncount. using default (%g)\n", |
|---|
| 737 | filename, McStasStruct.Ncount); |
|---|
| 738 | } |
|---|
| 739 | if (!McStasStruct.RunNum) McStasStruct.RunNum = McStasStruct.Ncount; |
|---|
| 740 | if (McStasStruct.RunNum < McStasStruct.Ncount*0.99) |
|---|
| 741 | fprintf(stderr, "Warning: %s: Temporary results with ratio %g/%g. Simulation results are not completed.\n", |
|---|
| 742 | filename, McStasStruct.RunNum, McStasStruct.Ncount); |
|---|
| 743 | |
|---|
| 744 | /* analyse type, and check that Data dims are m,n,p */ |
|---|
| 745 | if (McStasStruct.type) { |
|---|
| 746 | if (!strcmp(McStasStruct.type, "array_0d")) m=n=p=1; |
|---|
| 747 | else if (sscanf(McStasStruct.type, "array_1d(%d)",&m) == 1) n=p=1; |
|---|
| 748 | else if (sscanf(McStasStruct.type, "array_2d(%d, %d)",&n,&m) == 2) p=1; |
|---|
| 749 | else if (sscanf(McStasStruct.type, "array_3d(%d, %d, %d)",&n,&m,&p) == 3) { /* void */ } |
|---|
| 750 | else if (sscanf(McStasStruct.type, "multiarray_1d(%d)", &m)) { |
|---|
| 751 | if (!mcscanmode) fprintf(stderr, "Warning: %s: use --scan flag for multiarray/scans (skipped)\n", filename); |
|---|
| 752 | return(McStasStruct); |
|---|
| 753 | } |
|---|
| 754 | } else { |
|---|
| 755 | fprintf(stderr, "Warning: %s: invalid data type '%s' (not 1d/2d/3d/multiarray)\n", filename, McStasStruct.type); |
|---|
| 756 | return(McStasStruct); |
|---|
| 757 | } |
|---|
| 758 | |
|---|
| 759 | /* Scans: just test existence. If yes, then will skip the SIM file */ |
|---|
| 760 | /* |
|---|
| 761 | "# Numpoints: " |
|---|
| 762 | "# xvars: " |
|---|
| 763 | "# yvars: " |
|---|
| 764 | */ |
|---|
| 765 | /* check if data block is transposed */ |
|---|
| 766 | if (m != rTable[0].rows && n != rTable[0].columns |
|---|
| 767 | && m == rTable[0].columns && n == rTable[0].rows) { |
|---|
| 768 | if (mcverbose) fprintf(stderr, "Warning: %s: Data block is transposed. Fixing.\n", filename); |
|---|
| 769 | int tmp=m; |
|---|
| 770 | m=n; n=tmp; |
|---|
| 771 | } |
|---|
| 772 | if (m != rTable[0].rows) { |
|---|
| 773 | fprintf(stderr, "Warning: %s: conflicting Data row numbers\n" |
|---|
| 774 | " expected=%d found=%ld. Fixing. Check first line of Data block.\n", filename, m, rTable[0].rows); |
|---|
| 775 | m = rTable[0].rows; |
|---|
| 776 | } |
|---|
| 777 | if (McStasStruct.Format && (strstr(McStasStruct.Format, "binary") || strstr(McStasStruct.Format, "float") || strstr(McStasStruct.Format, "double"))) |
|---|
| 778 | fprintf(stderr, "WARNING: %s: Format of data file indicates binary blocks." |
|---|
| 779 | " Not supported. Might crash.\n", filename); |
|---|
| 780 | if (McStasStruct.Format && McStasStruct.type |
|---|
| 781 | && strstr(McStasStruct.Format, "PGPLOT") && array_length == 1 |
|---|
| 782 | && strstr(McStasStruct.type, "array_1d") && rTable[0].columns == 4) flag_pgplot1d=1; |
|---|
| 783 | if (flag_pgplot1d) n = 4; |
|---|
| 784 | if (n != rTable[0].columns) { |
|---|
| 785 | fprintf(stderr, "Warning: %s: conflicting Data column numbers\n" |
|---|
| 786 | " expected=%d found=%ld. Fixing. Check first line of Data block.\n", filename, n, rTable[0].columns); |
|---|
| 787 | n = rTable[0].columns; |
|---|
| 788 | } |
|---|
| 789 | if (flag_pgplot1d) n = 1; |
|---|
| 790 | McStasStruct.m = rTable[0].rows; /* dimensions from the Table */ |
|---|
| 791 | McStasStruct.n = flag_pgplot1d ? 1 : rTable[0].columns; |
|---|
| 792 | McStasStruct.p = p; /* extracted from type */ |
|---|
| 793 | |
|---|
| 794 | m = McStasStruct.m; |
|---|
| 795 | n = McStasStruct.n; |
|---|
| 796 | |
|---|
| 797 | |
|---|
| 798 | /* extract limits values */ |
|---|
| 799 | McStasStruct.x1=1; McStasStruct.x2=McStasStruct.m; |
|---|
| 800 | McStasStruct.y1=1; McStasStruct.y2=McStasStruct.n; |
|---|
| 801 | McStasStruct.z1=1; McStasStruct.z2=McStasStruct.p; |
|---|
| 802 | if (McStasStruct.xylimits) { |
|---|
| 803 | i = sscanf(McStasStruct.xylimits, "%lg %lg %lg %lg %lg %lg", |
|---|
| 804 | &(McStasStruct.x1), &(McStasStruct.x2), |
|---|
| 805 | &(McStasStruct.y1), &(McStasStruct.y2), |
|---|
| 806 | &(McStasStruct.z1), &(McStasStruct.z2)); |
|---|
| 807 | if (i != 2 && i != 4 && i != 6) |
|---|
| 808 | fprintf(stderr, "Warning: %s: invalid xylimits '%s'. extracted %i values\n", |
|---|
| 809 | filename, McStasStruct.xylimits, i); |
|---|
| 810 | } |
|---|
| 811 | |
|---|
| 812 | /* special case of 2D binary files: axes must be exchanged */ |
|---|
| 813 | if (strstr(mcformat.Name, "binary") || strstr(mcformat.Name, "float") || strstr(mcformat.Name, "double")) |
|---|
| 814 | if (p == 1 && m>1 && n>1) { |
|---|
| 815 | double tmp; char* c; |
|---|
| 816 | tmp=McStasStruct.x1; McStasStruct.x1=McStasStruct.y1; McStasStruct.y1=tmp; |
|---|
| 817 | tmp=McStasStruct.x2; McStasStruct.x2=McStasStruct.y2; McStasStruct.y2=tmp; |
|---|
| 818 | c=McStasStruct.xlabel; McStasStruct.xlabel=McStasStruct.ylabel; McStasStruct.ylabel=c; |
|---|
| 819 | c=McStasStruct.xvar; McStasStruct.xvar=McStasStruct.yvar; McStasStruct.yvar=c; |
|---|
| 820 | } |
|---|
| 821 | |
|---|
| 822 | McStasStruct.filename = str_dup(filename); |
|---|
| 823 | if (!McStasStruct.component) McStasStruct.component=str_dup(filename); |
|---|
| 824 | struct fileparts_struct file_parts=fileparts(filename); |
|---|
| 825 | char *tmp=str_cat(file_parts.Name, ".", file_parts.Extension, NULL); |
|---|
| 826 | McStasStruct.outputname = str_dup_name(tmp, 0); |
|---|
| 827 | memfree(tmp); |
|---|
| 828 | fileparts_free(file_parts); |
|---|
| 829 | McStasStruct.mcdirname = str_dup(mcdirname); |
|---|
| 830 | if (McStasStruct.position) sscanf(McStasStruct.position, "%lg %lg %lg", |
|---|
| 831 | &McStasStruct.POSITION.x,&McStasStruct.POSITION.y,&McStasStruct.POSITION.z); |
|---|
| 832 | |
|---|
| 833 | /* header analysis: get instrument parameters and fills numipar and inputtable */ |
|---|
| 834 | char *s = rTable[0].header; |
|---|
| 835 | char *tok=s; |
|---|
| 836 | char *equal_sign=NULL; |
|---|
| 837 | char *name_start=NULL; |
|---|
| 838 | mcnumipar = 0; |
|---|
| 839 | while (tok) { /* extract parameter=value as clean names */ |
|---|
| 840 | tok = strstr(s, "Parameters"); |
|---|
| 841 | if (!tok) tok = strstr(s, "parameters"); |
|---|
| 842 | if (!tok) tok = strstr(s, "Param"); |
|---|
| 843 | if (!tok) tok = strstr(s, "param"); |
|---|
| 844 | if (!tok) break; |
|---|
| 845 | parsing = Table_ParseHeader(tok, "Parameters", NULL); /* get line */ |
|---|
| 846 | if (!parsing[0]) parsing = Table_ParseHeader(tok, "parameters", NULL); /* get line */ |
|---|
| 847 | if (!parsing[0]) parsing = Table_ParseHeader(tok, "Param", NULL); /* get line */ |
|---|
| 848 | if (!parsing[0]) parsing = Table_ParseHeader(tok, "param", NULL); /* get line */ |
|---|
| 849 | name_start = (parsing[0] ? str_dup(parsing[0]) : NULL); |
|---|
| 850 | memfree(parsing[0]); free(parsing); |
|---|
| 851 | if (!name_start) break; |
|---|
| 852 | equal_sign = strchr(name_start+1, '='); |
|---|
| 853 | if (equal_sign > name_start && strlen(name_start)) { |
|---|
| 854 | char *name_to_equal=str_dup_n(name_start, equal_sign-name_start); |
|---|
| 855 | char *name=str_last_word(name_to_equal); |
|---|
| 856 | char *value = str_dup(equal_sign+1); |
|---|
| 857 | if (name && value && strlen(name) && strlen(value)) { |
|---|
| 858 | char *name_label = str_dup_label(name); |
|---|
| 859 | /*printf("name_to_equal='%s' name='%s' value='%s'\n", name_to_equal, name, value); */ |
|---|
| 860 | mcinputtable[mcnumipar].name = name_label; |
|---|
| 861 | mcinputtable[mcnumipar].type = instr_type_string; |
|---|
| 862 | mcinputtable[mcnumipar].val = value; |
|---|
| 863 | mcinputtable[mcnumipar].par = NULL; |
|---|
| 864 | mcnumipar++; |
|---|
| 865 | } |
|---|
| 866 | memfree(name_to_equal); |
|---|
| 867 | } |
|---|
| 868 | memfree(name_start); |
|---|
| 869 | s = tok+strlen("Param"); |
|---|
| 870 | } /* end while tok */ |
|---|
| 871 | |
|---|
| 872 | /* now transfer mcinputtable into McStasStruct */ |
|---|
| 873 | McStasStruct.mcnumipar = mcnumipar; |
|---|
| 874 | McStasStruct.mcinputtable = (struct mcinputtable_struct *)mem(mcnumipar*sizeof(struct mcinputtable_struct)); |
|---|
| 875 | for (i=0; i<mcnumipar; i++) { |
|---|
| 876 | McStasStruct.mcinputtable[i] = mcinputtable[i]; |
|---|
| 877 | } |
|---|
| 878 | |
|---|
| 879 | McStasStruct.Data = rTable; |
|---|
| 880 | |
|---|
| 881 | /* transfer Data into p0, p1, p2 */ |
|---|
| 882 | McStasStruct.p1 = (double*)mem(McStasStruct.m*McStasStruct.n*McStasStruct.p*sizeof(double)); |
|---|
| 883 | if ((array_length == 3 || flag_pgplot1d) && !strstr(McStasStruct.Format, " list ")) { |
|---|
| 884 | McStasStruct.p0 = (double*)mem(McStasStruct.m*McStasStruct.n*McStasStruct.p*sizeof(double)); |
|---|
| 885 | McStasStruct.p2 = (double*)mem(McStasStruct.m*McStasStruct.n*McStasStruct.p*sizeof(double)); |
|---|
| 886 | } |
|---|
| 887 | |
|---|
| 888 | if (flag_pgplot1d) |
|---|
| 889 | { /* this is a 1D PGPLOT data file. |
|---|
| 890 | columns [ xvar, p, err, N ] */ |
|---|
| 891 | memfree(McStasStruct.yvar); McStasStruct.yvar=str_dup("I"); |
|---|
| 892 | for (i=0; i<m; i++) { |
|---|
| 893 | McStasStruct.p1[i] = Table_Index(McStasStruct.Data[0], i, 1); |
|---|
| 894 | McStasStruct.p2[i] = Table_Index(McStasStruct.Data[0], i, 2); |
|---|
| 895 | McStasStruct.p0[i] = Table_Index(McStasStruct.Data[0], i, 3); |
|---|
| 896 | } |
|---|
| 897 | } else if (array_length == 1 || strstr(McStasStruct.Format, " list ")) { |
|---|
| 898 | /* lists are stored as is */ |
|---|
| 899 | for (i=0; i<m; i++) |
|---|
| 900 | for (j=0; j <n*p; j++) { |
|---|
| 901 | int tmp=i*n*p+j; |
|---|
| 902 | McStasStruct.p1[tmp] = |
|---|
| 903 | Table_Index(McStasStruct.Data[0], i, j); |
|---|
| 904 | } |
|---|
| 905 | } else if (array_length == 3) { /* order in files is [p, err, N] */ |
|---|
| 906 | for (i=0; i<m; i++) |
|---|
| 907 | for (j=0; j <n*p; j++) { |
|---|
| 908 | int tmp=i*n*p+j; |
|---|
| 909 | McStasStruct.p1[tmp] = Table_Index(McStasStruct.Data[0], i, j); |
|---|
| 910 | McStasStruct.p2[tmp] = Table_Index(McStasStruct.Data[1], i, j); |
|---|
| 911 | McStasStruct.p0[tmp] = Table_Index(McStasStruct.Data[2], i, j); |
|---|
| 912 | } |
|---|
| 913 | } else |
|---|
| 914 | fprintf(stderr, "Warning: %s: can not store data blocks (total %ld).\n", |
|---|
| 915 | filename, array_length); |
|---|
| 916 | |
|---|
| 917 | /* compute back the original sigma->p2 array (see mcestimate_error) */ |
|---|
| 918 | if (McStasStruct.p0 && McStasStruct.p1 && McStasStruct.p2) { |
|---|
| 919 | double *p0 = McStasStruct.p0; |
|---|
| 920 | double *p1 = McStasStruct.p1; |
|---|
| 921 | double *p2 = McStasStruct.p2; |
|---|
| 922 | for (i=0; i < m*n*p; i++) { |
|---|
| 923 | if (p2[i] > 0) p2[i] = (p0[i] > 1 ? ((p0[i]-1)*p2[i]*p2[i] + p1[i]*p1[i]/p0[i])/p0[i] |
|---|
| 924 | : p1[i]); |
|---|
| 925 | } |
|---|
| 926 | } |
|---|
| 927 | McStasStruct.m *= -1; /* always transposed in files w/r to memory */ |
|---|
| 928 | |
|---|
| 929 | /* free McStasStruct.Data for better memory management */ |
|---|
| 930 | Table_Free_Array(McStasStruct.Data); McStasStruct.Data=NULL; |
|---|
| 931 | |
|---|
| 932 | return(McStasStruct); |
|---|
| 933 | } /* end mcformat_read_mcstas */ |
|---|
| 934 | |
|---|
| 935 | /******************************************************************************* |
|---|
| 936 | * mcformat_dirwalk: apply fcn to all files in dir (see K & R 'C language') |
|---|
| 937 | * returns number of processed files |
|---|
| 938 | *******************************************************************************/ |
|---|
| 939 | int mcformat_dirwalk(char *dir, int (*fcn)(char *)) |
|---|
| 940 | { |
|---|
| 941 | char name[CHAR_BUF_LENGTH]; |
|---|
| 942 | int ret=0; |
|---|
| 943 | struct dirent *dp; |
|---|
| 944 | DIR *dfd; |
|---|
| 945 | |
|---|
| 946 | if ((dfd = opendir(dir)) == NULL) { |
|---|
| 947 | fprintf(stderr, "mcformat: can't open %s\n", dir); |
|---|
| 948 | return 0; |
|---|
| 949 | } |
|---|
| 950 | while ((dp = readdir(dfd)) != NULL) { |
|---|
| 951 | if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) |
|---|
| 952 | continue; /* skip self and parent */ |
|---|
| 953 | if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name)) |
|---|
| 954 | fprintf(stderr, "mcformat: name %s%c%s too long\n", |
|---|
| 955 | dir, MC_PATHSEP_C, dp->d_name); |
|---|
| 956 | else { |
|---|
| 957 | sprintf(name, "%s%c%s", dir, MC_PATHSEP_C, dp->d_name); |
|---|
| 958 | ret += (*fcn)(name); |
|---|
| 959 | } |
|---|
| 960 | } |
|---|
| 961 | closedir(dfd); |
|---|
| 962 | return(ret); |
|---|
| 963 | } /* end mcformat_dirwalk */ |
|---|
| 964 | |
|---|
| 965 | /******************************************************************************* |
|---|
| 966 | * mcformat_usedir: set directory to use. Same as mcuse_dir with force option. |
|---|
| 967 | *******************************************************************************/ |
|---|
| 968 | static void mcformat_usedir(char *dir) |
|---|
| 969 | { |
|---|
| 970 | #ifdef MC_PORTABLE |
|---|
| 971 | fprintf(stderr, "Error: " |
|---|
| 972 | "Directory output cannot be used with portable simulation (mcformat_usedir)\n"); |
|---|
| 973 | return; |
|---|
| 974 | #else /* !MC_PORTABLE */ |
|---|
| 975 | #ifndef WIN32 |
|---|
| 976 | if(!mctestmode && mkdir(dir, 0777)) |
|---|
| 977 | #else |
|---|
| 978 | if(!mctestmode && mkdir(dir)) |
|---|
| 979 | #endif |
|---|
| 980 | { |
|---|
| 981 | int errno_mkdir = errno; |
|---|
| 982 | if (errno_mkdir == ENOENT) { |
|---|
| 983 | if (mcverbose) fprintf(stderr, "mkdir: ENOENT A directory component in pathname '%s' does not exist or is a dangling symbolic link.\n", dir); |
|---|
| 984 | /* we build the required elements in the path */ |
|---|
| 985 | struct fileparts_struct dir_parts = fileparts(dir); |
|---|
| 986 | if (strlen(dir_parts.Path)) { |
|---|
| 987 | char *path_pos= strrchr(dir_parts.Path, MC_PATHSEP_C); /* last PATHSEP */ |
|---|
| 988 | if (path_pos == dir_parts.Path+strlen(dir_parts.Path)-1) dir_parts.Path[strlen(dir_parts.Path)-1] = '\0'; |
|---|
| 989 | if (mcverbose) fprintf(stderr, "mcformat: Warning: building output directory '%s' from '%s'.\n", dir_parts.Path, dir); |
|---|
| 990 | mcformat_usedir(dir_parts.Path); |
|---|
| 991 | fileparts_free(dir_parts); |
|---|
| 992 | mcformat_usedir(dir); |
|---|
| 993 | } |
|---|
| 994 | } else if (errno_mkdir == EEXIST) { |
|---|
| 995 | fprintf(stderr, "mkdir: EEXIST pathname %s already exists (not necessarily as a directory).\n", dir); |
|---|
| 996 | if (!mcforcemode && mcscanmode != 2) { |
|---|
| 997 | fprintf(stderr, "Error: unable to create directory '%s' (mcformat_usedir)\n", dir); |
|---|
| 998 | fprintf(stderr, "(Maybe the directory already exists? Use --force, --scan-only or --test before -d %s to override)\n", dir); |
|---|
| 999 | exit(1); |
|---|
| 1000 | } |
|---|
| 1001 | fprintf(stderr, "mcformat: Warning: re-using output directory '%s'.\n", dir); |
|---|
| 1002 | } else { |
|---|
| 1003 | switch (errno_mkdir) { |
|---|
| 1004 | #ifdef EACCES |
|---|
| 1005 | case EACCES: |
|---|
| 1006 | fprintf(stderr, "mkdir: EACCES The parent directory does not allow write permission\n" |
|---|
| 1007 | " or one of the directories in pathname did not allow search permission.\n"); break; |
|---|
| 1008 | #endif |
|---|
| 1009 | #ifdef EFAULT |
|---|
| 1010 | case EFAULT: |
|---|
| 1011 | fprintf(stderr, "mkdir: EFAULT pathname points outside your accessible address space.\n"); break; |
|---|
| 1012 | #endif |
|---|
| 1013 | #ifdef ELOOP |
|---|
| 1014 | case ELOOP: |
|---|
| 1015 | fprintf(stderr, "mkdir: ELOOP Too many symbolic links were encountered in resolving pathname.\n"); break; |
|---|
| 1016 | #endif |
|---|
| 1017 | #ifdef ENAMETOOLONG |
|---|
| 1018 | case ENAMETOOLONG: |
|---|
| 1019 | fprintf(stderr, "mkdir: ENAMETOOLONG pathname was too long.\n"); break; |
|---|
| 1020 | #endif |
|---|
| 1021 | #ifdef ENOMEM |
|---|
| 1022 | case ENOMEM: |
|---|
| 1023 | fprintf(stderr, "mkdir: ENOMEM Insufficient kernel memory was available.\n"); break; |
|---|
| 1024 | #endif |
|---|
| 1025 | #ifdef ENOSPC |
|---|
| 1026 | case ENOSPC: |
|---|
| 1027 | fprintf(stderr, "mkdir: ENOSPC The device containing pathname has no room for the new directory.\n"); break; |
|---|
| 1028 | #endif |
|---|
| 1029 | #ifdef ENOTDIR |
|---|
| 1030 | case ENOTDIR: |
|---|
| 1031 | fprintf(stderr, "mkdir: ENOTDIR A component used as a directory in pathname is not, in fact, a directory.\n"); break; |
|---|
| 1032 | #endif |
|---|
| 1033 | #ifdef EPERM |
|---|
| 1034 | case EPERM: |
|---|
| 1035 | fprintf(stderr, "mkdir: EPERM The filesystem containing pathname does not support the creation of directories.\n"); break; |
|---|
| 1036 | #endif |
|---|
| 1037 | #ifdef EROFS |
|---|
| 1038 | case EROFS: |
|---|
| 1039 | fprintf(stderr, "mkdir: EROFS pathname refers to a file on a read-only filesystem.\n"); break; |
|---|
| 1040 | #endif |
|---|
| 1041 | default: |
|---|
| 1042 | fprintf(stderr, "mkdir: ERROR %i using mkdir.\n", errno_mkdir); break; |
|---|
| 1043 | } |
|---|
| 1044 | fprintf(stderr, "mcformat: Fatal error accessing %s. Aborting.\n", dir); |
|---|
| 1045 | exit(-1); |
|---|
| 1046 | } |
|---|
| 1047 | } |
|---|
| 1048 | if (mcverbose) printf("mcformat: Creating directory %s.\n", dir); |
|---|
| 1049 | mcdirname = dir; |
|---|
| 1050 | |
|---|
| 1051 | #endif /* !MC_PORTABLE */ |
|---|
| 1052 | } /* mcformat_usedir */ |
|---|
| 1053 | |
|---|
| 1054 | /******************************************************************************* |
|---|
| 1055 | * mcformat_output: write monitor file and optionally free memory |
|---|
| 1056 | *******************************************************************************/ |
|---|
| 1057 | int mcformat_output(struct McStas_file_format McStasStruct) |
|---|
| 1058 | { |
|---|
| 1059 | char *currentdir= mcdirname; /* save current dir */ |
|---|
| 1060 | int i; |
|---|
| 1061 | |
|---|
| 1062 | |
|---|
| 1063 | if (mctestmode) return(1); |
|---|
| 1064 | if (!McStasStruct.p1) return(0); /* empty data */ |
|---|
| 1065 | /* determine in which directory we are and set SIM file */ |
|---|
| 1066 | |
|---|
| 1067 | if (!mcdircount) { |
|---|
| 1068 | if (!strlen(mcinstrument_name)) strcpy(mcinstrument_name, McStasStruct.InstrName); |
|---|
| 1069 | if (!strlen(mcinstrument_source)) strcpy(mcinstrument_source, McStasStruct.Source); |
|---|
| 1070 | if (!mcsiminfo_file) mcsiminfo_init(NULL); /* open SIM file once */ |
|---|
| 1071 | } else { |
|---|
| 1072 | if (!mcmergemode) i=mcdircount-1; |
|---|
| 1073 | else { |
|---|
| 1074 | for (i=0; i<mcdircount; i++) |
|---|
| 1075 | if (!strcmp(mcdirnames[i], McStasStruct.mcdirname)) break; |
|---|
| 1076 | } |
|---|
| 1077 | if (i >= mcdircount) { |
|---|
| 1078 | fprintf(stderr, "ERROR: unable to find directory '%s' in scanned list\n", McStasStruct.mcdirname); |
|---|
| 1079 | return(0); |
|---|
| 1080 | } |
|---|
| 1081 | if (!mcsimfiles[i]) { |
|---|
| 1082 | mcdirname = McStasStruct.mcdirname; |
|---|
| 1083 | mcinstrnames[i]= str_dup(McStasStruct.InstrName); |
|---|
| 1084 | mcsources[i] = str_dup(McStasStruct.Source); |
|---|
| 1085 | strncpy(mcinstrument_name, str_last_word(mcinstrnames[i]), CHAR_BUF_LENGTH); |
|---|
| 1086 | strncpy(mcinstrument_source , str_dup(mcsources[i]), CHAR_BUF_LENGTH); |
|---|
| 1087 | mcsiminfo_init(NULL); /* open new SIM file in this dir for the first time */ |
|---|
| 1088 | mcsimfiles[i] = mcsiminfo_file; |
|---|
| 1089 | } else mcsiminfo_file = mcsimfiles[i]; |
|---|
| 1090 | mcdirname = mcdirnames[i]; |
|---|
| 1091 | } |
|---|
| 1092 | |
|---|
| 1093 | /* transfer to global variables used in output functions */ |
|---|
| 1094 | if (!McStasStruct.Date) mcstartdate = 0; |
|---|
| 1095 | else { |
|---|
| 1096 | mcstartdate = atol(McStasStruct.Date); |
|---|
| 1097 | if (!mcstartdate) sscanf(McStasStruct.Date, "Simulation started %ld", &mcstartdate); |
|---|
| 1098 | } |
|---|
| 1099 | mcgravitation = (McStasStruct.gravitation && strstr(McStasStruct.gravitation, "yes") ? 1 : 0); |
|---|
| 1100 | mcrun_num = McStasStruct.RunNum; |
|---|
| 1101 | mcncount = McStasStruct.Ncount; |
|---|
| 1102 | strncpy(mcinstrument_source, str_dup(McStasStruct.Source), CHAR_BUF_LENGTH); |
|---|
| 1103 | strncpy(mcinstrument_name , str_last_word(McStasStruct.InstrName), CHAR_BUF_LENGTH); |
|---|
| 1104 | /* transfer mcnumipar */ |
|---|
| 1105 | mcnumipar = McStasStruct.mcnumipar; |
|---|
| 1106 | for (i=0; i<mcnumipar; i++) { |
|---|
| 1107 | mcinputtable[i] = McStasStruct.mcinputtable[i]; |
|---|
| 1108 | } |
|---|
| 1109 | mcdirname = McStasStruct.mcdirname; |
|---|
| 1110 | |
|---|
| 1111 | /* write data file from McStasStruct */ |
|---|
| 1112 | if (mcverbose) printf("mcformat: Writing %s from %s\n", McStasStruct.outputname, McStasStruct.filename); |
|---|
| 1113 | |
|---|
| 1114 | if (strstr(McStasStruct.Format, "PGPLOT") && strstr(McStasStruct.type, "array_1d") && !mctestmode) { |
|---|
| 1115 | mcdetector_out_1D(McStasStruct.title, McStasStruct.xlabel, McStasStruct.ylabel, |
|---|
| 1116 | McStasStruct.xvar, McStasStruct.x1, McStasStruct.x2, McStasStruct.m, |
|---|
| 1117 | McStasStruct.p0, McStasStruct.p1, McStasStruct.p2, McStasStruct.outputname, |
|---|
| 1118 | McStasStruct.component, McStasStruct.POSITION); |
|---|
| 1119 | } else if (!mctestmode) |
|---|
| 1120 | mcdetector_out_3D(McStasStruct.title, |
|---|
| 1121 | McStasStruct.xlabel, McStasStruct.ylabel, McStasStruct.zlabel, |
|---|
| 1122 | McStasStruct.xvar, McStasStruct.yvar, McStasStruct.zvar, |
|---|
| 1123 | McStasStruct.x1, McStasStruct.x2, McStasStruct.y1, McStasStruct.y2, McStasStruct.z1, McStasStruct.z2, |
|---|
| 1124 | McStasStruct.m, McStasStruct.n, McStasStruct.p, |
|---|
| 1125 | McStasStruct.p0, |
|---|
| 1126 | McStasStruct.p1, |
|---|
| 1127 | McStasStruct.p2, |
|---|
| 1128 | McStasStruct.outputname, |
|---|
| 1129 | McStasStruct.component, |
|---|
| 1130 | McStasStruct.POSITION); |
|---|
| 1131 | |
|---|
| 1132 | mcdirname = currentdir; |
|---|
| 1133 | return(1); |
|---|
| 1134 | } /* end mcformat_output */ |
|---|
| 1135 | |
|---|
| 1136 | /******************************************************************************* |
|---|
| 1137 | * mcformat_convert: recursive wrapper to the conversion routine (see K & R) |
|---|
| 1138 | * returns number of processed files |
|---|
| 1139 | *******************************************************************************/ |
|---|
| 1140 | int mcformat_convert(char *name) |
|---|
| 1141 | { |
|---|
| 1142 | struct stat stbuf; |
|---|
| 1143 | struct McStas_file_format McStasFile; |
|---|
| 1144 | int ret=0; |
|---|
| 1145 | |
|---|
| 1146 | if (!name || !strlen(name)) return(0); |
|---|
| 1147 | |
|---|
| 1148 | if (stat(name, &stbuf) == -1) { |
|---|
| 1149 | fprintf(stderr, "mcformat: can't access file %s\n", name); |
|---|
| 1150 | return 0; |
|---|
| 1151 | } |
|---|
| 1152 | if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { /* dir: recursive call */ |
|---|
| 1153 | char *upper_dir= mcdirname; |
|---|
| 1154 | char *name_win=name; |
|---|
| 1155 | #ifdef WIN32 |
|---|
| 1156 | if (isalpha(name[0]) && name[1] == ':') name_win += 2; // skip Windows disk label before cat |
|---|
| 1157 | #endif |
|---|
| 1158 | char *lower_dir= mcoutputdir ? str_cat(mcoutputdir, MC_PATHSEP_S, name_win, NULL) |
|---|
| 1159 | : str_dup(name); |
|---|
| 1160 | /* entering new directory */ |
|---|
| 1161 | if (!mctestmode) mcformat_usedir(lower_dir); |
|---|
| 1162 | else mcdirname = lower_dir; |
|---|
| 1163 | mcdirnames[mcdircount] = lower_dir; |
|---|
| 1164 | mcsimfiles[mcdircount] = NULL; |
|---|
| 1165 | mcinstrnames[mcdircount]=NULL; |
|---|
| 1166 | mcsources[mcdircount] =NULL; |
|---|
| 1167 | mcdircount++; /* number of directories scanned */ |
|---|
| 1168 | ret += mcformat_dirwalk(name, mcformat_convert); |
|---|
| 1169 | if (mcverbose) printf("mcformat: coming back to upper directory %s\n", upper_dir); |
|---|
| 1170 | mcdirname = upper_dir; |
|---|
| 1171 | } else { |
|---|
| 1172 | /* process the current file */ |
|---|
| 1173 | if (mcverbose) printf("mcformat: reading %s (%ld bytes)\n", name, stbuf.st_size); |
|---|
| 1174 | McStasFile = mcformat_read_mcstas(name); |
|---|
| 1175 | |
|---|
| 1176 | if (!McStasFile.p1) { |
|---|
| 1177 | if (mcverbose) fprintf(stderr, "mcformat: warning: skipping %s (invalid format).\n", name); |
|---|
| 1178 | return 0; |
|---|
| 1179 | } |
|---|
| 1180 | |
|---|
| 1181 | if (!mcmergemode && !mcscanmode) { /* direct conversion */ |
|---|
| 1182 | |
|---|
| 1183 | /* now calls the output routines: sim and data files (0d, 1d, 2d) and free */ |
|---|
| 1184 | if (mcverbose) mcformat_print_mcstas_struct(McStasFile); fflush(stdout); |
|---|
| 1185 | if (mcformat_output(McStasFile)) |
|---|
| 1186 | if (mcverbose) { |
|---|
| 1187 | printf("mcformat: converting %s (%ld bytes) ", name, stbuf.st_size); |
|---|
| 1188 | printf("into %s%s ", mcdirname ? mcdirname : ".", mcdirname ? MC_PATHSEP_S : ""); |
|---|
| 1189 | if (mctestmode) printf(" (--test mode)\n"); else printf("\n"); |
|---|
| 1190 | } |
|---|
| 1191 | |
|---|
| 1192 | mcformat_free_mcstas_struct(McStasFile); |
|---|
| 1193 | |
|---|
| 1194 | } else { /* store: merging of all files from either a scan or similar files */ |
|---|
| 1195 | Files_to_Merge[mcnbconvert] = McStasFile; /* copy */ |
|---|
| 1196 | mcnbconvert++; /* global index */ |
|---|
| 1197 | } |
|---|
| 1198 | |
|---|
| 1199 | ret++; /* number of valid data files loaded from DIR */ |
|---|
| 1200 | } /* end else single file */ |
|---|
| 1201 | return (ret); |
|---|
| 1202 | } /* end mcformat_convert */ |
|---|
| 1203 | |
|---|
| 1204 | /******************************************************************************* |
|---|
| 1205 | * mcformat_count: count the number of files to store for merge mode |
|---|
| 1206 | *******************************************************************************/ |
|---|
| 1207 | int mcformat_count(char *name) |
|---|
| 1208 | { |
|---|
| 1209 | struct stat stbuf; |
|---|
| 1210 | int ret=0; |
|---|
| 1211 | |
|---|
| 1212 | if (!name || !strlen(name)) return(0); |
|---|
| 1213 | |
|---|
| 1214 | if (stat(name, &stbuf) == -1) { |
|---|
| 1215 | fprintf(stderr, "mcformat: can't access file %s\n", name); |
|---|
| 1216 | return 0; |
|---|
| 1217 | } |
|---|
| 1218 | if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { /* recursive call */ |
|---|
| 1219 | mcdircount++; /* number of directories scanned */ |
|---|
| 1220 | ret += mcformat_dirwalk(name, mcformat_count); |
|---|
| 1221 | } else { |
|---|
| 1222 | ret++; |
|---|
| 1223 | } |
|---|
| 1224 | return (ret); |
|---|
| 1225 | } /* end mcformat_count */ |
|---|
| 1226 | |
|---|
| 1227 | /******************************************************************************* |
|---|
| 1228 | * mcformat_merge_compare: merge files and free the redundant items. Find scans. |
|---|
| 1229 | *******************************************************************************/ |
|---|
| 1230 | int mcformat_merge_compare(int nb) |
|---|
| 1231 | { |
|---|
| 1232 | int i,j,k; |
|---|
| 1233 | |
|---|
| 1234 | if (!Files_to_Merge) return(0); |
|---|
| 1235 | /* loop on Files_to_Merge */ |
|---|
| 1236 | for (i=0; i<nb; i++) { |
|---|
| 1237 | struct McStas_file_format McStasStruct=Files_to_Merge[i]; |
|---|
| 1238 | |
|---|
| 1239 | /* skip empty elements */ |
|---|
| 1240 | if (!McStasStruct.p1) continue; |
|---|
| 1241 | |
|---|
| 1242 | /* we multiply the p1 and p2 by the Ncount so that the operations take |
|---|
| 1243 | into account the relative Ncount weight of each simulation. We will |
|---|
| 1244 | divide by the sum(Ncount) at the end of operation */ |
|---|
| 1245 | if (!strstr(McStasStruct.Format, " list ")) /* NOT FOR LISTs (content non additive) */ |
|---|
| 1246 | for (j=0; j<abs(McStasStruct.m*McStasStruct.n*McStasStruct.p); j++) { |
|---|
| 1247 | Files_to_Merge[i].p1[j] *= Files_to_Merge[i].Ncount; |
|---|
| 1248 | if (Files_to_Merge[i].p2) Files_to_Merge[i].p2[j] *= Files_to_Merge[i].Ncount; |
|---|
| 1249 | } |
|---|
| 1250 | |
|---|
| 1251 | /* second loop to search for similar items to add to Files_to_Merge[i] */ |
|---|
| 1252 | for (j=i+1; j<nb; j++) { |
|---|
| 1253 | struct McStas_file_format ThisStruct=Files_to_Merge[j]; |
|---|
| 1254 | if (!ThisStruct.p1) continue; |
|---|
| 1255 | |
|---|
| 1256 | /* Parameters check: mcinputtable.name and mcinputtable.val */ |
|---|
| 1257 | /* flag_equiv_parname must be true to go on */ |
|---|
| 1258 | /* flag_equiv_parval is false if this is a SCAN item */ |
|---|
| 1259 | char flag_equiv_parname = (ThisStruct.mcnumipar == McStasStruct.mcnumipar); |
|---|
| 1260 | char flag_equiv_parval = flag_equiv_parname; |
|---|
| 1261 | if (flag_equiv_parname) { |
|---|
| 1262 | for (k=0; k<McStasStruct.mcnumipar; k++) { |
|---|
| 1263 | /* test if parameter names are the same */ |
|---|
| 1264 | if (strcmp(ThisStruct.mcinputtable[k].name, McStasStruct.mcinputtable[k].name)) |
|---|
| 1265 | { flag_equiv_parname=0; break; } |
|---|
| 1266 | if (strcmp(ThisStruct.mcinputtable[k].val, McStasStruct.mcinputtable[k].val)) |
|---|
| 1267 | flag_equiv_parval=0; |
|---|
| 1268 | } |
|---|
| 1269 | } |
|---|
| 1270 | if (!flag_equiv_parname) continue; |
|---|
| 1271 | |
|---|
| 1272 | /* Data/List: must be of same kind */ |
|---|
| 1273 | char flag_list = 0; |
|---|
| 1274 | if ( strstr(ThisStruct.Format, " list ") && strstr(McStasStruct.Format, " list ")) |
|---|
| 1275 | flag_list=1; /* two lists */ |
|---|
| 1276 | else if (!strstr(ThisStruct.Format, " list ") && !strstr(McStasStruct.Format, " list ")) |
|---|
| 1277 | flag_list=2; /* two monitors */ |
|---|
| 1278 | if (!flag_list) continue; |
|---|
| 1279 | |
|---|
| 1280 | /* Data type check: dimension, limits, xvar, yvar, zvar, xlabel, ylabel, zlabel */ |
|---|
| 1281 | /* limits may be forced (to avoid rounding errors) */ |
|---|
| 1282 | /* number of rows may be different for lists */ |
|---|
| 1283 | char flag_data = ( |
|---|
| 1284 | (flag_list==1 || ThisStruct.m == McStasStruct.m) && |
|---|
| 1285 | ThisStruct.n == McStasStruct.n && |
|---|
| 1286 | ThisStruct.p == McStasStruct.p && |
|---|
| 1287 | (!ThisStruct.xvar || !McStasStruct.xvar || !strcmp(ThisStruct.xvar, McStasStruct.xvar)) && |
|---|
| 1288 | (!ThisStruct.yvar || !McStasStruct.yvar || !strcmp(ThisStruct.yvar, McStasStruct.yvar)) && |
|---|
| 1289 | (!ThisStruct.zvar || !McStasStruct.zvar || !strcmp(ThisStruct.zvar, McStasStruct.zvar)) && |
|---|
| 1290 | (!ThisStruct.xlabel || !McStasStruct.xlabel || !strcmp(ThisStruct.xlabel, McStasStruct.xlabel)) && |
|---|
| 1291 | (!ThisStruct.ylabel || !McStasStruct.ylabel || !strcmp(ThisStruct.ylabel, McStasStruct.ylabel)) && |
|---|
| 1292 | (!ThisStruct.zlabel || !McStasStruct.zlabel || !strcmp(ThisStruct.zlabel, McStasStruct.zlabel)) ); |
|---|
| 1293 | if (!flag_data) continue; |
|---|
| 1294 | |
|---|
| 1295 | char flag_limits=(mcforcemode || mcscanmode || |
|---|
| 1296 | (ThisStruct.n == 1 && ThisStruct.x1 == McStasStruct.x1) || |
|---|
| 1297 | (ThisStruct.x1 == McStasStruct.x1 && ThisStruct.y1 == McStasStruct.y1) |
|---|
| 1298 | ); |
|---|
| 1299 | if (!flag_limits) { |
|---|
| 1300 | fprintf(stderr, "Warning: Axes limits are not identical for %s and %s. Skipping (use --force to override).\n", |
|---|
| 1301 | McStasStruct.filename, ThisStruct.filename); |
|---|
| 1302 | continue; |
|---|
| 1303 | } |
|---|
| 1304 | |
|---|
| 1305 | /* Warning if gravitation not constant (may be forced) */ |
|---|
| 1306 | char flag_gravitation = mcforcemode || ( |
|---|
| 1307 | ThisStruct.gravitation && McStasStruct.gravitation |
|---|
| 1308 | && !strcmp(ThisStruct.gravitation, McStasStruct.gravitation)); |
|---|
| 1309 | if (!flag_gravitation && (ThisStruct.gravitation || McStasStruct.gravitation)) |
|---|
| 1310 | fprintf(stderr, "Warning: Gravitation is not constant for %s and %s.\n", |
|---|
| 1311 | McStasStruct.filename, ThisStruct.filename); |
|---|
| 1312 | |
|---|
| 1313 | /* Names check: InstrName, Source and component */ |
|---|
| 1314 | /* directories must be different except if mcmergesamedir */ |
|---|
| 1315 | char flag_names = ( |
|---|
| 1316 | (!ThisStruct.InstrName || !McStasStruct.InstrName |
|---|
| 1317 | || !strcmp(ThisStruct.InstrName, McStasStruct.InstrName)) && |
|---|
| 1318 | (!ThisStruct.Source || !McStasStruct.Source |
|---|
| 1319 | || !strcmp(ThisStruct.Source, McStasStruct.Source)) && |
|---|
| 1320 | (!ThisStruct.component || !McStasStruct.component |
|---|
| 1321 | || !strcmp(ThisStruct.component, McStasStruct.component)) && |
|---|
| 1322 | (mcmergesamedir || !ThisStruct.mcdirname || !McStasStruct.mcdirname |
|---|
| 1323 | || strcmp(ThisStruct.mcdirname, McStasStruct.mcdirname)) ); |
|---|
| 1324 | if (!flag_names) continue; |
|---|
| 1325 | |
|---|
| 1326 | /* handle scan index */ |
|---|
| 1327 | if (!flag_equiv_parval) { |
|---|
| 1328 | /* attach index j to scan column origin monitor 'i' */ |
|---|
| 1329 | if (Scans_to_merge[i] < 0) Scans_to_merge[i] = i; |
|---|
| 1330 | if (mcverbose && Scans_to_merge[j] < 0 && Scans_to_merge[i] >= 0) printf(" Gathering Scan step %s/%s (%d) with %s/%s (%d)\n", |
|---|
| 1331 | McStasStruct.mcdirname, McStasStruct.outputname, i, |
|---|
| 1332 | ThisStruct.mcdirname, ThisStruct.outputname, j); |
|---|
| 1333 | if (Scans_to_merge[j] < 0) Scans_to_merge[j] = i; |
|---|
| 1334 | /* next i if this is a scan (no add/cat) */ |
|---|
| 1335 | continue; /* for j */ |
|---|
| 1336 | } |
|---|
| 1337 | |
|---|
| 1338 | if (!mcmergemode) continue; |
|---|
| 1339 | |
|---|
| 1340 | if (mcverbose) fprintf(stderr," %s %s/%s (%d) with %s/%s (%d) total %ld elements\n", |
|---|
| 1341 | flag_list==2 ? "Adding" : "Appending", |
|---|
| 1342 | McStasStruct.mcdirname, McStasStruct.outputname, i, |
|---|
| 1343 | ThisStruct.mcdirname, ThisStruct.outputname, j, |
|---|
| 1344 | (long)abs(McStasStruct.m*McStasStruct.n*McStasStruct.p)); |
|---|
| 1345 | |
|---|
| 1346 | if (flag_list==1) { /* if list: catenate data j to end of i */ |
|---|
| 1347 | /* allocate new array of size rows(i+j), same n,p */ |
|---|
| 1348 | double *p1=mem(abs((ThisStruct.m+McStasStruct.m)*McStasStruct.n*McStasStruct.p)*sizeof(double)); |
|---|
| 1349 | /* copy data from i */ |
|---|
| 1350 | int index_i, index_j, index; /* data index is index_i*columns+index_j */ |
|---|
| 1351 | for (index_i=0; index_i<abs(McStasStruct.m); index_i++) |
|---|
| 1352 | for (index_j=0; index_j<abs(McStasStruct.n*McStasStruct.p); index_j++) { |
|---|
| 1353 | index=index_i*abs(McStasStruct.n*McStasStruct.p)+index_j; |
|---|
| 1354 | p1[index] = McStasStruct.p1[index]; |
|---|
| 1355 | } |
|---|
| 1356 | /* catenate data from j */ |
|---|
| 1357 | for (index_i=0; index_i<abs(ThisStruct.m); index_i++) |
|---|
| 1358 | for (index_j=0; index_j<abs(McStasStruct.n*McStasStruct.p); index_j++) { |
|---|
| 1359 | int index_shifted=(index_i+abs(McStasStruct.m))*abs(McStasStruct.n*McStasStruct.p)+index_j; |
|---|
| 1360 | index=index_i*abs(McStasStruct.n*McStasStruct.p)+index_j; |
|---|
| 1361 | p1[index_shifted] = ThisStruct.p1[index]; |
|---|
| 1362 | } |
|---|
| 1363 | Files_to_Merge[i].m += ThisStruct.m; |
|---|
| 1364 | /* free original arrays in i and j */ |
|---|
| 1365 | memfree(McStasStruct.p1); memfree(ThisStruct.p1); |
|---|
| 1366 | Files_to_Merge[j].p1 = NULL; |
|---|
| 1367 | /* attach new array to i and leave j in empty state */ |
|---|
| 1368 | Files_to_Merge[i].p1 = p1; |
|---|
| 1369 | } else { /* else add data i+j */ |
|---|
| 1370 | int index_i; |
|---|
| 1371 | /* add data from j to i. p1 and p2 are weighted by their Ncount */ |
|---|
| 1372 | for (index_i=0; index_i<abs(McStasStruct.m*McStasStruct.n*McStasStruct.p); index_i++) { |
|---|
| 1373 | if (McStasStruct.p0) Files_to_Merge[i].p0[index_i] += ThisStruct.p0[index_i]; |
|---|
| 1374 | Files_to_Merge[i].p1[index_i] += ThisStruct.Ncount*ThisStruct.p1[index_i]; |
|---|
| 1375 | if (McStasStruct.p2) Files_to_Merge[i].p2[index_i] += ThisStruct.Ncount*ThisStruct.p2[index_i]; |
|---|
| 1376 | |
|---|
| 1377 | } |
|---|
| 1378 | /* free and leave j in empty state */ |
|---|
| 1379 | memfree(ThisStruct.p0); memfree(ThisStruct.p1); memfree(ThisStruct.p2); |
|---|
| 1380 | Files_to_Merge[j].p0=Files_to_Merge[j].p1=Files_to_Merge[j].p2=NULL; |
|---|
| 1381 | } |
|---|
| 1382 | Files_to_Merge[i].Ncount += ThisStruct.Ncount; |
|---|
| 1383 | Files_to_Merge[i].RunNum += ThisStruct.RunNum; |
|---|
| 1384 | } /* end for j */ |
|---|
| 1385 | |
|---|
| 1386 | /* divide p1 and p2 by total Ncount to account for the weighted sum */ |
|---|
| 1387 | if (!strstr(McStasStruct.Format, " list ")) /* NOT FOR LISTs (content non additive) */ |
|---|
| 1388 | for (j=0; j<abs(McStasStruct.m*McStasStruct.n*McStasStruct.p); j++) { |
|---|
| 1389 | Files_to_Merge[i].p1[j] /= Files_to_Merge[i].Ncount; |
|---|
| 1390 | if (Files_to_Merge[i].p2) Files_to_Merge[i].p2[j] /= Files_to_Merge[i].Ncount; |
|---|
| 1391 | } |
|---|
| 1392 | |
|---|
| 1393 | /* now count integral values for item Files_to_Merge[i] */ |
|---|
| 1394 | double Nsum=0, Psum=0, P2sum=0; |
|---|
| 1395 | for (j=0; j<abs(Files_to_Merge[i].m*Files_to_Merge[i].n*Files_to_Merge[i].p); j++) { |
|---|
| 1396 | double N=1,I=0,E=0; |
|---|
| 1397 | if (Files_to_Merge[i].p0) N = Files_to_Merge[i].p0[j]; |
|---|
| 1398 | if (Files_to_Merge[i].p1) I = Files_to_Merge[i].p1[j]; |
|---|
| 1399 | if (Files_to_Merge[i].p2) E = Files_to_Merge[i].p2[j]; |
|---|
| 1400 | Nsum += N; |
|---|
| 1401 | Psum += I; |
|---|
| 1402 | P2sum += Files_to_Merge[i].p2 ? E : I*I; |
|---|
| 1403 | } |
|---|
| 1404 | Files_to_Merge[i].Nsum = Nsum; |
|---|
| 1405 | Files_to_Merge[i].Psum = Psum; |
|---|
| 1406 | Files_to_Merge[i].P2sum= P2sum; |
|---|
| 1407 | } /* end for i */ |
|---|
| 1408 | return(nb); |
|---|
| 1409 | } /* mcformat_merge_compare */ |
|---|
| 1410 | |
|---|
| 1411 | /* sorting functions for qsort: sort monitor files with distance */ |
|---|
| 1412 | #ifdef HAVE_QSORT |
|---|
| 1413 | int sort_distances (const void *a, const void *b) |
|---|
| 1414 | { |
|---|
| 1415 | const int *pa = (const int *) a; |
|---|
| 1416 | const int *pb = (const int *) b; |
|---|
| 1417 | int ia=*pa; |
|---|
| 1418 | int ib=*pb; |
|---|
| 1419 | double da=Files_to_Merge[ia].POSITION.x*Files_to_Merge[ia].POSITION.x |
|---|
| 1420 | +Files_to_Merge[ia].POSITION.y*Files_to_Merge[ia].POSITION.y |
|---|
| 1421 | +Files_to_Merge[ia].POSITION.z*Files_to_Merge[ia].POSITION.z; |
|---|
| 1422 | double db=Files_to_Merge[ib].POSITION.x*Files_to_Merge[ib].POSITION.x |
|---|
| 1423 | +Files_to_Merge[ib].POSITION.y*Files_to_Merge[ib].POSITION.y |
|---|
| 1424 | +Files_to_Merge[ib].POSITION.z*Files_to_Merge[ib].POSITION.z; |
|---|
| 1425 | if (da > db) return 1; |
|---|
| 1426 | else if (da < db) return -1; |
|---|
| 1427 | else /* same distance, sort on names */ |
|---|
| 1428 | return strcmp(Files_to_Merge[ia].filename, Files_to_Merge[ib].filename); |
|---|
| 1429 | } |
|---|
| 1430 | |
|---|
| 1431 | /* sorting functions for qsort: sort monitor column with ipar.val */ |
|---|
| 1432 | int sort_ipar_mon (const void *a, const void *b) |
|---|
| 1433 | { |
|---|
| 1434 | const int *pa = (const int *) a; |
|---|
| 1435 | const int *pb = (const int *) b; |
|---|
| 1436 | int ia=*pa; |
|---|
| 1437 | int ib=*pb; |
|---|
| 1438 | double da=Files_to_Merge[ia].mcinputtable[ipar_var].type == instr_type_string ? |
|---|
| 1439 | 0 : atof(Files_to_Merge[ia].mcinputtable[ipar_var].val); |
|---|
| 1440 | double db=Files_to_Merge[ib].mcinputtable[ipar_var].type == instr_type_string ? |
|---|
| 1441 | 0 : atof(Files_to_Merge[ib].mcinputtable[ipar_var].val); |
|---|
| 1442 | if (da > db) return 1; |
|---|
| 1443 | else if (da < db) return -1; |
|---|
| 1444 | else {/* same distance, sort on ipar value then filenames */ |
|---|
| 1445 | int tmp=strcmp(Files_to_Merge[ia].mcinputtable[ipar_var].val, |
|---|
| 1446 | Files_to_Merge[ib].mcinputtable[ipar_var].val); |
|---|
| 1447 | if (tmp) return(tmp); |
|---|
| 1448 | else return strcmp(Files_to_Merge[ia].filename, Files_to_Merge[ib].filename); |
|---|
| 1449 | } |
|---|
| 1450 | } |
|---|
| 1451 | #endif |
|---|
| 1452 | |
|---|
| 1453 | /********************************************************************* |
|---|
| 1454 | * mcformat_scan_compare: assemble scanned monitors into multiarray sets |
|---|
| 1455 | * warning: this function is a real headache |
|---|
| 1456 | *********************************************************************/ |
|---|
| 1457 | void mcformat_scan_compare(int nb) |
|---|
| 1458 | { |
|---|
| 1459 | /* definition of a scan |
|---|
| 1460 | Must be 'mergeable' data but with different ipar values |
|---|
| 1461 | Each Scans_to_merge[] index set is a column of multiarray_1d (this is a scanned monitor) |
|---|
| 1462 | Must analyse scan columns (Scans_to_merge[]) to gather them with |
|---|
| 1463 | -common ipar names (set of scanned monitors) |
|---|
| 1464 | -same set (monitor number) length and monitor names |
|---|
| 1465 | -same ipar values define rows |
|---|
| 1466 | */ |
|---|
| 1467 | int scan_index1=0; |
|---|
| 1468 | int i=0,j; |
|---|
| 1469 | |
|---|
| 1470 | /* test if there is scan data to be processed */ |
|---|
| 1471 | for (scan_index1=0; scan_index1<nb; scan_index1++) { |
|---|
| 1472 | if (Scans_to_merge[scan_index1] < 0 || Scans_to_merge[scan_index1] < scan_index1) continue; |
|---|
| 1473 | else { i=1; break; } |
|---|
| 1474 | } |
|---|
| 1475 | |
|---|
| 1476 | if (i == 0) |
|---|
| 1477 | fprintf(stderr, "Warning: Could not find scanned parameter within 'Param' lines in data file headers.\n" |
|---|
| 1478 | "Ignoring [mcformat:mcformat_scan_compare].\n"); |
|---|
| 1479 | |
|---|
| 1480 | /* loop on Scans_to_merge: index > -1 */ |
|---|
| 1481 | for (scan_index1=0; scan_index1<nb; scan_index1++) { |
|---|
| 1482 | if (Scans_to_merge[scan_index1] < 0 || Scans_to_merge[scan_index1] < scan_index1) continue; |
|---|
| 1483 | /* get all sets of given index: Scans_to_merge[j] = index */ |
|---|
| 1484 | int scan_length1= 1; |
|---|
| 1485 | int next_in_scan=-1; |
|---|
| 1486 | ipar_var = 0; /* global variable, as it is used in sorting function 'sort_ipar_mon' */ |
|---|
| 1487 | int scan_index2; |
|---|
| 1488 | /* compute length of monitor column (length of scan): scan_length1 */ |
|---|
| 1489 | for (scan_index2=scan_index1+1; scan_index2<nb; scan_index2++) |
|---|
| 1490 | if (Scans_to_merge[scan_index1] == Scans_to_merge[scan_index2]) { |
|---|
| 1491 | scan_length1++; |
|---|
| 1492 | if (next_in_scan < 0) next_in_scan = scan_index2; |
|---|
| 1493 | } |
|---|
| 1494 | if (scan_length1 <= 1) continue; /* not a scan, single data set: go to next data file */ |
|---|
| 1495 | |
|---|
| 1496 | /* count other monitors in Scans_to_merge with same ipar names and values: mon_count */ |
|---|
| 1497 | int mon_count=0; |
|---|
| 1498 | int Scan_columns[nb]; |
|---|
| 1499 | for (scan_index2=0; scan_index2<nb; Scan_columns[scan_index2++]=-1); |
|---|
| 1500 | |
|---|
| 1501 | for (scan_index2=0; scan_index2<nb; scan_index2++) { |
|---|
| 1502 | char flag_matchpar=0; |
|---|
| 1503 | if (scan_index1 == scan_index2) { |
|---|
| 1504 | mon_count++; Scan_columns[scan_index2] = scan_index1; continue; |
|---|
| 1505 | } |
|---|
| 1506 | /* must be a scan */ |
|---|
| 1507 | if (Scans_to_merge[scan_index2] < 0) continue; /* scan_index2 */ |
|---|
| 1508 | /* must have same numipar */ |
|---|
| 1509 | if (Files_to_Merge[scan_index1].mcnumipar != Files_to_Merge[scan_index2].mcnumipar) continue; /* scan_index2 */ |
|---|
| 1510 | /* must have same scan length as first monitor */ |
|---|
| 1511 | int scan_length2= 0; |
|---|
| 1512 | for (j=scan_index2; j<nb; j++) |
|---|
| 1513 | if (Scans_to_merge[scan_index2] == Scans_to_merge[j]) { |
|---|
| 1514 | scan_length2++; |
|---|
| 1515 | } |
|---|
| 1516 | if (scan_length1 != scan_length2) continue; /* scan_index2 */ |
|---|
| 1517 | /* must have same ipar.name and values along column */ |
|---|
| 1518 | int ipar2; |
|---|
| 1519 | for (ipar2=0; ipar2<Files_to_Merge[scan_index2].mcnumipar; ipar2++) { |
|---|
| 1520 | char *this_parname = Files_to_Merge[scan_index2].mcinputtable[ipar2].name; |
|---|
| 1521 | char *this_parval = Files_to_Merge[scan_index2].mcinputtable[ipar2].val; |
|---|
| 1522 | /* look back into 'scan_index1' series for similar parameters */ |
|---|
| 1523 | for(j=scan_index1; j<nb; j++) { |
|---|
| 1524 | if (Scans_to_merge[j] == Scans_to_merge[scan_index1]) { |
|---|
| 1525 | /* in original column, look if we can find ipar */ |
|---|
| 1526 | int ipar1; |
|---|
| 1527 | for (ipar1=0; ipar1<Files_to_Merge[j].mcnumipar; ipar1++) { |
|---|
| 1528 | if (strcmp(Files_to_Merge[j].mcinputtable[ipar1].name, this_parname) |
|---|
| 1529 | || strcmp(Files_to_Merge[j].mcinputtable[ipar1].val, this_parval) ) continue; /* ipar1 */ |
|---|
| 1530 | flag_matchpar=1; |
|---|
| 1531 | break; |
|---|
| 1532 | } /* for ipar1 */ |
|---|
| 1533 | if (flag_matchpar) break; /* j: we found matching ipar both in scan_index1 and scan_index2 */ |
|---|
| 1534 | } /* if */ |
|---|
| 1535 | } /* for scan_index1b */ |
|---|
| 1536 | if (!flag_matchpar) break; /* ipar2: ipar of scan_index2 not found in scan_index1 */ |
|---|
| 1537 | } /* for ipar2 */ |
|---|
| 1538 | if (!flag_matchpar) continue; /* scan_index2: an ipar of scan_index2 was not found in scan_index1. try other scan_index2 */ |
|---|
| 1539 | else { |
|---|
| 1540 | mon_count++; |
|---|
| 1541 | /* attach that file to first monitor of dir/column */ |
|---|
| 1542 | Scan_columns[scan_index2] = scan_index2; |
|---|
| 1543 | } |
|---|
| 1544 | } /* for scan_index2 */ |
|---|
| 1545 | |
|---|
| 1546 | /* get first varying ipar: ipar_var */ |
|---|
| 1547 | for (j=0; j<Files_to_Merge[scan_index1].mcnumipar; j++) { |
|---|
| 1548 | /* compare ipar value of scan_index1 and next_in_scan: stored in j */ |
|---|
| 1549 | if (strcmp(Files_to_Merge[scan_index1].mcinputtable[j].val, Files_to_Merge[next_in_scan].mcinputtable[j].val)) break; |
|---|
| 1550 | } |
|---|
| 1551 | /* test if ipar has changed in scan else go to next data file */ |
|---|
| 1552 | if (j < Files_to_Merge[scan_index1].mcnumipar) ipar_var=j; |
|---|
| 1553 | /* now we know how many scanned monitor there are */ |
|---|
| 1554 | |
|---|
| 1555 | if (mcverbose) |
|---|
| 1556 | printf("scan from %s has %d rows (scan steps) of %d columns (monitors) varying %s\n", |
|---|
| 1557 | Files_to_Merge[scan_index1].filename, scan_length1, mon_count, |
|---|
| 1558 | Files_to_Merge[scan_index1].mcinputtable[ipar_var].name); |
|---|
| 1559 | |
|---|
| 1560 | /* single Scan_columns[] is an unsorted row |
|---|
| 1561 | and have same ipar name/value in same dir/row */ |
|---|
| 1562 | |
|---|
| 1563 | /* single Scans_to_merge[i] value is an unsorted column |
|---|
| 1564 | and have same name in different directories/columns |
|---|
| 1565 | but different ipar values */ |
|---|
| 1566 | |
|---|
| 1567 | /* allocate array: scan_length1(rows)*(mcnumipar+2*mon_count) */ |
|---|
| 1568 | t_Table Scan; |
|---|
| 1569 | if (!Table_Init(&Scan, |
|---|
| 1570 | scan_length1, |
|---|
| 1571 | Files_to_Merge[scan_index1].mcnumipar+2*mon_count)) { |
|---|
| 1572 | fprintf(stderr, "Warning: %s: Can not allocate Scan %ix(%i+2*%i) multiarray_1d. Skipping.\n", |
|---|
| 1573 | Files_to_Merge[scan_index1].filename, scan_length1, |
|---|
| 1574 | Files_to_Merge[scan_index1].mcnumipar, |
|---|
| 1575 | mon_count); |
|---|
| 1576 | continue; |
|---|
| 1577 | } |
|---|
| 1578 | char *header=(char*)mem(64*CHAR_BUF_LENGTH); strcpy(header, ""); |
|---|
| 1579 | char *youts =(char*)mem(64*CHAR_BUF_LENGTH); strcpy(youts, ""); |
|---|
| 1580 | double ipar_min=FLT_MAX, ipar_max=0; |
|---|
| 1581 | |
|---|
| 1582 | /* we first sort Scan_columns(monitors) with distance */ |
|---|
| 1583 | int Scan_distances[mon_count]; /* this is column index */ |
|---|
| 1584 | j = 0; |
|---|
| 1585 | |
|---|
| 1586 | for (scan_index2=0; scan_index2<nb; scan_index2++) |
|---|
| 1587 | if (Scan_columns[scan_index2]>=0) Scan_distances[j++] = Scan_columns[scan_index2]; |
|---|
| 1588 | #ifdef HAVE_QSORT |
|---|
| 1589 | qsort(Scan_distances, mon_count, sizeof(int), sort_distances); |
|---|
| 1590 | #endif |
|---|
| 1591 | for (j=0; j<mon_count; j++) { /* loop for each column */ |
|---|
| 1592 | int Monitor_column[scan_length1]; |
|---|
| 1593 | int k=0; |
|---|
| 1594 | for (i=0; i<scan_length1; Monitor_column[i]=i) { i++; } |
|---|
| 1595 | for (scan_index2=0; scan_index2<nb; scan_index2++) { |
|---|
| 1596 | /* find Scan_distances[j] in Scans_to_merge */ |
|---|
| 1597 | if (Scans_to_merge[scan_index2] >= 0 && Scans_to_merge[scan_index2] == Scan_distances[j]) { |
|---|
| 1598 | Monitor_column[k++] = scan_index2; |
|---|
| 1599 | Scans_to_merge[scan_index2]=-1; /*unactivate that scan element */ |
|---|
| 1600 | } |
|---|
| 1601 | } |
|---|
| 1602 | /* sort each monitor column with ipar value */ |
|---|
| 1603 | #ifdef HAVE_QSORT |
|---|
| 1604 | qsort(Monitor_column, scan_length1, sizeof(int), sort_ipar_mon); |
|---|
| 1605 | #endif |
|---|
| 1606 | /* extract sorted column and set Scan */ |
|---|
| 1607 | for (i=0; i<scan_length1; i++) { /* loop on column elements(row) */ |
|---|
| 1608 | Table_SetElement(&Scan, |
|---|
| 1609 | i, |
|---|
| 1610 | Files_to_Merge[scan_index1].mcnumipar+2*j, |
|---|
| 1611 | Files_to_Merge[Monitor_column[i]].Psum); |
|---|
| 1612 | Table_SetElement(&Scan, |
|---|
| 1613 | i, Files_to_Merge[scan_index1].mcnumipar+2*j+1, |
|---|
| 1614 | mcestimate_error( |
|---|
| 1615 | Files_to_Merge[Monitor_column[i]].Ncount, |
|---|
| 1616 | Files_to_Merge[Monitor_column[i]].Psum, |
|---|
| 1617 | Files_to_Merge[Monitor_column[i]].P2sum)); |
|---|
| 1618 | if (j==0) { /* first monitor in row also sets ipar */ |
|---|
| 1619 | for (k=0; k<Files_to_Merge[Monitor_column[i]].mcnumipar; k++) { |
|---|
| 1620 | Table_SetElement(&Scan, |
|---|
| 1621 | i, k, |
|---|
| 1622 | atof(Files_to_Merge[Monitor_column[i]].mcinputtable[k].val)); |
|---|
| 1623 | /* set name of ipar */ |
|---|
| 1624 | if (i==0) { |
|---|
| 1625 | strcat(header, Files_to_Merge[Monitor_column[i]].mcinputtable[k].name); |
|---|
| 1626 | strcat(header, " "); |
|---|
| 1627 | } |
|---|
| 1628 | } |
|---|
| 1629 | } /* if j==0 */ |
|---|
| 1630 | double this=atof(Files_to_Merge[Monitor_column[i]].mcinputtable[ipar_var].val); |
|---|
| 1631 | if (ipar_min > this) ipar_min=this; |
|---|
| 1632 | if (ipar_max < this) ipar_max=this; |
|---|
| 1633 | } /* for i */ |
|---|
| 1634 | strcat(header, Files_to_Merge[Scan_distances[j]].outputname); strcat(header, "_I "); |
|---|
| 1635 | strcat(header, Files_to_Merge[Scan_distances[j]].outputname); strcat(header, "_Err "); |
|---|
| 1636 | strcat(youts, "("); strcat(youts, Files_to_Merge[Scan_distances[j]].outputname); strcat(youts, "_I,"); |
|---|
| 1637 | strcat(youts, Files_to_Merge[Scan_distances[j]].outputname); strcat(youts, "_Err) "); |
|---|
| 1638 | } /* for j */ |
|---|
| 1639 | Scan.header=header; |
|---|
| 1640 | |
|---|
| 1641 | Scans_to_merge[scan_index1]=-1; /* unactivate that scan element */ |
|---|
| 1642 | |
|---|
| 1643 | char *title=str_cat("Scan of ", |
|---|
| 1644 | Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, NULL); |
|---|
| 1645 | /* output scan multiarray */ |
|---|
| 1646 | /* for PGPLOT: open mcstas.sim */ |
|---|
| 1647 | if (strstr(mcformat.Name, "McStas")) mcsiminfo_init(NULL); /* open new SIM file in this dir for the first time */ |
|---|
| 1648 | else mcsiminfo_name=NULL; |
|---|
| 1649 | char *datfile=NULL; |
|---|
| 1650 | if (mcsingle_file && mcsiminfo_name) datfile=str_dup(mcsiminfo_name); |
|---|
| 1651 | if (!datfile) datfile = str_cat("mcstas.", strstr(mcformat.Name, "McStas") ? "dat" : mcformat.Extension, NULL); |
|---|
| 1652 | strcat(mcformat.Name, " scan "); |
|---|
| 1653 | if (mcverbose) |
|---|
| 1654 | printf("Writing scan file=%s (%s) into directory %s: %s=%g:%g\n", |
|---|
| 1655 | datfile, mcsiminfo_name, mcdirname, |
|---|
| 1656 | Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, ipar_min, ipar_max); |
|---|
| 1657 | strcpy(mcinstrument_name, Files_to_Merge[scan_index1].InstrName); |
|---|
| 1658 | strcpy(mcinstrument_source, Files_to_Merge[scan_index1].Source); |
|---|
| 1659 | if (!mctestmode) |
|---|
| 1660 | mcdetector_out_3D(title, |
|---|
| 1661 | Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, |
|---|
| 1662 | Files_to_Merge[scan_index1].ylabel, "", |
|---|
| 1663 | Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, |
|---|
| 1664 | youts, |
|---|
| 1665 | header, |
|---|
| 1666 | ipar_min, ipar_max, 0, 0, 0, 0, |
|---|
| 1667 | -scan_length1, Files_to_Merge[scan_index1].mcnumipar+2*mon_count, 1, |
|---|
| 1668 | NULL, Scan.data, NULL, datfile, |
|---|
| 1669 | Files_to_Merge[scan_index1].component, |
|---|
| 1670 | Files_to_Merge[scan_index1].POSITION); |
|---|
| 1671 | |
|---|
| 1672 | /* for PGPLOT: close mcstas.sim */ |
|---|
| 1673 | if (strstr(mcformat.Name, "McStas")) mcsiminfo_close(); |
|---|
| 1674 | Table_Free(&Scan); |
|---|
| 1675 | memfree(datfile); |
|---|
| 1676 | memfree(youts); |
|---|
| 1677 | memfree(title); |
|---|
| 1678 | /* go to end of scan and continue to search for scans */ |
|---|
| 1679 | } /* for scan_index1 */ |
|---|
| 1680 | } /* mcformat_scan_compare */ |
|---|
| 1681 | |
|---|
| 1682 | /******************************************************************************* |
|---|
| 1683 | * mcformat_merge_output: output non empty files |
|---|
| 1684 | * special handling for multiarray/scans |
|---|
| 1685 | *******************************************************************************/ |
|---|
| 1686 | int mcformat_merge_output(int nb) |
|---|
| 1687 | { |
|---|
| 1688 | int i; |
|---|
| 1689 | char mctestmode_sav=mctestmode; |
|---|
| 1690 | if (mcscanmode == 2) mctestmode=1; /* scan only will skip writing for non scan files */ |
|---|
| 1691 | /* output files for non empty elements */ |
|---|
| 1692 | for (i=0; i<nb; i++) { |
|---|
| 1693 | if (mcformat_output(Files_to_Merge[i])) { |
|---|
| 1694 | if (mcverbose) { |
|---|
| 1695 | printf("mcformat: merging/scanning %s ", Files_to_Merge[i].outputname); |
|---|
| 1696 | printf("into %s%s ", |
|---|
| 1697 | Files_to_Merge[i].mcdirname ? Files_to_Merge[i].mcdirname : ".", |
|---|
| 1698 | Files_to_Merge[i].mcdirname ? MC_PATHSEP_S : ""); |
|---|
| 1699 | if (mctestmode) printf(" (--test or --scan-only mode)\n"); else printf("\n"); |
|---|
| 1700 | } |
|---|
| 1701 | } |
|---|
| 1702 | } |
|---|
| 1703 | mctestmode = mctestmode_sav; |
|---|
| 1704 | |
|---|
| 1705 | if (mcscanmode) { |
|---|
| 1706 | /* build and output scans (if any) for non empty elements of same index */ |
|---|
| 1707 | mcformat_scan_compare(nb); |
|---|
| 1708 | /* allocate nb_scan rows of nb_vars+(nb_monitors*3) columns */ |
|---|
| 1709 | /* fill in scan variables extracted from mcinputtable */ |
|---|
| 1710 | /* fill in monitor values */ |
|---|
| 1711 | /* call outout routine for scans (can not be binary format): from mcrun.pl */ |
|---|
| 1712 | } |
|---|
| 1713 | |
|---|
| 1714 | /* free merged/scan elements */ |
|---|
| 1715 | for (i=0; i<nb; i++) mcformat_free_mcstas_struct(Files_to_Merge[i]); |
|---|
| 1716 | return(nb); |
|---|
| 1717 | } |
|---|
| 1718 | |
|---|
| 1719 | /******************************************************************************* |
|---|
| 1720 | * mcformat_usage: print mcformat usage/help |
|---|
| 1721 | *******************************************************************************/ |
|---|
| 1722 | void mcformat_usage(char *pgmname) |
|---|
| 1723 | { |
|---|
| 1724 | int i; |
|---|
| 1725 | |
|---|
| 1726 | fprintf(stderr, "mcformat version %s format conversion tool (" MCSTAS_VERSION ")\n", MCFORMAT); |
|---|
| 1727 | fprintf(stderr, "Usage: %s [options] file1|dir1 file2|dir2 ...\n", pgmname); |
|---|
| 1728 | fprintf(stderr, |
|---|
| 1729 | "Convert/merge files and directories from McStas format to an other specified format\n" |
|---|
| 1730 | "Options are:\n" |
|---|
| 1731 | " -d DIR --dir=DIR Put all data files in directory DIR.\n" |
|---|
| 1732 | " -f FILE --file=FILE Put all data in a single file.\n" |
|---|
| 1733 | " -a --data-only Do not put any headers in the data files.\n" |
|---|
| 1734 | " --no-output-files Do not write any data files (test data).\n" |
|---|
| 1735 | " -h --help Show this help message.\n" |
|---|
| 1736 | " -p FORMAT --format=FORMAT Output data files using format FORMAT\n" |
|---|
| 1737 | " -c --force Force writting in existing directories\n" |
|---|
| 1738 | " -t --test Test mode, does not write files\n" |
|---|
| 1739 | " -m --merge Add/Append equivalent data files and lists\n" |
|---|
| 1740 | " --merge-samedir Merges inside same directories (dangerous)\n" |
|---|
| 1741 | " -s --scan Gather simulations per scan series\n" |
|---|
| 1742 | " -so --scan-only Create scan series but does not merge data\n" |
|---|
| 1743 | " --verbose Verbose mode\n" |
|---|
| 1744 | "\n" |
|---|
| 1745 | "Examples:\n" |
|---|
| 1746 | "mcformat -d target_dir original_dir\n" |
|---|
| 1747 | " # using default target format %s\n" |
|---|
| 1748 | "mcformat -d target_dir original_dir --format=target_format\n" |
|---|
| 1749 | "mcformat -d target_dir original_dir1 original_dir2 --merge\n" |
|---|
| 1750 | " # merge simulation data sets (grids)\n" |
|---|
| 1751 | "mcformat -d target_dir dir1 dir2 ... --scan\n" |
|---|
| 1752 | " # merge scan data sets\n\n", |
|---|
| 1753 | getenv("MCSTAS_FORMAT") ? getenv("MCSTAS_FORMAT") : MCSTAS_FORMAT); |
|---|
| 1754 | |
|---|
| 1755 | fprintf(stderr, "Available output formats are (default is %s):\n ", mcformat.Name); |
|---|
| 1756 | for (i=0; i < mcNUMFORMATS; fprintf(stderr,"\"%s\" " , mcformats[i++].Name) ); |
|---|
| 1757 | fprintf(stderr, "\n Format modifiers: FORMAT may be followed by 'binary float' or \n"); |
|---|
| 1758 | fprintf(stderr, " 'binary double' to save data blocks as binary. This removes text headers.\n"); |
|---|
| 1759 | fprintf(stderr, " The MCSTAS_FORMAT environment variable may set the default FORMAT to use.\n"); |
|---|
| 1760 | } /* mcformat_usage */ |
|---|
| 1761 | |
|---|
| 1762 | /******************************************************************************* |
|---|
| 1763 | * mcformat_parseoptions: parse command line parameters |
|---|
| 1764 | *******************************************************************************/ |
|---|
| 1765 | void |
|---|
| 1766 | mcformat_parseoptions(int argc, char *argv[]) |
|---|
| 1767 | { |
|---|
| 1768 | int i; |
|---|
| 1769 | char cwd[CHAR_BUF_LENGTH]; |
|---|
| 1770 | mcdirname = NULL; |
|---|
| 1771 | for(i = 1; i < argc; i++) |
|---|
| 1772 | { |
|---|
| 1773 | if(!strcmp("-d", argv[i]) && (i + 1) < argc) |
|---|
| 1774 | mcformat_usedir(argv[++i]); |
|---|
| 1775 | else if(!strncmp("-d", argv[i], 2)) |
|---|
| 1776 | mcformat_usedir(&argv[i][2]); |
|---|
| 1777 | else if(!strcmp("--dir", argv[i]) && (i + 1) < argc) |
|---|
| 1778 | mcformat_usedir(argv[++i]); |
|---|
| 1779 | else if(!strncmp("--dir=", argv[i], 6)) |
|---|
| 1780 | mcformat_usedir(&argv[i][6]); |
|---|
| 1781 | else if(!strcmp("-f", argv[i]) && (i + 1) < argc) |
|---|
| 1782 | mcuse_file(argv[++i]); |
|---|
| 1783 | else if(!strncmp("-f", argv[i], 2)) |
|---|
| 1784 | mcuse_file(&argv[i][2]); |
|---|
| 1785 | else if(!strcmp("--file", argv[i]) && (i + 1) < argc) |
|---|
| 1786 | mcuse_file(argv[++i]); |
|---|
| 1787 | else if(!strncmp("--file=", argv[i], 7)) |
|---|
| 1788 | mcuse_file(&argv[i][7]); |
|---|
| 1789 | else if(!strcmp("-h", argv[i]) || !strcmp("--help", argv[i])) |
|---|
| 1790 | { mcformat_usage(argv[0]); exit(-1); } |
|---|
| 1791 | else if(!strcmp("-v", argv[i]) || !strcmp("--version", argv[i])) |
|---|
| 1792 | { fprintf(stderr, "mcformat version %s format conversion tool (" MCSTAS_VERSION ")\n", MCFORMAT); exit(-1); } |
|---|
| 1793 | else if(!strcmp("-a", argv[i])) |
|---|
| 1794 | mcascii_only = 1; |
|---|
| 1795 | else if(!strcmp("+a", argv[i])) |
|---|
| 1796 | mcascii_only = 0; |
|---|
| 1797 | else if(!strcmp("-c", argv[i])) |
|---|
| 1798 | mcforcemode = 1; |
|---|
| 1799 | else if(!strcmp("--force", argv[i])) |
|---|
| 1800 | mcforcemode = 1; |
|---|
| 1801 | else if(!strcmp("--data-only", argv[i])) |
|---|
| 1802 | mcascii_only = 1; |
|---|
| 1803 | else if(!strncmp("--format=", argv[i], 9)) { |
|---|
| 1804 | mcascii_only = 0; |
|---|
| 1805 | mcformat=mcuse_format(&argv[i][9]); |
|---|
| 1806 | } |
|---|
| 1807 | else if(!strcmp("--format", argv[i]) && (i + 1) < argc) { |
|---|
| 1808 | mcascii_only = 0; |
|---|
| 1809 | mcformat=mcuse_format(argv[++i]); |
|---|
| 1810 | } |
|---|
| 1811 | else if(!strncmp("-p=", argv[i], 3)) { |
|---|
| 1812 | mcascii_only = 0; |
|---|
| 1813 | mcformat=mcuse_format(&argv[i][3]); |
|---|
| 1814 | } |
|---|
| 1815 | else if(!strcmp("-p", argv[i]) && (i + 1) < argc) { |
|---|
| 1816 | mcascii_only = 0; |
|---|
| 1817 | mcformat=mcuse_format(argv[++i]); |
|---|
| 1818 | } |
|---|
| 1819 | else if(!strncmp("--format_data=", argv[i], 14) || !strncmp("--format-data=", argv[i], 14)) { |
|---|
| 1820 | mcascii_only = 0; |
|---|
| 1821 | mcformat_data=mcuse_format(&argv[i][14]); |
|---|
| 1822 | } |
|---|
| 1823 | else if((!strcmp("--format_data", argv[i]) || !strcmp("--format-data", argv[i])) && (i + 1) < argc) { |
|---|
| 1824 | mcascii_only = 0; |
|---|
| 1825 | mcformat_data=mcuse_format(argv[++i]); |
|---|
| 1826 | } |
|---|
| 1827 | else if(!strcmp("--no-output-files", argv[i])) |
|---|
| 1828 | mcdisable_output_files = 1; |
|---|
| 1829 | else if(!strcmp("--verbose", argv[i])) |
|---|
| 1830 | mcverbose = 1; |
|---|
| 1831 | else if(!strcmp("-t", argv[i]) || !strcmp("--test", argv[i])) |
|---|
| 1832 | mctestmode = 1; |
|---|
| 1833 | else if(!strcmp("-m", argv[i]) || !strcmp("--merge", argv[i])) |
|---|
| 1834 | mcmergemode= 1; |
|---|
| 1835 | else if(!strcmp("-s", argv[i]) || !strcmp("--scan", argv[i])) |
|---|
| 1836 | mcscanmode = 1; |
|---|
| 1837 | else if(!strcmp("-so", argv[i]) || !strcmp("--scan-only", argv[i])) |
|---|
| 1838 | mcscanmode = 2; |
|---|
| 1839 | else if(!strcmp("--merge-samedir", argv[i])) |
|---|
| 1840 | mcmergesamedir=mcmergemode=1; |
|---|
| 1841 | else { |
|---|
| 1842 | /* convert argv[i]: store index of argument */ |
|---|
| 1843 | if (files_to_convert_NB <CHAR_BUF_LENGTH) |
|---|
| 1844 | files_to_convert_Array[files_to_convert_NB++] = i; |
|---|
| 1845 | else |
|---|
| 1846 | fprintf(stderr, "Warning: Exceeding maximum number of files to process (%d).\n" |
|---|
| 1847 | "Ignoring %s [mcformat:mcformat_parseoptions].\n", |
|---|
| 1848 | CHAR_BUF_LENGTH, argv[i]); |
|---|
| 1849 | } |
|---|
| 1850 | } |
|---|
| 1851 | if (!mcascii_only) { |
|---|
| 1852 | if (strstr(mcformat.Name,"binary")) |
|---|
| 1853 | fprintf(stderr, "Warning: %s files will contain text headers.\n" |
|---|
| 1854 | " Use -a option to clean up.\n", mcformat.Name); |
|---|
| 1855 | strcat(mcformat.Name, " with text headers"); |
|---|
| 1856 | } |
|---|
| 1857 | if (!mcdirname) { |
|---|
| 1858 | getcwd(cwd, CHAR_BUF_LENGTH); |
|---|
| 1859 | mcdirname = str_dup(cwd); /* default is to export to PWD */ |
|---|
| 1860 | } |
|---|
| 1861 | } /* mcformat_parseoptions */ |
|---|
| 1862 | |
|---|
| 1863 | /******************************************************************************* |
|---|
| 1864 | * main: program entry point (start):calls parseoptions, convert and merge |
|---|
| 1865 | *******************************************************************************/ |
|---|
| 1866 | int main(int argc, char *argv[]) |
|---|
| 1867 | { |
|---|
| 1868 | time_t t; |
|---|
| 1869 | int j; |
|---|
| 1870 | |
|---|
| 1871 | #ifdef MAC |
|---|
| 1872 | argc = ccommand(&argv); |
|---|
| 1873 | #endif |
|---|
| 1874 | |
|---|
| 1875 | t = (time_t)mcstartdate; |
|---|
| 1876 | time(&t); |
|---|
| 1877 | mcstartdate = t; |
|---|
| 1878 | mcformat=mcuse_format(getenv("MCSTAS_FORMAT") ? getenv("MCSTAS_FORMAT") : MCSTAS_FORMAT); |
|---|
| 1879 | /* default is to output as McStas format */ |
|---|
| 1880 | mcformat_data.Name=NULL; |
|---|
| 1881 | |
|---|
| 1882 | /* parse parameters from the command line and get files to convert */ |
|---|
| 1883 | mcformat_parseoptions(argc, argv); |
|---|
| 1884 | |
|---|
| 1885 | if (!files_to_convert_NB) { mcformat_usage(argv[0]); exit(-1); } |
|---|
| 1886 | if (!mcformat_data.Name && !strcmp(mcformat.Name, "HTML")) |
|---|
| 1887 | mcformat_data = mcuse_format("VRML"); |
|---|
| 1888 | |
|---|
| 1889 | mcnbconvert = mcdircount = 0; |
|---|
| 1890 | mcoutputdir = mcdirname; /* base output dir */ |
|---|
| 1891 | |
|---|
| 1892 | if (mcscanmode && mcverbose && !strstr(mcformat.Name, "McStas")) |
|---|
| 1893 | printf("Warning: Scan gathering mode is only compatible when using --format=McStas\n"); |
|---|
| 1894 | |
|---|
| 1895 | /* count the number of files to store */ |
|---|
| 1896 | for(j = 0; j < files_to_convert_NB; j++) { |
|---|
| 1897 | int i; |
|---|
| 1898 | i = files_to_convert_Array[j]; /* does the job for each file/dir */ |
|---|
| 1899 | mcnbconvert += mcformat_count(argv[i]); |
|---|
| 1900 | } |
|---|
| 1901 | if (mcdircount) { /* allocate list of directories amd FILE handles */ |
|---|
| 1902 | mcdirnames = (char**)mem(mcdircount*sizeof(char*)); |
|---|
| 1903 | mcsimfiles = (FILE**)mem(mcdircount*sizeof(FILE*)); |
|---|
| 1904 | mcinstrnames= (char**)mem(mcdircount*sizeof(char*)); |
|---|
| 1905 | mcsources = (char**)mem(mcdircount*sizeof(char*)); |
|---|
| 1906 | } |
|---|
| 1907 | if (mcmergemode || mcscanmode) { |
|---|
| 1908 | printf("mcformat: Will process and merge/scan %d data file%s in %d director%s.\n", |
|---|
| 1909 | mcnbconvert, mcnbconvert > 1 ? "s" : "", mcdircount, mcdircount > 1 ? "ies" : "y"); |
|---|
| 1910 | /* allocate array of Original file structures */ |
|---|
| 1911 | Files_to_Merge = mem(mcnbconvert*sizeof(struct McStas_file_format)); |
|---|
| 1912 | Scans_to_merge = mem(mcnbconvert*sizeof(int)); |
|---|
| 1913 | for (j=0; j<mcnbconvert; j++) { |
|---|
| 1914 | Files_to_Merge[j] = mcformat_init_mcstas_struct(); |
|---|
| 1915 | Scans_to_merge[j] = -1; |
|---|
| 1916 | } |
|---|
| 1917 | |
|---|
| 1918 | } |
|---|
| 1919 | mcnbconvert = mcdircount = 0; |
|---|
| 1920 | |
|---|
| 1921 | strcpy(mcinstrument_source, ""); |
|---|
| 1922 | strcpy(mcinstrument_name , ""); |
|---|
| 1923 | |
|---|
| 1924 | /* calls the conversion routine. SIM file opened at first conversion in mcformat_convert */ |
|---|
| 1925 | for(j = 0; j < files_to_convert_NB; j++) { |
|---|
| 1926 | int i; |
|---|
| 1927 | i = files_to_convert_Array[j]; /* does the job for each file/dir */ |
|---|
| 1928 | mcformat_convert(argv[i]); |
|---|
| 1929 | } |
|---|
| 1930 | |
|---|
| 1931 | if (mcmergemode || mcscanmode) { |
|---|
| 1932 | /* call to merging routine (free some Files_to_Merge elements) */ |
|---|
| 1933 | mcformat_merge_compare(mcnbconvert); |
|---|
| 1934 | /* iterative call to output routine for remaining elements of Files_to_Merge */ |
|---|
| 1935 | mcformat_merge_output(mcnbconvert); |
|---|
| 1936 | if (Files_to_Merge) memfree(Files_to_Merge); |
|---|
| 1937 | if (Scans_to_merge) memfree(Scans_to_merge); |
|---|
| 1938 | } |
|---|
| 1939 | |
|---|
| 1940 | /* clean up: close all SIM files */ |
|---|
| 1941 | if (!mctestmode) { |
|---|
| 1942 | if (!mcdircount) mcsiminfo_close(); |
|---|
| 1943 | else { |
|---|
| 1944 | for (j=0; j<mcdircount; j++) { |
|---|
| 1945 | if (mcsimfiles[j]) { |
|---|
| 1946 | mcdirname = mcdirnames[j]; |
|---|
| 1947 | mcsiminfo_file = mcsimfiles[j]; |
|---|
| 1948 | strncpy(mcinstrument_source, str_last_word(mcinstrnames[j]), CHAR_BUF_LENGTH); |
|---|
| 1949 | strncpy(mcinstrument_name , str_last_word(mcsources[j]), CHAR_BUF_LENGTH); |
|---|
| 1950 | mcsiminfo_close(); |
|---|
| 1951 | mcsimfiles[j] = NULL; |
|---|
| 1952 | memfree(mcinstrnames[j]); |
|---|
| 1953 | memfree(mcsources[j]); |
|---|
| 1954 | memfree(mcdirnames[j]); |
|---|
| 1955 | } |
|---|
| 1956 | } |
|---|
| 1957 | memfree(mcdirnames); |
|---|
| 1958 | memfree(mcsimfiles); |
|---|
| 1959 | memfree(mcinstrnames); |
|---|
| 1960 | memfree(mcsources); |
|---|
| 1961 | } |
|---|
| 1962 | } |
|---|
| 1963 | |
|---|
| 1964 | mcclear_format(mcformat); |
|---|
| 1965 | if (mcformat_data.Name) mcclear_format(mcformat_data); |
|---|
| 1966 | |
|---|
| 1967 | return mcnbconvert; /* number of converted files */ |
|---|
| 1968 | |
|---|
| 1969 | } /* main */ |
|---|
| 1970 | |
|---|
| 1971 | |
|---|