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

Detailed Description

Converts M. Borland's older mpl (Multi-Purpose Library) files into a single SDDS file.

This program processes multiple mpl (Multi-Purpose Library) files and consolidates their data into a single SDDS (Self Describing Data Set) file. It supports both ASCII and binary formats for the output SDDS file and provides options to overwrite existing data or create a new file.

The program ensures consistent formatting of the resulting SDDS file, handling cases such as differing numbers of rows in input files or existing data conflicts.

Usage

mpl2sdds <mpl-filename> [<mpl-filename>...] -output=<SDDS-filename> [-erase] [-binary]

Options

Required Description
-output Specifies the output SDDS file.
Optional Description
-erase Erase existing data in the output SDDS file before adding new data.
-binary Write the SDDS file in binary format instead of ASCII.

Incompatibilities

  • -erase is incompatible with loading existing data from the specified output file.

Requirements

  • Input MPL files must have matching numbers of rows.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
M. Borland, C. Saunders, R. Soliday

Definition in file mpl2sdds.c.

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

Go to the source code of this file.

Functions

void extract_name_and_unit (char **name, char **unit, char *label)
 
long add_definition (SDDS_DATASET *SDDS_dataset, char *label, char *filename)
 
void fix_mpl_name (char *name)
 
int main (int argc, char **argv)
 

Function Documentation

◆ add_definition()

long add_definition ( SDDS_DATASET * SDDS_dataset,
char * label,
char * filename )

Definition at line 226 of file mpl2sdds.c.

226 {
227 char *symbol, *name, *unit;
228 long index;
229
230 extract_name_and_unit(&symbol, &unit, label);
231 SDDS_CopyString(&name, symbol);
232 fix_mpl_name(name);
233
234 if (SDDS_GetColumnIndex(SDDS_dataset, name) >= 0) {
235 fprintf(stderr, "Warning: Column name '%s' from file '%s' already exists and will be ignored.\n", name, filename);
236 return -1;
237 }
238
239 if ((index = SDDS_DefineColumn(SDDS_dataset, name, symbol, unit, NULL, NULL, SDDS_DOUBLE, 0)) < 0) {
240 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
241 return -1;
242 }
243
244 return index;
245}
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37

◆ extract_name_and_unit()

void extract_name_and_unit ( char ** name,
char ** unit,
char * label )

Definition at line 247 of file mpl2sdds.c.

247 {
248 char *ptr, *uptr;
249
250 if ((uptr = strchr(label, '('))) {
251 *uptr++ = '\0';
252 if ((ptr = strchr(uptr, ')'))) {
253 *ptr = '\0';
254 }
255 SDDS_CopyString(unit, uptr);
256 } else {
257 *unit = NULL;
258 }
259
260 /* Trim trailing spaces from label */
261 ptr = label + strlen(label) - 1;
262 while (ptr != label && *ptr == ' ') {
263 *ptr-- = '\0';
264 }
265 SDDS_CopyString(name, label);
266}

◆ fix_mpl_name()

void fix_mpl_name ( char * name)

Definition at line 268 of file mpl2sdds.c.

268 {
269 char *ptr, *ptr1;
270
271 ptr = name;
272 while ((ptr = strchr(ptr, '$'))) {
273 switch (*(ptr + 1)) {
274 case 'a':
275 case 'b':
276 case 'n':
277 case 'g':
278 case 'r':
279 case 's':
280 case 'e':
281 strcpy_ss(ptr, ptr + 2);
282 break;
283 default:
284 ptr += 1;
285 break;
286 }
287 }
288
289 ptr = name;
290 while ((ptr = strchr(ptr, ' '))) {
291 ptr1 = ptr;
292 while (*ptr1 == ' ') {
293 ptr1++;
294 }
295 strcpy_ss(ptr, ptr1);
296 }
297}
char * strcpy_ss(char *dest, const char *src)
Safely copies a string, handling memory overlap.
Definition str_copy.c:34

◆ main()

int main ( int argc,
char ** argv )

Definition at line 81 of file mpl2sdds.c.

