62static char *option[N_OPTIONS] = {
73 "sddscliptails [<input>] [<output>] [-pipe=[in][,out]]\n"
74 " [-columns=<listOfNames>] [-fractional=<value>] [-absolute=<value>] [-fwhm=<multiplier>]\n"
75 " [-afterzero[=<bufferWidth>]] [-majorOrder=row|column]\n\n"
76 "-columns List of columns to process.\n"
77 "-fractional Clip a tail if it falls below this fraction of the peak.\n"
78 "-absolute Clip a tail if it falls below this absolute value.\n"
79 "-fwhm Clip a tail if it is beyond this many FWHM from the peak.\n"
80 "-afterzero Clip a tail if it is separated from the peak by values equal to zero.\n"
81 " If <bufferWidth> is specified, then a region <bufferWidth> wide is kept\n"
82 " on either side of the peak, if possible.\n"
83 "-majorOrder Writes output file in row or column major order.\n\n"
84 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
86static long resolve_column_names(
SDDS_DATASET *sdds_in,
char ***column, int32_t *columns);
87static void clip_tail(
double *data, int64_t rows,
double abs_limit,
double frac_limit,
short *in_tail);
88static void clip_fwhm(
double *data, int64_t n_data,
double fwhm_limit,
double *indep_data,
short *in_tail);
89static void clip_after_zero(
double *data, int64_t rows,
long buffer_width,
short *in_tail);
91int main(
int argc,
char **argv) {
95 long read_code, after_zero, after_zero_buffer_width;
98 unsigned long pipe_flags, major_order_flag;
101 double *data, *indep_data;
102 double fractional_limit, absolute_limit, fwhm_limit;
104 short column_major_order = -1;
107 argc =
scanargs(&scanned, argc, argv);
111 output = input = NULL;
115 fractional_limit = fwhm_limit = 0;
119 for (i_arg = 1; i_arg < argc; i_arg++) {
120 if (scanned[i_arg].arg_type == OPTION) {
122 switch (
match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
123 case CLO_MAJOR_ORDER:
124 major_order_flag = 0;
125 scanned[i_arg].n_items--;
126 if (scanned[i_arg].n_items > 0 &&
127 (!
scanItemList(&major_order_flag, scanned[i_arg].list + 1, &scanned[i_arg].n_items, 0,
128 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
129 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
130 SDDS_Bomb(
"invalid -majorOrder syntax/values");
131 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER)
132 column_major_order = 1;
133 else if (major_order_flag & SDDS_ROW_MAJOR_ORDER)
134 column_major_order = 0;
137 if (scanned[i_arg].n_items < 2)
139 input_column =
tmalloc(
sizeof(*input_column) * (columns = scanned[i_arg].n_items - 1));
140 for (i = 0; i < columns; i++)
141 input_column[i] = scanned[i_arg].list[i + 1];
144 if (!
processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipe_flags))
148 if (scanned[i_arg].n_items < 2 || sscanf(scanned[i_arg].list[1],
"%lf", &fractional_limit) != 1 || fractional_limit < 0)
152 if (scanned[i_arg].n_items < 2 || sscanf(scanned[i_arg].list[1],
"%lf", &absolute_limit) != 1 || absolute_limit < 0)
156 if (scanned[i_arg].n_items < 2 || sscanf(scanned[i_arg].list[1],
"%lf", &fwhm_limit) != 1 || fwhm_limit < 0)
161 if (scanned[i_arg].n_items > 2 ||
162 (scanned[i_arg].n_items == 2 &&
163 (sscanf(scanned[i_arg].list[1],
"%ld", &after_zero_buffer_width) != 1 ||
164 after_zero_buffer_width <= 0)))
168 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", scanned[i_arg].list[0]);
174 input = scanned[i_arg].list[0];
176 output = scanned[i_arg].list[0];
185 SDDS_Bomb(
"supply the names of columns to process with the -columns option");
190 if (!resolve_column_names(&sdds_in, &input_column, &columns))
193 SDDS_Bomb(
"no columns selected for processing");
197 if (column_major_order != -1)
198 sdds_out.layout.data_mode.column_major = column_major_order;
200 sdds_out.layout.data_mode.column_major = sdds_in.layout.data_mode.column_major;
214 if (fwhm_limit > 0) {
215 indep_data =
SDDS_Realloc(indep_data,
sizeof(*indep_data) * rows);
218 for (i = 0; i < rows; i++)
221 in_tail =
SDDS_Realloc(in_tail,
sizeof(*in_tail) * rows);
224 for (i = 0; i < rows; i++)
226 for (i = 0; i < columns; i++) {
230 clip_tail(data, rows, absolute_limit, fractional_limit, in_tail);
232 clip_fwhm(data, rows, fwhm_limit, indep_data, in_tail);
234 clip_after_zero(data, rows, after_zero_buffer_width, in_tail);
240 if (!
SDDS_SetColumn(&sdds_out, SDDS_SET_BY_NAME, in_tail, rows,
"InTail"))
260static long resolve_column_names(
SDDS_DATASET *sdds_in,
char ***column, int32_t *columns) {
264 for (i = 0; i < *columns; i++) {
270 if (!*column || *columns == 0) {
277static void clip_tail(
double *data, int64_t rows,
double abs_limit,
double frac_limit,
short *in_tail) {
279 int64_t i, imin, imax;
282 if (abs_limit < 0 && frac_limit <= 0)
291 abs_limit2 = frac_limit * data[imax];
292 if (abs_limit < 0 || (frac_limit && abs_limit2 < abs_limit))
293 abs_limit = abs_limit2;
298 for (i = imax - 1, clip = 0; i >= 0; i--) {
299 if (!clip && data[i] < abs_limit)
307 for (i = imax + 1, clip = 0; i < rows; i++) {
308 if (!clip && data[i] < abs_limit)
317static void clip_fwhm(
double *data, int64_t n_data,
double fwhm_limit,
double *indep_data,
short *in_tail) {
318 double top, base, fwhm;
319 int64_t i1, i2, i2_save, i, imin, imax;
320 double point1, point2;
322 if (n_data < 3 || fwhm_limit <= 0)
344 fwhm = point2 - point1;
346 for (i = imax + fwhm * fwhm_limit; i < n_data; i++) {
350 for (i = imax - fwhm * fwhm_limit; i >= 0; i--) {
356static void clip_after_zero(
double *data, int64_t rows,
long buffer_width,
short *in_tail) {
357 int64_t imin, imax, i, j;
361 for (i = imax + 1; i < rows; i++) {
363 for (j = i + buffer_width; j < rows; j++) {
371 for (i = imax - 1; i >= 0; i--) {
373 for (j = i - buffer_width; j >= 0; j--) {
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
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_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.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns 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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_SHORT
Identifier for the signed short integer data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
int index_min_max(int64_t *imin, int64_t *imax, double *list, int64_t n)
Finds the indices of the minimum and maximum values in a list of doubles.
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.
long findTopBaseLevels(double *top, double *base, double *data, int64_t points, long bins, double sigmasRequired)
Finds the top-level and base-level of a dataset.
int64_t findCrossingPoint(int64_t start, double *data, int64_t points, double level, long direction, double *indepData, double *location)
Finds the crossing point in the data where the data crosses a specified level.