Skip to content

Commit

Permalink
Add legend symbol for confidence lines (#6890)
Browse files Browse the repository at this point in the history
* Add symbol L for ine with confidence envelope

Needed for legend settings, especially.

* Finalize confidence line symbol

* Only for confidence lines, not fill under lines
  • Loading branch information
PaulWessel committed Jul 17, 2022
1 parent de60d51 commit e280ff5
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 41 deletions.
7 changes: 6 additions & 1 deletion src/gmt_init.c
Expand Up @@ -19383,7 +19383,7 @@ GMT_LOCAL void gmtinit_set_symbol_size (struct GMTAPI_CTRL *API, struct GMT_SYMB
}
}

void gmt_add_legend_item (struct GMTAPI_CTRL *API, struct GMT_SYMBOL *S, bool do_fill, struct GMT_FILL *fill, bool do_line, struct GMT_PEN *pen, struct GMT_LEGEND_ITEM *item) {
void gmt_add_legend_item (struct GMTAPI_CTRL *API, struct GMT_SYMBOL *S, bool do_fill, struct GMT_FILL *fill, bool do_line, struct GMT_PEN *pen, struct GMT_LEGEND_ITEM *item, struct GMT_PEN *cpen) {
/* Adds a new entry to the auto-legend information file hidden in the session directory */
char file[PATH_MAX] = {""}, label[GMT_LEN128] = {""}, size_string[GMT_LEN128] = {""}, symbol;
bool gap_done = false;
Expand Down Expand Up @@ -19535,6 +19535,11 @@ void gmt_add_legend_item (struct GMTAPI_CTRL *API, struct GMT_SYMBOL *S, bool do
if (S->D.fill[0]) strcat (scode, "+g"), strcat (scode, S->D.fill);
fprintf (fp, "S - %s - %s %s - %s\n", scode, (do_fill) ? gmtlib_putfill (API->GMT, fill) : "-", (do_line) ? gmt_putpen (API->GMT, pen) : "-", label);
}
else if (symbol == 'L') { /* Confidence-bound line [Experimental] */
/* Confidence band with line is plotted as two symbol; pslegend will not advance y after L */
fprintf (fp, "S - L %s %s %s - %s\n", size_string, gmtlib_putfill (API->GMT, fill), (cpen) ? gmt_putpen (API->GMT, cpen) : "-", label);
fprintf (fp, "S - - %s - %s - %s\n", size_string, gmt_putpen (API->GMT, pen), "");
}
else
fprintf (fp, "S - %c %s %s %s - %s\n", symbol, size_string, (do_fill) ? gmtlib_putfill (API->GMT, fill) : "-", (do_line) ? gmt_putpen (API->GMT, pen) : "-", label);
}
Expand Down
2 changes: 1 addition & 1 deletion src/gmt_prototypes.h
Expand Up @@ -489,7 +489,7 @@ EXTERN_MSC bool gmt_consider_current_cpt (struct GMTAPI_CTRL *API, bool *active,
EXTERN_MSC double * gmt_list_to_array (struct GMT_CTRL *GMT, char *list, unsigned int type, bool unique, uint64_t *n);
EXTERN_MSC int gmt_getfonttype (struct GMT_CTRL *GMT, char *name);
EXTERN_MSC int gmt_legend_file (struct GMTAPI_CTRL *API, char *file);
EXTERN_MSC void gmt_add_legend_item (struct GMTAPI_CTRL *API, struct GMT_SYMBOL *S, bool do_fill, struct GMT_FILL *fill, bool do_line, struct GMT_PEN *pen, struct GMT_LEGEND_ITEM *item);
EXTERN_MSC void gmt_add_legend_item (struct GMTAPI_CTRL *API, struct GMT_SYMBOL *S, bool do_fill, struct GMT_FILL *fill, bool do_line, struct GMT_PEN *pen, struct GMT_LEGEND_ITEM *item, struct GMT_PEN *cpen);
EXTERN_MSC bool gmt_get_legend_info (struct GMTAPI_CTRL *API, double *width, double *scale, char justification[], char pen[], char fill[], char off[]);
EXTERN_MSC unsigned int gmt_parse_array (struct GMT_CTRL *GMT, char option, char *argument, struct GMT_ARRAY *T, unsigned int flags, unsigned int tcol);
EXTERN_MSC unsigned int gmt_create_array (struct GMT_CTRL *GMT, char option, struct GMT_ARRAY *T, double *min, double *max);
Expand Down
10 changes: 5 additions & 5 deletions src/grdcontour.c
Expand Up @@ -1425,22 +1425,22 @@ EXTERN_MSC int GMT_grdcontour (void *V_API, int mode, void *args) {
if (strchr ("|/", GMT->common.l.item.label[0])) { /* Gave single label for contour pen since starting with | or / */
gmt_M_memcpy (&copy, &(GMT->common.l.item), 1, struct GMT_LEGEND_ITEM); /* Make an identical copy */
gmt_strlshift (copy.label, 1U); /* Remove the leading divider */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy);
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy, NULL);
}
else if ((p = strchr (GMT->common.l.item.label, '|')) || (p = strchr (GMT->common.l.item.label, '/'))) { /* Got two titles */
char q = p[0]; /* Get the divider character */
gmt_M_memcpy (&copy, &(GMT->common.l.item), 1, struct GMT_LEGEND_ITEM); /* Make an identical copy */
p[0] = '\0'; /* Truncate the second contour label */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item)); /* Place the first annotated contour entry */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item), NULL); /* Place the first annotated contour entry */
p[0] = q; /* Restore the label in the original -l setting */
if (copy.draw & GMT_LEGEND_DRAW_D) copy.draw -= GMT_LEGEND_DRAW_D; /* Only want to draw one horizontal line (if set), so remove for the 2nd entry */
gmt_strlshift (copy.label, (size_t)(p - GMT->common.l.item.label)+1); /* Remove the leading annotated contour label first */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy); /* Place the second regular contour entry */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy, NULL); /* Place the second regular contour entry */
}
else if (Ctrl->A.active) /* Got a single entry for annotated contours */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item));
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item), NULL);
else /* Got a single entry for plain contours */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &(GMT->common.l.item));
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &(GMT->common.l.item), NULL);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/grdvector.c
Expand Up @@ -758,7 +758,7 @@ EXTERN_MSC int GMT_grdvector (void *V_API, int mode, void *args) {
scaled_vec_length /= scale; /* Now in inches suitable for reference vector in legend */
}
GMT->common.l.item.size = scaled_vec_length;
gmt_add_legend_item (API, &Ctrl->Q.S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item));
gmt_add_legend_item (API, &Ctrl->Q.S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item), NULL);
Ctrl->Q.S.symbol = was; /* Restore to original type */
}

