SDDSlib
Loading...
Searching...
No Matches
sddszerofind.c File Reference

A program to find zero crossings in a column of an SDDS file. More...

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

Go to the source code of this file.

Macros

#define FL_SLOPEOUTPUT   0x00001UL
 

Enumerations

enum  option_type {
  CLO_PIPE , CLO_COLUMNS , CLO_SLOPEOUTPUT , CLO_ZEROESOF ,
  CLO_OFFSET , CLO_MAJOR_ORDER , N_OPTIONS
}
 

Functions

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

Variables

char * option [N_OPTIONS]
 
static char * USAGE
 

Detailed Description

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

This program identifies zero-crossing points in one SDDS column as a function of another column. It performs interpolation to compute zero positions and optionally calculates the slope at each zero.

Key Features

  • Supports multiple input and output formats, including piping.
  • Allows specification of columns for zero-finding and dependent columns for interpolation.
  • Option to include slope information in the output.
  • Provides flexible row or column-major ordering for output files.

Usage

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

Options

  • -zeroesOf=<columnName>: Specifies the column to find zero crossings.
  • -columns=<columnNames>: Specifies columns for interpolation (default: all numerical columns).
  • -offset=

: Adjusts the zero-finding threshold by adding an offset.

  • -slopeOutput: Outputs the slope at zero-crossing points.
  • -majorOrder=row|column: Sets output ordering in row or column-major format.

Example

sddszerofind input.sdds output.sdds -zeroesOf=ColumnA -columns=ColumnB,ColumnC -offset=0.5 -slopeOutput
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.

Macro Definition Documentation

◆ FL_SLOPEOUTPUT

#define FL_SLOPEOUTPUT   0x00001UL

Definition at line 85 of file sddszerofind.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 48 of file sddszerofind.c.

48 {
49 CLO_PIPE,
50 CLO_COLUMNS,
51 CLO_SLOPEOUTPUT,
52 CLO_ZEROESOF,
53 CLO_OFFSET,
54 CLO_MAJOR_ORDER,
55 N_OPTIONS
56} option_type;

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 89 of file sddszerofind.c.

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

287 {
288 long index;
289 char s[SDDS_MAXLINE];
290
291 index = SDDS_GetColumnIndex(SDDSin, depen_quantity);
292 if (index < 0 || !SDDS_NUMERIC_TYPE(SDDS_GetColumnType(SDDSin, index))) {
293 snprintf(s, SDDS_MAXLINE, "column %s is non-existent or non-numeric", depen_quantity);
294 SDDS_SetError(s);
295 return 0;
296 }
297
298 if (*indep_quantities) {
299 SDDS_SetColumnFlags(SDDSin, 0);
300 for (long i = 0; i < *indep_quantities; i++) {
301 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, (*indep_quantity)[i], SDDS_OR)) {
302 return 0;
303 }
304 }
305 } else {
306 SDDS_SetColumnFlags(SDDSin, 1);
307 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, depen_quantity, SDDS_NEGATE_MATCH | SDDS_AND)) {
308 return 0;
309 }
310 *indep_quantity = SDDS_GetColumnNames(SDDSin, indep_quantities);
311 if (!(*indep_quantity) || *indep_quantities == 0) {
312 SDDS_SetError("no independent quantities found");
313 return 0;
314 }
315 for (long i = 0; i < *indep_quantities; i++) {
316 index = SDDS_GetColumnIndex(SDDSin, (*indep_quantity)[i]);
317 if (!SDDS_NUMERIC_TYPE(SDDS_GetColumnType(SDDSin, index)) &&
318 !SDDS_AssertColumnFlags(SDDSin, SDDS_INDEX_LIMITS, index, index, 0)) {
319 return 0;
320 }
321 }
322 }
323
324 free(*indep_quantity);
325 *indep_quantity = SDDS_GetColumnNames(SDDSin, indep_quantities);
326 if (!(*indep_quantity) || *indep_quantities == 0) {
327 SDDS_SetError("no independent quantities found");
328 return 0;
329 }
330 return 1;
331}
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

Variable Documentation

◆ option

char* option[N_OPTIONS]
Initial value:
=
{
"pipe",
"columns",
"slopeoutput",
"zeroesof",
"offset",
"majorOrder",
}

Definition at line 58 of file sddszerofind.c.

59 {
60 "pipe",
61 "columns",
62 "slopeoutput",
63 "zeroesof",
64 "offset",
65 "majorOrder",
66 };

◆ USAGE

char* USAGE
static
Initial value:
=
"sddszerofind [<inputfile>] [<outputfile>] [-pipe=[input][,output]]\n"
"-zeroesOf=<columnName> [-columns=<columnNames>] [-offset=<value>] "
"[-slopeOutput] [-majorOrder=row|column]\n\n"
"Finds values of columns of data at interpolated zero positions in another\n"
"column.\n\n"
"-zeroesOf Specifies the column for which to find zeroes.\n"
"-offset Specifies a value to add to the values of the -zeroesOf column\n"
" prior to finding the zeroes. -offset=1 will find places where\n"
" the original values are -1.\n"
"-columns Specifies the columns to interpolate at the zero positions.\n"
" Default is all numerical columns in the file.\n"
"-majorOrder Specify output file in row or column order.\n"
"-slopeOutput Provide output of the slope of each -column column at the zero\n"
" position.\n\n"
"Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"

Definition at line 68 of file sddszerofind.c.