/*******************************************************************************
*
* 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