SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsremoveoffsets.c File Reference

Detailed Description

A program to remove offsets from BPM waveform data in SDDS files.

This program processes SDDS files to remove offsets in specified data columns, ensuring the resulting data has a zero average. Supports advanced options for output format, column selection, and commutation modes.

Usage

sddsremoveoffsets [<input-file>] [<output-file>]
[-pipe=[input],[output]]
-columns=<name>
[-commutationMode=<string>]
[-removeCommutationOffsetOnly]
[-fhead=<value>]
[-majorOrder=row|column]
[-verbose]

Options

Required Description
-columns Specifies data columns for offset adjustment.
Optional Description
-pipe Use pipes for input/output.
-commutationMode Specifies commutation mode (a, b, ab1, ab2).
-removeCommutationOffsetOnly Removes only commutation offset, leaving other data unaffected.
-fhead Fraction of head rows used for offset calculation.

| -majorOrder=row|column | Sets the major order of the output (row or column). | | -verbose | Enables detailed output during processing. |

Specific Requirements

  • For -fhead=<value>:
    • Value must be a number greater than 0 and less than or equal to 1.
  • For -commutationMode=<string>:
    • Mode must match one of the predefined modes (a, b, ab1, ab2).
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
L. Emery, Jialun Luo, R. Soliday

Definition in file sddsremoveoffsets.c.

#include "mdb.h"
#include "scan.h"
#include "match_string.h"
#include "SDDS.h"

Go to the source code of this file.

Functions

long resolve_column_names (SDDS_DATASET *sdds_in, char ***column, int32_t *columns)
 
int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 108 of file sddsremoveoffsets.c.

