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