SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddskde.c File Reference

Detailed Description

Kernel Density Estimation for SDDS Data.

This program performs Kernel Density Estimation (KDE) for one-dimensional data read from an SDDS file. It computes probability density functions (PDFs) and cumulative distribution functions (CDFs) for the specified columns and writes the results to an SDDS output file. It uses Gaussian kernel functions for KDE calculations and supports options for selecting columns and customizing the margin for data extension.

Usage

sddskde [<inputfile>] [<outputfile>]
[-pipe=[input][,output]]
-column=<list of columns>
[-margin=<value>]
[-threads=<number>]

Options

Required Description
-column Specifies the columns for KDE calculations. Comma-separated and supports wildcards.
Optional Description
-pipe Enable SDDS Toolkit piping for input/output.
-margin Set the margin as a ratio to extend data range (default 0.3).
-threads Set the number of threads for PDF sample evaluation.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
Yipeng Sun, H. Shang, M. Borland, R. Soliday

Definition in file sddskde.c.

#include <math.h>
#include <gsl/gsl_statistics.h>
#include <gsl/gsl_sort.h>
#include <gsl/gsl_math.h>
#include "SDDS.h"
#include "mdb.h"
#include "scan.h"
#include "SDDSutils.h"

Go to the source code of this file.

Functions

double bandwidth (double data[], int64_t M)
 
double gaussiankernelfunction (double sample)
 
double kerneldensityestimate (double *trainingdata, double sample, int64_t n, double h)
 
double * linearspace (double initial, double final, int N)
 
int main (int argc, char **argv)
 

Function Documentation

◆ bandwidth()

double bandwidth ( double data[],
int64_t M )

Definition at line 284 of file sddskde.c.

284 {
285 double sigma, min_val, bwidth, interquartile_range;
286 double hspread_three, hspread_one;
287
288 gsl_sort(data, 1, M);
289 sigma = gsl_stats_sd(data, 1, M);
290 hspread_three = gsl_stats_quantile_from_sorted_data(data, 1, M, 0.750);
291 hspread_one = gsl_stats_quantile_from_sorted_data(data, 1, M, 0.250);
292 interquartile_range = hspread_three - hspread_one;
293 min_val = GSL_MIN(interquartile_range / 1.339999, sigma);
294 bwidth = 0.90 * min_val * pow(M, -0.20);
295
296 return bwidth;
297}

◆ gaussiankernelfunction()

double gaussiankernelfunction ( double sample)

Definition at line 299 of file sddskde.c.

299 {
300 double k;
301 k = exp(-(gsl_pow_2(sample) / 2.0));
302 k = k / (M_SQRT2 * sqrt(M_PI));
303
304 return k;
305}

◆ kerneldensityestimate()

double kerneldensityestimate ( double * trainingdata,
double sample,
int64_t n,
double h )

Definition at line 307 of file sddskde.c.

307 {
308 int64_t i;
309 double pdf = 0.0;
310
311 for (i = 0; i < n; i++) {
312 pdf += gaussiankernelfunction((trainingdata[i] - sample) / h);
313 }
314
315 pdf = pdf / (n * h);
316
317 return pdf;
318}

◆ linearspace()

double * linearspace ( double initial,
double final,
int N )

Definition at line 320 of file sddskde.c.

320 {
321 double *x;
322 int i;
323 double step;
324
325 x = calloc(N, sizeof(double));
326 step = (end - start) / (double)(N - 1);
327
328 x[0] = start;
329 for (i = 1; i < N; i++) {
330 x[i] = x[i - 1] + step;
331 }
332 x[N - 1] = end;
333
334 return x;
335}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 88 of file sddskde.c.