Expand Down
10 changes: 5 additions & 5 deletions src/pscontour.c
Expand Up @@ -1089,22 +1089,22 @@ EXTERN_MSC int GMT_pscontour (void *V_API, int mode, void *args) {
if (strchr ("|/", GMT->common.l.item.label[0])) { /* Gave single label for contour pen since starting with | or / */
gmt_M_memcpy (&copy, &(GMT->common.l.item), 1, struct GMT_LEGEND_ITEM); /* Make an identical copy */
gmt_strlshift (copy.label, 1U); /* Remove the leading divider */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy);
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy, NULL);
}
else if ((p = strchr (GMT->common.l.item.label, '|')) || (p = strchr (GMT->common.l.item.label, '/'))) { /* Got two titles */
char q = p[0]; /* Get the divider character */
gmt_M_memcpy (&copy, &(GMT->common.l.item), 1, struct GMT_LEGEND_ITEM); /* Make an identical copy */
p[0] = '\0'; /* Truncate the second contour label */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item)); /* Place the first annotated contour entry */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item), NULL); /* Place the first annotated contour entry */
p[0] = q; /* Restore the label in the original -l setting */
if (copy.draw & GMT_LEGEND_DRAW_D) copy.draw -= GMT_LEGEND_DRAW_D; /* Only want to draw one horizontal line (if set), so remove for the 2nd entry */
gmt_strlshift (copy.label, (size_t)(p - GMT->common.l.item.label)+1); /* Remove the leading annotated contour label first */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy); /* Place the second regular contour entry */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &copy, NULL); /* Place the second regular contour entry */
}
else if (Ctrl->A.active) /* Got a single entry for annotated contours */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item));
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_ANNOT]), &(GMT->common.l.item), NULL);
else /* Got a single entry for plain contours */
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &(GMT->common.l.item));
gmt_add_legend_item (API, NULL, false, NULL, true, &(Ctrl->W.pen[PEN_CONT]), &(GMT->common.l.item), NULL);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/pshistogram.c
Expand Up @@ -1359,7 +1359,7 @@ EXTERN_MSC int GMT_pshistogram (void *V_API, int mode, void *args) {
else
S.size_y = S.size_x / 1.5; /* Width to height ratio is 3:2 */
}
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item));
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item), NULL);
}

