51#include <gsl/gsl_statistics.h>
52#include <gsl/gsl_sort.h>
53#include <gsl/gsl_math.h>
59double bandwidth(
double data[], int64_t M);
60double gaussiankernelfunction(
double sample);
61double kerneldensityestimate(
double *trainingdata_x,
double *trainingdata_y,
62 double sample_x,
double sample_y, int64_t n);
63double *gridX(
double start,
double end,
int N);
64double *gridY(
double start,
double end,
int N);
75char *option[N_OPTIONS] = {
82 "Usage: sddskde2d [<inputfile>] [<outputfile>] \n"
83 " [-pipe=[input][,output]] \n"
84 " -column=<column1,column2> \n"
86 " [-margin=<value>]\n\n"
88 " -column Specify two column names separated by a comma. Wildcards are accepted.\n"
89 " -margin Ratio to extend the original data (default: 0.05).\n"
90 " -samescales Use the same X and Y ranges for all output pages.\n"
91 " -pipe Utilize the standard SDDS Toolkit pipe option.\n\n"
93 " sddskde2d performs kernel density estimation for two-dimensional data.\n\n"
95 " Yipeng Sun (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
97int main(
int argc,
char **argv) {
98 int n_test, n_total, same_scales;
99 double lowerx, upperx;
100 double lowery, uppery;
101 double margin = 0.05;
103 char *input_file, *output_file, **column;
104 long tmpfile_used = 0, columns, no_warnings = 1;
105 unsigned long pipe_flags;
108 double **column_data_x, **column_data_y, *pdf;
109 int64_t *rows, rows0;
110 int32_t n_pages, i_page;
112 input_file = output_file = NULL;
119 n_total = n_test * n_test;
122 argc =
scanargs(&s_arg, argc, argv);
126 fprintf(stderr,
"%s", usage);
129 for (i_arg = 1; i_arg < argc; i_arg++) {
130 if (s_arg[i_arg].arg_type == OPTION) {
132 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
134 columns = s_arg[i_arg].n_items - 1;
135 column =
trealloc(column,
sizeof(*column) * columns);
136 for (i = 1; i < s_arg[i_arg].n_items; i++)
137 column[i - 1] = s_arg[i_arg].list[i];
140 if (s_arg[i_arg].n_items != 2)
141 SDDS_Bomb(
"Invalid -margin option. Too many qualifiers.");
142 if (!
get_double(&margin, s_arg[i_arg].list[1]))
143 SDDS_Bomb(
"Invalid -margin value provided.");
145 case SET_SAME_SCALES:
146 if (s_arg[i_arg].n_items != 1)
147 SDDS_Bomb(
"Invalid -sameScales option. No qualifiers are accepted.");
151 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags)) {
152 fprintf(stderr,
"Error (%s): invalid -pipe syntax\n", argv[0]);
159 input_file = s_arg[i_arg].list[0];
160 else if (output_file == NULL)
161 output_file = s_arg[i_arg].list[0];
163 fprintf(stderr,
"Error (%s): too many filenames\n", argv[0]);
168 processFilenames(
"sddskde2d", &input_file, &output_file, pipe_flags, no_warnings, &tmpfile_used);
170 fprintf(stderr,
"%s", usage);
177 if ((columns = expandColumnPairNames(&SDDSin, &column, NULL, columns, NULL, 0, FIND_NUMERIC_TYPE, 0)) <= 0) {
182 fprintf(stderr,
"%s", usage);
183 SDDS_Bomb(
"Only 2 columns may be accepted.");
196 column_data_x = NULL;
197 column_data_y = NULL;
201 column_data_x = (
double **)
SDDS_Realloc(column_data_x,
sizeof(*column_data_x) * (n_pages + 1));
202 column_data_y = (
double **)
SDDS_Realloc(column_data_y,
sizeof(*column_data_y) * (n_pages + 1));
203 rows = (int64_t *)
SDDS_Realloc(rows,
sizeof(*rows) * (n_pages + 1));
204 rows[n_pages] = rows0;
216 double llx, lly, uux, uuy;
217 lowerx = lowery = DBL_MAX;
218 upperx = uppery = -DBL_MAX;
219 for (i_page = 0; i_page < n_pages; i_page++) {
220 find_min_max(&llx, &uux, column_data_x[i_page], rows[i_page]);
221 lowerx = MIN(llx, lowerx);
222 upperx = MAX(uux, upperx);
223 find_min_max(&lly, &uuy, column_data_y[i_page], rows[i_page]);
224 lowery = MIN(lly, lowery);
225 uppery = MAX(uuy, uppery);
229 pdf = malloc(
sizeof(*pdf) * n_total);
230 for (i_page = 0; i_page < n_pages; i_page++) {
234 find_min_max(&lowerx, &upperx, column_data_x[i_page], rows[i_page]);
235 find_min_max(&lowery, &uppery, column_data_y[i_page], rows[i_page]);
237 double *x_array = gridX(lowerx, upperx, n_test);
238 double *y_array = gridY(lowery, uppery, n_test);
239 for (j = 0; j < n_total; j++) {
240 pdf[j] = kerneldensityestimate(column_data_x[i_page], column_data_y[i_page], x_array[j], y_array[j], rows[i_page]);
248 free(column_data_x[i_page]);
249 free(column_data_y[i_page]);
268double bandwidth(
double data[], int64_t M) {
269 double sigma, bwidth, silver_factor;
270 sigma = gsl_stats_sd(data, 1, M);
271 silver_factor = pow(M, -0.16666666);
272 bwidth = pow(silver_factor, 2.0) * pow(sigma, 2.0);
276double gaussiankernelfunction(
double sample) {
278 k = exp(-sample / 2.0);
279 k = k / (2.0 * M_PI);
283double kerneldensityestimate(
double *trainingdata_x,
double *trainingdata_y,
284 double sample_x,
double sample_y, int64_t n) {
286 double pdf, hx, hy, z;
288 hx = bandwidth(trainingdata_x, n);
289 hy = bandwidth(trainingdata_y, n);
291 for (i = 0; i < n; i++) {
292 z = (trainingdata_x[i] - sample_x) * (trainingdata_x[i] - sample_x) / hx;
293 z += (trainingdata_y[i] - sample_y) * (trainingdata_y[i] - sample_y) / hy;
294 pdf += gaussiankernelfunction(z);
296 pdf = pdf / (n * sqrt(hx) * sqrt(hy));
300double *gridX(
double start,
double end,
int N) {
306 x = (
double *)calloc(n_grid,
sizeof(
double));
307 step = (end - start) / (
double)(N - 1);
310 for (j = 0; j < N; j++) {
311 for (i = 0; i < N; i++) {
312 x[i + j * N] = start + i * step;
318double *gridY(
double start,
double end,
int N) {
324 x = (
double *)calloc(n_grid,
sizeof(
double));
325 step = (end - start) / (
double)(N - 1);
328 for (j = 0; j < N; j++) {
329 for (i = 0; i < N; i++) {
330 x[i + j * N] = start + j * step;
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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.
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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_DOUBLE
Identifier for the double data type.
Utility functions for SDDS dataset manipulation and string array operations.
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
int get_double(double *dptr, char *s)
Parses a double value from the given string.
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.
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)