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

Detailed Description

A program to identify zero crossings in a specified column of an SDDS file.

This program processes SDDS files to find zero-crossing points in one column as a function of another column. It performs interpolation to compute zero positions and optionally calculates the slope at each zero. The output can be configured to include additional slope information and different ordering formats.

Usage

sddszerofind [<inputfile>] [<outputfile>]
[-pipe=[input][,output]]
-zeroesOf=<columnName>
[-columns=<columnNames>]
[-offset=<value>]
[-slopeOutput]
[-majorOrder=row|column]

Options

Required Description
-zeroesOf Specifies the column to find zero crossings.
Optional Description
-pipe Enables input and/or output through a pipe.
-columns Specifies columns for interpolation (default: all numerical columns).
-offset Adjusts the zero-finding threshold by adding an offset.
-slopeOutput Includes the slope at zero-crossing points in the output.
-majorOrder Configures the output ordering in row or column-major format.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, R. Soliday, H. Shang

Definition in file sddszerofind.c.

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

Go to the source code of this file.

Functions

long resolve_column_names (SDDS_DATASET *SDDSin, char *depen_quantity, char ***indep_quantity, int32_t *indep_quantities)
 
int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 91 of file sddszerofind.c.

91 {
92 SDDS_DATASET in_set, out_set;
93 SCANNED_ARG *s_arg;
94 char *input = NULL, *output = NULL, *zero_name = NULL, **column_name = NULL;
95 long i_arg, page_returned;
96 int64_t rows, zrow;
97 int32_t column_names = 0;
98 double **indep_data, *depen_data, **slope_data, slope, offset = 0;
99 unsigned long pipe_flags = 0, flags = 0, major_order_flag;
100 char s[SDDS_MAXLINE];
101 short column_major_order = -1;
102
104 argc = scanargs(&s_arg, argc, argv);
105 if (argc < 2 || argc > (2 + N_OPTIONS)) {
106 bomb(NULL, USAGE);
107 }
108
109 for (i_arg = 1; i_arg < argc; i_arg++) {
110 if (s_arg[i_arg].arg_type == OPTION) {
111 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
112 case CLO_MAJOR_ORDER:
113 major_order_flag = 0;
114 s_arg[i_arg].n_items--;
115 if (s_arg[i_arg].n_items > 0 &&
116 (!scanItemList(&major_order_flag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
117 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
118 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
119 SDDS_Bomb("invalid -majorOrder syntax/values");
120 }
121 column_major_order = (major_order_flag & SDDS_COLUMN_MAJOR_ORDER) ? 1 : 0;
122 break;
123 case CLO_PIPE:
124 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags)) {
125 SDDS_Bomb("invalid -pipe syntax");
126 }
127 break;
128 case CLO_ZEROESOF:
129 if (s_arg[i_arg].n_items != 2) {
130 SDDS_Bomb("invalid -zeroesOf syntax");
131 }
132 zero_name = s_arg[i_arg].list[1];
133 break;
134 case CLO_COLUMNS:
135 if (s_arg[i_arg].n_items < 2) {
136 SDDS_Bomb("invalid -columns syntax");
137 }
138 column_name = tmalloc(sizeof(*column_name) * (column_names = s_arg[i_arg].n_items - 1));
139 for (int i = 0; i < column_names; i++) {
140 column_name[i] = s_arg[i_arg].list[i + 1];
141 }
142 break;
143 case CLO_SLOPEOUTPUT:
144 flags |= FL_SLOPEOUTPUT;
145 break;
146 case CLO_OFFSET:
147 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%le", &offset) != 1) {
148 SDDS_Bomb("invalid -offset syntax");
149 }
150 break;
151 default:
152 fprintf(stderr, "Error (%s): unknown/ambiguous option: %s\n", argv[0], s_arg[i_arg].list[0]);
153 exit(1);
154 }
155 } else {
156 if (input == NULL) {
157 input = s_arg[i_arg].list[0];
158 } else if (output == NULL) {
159 output = s_arg[i_arg].list[0];
160 } else {
161 SDDS_Bomb("too many filenames");
162 }
163 }
164 }
165
166 processFilenames("sddszerofind", &input, &output, pipe_flags, 0, NULL);
167
168 if (!zero_name) {
169 SDDS_Bomb("-zeroesOf option must be given");
170 }
171
172 if (!SDDS_InitializeInput(&in_set, input)) {
173 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
174 }
175
176 if (!resolve_column_names(&in_set, zero_name, &column_name, &column_names) ||
177 !SDDS_InitializeOutput(&out_set, SDDS_BINARY, 0, NULL, "sddszerofind output", output) ||
178 !SDDS_TransferColumnDefinition(&out_set, &in_set, zero_name, NULL)) {
179 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
180 }
181
182 out_set.layout.data_mode.column_major = (column_major_order != -1) ? column_major_order : in_set.layout.data_mode.column_major;
183
184 for (int i = 0; i < column_names; i++) {
185 snprintf(s, SDDS_MAXLINE, "%sSlope", column_name[i]);
186 if (!SDDS_TransferColumnDefinition(&out_set, &in_set, column_name[i], NULL) ||
187 (flags & FL_SLOPEOUTPUT && !SDDS_TransferColumnDefinition(&out_set, &in_set, column_name[i], s))) {
188 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
189 }
190 }
191
192 if (!SDDS_WriteLayout(&out_set)) {
193 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
194 }
195
196 indep_data = tmalloc(sizeof(*indep_data) * column_names);
197 slope_data = tmalloc(sizeof(*slope_data) * column_names);
198
199 while ((page_returned = SDDS_ReadPage(&in_set)) > 0) {
200 if (!SDDS_StartPage(&out_set, 0)) {
201 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
202 }
203
204 if ((rows = SDDS_CountRowsOfInterest(&in_set)) > 1) {
205 depen_data = SDDS_GetColumnInDoubles(&in_set, zero_name);
206 if (!depen_data) {
207 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
208 }
209
210 for (int i = 0; i < column_names; i++) {
211 indep_data[i] = SDDS_GetColumnInDoubles(&in_set, column_name[i]);
212 if (!indep_data[i]) {
213 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
214 }
215
216 if (flags & FL_SLOPEOUTPUT) {
217 slope_data[i] = tmalloc(sizeof(**slope_data) * rows);
218 }
219 }
220
221 if (offset) {
222 for (int row = 0; row < rows; row++) {
223 depen_data[row] += offset;
224 }
225 }
226
227 zrow = 0;
228 for (int row = 0; row < rows - 1; row++) {
229 if ((depen_data[row] <= 0 && depen_data[row + 1] >= 0) ||
230 (depen_data[row] >= 0 && depen_data[row + 1] <= 0)) {
231 for (int i = 0; i < column_names; i++) {
232 if (indep_data[i][row] == indep_data[i][row + 1]) {
233 if (flags & FL_SLOPEOUTPUT) {
234 slope_data[i][zrow] = DBL_MAX;
235 }
236 indep_data[i][zrow] = indep_data[i][row];
237 } else {
238 slope = (depen_data[row + 1] - depen_data[row]) / (indep_data[i][row + 1] - indep_data[i][row]);
239 if (flags & FL_SLOPEOUTPUT) {
240 slope_data[i][zrow] = slope;
241 }
242 indep_data[i][zrow] = (slope) ? (indep_data[i][row] - depen_data[row] / slope) : ((indep_data[i][row] + indep_data[i][row + 1]) / 2);
243 }
244 }
245 depen_data[zrow] = -offset;
246 zrow++;
247 }
248 }
249
250 if (zrow) {
251 if (!SDDS_LengthenTable(&out_set, zrow) ||
252 !SDDS_SetColumnFromDoubles(&out_set, SDDS_SET_BY_NAME, depen_data, zrow, zero_name)) {
253 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
254 }
255
256 for (int i = 0; i < column_names; i++) {
257 snprintf(s, SDDS_MAXLINE, "%sSlope", column_name[i]);
258 if (!SDDS_SetColumnFromDoubles(&out_set, SDDS_SET_BY_NAME, indep_data[i], zrow, column_name[i]) ||
259 (flags & FL_SLOPEOUTPUT && !SDDS_SetColumnFromDoubles(&out_set, SDDS_SET_BY_NAME, slope_data[i], zrow, s))) {
260 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
261 }
262 }
263 }
264
265 free(depen_data);
266 for (int i = 0; i < column_names; i++) {
267 free(indep_data[i]);
268 }
269 if (flags & FL_SLOPEOUTPUT) {
270 for (int i = 0; i < column_names; i++) {
271 free(slope_data[i]);
272 }
273 }
274 }
275
276 if (!SDDS_WritePage(&out_set)) {
277 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
278 }
279 }
280
281 if (!SDDS_Terminate(&in_set) || !SDDS_Terminate(&out_set)) {
282 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
283 exit(1);
284 }
285
286 return 0;
287}
int32_t SDDS_LengthenTable(SDDS_DATASET *SDDS_dataset, int64_t n_additional_rows)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
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.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
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.
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.

