Skip to content

Commit

Permalink
Strengthen -Elines documentation for grdtrack and grdinterpolate (#8108)
Browse files Browse the repository at this point in the history
* Strengthen -Elines documentation for grdtrack and grdinterpolate

These two functions both use the very rich -E option for creating profiles on the fly.  The repetitive documentation for the two ahd some issues and missing modifiers, so this PR addes an explain_interpolant.rst_ file they can share.  Also, the parsing of -F for the interpolant different between the two modules so I have introduced some function that both can call to avoid duplicate and errors in the code.  Likewise, for teh documentation I added explain_interpolant.rst

* polish

* Update grdtrack.rst

* Add common usage explanation for -E in grdtrack and grdinterpolate

* Update grdtrack.c
  • Loading branch information
PaulWessel authored Nov 29, 2023
1 parent 454aa69 commit 1200849
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 178 deletions.
14 changes: 14 additions & 0 deletions doc/rst/source/explain_interpolant.rst_
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
**-Fl**\|\ **a**\|\ **c**\|\ **e**\|\ **l**\|\ **n**\|\ **s**\ *p*\ [**+d1**\|\ **2**]
Choose the desired 1-D spline interpolant from one of these directives:

- **a**: Akima spline [Default].
- **e**: Step curve.
- **c**: Natural cubic spline.
- **l**: Linear interpolant.
- **n**: No interpolation, just select nearest point.
- **s**: Smoothing cubic spline; append fit parameter *p* for an approximate fit.

You may change the GMT default interpolant; see :term:`GMT_INTERPOLANT` in your :doc:`gmt.conf` file.
You may optionally evaluate the first or second derivative of the spline
by appending **+d1** or **+d2**, respectively. **Note**: If you use derivatives
with directives **e** or **n** then the result is always zero.
33 changes: 33 additions & 0 deletions doc/rst/source/explain_lines.rst_
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
**-E**\ *table*\|\ *origin*\ |\ *line*\ [,\ *line*,...][**+a**\ *az*][**+c**][**+d**][**+g**][**+i**\ *inc*][**+l**\ *length*][**+n**\ *np*][**+o**\ *az*][**+p**][**+r**\ *radius*][**+x**]
Specify one or more profiles along which we will sample the grid (or cube).
There are several way to supply or create the profiles:

- Give your custom profiles via a *table* containing *lon lat* points.
- Given an *origin* (and *azimuth* and *length* and relevant modifiers below).
- Give one or more lines. The format of each *line* is *start*/*stop*, where
*start* or *stop* are either *lon*/*lat* (*x*/*y* for Cartesian data) or a
2-character key that uses the :doc:`text`-style justification format to
specify a point on the map as [LCR][BMT]. In addition to line coordinates,
you can use Z-, Z+ to mean the global minimum and maximum locations in the
grid (only available if a single input grid is given) or top layer in a cube
(only for doc:`grdinterpolate`).

Choose among several modifiers to create profiles:

- **+a**: Set the *azimuth* of a profile of given *length* (see **+l**) starting at the given *origin*.
- **+c**: Connect multiple profile segments with shared joints into a single segment.
- **+d**: Compute the along-track distances of the profiles.
- **+g**: Report degrees of longitude or latitude instead of great circle distances starting at zero [Default].
- **+i**: Append *inc* to set the sampling interval; if not given then we default to half the minimum grid interval.
- **+l**: Append the total *length* of the profile if **+a** or **+o** are used with an *origin*.
- **+n**: Append the desired number of points along profile (which determines the sampling interval).
- **+o**: Like **+a**, but centers the profile on the given *origin* in the *azimuth* direction.
- **+p**: Force sampling along the parallel if your *line* starts and ends at the same latitude [Great circle].
- **+r**: Append *radius* for circular sampling along small circle of given radius centered on the *origin*.
Requires either **+n** or **+i**.
- **+x**: Compute distances along a loxodrome (i.e., rhumbline) instead of along the great circle.

**Notes**: (1) Only one distance unit can be chosen. Giving different units
will result in an error. If no units are specified we default to
great circle distances in km (if geographic). (2) If working with geographic
data you can use **-j** to control the distance calculation mode [Great Circle].
37 changes: 5 additions & 32 deletions doc/rst/source/grdinterpolate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Synopsis
**gmt grdinterpolate** *cube* | *grd1 grd2 ...*
|-G|\ *outfile*
[ |SYN_OPT-D3| ]
[ |-E|\ *table*\|\ *line* ]
[ |-F|\ **l**\|\ **a**\|\ **c**\|\ **n**\ [**+d**\ 1\|\ 2] ]
[ |-E|\ *line* ]
[ |-F|\ **a**\|\ **c**\|\ **e**\|\ **l**\|\ **n**\|\ **s**\ *p*\ [**+d1**\|\ **2**] ]
[ |SYN_OPT-R| ]
[ |-S|\ *x/y*\|\ *pointfile*\ [**+h**\ *header*] ]
[ |-T|\ [*min/max*\ /]\ *inc*\ [**+i**\|\ **n**] \|\ |-T|\ *file*\|\ *list* ]
Expand Down Expand Up @@ -78,40 +78,13 @@ Optional Arguments

.. _-E:

**-E**\ *table*\|\ *line*\ [,\ *line*,...][**+a**\ *az*][**+g**][**+i**\ *inc*][**+l**\ *length*][**+n**\ *np*][**+o**\ *az*][**+p**][**+r**\ *radius*][**+x**]
Specify a crossectinonal profile via a *file* or from specified *line* coordinates and modifiers.
If a *file*, it must be contain a single segment with either *lon lat* or *lon lat dist* records.
These must be equidistant. Alternatively, the format of each *line* is
*start*/*stop*, where *start* or *stop* are *lon*/*lat* (*x*/*y* for
Cartesian data). You may append **+i**\ *inc* to set the sampling interval;
if not given then we default to half the minimum grid interval. If your *line* starts and
ends at the same latitude you can force sampling along the parallel with **+p** [great circle].
For a *line* along parallels or meridians you can add **+g** to report degrees of longitude or latitude
instead of great circle distances starting at zero. Append **+x** to compute distances
along a loxodrome (rhumbline) instead of great circle. Instead of two coordinates
you can specify an origin and one of **+a**, **+o**, or **+r**.
The **+a** sets the azimuth of a profile of given
length starting at the given origin, while **+o** centers the profile
on the origin; both require **+l**. For circular sampling specify
**+r** to define a circle of given radius centered on the origin;
this option requires either **+n** or **+i**. The **+n**\ *np* modifier sets
the desired number of points, while **+l**\ *length* gives the
total length of the profile.
Also note that only one distance unit can be chosen. Giving different units
will result in an error. If no units are specified we default to
great circle distances in km (if geographic). If working with geographic
data you can use **-j** to control distance calculation mode [Great Circle].
.. include:: explain_lines.rst_

Use |-G| to set the output grid file name.

.. _-F:

**-Fl**\|\ **a**\|\ **c**\|\ **n**\ [**+d**\ 1\|\ 2]
Choose from **l** (Linear), **a** (Akima spline), **c** (natural
cubic spline), and **n** (no interpolation: nearest point) [Default
is **-Fa**]. You may change the default interpolant; see
:term:`GMT_INTERPOLANT` in your :doc:`gmt.conf` file.
You may optionally evaluate the first or second derivative of the spline
by appending **+d** and specify 1 or 2, respectively.
.. include:: explain_interpolant.rst_

.. |Add_-R| replace:: Using the |-R| option will select a subsection of the grid. If this subsection exceeds the
boundaries of the grid, only the common region will be output. |Add_-R_links|
Expand Down
37 changes: 6 additions & 31 deletions doc/rst/source/grdtrack.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,47 +137,22 @@ Optional Arguments
*deviation* [0]. Looking in the direction of the line, a positive *deviation*
will rotate the crosslines clockwise and a negative one will rotate them
counter-clockwise. Finally, you can use **+f** to set a fixed azimuth
for all profiles.
for all profiles. **Note**: If |-C| is set and *spacing* is given then
that sampling scheme overrules any modifier set in |-E|.

.. _-D:

**-D**\ *dfile*
In concert with |-C| we can save the (possibly resampled) original
lines to the file *dfile* [Default only saves the cross-profiles].
The columns will be *lon*, *lat*, *dist*, *azimuth*, *z1*, *z2*, ...
(sampled value for each grid)
(sampled value for each grid).

.. _-E:

**-E**\ *line*\ [,\ *line*,...][**+a**\ *az*][**+c**][**+d**][**+g**][**+i**\ *inc*][**+l**\ *length*][**+n**\ *np*][**+o**\ *az*][**+r**\ *radius*]
Instead of reading input track coordinates, specify profiles via
coordinates and modifiers. The format of each *line* is
*start*/*stop*, where *start* or *stop* are either *lon*/*lat* (*x*/*y* for
Cartesian data) or a 2-character XY key that uses the :doc:`text`-style
justification format to specify a point on the map as
[LCR][BMT]. Each line will be a separate segment unless **+c** is used
which will connect segments with shared joints into a single segment.
In addition to line coordinates, you can use Z-, Z+ to mean the global
minimum and maximum locations in the grid (only available if a
single grid is given via |-G|). You may append
**+i**\ *inc* to set the sampling interval; if not given then
we default to half the minimum grid interval. For a *line* along parallels
or meridians you can add **+g** to report degrees of longitude or latitude
instead of great circle distances starting at zero. Instead of two coordinates
you can specify an origin and one of **+a**, **+o**, or **+r**.
The **+a** sets the azimuth of a profile of given
length starting at the given origin, while **+o** centers the profile
on the origin; both require **+l**. For circular sampling specify
**+r** to define a circle of given radius centered on the origin;
this option requires either **+n** or **+i**. The **+n**\ *np* modifier sets
the desired number of points, while **+l**\ *length* gives the
total length of the profile. Append **+d** to output the along-track
distances after the coordinates. **Notes**: (1) No track file will be read.
Also note that only one distance unit can be chosen. Giving different units
will result in an error. If no units are specified we default to
great circle distances in km (if geographic). If working with geographic
data you can use **-j** to control distance calculation mode [Great Circle].
(2) If |-C| is set and *spacing* is given the that sampling scheme
.. include:: explain_lines.rst_

(3) If |-C| is set and *spacing* is given then that sampling scheme
overrules any modifier set in |-E|.

.. _-F:
Expand Down
10 changes: 2 additions & 8 deletions doc/rst/source/sample1d.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,13 @@ Optional Arguments

.. _-F:

**-Fl**\|\ **a**\|\ **c**\|\ **e**\|\ **l**\|\ **n**\|\ **s**\ *p*\ [**+d1**\|\ **2**]
Choose from **a** (Akima spline), **e** (step curve), **c** (natural cubic spline),
**l** (Linear), **n** (no interpolation: nearest point), or **s** (smoothing cubic
spline; append fit parameter *p*) [Default is **-Fa**]. You may change the default interpolant; see :term:`GMT_INTERPOLANT` in your :doc:`gmt.conf` file.
You may optionally evaluate the first or second derivative of the spline
by appending **+d1** or **+d2**, respectively. **Note**: If you use the derivatives
with directives **e** or **n** then the result is always zero.
.. include:: explain_interpolant.rst_

.. figure:: /_images/GMT_splines.*
:width: 500 px
:align: center

The |-F| option lets you choose among several interpolators, including
The |-F| option lets you choose among several interpolants, including
one that is approximate (the smoothing spline). You can also specify
that you actually need a derivative of the solution instead of the value.

Expand Down
3 changes: 3 additions & 0 deletions src/gmt_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ enum GMT_time_period {
/* Modifiers for contour -A option */
#define GMT_CONTSPEC_MODS "acdefghijklLnNoprstuvwxX="

/* Directives and modifiers for -F interpolant option */
#define GMT_INTERPOLANT_OPT "a|c|e|l|n|s<p>[+d1|2]"

/* Valid modifiers for various input files */

/* Valid modifiers for -Tmin/max/inc array creator */
Expand Down
3 changes: 3 additions & 0 deletions src/gmt_prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,9 @@ EXTERN_MSC struct GMT_CONTOUR_INFO * gmt_get_contours_from_table (struct GMT_CTR
EXTERN_MSC int gmt_signum (double x);
EXTERN_MSC void gmt_get_rgb_lookup (struct GMT_CTRL *GMT, struct GMT_PALETTE *P, int index, double value, double *rgb);
EXTERN_MSC int gmt_locate_custom_symbol (struct GMT_CTRL *GMT, const char *in_name, char *name, char *path, unsigned int *pos);
EXTERN_MSC unsigned gmt_parse_interpolant (struct GMTAPI_CTRL *API, char *arg, unsigned int *mode, unsigned int *type, double *fit);
EXTERN_MSC unsigned int gmt_set_interpolate_mode (struct GMT_CTRL *GMT, unsigned int mode, unsigned int type);
EXTERN_MSC void gmt_explain_interpolate_mode (struct GMTAPI_CTRL *API);
EXTERN_MSC unsigned int gmt_get_dist_units (struct GMT_CTRL *GMT, char *args, char *unit, unsigned int *mode);
EXTERN_MSC unsigned int gmt_validate_cpt_parameters (struct GMT_CTRL *GMT, struct GMT_PALETTE *P, char *file, bool *interpolate, bool *force_continuous);
EXTERN_MSC void gmt_extend_region (struct GMT_CTRL *GMT, double wesn[], unsigned int mode, double inc[]);
Expand Down Expand Up @@ -541,6 +543,7 @@ EXTERN_MSC void gmt_set_refpoint (struct GMT_CTRL *GMT, struct GMT_REFPOINT *A);
EXTERN_MSC void gmt_free_refpoint (struct GMT_CTRL *GMT, struct GMT_REFPOINT **Ap);
EXTERN_MSC void gmt_flip_azim_d (struct GMT_CTRL *GMT, double *azim);
EXTERN_MSC void gmt_flip_angle_d (struct GMT_CTRL *GMT, double *angle);
EXTERN_MSC void gmt_explain_lines (struct GMTAPI_CTRL *API, unsigned mode);
EXTERN_MSC struct GMT_DATASET * gmt_make_profiles (struct GMT_CTRL *GMT, char option, char *args, bool resample, bool project, bool get_distances, double step, enum GMT_enum_track mode, double xyz[2][3], unsigned int *dtype);
EXTERN_MSC unsigned int gmt_split_poly_at_dateline (struct GMT_CTRL *GMT, struct GMT_DATASEGMENT *S, struct GMT_DATASEGMENT ***Lout);
EXTERN_MSC bool gmt_x_is_outside (struct GMT_CTRL *GMT, double *x, double left, double right);
Expand Down
85 changes: 85 additions & 0 deletions src/gmt_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,65 @@ bool gmt_consider_current_cpt (struct GMTAPI_CTRL *API, bool *active, char **arg
return ret;
}

unsigned gmt_parse_interpolant (struct GMTAPI_CTRL *API, char *arg, unsigned int *mode, unsigned int *type, double *fit) {
/* Do the parsing of the -F interpolant option using in sample1d and grdinterpolate */
unsigned int n_errors = 0;

*type = *mode = 0; *fit = 0.0;
switch (arg[0]) {
case 'l':
*mode = GMT_SPLINE_LINEAR;
break;
case 'a':
*mode = GMT_SPLINE_AKIMA;
break;
case 'c':
*mode = GMT_SPLINE_CUBIC;
break;
case 'n':
*mode = GMT_SPLINE_NN;
break;
case 'e':
*mode = GMT_SPLINE_STEP;
break;
case 's':
*mode = GMT_SPLINE_SMOOTH;
if (arg[1])
*fit = atof (&arg[1]);
else {
GMT_Report (API, GMT_MSG_ERROR, "Option -Fs: No fit parameter given\n");
n_errors++;
}
break;
default:
GMT_Report (API, GMT_MSG_ERROR, "Option -F: Bad interpolant selector %c\n", arg[0]);
n_errors++;
break;
}
if (strstr (&arg[1], "+d1")) *type = 1; /* Want first derivative */
else if (strstr (&arg[1], "+d2")) *type = 2; /* Want second derivative */
else if (strstr (&arg[1], "+1")) *type = 1; /* Want first derivative (backwards compatibility) */
else if (strstr (&arg[1], "+2")) *type = 2; /* Want second derivative (backwards compatibility) */
return (n_errors);
}

void gmt_explain_interpolate_mode (struct GMTAPI_CTRL *API) {
/* Display usage synopsis for -F interpolant option */
char type[3] = {'l', 'a', 'c'};

GMT_Usage (API, 1, "\n-F%s", GMT_INTERPOLANT_OPT);
GMT_Usage (API, -2, "Set the 1-D interpolation mode. Choose from:");
GMT_Usage (API, 3, "a: Akima spline interpolation.");
GMT_Usage (API, 3, "c: Cubic spline interpolation.");
GMT_Usage (API, 3, "e: Step-up interpolation (to next value).");
GMT_Usage (API, 3, "l: Linear interpolation.");
GMT_Usage (API, 3, "n: No interpolation (nearest point).");
GMT_Usage (API, 3, "s: Smooth spline interpolation (append fit parameter <p>).");
GMT_Usage (API, -2, "Optionally, request a spline derivative via a modifier:");
GMT_Usage (API, 3, "+d Append 1 for 1st derivative or 2 for 2nd derivative.");
GMT_Usage (API, -2, "[Default is -F%c].", type[API->GMT->current.setting.interpolant]);
}

unsigned int gmt_set_interpolate_mode (struct GMT_CTRL *GMT, unsigned int mode, unsigned int type) {
/* Convenience function that hides away the embedding of mode and type via the GMT_SPLINE_SLOPE factor */
gmt_M_unused (GMT);
Expand Down Expand Up @@ -11101,6 +11160,32 @@ unsigned int gmt_get_dist_units (struct GMT_CTRL *GMT, char *args, char *unit, u
return (error);
}

void gmt_explain_lines (struct GMTAPI_CTRL *API, unsigned mode) {
/* mode is 0 for gratrack and 1for grdinterpolate */
static char *item[2] = {"grid", "top layer in the cube"};
GMT_Usage (API, 1, "\n-E<table|<origin>|<line1>[,<line2>,...][+a<az>][+c][+d][+g][+i<step>][+l<length>][+n<np>][+o<az>][+p][+r<radius>][+x]");
GMT_Usage (API, -2, "Read profiles from <table> or create them on the fly. Choose on of these choices:");
GMT_Usage (API, 3, "%s Read one or more profiles from <table>", GMT_LINE_BULLET);
GMT_Usage (API, 3, "%s Create quick paths based on <line1>[,<line2>,...]. Each <line> is given by <start>/<stop>, where <start> or <stop> "
"are <lon/lat> or a 2-character key that uses the \"pstext\"-style justification format "
"to specify a point on the map as [LCR][BMT]. In addition, you can use Z-, Z+ to mean "
"the global minimum and maximum locations in the %s.", GMT_LINE_BULLET, item[mode]);
GMT_Usage (API, 3, "%s Set an origin, provide azimuth and length and more via modifiers and create a profile.", GMT_LINE_BULLET);
GMT_Usage (API, -2, "Several modifiers are available to create the profiles:");
GMT_Usage (API, 3, "+a Define a profile from <origin> in the <az> direction; requires +l.");
GMT_Usage (API, 3, "+c Create a continuous segment if two end points are identical [separate segments].");
GMT_Usage (API, 3, "+d Insert an extra output column with distances following the coordinates.");
GMT_Usage (API, 3, "+g Use gridline coordinates (degree longitude or latitude) if <line> is so aligned [great circle].");
GMT_Usage (API, 3, "+i Set the sampling increment <step> [Default is 0.5 x min of (x_inc, y_inc)].");
GMT_Usage (API, 3, "+l Set the length of the profile.");
GMT_Usage (API, 3, "+o Like +a but centers profile on <origin>; requires +l.");
GMT_Usage (API, 3, "+p Sample along the parallel if <line> has constant latitude.");
GMT_Usage (API, 3, "+n Set <np>, the number of output points and compute <inc> from <length>, so +l is required.");
GMT_Usage (API, 3, "+r Set <radius> of circle about <origin>; requires +i or +n.");
GMT_Usage (API, 3, "+x Follow a loxodrome (rhumbline) [great circle].");
GMT_Usage (API, -2, "Note: A unit is optional. Only ONE unit type from %s can be used throughout this option, "
"so mixing of units is not allowed [Default unit is km, if geographic].", GMT_LEN_UNITS2_DISPLAY);
}

/*! . */
struct GMT_DATASET *gmt_make_profiles (struct GMT_CTRL *GMT, char option, char *args, bool resample, bool project, bool get_distances, double step, enum GMT_enum_track mode, double xyz[2][3], unsigned int *dtype) {
Expand Down
Loading

0 comments on commit 1200849

Please sign in to comment.