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

Detailed Description

Performs kernel density estimation (KDE) for two-dimensional data using the SDDS library.

This program processes input data from an SDDS file, applies kernel density estimation to two selected columns, and outputs the resulting density estimates to a new SDDS file. It supports flexible options such as specifying columns, margins, and whether to use the same scales across data pages.

Usage

sddskde2d [<inputfile>] [<outputfile>]
[-pipe=[input][,output]]
-column=<column1,column2>
[-samescales]
[-margin=<value>]
[-threads=<number>]

Options

Required Description
-column Specify two column names for KDE, separated by a comma. Wildcards accepted.
Option Description
-pipe Utilize the standard SDDS Toolkit pipe option.
-samescales Use the same X and Y ranges for all output pages.
-margin Ratio to extend the original data range (default: 0.05).
-threads Set the number of threads for grid PDF evaluation.

Features

  • Reads input data from SDDS files and writes results in SDDS format.
  • Allows users to specify the columns for KDE using wildcards.
  • Handles margins and ensures proper scaling of the data.
  • Supports generating grids for density estimation.
  • Implements bandwidth selection and Gaussian kernel functions.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
Yipeng Sun, M. Borland, R. Soliday

Definition in file sddskde2d.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_x, double *trainingdata_y, double sample_x, double sample_y, int64_t n, double hx, double hy)
 
double * gridX (double start, double end, int N)
 
double * gridY (double start, double end, int N)
 
int main (int argc, char **argv)
 

Function Documentation

◆ bandwidth()

double bandwidth ( double data[],
int64_t M )

Definition at line 284 of file sddskde2d.c.

284 {
285 double sigma, bwidth, silver_factor;
286 sigma = gsl_stats_sd(data, 1, M);
287 silver_factor = pow(M, -0.16666666);
288 bwidth = pow(silver_factor, 2.0) * pow(sigma, 2.0);
289 return bwidth;
290}

◆ gaussiankernelfunction()

double gaussiankernelfunction ( double sample)

Definition at line 292 of file sddskde2d.c.

292 {
293 double k;
294 k = exp(-sample / 2.0);
295 k = k / (2.0 * M_PI);
296 return k;
297}

◆ gridX()

double * gridX ( double start,
double end,
int N )

Definition at line 315 of file sddskde2d.c.

315 {
316 double *x;
317 int i, j, n_grid;
318 double step;
319
320 n_grid = N * N;
321 x = (double *)calloc(n_grid, sizeof(double));
322 step = (end - start) / (double)(N - 1);
323
324 i = 0;
325 for (j = 0; j < N; j++) {
326 for (i = 0; i < N; i++) {
327 x[i + j * N] = start + i * step;
328 }
329 }
330 return x;
331}

◆ gridY()

double * gridY ( double start,
double end,
int N )

Definition at line 333 of file sddskde2d.c.

333 {
334 double *x;
335 int i, j, n_grid;
336 double step;
337
338 n_grid = N * N;
339 x = (double *)calloc(n_grid, sizeof(double));
340 step = (end - start) / (double)(N - 1);
341
342 i = 0;
343 for (j = 0; j < N; j++) {
344 for (i = 0; i < N; i++) {
345 x[i + j * N] = start + j * step;
346 }
347 }
348 return x;
349}

◆ kerneldensityestimate()

double kerneldensityestimate ( double * trainingdata_x,
double * trainingdata_y,
double sample_x,
double sample_y,
int64_t n,
double hx,
double hy )

Definition at line 299 of file sddskde2d.c.

301 {
302 int64_t i;
303 double pdf, z;
304
305 pdf = 0.0;
306 for (i = 0; i < n; i++) {
307 z = (trainingdata_x[i] - sample_x) * (trainingdata_x[i] - sample_x) / hx;
308 z += (trainingdata_y[i] - sample_y) * (trainingdata_y[i] - sample_y) / hy;
309 pdf += gaussiankernelfunction(z);
310 }
311 pdf = pdf / (n * sqrt(hx) * sqrt(hy));
312 return pdf;
313}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 104 of file sddskde2d.c.