108 {
109 SCANNED_ARG *s_arg;
110 SDDS_DATASET sdds_in, sdds_out;
111 unsigned long major_order_flag;
112 char *input = NULL, *output = NULL;
113 int64_t j, rows;
114 int32_t columns = 0;
115 char **input_column = NULL, **output_column = NULL;
116
117 long i, i_arg;
118 long verbose = 0;
119 long commutation_mode = 0;
120 long remove_commutation_offset_only = 0;
121 unsigned long pipe_flags = 0;
122 long tmpfile_used = 0, no_warnings = 0;
123 short column_major_order = -1;
124 double *data, offset1 = 0, offset2 = 0, ave_offset = 0;
125 double fhead = 1;
126
128 argc = scanargs(&s_arg, argc, argv);
129 if (argc == 1)
130 bomb(NULL, usage);
131
132 for (i_arg = 1; i_arg < argc; i_arg++) {
133 if (s_arg[i_arg].arg_type == OPTION) {
134 switch (match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
135 case CLO_MAJOR_ORDER:
136 major_order_flag = 0;
137 s_arg[i_arg].n_items--;
138 if (s_arg[i_arg].n_items > 0 && (!scanItemList(&major_order_flag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
139 SDDS_Bomb("invalid -majorOrder syntax/values");
140 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER)
141 column_major_order = 1;
142 else if (major_order_flag & SDDS_ROW_MAJOR_ORDER)
143 column_major_order = 0;
144 break;
145 case CLO_COMMUTATION_MODE:
146 if (s_arg[i_arg].n_items != 2)
147 bomb("invalid -commutationMode syntax", NULL);
148 if ((commutation_mode = match_string(str_tolower(s_arg[i_arg].list[1]), commutation_mode_list, commutation_modes, EXACT_MATCH)) < 0)
149 SDDS_Bomb("invalid commutationMode given!");
150 break;
151 case CLO_VERBOSE:
152 verbose = 1;
153 break;
154 case CLO_REMOVE_COMMUTATION_OFFSET_ONLY:
155 remove_commutation_offset_only = 1;
156 break;
157 case CLO_FHEAD:
158 if (s_arg[i_arg].n_items != 2)
159 bomb("invalid -fhead syntax", NULL);
160 if (sscanf(s_arg[i_arg].list[1], "%lf", &fhead) != 1 || fhead <= 0 || fhead > 1)
161 fprintf(stderr, "Error: invalid -fhead syntax\n");
162 break;
163 case CLO_PIPE:
164 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags))
165 SDDS_Bomb("invalid -pipe syntax");
166 break;
167 case CLO_COLUMNS:
168 if (columns)
169 SDDS_Bomb("only one -columns option may be given");
170 if (s_arg[i_arg].n_items < 2)
171 SDDS_Bomb("invalid -columns syntax");
172 input_column = tmalloc(sizeof(*input_column) * (columns = s_arg[i_arg].n_items - 1));
173 for (i = 0; i < columns; i++)
174 input_column[i] = s_arg[i_arg].list[i + 1];
175 break;
176 default:
177 SDDS_Bomb("unrecognized option given");
178 }
179 } else {
180 if (!input)
181 input = s_arg[i_arg].list[0];
182 else if (!output)
183 output = s_arg[i_arg].list[0];
184 else
185 SDDS_Bomb("too many filenames seen");
186 }
187 }
188
189 processFilenames("sddsremoveoffsets", &input, &output, pipe_flags, no_warnings, &tmpfile_used);
190
191 if (!columns)
192 SDDS_Bomb("supply the names of columns for offset removal with the -columns option");
193
194 if (!SDDS_InitializeInput(&sdds_in, input))
195 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
196
197 if (!resolve_column_names(&sdds_in, &input_column, &columns))
198 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
199 if (!columns)
200 SDDS_Bomb("no columns selected for offset removal");
201
202 if (!SDDS_InitializeCopy(&sdds_out, &sdds_in, output, "w"))
203 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
204
205 output_column = tmalloc(sizeof(*output_column) * columns);
206 for (i = 0; i < columns; i++)
207 output_column[i] = input_column[i];
208
209 if (!SDDS_InitializeOutput(&sdds_out, SDDS_BINARY, 1, "Remove offset from BPM waveforms", "Modified data", output) ||
210 !SDDS_InitializeCopy(&sdds_out, &sdds_in, output, "w"))
211 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
212 if (column_major_order != -1)
213 sdds_out.layout.data_mode.column_major = column_major_order;
214 else
215 sdds_out.layout.data_mode.column_major = sdds_in.layout.data_mode.column_major;
216 if (!SDDS_WriteLayout(&sdds_out))
217 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
218
219 while (SDDS_ReadPage(&sdds_in) > 0) {
220 if (!SDDS_CopyPage(&sdds_out, &sdds_in))
221 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
222 if ((rows = SDDS_CountRowsOfInterest(&sdds_in))) {
223 for (i = 0; i < columns; i++) {
224 if (!(data = SDDS_GetColumnInDoubles(&sdds_in, input_column[i])))
225 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
226
227 long repeat_offset = (data[0] == data[1]) ? 0 : 1;
228
229 double sum1 = 0, sum2 = 0;
230 unsigned long count1 = 0, count2 = 0;
231 unsigned long half_pattern_length = pattern_length / 2;
232 for (j = 0; j < fhead * rows; j++) {
233 if ((j - repeat_offset) % pattern_length < half_pattern_length) {
234 sum1 += data[j];
235 count1++;
236 } else {
237 sum2 += data[j];
238 count2++;
239 }
240 }
241 offset1 = sum1 / count1;
242 offset2 = sum2 / count2;
243 if (!remove_commutation_offset_only) {
244 for (j = 0; j < rows; j++) {
245 if ((j - repeat_offset) % pattern_length < half_pattern_length)
246 data[j] -= offset1;
247 else
248 data[j] -= offset2;
249 }
250 } else {
251 ave_offset = (offset1 + offset2) / 2.0;
252 for (j = 0; j < rows; j++) {
253 if ((j - repeat_offset) % pattern_length < half_pattern_length)
254 data[j] = data[j] - offset1 + ave_offset;
255 else
256 data[j] = data[j] - offset2 + ave_offset;
257 }
258 }
259
260 if (verbose) {
261 printf("offset1 = %f \t offset2 = %f\n", offset1, offset2);
262 double new_sum = 0;
263 for (j = 0; j < rows; j++) {
264 new_sum += data[j];
265 }
266 double new_mean = new_sum / rows;
267 printf("New average: %f\n", new_mean);
268 }
269
270 if (!SDDS_SetColumnFromDoubles(&sdds_out, SDDS_SET_BY_NAME, data, rows, output_column[i]))
271 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
272 free(data);
273 }
274 }
275 if (!SDDS_WritePage(&sdds_out))
276 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
277 }
278
279 if (!SDDS_Terminate(&sdds_in) || !SDDS_Terminate(&sdds_out))
280 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
281
282 if (tmpfile_used && !replaceFileAndBackUp(input, output))
283 exit(EXIT_FAILURE);
284
285 return 0;
286}
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
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.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *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_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:75
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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.
char * str_tolower(char *s)
Convert a string to lower case.
Definition str_tolower.c:27

◆ resolve_column_names()

long resolve_column_names ( SDDS_DATASET * sdds_in,
char *** column,
int32_t * columns )

Definition at line 288 of file sddsremoveoffsets.c.

288 {
289 long i;
290
291 SDDS_SetColumnFlags(sdds_in, 0);
292 for (i = 0; i < *columns; i++) {
293 if (!SDDS_SetColumnsOfInterest(sdds_in, SDDS_MATCH_STRING, (*column)[i], SDDS_OR))
294 return 0;
295 }
296 free(*column);
297 if (!(*column = SDDS_GetColumnNames(sdds_in, columns)) || *columns == 0) {
298 SDDS_SetError("no columns found");
299 return 0;
300 }
301 return 1;
302}
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.