◆ resolve_column_names()

long resolve_column_names ( SDDS_DATASET * SDDSin,
char * depen_quantity,
char *** indep_quantity,
int32_t * indep_quantities )

Definition at line 289 of file sddszerofind.c.

289 {
290 long index;
291 char s[SDDS_MAXLINE];
292
293 index = SDDS_GetColumnIndex(SDDSin, depen_quantity);
294 if (index < 0 || !SDDS_NUMERIC_TYPE(SDDS_GetColumnType(SDDSin, index))) {
295 snprintf(s, SDDS_MAXLINE, "column %s is non-existent or non-numeric", depen_quantity);
296 SDDS_SetError(s);
297 return 0;
298 }
299
300 if (*indep_quantities) {
301 SDDS_SetColumnFlags(SDDSin, 0);
302 for (long i = 0; i < *indep_quantities; i++) {
303 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, (*indep_quantity)[i], SDDS_OR)) {
304 return 0;
305 }
306 }
307 } else {
308 SDDS_SetColumnFlags(SDDSin, 1);
309 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, depen_quantity, SDDS_NEGATE_MATCH | SDDS_AND)) {
310 return 0;
311 }
312 *indep_quantity = SDDS_GetColumnNames(SDDSin, indep_quantities);
313 if (!(*indep_quantity) || *indep_quantities == 0) {
314 SDDS_SetError("no independent quantities found");
315 return 0;
316 }
317 for (long i = 0; i < *indep_quantities; i++) {
318 index = SDDS_GetColumnIndex(SDDSin, (*indep_quantity)[i]);
319 if (!SDDS_NUMERIC_TYPE(SDDS_GetColumnType(SDDSin, index)) &&
320 !SDDS_AssertColumnFlags(SDDSin, SDDS_INDEX_LIMITS, index, index, 0)) {
321 return 0;
322 }
323 }
324 }
325
326 free(*indep_quantity);
327 *indep_quantity = SDDS_GetColumnNames(SDDSin, indep_quantities);
328 if (!(*indep_quantity) || *indep_quantities == 0) {
329 SDDS_SetError("no independent quantities found");
330 return 0;
331 }
332 return 1;
333}
int32_t SDDS_AssertColumnFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for columns based on specified criteria.
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
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138