104 {
105 int n_test, n_total, same_scales, threads;
106 double lowerx, upperx;
107 double lowery, uppery;
108 double margin = 0.05;
109 SDDS_DATASET SDDSin, SDDSout;
110 char *input_file, *output_file, **column;
111 long tmpfile_used = 0, columns, no_warnings = 1;
112 unsigned long pipe_flags;
113 long i, i_arg, j;
114 SCANNED_ARG *s_arg;
115 double **column_data_x, **column_data_y, *pdf;
116 int64_t *rows, rows0;
117 int32_t n_pages, i_page;
118
119 input_file = output_file = NULL;
120 pdf = NULL;
121 columns = 0;
122 column = NULL;
123 same_scales = 0;
124 threads = 1;
125
126 n_test = 50;
127 n_total = n_test * n_test;
128
130 argc = scanargs(&s_arg, argc, argv);
131 pipe_flags = 0;
132 tmpfile_used = 0;
133 if (argc < 2) {
134 fprintf(stderr, "%s", usage);
135 exit(1);
136 }
137 for (i_arg = 1; i_arg < argc; i_arg++) {
138 if (s_arg[i_arg].arg_type == OPTION) {
139 delete_chars(s_arg[i_arg].list[0], "_");
140 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
141 case SET_COLUMN:
142 columns = s_arg[i_arg].n_items - 1;
143 column = trealloc(column, sizeof(*column) * columns);
144 for (i = 1; i < s_arg[i_arg].n_items; i++)
145 column[i - 1] = s_arg[i_arg].list[i];
146 break;
147 case SET_MARGIN:
148 if (s_arg[i_arg].n_items != 2)
149 SDDS_Bomb("Invalid -margin option. Too many qualifiers.");
150 if (!get_double(&margin, s_arg[i_arg].list[1]))
151 SDDS_Bomb("Invalid -margin value provided.");
152 break;
153 case SET_SAME_SCALES:
154 if (s_arg[i_arg].n_items != 1)
155 SDDS_Bomb("Invalid -sameScales option. No qualifiers are accepted.");
156 same_scales = 1;
157 break;
158 case SET_THREADS:
159 if (s_arg[i_arg].n_items != 2 ||
160 sscanf(s_arg[i_arg].list[1], "%d", &threads) != 1 || threads < 1)
161 SDDS_Bomb("invalid -threads syntax");
162 break;
163 case SET_PIPE:
164 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags)) {
165 fprintf(stderr, "Error (%s): invalid -pipe syntax\n", argv[0]);
166 return 1;
167 }
168 break;
169 }
170 } else {
171 if (!input_file)
172 input_file = s_arg[i_arg].list[0];
173 else if (output_file == NULL)
174 output_file = s_arg[i_arg].list[0];
175 else {
176 fprintf(stderr, "Error (%s): too many filenames\n", argv[0]);
177 return 1;
178 }
179 }
180 }
181 processFilenames("sddskde2d", &input_file, &output_file, pipe_flags, no_warnings, &tmpfile_used);
182 if (!columns) {
183 fprintf(stderr, "%s", usage);
184 SDDS_Bomb("No column provided!");
185 }
186 if (!SDDS_InitializeInput(&SDDSin, input_file)) {
187 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
188 return 1;
189 }
190 if ((columns = expandColumnPairNames(&SDDSin, &column, NULL, columns, NULL, 0, FIND_NUMERIC_TYPE, 0)) <= 0) {
191 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
192 SDDS_Bomb("no columns selected.");
193 }
194 if (columns > 2) {
195 fprintf(stderr, "%s", usage);
196 SDDS_Bomb("Only 2 columns may be accepted.");
197 }
198 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 1, NULL, NULL, output_file))
199 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
200 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, column[0], NULL) ||
201 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, column[1], NULL) ||
202 SDDS_DefineColumn(&SDDSout, "PDF", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0)
203 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
204 if (!SDDS_WriteLayout(&SDDSout))
205 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
206
207 /* Read all the data in case we need to use fixed scales */
208 n_pages = 0;
209 column_data_x = NULL;
210 column_data_y = NULL;
211 rows = NULL;
212 while (SDDS_ReadPage(&SDDSin) >= 0) {
213 if ((rows0 = SDDS_CountRowsOfInterest(&SDDSin))) {
214 column_data_x = (double **)SDDS_Realloc(column_data_x, sizeof(*column_data_x) * (n_pages + 1));
215 column_data_y = (double **)SDDS_Realloc(column_data_y, sizeof(*column_data_y) * (n_pages + 1));
216 rows = (int64_t *)SDDS_Realloc(rows, sizeof(*rows) * (n_pages + 1));
217 rows[n_pages] = rows0;
218 if (!(column_data_x[n_pages] = SDDS_GetColumnInDoubles(&SDDSin, column[0])))
219 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
220 if (!(column_data_y[n_pages] = SDDS_GetColumnInDoubles(&SDDSin, column[1])))
221 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
222 n_pages++;
223 }
224 }
225 if (n_pages == 0)
226 SDDS_Bomb("No data in file");
227
228 if (same_scales) {
229 double llx, lly, uux, uuy;
230 lowerx = lowery = DBL_MAX;
231 upperx = uppery = -DBL_MAX;
232 for (i_page = 0; i_page < n_pages; i_page++) {
233 find_min_max(&llx, &uux, column_data_x[i_page], rows[i_page]);
234 lowerx = MIN(llx, lowerx);
235 upperx = MAX(uux, upperx);
236 find_min_max(&lly, &uuy, column_data_y[i_page], rows[i_page]);
237 lowery = MIN(lly, lowery);
238 uppery = MAX(uuy, uppery);
239 }
240 }
241
242 pdf = malloc(sizeof(*pdf) * n_total);
243 for (i_page = 0; i_page < n_pages; i_page++) {
244 if (!SDDS_StartPage(&SDDSout, n_total))
245 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
246 if (!same_scales) {
247 find_min_max(&lowerx, &upperx, column_data_x[i_page], rows[i_page]);
248 find_min_max(&lowery, &uppery, column_data_y[i_page], rows[i_page]);
249 }
250 double *x_array = gridX(lowerx, upperx, n_test);
251 double *y_array = gridY(lowery, uppery, n_test);
252 double hx = bandwidth(column_data_x[i_page], rows[i_page]);
253 double hy = bandwidth(column_data_y[i_page], rows[i_page]);
254#pragma omp parallel for if (threads > 1) num_threads(threads)
255 for (j = 0; j < n_total; j++) {
256 pdf[j] = kerneldensityestimate(column_data_x[i_page], column_data_y[i_page], x_array[j], y_array[j], rows[i_page], hx, hy);
257 }
258 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, x_array, n_total, column[0]))
259 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
260 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, y_array, n_total, column[1]))
261 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
262 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, pdf, n_total, "PDF"))
263 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
264 free(column_data_x[i_page]);
265 free(column_data_y[i_page]);
266 free(x_array);
267 free(y_array);
268 if (!SDDS_WritePage(&SDDSout))
269 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
270 }
271 free(pdf);
272 free(column_data_x);
273 free(column_data_y);
274 free(rows);
275 if (!SDDS_Terminate(&SDDSin) || !SDDS_Terminate(&SDDSout))
276 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
277 if (tmpfile_used && !replaceFileAndBackUp(input_file, output_file)) {
278 return 1;
279 }
280 free(column);
281 return 0;
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_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
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:190
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