83char *option[N_OPTIONS] = {
97 " elegant2genesis [<input>] [<output>]\n"
98 " [-pipe=[in][,out]] \n"
100 " [-totalCharge=<charge-in-Coulombs>]\n"
101 " [-chargeParameter=<name>]\n"
102 " [-wavelength=<meters>]\n"
103 " [-slices=<integer>]\n"
105 " [-removePTails=deltaLimit=<value>[,fit][,beamOutput=<filename>]]\n"
106 " [-reverseOrder] \n"
109 " -pipe=[in][,out] Set up pipe communication for input and/or output.\n"
110 " -textOutput Make the output file a text file instead of an SDDS file.\n"
111 " -totalCharge=<charge-in-Coulombs> Specify the total charge in Coulombs.\n"
112 " -chargeParameter=<name> Specify the name of a parameter in the input file that gives the total charge in Coulombs.\n"
113 " -wavelength=<meters> Specify the wavelength of light in meters.\n"
114 " -slices=<integer> Specify the number of slices to divide the beam into.\n"
115 " -steer Force the x, x', y, and y' centroids for the whole beam to zero.\n"
116 " Slices may still have nonzero centroids.\n"
117 " -removePTails=deltaLimit=<value>[,fit][,beamOutput=<filename>]\n"
118 " Remove the momentum tails from the beam.\n"
119 " deltaLimit specifies the maximum |p - <p>|/<p> to keep.\n"
120 " 'fit' enables a linear fit to (t, p) for tail removal based on residuals.\n"
121 " 'beamOutput' writes the filtered beam to the specified file for review.\n"
122 " -reverseOrder Output the data for the tail of the beam first instead of the head.\n"
123 " -localFit Perform a local linear fit of momentum vs time for each slice and subtract it from the momentum data,\n"
124 " removing a contribution to the energy spread.\n\n"
125 "Program by Robert Soliday and Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
127#define PTAILS_DELTALIMIT 0x0001U
128#define PTAILS_FITMODE 0x0002U
129#define PTAILS_OUTPUT 0x0004U
131int64_t removeMomentumTails(
double *x,
double *xp,
double *y,
double *yp,
double *s,
double *p,
double *t, int64_t rows,
double limit,
unsigned long flags);
132void removeLocalFit(
double *p,
double *s,
short *selected,
double pAverage, int64_t rows);
136int main(
int argc,
char **argv) {
141 char *input, *output;
142 unsigned long pipeFlags = 0;
143 long noWarnings = 0, tmpfile_used = 0;
144 long retval, sddsOutput = 1, steer = 0, firstOne, sliceOffset = 0;
145 int64_t i, j, rows, origRows;
146 long reverseOrder = 0;
147 char *chargeParameter;
148 unsigned long removePTailsFlags = 0;
149 double pTailsDeltaLimit, term;
150 char *pTailsOutputFile = NULL;
154 char column[7][15] = {
"x",
"xp",
"y",
"yp",
"t",
"p",
"particleID"};
157 double *tValues, *sValues, *xValues, *xpValues, *yValues, *ypValues, *pValues;
158 double sAverage, pAverage, pStDev;
159 double xAverage, xpAverage, xRMS, x2Average, xp2Average, xxpAverage, xEmittance;
160 double yAverage, ypAverage, yRMS, y2Average, yp2Average, yypAverage, yEmittance;
161 double sMin = 1, sMax = -1, s1, s2;
165 double alphax, alphay;
167 double wavelength = 0.0001;
168 double totalCharge = 0;
175 input = output = NULL;
177 chargeParameter = NULL;
181 argc =
scanargs(&s_arg, argc, argv);
183 fprintf(stderr,
"Error: Insufficient arguments.\n");
184 fprintf(stderr,
"%s", USAGE);
189 for (i_arg = 1; i_arg < argc; i_arg++) {
190 if (s_arg[i_arg].arg_type == OPTION) {
191 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
192 case SET_TOTALCHARGE:
193 if (s_arg[i_arg].n_items != 2) {
194 fprintf(stderr,
"Error: Invalid -totalCharge syntax.\n");
197 if (sscanf(s_arg[i_arg].list[1],
"%lf", &totalCharge) != 1) {
198 fprintf(stderr,
"Error: Invalid -totalCharge value.\n");
204 fprintf(stderr,
"Error: -wavelength and -slices cannot be used together.\n");
207 if (s_arg[i_arg].n_items != 2) {
208 fprintf(stderr,
"Error: Invalid -wavelength syntax.\n");
211 if (sscanf(s_arg[i_arg].list[1],
"%lf", &wavelength) != 1 || wavelength <= 0) {
212 fprintf(stderr,
"Error: Invalid -wavelength value.\n");
219 fprintf(stderr,
"Error: -wavelength and -slices cannot be used together.\n");
222 if (s_arg[i_arg].n_items != 2) {
223 fprintf(stderr,
"Error: Invalid -slices syntax.\n");
226 if (sscanf(s_arg[i_arg].list[1],
"%ld", &slices) != 1 || slices <= 0) {
227 fprintf(stderr,
"Error: Invalid -slices value.\n");
238 case SET_CHARGEPARAMETER:
239 if (s_arg[i_arg].n_items != 2) {
240 fprintf(stderr,
"Error: Invalid -chargeParameter syntax.\n");
243 chargeParameter = s_arg[i_arg].list[1];
246 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
251 if (s_arg[i_arg].n_items > 1) {
252 if (!
scanItemList(&removePTailsFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
253 "deltalimit",
SDDS_DOUBLE, &pTailsDeltaLimit, 1, PTAILS_DELTALIMIT,
254 "fit", -1, NULL, 0, PTAILS_FITMODE,
255 "beamoutput",
SDDS_STRING, &pTailsOutputFile, 1, PTAILS_OUTPUT,
257 !(removePTailsFlags & PTAILS_DELTALIMIT) || pTailsDeltaLimit <= 0) {
258 SDDS_Bomb(
"Invalid -removePTails syntax or values.");
262 case SET_REVERSEORDER:
269 fprintf(stderr,
"Error: Unknown option '%s'.\n", s_arg[i_arg].list[0]);
274 input = s_arg[i_arg].list[0];
275 }
else if (output == NULL) {
276 output = s_arg[i_arg].list[0];
278 fprintf(stderr,
"Error: Too many filenames provided.\n");
284 processFilenames(
"elegant2genesis", &input, &output, pipeFlags, noWarnings, &tmpfile_used);
293 for (i = 0; i < 7; i++) {
295 fprintf(stderr,
"Error: Column '%s' does not exist.\n", column[i]);
300 if (removePTailsFlags & PTAILS_OUTPUT) {
317 rows = origRows = SDDS_RowCount(&SDDS_input);
319 fprintf(stderr,
"Error: No rows found for page %ld.\n", retval);
331 SDDS_Bomb(
"Unable to read charge from file.");
333 if (!(tValues && xValues && xpValues && yValues && ypValues && pValues)) {
334 fprintf(stderr,
"Error: Invalid data for page %ld.\n", retval);
337 selected = realloc(selected,
sizeof(*selected) * rows);
338 sValues = realloc(sValues,
sizeof(*sValues) * rows);
339 if (!selected || !sValues) {
343 sAverage = xAverage = xpAverage = yAverage = ypAverage = 0;
344 for (i = 0; i < rows; i++) {
345 sValues[i] = tValues[i] * 2.99792458e8;
346 sAverage += tValues[i];
347 xAverage += xValues[i];
348 xpAverage += xpValues[i];
349 yAverage += yValues[i];
350 ypAverage += ypValues[i];
352 sAverage = sAverage * 2.99792458e8 / rows;
358 for (i = 0; i < rows; i++) {
360 sValues[i] = sAverage - sValues[i];
364 if (removePTailsFlags) {
365 rows = removeMomentumTails(xValues, xpValues, yValues, ypValues, sValues, pValues, tValues, rows, pTailsDeltaLimit, removePTailsFlags);
367 SDDS_Bomb(
"All data removed by P-tails filter.");
369 if (removePTailsFlags & PTAILS_OUTPUT) {
371 !
SDDS_SetColumn(&SDDS_pTails, SDDS_SET_BY_NAME, xValues, rows,
"x") ||
372 !
SDDS_SetColumn(&SDDS_pTails, SDDS_SET_BY_NAME, xpValues, rows,
"xp") ||
373 !
SDDS_SetColumn(&SDDS_pTails, SDDS_SET_BY_NAME, yValues, rows,
"y") ||
374 !
SDDS_SetColumn(&SDDS_pTails, SDDS_SET_BY_NAME, ypValues, rows,
"yp") ||
375 !
SDDS_SetColumn(&SDDS_pTails, SDDS_SET_BY_NAME, tValues, rows,
"t") ||
376 !
SDDS_SetColumn(&SDDS_pTails, SDDS_SET_BY_NAME, pValues, rows,
"p") ||
386 for (i = 0; i < rows; i++) {
387 xValues[i] -= xAverage;
388 xpValues[i] -= xpAverage;
389 yValues[i] -= yAverage;
390 ypValues[i] -= ypAverage;
396 if ((tmp == 1) || (tmp == 0)) {
397 slices = (sMax - sMin) / wavelength + 1;
400 wavelength = (sMax - sMin) / slices;
437 fileID = fopen(output,
"w");
438 if (fileID == NULL) {
439 fprintf(stderr,
"Error: Unable to open output file for writing.\n");
442 fprintf(fileID,
"%ld", slices);
450 sliceOffset += slices;
454 for (i = 0; i < slices; i++) {
456 xAverage = xpAverage = xRMS = x2Average = xp2Average = xxpAverage = 0;
457 yAverage = ypAverage = yRMS = y2Average = yp2Average = yypAverage = 0;
458 pAverage = alphax = alphay = 0;
461 s1 = sMin + (wavelength * i);
462 s2 = sMin + (wavelength * (i + 1));
464 s1 = sMin + (wavelength * (slices - i - 1));
465 s2 = sMin + (wavelength * (slices - i));
468 for (j = 0; j < rows; j++) {
470 if ((s1 <= sValues[j]) && (s2 > sValues[j])) {
473 xAverage += xValues[j];
474 xpAverage += xpValues[j];
475 yAverage += yValues[j];
476 ypAverage += ypValues[j];
477 pAverage += pValues[j];
482 current = N * 2.99792458e8 * (totalCharge / (origRows * wavelength));
483 Ne = totalCharge * N / (e_mks * origRows);
492 removeLocalFit(pValues, sValues, selected, pAverage, rows);
494 for (j = 0; j < rows; j++) {
496 pStDev += (pValues[j] - pAverage) * (pValues[j] - pAverage);
497 x2Average += (xValues[j] - xAverage) * (xValues[j] - xAverage);
498 y2Average += (yValues[j] - yAverage) * (yValues[j] - yAverage);
499 xp2Average += (xpValues[j] - xpAverage) * (xpValues[j] - xpAverage);
500 yp2Average += (ypValues[j] - ypAverage) * (ypValues[j] - ypAverage);
501 xxpAverage += (xValues[j] - xAverage) * (xpValues[j] - xpAverage);
502 yypAverage += (yValues[j] - yAverage) * (ypValues[j] - ypAverage);
505 pStDev = sqrt(pStDev / (N - 1.0));
512 xRMS = sqrt(x2Average);
513 yRMS = sqrt(y2Average);
515 if ((term = (x2Average * xp2Average) - (xxpAverage * xxpAverage)) > 0) {
516 xEmittance = sqrt(term) * pAverage;
521 if ((term = (y2Average * yp2Average) - (yypAverage * yypAverage)) > 0) {
522 yEmittance = sqrt(term) * pAverage;
527 alphax = -xxpAverage / ((xEmittance > 0) ? (xEmittance / pAverage) : 1);
528 alphay = -yypAverage / ((yEmittance > 0) ? (yEmittance / pAverage) : 1);
530 pAverage = pStDev = xEmittance = yEmittance = xRMS = yRMS = xAverage = yAverage = xpAverage = ypAverage = alphax = alphay = current = Ne = 0;
534 if (
SDDS_SetRowValues(&SDDS_output, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, i + sliceOffset,
539 "Sdelta", (pAverage > 0) ? (pStDev / pAverage) : 0,
559 fprintf(fileID,
"\n%.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E %.6E 0.000000E+00",
560 s1, pAverage, pStDev, xEmittance, yEmittance, xRMS, yRMS,
561 xAverage, yAverage, xpAverage, ypAverage, alphax, alphay, current);
593 if ((removePTailsFlags & PTAILS_OUTPUT) && !
SDDS_Terminate(&SDDS_pTails)) {
601int64_t removeMomentumTails(
double *x,
double *xp,
double *y,
double *yp,
double *s,
double *p,
double *t, int64_t rows,
double limit,
unsigned long flags) {
606 static FILE *fp = NULL;
612 delta = malloc(
sizeof(*delta) * rows);
616 for (ip = pAve = 0; ip < rows; ip++)
620 for (ip = 0; ip < rows; ip++)
621 delta[ip] = (p[ip] - pAve) / pAve;
623 if (flags & PTAILS_FITMODE) {
624 double slope, intercept, variance;
626 SDDS_Bomb(
"Fit failed in momentum tail removal.");
627 for (ip = 0; ip < rows; ip++)
628 delta[ip] -= s[ip] * slope + intercept;
632 for (ip = 0; ip < rows; ip++) {
633 if (fabs(delta[ip]) > limit) {
642 delta[ip] = delta[jp];
653 fp = fopen(
"e2g.sdds",
"w");
655 fprintf(fp,
"SDDS1\n&column name=x type=double &end\n");
656 fprintf(fp,
"&column name=xp type=double &end\n");
657 fprintf(fp,
"&column name=y type=double &end\n");
658 fprintf(fp,
"&column name=yp type=double &end\n");
659 fprintf(fp,
"&column name=s type=double &end\n");
660 fprintf(fp,
"&column name=p type=double &end\n");
661 fprintf(fp,
"&data mode=ascii &end\n");
662 fprintf(fp,
"%ld\n", rows);
666 for (ip = 0; ip < rows; ip++)
667 fprintf(fp,
"%le %le %le %le %le %le\n", x[ip], xp[ip], y[ip], yp[ip], s[ip], p[ip]);
674void removeLocalFit(
double *p,
double *s,
short *selected,
double pAverage, int64_t rows) {
675 double slope, intercept, variance;
679 for (i = 0; i < rows; i++) {
681 p[i] -= intercept + slope * s[i] - pAverage;
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_LengthenTable(SDDS_DATASET *SDDS_dataset, int64_t n_additional_rows)
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
long unweightedLinearFitSelect(double *xData, double *yData, short *select, long nData, double *slope, double *intercept, double *variance)
Performs an unweighted linear fit on the provided data with optional data point selection.
long unweightedLinearFit(double *xData, double *yData, long nData, double *slope, double *intercept, double *variance)
Performs an unweighted linear fit on the provided data.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.