if (Ctrl->N.active) { /* Want to draw one or more normal distributions; we use 101 points to do so */
Expand Down
16 changes: 10 additions & 6 deletions src/pslegend.c
Expand Up @@ -531,6 +531,7 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
int i, justify = 0, n = 0, n_columns = 1, n_col, col, error = 0, column_number = 0, id, n_scan, status = 0, max_cols = 0;
bool flush_paragraph = false, v_line_draw_now = false, gave_label, gave_mapscale_options, did_old = false, use[2] = {false, true};
bool drawn = false, b_cpt = false, C_is_active = false, do_width = false, in_PS_ok = true, got_line = false, got_geometric = false;
bool confidence_band = false;
uint64_t seg, row, n_fronts = 0, n_quoted_lines = 0, n_decorated_lines = 0, n_symbols = 0, n_par_lines = 0, n_par_total = 0, krow[N_DAT], n_records = 0;
int64_t n_para = -1;
size_t n_char = 0;
Expand All @@ -543,7 +544,7 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
char module_options[GMT_LEN256] = {""}, r_options[GMT_LEN256] = {""}, xy_mode[3] = {""}, J_arg[GMT_LEN64] = {"-Jx1i"};
char txtcolor[GMT_LEN256] = {""}, def_txtcolor[GMT_LEN256] = {""}, buffer[GMT_BUFSIZ] = {""}, A[GMT_LEN32] = {""}, legend_file[PATH_MAX] = {""};
char path[PATH_MAX] = {""}, B[GMT_LEN32] = {""}, C[GMT_LEN32] = {""}, p[GMT_LEN256] = {""};
char *plot_points[2] = {"psxy", "plot"}, *plot_text[2] = {"pstext", "text"};
char *plot_points[2] = {"psxy", "plot"}, *plot_text[2] = {"pstext", "text"}, orig_symbol = 0;
char *line = NULL, string[GMT_VF_LEN] = {""}, *c = NULL, *fill[PSLEGEND_MAX_COLS];
#ifdef DEBUG
char *dname[N_DAT] = {"symbol", "front", "qline", "textline", "partext"};
Expand Down Expand Up @@ -842,13 +843,13 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
break;

case 'S': /* Symbol record: S [dx1 symbol size fill pen [ dx2 text ]] */
if (column_number%n_columns == 0) {
text[0] = '\0';
n_scan = sscanf (line, "%*s %*s %s %s %*s %*s %s %[^\n]", symbol, size, txt_b, text);
if (column_number%n_columns == 0 && symbol[0] != 'L') { /* Skip L to not count both symbols making up the confidence line */
height += one_line_spacing;
column_number = 0;
}
column_number++;
text[0] = '\0';
n_scan = sscanf (line, "%*s %*s %s %s %*s %*s %s %[^\n]", symbol, size, txt_b, text);
/* Find the largest symbol size specified */
gmt_strrepc (size, '/', ' '); /* Replace any slashes with spaces */
gmt_strrepc (size, ',', ' '); /* Replace any commas with spaces */
Expand Down Expand Up @@ -1534,11 +1535,13 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
n_scan = sscanf (&line[2], "%s %s %s %s %s %s %[^\n]", txt_a, symbol, size, txt_c, txt_d, txt_b, text);
else /* No args given means skip to next cell */
n_scan = 0;
orig_symbol = symbol[0]; /* Needed for L since we change it to r herein */
if (column_number%n_columns == 0) { /* Symbol in first column, also fill row if requested */
pslegend_fillcell (GMT, Ctrl->D.refpoint->x, row_base_y-one_line_spacing, row_base_y+gap, x_off_col, &d_line_after_gap, n_columns, fill);
row_base_y -= one_line_spacing;
if (!confidence_band) row_base_y -= one_line_spacing;
column_number = 0;
}
if (symbol[0] == 'L') symbol[0] = 'r'; /* L means rectangle followed by central line */
if (n_scan <= 0) { /* No symbol, just skip to next cell */
column_number++;
GMT_Report (API, GMT_MSG_DEBUG, "The S record give no info so skip to next cell\n");
Expand Down Expand Up @@ -1848,7 +1851,8 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
pslegend_maybe_realloc_segment (GMT, S[TXT]);
GMT_Report (API, GMT_MSG_DEBUG, "TXT: %s\n", buffer);
}
column_number++;
confidence_band = (orig_symbol == 'L'); /* Next entry will do line and need to overwrite */
if (!confidence_band) column_number++;
if (Ctrl->F.debug) pslegend_drawbase (GMT, PSL, Ctrl->D.refpoint->x, Ctrl->D.refpoint->x + Ctrl->D.dim[GMT_X], row_base_y);
drawn = true;
break;
Expand Down
25 changes: 14 additions & 11 deletions src/psxy.c
Expand Up @@ -1437,7 +1437,7 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {
GMT_Report (API, GMT_MSG_WARNING, "Cannot use auto-legend -l for variable symbol size unless +S<size> is used. Option -l ignored.\n");
else {
/* For specified symbol, size, color we can do an auto-legend entry under modern mode */
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item));
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item), NULL);
}

}
Expand Down Expand Up @@ -2290,7 +2290,7 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {
}
else { /* Line/polygon part */
uint64_t seg, seg_out = 0, n_new, n_cols = 2;
bool duplicate, resampled;
bool duplicate, resampled, conf_line = false;
struct GMT_DATASET *D = NULL; /* Pointer to GMT multisegment table(s) */
struct GMT_PALETTE *A = NULL;
struct GMT_DATASET_HIDDEN *DH = NULL;
Expand All @@ -2303,6 +2303,7 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {

if (Ctrl->L.anchor == PSXY_POL_SYMM_DEV) n_cols = 3;
else if (Ctrl->L.anchor == PSXY_POL_ASYMM_DEV || Ctrl->L.anchor == PSXY_POL_ASYMM_ENV) n_cols = 4;
conf_line = (Ctrl->L.anchor >= PSXY_POL_SYMM_DEV && Ctrl->L.anchor <= PSXY_POL_ASYMM_ENV);

if (GMT_Init_IO (API, GMT_IS_DATASET, geometry, GMT_IN, GMT_ADD_DEFAULT, 0, options) != GMT_NOERROR) { /* Register data input */
Return (API->error);
Expand Down Expand Up @@ -2380,17 +2381,18 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {

if (!seq_legend && GMT->common.l.active) {
if (S.symbol == GMT_SYMBOL_LINE) {
if (polygon || Ctrl->L.active) { /* Place a rectangle in the legend */
if (polygon || conf_line) { /* Place a rectangle in the legend */
int symbol = S.symbol;
S.symbol = PSL_RECT;
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item));
struct GMT_PEN *cpen = (Ctrl->L.outline) ? &(Ctrl->L.pen) : NULL;
S.symbol = (Ctrl->L.active && Ctrl->G.active && Ctrl->W.active) ? 'L' : PSL_RECT; /* L means confidence-line */
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item), cpen);
S.symbol = symbol;
}
else /* For specified line, width, color we can do an auto-legend entry under modern mode */
gmt_add_legend_item (API, &S, false, NULL, Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item));
gmt_add_legend_item (API, &S, false, NULL, Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item), NULL);
}
else /* Decorated or quoted lines */
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item));
gmt_add_legend_item (API, &S, Ctrl->G.active, &(Ctrl->G.fill), Ctrl->W.active, &(Ctrl->W.pen), &(GMT->common.l.item), NULL);
//GMT_Report (API, GMT_MSG_WARNING, "Cannot use auto-legend -l for selected feature. Option -l ignored.\n");
}

