diff --git a/doc/rst/source/grd2cpt.rst b/doc/rst/source/grd2cpt.rst index 32d60bda53f..ef3b927ce6c 100644 --- a/doc/rst/source/grd2cpt.rst +++ b/doc/rst/source/grd2cpt.rst @@ -168,7 +168,8 @@ Optional Arguments **-L**\ *minlimit/maxlimit* Limit range of CPT to *minlimit/maxlimit*, and don't count data - outside this range when estimating CDF(Z). [Default uses min and max of data.] + outside this range when estimating CDF(Z). To set only one limit, + specify the other limit as "-" [Default uses min and max of data.] .. _-M: diff --git a/src/grd2cpt.c b/src/grd2cpt.c index 416c3478804..8e4d5ca22bc 100644 --- a/src/grd2cpt.c +++ b/src/grd2cpt.c @@ -90,6 +90,7 @@ struct GRD2CPT_CTRL { } I; struct GRD2CPT_L { /* -L/ */ bool active; + bool minimum_given, maximum_given; double min, max; } L; struct GRD2CPT_M { /* -M */ @@ -181,7 +182,7 @@ static int usage (struct GMTAPI_CTRL *API, int level) { GMT_Message (API, GMT_TIME_NONE, "\t -Ic Reverse sense of color table as well as back- and foreground color [Default].\n"); GMT_Message (API, GMT_TIME_NONE, "\t -Iz Reverse sign of z-values in the color table (takes affect before -G, T are consulted).\n"); GMT_Message (API, GMT_TIME_NONE, "\t-L Limit the range of the data. Node values outside this range are set to NaN.\n"); - GMT_Message (API, GMT_TIME_NONE, "\t [Default uses actual min,max of data].\n"); + GMT_Message (API, GMT_TIME_NONE, "\t To only give min or max limit, set the other to - [Default uses actual min,max of data].\n"); GMT_Message (API, GMT_TIME_NONE, "\t-M Use GMT defaults to set back-, foreground, and NaN colors [Default uses color table].\n"); GMT_Message (API, GMT_TIME_NONE, "\t-N Do not write back-, foreground, and NaN colors [Default will].\n"); GMT_Message (API, GMT_TIME_NONE, "\t-Q Assign a logarithmic colortable [Default is linear].\n"); @@ -318,10 +319,14 @@ static int parse (struct GMT_CTRL *GMT, struct GRD2CPT_CTRL *Ctrl, struct GMT_OP break; case 'L': /* Limit data range */ Ctrl->L.active = true; - if (sscanf (opt->arg, "%lf/%lf", &Ctrl->L.min, &Ctrl->L.max) != 2) { - GMT_Report (API, GMT_MSG_ERROR, "Option -L: Cannot decode limits\n"); + if ((n = sscanf (opt->arg, "%[^/]/%s", txt_a, txt_b)) != 2) { + GMT_Report (API, GMT_MSG_ERROR, "Option -L: Cannot decode two limits\n"); n_errors++; } + else { /* Assign limits unless give as "-" which means to skip that limit */ + if (strcmp (txt_a, "-")) Ctrl->L.min = atof (txt_a), Ctrl->L.minimum_given = true; + if (strcmp (txt_b, "-")) Ctrl->L.max = atof (txt_b), Ctrl->L.maximum_given = true; + } break; case 'M': /* Override fore/back/NaN using GMT defaults */ Ctrl->M.active = true; @@ -436,7 +441,7 @@ static int parse (struct GMT_CTRL *GMT, struct GRD2CPT_CTRL *Ctrl, struct GMT_OP "Options -W and -Z cannot be used simultaneously\n"); n_errors += gmt_M_check_condition (GMT, Ctrl->F.cat && Ctrl->Z.active, "Options -F+c and -Z cannot be used simultaneously\n"); - n_errors += gmt_M_check_condition (GMT, Ctrl->L.active && Ctrl->L.min >= Ctrl->L.max, + n_errors += gmt_M_check_condition (GMT, Ctrl->L.active && Ctrl->L.minimum_given && Ctrl->L.maximum_given && Ctrl->L.min >= Ctrl->L.max, "Option -L: min_limit must be less than max_limit.\n"); n_errors += gmt_M_check_condition (GMT, Ctrl->T.active && Ctrl->T.mode == 0 && (Ctrl->T.high <= Ctrl->T.low || Ctrl->T.inc <= 0.0), "Option -S: Bad arguments\n"); @@ -598,14 +603,18 @@ EXTERN_MSC int GMT_grd2cpt (void *V_API, int mode, void *args) { nfound = 0; mean = sd = 0.0; if (Ctrl->L.active) { /* Loop over the grdfiles, and set anything outside the limiting values to NaN. */ - G[0]->header->z_min = Ctrl->L.min; - G[0]->header->z_max = Ctrl->L.max; + G[0]->header->z_min = (Ctrl->L.minimum_given) ? Ctrl->L.min : G[0]->header->z_max; + G[0]->header->z_max = (Ctrl->L.maximum_given) ? Ctrl->L.max : G[0]->header->z_min; for (k = 0; k < ngrd; k++) { /* For each grid */ gmt_M_grd_loop (GMT, G[k], row, col, ij) { if (gmt_M_is_fnan (G[k]->data[ij])) nfound++; else { - if (G[k]->data[ij] < Ctrl->L.min || G[k]->data[ij] > Ctrl->L.max) { + if (Ctrl->L.minimum_given && G[k]->data[ij] < Ctrl->L.min) { + nfound++; + G[k]->data[ij] = GMT->session.f_NaN; + } + else if (Ctrl->L.maximum_given && G[k]->data[ij] > Ctrl->L.max) { nfound++; G[k]->data[ij] = GMT->session.f_NaN; } @@ -617,10 +626,14 @@ EXTERN_MSC int GMT_grd2cpt (void *V_API, int mode, void *args) { else { mean += G[k]->data[ij]; sd += G[k]->data[ij] * G[k]->data[ij]; + if (!Ctrl->L.minimum_given && G[k]->data[ij] < Ctrl->L.min) Ctrl->L.min = G[k]->data[ij]; + if (!Ctrl->L.maximum_given && G[k]->data[ij] > Ctrl->L.max) Ctrl->L.max = G[k]->data[ij]; } } } } + if (!Ctrl->L.minimum_given) G[0]->header->z_min = Ctrl->L.min; + if (!Ctrl->L.maximum_given) G[0]->header->z_max = Ctrl->L.max; } else { Ctrl->L.min = G[0]->header->z_max; /* This is just to double check G[k]->header->z_min, G[k]->header->z_max */