/******************************************************************************* * * McStas, neutron ray-tracing package * Copyright (C) 1997-2009, All rights reserved * Risoe National Laboratory, Roskilde, Denmark * Institut Laue Langevin, Grenoble, France * * Instrument: mcformat, McStas format converter * * %Identification * Written by: Emmanuel Farhi * Date: 1st Feb 2001. * Origin: ILL (France) * Release: McXtrace 1.2 - Jul. 02, 2015 * Version: $Revision$ * * A McCode format converter to merge/convert data files. * * %Description * * A McCode format converter to merge/convert data files. * Parameters are the files/directories to process, and option flags. * May be used to: * 1- continue an interupted simulation, and then add (--merge option) the similar * data files. * 2- convert original simple text format into NeXus format (--format=NeXus) * 3- catenate list files * 4- reconstruct parameter scan sumulations (--scan) * * %Parameters * INPUT PARAMETERS: * files [string]: list of files/directories to convert, separated by spaces * * %Link * * %End *******************************************************************************/ #ifndef MCFORMAT #define MCFORMAT "$Revision$" /* avoid memory.c to define Pool functions */ #endif #ifdef USE_MPI #undef USE_MPI #endif /* Instead of including mccode.h file, which would then require to link most of the functions of the mcstas executable, we just put there some parts of the mccode.h file. Build: cc -o mcformat mcformat.c -lm */ #define fatal_error printf /* remove debug.c dependency */ #define debug(msg) #define MCCODE_H /* avoids memory.c to import mccode.h */ typedef struct Pool_header *Pool; /* allows memory to be included */ #include "memory.c" #include "../lib/share/mccode-r.h" /* with decl of MC_PATHSEP */ #include "../lib/share/mccode-r.c" /* end of parts copied from mccode.h */ #include "../lib/share/read_table-lib.h" /* independent library */ #include "../lib/share/read_table-lib.c" #include #include /* Functions defined in memory.c */ void *mem(size_t); /* Allocate memory. */ void memfree(void *); /* Free memory. */ char *str_dup(char *); /* Allocate new copy of string. */ char *str_dup_n(char *string, int n); /* Copies only first N chars. */ char *str_cat(char *first, ...);/* Concatenate strings to allocated string. */ char *str_quote(char *string); /* Quote string for inclusion in C code */ void str_free(char *); /* Free memory for string. */ /* default global variables required by mccode-r (usually generated in cogen) */ int mcdefaultmain = 1; int mctraceenabled = 0; char mcinstrument_name[CHAR_BUF_LENGTH]; char mcinstrument_source[CHAR_BUF_LENGTH]; char *mcinstrument_exe = NULL; int mcnumipar = 0; struct mcinputtable_struct mcinputtable[CHAR_BUF_LENGTH]; mcstatic FILE *mcsiminfo_file = NULL; /* default global variables for mcformat converter */ int files_to_convert_NB = 0; /* nb of files to convert */ int files_to_convert_Array[CHAR_BUF_LENGTH]; /* index of argv[] for these files */ char mcforcemode =0; char mcverbose =0; char mcmergemode =0; char mcscanmode =0; char mcmergesamedir=0; int mcdircount =0; /* number of directories scanned */ int mcnbconvert =0; /* index of current file */ FILE **mcsimfiles; char **mcdirnames; char **mcinstrnames; char **mcsources; char *mcoutputdir=NULL; int ipar_var =0; /* column index of scan variable (used in mcformat_scan_compare) */ struct fileparts_struct { char *FullName; char *Path; char *Name; char *Extension; }; /* list of functions ******************************************************** */ /* char *str_dup_numeric(char *orig) char *str_dup_name(char *orig, int length) char *str_dup_label(char *orig) char *str_last_word(char *orig) struct fileparts_struct fileparts_init(void) struct fileparts_struct fileparts(char *name) void fileparts_free(struct fileparts_struct parts) struct McStas_file_format mcformat_init_mcstas_struct(void) void mcformat_print_mcstas_struct(struct McStas_file_format McStasStruct) struct McStas_file_format mcformat_free_mcstas_struct(struct McStas_file_format McStasStruct) struct McStas_file_format mcformat_read_mcstas(char *filename) int mcformat_dirwalk(char *dir, int (*fcn)(char *)) static void mcformat_usedir(char *dir) int mcformat_output(struct McStas_file_format McStasStruct) int mcformat_convert(char *name) int mcformat_count(char *name) int mcformat_merge_compare(int nb) void mcformat_scan_compare(int nb) int mcformat_merge_output(int nb) void mcformat_usage(char *pgmname) void mcformat_parseoptions(int argc, char *argv[]) int main(int argc, char *argv[]) */ /******************************************************************************* * str_dup_numeric: makes a clean copy of a string and allocate as numeric *******************************************************************************/ char *str_dup_numeric(char *orig) { long i; char *valid; if (!orig || !strlen(orig)) return(NULL); for (i=0; i < strlen(orig); i++) { if ( (orig[i] > 122) || (orig[i] < 32) || (strchr("!\"#$%&'()*,:;<=>?@[\\]^`/ ", orig[i]) != NULL) ) { orig[i] = ' '; } } orig[i] = '\0'; /* now skip spaces */ for (i=0; i < strlen(orig); i++) { if (*orig == ' ') orig++; else break; } valid=str_dup(orig); return(valid); } /* str_dup_numeric */ /******************************************************************************* * str_dup_name: makes a clean copy of a string and allocate as name *******************************************************************************/ char *str_dup_name(char *orig, int length) { char *valid; if (!orig || !strlen(orig)) return(NULL); valid=str_dup_n(orig, length > 0 ? length : strlen(orig)); strcpy_valid(valid, orig); return(valid); } /* str_dup_name */ /******************************************************************************* * str_dup_label: makes a clean copy of a string and allocate as label/title *******************************************************************************/ char *str_dup_label(char *orig) { long i; char *valid; int length=0; if (!orig || !strlen(orig)) return(NULL); for (i=0; i < strlen(orig); i++) { if ( (orig[i] > 122) || (orig[i] < 32) || (strchr("\"'=:;", orig[i]) != NULL) ) { orig[i] = ' '; } } orig[i] = '\0'; /* now skip spaces at begining */ for (i=0; i < strlen(orig); i++) { if (*orig == ' ') orig++; else break; } length = strlen(orig); /* skip trailing blanks */ for (i=strlen(orig)-1; i > 0; i--) { if (orig[i] == ' ') length--; else break; } valid=str_dup_n(orig, length); return(valid); } /* str_dup_label */ /******************************************************************************* * str_last_word: points to last word of string *******************************************************************************/ char *str_last_word(char *orig) { char *pos_end =NULL; char *pos_begin=NULL; char separators[]= MC_PATHSEP_S " !\"#$%&'()*,:;<=>?@[\\]^`/."; /* first skip trailing separators */ pos_end = orig+strlen(orig); while (pos_end > orig) { if (strchr(separators, *pos_end)) pos_end--; /* pass separators at the end */ else break; } pos_begin = pos_end-1; /* search for non separators (pass word) */ while (pos_begin >= orig) { if (!strchr(separators, *pos_begin)) pos_begin--; /* pass non separators */ else break; } pos_begin++; if (pos_begin < orig) pos_begin=orig; return(pos_begin); } /* str_last_word */ /******************************************************************************* * fileparts_init: Initialize a zero fileparts structure *******************************************************************************/ struct fileparts_struct fileparts_init(void) { struct fileparts_struct parts; parts.FullName = NULL; parts.Path = NULL; parts.Name = NULL; parts.Extension = NULL; return(parts); } /* fileparts_init */ /******************************************************************************* * fileparts: Split a fully qualified file name/path into pieces * Returns a zero structure if called with NULL argument. * Returns: fields are non NULL if they exist * Path is NULL if no Path * Name is NULL if just a Path * Extension is "" if just a dot *******************************************************************************/ struct fileparts_struct fileparts(char *name) { struct fileparts_struct parts; parts = fileparts_init(); if (name) { char *dot_pos = NULL; char *path_pos = NULL; char *end_pos = NULL; char *name_pos = NULL; long dot_length = 0; long path_length= 0; long name_length= 0; parts.FullName = str_dup(name); /* extract path+filename+extension from full filename */ if (strlen(name) == 0) return(parts); end_pos = name+strlen(name); /* end of file name */ /* extract path: searches for last file separator */ path_pos= strrchr(name, MC_PATHSEP_C); /* last PATHSEP */ if (!path_pos) { path_pos =name; path_length=0; name_pos =name; parts.Path = str_dup(""); } else { name_pos = path_pos+1; path_length = name_pos - name; /* from start to path+sep */ if (path_length) { parts.Path = str_cat(name, MC_PATHSEP_S, NULL); strncpy(parts.Path, name, path_length); parts.Path[path_length]='\0'; } else parts.Path = str_dup(""); } /* extract ext: now looks for the 'dot' */ dot_pos = strrchr(name_pos, '.'); /* last dot */ if (dot_pos > name_pos) { dot_length = end_pos - dot_pos; if (dot_length > 0) { parts.Extension = str_dup(name); strncpy(parts.Extension, dot_pos+1, dot_length); /* skip the dot */ parts.Extension[dot_length]='\0'; } } else dot_pos = end_pos; /* extract Name (without extension) */ name_length = dot_pos - name_pos; /* from path to dot */ if (name_length) { parts.Name = str_dup(name); strncpy(parts.Name, name_pos, name_length); parts.Name[name_length]='\0'; } } /* if (name) */ return (parts); } /* fileparts */ /******************************************************************************* * fileparts_free: Free a fileparts_struct fields *******************************************************************************/ void fileparts_free(struct fileparts_struct parts) { str_free(parts.FullName); str_free(parts.Path); str_free(parts.Name); str_free(parts.Extension); } /* fileparts_free */ struct McStas_file_format { char *Source; char *Creator; char *Editor; char *InstrName; char *filename; char *Format; char *Date; char *EndDate; double Ncount; char *component; char *type; char *title; char *xlabel; char *ylabel; char *zlabel; char *xvar; char *yvar; char *zvar; char *xylimits; char *position; char *gravitation; char *outputname; char *Ncount_str; t_Table *Data; long m, n, p; double x1, x2, y1, y2, z1, z2; char *ratio; double RunNum; double *p0, *p1, *p2; double Nsum, Psum, P2sum; Coords POSITION; int mcnumipar; struct mcinputtable_struct *mcinputtable; char *mcdirname; double Scan_ipar_value; int Scan_ipar_index; double Scan_mon_distance; int Scan_mon_index; }; /* McStas_file_format */ struct McStas_file_format *Files_to_Merge=NULL; int *Scans_to_merge=NULL; /******************************************************************************* * mcformat_init_mcstas_struct: Init an empty McStas data structure *******************************************************************************/ struct McStas_file_format mcformat_init_mcstas_struct(void) { struct McStas_file_format McStasStruct; McStasStruct.Format = NULL; McStasStruct.Creator = NULL; McStasStruct.Editor = NULL; McStasStruct.Date = NULL; McStasStruct.EndDate = NULL; McStasStruct.Ncount = 0; McStasStruct.type = NULL; McStasStruct.Source = NULL; McStasStruct.InstrName = NULL; McStasStruct.component = NULL; McStasStruct.title = NULL; McStasStruct.ratio = NULL; McStasStruct.filename = NULL; McStasStruct.xvar = NULL; McStasStruct.yvar = NULL; McStasStruct.xlabel = NULL; McStasStruct.ylabel = NULL; McStasStruct.zvar = NULL; McStasStruct.zlabel = NULL; McStasStruct.xylimits = NULL; McStasStruct.position = NULL; McStasStruct.outputname = NULL; McStasStruct.Ncount_str = NULL; McStasStruct.Data = NULL; McStasStruct.p0 = NULL; McStasStruct.p1 = NULL; McStasStruct.p2 = NULL; McStasStruct.Nsum = 0; McStasStruct.Psum = 0; McStasStruct.P2sum = 0; McStasStruct.POSITION.x=McStasStruct.POSITION.y=McStasStruct.POSITION.z=0; McStasStruct.RunNum = 0; McStasStruct.m = 0; McStasStruct.n = 0; McStasStruct.p = 0; McStasStruct.x1 = 0; McStasStruct.x2 = 0; McStasStruct.y1 = 0; McStasStruct.y2 = 0; McStasStruct.z1 = 0; McStasStruct.z2 = 0; McStasStruct.gravitation= NULL; McStasStruct.mcnumipar =0; McStasStruct.mcinputtable =NULL; McStasStruct.mcdirname =NULL; McStasStruct.Scan_ipar_value =0; McStasStruct.Scan_ipar_index =0; McStasStruct.Scan_mon_distance=0; McStasStruct.Scan_mon_index =0; return(McStasStruct); } /* mcformat_init_mcstas_struct */ void mcformat_print_mcstas_struct(struct McStas_file_format McStasStruct) { printf("Structure from file %s\n", McStasStruct.filename); printf(" Format = %s\n", McStasStruct.Format ); printf(" Creator = %s\n", McStasStruct.Creator ); printf(" Editor = %s\n", McStasStruct.Editor ); printf(" Date = %s\n", McStasStruct.Date ); printf(" EndDate = %s\n", McStasStruct.EndDate ); printf(" type = %s\n", McStasStruct.type ); printf(" Source = %s\n", McStasStruct.Source ); printf(" InstrName = %s\n", McStasStruct.InstrName ); printf(" component = %s\n", McStasStruct.component ); printf(" title = %s\n", McStasStruct.title ); printf(" ratio = %s\n", McStasStruct.ratio ); printf(" xvar = %s\n", McStasStruct.xvar ); printf(" yvar = %s\n", McStasStruct.yvar ); printf(" xlabel = %s\n", McStasStruct.xlabel ); printf(" ylabel = %s\n", McStasStruct.ylabel ); printf(" zvar = %s\n", McStasStruct.zvar ); printf(" zlabel = %s\n", McStasStruct.zlabel ); printf(" xylimits = %s\n", McStasStruct.xylimits ); printf(" position = %s\n", McStasStruct.position ); printf(" outputname = %s\n", McStasStruct.outputname ); printf(" Ncount_str = %s\n", McStasStruct.Ncount_str ); printf(" mcdirname = %s\n", McStasStruct.mcdirname ); printf(" gravitation= %s\n", McStasStruct.gravitation ); printf(" Ncount = %g\n", McStasStruct.Ncount); printf(" RunNum = %g\n", McStasStruct.RunNum); printf(" x1 = %g\n", McStasStruct.x1); printf(" x2 = %g\n", McStasStruct.x2); printf(" y1 = %g\n", McStasStruct.y1); printf(" y2 = %g\n", McStasStruct.y2); printf(" z1 = %g\n", McStasStruct.z1); printf(" z2 = %g\n", McStasStruct.z2); printf(" Data = %s\n", McStasStruct.Data ? "OK" : "NULL"); printf(" m = %ld\n", McStasStruct.m); printf(" n = %ld\n", McStasStruct.n); printf(" p = %ld\n", McStasStruct.p); printf(" p0 = %s\n", McStasStruct.p0 ? "OK": "NULL"); printf(" p1 = %s\n", McStasStruct.p1 ? "OK": "NULL"); printf(" p2 = %s\n", McStasStruct.p2 ? "OK": "NULL"); printf(" POSITION = %g %g %g\n", McStasStruct.POSITION.x, McStasStruct.POSITION.y, McStasStruct.POSITION.z); printf(" mcnumipar = %d\n", McStasStruct.mcnumipar); printf(" inputtable = %s\n", McStasStruct.mcinputtable ? "OK": "NULL"); } /******************************************************************************* * mcformat_free_mcstas_struct: Free a McStas data structure *******************************************************************************/ struct McStas_file_format mcformat_free_mcstas_struct(struct McStas_file_format McStasStruct) { memfree(McStasStruct.Format ); memfree(McStasStruct.Date ); memfree(McStasStruct.EndDate ); memfree(McStasStruct.Creator ); memfree(McStasStruct.Editor ); memfree(McStasStruct.type ); memfree(McStasStruct.Source ); memfree(McStasStruct.InstrName); memfree(McStasStruct.component); memfree(McStasStruct.gravitation); memfree(McStasStruct.title ); memfree(McStasStruct.ratio ); memfree(McStasStruct.filename ); memfree(McStasStruct.xvar ); memfree(McStasStruct.yvar ); memfree(McStasStruct.xlabel ); memfree(McStasStruct.ylabel ); memfree(McStasStruct.zvar ); memfree(McStasStruct.zlabel ); memfree(McStasStruct.xylimits ); memfree(McStasStruct.position ); memfree(McStasStruct.outputname ); memfree(McStasStruct.Ncount_str ); if (McStasStruct.Data) Table_Free_Array(McStasStruct.Data); if (McStasStruct.p0) memfree(McStasStruct.p0 ); if (McStasStruct.p1) memfree(McStasStruct.p1 ); if (McStasStruct.p2) memfree(McStasStruct.p2 ); memfree(McStasStruct.mcdirname ); /* free mcinputtable */ int i; for (i=0; i RunNum */ if (parsing[17]) McStasStruct.xlabel = str_dup_label(parsing[17]); if (parsing[18]) McStasStruct.ylabel = str_dup_label(parsing[18]); if (parsing[19]) McStasStruct.zlabel = str_dup_label(parsing[19]); if (parsing[20]) McStasStruct.xvar = str_dup_label(parsing[20]); if (parsing[21]) McStasStruct.yvar = str_dup_label(parsing[21]); if (parsing[22]) McStasStruct.zvar = str_dup_label(parsing[22]); if (parsing[23]) McStasStruct.xylimits = str_dup_numeric(parsing[23]); /* x/y min/max */ if (parsing[24] && !McStasStruct.xylimits) McStasStruct.xylimits = str_dup_numeric(parsing[24]); for (i=0; i<=24; i++) { if (parsing[i]) free(parsing[i]); } free(parsing); } /* will be determined over original values when writting new data file: filename format statistics signal values */ if (!McStasStruct.InstrName && !McStasStruct.Source) McStasStruct.Source = str_dup("McStas_Instrument"); else if (!McStasStruct.InstrName && McStasStruct.Source) { char *ext=NULL; /* if not found, use instr file name without extension */ ext = strstr(McStasStruct.Source, ".ins"); if (!ext) ext = strstr(McStasStruct.Source, " ins"); if (ext) McStasStruct.InstrName = str_dup_n(McStasStruct.Source, (ext-McStasStruct.Source)); else McStasStruct.InstrName = str_dup(McStasStruct.Source); } else if (McStasStruct.InstrName && !McStasStruct.Source) { char *ext=NULL; /* if not found, use instr name without extension */ ext = strstr(McStasStruct.InstrName, ".ins"); if (!ext) ext = strstr(McStasStruct.InstrName, " ins"); if (ext) McStasStruct.Source = str_dup_n(McStasStruct.InstrName, (ext-McStasStruct.InstrName)); else McStasStruct.Source = str_dup(McStasStruct.InstrName); } if (McStasStruct.Ncount_str) McStasStruct.Ncount=atof(McStasStruct.Ncount_str); /* header analysis: general keywords */ if (McStasStruct.ratio) { /* extracts RunNum and Ncount values separated by '/' */ double runnum=0, ncount=0; int i; i = sscanf(McStasStruct.ratio, "%lg %lg", &runnum, &ncount); if (i) McStasStruct.RunNum = runnum; if (i>1) { if (!McStasStruct.Ncount && ncount) McStasStruct.Ncount = ncount; else if (ncount && McStasStruct.Ncount != ncount) fprintf(stderr, "Warning: %s: conflicting Ncount %f value with 'ratio' one %f\n", filename, McStasStruct.Ncount, ncount); } else if (!McStasStruct.Ncount) /* no Ncount and ratio is a single value: Ncount == runnum */ McStasStruct.Ncount = McStasStruct.RunNum; } if (!McStasStruct.Ncount) { McStasStruct.Ncount = 1e6; fprintf(stderr, "Warning: %s: can not extract Ncount. using default (%g)\n", filename, McStasStruct.Ncount); } if (!McStasStruct.RunNum) McStasStruct.RunNum = McStasStruct.Ncount; if (McStasStruct.RunNum < McStasStruct.Ncount*0.99) fprintf(stderr, "Warning: %s: Temporary results with ratio %g/%g. Simulation results are not completed.\n", filename, McStasStruct.RunNum, McStasStruct.Ncount); /* analyse type, and check that Data dims are m,n,p */ if (McStasStruct.type) { if (!strcmp(McStasStruct.type, "array_0d")) m=n=p=1; else if (sscanf(McStasStruct.type, "array_1d(%d)",&m) == 1) n=p=1; else if (sscanf(McStasStruct.type, "array_2d(%d, %d)",&n,&m) == 2) p=1; else if (sscanf(McStasStruct.type, "array_3d(%d, %d, %d)",&n,&m,&p) == 3) { /* void */ } else if (sscanf(McStasStruct.type, "multiarray_1d(%d)", &m)) { if (!mcscanmode) fprintf(stderr, "Warning: %s: use --scan flag for multiarray/scans (skipped)\n", filename); return(McStasStruct); } } else { fprintf(stderr, "Warning: %s: invalid data type '%s' (not 1d/2d/3d/multiarray)\n", filename, McStasStruct.type); return(McStasStruct); } /* Scans: just test existence. If yes, then will skip the SIM file */ /* "# Numpoints: " "# xvars: " "# yvars: " */ /* check if data block is transposed */ if (m != rTable[0].rows && n != rTable[0].columns && m == rTable[0].columns && n == rTable[0].rows) { if (mcverbose) fprintf(stderr, "Warning: %s: Data block is transposed. Fixing.\n", filename); int tmp=m; m=n; n=tmp; } if (m != rTable[0].rows) { fprintf(stderr, "Warning: %s: conflicting Data row numbers\n" " expected=%d found=%ld. Fixing. Check first line of Data block.\n", filename, m, rTable[0].rows); m = rTable[0].rows; } if (McStasStruct.Format && (strstr(McStasStruct.Format, "binary") || strstr(McStasStruct.Format, "float") || strstr(McStasStruct.Format, "double"))) fprintf(stderr, "WARNING: %s: Format of data file indicates binary blocks." " Not supported. Might crash.\n", filename); if (McStasStruct.Format && McStasStruct.type && strstr(McStasStruct.Format, "PGPLOT") && array_length == 1 && strstr(McStasStruct.type, "array_1d") && rTable[0].columns == 4) flag_pgplot1d=1; if (flag_pgplot1d) n = 4; if (n != rTable[0].columns) { fprintf(stderr, "Warning: %s: conflicting Data column numbers\n" " expected=%d found=%ld. Fixing. Check first line of Data block.\n", filename, n, rTable[0].columns); n = rTable[0].columns; } if (flag_pgplot1d) n = 1; McStasStruct.m = rTable[0].rows; /* dimensions from the Table */ McStasStruct.n = flag_pgplot1d ? 1 : rTable[0].columns; McStasStruct.p = p; /* extracted from type */ m = McStasStruct.m; n = McStasStruct.n; /* extract limits values */ McStasStruct.x1=1; McStasStruct.x2=McStasStruct.m; McStasStruct.y1=1; McStasStruct.y2=McStasStruct.n; McStasStruct.z1=1; McStasStruct.z2=McStasStruct.p; if (McStasStruct.xylimits) { i = sscanf(McStasStruct.xylimits, "%lg %lg %lg %lg %lg %lg", &(McStasStruct.x1), &(McStasStruct.x2), &(McStasStruct.y1), &(McStasStruct.y2), &(McStasStruct.z1), &(McStasStruct.z2)); if (i != 2 && i != 4 && i != 6) fprintf(stderr, "Warning: %s: invalid xylimits '%s'. extracted %i values\n", filename, McStasStruct.xylimits, i); } /* special case of 2D binary files: axes must be exchanged */ if (strstr(mcformat, "binary") || strstr(mcformat, "float") || strstr(mcformat, "double")) if (p == 1 && m>1 && n>1) { double tmp; char* c; tmp=McStasStruct.x1; McStasStruct.x1=McStasStruct.y1; McStasStruct.y1=tmp; tmp=McStasStruct.x2; McStasStruct.x2=McStasStruct.y2; McStasStruct.y2=tmp; c=McStasStruct.xlabel; McStasStruct.xlabel=McStasStruct.ylabel; McStasStruct.ylabel=c; c=McStasStruct.xvar; McStasStruct.xvar=McStasStruct.yvar; McStasStruct.yvar=c; } McStasStruct.filename = str_dup(filename); if (!McStasStruct.component) McStasStruct.component=str_dup(filename); struct fileparts_struct file_parts=fileparts(filename); char *tmp=str_cat(file_parts.Name, ".", file_parts.Extension, NULL); McStasStruct.outputname = str_dup_name(tmp, 0); memfree(tmp); fileparts_free(file_parts); McStasStruct.mcdirname = str_dup(mcdirname); if (McStasStruct.position) sscanf(McStasStruct.position, "%lg %lg %lg", &McStasStruct.POSITION.x,&McStasStruct.POSITION.y,&McStasStruct.POSITION.z); /* header analysis: get instrument parameters and fills numipar and inputtable */ char *s = rTable[0].header; char *tok=s; char *equal_sign=NULL; char *name_start=NULL; mcnumipar = 0; while (tok) { /* extract parameter=value as clean names */ tok = strstr(s, "Parameters"); if (!tok) tok = strstr(s, "parameters"); if (!tok) tok = strstr(s, "Param"); if (!tok) tok = strstr(s, "param"); if (!tok) break; parsing = Table_ParseHeader(tok, "Parameters", NULL); /* get line */ if (!parsing[0]) parsing = Table_ParseHeader(tok, "parameters", NULL); /* get line */ if (!parsing[0]) parsing = Table_ParseHeader(tok, "Param", NULL); /* get line */ if (!parsing[0]) parsing = Table_ParseHeader(tok, "param", NULL); /* get line */ name_start = (parsing[0] ? str_dup(parsing[0]) : NULL); memfree(parsing[0]); free(parsing); if (!name_start) break; equal_sign = strchr(name_start+1, '='); if (equal_sign > name_start && strlen(name_start)) { char *name_to_equal=str_dup_n(name_start, equal_sign-name_start); char *name=str_last_word(name_to_equal); char *value = str_dup(equal_sign+1); if (name && value && strlen(name) && strlen(value)) { char *name_label = str_dup_label(name); /*printf("name_to_equal='%s' name='%s' value='%s'\n", name_to_equal, name, value); */ mcinputtable[mcnumipar].name = name_label; mcinputtable[mcnumipar].type = instr_type_string; mcinputtable[mcnumipar].val = value; mcinputtable[mcnumipar].par = NULL; mcnumipar++; } memfree(name_to_equal); } memfree(name_start); s = tok+strlen("Param"); } /* end while tok */ /* now transfer mcinputtable into McStasStruct */ McStasStruct.mcnumipar = mcnumipar; McStasStruct.mcinputtable = (struct mcinputtable_struct *)mem(mcnumipar*sizeof(struct mcinputtable_struct)); for (i=0; ip2 array (see mcestimate_error) */ if (McStasStruct.p0 && McStasStruct.p1 && McStasStruct.p2) { double *p0 = McStasStruct.p0; double *p1 = McStasStruct.p1; double *p2 = McStasStruct.p2; for (i=0; i < m*n*p; i++) { if (p2[i] > 0) p2[i] = (p0[i] > 1 ? ((p0[i]-1)*p2[i]*p2[i] + p1[i]*p1[i]/p0[i])/p0[i] : p1[i]); } } McStasStruct.m *= -1; /* always transposed in files w/r to memory */ /* free McStasStruct.Data for better memory management */ Table_Free_Array(McStasStruct.Data); McStasStruct.Data=NULL; return(McStasStruct); } /* end mcformat_read_mcstas */ /******************************************************************************* * mcformat_dirwalk: apply fcn to all files in dir (see K & R 'C language') * returns number of processed files *******************************************************************************/ int mcformat_dirwalk(char *dir, int (*fcn)(char *)) { char name[CHAR_BUF_LENGTH]; int ret=0; struct dirent *dp; DIR *dfd; if ((dfd = opendir(dir)) == NULL) { fprintf(stderr, "mcformat: can't open %s\n", dir); return 0; } while ((dp = readdir(dfd)) != NULL) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; /* skip self and parent */ if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name)) fprintf(stderr, "mcformat: name %s%c%s too long\n", dir, MC_PATHSEP_C, dp->d_name); else { sprintf(name, "%s%c%s", dir, MC_PATHSEP_C, dp->d_name); ret += (*fcn)(name); } } closedir(dfd); return(ret); } /* end mcformat_dirwalk */ /******************************************************************************* * mcformat_usedir: set directory to use. Same as mcuse_dir with force option. *******************************************************************************/ static void mcformat_usedir(char *dir) { #ifdef MC_PORTABLE fprintf(stderr, "Error: " "Directory output cannot be used with portable simulation (mcformat_usedir)\n"); return; #else /* !MC_PORTABLE */ #ifndef WIN32 if(!mcdisable_output_files && mkdir(dir, 0777)) #else if(!mcdisable_output_files && mkdir(dir)) #endif { int errno_mkdir = errno; if (errno_mkdir == ENOENT) { if (mcverbose) fprintf(stderr, "mkdir: ENOENT A directory component in pathname '%s' does not exist or is a dangling symbolic link.\n", dir); /* we build the required elements in the path */ struct fileparts_struct dir_parts = fileparts(dir); if (strlen(dir_parts.Path)) { char *path_pos= strrchr(dir_parts.Path, MC_PATHSEP_C); /* last PATHSEP */ if (path_pos == dir_parts.Path+strlen(dir_parts.Path)-1) dir_parts.Path[strlen(dir_parts.Path)-1] = '\0'; if (mcverbose) fprintf(stderr, "mcformat: Warning: building output directory '%s' from '%s'.\n", dir_parts.Path, dir); mcformat_usedir(dir_parts.Path); fileparts_free(dir_parts); mcformat_usedir(dir); } } else if (errno_mkdir == EEXIST) { fprintf(stderr, "mkdir: EEXIST pathname %s already exists (not necessarily as a directory).\n", dir); if (!mcforcemode && mcscanmode != 2) { fprintf(stderr, "Error: unable to create directory '%s' (mcformat_usedir)\n", dir); fprintf(stderr, "(Maybe the directory already exists? Use --force, --scan-only or --test before -d %s to override)\n", dir); exit(1); } fprintf(stderr, "mcformat: Warning: re-using output directory '%s'.\n", dir); } else { switch (errno_mkdir) { #ifdef EACCES case EACCES: fprintf(stderr, "mkdir: EACCES The parent directory does not allow write permission\n" " or one of the directories in pathname did not allow search permission.\n"); break; #endif #ifdef EFAULT case EFAULT: fprintf(stderr, "mkdir: EFAULT pathname points outside your accessible address space.\n"); break; #endif #ifdef ELOOP case ELOOP: fprintf(stderr, "mkdir: ELOOP Too many symbolic links were encountered in resolving pathname.\n"); break; #endif #ifdef ENAMETOOLONG case ENAMETOOLONG: fprintf(stderr, "mkdir: ENAMETOOLONG pathname was too long.\n"); break; #endif #ifdef ENOMEM case ENOMEM: fprintf(stderr, "mkdir: ENOMEM Insufficient kernel memory was available.\n"); break; #endif #ifdef ENOSPC case ENOSPC: fprintf(stderr, "mkdir: ENOSPC The device containing pathname has no room for the new directory.\n"); break; #endif #ifdef ENOTDIR case ENOTDIR: fprintf(stderr, "mkdir: ENOTDIR A component used as a directory in pathname is not, in fact, a directory.\n"); break; #endif #ifdef EPERM case EPERM: fprintf(stderr, "mkdir: EPERM The filesystem containing pathname does not support the creation of directories.\n"); break; #endif #ifdef EROFS case EROFS: fprintf(stderr, "mkdir: EROFS pathname refers to a file on a read-only filesystem.\n"); break; #endif default: fprintf(stderr, "mkdir: ERROR %i using mkdir.\n", errno_mkdir); break; } fprintf(stderr, "mcformat: Fatal error accessing %s. Aborting.\n", dir); exit(-1); } } if (mcverbose) printf("mcformat: Creating directory %s.\n", dir); mcdirname = dir; #endif /* !MC_PORTABLE */ } /* mcformat_usedir */ /******************************************************************************* * mcformat_output: write monitor file and optionally free memory *******************************************************************************/ int mcformat_output(struct McStas_file_format McStasStruct) { char *currentdir= mcdirname; /* save current dir */ int i; if (mcdisable_output_files) return(1); if (!McStasStruct.p1) return(0); /* empty data */ /* determine in which directory we are and set SIM file */ if (!mcdircount) { if (!strlen(mcinstrument_name)) strcpy(mcinstrument_name, McStasStruct.InstrName); if (!strlen(mcinstrument_source)) strcpy(mcinstrument_source, McStasStruct.Source); if (!mcsiminfo_file) mcsiminfo_init(NULL); /* open SIM file once */ } else { if (!mcmergemode) i=mcdircount-1; else { for (i=0; i= mcdircount) { fprintf(stderr, "ERROR: unable to find directory '%s' in scanned list\n", McStasStruct.mcdirname); return(0); } if (!mcsimfiles[i]) { mcdirname = McStasStruct.mcdirname; mcinstrnames[i]= str_dup(McStasStruct.InstrName); mcsources[i] = str_dup(McStasStruct.Source); strncpy(mcinstrument_name, str_last_word(mcinstrnames[i]), CHAR_BUF_LENGTH); strncpy(mcinstrument_source , str_dup(mcsources[i]), CHAR_BUF_LENGTH); mcsiminfo_init(NULL); /* open new SIM file in this dir for the first time */ mcsimfiles[i] = mcsiminfo_file; } else mcsiminfo_file = mcsimfiles[i]; mcdirname = mcdirnames[i]; } /* transfer to global variables used in output functions */ if (!McStasStruct.Date) mcstartdate = 0; else { mcstartdate = atol(McStasStruct.Date); if (!mcstartdate) sscanf(McStasStruct.Date, "Simulation started %ld", &mcstartdate); } mcgravitation = (McStasStruct.gravitation && strstr(McStasStruct.gravitation, "yes") ? 1 : 0); mcrun_num = McStasStruct.RunNum; mcncount = McStasStruct.Ncount; strncpy(mcinstrument_source, str_dup(McStasStruct.Source), CHAR_BUF_LENGTH); strncpy(mcinstrument_name , str_last_word(McStasStruct.InstrName), CHAR_BUF_LENGTH); /* transfer mcnumipar */ mcnumipar = McStasStruct.mcnumipar; for (i=0; i= 0) printf(" Gathering Scan step %s/%s (%d) with %s/%s (%d)\n", McStasStruct.mcdirname, McStasStruct.outputname, i, ThisStruct.mcdirname, ThisStruct.outputname, j); if (Scans_to_merge[j] < 0) Scans_to_merge[j] = i; /* next i if this is a scan (no add/cat) */ continue; /* for j */ } if (!mcmergemode) continue; if (mcverbose) fprintf(stderr," %s %s/%s (%d) with %s/%s (%d) total %ld elements\n", flag_list==2 ? "Adding" : "Appending", McStasStruct.mcdirname, McStasStruct.outputname, i, ThisStruct.mcdirname, ThisStruct.outputname, j, (long)abs(McStasStruct.m*McStasStruct.n*McStasStruct.p)); if (flag_list==1) { /* if list: catenate data j to end of i */ /* allocate new array of size rows(i+j), same n,p */ double *p1=mem(abs((ThisStruct.m+McStasStruct.m)*McStasStruct.n*McStasStruct.p)*sizeof(double)); /* copy data from i */ int index_i, index_j, index; /* data index is index_i*columns+index_j */ for (index_i=0; index_i db) return 1; else if (da < db) return -1; else /* same distance, sort on names */ return strcmp(Files_to_Merge[ia].filename, Files_to_Merge[ib].filename); } /* sorting functions for qsort: sort monitor column with ipar.val */ int sort_ipar_mon (const void *a, const void *b) { const int *pa = (const int *) a; const int *pb = (const int *) b; int ia=*pa; int ib=*pb; double da=Files_to_Merge[ia].mcinputtable[ipar_var].type == instr_type_string ? 0 : atof(Files_to_Merge[ia].mcinputtable[ipar_var].val); double db=Files_to_Merge[ib].mcinputtable[ipar_var].type == instr_type_string ? 0 : atof(Files_to_Merge[ib].mcinputtable[ipar_var].val); if (da > db) return 1; else if (da < db) return -1; else {/* same distance, sort on ipar value then filenames */ int tmp=strcmp(Files_to_Merge[ia].mcinputtable[ipar_var].val, Files_to_Merge[ib].mcinputtable[ipar_var].val); if (tmp) return(tmp); else return strcmp(Files_to_Merge[ia].filename, Files_to_Merge[ib].filename); } } #endif /********************************************************************* * mcformat_scan_compare: assemble scanned monitors into multiarray sets * warning: this function is a real headache *********************************************************************/ void mcformat_scan_compare(int nb) { /* definition of a scan Must be 'mergeable' data but with different ipar values Each Scans_to_merge[] index set is a column of multiarray_1d (this is a scanned monitor) Must analyse scan columns (Scans_to_merge[]) to gather them with -common ipar names (set of scanned monitors) -same set (monitor number) length and monitor names -same ipar values define rows */ int scan_index1=0; int i=0,j; /* test if there is scan data to be processed */ for (scan_index1=0; scan_index1 -1 */ for (scan_index1=0; scan_index1=0) Scan_distances[j++] = Scan_columns[scan_index2]; #ifdef HAVE_QSORT qsort(Scan_distances, mon_count, sizeof(int), sort_distances); #endif for (j=0; j= 0 && Scans_to_merge[scan_index2] == Scan_distances[j]) { Monitor_column[k++] = scan_index2; Scans_to_merge[scan_index2]=-1; /*unactivate that scan element */ } } /* sort each monitor column with ipar value */ #ifdef HAVE_QSORT qsort(Monitor_column, scan_length1, sizeof(int), sort_ipar_mon); #endif /* extract sorted column and set Scan */ for (i=0; i this) ipar_min=this; if (ipar_max < this) ipar_max=this; } /* for i */ strcat(header, Files_to_Merge[Scan_distances[j]].outputname); strcat(header, "_I "); strcat(header, Files_to_Merge[Scan_distances[j]].outputname); strcat(header, "_ERR "); strcat(youts, "("); strcat(youts, Files_to_Merge[Scan_distances[j]].outputname); strcat(youts, "_I,"); strcat(youts, Files_to_Merge[Scan_distances[j]].outputname); strcat(youts, "_ERR) "); } /* for j */ Scan.header=header; Scans_to_merge[scan_index1]=-1; /* unactivate that scan element */ char *title=str_cat("Scan of ", Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, NULL); /* output scan multiarray */ /* for PGPLOT: open mcstas.sim */ if (strcasestr(mcformat, "McCode")) mcsiminfo_init(NULL); /* open new SIM file in this dir for the first time */ else mcsiminfo_name=NULL; char *datfile=NULL; if (!datfile) datfile = str_cat("mcstas.", "dat", NULL); strcat(mcformat, " scan "); if (mcverbose) printf("Writing scan file=%s (%s) into directory %s: %s=%g:%g\n", datfile, mcsiminfo_name, mcdirname, Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, ipar_min, ipar_max); strcpy(mcinstrument_name, Files_to_Merge[scan_index1].InstrName); strcpy(mcinstrument_source, Files_to_Merge[scan_index1].Source); if (!mcdisable_output_files) mcdetector_out_2D(title, Files_to_Merge[scan_index1].mcinputtable[ipar_var].name, Files_to_Merge[scan_index1].ylabel, ipar_min, ipar_max, 0, 0, -scan_length1, Files_to_Merge[scan_index1].mcnumipar+2*mon_count, NULL, Scan.data, NULL, datfile, Files_to_Merge[scan_index1].component, Files_to_Merge[scan_index1].POSITION); /* for PGPLOT: close mcstas.sim */ if (strstr(mcformat, "McCode")) mcsiminfo_close(); Table_Free(&Scan); memfree(datfile); memfree(youts); memfree(title); /* go to end of scan and continue to search for scans */ } /* for scan_index1 */ } /* mcformat_scan_compare */ /******************************************************************************* * mcformat_merge_output: output non empty files * special handling for multiarray/scans *******************************************************************************/ int mcformat_merge_output(int nb) { int i; char mcdisable_output_files_sav=mcdisable_output_files; if (mcscanmode == 2) mcdisable_output_files=1; /* scan only will skip writing for non scan files */ /* output files for non empty elements */ for (i=0; i 1 ? "s" : "", mcdircount, mcdircount > 1 ? "ies" : "y"); /* allocate array of Original file structures */ Files_to_Merge = mem(mcnbconvert*sizeof(struct McStas_file_format)); Scans_to_merge = mem(mcnbconvert*sizeof(int)); for (j=0; j