Expand Down Expand Up @@ -2429,14 +2431,15 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {
if (seq_legend && seq_n_legends >= 0 && (seq_frequency == GMT_COLOR_AUTO_SEGMENT || seg == 0)) {
if (GMT->common.l.item.label_type == GMT_LEGEND_LABEL_HEADER && L->header) /* Use a segment label if found in header */
gmt_extract_label (GMT, L->header, GMT->common.l.item.label, SH->ogr);
if (polygon) { /* Place a rectangle in the legend */
if (polygon || conf_line) { /* Place a rectangle in the legend */
int symbol = S.symbol;
S.symbol = PSL_RECT;
gmt_add_legend_item (API, &S, Ctrl->G.active, &current_fill, Ctrl->W.active, &current_pen, &(GMT->common.l.item));
struct GMT_PEN *cpen = (Ctrl->L.outline) ? &(Ctrl->L.pen) : NULL;
S.symbol = (Ctrl->L.active && Ctrl->G.active && Ctrl->W.active) ? 'L' : PSL_RECT; /* L means confidence-line */
gmt_add_legend_item (API, &S, Ctrl->G.active, &current_fill, Ctrl->W.active, &current_pen, &(GMT->common.l.item), cpen);
S.symbol = symbol;
}
else /* For specified line, width, color we can do an auto-legend entry under modern mode */
gmt_add_legend_item (API, &S, false, NULL, Ctrl->W.active, &current_pen, &(GMT->common.l.item));
gmt_add_legend_item (API, &S, false, NULL, Ctrl->W.active, &current_pen, &(GMT->common.l.item), NULL);
seq_n_legends--; /* One less to do */
GMT->common.l.item.ID++; /* Increment the label counter */
}
Expand Down

0 comments on commit e280ff5

Please sign in to comment.