81 {
82 SDDS_DATASET SDDS_dataset;
83 TABLE *mpl_data;
84 SCANNED_ARG *scanned;
85 char **input;
86 long i, j, i_arg, inputs;
87 char *output;
88 long erase, rows, new_columns, SDDS_rows;
89 double **data;
90 long *index;
91 long binary;
92
94 argc = scanargs(&scanned, argc, argv);
95 if (argc < 3) {
96 bomb(NULL, USAGE);
97 }
98
99 input = NULL;
100 output = NULL;
101 inputs = erase = binary = 0;
102
103 for (i_arg = 1; i_arg < argc; i_arg++) {
104 if (scanned[i_arg].arg_type == OPTION) {
105 /* Process options here */
106 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
107 case SET_ERASE:
108 erase = 1;
109 break;
110 case SET_OUTPUT:
111 if (scanned[i_arg].n_items != 2) {
112 bomb("Invalid syntax for -output option.", USAGE);
113 }
114 output = scanned[i_arg].list[1];
115 break;
116 case SET_BINARY:
117 if (scanned[i_arg].n_items != 1) {
118 bomb("Invalid syntax for -binary option.", USAGE);
119 }
120 binary = 1;
121 break;
122 default:
123 bomb("Unknown option provided.", USAGE);
124 }
125 } else {
126 input = trealloc(input, (inputs + 1) * sizeof(*input));
127 input[inputs++] = scanned[i_arg].list[0];
128 }
129 }
130
131 if (!output) {
132 bomb("The -output option must be specified.", USAGE);
133 }
134 if (!input) {
135 bomb("No input MPL files provided.", USAGE);
136 }
137
138 if (!erase && fexists(output)) {
139 /* Load data from existing file */
140 if (!SDDS_InitializeInput(&SDDS_dataset, output)) {
141 fprintf(stderr, "Error: Unable to read SDDS layout from %s.\n", output);
142 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
143 return EXIT_FAILURE;
144 }
145 if (!SDDS_ReadPage(&SDDS_dataset)) {
146 fprintf(stderr, "Error: Unable to read data table from %s.\n", output);
147 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
148 return EXIT_FAILURE;
149 }
150 SDDS_rows = SDDS_CountRowsOfInterest(&SDDS_dataset);
151 fclose(SDDS_dataset.layout.fp);
152 SDDS_dataset.layout.fp = fopen_e(output, "w", 0);
153 } else {
154 /* Start a new file */
155 if (!SDDS_InitializeOutput(&SDDS_dataset, binary ? SDDS_BINARY : SDDS_ASCII, 1, NULL, NULL, output)) {
156 fprintf(stderr, "Error: Unable to initialize output SDDS structure for %s.\n", output);
157 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
158 return EXIT_FAILURE;
159 }
160 SDDS_rows = -1;
161 }
162
163 rows = 0;
164 mpl_data = tmalloc(sizeof(*mpl_data) * inputs);
165 data = tmalloc(sizeof(*data) * (2 * inputs));
166 index = tmalloc(sizeof(*index) * (2 * inputs));
167 new_columns = 0;
168
169 for (i = 0; i < inputs; i++) {
170 if (!get_table(&mpl_data[i], input[i], 1, 0)) {
171 fprintf(stderr, "Warning: Unable to read data from %s. Continuing with other files.\n", input[i]);
172 continue;
173 }
174
175 if (!rows) {
176 if (!(rows = mpl_data[i].n_data)) {
177 fprintf(stderr, "Warning: No data in file %s. Continuing with other files.\n", input[i]);
178 continue;
179 }
180 } else if (rows != mpl_data[i].n_data) {
181 SDDS_Bomb("All MPL files must have the same number of data points.");
182 } else if (SDDS_rows != -1 && rows != SDDS_rows) {
183 SDDS_Bomb("Number of data points in MPL files must match the number of rows in the SDDS file.");
184 }
185
186 if ((index[new_columns] = add_definition(&SDDS_dataset, mpl_data[i].xlab, input[i])) < 0) {
187 free(mpl_data[i].c1);
188 } else {
189 data[new_columns++] = mpl_data[i].c1;
190 }
191
192 if ((index[new_columns] = add_definition(&SDDS_dataset, mpl_data[i].ylab, input[i])) < 0) {
193 free(mpl_data[i].c2);
194 } else {
195 data[new_columns++] = mpl_data[i].c2;
196 }
197 }
198
199 if (!rows || !new_columns) {
200 SDDS_Bomb("All input files are empty or invalid.");
201 }
202
203 if (!SDDS_WriteLayout(&SDDS_dataset)) {
204 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
205 return EXIT_FAILURE;
206 }
207 if (!SDDS_StartPage(&SDDS_dataset, rows)) {
208 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
209 return EXIT_FAILURE;
210 }
211
212 for (i = 0; i < new_columns; i++) {
213 for (j = 0; j < rows; j++) {
214 SDDS_SetRowValues(&SDDS_dataset, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, j, index[i], data[i][j], -1);
215 }
216 }
217
218 if (!SDDS_WritePage(&SDDS_dataset)) {
219 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
220 return EXIT_FAILURE;
221 }
222
223 return EXIT_SUCCESS;
224}
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
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_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 * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
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 fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
FILE * fopen_e(char *file, char *open_mode, long mode)
Opens a file with error checking, messages, and aborts.
Definition fopen_e.c:30
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 get_table(TABLE *tab, char *file, int64_t sample_interval, long flags)
Gets a table from a file in DPL format.
Definition table.c:45