SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddstdrpeeling.c
Go to the documentation of this file.
1/**
2 * @file sddstdrpeeling.c
3 * @brief Recursive TDR Impedance Peeling Algorithm Implementation.
4 *
5 * @details
6 * This file implements a program to process Time Domain Reflectometry (TDR) data
7 * using a recursive peeling algorithm. The algorithm calculates the impedance profile
8 * of a non-uniform transmission line based on input voltage and the characteristic
9 * line impedance. The program leverages the SDDS (Self Describing Data Sets) library
10 * for input and output data handling, supporting flexible data processing options.
11 *
12 * @section Usage
13 * ```
14 * sddstdrpeeling [<input>] [<output>]
15 * [-pipe=[input][,output]]
16 * -col=<data-column>
17 * [-inputVoltage=<value|@<parameter>]]
18 * [-z0=<value>]
19 * [-majorOrder=row|column]
20 * ```
21 *
22 * @section Options
23 * | Required | Description |
24 * |---------------------------------------|---------------------------------------------------------------------------------------|
25 * | `-col` | Specifies the data column name in the SDDS file. |
26 *
27 * | Optional | Description |
28 * |---------------------------------------|---------------------------------------------------------------------------------------|
29 * | `-pipe` | Enables piping for input and/or output streams. |
30 * | `-inputVoltage` | Sets the input voltage directly or references a parameter for its value. |
31 * | `-z0` | Defines the characteristic line impedance (default is 50 ohms). |
32 * | `-majorOrder` | Specifies the major order of data processing (default is based on input file). |
33 *
34 * @copyright
35 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
36 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
37 *
38 * @license
39 * This file is distributed under the terms of the Software License Agreement
40 * found in the file LICENSE included with this distribution.
41 *
42 * @author
43 * H. Shang, R. Soliday
44 */
45
46#include "mdb.h"
47#include "SDDS.h"
48#include "SDDSutils.h"
49#include "scan.h"
50#include <ctype.h>
51
52static char *USAGE =
53 "sddstdrpeeling [<input>] [<output>]\n"
54 " [-pipe=[input][,output]]\n"
55 " -col=<data-column>\n"
56 " [-inputVoltage=<value|@<parameter>]]\n"
57 " [-z0=<value>]\n\n"
58 "Options:\n"
59 " -column Provide the data column name.\n"
60 " -inputVoltage Specify the input voltage in volts for TDR (Time Domain Reflectometry).\n"
61 " -z0 Set the line impedance (default is 50 ohms).\n\n"
62 "Description:\n"
63 " sddstdrpeeling processes TDR data using a recursive algorithm to determine the impedance of a nonuniform transmission line.\n\n"
64 "Program Information:\n"
65 " Program by Hairong Shang. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")";
66
67/* Enumeration for option types */
68enum option_type {
69 CLO_PIPE,
70 CLO_COLUMN,
71 CLO_INPUT_VOLTAGE,
72 CLO_Z0,
73 CLO_MAJOR_ORDER,
74 N_OPTIONS
75} option_type;
76
77static char *option[N_OPTIONS] = {
78 "pipe",
79 "column",
80 "inputVoltage",
81 "z0",
82 "majorOrder"};
83
84int main(int argc, char **argv) {
85 double *meas_data = NULL, input_voltage = 0.2, z0 = 50;
86 char *input = NULL, *output = NULL, *data_column = NULL, *input_vol_param = NULL;
87 long i_arg, k;
88 double *left = NULL, *right = NULL, *gamma = NULL, *zline = NULL;
89 double g_product, vr_temp, d_increase;
90
91 SDDS_DATASET sdds_in, sdds_out;
92 SCANNED_ARG *scanned = NULL;
93 unsigned long pipe_flags = 0, major_order_flag = 0;
94 int64_t i, rows;
95 short column_major_order = -1;
96
98
99 argc = scanargs(&scanned, argc, argv);
100 if (argc == 1)
101 bomb(NULL, USAGE);
102
103 for (i_arg = 1; i_arg < argc; i_arg++) {
104 if (scanned[i_arg].arg_type == OPTION) {
105 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
106 case CLO_PIPE:
107 if (!processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipe_flags)) {
108 SDDS_Bomb("Invalid -pipe syntax");
109 }
110 break;
111 case CLO_MAJOR_ORDER:
112 major_order_flag = 0;
113 scanned[i_arg].n_items--;
114 if (scanned[i_arg].n_items > 0 &&
115 (!scanItemList(&major_order_flag, scanned[i_arg].list + 1, &scanned[i_arg].n_items, 0,
116 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
117 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
118 SDDS_Bomb("invalid -majorOrder syntax/values");
119 }
120 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER)
121 column_major_order = 1;
122 else if (major_order_flag & SDDS_ROW_MAJOR_ORDER)
123 column_major_order = 0;
124 break;
125 case CLO_INPUT_VOLTAGE:
126 if (scanned[i_arg].n_items != 2)
127 SDDS_Bomb("invalid -inputVoltage syntax");
128 if (scanned[i_arg].list[1][0] == '@') {
129 cp_str(&input_vol_param, scanned[i_arg].list[1] + 1);
130 } else {
131 if (!get_double(&input_voltage, scanned[i_arg].list[1]))
132 SDDS_Bomb("invalid -threshold value given");
133 }
134 break;
135 case CLO_COLUMN:
136 if (scanned[i_arg].n_items != 2)
137 SDDS_Bomb("invalid -column syntax");
138 data_column = scanned[i_arg].list[1];
139 break;
140 case CLO_Z0:
141 if (scanned[i_arg].n_items != 2)
142 SDDS_Bomb("invalid -z0 syntax");
143 if (!get_double(&z0, scanned[i_arg].list[1]))
144 SDDS_Bomb("invalid -z0 value given");
145 break;
146 default:
147 fprintf(stderr, "Unknown option %s provided\n", scanned[i_arg].list[0]);
148 exit(1);
149 break;
150 }
151 } else {
152 if (!input)
153 input = scanned[i_arg].list[0];
154 else if (!output)
155 output = scanned[i_arg].list[0];
156 else
157 SDDS_Bomb("too many filenames");
158 }
159 }
160
161 processFilenames("sddstdrpeeling", &input, &output, pipe_flags, 0, NULL);
162
163 if (!SDDS_InitializeInput(&sdds_in, input))
164 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
165
166 if (!SDDS_InitializeCopy(&sdds_out, &sdds_in, output, "w"))
167 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
168
169 if (column_major_order != -1)
170 sdds_out.layout.data_mode.column_major = column_major_order;
171 else
172 sdds_out.layout.data_mode.column_major = sdds_in.layout.data_mode.column_major;
173
174 if (!SDDS_DefineSimpleColumn(&sdds_out, "PeeledImpedance", "oms", SDDS_DOUBLE))
175 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
176
177 if (!SDDS_WriteLayout(&sdds_out))
178 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
179
180 while (SDDS_ReadPage(&sdds_in) > 0) {
181 if ((rows = SDDS_CountRowsOfInterest(&sdds_in)) <= 0)
182 continue;
183 if (!SDDS_StartPage(&sdds_out, rows) || !SDDS_CopyPage(&sdds_out, &sdds_in))
184 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
185 if (input_vol_param) {
186 if (!SDDS_GetParameterAsDouble(&sdds_in, input_vol_param, &input_voltage))
187 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
188 }
189 if (!(meas_data = SDDS_GetColumnInDoubles(&sdds_in, data_column)))
190 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
191
192 for (i = 0; i < rows; i++)
193 meas_data[i] /= input_voltage;
194
195 left = calloc(sizeof(*left), rows + 1);
196 right = calloc(sizeof(*right), rows + 1);
197 gamma = calloc(sizeof(*gamma), rows + 1);
198 zline = calloc(sizeof(*zline), rows + 1);
199 g_product = 1;
200
201 if (rows >= 1) {
202 gamma[1] = meas_data[0];
203 left[1] = 1;
204 g_product *= (1 - gamma[1] * gamma[1]);
205 }
206 if (rows >= 2) {
207 vr_temp = (1 - gamma[1]) * right[1] + gamma[1] * left[1];
208 gamma[2] = (meas_data[1] - vr_temp) / g_product;
209 left[2] = left[1] * (1 + gamma[1]);
210 right[1] = left[2] * gamma[2];
211 g_product *= (1 - gamma[2] * gamma[2]);
212 }
213 for (i = 3; i <= rows; i++) {
214 left[i] = left[i - 1] * (1 + gamma[i - 1]);
215 left[i - 1] = left[i - 2] * (1 + gamma[i - 2]) - right[i - 2] * gamma[i - 2];
216 for (k = i - 2; k > 2; k--) {
217 right[k] = gamma[k + 1] * left[k + 1] + (1 - gamma[k + 1] * right[k + 1]);
218 left[k] = (1 + gamma[k - 1]) * left[k - 1] - gamma[k - 1] * right[k - 1];
219 }
220 right[1] = left[2] * gamma[2] + right[2] * (1 - gamma[2]);
221 vr_temp = (1 - gamma[1]) * right[1] + gamma[1] * left[1];
222 gamma[i] = (meas_data[i - 1] - vr_temp) / g_product;
223 g_product *= (1 - gamma[i] * gamma[i]);
224 d_increase = left[i] * gamma[i];
225 right[i - 1] += d_increase;
226 for (k = i - 2; k > 1; k--) {
227 d_increase *= (1 - gamma[k + 1]);
228 right[k] += d_increase;
229 }
230 }
231 zline[0] = z0;
232 for (i = 1; i <= rows; i++) {
233 zline[i] = (1 + gamma[i]) / (1 - gamma[i]) * zline[i - 1];
234 }
235 if (!SDDS_SetColumnFromDoubles(&sdds_out, SDDS_BY_NAME, zline + 1, rows, "PeeledImpedance") ||
236 !SDDS_WritePage(&sdds_out)) {
237 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
238 }
239
240 free(left);
241 free(right);
242 free(gamma);
243 free(zline);
244 free(meas_data);
245 meas_data = NULL;
246 }
247
248 if (!SDDS_Terminate(&sdds_in) || !SDDS_Terminate(&sdds_out)) {
249 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
250 exit(1);
251 }
252
253 free_scanargs(&scanned, argc);
254 return 0;
255}
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)
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_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.
double * SDDS_GetParameterAsDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, double *memory)
Retrieves the value of a specified parameter as a double from the current data table of an SDDS datas...
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_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_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
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
Utility functions for SDDS dataset manipulation and string array operations.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
int get_double(double *dptr, char *s)
Parses a double value from the given string.
Definition data_scan.c:40
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
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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.