Skip to content

Commit

Permalink
Ensure external vectors are scaled via -i (#5291)
Browse files Browse the repository at this point in the history
* Ensure external vector is scaled via -I on rec-by-rec parsing

See GenericMappingTools/pygmt#1313 for details.  This PR ensures the record-by-record reading of external vectors have any adjustments set via -i applied.

* Update gmt_api.c
  • Loading branch information
PaulWessel authored Jun 3, 2021
1 parent 4385643 commit f96d51e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/gmt_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ GMT_LOCAL double gmtapi_get_record_value (struct GMT_CTRL *GMT, double *record,
double val;
unsigned int col_pos;
col_pos = gmtapi_pick_in_col_number (GMT, (unsigned int)col);
val = (col_pos >= n_colums) ? GMT->session.d_NaN : record[col_pos]; /* If we request a column beyond length of array, return NaN */
val = (col_pos >= n_colums) ? GMT->session.d_NaN : gmt_M_convert_col (GMT->current.io.col[GMT_IN][col_pos], record[col_pos]); /* If we request a column beyond length of array, return NaN */
if (GMT->common.d.active[GMT_IN] && gmt_M_is_dnan (val)) val = GMT->common.d.nan_proxy[GMT_IN]; /* Write this value instead of NaNs */
if (gmt_M_is_type (GMT, GMT_IN, col_pos, GMT_IS_LON)) gmt_lon_range_adjust (GMT->current.io.geo.range, &val); /* Set longitude range */
return (val);
Expand Down Expand Up @@ -3488,6 +3488,14 @@ GMT_LOCAL void gmtapi_switch_cols (struct GMT_CTRL *GMT, struct GMT_DATASET *D,
}
}

GMT_LOCAL bool gmtapi_vector_data_must_be_duplicated (struct GMTAPI_CTRL *API, struct GMT_VECTOR *V) {
/* Check if referenced vector data arrays must be scaled/offset and hence must be duplicated instead */
for (unsigned int col = 0; col < V->n_columns; col++) {
if (API->GMT->common.i.select && API->GMT->current.io.col[GMT_IN][col].convert) return (true); /* Cannot pass as read-only if it must be converted */
}
return false; /* Seems OK */
}

/*! . */
GMT_LOCAL struct GMT_DATASET * gmtapi_import_dataset (struct GMTAPI_CTRL *API, int object_ID, unsigned int mode) {
/* Does the actual work of loading in the entire virtual data set (possibly via many sources)
Expand Down Expand Up @@ -3562,6 +3570,12 @@ GMT_LOCAL struct GMT_DATASET * gmtapi_import_dataset (struct GMTAPI_CTRL *API, i
via = false;
geometry = (GMT->common.a.output) ? GMT->common.a.geometry : S_obj->geometry; /* When reading GMT and writing OGR/GMT we must make sure we set this first */
method = gmtapi_set_method (S_obj); /* Get the actual method to use */
/* At the time an external vector was created via GMT_Open_VirtualFile there is not yet any knowledge if this data
* will be passed to a module with options -i that could require scaling, offseting, or taking the log of the data.
* If that is the case then we cannot pass via reference but must switch method to duplicate. */
if (method == (GMT_IS_REFERENCE|GMT_VIA_VECTOR) && gmtapi_vector_data_must_be_duplicated (API, S_obj->resource))
method = GMT_IS_DUPLICATE|GMT_VIA_VECTOR; /* We need to adjust at least one vector due to -i+s+o+l so must duplicate input rather than reference */

switch (method) { /* File, array, stream, reference, etc ? */
case GMT_IS_FILE: /* Import all the segments, then count total number of records */
#ifdef SET_IO_MODE
Expand Down Expand Up @@ -8639,7 +8653,7 @@ GMT_LOCAL bool gmtapi_matrix_data_conforms_to_dataset (struct GMT_MATRIX *M) {
return (M->type == GMT_DOUBLE); /* Having double means we can use as is */
}

GMT_LOCAL bool gmtapi_vector_data_conforms_to_dataset (struct GMT_VECTOR *V, enum GMT_enum_type type) {
GMT_LOCAL bool gmtapi_vector_data_conforms_to_dataset (struct GMTAPI_CTRL *API, struct GMT_VECTOR *V, enum GMT_enum_type type) {
/* Check if the vector data arrays matches the form of a GMT dataset (columns of doubles) */
if (type != GMT_DOUBLE) { /* Only doubles can be passed or memcpy directly */
if (V->n_columns == 0) return (false); /* Having nothing yet means we must duplicate */
Expand Down Expand Up @@ -8685,7 +8699,7 @@ GMT_LOCAL void gmtapi_maybe_change_method_to_duplicate (struct GMTAPI_CTRL *API,
S_obj->method = GMT_IS_DUPLICATE; /* Must duplicate this resource */
GMT_Report (API, GMT_MSG_INFORMATION, "GMT_Open_VirtualFile: Switch method to GMT_IS_DUPLICATE as vectors are not compatible with a GMT grid\n");
}
else if (S_obj->actual_family == GMT_IS_VECTOR && S_obj->family == GMT_IS_DATASET && !gmtapi_vector_data_conforms_to_dataset (S_obj->resource, S_obj->type)) {
else if (S_obj->actual_family == GMT_IS_VECTOR && S_obj->family == GMT_IS_DATASET && !gmtapi_vector_data_conforms_to_dataset (API, S_obj->resource, S_obj->type)) {
S_obj->method = GMT_IS_DUPLICATE; /* Must duplicate this resource */
GMT_Report (API, GMT_MSG_INFORMATION, "GMT_Open_VirtualFile: Switch method to GMT_IS_DUPLICATE as input vectors are not compatible with a GMT dataset\n");
}
Expand Down Expand Up @@ -9637,11 +9651,13 @@ struct GMT_RECORD *api_get_record_vector (struct GMTAPI_CTRL *API, unsigned int
while (col < API->current_get_n_columns) {
col_pos = gmtapi_pick_in_col_number (GMT, (unsigned int)col);
API->current_get_V_val[col_pos] (&(V->data[col_pos]), S->rec, &(GMT->current.io.curr_rec[col]));
col++;
GMT->current.io.curr_rec[col] = gmt_M_convert_col (GMT->current.io.col[GMT_IN][col_pos], GMT->current.io.curr_rec[col]);
col++;
while (GMT->common.i.select && col < GMT->common.i.n_cols && GMT->current.io.col[GMT_IN][col].col == GMT->current.io.col[GMT_IN][col-1].col) {
/* This input column is requested more than once */
col_pos = GMT->current.io.col[GMT_IN][col].order; /* The data column that will receive this value */
API->current_get_V_val[col_pos] (&(V->data[col_pos]), S->rec, &(GMT->current.io.curr_rec[col]));
API->current_get_V_val[col_pos] (&(V->data[col_pos]), S->rec, &(GMT->current.io.curr_rec[col]));
GMT->current.io.curr_rec[col] = gmt_M_convert_col (GMT->current.io.col[GMT_IN][col_pos], GMT->current.io.curr_rec[col]);
col++;
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/gmt_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
#define gmt_nc_put_varm_grdfloat nc_put_varm_float
#endif

/*! Macro to apply columns log/scale/offset conversion on the fly */
#define gmt_M_convert_col(S,x) ((S.convert) ? ((S.convert & 2) ? log10 (x) : x) * S.scale + S.offset : x)

/* This macro is called via each modules "Return" macro so API and options are available */
#define gmt_M_free_options(mode) {if (GMT_Destroy_Options (API, &options) != GMT_OK) return (GMT_MEMORY_ERROR);}

Expand Down

0 comments on commit f96d51e

Please sign in to comment.