88 {
89 int n_test = 100;
90 double min_temp, max_temp;
91 double bwidth, gap, h, lower, upper;
92 double margin = 0.3;
93 SDDS_DATASET sdds_in, sdds_out;
94 char *input_file = NULL, *output_file = NULL, **column = NULL;
95 long tmpfile_used = 0, columns = 0, no_warnings = 1;
96 unsigned long pipe_flags;
97 long i, i_arg, j;
98 SCANNED_ARG *s_arg;
99 double *column_data = NULL, *pdf = NULL, *cdf = NULL;
100 char buffer_pdf[1024], buffer_cdf[1024], buffer_pdf_units[1024];
101 int64_t rows;
102 int threads = 1;
103
105 argc = scanargs(&s_arg, argc, argv);
106 pipe_flags = 0;
107
108 if (argc < 2) {
109 fprintf(stderr, "%s", usage);
110 exit(EXIT_FAILURE);
111 }
112
113 for (i_arg = 1; i_arg < argc; i_arg++) {
114 if (s_arg[i_arg].arg_type == OPTION) {
115 delete_chars(s_arg[i_arg].list[0], "_");
116 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
117 case SET_COLUMN:
118 columns = s_arg[i_arg].n_items - 1;
119 column = realloc(column, sizeof(*column) * columns);
120 for (i = 1; i < s_arg[i_arg].n_items; i++) {
121 column[i - 1] = s_arg[i_arg].list[i];
122 }
123 break;
124 case SET_MARGIN:
125 if (s_arg[i_arg].n_items != 2) {
126 SDDS_Bomb("Invalid -margin option!");
127 }
128 if (!get_double(&margin, s_arg[i_arg].list[1])) {
129 SDDS_Bomb("Invalid -margin value provided!");
130 }
131 break;
132 case SET_THREADS:
133 if (s_arg[i_arg].n_items != 2 ||
134 sscanf(s_arg[i_arg].list[1], "%d", &threads) != 1 || threads < 1) {
135 SDDS_Bomb("invalid -threads syntax");
136 }
137 break;
138 case SET_PIPE:
139 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags)) {
140 fprintf(stderr, "Error (%s): invalid -pipe syntax\n", argv[0]);
141 return EXIT_FAILURE;
142 }
143 break;
144 default:
145 fprintf(stderr, "Unknown option: %s\n", s_arg[i_arg].list[0]);
146 exit(EXIT_FAILURE);
147 }
148 } else {
149 if (!input_file) {
150 input_file = s_arg[i_arg].list[0];
151 } else if (!output_file) {
152 output_file = s_arg[i_arg].list[0];
153 } else {
154 fprintf(stderr, "Error (%s): too many filenames\n", argv[0]);
155 return EXIT_FAILURE;
156 }
157 }
158 }
159
160 processFilenames("sddskde", &input_file, &output_file, pipe_flags, no_warnings, &tmpfile_used);
161
162 if (!columns) {
163 fprintf(stderr, "%s", usage);
164 SDDS_Bomb("No column provided!");
165 }
166
167 if (!SDDS_InitializeInput(&sdds_in, input_file)) {
168 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
169 return EXIT_FAILURE;
170 }
171
172 if ((columns = expandColumnPairNames(&sdds_in, &column, NULL, columns, NULL, 0, FIND_NUMERIC_TYPE, 0)) <= 0) {
173 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
174 SDDS_Bomb("No columns selected.");
175 }
176
177 if (!SDDS_InitializeOutput(&sdds_out, SDDS_BINARY, 1, NULL, NULL, output_file)) {
178 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
179 }
180
181 for (i = 0; i < columns; i++) {
182 char *units = NULL;
183 if (SDDS_GetColumnInformation(&sdds_in, "units", &units, SDDS_GET_BY_NAME, column[i]) != SDDS_STRING) {
184 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
185 }
186
187 if (units && strlen(units)) {
188 snprintf(buffer_pdf_units, sizeof(buffer_pdf_units), "1/(%s)", units);
189 } else {
190 buffer_pdf_units[0] = '\0';
191 }
192
193 free(units);
194
195 snprintf(buffer_pdf, sizeof(buffer_pdf), "%sPDF", column[i]);
196 snprintf(buffer_cdf, sizeof(buffer_cdf), "%sCDF", column[i]);
197
198 if (!SDDS_TransferColumnDefinition(&sdds_out, &sdds_in, column[i], NULL) ||
199 SDDS_DefineColumn(&sdds_out, buffer_pdf, NULL, buffer_pdf_units, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
200 SDDS_DefineColumn(&sdds_out, buffer_cdf, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0) {
201 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
202 }
203 }
204
205 if (!SDDS_WriteLayout(&sdds_out)) {
206 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
207 }
208
209 pdf = malloc(sizeof(*pdf) * n_test);
210 cdf = malloc(sizeof(*cdf) * n_test);
211
212 while (SDDS_ReadPage(&sdds_in) >= 0) {
213 if ((rows = SDDS_CountRowsOfInterest(&sdds_in))) {
214 if (!SDDS_StartPage(&sdds_out, n_test)) {
215 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
216 }
217
218 for (i = 0; i < columns; i++) {
219 snprintf(buffer_pdf, sizeof(buffer_pdf), "%sPDF", column[i]);
220 snprintf(buffer_cdf, sizeof(buffer_cdf), "%sCDF", column[i]);
221
222 if (!(column_data = SDDS_GetColumnInDoubles(&sdds_in, column[i]))) {
223 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
224 }
225
226 find_min_max(&min_temp, &max_temp, column_data, rows);
227 gap = max_temp - min_temp;
228 lower = min_temp - gap * margin;
229 upper = max_temp + gap * margin;
230
231 double *x_array = linearspace(lower, upper, n_test);
232 bwidth = bandwidth(column_data, rows);
233 h = GSL_MAX(bwidth, 2e-6);
234
235#pragma omp parallel for if (threads > 1) num_threads(threads)
236 for (j = 0; j < n_test; j++) {
237 pdf[j] = kerneldensityestimate(column_data, x_array[j], rows, h);
238 cdf[j] = pdf[j];
239 }
240
241 for (j = 1; j < n_test; j++) {
242 cdf[j] += cdf[j - 1];
243 }
244
245 for (j = 0; j < n_test; j++) {
246 cdf[j] = cdf[j] / cdf[n_test - 1];
247 }
248
249 if (!SDDS_SetColumnFromDoubles(&sdds_out, SDDS_SET_BY_NAME, pdf, n_test, buffer_pdf) ||
250 !SDDS_SetColumnFromDoubles(&sdds_out, SDDS_SET_BY_NAME, cdf, n_test, buffer_cdf) ||
251 !SDDS_SetColumnFromDoubles(&sdds_out, SDDS_SET_BY_NAME, x_array, n_test, column[i])) {
252 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
253 }
254
255 free(column_data);
256 column_data = NULL;
257
258 free(x_array);
259 x_array = NULL;
260 }
261 }
262
263 if (!SDDS_WritePage(&sdds_out)) {
264 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
265 }
266 }
267
268 free(pdf);
269 free(cdf);
270
271 if (!SDDS_Terminate(&sdds_in) || !SDDS_Terminate(&sdds_out)) {
272 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
273 }
274
275 if (tmpfile_used && !replaceFileAndBackUp(input_file, output_file)) {
276 return EXIT_FAILURE;
277 }
278
279 free(column);
280
281 return EXIT_SUCCESS;
282}
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_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
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_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_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:474
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
int get_double(double *dptr, char *s)
Parses a double value from the given string.
Definition data_scan.c:40
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
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.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:78
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:357
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:391