2
/**********************************************************************
6
* AUTHOR(S): Roberto Antolin
8
* PURPOSE: Removal of data outliers
10
* COPYRIGHT: (C) 2006 by Politecnico di Milano -
11
* Polo Regionale di Como
13
* This program is free software under the
14
* GNU General Public License (>=v2).
15
* Read the file COPYING that comes with GRASS
18
**********************************************************************/
26
/* GLOBAL VARIABLES */
28
double stepN, stepE, Thres_Outlier;
30
/*--------------------------------------------------------------------*/
31
int main(int argc, char *argv[])
33
/* Variables declarations */
34
int nsplx_adj, nsply_adj;
35
int nsubregion_col, nsubregion_row;
36
int subregion = 0, nsubregions = 0;
37
double N_extension, E_extension, edgeE, edgeN;
38
int dim_vect, nparameters, BW, npoints;
40
const char *dvr, *db, *mapset;
41
char table_name[GNAME_MAX];
42
char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
44
int last_row, last_column, flag_auxiliar = FALSE;
48
double *TN, *Q, *parVect; /* Interpolating and least-square vectors */
49
double **N, **obsVect; /* Interpolation and least-square matrix */
51
/* Structs declarations */
52
struct Map_info In, Out, Outlier, Qgis;
53
struct Option *in_opt, *out_opt, *outlier_opt, *qgis_opt, *stepE_opt,
54
*stepN_opt, *lambda_f_opt, *Thres_O_opt, *filter_opt;
55
struct Flag *spline_step_flag;
56
struct GModule *module;
58
struct Reg_dimens dims;
59
struct Cell_head elaboration_reg, original_reg;
60
struct bound_box general_box, overlap_box;
66
/*----------------------------------------------------------------*/
67
/* Options declaration */
68
module = G_define_module();
69
G_add_keyword(_("vector"));
70
G_add_keyword(_("statistics"));
71
module->description = _("Removes outliers from vector point data.");
73
spline_step_flag = G_define_flag();
74
spline_step_flag->key = 'e';
75
spline_step_flag->label = _("Estimate point density and distance");
76
spline_step_flag->description =
77
_("Estimate point density and distance for the input vector points within the current region extends and quit");
79
in_opt = G_define_standard_option(G_OPT_V_INPUT);
81
out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
83
outlier_opt = G_define_option();
84
outlier_opt->key = "outlier";
85
outlier_opt->type = TYPE_STRING;
86
outlier_opt->key_desc = "name";
87
outlier_opt->required = YES;
88
outlier_opt->gisprompt = "new,vector,vector";
89
outlier_opt->description = _("Name of output outlier vector map");
91
qgis_opt = G_define_option();
92
qgis_opt->key = "qgis";
93
qgis_opt->type = TYPE_STRING;
94
qgis_opt->key_desc = "name";
95
qgis_opt->required = NO;
96
qgis_opt->gisprompt = "new,vector,vector";
97
qgis_opt->description = _("Name of vector map for visualization in QGIS");
99
stepE_opt = G_define_option();
100
stepE_opt->key = "ew_step";
101
stepE_opt->type = TYPE_DOUBLE;
102
stepE_opt->required = NO;
103
stepE_opt->answer = "10";
104
stepE_opt->description =
105
_("Length of each spline step in the east-west direction");
106
stepE_opt->guisection = _("Settings");
108
stepN_opt = G_define_option();
109
stepN_opt->key = "ns_step";
110
stepN_opt->type = TYPE_DOUBLE;
111
stepN_opt->required = NO;
112
stepN_opt->answer = "10";
113
stepN_opt->description =
114
_("Length of each spline step in the north-south direction");
115
stepN_opt->guisection = _("Settings");
117
lambda_f_opt = G_define_option();
118
lambda_f_opt->key = "lambda";
119
lambda_f_opt->type = TYPE_DOUBLE;
120
lambda_f_opt->required = NO;
121
lambda_f_opt->description = _("Tykhonov regularization weight");
122
lambda_f_opt->answer = "0.1";
123
lambda_f_opt->guisection = _("Settings");
125
Thres_O_opt = G_define_option();
126
Thres_O_opt->key = "threshold";
127
Thres_O_opt->type = TYPE_DOUBLE;
128
Thres_O_opt->required = NO;
129
Thres_O_opt->description = _("Threshold for the outliers");
130
Thres_O_opt->answer = "50";
132
filter_opt = G_define_option();
133
filter_opt->key = "filter";
134
filter_opt->type = TYPE_STRING;
135
filter_opt->required = NO;
136
filter_opt->description = _("Filtering option");
137
filter_opt->options = "both,positive,negative";
138
filter_opt->answer = "both";
142
if (G_parser(argc, argv))
145
if (!(db = G_getenv_nofatal2("DB_DATABASE", G_VAR_MAPSET)))
146
G_fatal_error(_("Unable to read name of database"));
148
if (!(dvr = G_getenv_nofatal2("DB_DRIVER", G_VAR_MAPSET)))
149
G_fatal_error(_("Unable to read name of driver"));
151
stepN = atof(stepN_opt->answer);
152
stepE = atof(stepE_opt->answer);
153
lambda = atof(lambda_f_opt->answer);
154
Thres_Outlier = atof(Thres_O_opt->answer);
157
if (strcmp(filter_opt->answer, "positive") == 0)
159
else if (strcmp(filter_opt->answer, "negative") == 0)
161
P_set_outlier_fn(filter_mode);
163
flag_auxiliar = FALSE;
165
/* Checking vector names */
166
Vect_check_input_output_name(in_opt->answer, out_opt->answer,
169
if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL) {
170
G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);
173
/* Setting auxiliar table's name */
174
if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) {
175
sprintf(table_name, "%s_aux", xname);
178
sprintf(table_name, "%s_aux", out_opt->answer);
180
/* Something went wrong in a previous v.outlier execution */
181
if (db_table_exists(dvr, db, table_name)) {
182
/* Start driver and open db */
183
driver = db_start_driver_open_database(dvr, db);
185
G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
187
db_set_error_handler_driver(driver);
189
if (P_Drop_Aux_Table(driver, table_name) != DB_OK)
190
G_fatal_error(_("Old auxiliar table could not be dropped"));
191
db_close_database_shutdown_driver(driver);
194
/* Open input vector */
195
Vect_set_open_level(1); /* WITHOUT TOPOLOGY */
196
if (1 > Vect_open_old(&In, in_opt->answer, mapset))
197
G_fatal_error(_("Unable to open vector map <%s> at the topological level"),
200
/* Input vector must be 3D */
201
if (!Vect_is_3d(&In))
202
G_fatal_error(_("Input vector map <%s> is not 3D!"), in_opt->answer);
204
/* Estimate point density and mean distance for current region */
205
if (spline_step_flag->answer) {
207
if (P_estimate_splinestep(&In, &dens, &dist) == 0) {
208
G_message("Estimated point density: %.4g", dens);
209
G_message("Estimated mean distance between points: %.4g", dist);
212
G_warning(_("No points in current region!"));
218
/* Open output vector */
219
if (qgis_opt->answer)
220
if (0 > Vect_open_new(&Qgis, qgis_opt->answer, WITHOUT_Z))
221
G_fatal_error(_("Unable to create vector map <%s>"),
224
if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z)) {
226
G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
229
if (0 > Vect_open_new(&Outlier, outlier_opt->answer, WITH_Z)) {
232
G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
235
/* Copy vector Head File */
236
Vect_copy_head_data(&In, &Out);
237
Vect_hist_copy(&In, &Out);
238
Vect_hist_command(&Out);
240
Vect_copy_head_data(&In, &Outlier);
241
Vect_hist_copy(&In, &Outlier);
242
Vect_hist_command(&Outlier);
244
if (qgis_opt->answer) {
245
Vect_copy_head_data(&In, &Qgis);
246
Vect_hist_copy(&In, &Qgis);
247
Vect_hist_command(&Qgis);
250
/* Open driver and database */
251
driver = db_start_driver_open_database(dvr, db);
253
G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
255
db_set_error_handler_driver(driver);
257
/* Create auxiliar table */
259
P_Create_Aux2_Table(driver, table_name)) == FALSE)
260
G_fatal_error(_("It was impossible to create <%s> table."), table_name);
262
db_create_index2(driver, table_name, "ID");
263
/* sqlite likes that ??? */
264
db_close_database_shutdown_driver(driver);
265
driver = db_start_driver_open_database(dvr, db);
267
/* Setting regions and boxes */
268
G_get_set_window(&original_reg);
269
G_get_set_window(&elaboration_reg);
270
Vect_region_box(&elaboration_reg, &overlap_box);
271
Vect_region_box(&elaboration_reg, &general_box);
273
/*------------------------------------------------------------------
274
| Subdividing and working with tiles:
275
| Each original region will be divided into several subregions.
276
| Each one will be overlaped by its neighbouring subregions.
277
| The overlapping is calculated as a fixed OVERLAP_SIZE times
278
| the largest spline step plus 2 * edge
279
----------------------------------------------------------------*/
281
/* Fixing parameters of the elaboration region */
282
P_zero_dim(&dims); /* Set dim struct to zero */
284
nsplx_adj = NSPLX_MAX;
285
nsply_adj = NSPLY_MAX;
287
dims.overlap = OVERLAP_SIZE * stepN;
289
dims.overlap = OVERLAP_SIZE * stepE;
290
P_get_edge(P_BILINEAR, &dims, stepE, stepN);
291
P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj);
293
G_verbose_message(_("Adjusted EW splines %d"), nsplx_adj);
294
G_verbose_message(_("Adjusted NS splines %d"), nsply_adj);
296
/* calculate number of subregions */
297
edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v;
298
edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h;
300
N_extension = original_reg.north - original_reg.south;
301
E_extension = original_reg.east - original_reg.west;
303
nsubregion_col = ceil(E_extension / edgeE) + 0.5;
304
nsubregion_row = ceil(N_extension / edgeN) + 0.5;
306
if (nsubregion_col < 0)
308
if (nsubregion_row < 0)
311
nsubregions = nsubregion_row * nsubregion_col;
313
elaboration_reg.south = original_reg.north;
316
while (last_row == FALSE) { /* For each row */
318
P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
321
if (elaboration_reg.north > original_reg.north) { /* First row */
323
P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
327
if (elaboration_reg.south <= original_reg.south) { /* Last row */
329
P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
335
ceil((elaboration_reg.north -
336
elaboration_reg.south) / stepN) + 0.5;
338
if (nsply > NSPLY_MAX)
341
G_debug(1, "nsply = %d", nsply);
343
elaboration_reg.east = original_reg.west;
346
while (last_column == FALSE) { /* For each column */
350
G_message(_("Processing subregion %d of %d..."), subregion, nsubregions);
351
else /* v.outlier -e will report mean point distance: */
352
G_warning(_("No subregions found! Check values for 'ew_step' and 'ns_step' parameters"));
354
P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
357
if (elaboration_reg.west < original_reg.west) { /* First column */
359
P_set_regions(&elaboration_reg, &general_box, &overlap_box,
363
if (elaboration_reg.east >= original_reg.east) { /* Last column */
365
P_set_regions(&elaboration_reg, &general_box, &overlap_box,
370
ceil((elaboration_reg.east -
371
elaboration_reg.west) / stepE) + 0.5;
373
if (nsplx > NSPLX_MAX)
376
G_debug(1, "nsplx = %d", nsplx);
378
/*Setting the active region */
379
dim_vect = nsplx * nsply;
381
P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints,
384
if (npoints > 0) { /* If there is any point falling into elaboration_reg... */
387
nparameters = nsplx * nsply;
389
/* Mean calculation */
390
mean = P_Mean_Calc(&elaboration_reg, observ, npoints);
392
/* Least Squares system */
393
G_debug(1, "Allocation memory for bilinear interpolation");
394
BW = P_get_BandWidth(P_BILINEAR, nsply); /* Bilinear interpolation */
395
N = G_alloc_matrix(nparameters, BW); /* Normal matrix */
396
TN = G_alloc_vector(nparameters); /* vector */
397
parVect = G_alloc_vector(nparameters); /* Bicubic parameters vector */
398
obsVect = G_alloc_matrix(npoints, 3); /* Observation vector */
399
Q = G_alloc_vector(npoints); /* "a priori" var-cov matrix */
400
lineVect = G_alloc_ivector(npoints);
402
/* Setting obsVect vector & Q matrix */
403
for (i = 0; i < npoints; i++) {
404
obsVect[i][0] = observ[i].coordX;
405
obsVect[i][1] = observ[i].coordY;
406
obsVect[i][2] = observ[i].coordZ - mean;
407
lineVect[i] = observ[i].lineID;
413
G_verbose_message(_("Bilinear interpolation"));
414
normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx,
415
nsply, elaboration_reg.west,
416
elaboration_reg.south, npoints, nparameters,
418
nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN);
419
G_math_solver_cholesky_sband(N, parVect, TN, nparameters, BW);
425
G_verbose_message(_("Outlier detection"));
426
if (qgis_opt->answer)
427
P_Outlier(&Out, &Outlier, &Qgis, elaboration_reg,
428
general_box, overlap_box, obsVect, parVect,
429
mean, dims.overlap, lineVect, npoints,
432
P_Outlier(&Out, &Outlier, NULL, elaboration_reg,
433
general_box, overlap_box, obsVect, parVect,
434
mean, dims.overlap, lineVect, npoints,
438
G_free_vector(parVect);
439
G_free_matrix(obsVect);
440
G_free_ivector(lineVect);
442
} /*! END IF; npoints > 0 */
445
G_warning(_("No data within this subregion. "
446
"Consider increasing spline step values."));
448
} /*! END WHILE; last_column = TRUE */
449
} /*! END WHILE; last_row = TRUE */
451
/* Drop auxiliar table */
453
G_debug(1, "%s: Dropping <%s>", argv[0], table_name);
454
if (P_Drop_Aux_Table(driver, table_name) != DB_OK)
455
G_fatal_error(_("Auxiliary table could not be dropped"));
458
db_close_database_shutdown_driver(driver);
462
Vect_close(&Outlier);
463
if (qgis_opt->answer) {