diff --git a/doc/rst/source/modules-classic.rst b/doc/rst/source/modules-classic.rst index d4a0a1c2ad4..28c70223385 100644 --- a/doc/rst/source/modules-classic.rst +++ b/doc/rst/source/modules-classic.rst @@ -127,6 +127,13 @@ All modules are requested via a call to the :doc:`gmt` program. supplements/geodesy/earthtide supplements/geodesy/gpsgridder supplements/geodesy/psvelo + supplements/gsfml/fzanalyzer + supplements/gsfml/fzblender + supplements/gsfml/fzinformer + supplements/gsfml/fzmapper + supplements/gsfml/fzmodeler + supplements/gsfml/fzprofile + supplements/gsfml/mlconverter supplements/gshhg/gshhg supplements/img/img2grd supplements/mgd77/mgd77convert @@ -290,6 +297,13 @@ Supplemental Modules - :doc:`/supplements/geodesy/earthtide` - :doc:`/supplements/geodesy/gpsgridder` - :doc:`/supplements/geodesy/psvelo` + - :doc:`/supplements/gsfml/fzanalyzer` + - :doc:`/supplements/gsfml/fzblender` + - :doc:`/supplements/gsfml/fzinformer` + - :doc:`/supplements/gsfml/fzmapper` + - :doc:`/supplements/gsfml/fzmodeler` + - :doc:`/supplements/gsfml/fzprofiler` + - :doc:`/supplements/gsfml/mlconverter` - :doc:`/supplements/gshhg/gshhg` - :doc:`/supplements/img/img2grd` - :doc:`/supplements/mgd77/mgd77convert` @@ -605,6 +619,25 @@ geodesy | :doc:`/supplements/geodesy/psvelo` | |psvelo_purpose| | +--------------------------------------------+----------------------+ +GSFML +----- + ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzanalyzer` | |fzanalyzer_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzblender` | |fzblender_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzinformer` | |fzinformer_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzmapper` | |fzmapper_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzmodeler` | |fzmodeler_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzprofiler` | |fzprofiler_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/mlconverter` | |mlconverter_purpose| | ++---------------------------------------+-----------------------+ + GSHHG ----- diff --git a/doc/rst/source/modules.rst b/doc/rst/source/modules.rst index bfd740f3a8b..11e99be218d 100644 --- a/doc/rst/source/modules.rst +++ b/doc/rst/source/modules.rst @@ -304,6 +304,13 @@ Supplemental Modules - :doc:`/supplements/geodesy/earthtide` - :doc:`/supplements/geodesy/gpsgridder` - :doc:`/supplements/geodesy/velo` + - :doc:`/supplements/gsfml/fzanalyzer` + - :doc:`/supplements/gsfml/fzblender` + - :doc:`/supplements/gsfml/fzinformer` + - :doc:`/supplements/gsfml/fzmapper` + - :doc:`/supplements/gsfml/fzmodeler` + - :doc:`/supplements/gsfml/fzprofiler` + - :doc:`/supplements/gsfml/mlconverter` - :doc:`/supplements/gshhg/gshhg` - :doc:`/supplements/img/img2grd` - :doc:`/supplements/mgd77/mgd77convert` @@ -638,6 +645,25 @@ geodesy | :doc:`/supplements/geodesy/velo` | |velo_purpose| | +--------------------------------------------+----------------------+ +GSFML +----- + ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzanalyzer` | |fzanalyzer_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzblender` | |fzblender_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzinformer` | |fzinformer_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzmapper` | |fzmapper_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzmodeler` | |fzmodeler_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/fzprofiler` | |fzprofiler_purpose| | ++---------------------------------------+-----------------------+ +| :doc:`/supplements/gsfml/mlconverter` | |mlconverter_purpose| | ++---------------------------------------+-----------------------+ + GSHHG ----- diff --git a/doc/rst/source/pstext.rst b/doc/rst/source/pstext.rst index f706ec58d30..4c5eaf08fae 100644 --- a/doc/rst/source/pstext.rst +++ b/doc/rst/source/pstext.rst @@ -17,7 +17,7 @@ Synopsis |SYN_OPT-Rz| [ |-A| ] |SYN_OPT-B| -[ |-C|\ [*dx/dy*][**+to**\|\ **O**\|\ **c**\|\ **C**] ] +[ |-C|\ [*dx*\ [/*dy*]][**+to**\|\ **O**\|\ **c**\|\ **C**] ] [ |-D|\ [**j**\|\ **J**]\ *dx*\ [/*dy*][**+v**\ [*pen*]] ] [ |-F|\ [**+a**\ [*angle*]][**+c**\ [*justify*]][**+f**\ [*font*]][**+j**\ [*justify*]][**+h**\|\ **l**\|\ **r**\ [*first*] \|\ **t**\ *text*\|\ **z**\ [*format*]] ] [ |-G|\ [*fill*][**+n**] ] diff --git a/doc/rst/source/supplements/gsfml/fzanalyzer.rst b/doc/rst/source/supplements/gsfml/fzanalyzer.rst new file mode 100644 index 00000000000..9c1a9c453ad --- /dev/null +++ b/doc/rst/source/supplements/gsfml/fzanalyzer.rst @@ -0,0 +1,313 @@ +.. index:: ! fzanalyzer +.. include:: ../module_supplements_purpose.rst_ + +********** +fzanalyzer +********** + +|fzanalyzer_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**gmt fzanalyzer** *crossprofiles* +|-F|\ *fzlines* +[ |-A|\ *min*/*max*/*inc* ] +[ |-C|\ *min*/*max*/*inc* ] +[ |-D|\ *corrwidth* ] +[ |-I|\ *FZ*\ [/*profile*] ] +[ |-S|\ [**b**\|\ **c**]] +[ |-T|\ *prefix* ] +[ |SYN_OPT-V| ] +[ |-W|\ *min*/*max*/*inc* ] +[ |SYN_OPT-bo| ] +[ |SYN_OPT-do| ] +[ |SYN_OPT-i| ] +[ |SYN_OPT-o| ] +[ |SYN_OPT--| ] + +|No-spaces| + +Description +----------- + +**fzanalyzer** is a tool developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It reads processed fracture zone (FZ) traces and cross-profiles as +produced by :doc:`grdtrack `. It then analyzes the trace of each FZ +by examining cross-sections orthogonal to the FZ trend and modeling these profiles +using a blend model of "Atlantic"-style symmetric troughs and "Pacific"-style asymmetric, +dipole-like anomalies, modulated with some peripheral bulges ("compression"). +We also fit just the symmetric trough model and +examine the empirical data minimum and trough width. Estimates are made +of the width of the data trough and 1-sigma uncertainties on the best FZ locations +given by the various models. We also compute several statistical measures and return +all the model parameters as a function of distances along each FZ. + + +Required Arguments +------------------ + +*crossprofiles* + This file is a table with cross-profiles as produced by :doc:`grdtrack ` **-C** + from an approximate digitized trace (with *lon*, *lat*) of one or more FZs. + This is an ASCII (or binary, see **-bi**) file that must contain 7 data columns: + *lon, lat, dist, azimuth, vgg, age, fzdist*. + +.. _-F: + +**-F**\ *fzlines* + Here, *fzlines* is a file with resampled track lines obtained by running :doc:`grdtrack ` **-D**. + As for *crossprofiles* the file must contain the same 7 data columns *lon, lat, dist, azimuth, vgg, age, fzdist*. + See Input Files for more details. + +Optional Arguments +------------------ + +.. _-A: + +**-A**\ *min*/*max*/*inc* + Specifies one or three parameters that control how the blending of the model signals will be done. + Here, *min* is the minimum asymmetry value [0, i.e., "Atlantic" symmetric trough], + *max* is the maximum asymmetry [1], i.e., "Pacific" dipole signal], and *inc* is the + increment used for the search [0.05]. To specify just a single asymmetry value (no search), + just provide the single desired asymmetry. + +.. _-C: + +**-C**\ *min*/*max*/*inc* + Specifies one or three parameters that control how the search for the "compression" model signal will be done. + Here, *min* is the minimum compression value [0], *max* is the maximum compression [1, i.e., + "Mexican Hat" end-member], and *inc* is the increment used for the search [0.05]. + To specify just a single compression value (no search), just provide the single desired compression value.. + +.. _-D: + +**-D**\ *corrwidth* + Specifies a *corrwidth* (in km) that sets the width of the central corridor [25]. The purpose + of this corridor is to constrain how far off center we may seek to relocate the location of the FZ trough. + +.. _-I: + +**-I**\ *FZ*\ [/*profile*] + By default, we will analyze the cross-profiles generated for all FZs. However, + you can use |-I| to specify a particular FZ *id* id (first *id* is 0). + Optionally, you can select that only one *profile* from that FZ be processed [Default is all]. + Note that the output files will still contain all profiles but derived quantities will be + zero except for the chosen profiles. + +.. _-S: + + +**-S**\ [**b**\|\ **c**] + Output the parameters set by the command-line options in a format suitable for inclusion + in a Bourne/bash shell script. Alternatively, append **c** for csh/tcsh syntax. + +.. _-T: + +**-T**\ *prefix* + Sets the file name prefix used for all output files [fztrack]. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +.. _-W: + +**-W**\ *min*/*max*/*inc* + Specifies three parameters that control how the modeling of the cross-FZ signal will be done. + Here, *min* is the minimum FZ signal width (in km) for a nonlinear width search [1], + *max* is the maximum width [50], and *inc* is the increment used for the width search [1]. + It is recommended to determine suitable limits of a particular region and tune |-W| accordingly. + Selecting too wide a range might lead to spurious fits driven by data features not associated with + the FZ trough. + +.. |Add_-bo| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-bo.rst_ + +.. |Add_-do| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-do.rst_ + +.. include:: ../../explain_-icols.rst_ + +.. include:: ../../explain_-ocols.rst_ + +.. include:: ../../explain_-q.rst_ + +.. include:: ../../explain_help.rst_ + +Input Files +----------- + +The two input files are themselves generated by running :doc:`grdtrack ` first. This step +requires a set of digitized FZ tracks (*lon*, *lat*) and three data grids: (a) a +VGG vertical gravity gradient file, (b) a 2 minute crustal age grid, and (c) +a grid with distance to the nearest FZ in km, listed in that order. The critical file is the +VGG grid. If you don't have or care about ages and distances you can make dummy grids that +are all NaNs. You design your cross-profile layout and resampled FZ trackes using :doc:`grdtrack ` +options **-C** and **-D**.. + +Nearest Fracture Zone Distances +------------------------------- + +You can use :doc:`grdmath` to create the nearest fracture zone distance grid (in km) required +to prepare the profiles. A typical command suitable for the Nazca plate area might be:: + + gmt grdmath -R-120/-65/-50/5 -I5m -fg digitize.txt LDIST DEG2KM = dist2fz.nc + +Since this is a very slow calculation for numerous FZs it is not necessary to use a very high resolution +in |-I| since the distances change smoothly and interpolation will be approximately correct. Consider +making a global grid but do it in quadrants (or smaller region chunks) and run concurrently on a multi-core +computer. For example, to make a global grid from quadrants, one may run:: + + gmt grdmath -R0/180/0/90 -I2m -fg -V3 global_FZ.txt LDIST DEG2KM = WN.nc + gmt grdmath -R180/360/0/90 -I2m -fg -V3 FZ_KM.txt LDIST DEG2KM = EN.nc + gmt grdmath -R0/180/-90/0 -I2m -fg -V3 FZ_KM.txt LDIST DEG2KM = WS.nc + gmt grdmath -R180/360/-90/0 -I2m -fg -V3 FZ_KM.txt LDIST DEG2KM = ES.nc + +then blend these together into a global grid with:: + + gmt grdblend -Rg -I2 -fg EN.nc WN.nc ES.nc WS.nc -Gdist2FZ.nc -V + rm -f WN.nc EN.nc WS.nc ES.nc + +To make NaN grids for ages and/or distances for the Nazca area, use:: + + gmt grdmath -R-120/-65/-50/5 -I5m -fg 0 0 NaN = ages.nc + +Output Files +------------ + +**fzanalyzer** can produce up to three output files; these are described below: + + #. File *prefix*\ _analysis.txt contains the results of the analysis for each cross + profile. There 61 output columns containing the fitted or observed values (see + Determined Parameters). This file is used by :doc:`fzblender` to produce a smooth + and optimal fit to the fracture zone. + #. File *prefix*\ _cross.txt contains both observed and predicted best-fitting models + for each cross profile. It can be used for plotting and visual analysis of the + results on a profile-by-profile basis. + #. The *prefix*\ _par.[c]sh is either a Bourne (|-S|) or cshell (|-S|\ **c**) script + that contains all parameters specified by the command line as shell variables. You + can include this script in custom mapping or analysis scripts and use the variables + as you see fit. + #. Finally, while not an output file from **fzanalyzer**, you should use the name + *prefix*\ _resampled.txt for the output of :doc:`grdtrack ` **-D** as that is what the + scripts for plotting expect. + +Examples +-------- + +To analyze digitized FZs we use the Sandwell/Smith VGG (1 minute vertical gravity gradient +@earth_vgg_01m), a 1-minute age grid (@earth_ages_01m), and a nearest-FZ distance grid +(in km). Given the potential FZ locations in the multi-segment file fz_digitized.txt, we +specify a 40 km cross-profile length, with profiles spaced every 5 km, and use an +along-cross-profile sampling interval of 2 km, by running:: + + gmt grdtrack fz_digitized.txt -C40k/2k/5k -G@earth_vgg_01m -G@earth_ages_01m -Gdist.nc -Dtraces_resampled.txt -fg --FORMAT_GEO_OUT=ddd.xxxx --FORMAT_FLOAT_OUT=%.1f > xprofiles.txt + +These two data tables can now be used with **fzanalyzer** to analyze the traces. Here, +we specify a 20 km central corridor and accept default values for most settings:: + + gmt fzanalyzer xprofiles.txt -D20 -Ftraces_resampled.txt -Ttraces -S --FORMAT_GEO_OUT=ddd.xxxx --FORMAT_FLOAT_OUT=%.1f + +You can then make plots of these cross-profiles with best-fitting curves and parameters +indicated by using:: + + fzprofiler traces -W6i -H2i -N2 + +which will plot all cross-profiles in separate 6x2 inch cross-sections stacked in one vertical panel. +You can show this information in map view via:: + + fzmapper traces -W9i -L1 -Ffz_digitized.txt + +See the :doc:`fzprofiler` and :doc:`fzmapper` documentation for further details. + +Determined Parameters +--------------------- + +Here are the header codes for each of the 61 output columns and what they represent: + + - **XR**: Longitude of raw digitized trace. + - **YR**: Latitude of raw digitized trace. + - **DR**: Distance at digitized points along raw digitized trace. + - **AR**: Azimuth at digitized points along raw digitized trace. + - **ZR**: Data value at digitizing locations + - **TL**: Crustal age estimate at left side of FZ (negative distances). + - **TR**: Crustal age estimate at right side of FZ (positive distances). + - **SD**: Shift of data minimum (in km) from raw line origin. + - **ST**: Shift of trough model minimum (in km) from raw line origin. + - **SB**: Shift of blend model minimum (in km) from raw line origin. + - **SE**: Shift of blend model maximum slope (in km) from raw line origin. + - **BL**: Best blend value [0-1]. + - **OR**: Orientation of blend model profile (-1 means left side is old, +1 means left side is young). + - **WD**: Width of data trough. + - **WT**: Width of model trough (for trough model). + - **WB**: Width of model trough (for blend model). + - **AD**: Peak-to-trough amplitude from data. + - **AT**: Peak-to-trough amplitude from model (for trough model). + - **AB**: Peak-to-trough amplitude from model (blend). + - **UT**: Compression indicator (for trough model). + - **UB**: Compression indicator (for blend model). + - **VT**: Variance reduction (%) from model (for trough model). + - **VB**: Variance reduction (%) from model (for blend model). + - **FT**: F-statistic (for trough model). + - **FB**: F-statistic (for blend model). + - **XDL**: Longitude of data minimum left bounds. + - **XD0**: Longitude of data minimum. + - **XDR**: Longitude of data minimum right bounds. + - **YDL**: Latitude of data minimum left bounds. + - **YD0**: Latitude of data minimum. + - **YDR**: Latitude of data minimum right bounds. + - **ZDL**: Value of data minimum left bounds. + - **ZD0**: Value of data minimum. + - **ZDR**: Value of data minimum right bounds. + - **XTL**: Longitude of minimum (for trough model) left bounds. + - **XT0**: Longitude of minimum (for trough model). + - **XTR**: Longitude of minimum (for trough model) right bounds. + - **YTL**: Latitude of minimum (for trough model) left bounds. + - **YT0**: Latitude of minimum (for trough model). + - **YTR**: Latitude of minimum (for trough model) right bounds. + - **ZTL**: Model prediction (for trough model) at left bounds. + - **ZT0**: Model prediction minimum (for trough model). + - **ZTR**: Model prediction (for trough model) at right bounds. + - **XBL**: Longitude of minimum (for blend model) left bounds. + - **XB0**: Longitude of minimum (for blend model). + - **XBR**: Longitude of minimum (for blend model) right bounds. + - **YBL**: Latitude of minimum (for blend model) left bounds. + - **YB0**: Latitude of minimum (for blend model). + - **YBR**: Latitude of minimum (for blend model) right bounds. + - **ZBL**: Model prediction (for blend model) at left bounds. + - **ZB0**: Model prediction minimum (for blend model). + - **ZBR**: Model prediction (for blend model) at right bounds. + - **XEL**: Longitude of maximum slope (for blend model) left bounds. + - **XE0**: Longitude of maximum slope (for blend model). + - **XER**: Longitude of maximum slope (for blend model) right bounds. + - **YEL**: Latitude of maximum slope (for blend model) left bounds. + - **YE0**: Latitude of maximum slope (for blend model). + - **YER**: Latitude of maximum slope (for blend model) right bounds. + - **ZEL**: Model prediction at maximum slope (for blend model) at left bounds. + - **ZE0**: Model prediction at maximum slope (for blend model). + - **ZER**: Model prediction at maximum slope (for blend model) at right bounds. + +See Also +-------- + +:doc:`gmt ` +:doc:`fzblender `, +:doc:`fzinformer `, +:doc:`fzmapper `, +:doc:`fzmodeler `, +:doc:`fzprofiler `, +:doc:`grdmath `, +:doc:`grdtrack `, +:doc:`mlconverter ` + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/gsfml/fzblender.rst b/doc/rst/source/supplements/gsfml/fzblender.rst new file mode 100644 index 00000000000..b3c6d3e4371 --- /dev/null +++ b/doc/rst/source/supplements/gsfml/fzblender.rst @@ -0,0 +1,228 @@ +.. index:: ! fzblender +.. include:: ../module_supplements_purpose.rst_ + +********* +fzblender +********* + +|fzblender_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**gmt fzblender** [ |-D| ] +[ |-E|\ *sfilter* ] +[ |-F|\ *pfilter* ] +[ |-I|\ *FZid* ] +[ |-Q|\ *q_min*/*q_max* ] +[ |-S|\ **b**\|\ **d**\|\ **e**\|\ **t**\|\ **u**\ [*weight*] ] +[ |-T|\ *prefix* ] +[ |SYN_OPT-V| ] +[ |-Z|\ *acut*/*vcut*/*fcut*/*wcut* ] + +|No-spaces| + +Description +----------- + +**fzblender** is a tool developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It reads an analysis file produced by +:doc:`fzanalyzer` and optionally filters those results along track. Then, given the +specified signal codes we will produce an optimal FZ track that is a +weighted blend between the user's original digitized trace and one or more +of the model traces obtained by :doc:`fzanalyzer`. The blend is based on +quality indices determined for the model traces: If the quality index is +high we favor this track, else we favor the digitized line; in between values +leads to a weighted blend. We expect to read the analysis results from the +file *prefix*\ _analysis.txt produced by :doc:`fzanalyzer`; the blend results +will be written to file *prefix*\ _blend.txt. Optionally, the intermediate +filtered analysis file can be written to *prefix*\ _filtered.txt if |-D| is given. + +Optional Arguments +------------------ + +.. _-D: + +**-D** + Do not remove filtered output but save them to *prefix*\_filtered.txt. [By default we delete these intermediate files]. + +.. _-E: + +**-E**\ *sfilter* + Apply a secondary filter after the primary required filter has completed. + This is sometimes useful if you apply a robust filter first, which may result in + short length-scale noise after removing gross outliers. See |-F| for how to specify the filter. + +.. _-F: + +**-F**\ *pfilter* + Sets the along-track primary filter. Choose among convolution and non-convolution filters. + Append the filter directive followed by the full (6-sigma) *width*. Available convolution filters are: + + - **b**: Boxcar: All weights are equal. + - **c**: Cosine Arch: Weights follow a cosine arch curve. + - **g**: Gaussian: Weights are given by a Gaussian function. + + Non-convolution filters are: + + - **m**: Median: Returns median value. + - **p**: Maximum likelihood probability (a mode estimator): Return modal value. + If more than one mode is found we return their average value. Append **+l** or **+u** to + the filter width if you rather want to return the lowermost or uppermost of the modal + values. + - **l**: Lower: Return the minimum of all values. + - **L**: Lower: Return minimum of all positive values only. + - **u**: Upper: Return maximum of all values. + - **U**: Upper: Return maximum or all negative values only. + + In the case of **L**\|\| **U** it is possible that no data passes the initial sign test; + in that case the filter will return 0.0. + +.. _-I: + +**-I**\ *FZid* + By default, we will analyze the cross-profiles generated for all FZs. However, + you can use |-I| to specify a particular *FZid* (first *FZid* is 0). + +.. _-Q: + +**-Q**\ *q_min*/*q_max* + Sets the range of quality indices that will be used in the blended result. + The quality index *q(d)* ranges from *q_min*) (0 or bad) to *q_max* (1 or very good) and varies + continuously with distance *d* along the FZ trace. The quality weight assigned to + the modeled FZ trace is *w_q(d)* = (*q(d)* - *q_min*)/(*q_max* - *q_min*)), + unless *w_q(d)* > *q_max*) (*w_q(d)* = 1) or *w_q(d)* < *q_min*) (*w_q(d)* = 0). You can use the |-Q| + option to change this weight assignment. The quality weight assigned to the digitized FZ trace is + *w_q(d)* = 1 - mean{model quality weights} (see |-S|). For the calculation of quality indices, see |-Z|. + +.. _-S: + +**-Sb**\|\ **d**\|\ **e**\|\ **t**\|\ **u**\ [*weight*] + Specify the model and data traces you wish to blend and the relative custom weights + of each [Defaults to 1 for all traces]. Repeat this option for each trace to consider. + If you specify more than one model trace then the models are first averaged according to their quality + indices and weights before blending with the digitized trace (if specified). Hence, the quality index assigned + to the digitized trace is *q_r* = 1 - mean(model quality indices). The final blend is thus a weighted + average that takes into account both the quality indices and the custom weights (if specified). + Choose among these directives: + + - **b**: The trough location for the optimal trough/edge model blend model. This is the best fit obtained to the data using + a blend of "Atlantic"-, "Pacific"-, and "Compression"-style synthetic shapes. + - **d**: This is the empirical picks of the trough locations along the trace. + - **e**: This is the location of maximum slope for the optimal trough/edge model blend model. + - **t**: This is the best fit using the "Atlantic"-style trough model only. + - **u**: The user's original digitized trace. + + In addition to the blended FZ locations, we also output estimates of the FZ width and the traces + of the 1-sigma boundaries on either side of the FZ. + +.. _-T: + +**-T**\ *prefix* + Sets the file name prefix used for all output files [fztrack]. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +.. _-Z: + +**-Z**\ *acut*/*vcut*/*fcut*/*wcut* + We will attempt to assign a single quality index *Q* that summarize how good we + believe a model fit to be. This assignment relies of four threshold values + that need to be determined empirically. Here, *a_cut* is the minimum peak-to-trough amplitude + (in Eotvos) of a model for the crossing profile [25], *v_cut* is the minimum + variance reduction offered by the model (in %) [50], *f_cu* is + the minimum F statistic computed for the model [50], and *w_cut* is a typical + FZ trough width (in km) [15]. Currently, the first three quantities + are used to arrive at a 5-level quality index (0-1) for fitted models, as follows: (1) Very Good: Requires + model parameters to exceed all three thresholds; (0.75) Good: Requires amplitude and + variance reduction to exceed thresholds; (0.5) Fair: Requires the variance reduction only + to exceed its threshold; (0.25) Poor: Requires the amplitude only to exceed its threshold; + and (0) Bad: None of the criteria were met. We compute separate quality indices for the + trough and blend models. For the empirical trough model we only have estimates or peak-to-trough + amplitude, *A*, and trough width, *W*. Here, we form the ratio (*A*/*a_cut*) over + (*W*/*w_cut*), take :math:`\tan^{-1}` of this ratio and scale the result to yield the range 0-1 rounded + to the nearest multiple of 0.25. + +.. |Add_-bo| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-bo.rst_ + +.. |Add_-do| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-do.rst_ + +.. include:: ../../explain_-icols.rst_ + +.. include:: ../../explain_-ocols.rst_ + +.. include:: ../../explain_-q.rst_ + +.. include:: ../../explain_help.rst_ + +.. include:: ../../explain_precision.rst_ + +Output Columns +-------------- + +**fzblender** reports 10 columns of data, which are *lon, lat, dist, shift, width, +qweight, lon_l, lat_l, lon_r, lat_r*, where *lon, lat* contain the blended track +along *dist*, with across-track *widt* and *shift* in origin. The blend +obtained a quality weight of *qweight*, and the four last columns contains the +coordinates for the left/right bounds along the FZ. + +Filtering +--------- + +Filtering always runs of of data near the FZ end points. We utilize :doc:`filter1d ` with its +**-E** option to extend the result to the end. Because we are filtering data columns that may +contain a strong trend (e.g., longitude versus along-track distance) we first remove such +linear trends before filtering, then restore the trends before blending. However, you should +be cautions in interpreting the blended results close to the ends of the FZs. You can examine +the effect of filtering more directly by using the |-D| option to save the filtered profiles. + +Blend Considerations +-------------------- + +Note that of the various directives in |-S|, the **e** is different in that it reflects +the FZ location estimate based on the theoretical prediction that the FZ crossing may be +associated with the steepest VGG slope. As such it will be offset from the trough by +several km (unless the blend is mostly "Atlantic") and combining it with the others +is unlikely to be productive. It is best used by itself with filtering. + +Examples +-------- + +To produce a weighted average of your digitized trace, the empirical trough locations, +and the trough model locations, giving the empirical locations a weight of 2 and the +model troughs a weight of 1, reading the file Pac_analysis.txt and selecting a median +filter of 70 km width followed by a 50-km Gaussian filter, try:: + + gmt fzblender -Su1 -Sd2 -St1 -Fm70 -Eg50 -TPac + +To produce a smooth trace of the maximum slope locations along track for the +same file, we try the same filters with the command:: + + gmt fzblender -Se -Fm70 -Eg50 -TPac + +See Also +-------- + +:doc:`gmt ` +:doc:`fzanalyzer `, +:doc:`fzinformer `, +:doc:`fzmapper `, +:doc:`fzmodeler `, +:doc:`fzprofiler `, +:doc:`filter1d `, +:doc:`mlconverter ` + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/gsfml/fzinformer.rst b/doc/rst/source/supplements/gsfml/fzinformer.rst new file mode 100644 index 00000000000..fe067ac3a9a --- /dev/null +++ b/doc/rst/source/supplements/gsfml/fzinformer.rst @@ -0,0 +1,161 @@ +.. index:: ! fzinformer +.. include:: ../module_supplements_purpose.rst_ + +********** +fzinformer +********** + +|fzinformer_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**fzinformer** [ |-D| ] +[ |-F|\ *max* ] +[ |-I|\ *profile* ] +[ |-N|\ *max* ] +[ |-S|\ *max* ] +[ |-T|\ *prefix* ] +[ |-W|\ *max* ] +[ |SYN_OPT-V| ] + +|No-spaces| + +Description +----------- + +**fzinformer** is a script developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It make plots of statistical information obtained +by :doc:`fzanalyzer` as a function of position along a fracture zone (FZ). + +Optional Arguments +------------------ + +.. _-D: + +**-D** + Use the filtered output from :doc:`fzblender` instead of the raw analysis file in making + the plot. This requires that you ran :doc:`fzblender` with the **-D** option. + +.. _-F: + +**-F**\ *max* + Sets the maximum *F*-statistic amplitude for the plot [10000]. A logarithmic + scale is used for this panel; all others are linear. + +.. _-I: + +**-I**\ *profile* + By default we plot all the cross-profiles in one stack. To select a single + profile only, append the running number of the profile, where 0 is the first profile. + +.. _-N: + +**-N**\ *max* + Sets the maximum range of VGG amplitudes (in Eotvos) for the plot [200]. + +.. _-S: + +**-S**\ *max* + Sets the maximum (±) half-range of FZ offsets (in km) [25]. + +.. _-T: + +**-T**\ *prefix* + Sets the file name prefix used when running :doc:`fzanalyzer` and :doc:`fzblender` + [The default is fztrack]. The files used here are *prefix*\ _analysis.txt + (or *prefix*\ _filtered.txt if |-D| is used) and *prefix*\ _blend.txt. + +.. _-W: + +**-W**\ *max* + Sets the maximum range of FZ widths (in km) [50]. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +.. _-Z: + +**-Z**\ *acut*/*vcut*/*fcut*/*wcut* + We will attempt to assign a single quality index *Q* that summarize how good we + believe a model fit to be. This assignment relies of four threshold values + that need to be determined empirically. Here, *a_cut* is the minimum peak-to-trough amplitude + (in Eotvos) of a model for the crossing profile [25], *v_cut* is the minimum + variance reduction offered by the model (in %) [50], *f_cut* is + the minimum *F* statistic computed for the model [50], and *w_cut* is a typical + FZ trough width (in km) [15]. Currently, the first three quantities + are used to arrive at a 5-level quality index (0-1) for fitted models, as follows: (1) Very Good: Requires + model parameters to exceed all three thresholds; (0.75) Good: Requires amplitude and + variance reduction to exceed thresholds; (0.5) Fair: Requires the variance reduction only + to exceed its threshold; (0.25) Poor: Requires the amplitude only to exceed its threshold; + and (0) Bad: None of the criteria were met. We compute separate quality indices for the + trough and blend models. For the empirical trough model we only have estimates or peak-to-trough + amplitude, |-A|, and trough width, |-W|. Here, we form the ratio (*A*/*a_cut*) over + (*W*/*w_cut*), take :math:`\tan^{-1}` of this ratio and scale the result to yield the range 0-1 rounded + to the nearest multiple of 0.25. + +.. |Add_-bo| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-bo.rst_ + +.. |Add_-do| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-do.rst_ + +.. include:: ../../explain_-icols.rst_ + +.. include:: ../../explain_-ocols.rst_ + +.. include:: ../../explain_-q.rst_ + +.. include:: ../../explain_help.rst_ + +Plot Features +------------- + +**fzinformer** packs much information into each plot by using different symbols and +colors. Empirical information obtained from raw data are shown in red. Information +derived from a forced trough FZ model are shown in green, while the information derived +from the optimal blend model are shown in blue. We present 7 panels for each FZ. Panel +1 (top) shows how the *F*-statistic parameter varies with distance for the trough (green) +and blend (blue) models. Panel 2 shows the reduction in variance for the same two models. +Panel 3 shows the maximum amplitude for the two models and the empirical data (red). +Panel 4 shows the width of the FZ signal for all three data. Panel 5 presents the offset +(in km) between the digitized trace and the optimal FZ locations (one curve for each type). +Panel 6 shows which side (left is -1, right = +1) is the young side assuming a Pacific +edge-anomaly model (it will tend to jump back and forth where the signal is close to +symmetric and should only be used when we have clearly asymmetric signals). Finally, panel 7 shows +the compression parameter *C* for the blend and trough models, as well as the blend parameter *A* +(black line) for the optimal blend model. + +Examples +-------- + +To look at the statistics for the 5th (0 is first) FZ analyzed as part of a larger group called traces, +accepting default values except we override the maximum amplitude by using 100, +try:: + + fzinformer -Ttraces -N100 -I5 + +The statistical plot will be named *prefix*\ _stat.pdf. + +See Also +-------- + +:doc:`gmt ` +:doc:`fzanalyzer `, +:doc:`fzblender ` +:doc:`mlconverter `, +:doc:`fzmapper `, +:doc:`fzmodeler `, +:doc:`fzprofiler ` + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/gsfml/fzmapper.rst b/doc/rst/source/supplements/gsfml/fzmapper.rst new file mode 100644 index 00000000000..f4b56bfaf76 --- /dev/null +++ b/doc/rst/source/supplements/gsfml/fzmapper.rst @@ -0,0 +1,117 @@ +.. index:: ! fzmapper +.. include:: ../module_supplements_purpose.rst_ + +******** +fzmapper +******** + +|fzmapper_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**fzmapper** [ |-A| ] +[ |-F|\ *origfile* ] +[ |-G|\ *vgg_grid* ] +[ |-L|\ *labelint* ] +[ |-O| ] +[ |-S| ] +[ |-T|\ *prefix* ] +[ |SYN_OPT-V| ] +[ |-W|\ *width*\ [**c**\|\ **i**\|\ **p**] ] + +|No-spaces| + +Description +----------- + +**fzmapper** is a Bash script developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It make a Mercator map of cross-profiles from the +processed fracture zone (FZ) traces and cross-profiles as +produced by :doc:`grdtrack `. Optionally, overlay analysis and blend results. + +Optional Arguments +------------------ + +.. _-A: + +**-A** + In addition to the resampled FZ trace and the cross-profiles, overlay the + result of :doc:`fzanalyzer` as color-coded points (red for data, green for trough, + and blue for blend model) [No model results]. + +.. _-F: + +**-F**\ *profile* + This is the original digitized FZ traces that was given as input to:doc:`grdtrack `. + +.. _-G: + +**-G**\ *vgg_grid* + Optionally, supply the name of the VGG grid to use as background [@earth_vgg_02m]. + +.. _-O: + +**-O** + Instead of making a stand-alone PDF plot, write a PostScript overlay to stdout, + i.e., make the plot using the GMT **-O -K** options. + +.. _-S: + +**-S** + Overlay the smoothed FZ trace produced by :doc:`fzblender` [no overlay]. + +.. _-T: + +**-T**\ *prefix* + Sets the file name prefix used for all input files as produced by + :doc:`fzanalyzer` [default is fztrack]. The files are *prefix*\ _cross.txt and + *prefix*\ _par.txt as well as the resampled output from :doc:`grdtrack ` which + should be called *prefix*\ _resampled.txt. When |-S| is set we also look for *prefix*\ _blend.txt + as produced by :doc:`fzblender`, and with |-A| we also look for *prefix*\ _analysis.txt. + +.. _-W: + +**-W**\ *width*\ [**c**\|\ **i**\|\ **p**] + Sets the *width* of the Mercator map. Unless the measure unit is appended the + unit is assumed to be whatever the GMT default :term:`PROJ_LENGTH_UNIT` is currently set to. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +Examples +-------- + +To look at the cross-profiles and the best-fit models and optimal FZ locations in +map view, with the prefix used previously as "traces", using a 9 inch wide Mercator, +and only label every other profile, try:: + + fzmapper -Ttraces -W9i -L2 -Fguides.txt -S -V -A + +where we use the original digitized FZ locations guides.txt, choosing to annotate every +other profile. The final map will be named *prefix*\ _map.pdf. For cross-section +profiles, see :doc:`fzprofiler`. + +See Also +-------- + +:doc:`gmt ` +:doc:`fzanalyzer `, +:doc:`fzblender `, +:doc:`mlconverter `, +:doc:`fzinformer `, +:doc:`fzmodeler `, +:doc:`fzprofiler `, +:doc:`grdtrack ` + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/gsfml/fzmodeler.rst b/doc/rst/source/supplements/gsfml/fzmodeler.rst new file mode 100644 index 00000000000..53cd53ccc61 --- /dev/null +++ b/doc/rst/source/supplements/gsfml/fzmodeler.rst @@ -0,0 +1,150 @@ +.. index:: ! fzmodeler +.. include:: ../module_supplements_purpose.rst_ + +********* +fzmodeler +********* + +|fzmodeler_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**fzmodeler** [ |-A|\ *asymmetry* ] +[ |-C|\ *compression* ] +[ |-D|\ *min*/*max*/*inc* ] +[ |-G|\ *comp* ] +[ |-M| ] +[ |-N|\ *amplitude* ] +[ |-O| ] +[ |-P| ] +[ |-S|\ *shift* ] +[ |-T|\ *prefix* ] +[ |SYN_OPT-V| ] +[ |-W|\ *width* ] + +|No-spaces| + +Description +----------- + +**zmodeler** is a script developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It builds a synthetic model cross-profile given +the chosen model parameters and optionally images the profile via a PDF plot. The +model evaluated is :math:`z(x) = A[mG_1 + (1-m)(uG_2 - G_0)]`, where *A* is amplitude (|-N|), +*m* is asymmetry (|-A|), and *u* is compression (|-C|). Here :math:`G_0` is the Gaussian +function, while :math:`G_1` and :math:`G_2` are the first two horizontal derivatives. +**Note**: The blend model subtracts Here :math:`G_0` since for fracture zones we want the negative Gaussian. + +.. _GFSML_model: + +.. figure:: /_images/GMT_gsfml_components.* + :width: 500 px + :align: center + + Three components (the Gaussian and its two first derivatives) can be used to create a blended + model that matches a FZ-crossing VGG anomaly. Modeling may also require a linear trend. + +Optional Arguments +------------------ + +.. _-A: + +**-A**\ *asymmetry* + Sets the asymmetry parameter used for the blend between symmetric ("Atlantic") + and asymmetric ("Pacific") signals [0]. + +.. _-C: + +**-C**\ *compression* + Sets the amount of compression (0-1) to use in the blending [0]. + +.. _-D: + +**-D**\ *min*/*max*/*inc* + Sets the domain for which to evaluate the model. If |-M| is used then + the domain is expected to be in km; otherwise *min* and *max* will be + expected to be in degrees of latitude which *inc* will be decoded as + arc minutes [-5/5/2 or -100/100/2, depending on |-M|]. + +.. _-G: + +**-G**\ *comp* + Only plot component :math:`G_i(x)`, where i = 0, 1, or 2 + +.. _-M: + +**-M** + The chosen domain (|-D|) is given degrees of latitude, with increment in arc minutes + [Default is in km]. + +.. _-N: + +**-N**\ *amplitude* + Sets the peak-to-trough amplitude of the blended signal [100]. + +.. _-O: + +**-O** + Instead of making a stand-alone PDF plot, write a PostScript overlay to stdout, + i.e., make the plot using the GMT classic code **-O -K** options. Requires (or sets) |-P|. + +.. _-P: + +**-P** + Produce a PDF plot (named *prefix*.pdf) of the synthetic FZ profile [no plot]. + +.. _-S: + +**-S**\ *shift* + Sets the shift of the FZ location from the origin, in km [0]. + +.. _-T: + +**-T**\ *prefix* + Set the output prefix for the model profile [fzprof]. Give |-T|\ **-** to send + the model profile to stdout. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +.. _-W: + +**-W**\ *width* + Sets the full width of the FZ, in km [25]. + +Examples +-------- + +To plot a synthetic profile for the Pacific, using otherwise default arguments, +try:: + + fzmodeler -C1 -V + +The final plot will be named *prefix*.pdf, with the model data in *prefix*.txt. +To just plot normalized component :math:`G_2(x)`, try:: + + fzmodeler -D-30/30/1 -C1 -N1 -W10 -G2 -T- | gmt plot -W1p -B -R-30/30/-1/1 -png G2 + +See Also +-------- + +:doc:`gmt ` +:doc:`fzanalyzer `, +:doc:`fzblender ` +:doc:`mlconverter `, +:doc:`fzinformer `, +:doc:`fzprofiler `, +:doc:`fzmapper `, + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/gsfml/fzprofiler.rst b/doc/rst/source/supplements/gsfml/fzprofiler.rst new file mode 100644 index 00000000000..b882e461383 --- /dev/null +++ b/doc/rst/source/supplements/gsfml/fzprofiler.rst @@ -0,0 +1,123 @@ +.. index:: ! fzprofiler +.. include:: ../module_supplements_purpose.rst_ + +********** +fzprofiler +********** + +|fzprofiler_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**fzprofiler** [ |-H|\ *height*\ [**c**\|\ **i**\|\ **p**] ] +[ |-I|\ *profile* ] +[ |-L|\ *inc* ] +[ |-M|\ *ncols* ] +[ |-T|\ *prefix* ] +[ |SYN_OPT-V| ] +[ |-W|\ *width*\,[**c**\|\ **i**\|\ **p**] ] + +|No-spaces| + +Description +----------- + +**fzprofiler** is a script developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It plots the cross-profiles and the information produced by :doc:`fzanalyzer`. +All plots are combined into one plot using whatever custom page size is needed to fit the individual plots given +their specifications. + +Optional Arguments +------------------ + +.. _-H: + +**-H**\ *width*\ [**c**\|\ **i**\|\ **p**] + Sets the plot height of an individual profile. Unless the measure unit is appended the + unit is assumed to be whatever the GMT default :term:`PROJ_LENGTH_UNIT` is currently set to. + +.. _-I: + +**-I**\ *profile* + By default we plot all the cross-profiles in one stack. To select a single + profile only, append the running number of the profile, where 0 is the first profile. + +.. _-L: + +**-L**\ *inc* + Determines which profiles to plot. By default we plot every profile (*inc* = 1). + Use |-L| to plot every *inc* profile instead [1]. + +.. _-N: + +**-N**\ *ncols* + Spread profiles across *ncols* columns. If *ncols* = 1 + then all profiles are stacked vertically in one long panel; if *ncols* = 2 + then we split the profiles evenly between two columns, etc. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +**-T**\ *prefix* + Sets the file name *prefix* used for all input files as produced by + :doc:`fzanalyzer` [default is fztrack]. The files are *prefix*\ _cross.txt, *prefix*\ _analysis.txt, + *prefix*\ _par.txt as well as the resampled output from :doc:`grdtrack` which + should be called *prefix*\ _resampled.txt. + +.. _-W: + +**-W**\ *width*\ [**c**\|\ **i**\|\ **p**] + Similarly sets the plot width of an individual profile. For units, see |-H|. + +Plot Features +------------- + +**fzprofiler** packs much information into each plot by using different symbols and +colors. The cross-profile VGG data are plotted as red circles connected by a faint +red dotted line. The central corridor set with :doc:`fzanalyzer` **-D** is shown in light +blue. Black line is the best symmetric +trough model; inverted triangle indicates the best location of the FZ (trough) and +its error bars reflect the half-width. Blue line is the best asymmetric blend model; +circle shows the best location of the maximum VGG slope. Finally, the inverted +red triangle and half-width error bar shows the best empirical trough location. Dashed +orange line shows the crustal age variations. Profile orientation is +indicated by the W-E or S-N letters, with vertical scale shown on the left (VGG) and +right (age). Finally, each panel prints the best blend parameters. + +Examples +-------- + +To look at the cross-profiles and the best-fit models and optimal FZ locations on +a per-profiles basis, with the prefix used previously as "traces", and placing the +profiles into two columns, each 6 inches wide with individual plots 2 inches tall, +try:: + + fzprofiler -Ttraces -W6i -H2i -N2 -V + +The final plot will be named *prefix*\ _cross.pdf. To see the same profiles in map +view, use :doc:`fzmapper`. To plot a synthetic profile, see :doc:`fzmodeler`. + +See Also +-------- + +:doc:`gmt ` +:doc:`fzanalyzer `, +:doc:`fzblender `, +:doc:`mlconverter `, +:doc:`fzinformer `, +:doc:`fzmodeler `, +:doc:`fzmapper `, +:doc:`grdtrack ` + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/gsfml/mlconverter.rst b/doc/rst/source/supplements/gsfml/mlconverter.rst new file mode 100644 index 00000000000..b72c1560b59 --- /dev/null +++ b/doc/rst/source/supplements/gsfml/mlconverter.rst @@ -0,0 +1,121 @@ +.. index:: ! mlconverter +.. include:: ../module_supplements_purpose.rst_ + +*********** +mlconverter +*********** + +|mlconverter_purpose| + +Synopsis +-------- + +.. include:: ../../common_SYN_OPTs.rst_ + +**gmt mlconverter** [ *ML_data* ] +[ |-A| ] +[ |-G|\ [**s**] ] +[ |-I|\ *FZid* ] +[ |-T|\ **c**\ |\ **g**\ |\ **o**\ |\ **s** ] +[ GMT_V_OPT ] + +|No-spaces| + +Description +----------- + +**mlconverter** is a module developed as part of the Global Seafloor Fabric +and Magnetic Lineation Project [see `GSFML `_ for a full +description of the project]. It reads a magnetic pick data file (or stdin) +and converts chron text-strings to ages using a selected magnetic time scale. +The input data must be OGR/GMT data files of the form distributed by the +GSFML project. + +Optional Arguments +------------------ + +*ML_data* + A magnetic ML pick data OGR/GMT file. If not given then we read standard input. + +.. _-A: + +**-A** + Append the metadata to the output records as additional columns [Default only + writes *lon*, *lat*, *age* records]. + +.. _-G: + +**-G**\ [**s**] + Generate an extended OGR/GMT table by appending the crustal age. + Append **s** to repair any lax chron nomenclature, if needed. + +.. _-T: + +**-Tc**\ |\ **g**\ |\ **o**\ |\ **s** + Select the magnetic time scale to use. Choose from **c** (Cande and Kent, 1995), + **g** (Gee and Kent, 2007), **o** (Ogg, 2012), or **s** (Gradstein, 2004) [**g**]. + +.. |Add_-V| replace:: |Add_-V_links| +.. include:: ../../explain_-V.rst_ + :start-after: **Syntax** + :end-before: **Description** + +.. _-Z: + +**-Z**\ *acut*/*vcut*/*fcut*/*wcut* + We will attempt to assign a single quality index *Q* that summarize how good we + believe a model fit to be. This assignment relies of four threshold values + that need to be determined empirically. Here, *a_cut* is the minimum peak-to-trough amplitude + (in Eotvos) of a model for the crossing profile [25], *v_cut* is the minimum + variance reduction offered by the model (in %) [50], *f_cu* is + the minimum *F* statistic computed for the model [50], and *w_cut* is a typical + FZ trough width (in km) [15]. Currently, the first three quantities + are used to arrive at a 5-level quality index (0-1) for fitted models, as follows: (1) Very Good: Requires + model parameters to exceed all three thresholds; (0.75) Good: Requires amplitude and + variance reduction to exceed thresholds; (0.5) Fair: Requires the variance reduction only + to exceed its threshold; (0.25) Poor: Requires the amplitude only to exceed its threshold; + and (0) Bad: None of the criteria were met. We compute separate quality indices for the + trough and blend models. For the empirical trough model we only have estimates or peak-to-trough + amplitude, *A*, and trough width, *W*. Here, we form the ratio (*A*/*a_cut*) over + (*W*/*w_cut*), take :math:`\tan^{-1}` of this ratio and scale the result to yield the range 0-1 rounded + to the nearest multiple of 0.25. + +.. |Add_-bo| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-bo.rst_ + +.. |Add_-do| unicode:: 0x20 .. just an invisible code +.. include:: ../../explain_-do.rst_ + +.. include:: ../../explain_-icols.rst_ + +.. include:: ../../explain_-ocols.rst_ + +.. include:: ../../explain_-q.rst_ + +.. include:: ../../explain_help.rst_ + +Examples +-------- + +To convert chrons to ages using the Cande and Kent, 1995 timescale, and append the +metadata at the end of the record, try:: + + gmt mlconverter -A -Tc ML_datafile.gmt > convertedfile.txt + +See Also +-------- + +:doc:`gmt ` +:doc:`fzanalyzer `, +:doc:`fzblender `, +:doc:`fzinformer `, +:doc:`fzmapper `, +:doc:`fzmodeler `, +:doc:`fzprofiler ` + +References +---------- + +Wessel, P., Matthews, K. J., Müller, R. D., Mazzoni, A., Whittaker, J. M., Myhill, R., Chandler, M. T., +2015, "Semiautomatic fracture zone tracking", *Geochem. Geophys. Geosyst.*, 16 (7), 2462–2472. +https://doi.org/10.1002/2015GC005853. diff --git a/doc/rst/source/supplements/module_supplements_purpose.rst_ b/doc/rst/source/supplements/module_supplements_purpose.rst_ index 22de57ec8e5..6393effa433 100644 --- a/doc/rst/source/supplements/module_supplements_purpose.rst_ +++ b/doc/rst/source/supplements/module_supplements_purpose.rst_ @@ -8,6 +8,12 @@ .. |psvelo_purpose| replace:: Plot velocity vectors, crosses, anisotropy bars and wedges +.. |fzanalyzer_purpose| replace:: Analysis of fracture zones using crossing profiles + +.. |fzblender_purpose| replace:: Produce a smooth blended FZ trace + +.. |mlconverter_purpose| replace:: Convert chrons to ages using selected magnetic timescale + .. |gshhg_purpose| replace:: Extract data tables from binary GSHHG or WDBII data files .. |img2grd_purpose| replace:: Extract a subset from an img file in Mercator or Geographic format @@ -120,3 +126,11 @@ .. |x2sys_solve_purpose| replace:: Determine least-squares systematic correction from crossovers +.. |fzinformer_purpose| replace:: Bash script to plot statistical information related to fracture zones + +.. |fzmapper_purpose| replace:: Bash script to plot fracture zone cross-profiles on a Mercator map + +.. |fzmodeler_purpose| replace:: Bash script to build fracture zone cross-profile model + +.. |fzprofiler_purpose| replace:: Bash script to plot fracture zone cross-profiles + diff --git a/doc/rst/source/text.rst b/doc/rst/source/text.rst index 3ba4a028255..ddbf5119316 100644 --- a/doc/rst/source/text.rst +++ b/doc/rst/source/text.rst @@ -17,7 +17,7 @@ Synopsis |SYN_OPT-Rz| [ |-A| ] [ |SYN_OPT-B| ] -[ |-C|\ [*dx/dy*][**+to**\|\ **O**\|\ **c**\|\ **C**] ] +[ |-C|\ [*dx*\ [/*dy*]][**+to**\|\ **O**\|\ **c**\|\ **C**] ] [ |-D|\ [**j**\|\ **J**]\ *dx*\ [/*dy*][**+v**\ [*pen*]] ] [ |-F|\ [**+a**\ [*angle*]][**+c**\ [*justify*]][**+f**\ [*font*]][**+j**\ [*justify*]][**+h**\|\ **l**\|\ **r**\ [*first*] \|\ **t**\ *text*\|\ **z**\ [*format*]] ] [ |-G|\ [*fill*][**+n**] ] @@ -148,12 +148,13 @@ Optional Arguments .. _-C: -**-C**\ [*dx/dy*][**+to**\|\ **O**\|\ **c**\|\ **C**] +**-C**\ [*dx*\ [/*dy*]][**+to**\|\ **O**\|\ **c**\|\ **C**] Adjust the clearance between the text and the surrounding box [15%]. Only used if |-W| or |-G| are specified. Append the unit you want (**c**\ m, **i**\ nch, or **p**\ oint; if not given we consult :term:`PROJ_LENGTH_UNIT`) or % for a percentage of the font size. - Optionally, use modifier **+t** to set the shape of the textbox when using |-G| and/or |-W|. + If *dy* is not specified then it is set equal to *dx*. Optionally, + use modifier **+t** to set the shape of the textbox when using |-G| and/or |-W|. Append lower case **o** to get a straight rectangle [Default]. Append upper case **O** to get a rounded rectangle. In paragraph mode (|-M|) you can also append lower case **c** to get a concave diff --git a/doc/scripts/GMT_gsfml_components.sh b/doc/scripts/GMT_gsfml_components.sh new file mode 100755 index 00000000000..368531bcf1d --- /dev/null +++ b/doc/scripts/GMT_gsfml_components.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Plot the three building blocks G0, G1, G2 in a normalized way +gmt begin GMT_gsfml_components + fzmodeler -D-30/30/0.1 -N1 -W10 -G0 -T- | gmt plot -W1p,red -Bxafg5 -Byafg1 -R-30/30/-1.1/1.1 -JX15c/-4c -l"-G@-0@-" + fzmodeler -D-30/30/0.1 -N1 -W10 -A1 -G1 -T- | gmt plot -W1p,green -JX15c/4c -l"G@-1@-" + fzmodeler -D-30/30/0.1 -N1 -W10 -C1 -G2 -T- | gmt plot -W1p,blue -l"G@-2@-" +gmt end show diff --git a/doc/scripts/images/GMT_gsfml_components.ps.dvc b/doc/scripts/images/GMT_gsfml_components.ps.dvc new file mode 100644 index 00000000000..e62dd375e64 --- /dev/null +++ b/doc/scripts/images/GMT_gsfml_components.ps.dvc @@ -0,0 +1,5 @@ +outs: +- md5: 93ed456e06d5c1f9d6acc2fc98e49fbf + size: 29551 + hash: md5 + path: GMT_gsfml_components.ps diff --git a/src/gmt_make_module_purpose.sh b/src/gmt_make_module_purpose.sh index 8b92dd243fd..718cfc93794 100755 --- a/src/gmt_make_module_purpose.sh +++ b/src/gmt_make_module_purpose.sh @@ -59,4 +59,17 @@ while read program; do done < ${TMPDIR}/gmt_supplements_modules.lst rm -f ${TMPDIR}/gmt_supplements_modules.lst +# Add purpose for a few GSFML bash scripts (i.e, not .c code) + +cat <<- EOF >> ${FILE_SUPPL_MODULE_PURPOSE} +.. |fzinformer_purpose| replace:: Bash script to plot statistical information related to fracture zones + +.. |fzmapper_purpose| replace:: Bash script to plot fracture zone cross-profiles on a Mercator map + +.. |fzmodeler_purpose| replace:: Bash script to build fracture zone cross-profile model + +.. |fzprofiler_purpose| replace:: Bash script to plot fracture zone cross-profiles + +EOF + echo "Writing done" diff --git a/src/gsfml/CK1995n.h b/src/gsfml/CK1995n.h new file mode 100644 index 00000000000..b676949c35c --- /dev/null +++ b/src/gsfml/CK1995n.h @@ -0,0 +1,231 @@ +{ 0, 0.78 }, +{ 0.99, 1.07 }, +{ -1.0, -1.0 }, +{ 1.77, 1.95 }, +{ 2.14, 2.15 }, +{ 2.581, 3.04 }, +{ 3.11, 3.22 }, +{ 3.33, 3.58 }, +{ 4.18, 4.29 }, +{ 4.48, 4.62 }, +{ 4.8, 4.89 }, +{ 4.98, 5.23 }, +{ 5.894, 6.137 }, +{ 6.269, 6.567 }, +{ 6.935, 7.091 }, +{ 7.135, 7.17 }, +{ 7.341, 7.375 }, +{ 7.432, 7.562 }, +{ 7.65, 8.072 }, +{ 8.225, 8.257 }, +{ -1.0, -1.0 }, +{ 8.699, 9.025 }, +{ -1.0, -1.0 }, +{ 9.23, 9.308 }, +{ 9.58, 9.642 }, +{ 9.74, 9.88 }, +{ 9.92, 10.949 }, +{ 11.052, 11.099 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 11.476, 11.531 }, +{ -1.0, -1.0 }, +{ 11.935, 12.078 }, +{ 12.184, 12.401 }, +{ 12.678, 12.708 }, +{ 12.775, 12.819 }, +{ 12.991, 13.139 }, +{ 13.302, 13.51 }, +{ 13.703, 14.076 }, +{ 14.178, 14.612 }, +{ 14.8, 14.888 }, +{ 15.034, 15.155 }, +{ 16.014, 16.293 }, +{ 16.327, 16.488 }, +{ 16.556, 16.726 }, +{ 17.277, 17.615 }, +{ -1.0, -1.0 }, +{ 18.281, 18.781 }, +{ 19.048, 20.131 }, +{ 20.518, 20.725 }, +{ 20.996, 21.32 }, +{ 21.768, 21.859 }, +{ 22.151, 22.248 }, +{ 22.459, 22.493 }, +{ 22.588, 22.75 }, +{ 22.804, 23.069 }, +{ 23.353, 23.535 }, +{ 23.677, 23.8 }, +{ 23.999, 24.118 }, +{ 24.73, 24.781 }, +{ 24.835, 25.183 }, +{ 25.496, 25.648 }, +{ -1.0, -1.0 }, +{ 25.823, 25.951 }, +{ 25.992, 26.554 }, +{ 27.027, 27.972 }, +{ 28.283, 28.512 }, +{ 28.578, 28.745 }, +{ 29.401, 29.662 }, +{ 29.765, 30.098 }, +{ 30.479, 30.939 }, +{ 33.058, 33.545 }, +{ 34.655, 34.94 }, +{ 35.343, 35.526 }, +{ 35.685, 36.341 }, +{ 36.618, 37.473 }, +{ 37.604, 37.848 }, +{ 37.92, 38.113 }, +{ 38.426, 39.552 }, +{ 39.631, 40.13 }, +{ 41.257, 41.521 }, +{ 42.536, 43.789 }, +{ 46.264, 47.906 }, +{ 49.037, 49.714 }, +{ 50.778, 50.946 }, +{ 51.047, 51.743 }, +{ 52.364, 52.663 }, +{ 52.757, 52.801 }, +{ 52.903, 53.347 }, +{ 55.904, 56.391 }, +{ 57.554, 57.911 }, +{ 60.92, 61.276 }, +{ 62.499, 63.634 }, +{ 63.976, 64.745 }, +{ 65.578, 67.61 }, +{ 67.735, 68.737 }, +{ 71.071, 71.338 }, +{ 71.587, 73.004 }, +{ 73.291, 73.374 }, +{ 73.619, 79.075 }, +{ 83, 118 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -999.0, -999.0} diff --git a/src/gsfml/CK1995r.h b/src/gsfml/CK1995r.h new file mode 100644 index 00000000000..7319f198712 --- /dev/null +++ b/src/gsfml/CK1995r.h @@ -0,0 +1,231 @@ +{ 0.78, 0.99 }, +{ 1.07, -1.0 }, +{ -1.0, 1.77 }, +{ 1.95, 2.14 }, +{ 2.15, 2.581 }, +{ 3.04, 3.11 }, +{ 3.22, 3.33 }, +{ 3.58, 4.18 }, +{ 4.29, 4.48 }, +{ 4.62, 4.8 }, +{ 4.89, 4.98 }, +{ 5.23, 5.894 }, +{ 6.137, 6.269 }, +{ 6.567, 6.935 }, +{ 7.091, 7.135 }, +{ 7.17, 7.341 }, +{ 7.375, 7.432 }, +{ 7.562, 7.65 }, +{ 8.072, 8.225 }, +{ 8.257, -1.0 }, +{ -1.0, 8.699 }, +{ 9.025, -1.0 }, +{ -1.0, 9.23 }, +{ 9.308, 9.58 }, +{ 9.642, 9.74 }, +{ 9.88, 9.92 }, +{ 10.949, 11.052 }, +{ 11.099, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, 11.476 }, +{ 11.531, -1.0 }, +{ -1.0, 11.935 }, +{ 12.078, 12.184 }, +{ 12.401, 12.678 }, +{ 12.708, 12.775 }, +{ 12.819, 12.991 }, +{ 13.139, 13.302 }, +{ 13.51, 13.703 }, +{ 14.076, 14.178 }, +{ 14.612, 14.8 }, +{ 14.888, 15.034 }, +{ 15.155, 16.014 }, +{ 16.293, 16.327 }, +{ 16.488, 16.556 }, +{ 16.726, 17.277 }, +{ 17.615, -1.0 }, +{ -1.0, 18.281 }, +{ 18.781, 19.048 }, +{ 20.131, 20.518 }, +{ 20.725, 20.996 }, +{ 21.32, 21.768 }, +{ 21.859, 22.151 }, +{ 22.248, 22.459 }, +{ 22.493, 22.588 }, +{ 22.75, 22.804 }, +{ 23.069, 23.353 }, +{ 23.535, 23.677 }, +{ 23.8, 23.999 }, +{ 24.118, 24.73 }, +{ 24.781, 24.835 }, +{ 25.183, 25.496 }, +{ 25.648, -1.0 }, +{ -1.0, 25.823 }, +{ 25.951, 25.992 }, +{ 26.554, 27.027 }, +{ 27.972, 28.283 }, +{ 28.512, 28.578 }, +{ 28.745, 29.401 }, +{ 29.662, 29.765 }, +{ 30.098, 30.479 }, +{ 30.939, 33.058 }, +{ 33.545, 34.655 }, +{ 34.94, 35.343 }, +{ 35.526, 35.685 }, +{ 36.341, 36.618 }, +{ 37.473, 37.604 }, +{ 37.848, 37.92 }, +{ 38.113, 38.426 }, +{ 39.552, 39.631 }, +{ 40.13, 41.257 }, +{ 41.521, 42.536 }, +{ 43.789, 46.264 }, +{ 47.906, 49.037 }, +{ 49.714, 50.778 }, +{ 50.946, 51.047 }, +{ 51.743, 52.364 }, +{ 52.663, 52.757 }, +{ 52.801, 52.903 }, +{ 53.347, 55.904 }, +{ 56.391, 57.554 }, +{ 57.911, 60.92 }, +{ 61.276, 62.499 }, +{ 63.634, 63.976 }, +{ 64.745, 65.578 }, +{ 67.61, 67.735 }, +{ 68.737, 71.071 }, +{ 71.338, 71.587 }, +{ 73.004, 73.291 }, +{ 73.374, 73.619 }, +{ 79.075, 83 }, +{ 118, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -999.0, -999.0} diff --git a/src/gsfml/CMakeLists.txt b/src/gsfml/CMakeLists.txt new file mode 100644 index 00000000000..4768be26ac1 --- /dev/null +++ b/src/gsfml/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 1991-2023 by the GMT Team (https://www.generic-mapping-tools.org/team.html) +# See LICENSE.TXT file for copying and redistribution conditions. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; version 3 or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# Contact info: www.generic-mapping-tools.org +#------------------------------------------------------------------------------- +# +# CMake settings for supplemental package: +# +# SUPPL_NAME: name of the supplemental package +# SUPPL_HEADERS: header files. Will be installed if BUILD_DEVELOPER is TRUE +# SUPPL_PROGS_SRCS: list of C source codes for supplemental modules +# SUPPL_LIB_SRCS: list of C source codes for supplemental library +# SUPPL_EXAMPLE_FILES: README and other example files +# SUPPL_EXAMPLE_PROGS: Example scripts +# + +set (SUPPL_NAME gsfml) +set (SUPPL_HEADERS CK1995n.h Chron_Normal.h Chron_Reverse.h GST2004n.h GST2012n.h Geek2007n.h + CK1995r.h Chron_Normal2.h Chron_Reverse2.h GST2004r.h GST2012r.h Geek2007r.h + fz_analysis.h) +AUX_SOURCE_DIRECTORY (longopt SUPPL_LONG_OPT_H) +set (SUPPL_PROGS_SRCS fzanalyzer.c fzblender.c mlconverter.c ${SUPPL_LONG_OPT_H}) +set (SUPPL_LIB_SRCS ${SUPPL_PROGS_SRCS}) +set (SUPPL_EXAMPLE_FILES README.gsfml) + +install (PROGRAMS fz_funcs.sh + RENAME fz_funcs${GMT_INSTALL_NAME_SUFFIX}.sh + DESTINATION ${GMT_BINDIR} + COMPONENT Runtime) +install (PROGRAMS fzinformer + RENAME fz_funcs${GMT_INSTALL_NAME_SUFFIX} + DESTINATION ${GMT_BINDIR} + COMPONENT Runtime) +install (PROGRAMS fzmapper + RENAME fz_funcs${GMT_INSTALL_NAME_SUFFIX} + DESTINATION ${GMT_BINDIR} + COMPONENT Runtime) +install (PROGRAMS fzmodeler + RENAME fzmodeler${GMT_INSTALL_NAME_SUFFIX} + DESTINATION ${GMT_BINDIR} + COMPONENT Runtime) +install (PROGRAMS fzprofiler + RENAME fzprofiler${GMT_INSTALL_NAME_SUFFIX} + DESTINATION ${GMT_BINDIR} + COMPONENT Runtime) diff --git a/src/gsfml/Chron_Normal.h b/src/gsfml/Chron_Normal.h new file mode 100644 index 00000000000..7d229d8d48d --- /dev/null +++ b/src/gsfml/Chron_Normal.h @@ -0,0 +1,231 @@ +"C1n", +"C1r.1n", +"C1r.2r-1n", +"C2n", +"C2r.1n", +"C2An.1n", +"C2An.2n", +"C2An.3n", +"C3n.1n", +"C3n.2n", +"C3n.3n", +"C3n.4n", +"C3An.1n", +"C3An.2n", +"C3Bn", +"C3Br.1n", +"C3Br.2n", +"C4n.1n", +"C4n.2n", +"C4r.1n", +"C4r.2r-1n", +"C4An", +"C4Ar.1r-1n", +"C4Ar.1n", +"C4Ar.2n", +"C5n.1n", +"C5n.2n", +"C5r.1n", +"C5r.2r-1n", +"C5r.2r-2n", +"C5r.2n", +"C5r.3r-1n", +"C5An.1n", +"C5An.2n", +"C5Ar.1n", +"C5Ar.2n", +"C5AAn", +"C5ABn", +"C5ACn", +"C5ADn", +"C5Bn.1n", +"C5Bn.2n", +"C5Cn.1n", +"C5Cn.2n", +"C5Cn.3n", +"C5Dn", +"C5Dr-1n", +"C5En", +"C6n", +"C6An.1n", +"C6An.2n", +"C6AAn", +"C6AAr.1n", +"C6AAr.2n", +"C6Bn.1n", +"C6Bn.2n", +"C6Cn.1n", +"C6Cn.2n", +"C6Cn.3n", +"C7n.1n", +"C7n.2n", +"C7An", +"C7Ar-1n", +"C8n.1n", +"C8n.2n", +"C9n", +"C10n.1n", +"C10n.2n", +"C11n.1n", +"C11n.2n", +"C12n", +"C13n", +"C15n", +"C16n.1n", +"C16n.2n", +"C17n.1n", +"C17n.2n", +"C17n.3n", +"C18n.1n", +"C18n.2n", +"C19n", +"C20n", +"C21n", +"C22n", +"C23n.1n", +"C23n.2n", +"C24n.1n", +"C24n.2n", +"C24n.3n", +"C25n", +"C26n", +"C27n", +"C28n", +"C29n", +"C30n", +"C31n", +"C32n.1n", +"C32n.2n", +"C32r.1n", +"C33n", +"C34n", +"M1n", +"M2n", +"M4n", +"M6n", +"M7n", +"M8n", +"M9n", +"M10n", +"M10Nn.1n", +"M10Nn.2n", +"M10Nn.3n", +"M11n", +"M11r.1n", +"M11An.1n", +"M11An.2n", +"M12n", +"M12r.1n", +"M12An", +"M13n", +"M14n", +"M15n", +"M16n", +"M17n", +"M18n", +"M19n.1n", +"M19n", +"M20n.1n", +"M20n.2n", +"M21n", +"M22n.1n", +"M22n.2n", +"M22n.3n", +"M22An", +"M23n.1n", +"M23n.2n", +"M24n.1n", +"M24n.2n", +"M24An", +"M24Bn", +"M25n", +"M25An.1n", +"M25An.2n", +"M25An.3n", +"M26n.1n", +"M26n.2n", +"M26n.3n", +"M26n.4n", +"M27n", +"M28n", +"M28An", +"M28Bn", +"M28Cn", +"M28Dn", +"M29n.1n", +"M29n.2n", +"M29An", +"M30n", +"M30An", +"M31n.1n", +"M31n.2n", +"M31n", +"M32n.1n", +"M32n.2n", +"M32n", +"M33n", +"M33An", +"M33Bn", +"M33Cn.1n", +"M33Cn", +"M34n.1n", +"M34n.2n", +"M34n.3n", +"M34An", +"M34Bn.1n", +"M34Bn", +"M35n", +"M36n.1n", +"M36An", +"M36Bn", +"M36Cn", +"M37n.1n", +"M37n", +"M38n.1n", +"M38n.2n", +"M38n.3n", +"M38n.4n", +"M38n", +"M39n.1n", +"M39n.2n", +"M39n.3n", +"M39n.4n", +"M39n.5n", +"M39n.6n", +"M39n.7n", +"M39n", +"M40n.1n", +"M40n.2n", +"M40n.3n", +"M40n", +"M41n.1n", +"M41n.2n", +"M41n.3n", +"M41n", +"M42n.1n", +"M42n.2n", +"M42n.3n", +"M42n.4n", +"M42n.5n", +"M42n.6n", +"M42n.7n", +"M42n.8n", +"M42n.9n", +"M42n.10n", +"M42n", +"M43n.1n", +"M43n.2n", +"M43n.3n", +"M43n.4n", +"M43n", +"M44n.1n", +"M44n.2n", +"M44n.3n", +"M44n.4n", +"M44n.5n", +"M44n.6n", +"M44n.7n", +"M44n.8r", +"M44n", +"M45n", +NULL diff --git a/src/gsfml/Chron_Normal2.h b/src/gsfml/Chron_Normal2.h new file mode 100644 index 00000000000..ed0a43bce6f --- /dev/null +++ b/src/gsfml/Chron_Normal2.h @@ -0,0 +1,231 @@ +"C1N", +"C1R1N", +"C1R2R-1N", +"C2N", +"C2R1N", +"C2AN1N", +"C2AN2N", +"C2AN3N", +"C3N1N", +"C3N2N", +"C3N3N", +"C3N4N", +"C3AN1N", +"C3AN2N", +"C3BN", +"C3BR1N", +"C3BR2N", +"C4N1N", +"C4N2N", +"C4R1N", +"C4R2R-1N", +"C4AN", +"C4AR1R-1N", +"C4AR1N", +"C4AR2N", +"C5N1N", +"C5N2N", +"C5R1N", +"C5R2R-1N", +"C5R2R-2N", +"C5R2N", +"C5R3R-1N", +"C5AN1N", +"C5AN2N", +"C5AR1N", +"C5AR2N", +"C5AAN", +"C5ABN", +"C5ACN", +"C5ADN", +"C5BN1N", +"C5BN2N", +"C5CN1N", +"C5CN2N", +"C5CN3N", +"C5DN", +"C5DR-1N", +"C5EN", +"C6N", +"C6AN1N", +"C6AN2N", +"C6AAN", +"C6AAR1N", +"C6AAR2N", +"C6BN1N", +"C6BN2N", +"C6CN1N", +"C6CN2N", +"C6CN3N", +"C7N1N", +"C7N2N", +"C7AN", +"C7AR-1N", +"C8N1N", +"C8N2N", +"C9N", +"C10N1N", +"C10N2N", +"C11N1N", +"C11N2N", +"C12N", +"C13N", +"C15N", +"C16N1N", +"C16N2N", +"C17N1N", +"C17N2N", +"C17N3N", +"C18N1N", +"C18N2N", +"C19N", +"C20N", +"C21N", +"C22N", +"C23N1N", +"C23N2N", +"C24N1N", +"C24N2N", +"C24N3N", +"C25N", +"C26N", +"C27N", +"C28N", +"C29N", +"C30N", +"C31N", +"C32N1N", +"C32N2N", +"C32R1N", +"C33N", +"C34N", +"M1N", +"M2N", +"M4N", +"M6N", +"M7N", +"M8N", +"M9N", +"M10N", +"M10NN1N", +"M10NN2N", +"M10NN3N", +"M11N", +"M11R1N", +"M11AN1N", +"M11AN2N", +"M12N", +"M12R1N", +"M12AN", +"M13N", +"M14N", +"M15N", +"M16N", +"M17N", +"M18N", +"M19N1N", +"M19N", +"M20N1N", +"M20N2N", +"M21N", +"M22N1N", +"M22N2N", +"M22N3N", +"M22AN", +"M23N1N", +"M23N2N", +"M24N1N", +"M24N2N", +"M24AN", +"M24BN", +"M25N", +"M25AN1N", +"M25AN2N", +"M25AN3N", +"M26N1N", +"M26N2N", +"M26N3N", +"M26N4N", +"M27N", +"M28N", +"M28AN", +"M28BN", +"M28CN", +"M28DN", +"M29N1N", +"M29N2N", +"M29AN", +"M30N", +"M30AN", +"M31N1N", +"M31N2N", +"M31N", +"M32N1N", +"M32N2N", +"M32N", +"M33N", +"M33AN", +"M33BN", +"M33CN1N", +"M33CN", +"M34N1N", +"M34N2N", +"M34N3N", +"M34AN", +"M34BN1N", +"M34BN", +"M35N", +"M36N1N", +"M36AN", +"M36BN", +"M36CN", +"M37N1N", +"M37N", +"M38N1N", +"M38N2N", +"M38N3N", +"M38N4N", +"M38N", +"M39N1N", +"M39N2N", +"M39N3N", +"M39N4N", +"M39N5N", +"M39N6N", +"M39N7N", +"M39N", +"M40N1N", +"M40N2N", +"M40N3N", +"M40N", +"M41N1N", +"M41N2N", +"M41N3N", +"M41N", +"M42N1N", +"M42N2N", +"M42N3N", +"M42N4N", +"M42N5N", +"M42N6N", +"M42N7N", +"M42N8N", +"M42N9N", +"M42N10N", +"M42N", +"M43N1N", +"M43N2N", +"M43N3N", +"M43N4N", +"M43N", +"M44N1N", +"M44N2N", +"M44N3N", +"M44N4N", +"M44N5N", +"M44N6N", +"M44N7N", +"M44N8R", +"M44N", +"M45N", +NULL diff --git a/src/gsfml/Chron_Reverse.h b/src/gsfml/Chron_Reverse.h new file mode 100644 index 00000000000..98046ec1e7e --- /dev/null +++ b/src/gsfml/Chron_Reverse.h @@ -0,0 +1,231 @@ +"C1r.1r", +"C1r.2r", +"C1r.2r", +"C2r.1r", +"C2r.2r", +"C2An.1r", +"C2An.2r", +"C2Ar", +"C3n.1r", +"C3n.2r", +"C3n.3r", +"C3r", +"C3An.1r", +"C3Ar", +"C3Br.1r", +"C3Br.2r", +"C3Br.3r", +"C4n.1r", +"C4r.1r", +"C4r.2r", +"C4r.2r", +"C4Ar.1r", +"C4Ar.1r", +"C4Ar.2r", +"C4Ar.3r", +"C5n.1r", +"C5r.1r", +"C5r.2r", +"C5r.2r", +"C5r.2r", +"C5r.3r", +"C5r.3r", +"C5An.1r", +"C5Ar.1r", +"C5Ar.2r", +"C5Ar.3r", +"C5AAr", +"C5ABr", +"C5ACr", +"C5ADr", +"C5Bn.1r", +"C5Br", +"C5Cn.1r", +"C5Cn.2r", +"C5Cr", +"C5Dr", +"C5Dr", +"C5Er", +"C6r", +"C6An.1r", +"C6Ar", +"C6AAr.1r", +"C6AAr.2r", +"C6AAr.3r", +"C6Bn.1r", +"C6Br", +"C6Cn.1r", +"C6Cn.2r", +"C6Cr", +"C7n.1r", +"C7r", +"C7Ar*", +"C7Ar*", +"C8n.1r", +"C8r", +"C9r", +"C10n.1r", +"C10r", +"C11n.1r", +"C11r", +"C12r", +"C13r", +"C15r", +"C16n.1r", +"C16r", +"C17n.1r", +"C17n.2r", +"C17r", +"C18n.1r", +"C18r", +"C19r", +"C20r", +"C21r", +"C22r", +"C23n.1r", +"C23r", +"C24n.1r", +"C24n.2r", +"C24r", +"C25r", +"C26r", +"C27r", +"C28r", +"C29r", +"C30r", +"C31r", +"C32n.1r", +"C32r.1r", +"C32r.2r", +"C33r", +"M0r", +"M1r", +"M3r", +"M5r", +"M6r", +"M7r", +"M8r", +"M9r", +"M10r", +"M10Nn.1r", +"M10Nn.2r", +"M10Nr", +"M11r.1r", +"M11r.2r", +"M11An.1r", +"M11Ar", +"M12r.1r", +"M12r.2r", +"M12Ar", +"M13r", +"M14r", +"M15r", +"M16r", +"M17r", +"M18r", +"M19n.1r", +"M19r", +"M20n.1r", +"M20r", +"M21r", +"M22n.1r", +"M22n.2r", +"M22r", +"M22Ar", +"M23n.1r", +"M23r", +"M24n.1r", +"M24r", +"M24Ar", +"M24Br", +"M25r", +"M25An.1r", +"M25An.2r", +"M25Ar", +"M26n.1r", +"M26n.2r", +"M26n.3r", +"M26r", +"M27r", +"M28r", +"M28Ar", +"M28Br", +"M28Cr", +"M28Dr", +"M29n.1r", +"M29r", +"M29Ar", +"M30r", +"M30Ar", +"M31n.1r", +"M31n.2r", +"M31r", +"M32n.1r", +"M32n.2r", +"M32r", +"M33r", +"M33Ar", +"M33Br", +"M33Cn.1r", +"M33Cr", +"M34n.1r", +"M34n.2r", +"M34n.3r", +"M34Ar", +"M34Bn.1r", +"M34Br", +"M35r", +"M36n.1r", +"M36Ar", +"M36Br", +"M36Cr", +"M37n.1r", +"M37r", +"M38n.1r", +"M38n.2r", +"M38n.3r", +"M38n.4r", +"M38r", +"M39n.1r", +"M39n.2r", +"M39n.3r", +"M39n.4r", +"M39n.5r", +"M39n.6r", +"M39n.7r", +"M39r", +"M40n.1r", +"M40n.2r", +"M40n.3r", +"M40r", +"M41n.1r", +"M41n.2r", +"M41n.3r", +"M41r", +"M42n.1r", +"M42n.2r", +"M42n.3r", +"M42n.4r", +"M42n.5r", +"M42n.6r", +"M42n.7r", +"M42n.8r", +"M42n.9r", +"M42n.10r", +"M42r", +"M43n.1r", +"M43n.2r", +"M43n.3r", +"M43n.4r", +"M43r", +"M44n.1r", +"M44n.2r", +"M44n.3r", +"M44n.4r", +"M44n.5r", +"M44n.6r", +"M44n.7r", +"M44n.8r", +"M44r", +"M45r", +NULL diff --git a/src/gsfml/Chron_Reverse2.h b/src/gsfml/Chron_Reverse2.h new file mode 100644 index 00000000000..fc936dea9cd --- /dev/null +++ b/src/gsfml/Chron_Reverse2.h @@ -0,0 +1,231 @@ +"C1R1R", +"C1R2R", +"C1R2R", +"C2R1R", +"C2R2R", +"C2AN1R", +"C2AN2R", +"C2AR", +"C3N1R", +"C3N2R", +"C3N3R", +"C3R", +"C3AN1R", +"C3AR", +"C3BR1R", +"C3BR2R", +"C3BR3R", +"C4N1R", +"C4R1R", +"C4R2R", +"C4R2R", +"C4AR1R", +"C4AR1R", +"C4AR2R", +"C4AR3R", +"C5N1R", +"C5R1R", +"C5R2R", +"C5R2R", +"C5R2R", +"C5R3R", +"C5R3R", +"C5AN1R", +"C5AR1R", +"C5AR2R", +"C5AR3R", +"C5AAR", +"C5ABR", +"C5ACR", +"C5ADR", +"C5BN1R", +"C5BR", +"C5CN1R", +"C5CN2R", +"C5CR", +"C5DR", +"C5DR", +"C5ER", +"C6R", +"C6AN1R", +"C6AR", +"C6AAR1R", +"C6AAR2R", +"C6AAR3R", +"C6BN1R", +"C6BR", +"C6CN1R", +"C6CN2R", +"C6CR", +"C7N1R", +"C7R", +"C7AR*", +"C7AR*", +"C8N1R", +"C8R", +"C9R", +"C10N1R", +"C10R", +"C11N1R", +"C11R", +"C12R", +"C13R", +"C15R", +"C16N1R", +"C16R", +"C17N1R", +"C17N2R", +"C17R", +"C18N1R", +"C18R", +"C19R", +"C20R", +"C21R", +"C22R", +"C23N1R", +"C23R", +"C24N1R", +"C24N2R", +"C24R", +"C25R", +"C26R", +"C27R", +"C28R", +"C29R", +"C30R", +"C31R", +"C32N1R", +"C32R1R", +"C32R2R", +"C33R", +"M0R", +"M1R", +"M3R", +"M5R", +"M6R", +"M7R", +"M8R", +"M9R", +"M10R", +"M10NN1R", +"M10NN2R", +"M10NR", +"M11R1R", +"M11R2R", +"M11AN1R", +"M11AR", +"M12R1R", +"M12R2R", +"M12AR", +"M13R", +"M14R", +"M15R", +"M16R", +"M17R", +"M18R", +"M19N1R", +"M19R", +"M20N1R", +"M20R", +"M21R", +"M22N1R", +"M22N2R", +"M22R", +"M22AR", +"M23N1R", +"M23R", +"M24N1R", +"M24R", +"M24AR", +"M24BR", +"M25R", +"M25AN1R", +"M25AN2R", +"M25AR", +"M26N1R", +"M26N2R", +"M26N3R", +"M26R", +"M27R", +"M28R", +"M28AR", +"M28BR", +"M28CR", +"M28DR", +"M29N1R", +"M29R", +"M29AR", +"M30R", +"M30AR", +"M31N1R", +"M31N2R", +"M31R", +"M32N1R", +"M32N2R", +"M32R", +"M33R", +"M33AR", +"M33BR", +"M33CN1R", +"M33CR", +"M34N1R", +"M34N2R", +"M34N3R", +"M34AR", +"M34BN1R", +"M34BR", +"M35R", +"M36N1R", +"M36AR", +"M36BR", +"M36CR", +"M37N1R", +"M37R", +"M38N1R", +"M38N2R", +"M38N3R", +"M38N4R", +"M38R", +"M39N1R", +"M39N2R", +"M39N3R", +"M39N4R", +"M39N5R", +"M39N6R", +"M39N7R", +"M39R", +"M40N1R", +"M40N2R", +"M40N3R", +"M40R", +"M41N1R", +"M41N2R", +"M41N3R", +"M41R", +"M42N1R", +"M42N2R", +"M42N3R", +"M42N4R", +"M42N5R", +"M42N6R", +"M42N7R", +"M42N8R", +"M42N9R", +"M42N10R", +"M42R", +"M43N1R", +"M43N2R", +"M43N3R", +"M43N4R", +"M43R", +"M44N1R", +"M44N2R", +"M44N3R", +"M44N4R", +"M44N5R", +"M44N6R", +"M44N7R", +"M44N8R", +"M44R", +"M45R", +NULL diff --git a/src/gsfml/GST2004n.h b/src/gsfml/GST2004n.h new file mode 100644 index 00000000000..ce9a3f986bf --- /dev/null +++ b/src/gsfml/GST2004n.h @@ -0,0 +1,231 @@ +{ 0, 0.781 }, +{ 0.988, 1.072 }, +{ 1.072, 1.173 }, +{ 1.778, 1.945 }, +{ 2.128, 2.148 }, +{ 2.518, 3.032 }, +{ 3.116, 3.207 }, +{ 3.33, 3.596 }, +{ 4.187, 4.3 }, +{ 4.493, 4.631 }, +{ 4.799, 4.896 }, +{ 4.997, 5.235 }, +{ 6.033, 6.252 }, +{ 6.436, 6.733 }, +{ 7.14, 7.212 }, +{ 7.212, 7.251 }, +{ 7.454, 7.489 }, +{ 7.528, 7.642 }, +{ 7.695, 8.108 }, +{ 8.254, 8.3 }, +{ 8.661, 8.699 }, +{ 8.769, 9.098 }, +{ -1.0, -1.0 }, +{ 9.312, 9.409 }, +{ 9.656, 9.717 }, +{ 9.779, 9.934 }, +{ 9.987, 11.04 }, +{ 11.118, 11.154 }, +{ 11.267, 11.298 }, +{ -1.0, 11.504 }, +{ 11.554, 11.614 }, +{ -1.0, -1.0 }, +{ 12.014, 12.116 }, +{ 12.207, 12.415 }, +{ 12.73, 12.765 }, +{ 12.82, 12.878 }, +{ 13.015, 13.183 }, +{ 13.369, 13.605 }, +{ 13.734, 14.095 }, +{ 14.194, 14.581 }, +{ 14.784, 14.877 }, +{ 15.032, 15.16 }, +{ 15.974, 16.268 }, +{ 16.303, 16.472 }, +{ 16.543, 16.721 }, +{ 17.235, 17.533 }, +{ -1.0, -1.0 }, +{ 18.056, 18.524 }, +{ 18.748, 19.722 }, +{ 20.04, 20.213 }, +{ 20.439, 20.709 }, +{ 21.083, 21.159 }, +{ 21.403, 21.483 }, +{ 21.659, 21.688 }, +{ 21.767, 21.936 }, +{ 21.992, 22.268 }, +{ 22.564, 22.754 }, +{ 22.902, 23.03 }, +{ 23.249, 23.375 }, +{ 24.044, 24.102 }, +{ 24.163, 24.556 }, +{ 24.915, 25.091 }, +{ -1.0, -1.0 }, +{ 25.295, 25.444 }, +{ 25.492, 26.154 }, +{ 26.714, 27.826 }, +{ 28.186, 28.45 }, +{ 28.525, 28.715 }, +{ 29.451, 29.74 }, +{ 29.853, 30.217 }, +{ 30.627, 31.116 }, +{ 33.266, 33.738 }, +{ 34.782, 35.043 }, +{ 35.404, 35.567 }, +{ 35.707, 36.276 }, +{ 36.512, 37.235 }, +{ 37.345, 37.549 }, +{ 37.61, 37.771 }, +{ 38.032, 38.975 }, +{ 39.041, 39.464 }, +{ 40.439, 40.671 }, +{ 41.59, 42.774 }, +{ 45.346, 47.235 }, +{ 48.599, 49.427 }, +{ 50.73, 50.932 }, +{ 51.057, 51.901 }, +{ 52.648, 53.004 }, +{ 53.116, 53.167 }, +{ 53.286, 53.808 }, +{ 56.665, 57.18 }, +{ 58.379, 58.737 }, +{ 61.65, 61.983 }, +{ 63.104, 64.128 }, +{ 64.432, 65.118 }, +{ 65.861, 67.696 }, +{ 67.809, 68.732 }, +{ 70.961, 71.225 }, +{ 71.474, 72.929 }, +{ 73.231, 73.318 }, +{ 73.557, 79.543 }, +{ 84, 125 }, +{ 125, 127.61 }, +{ 127.61, 128.11 }, +{ 129.76, 130.8 }, +{ 131.19, 131.41 }, +{ 131.56, 131.85 }, +{ 132.2, 132.52 }, +{ 132.83, 133.14 }, +{ 133.5, 133.87 }, +{ 134.3, 134.62 }, +{ 134.67, 134.98 }, +{ 135, 135.28 }, +{ 135.69, 136.44 }, +{ 136.68, 136.71 }, +{ 136.9, 137.39 }, +{ 137.44, 137.51 }, +{ 137.6, 137.82 }, +{ 138.56, 138.63 }, +{ 138.78, 139.03 }, +{ 139.12, 139.29 }, +{ 139.53, 139.77 }, +{ 140.36, 140.66 }, +{ 141.05, 142.06 }, +{ 142.55, 142.84 }, +{ 144.04, 144.57 }, +{ 144.88, 144.99 }, +{ 145.06, 145.95 }, +{ 146.16, 146.47 }, +{ 146.52, 147.16 }, +{ 147.77, 148.54 }, +{ 148.92, 150.05 }, +{ 150.08, 150.12 }, +{ 150.16, 150.21 }, +{ 150.73, 150.84 }, +{ 151.01, 151.34 }, +{ 151.62, 151.64 }, +{ 152.26, 152.5 }, +{ 152.96, 152.98 }, +{ 153.18, 153.31 }, +{ 153.58, 153.93 }, +{ 154.08, 154.37 }, +{ 154.55, 154.67 }, +{ 154.73, 154.81 }, +{ 154.86, 154.97 }, +{ 155.05, 155.13 }, +{ 155.18, 155.24 }, +{ 155.3, 155.35 }, +{ 155.39, 155.54 }, +{ 155.71, 155.85 }, +{ 156.01, 156.29 }, +{ 156.44, 156.53 }, +{ 156.76, 156.81 }, +{ 156.89, 156.99 }, +{ 157.08, 157.16 }, +{ 157.26, 157.41 }, +{ 157.44, 157.51 }, +{ 157.73, 157.78 }, +{ 157.84, 157.96 }, +{ 158.12, 158.21 }, +{ 158.24, 158.39 }, +{ 158.47, 158.5 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -999.0, -999.0} diff --git a/src/gsfml/GST2004r.h b/src/gsfml/GST2004r.h new file mode 100644 index 00000000000..dcbee2c7efc --- /dev/null +++ b/src/gsfml/GST2004r.h @@ -0,0 +1,231 @@ +{ 0.781, 0.988 }, +{ 1.072, 1.072 }, +{ 1.173, 1.778 }, +{ 1.945, 2.128 }, +{ 2.148, 2.518 }, +{ 3.032, 3.116 }, +{ 3.207, 3.33 }, +{ 3.596, 4.187 }, +{ 4.3, 4.493 }, +{ 4.631, 4.799 }, +{ 4.896, 4.997 }, +{ 5.235, 6.033 }, +{ 6.252, 6.436 }, +{ 6.733, 7.14 }, +{ 7.212, 7.212 }, +{ 7.251, 7.454 }, +{ 7.489, 7.528 }, +{ 7.642, 7.695 }, +{ 8.108, 8.254 }, +{ 8.3, 8.661 }, +{ 8.699, 8.769 }, +{ 9.098, -1.0 }, +{ -1.0, 9.312 }, +{ 9.409, 9.656 }, +{ 9.717, 9.779 }, +{ 9.934, 9.987 }, +{ 11.04, 11.118 }, +{ 11.154, 11.267 }, +{ 11.298, -1.0 }, +{ 11.504, 11.554 }, +{ 11.614, -1.0 }, +{ -1.0, 12.014 }, +{ 12.116, 12.207 }, +{ 12.415, 12.73 }, +{ 12.765, 12.82 }, +{ 12.878, 13.015 }, +{ 13.183, 13.369 }, +{ 13.605, 13.734 }, +{ 14.095, 14.194 }, +{ 14.581, 14.784 }, +{ 14.877, 15.032 }, +{ 15.16, 15.974 }, +{ 16.268, 16.303 }, +{ 16.472, 16.543 }, +{ 16.721, 17.235 }, +{ 17.533, -1.0 }, +{ -1.0, 18.056 }, +{ 18.524, 18.748 }, +{ 19.722, 20.04 }, +{ 20.213, 20.439 }, +{ 20.709, 21.083 }, +{ 21.159, 21.403 }, +{ 21.483, 21.659 }, +{ 21.688, 21.767 }, +{ 21.936, 21.992 }, +{ 22.268, 22.564 }, +{ 22.754, 22.902 }, +{ 23.03, 23.249 }, +{ 23.375, 24.044 }, +{ 24.102, 24.163 }, +{ 24.556, 24.915 }, +{ 25.091, -1.0 }, +{ -1.0, 25.295 }, +{ 25.444, 25.492 }, +{ 26.154, 26.714 }, +{ 27.826, 28.186 }, +{ 28.45, 28.525 }, +{ 28.715, 29.451 }, +{ 29.74, 29.853 }, +{ 30.217, 30.627 }, +{ 31.116, 33.266 }, +{ 33.738, 34.782 }, +{ 35.043, 35.404 }, +{ 35.567, 35.707 }, +{ 36.276, 36.512 }, +{ 37.235, 37.345 }, +{ 37.549, 37.61 }, +{ 37.771, 38.032 }, +{ 38.975, 39.041 }, +{ 39.464, 40.439 }, +{ 40.671, 41.59 }, +{ 42.774, 45.346 }, +{ 47.235, 48.599 }, +{ 49.427, 50.73 }, +{ 50.932, 51.057 }, +{ 51.901, 52.648 }, +{ 53.004, 53.116 }, +{ 53.167, 53.286 }, +{ 53.808, 56.665 }, +{ 57.18, 58.379 }, +{ 58.737, 61.65 }, +{ 61.983, 63.104 }, +{ 64.128, 64.432 }, +{ 65.118, 65.861 }, +{ 67.696, 67.809 }, +{ 68.732, 70.961 }, +{ 71.225, 71.474 }, +{ 72.929, 73.231 }, +{ 73.318, 73.557 }, +{ 79.543, 84 }, +{ 124.61, 125 }, +{ 127.61, 127.61 }, +{ 128.11, 129.76 }, +{ 130.8, 131.19 }, +{ 131.41, 131.56 }, +{ 131.85, 132.2 }, +{ 132.52, 132.83 }, +{ 133.14, 133.5 }, +{ 133.87, 134.3 }, +{ 134.62, 134.67 }, +{ 134.98, 135 }, +{ 135.28, 135.69 }, +{ 136.44, 136.68 }, +{ 136.71, 136.9 }, +{ 137.39, 137.44 }, +{ 137.51, 137.6 }, +{ 137.82, 138.56 }, +{ 138.63, 138.78 }, +{ 139.03, 139.12 }, +{ 139.29, 139.53 }, +{ 139.77, 140.36 }, +{ 140.66, 141.05 }, +{ 142.06, 142.55 }, +{ 142.84, 144.04 }, +{ 144.57, 144.88 }, +{ 144.99, 145.06 }, +{ 145.95, 146.16 }, +{ 146.47, 146.52 }, +{ 147.16, 147.77 }, +{ 148.54, 148.92 }, +{ 150.05, 150.08 }, +{ 150.12, 150.16 }, +{ 150.21, 150.73 }, +{ 150.84, 151.01 }, +{ 151.34, 151.62 }, +{ 151.64, 152.26 }, +{ 152.5, 152.96 }, +{ 152.98, 153.18 }, +{ 153.31, 153.58 }, +{ 153.93, 154.08 }, +{ 154.37, 154.55 }, +{ 154.67, 154.73 }, +{ 154.81, 154.86 }, +{ 154.97, 155.05 }, +{ 155.13, 155.18 }, +{ 155.24, 155.3 }, +{ 155.35, 155.39 }, +{ 155.54, 155.71 }, +{ 155.85, 156.01 }, +{ 156.29, 156.44 }, +{ 156.53, 156.76 }, +{ 156.81, 156.89 }, +{ 156.99, 157.08 }, +{ 157.16, 157.26 }, +{ 157.41, 157.44 }, +{ 157.51, 157.73 }, +{ 157.78, 157.84 }, +{ 157.96, 158.12 }, +{ 158.21, 158.24 }, +{ 158.39, 158.47 }, +{ 158.5, 158.54 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -999.0, -999.0} diff --git a/src/gsfml/GST2012n.h b/src/gsfml/GST2012n.h new file mode 100644 index 00000000000..5caa52dfdd4 --- /dev/null +++ b/src/gsfml/GST2012n.h @@ -0,0 +1,231 @@ +{ 0, 0.781 }, +{ 0.988, 1.072 }, +{ 1.173, 1.185 }, +{ 1.778, 1.945 }, +{ 2.128, 2.148 }, +{ 2.581, 3.032 }, +{ 3.116, 3.207 }, +{ 3.33, 3.596 }, +{ 4.187, 4.3 }, +{ 4.493, 4.631 }, +{ 4.799, 4.896 }, +{ 4.997, 5.235 }, +{ 6.033, 6.252 }, +{ 6.436, 6.733 }, +{ 7.14, 7.212 }, +{ 7.251, 7.285 }, +{ 7.454, 7.489 }, +{ 7.528, 7.642 }, +{ 7.695, 8.108 }, +{ 8.254, 8.3 }, +{ -1.0, -1.0 }, +{ 8.771, 9.105 }, +{ -1.0, -1.0 }, +{ 9.311, 9.426 }, +{ 9.647, 9.721 }, +{ 9.786, 9.937 }, +{ 9.984, 11.056 }, +{ 11.146, 11.188 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 11.592, 11.657 }, +{ -1.0, -1.0 }, +{ 12.049, 12.174 }, +{ 12.272, 12.474 }, +{ 12.735, 12.77 }, +{ 12.829, 12.887 }, +{ 13.032, 13.183 }, +{ 13.363, 13.608 }, +{ 13.739, 14.07 }, +{ 14.163, 14.609 }, +{ 14.775, 14.87 }, +{ 15.032, 15.16 }, +{ 15.974, 16.268 }, +{ 16.303, 16.472 }, +{ 16.543, 16.721 }, +{ 17.235, 17.533 }, +{ 17.717, 17.74 }, +{ 18.056, 18.524 }, +{ 18.748, 19.722 }, +{ 20.04, 20.213 }, +{ 20.439, 20.709 }, +{ 21.083, 21.159 }, +{ 21.403, 21.483 }, +{ 21.659, 21.688 }, +{ 21.767, 21.936 }, +{ 21.992, 22.268 }, +{ 22.564, 22.754 }, +{ 22.902, 23.03 }, +{ 23.233, 23.295 }, +{ 23.962, 24 }, +{ 24.109, 24.474 }, +{ 24.761, 24.984 }, +{ -1.0, -1.0 }, +{ 25.099, 25.264 }, +{ 25.304, 25.987 }, +{ 26.42, 27.439 }, +{ 27.859, 28.087 }, +{ 28.141, 28.278 }, +{ 29.183, 29.477 }, +{ 29.527, 29.97 }, +{ 30.591, 31.034 }, +{ 33.157, 33.705 }, +{ 34.999, 35.294 }, +{ 35.706, 35.892 }, +{ 36.051, 36.7 }, +{ 36.969, 37.753 }, +{ 37.872, 38.093 }, +{ 38.159, 38.333 }, +{ 38.615, 39.627 }, +{ 39.698, 40.145 }, +{ 41.154, 41.39 }, +{ 42.301, 43.432 }, +{ 45.724, 47.349 }, +{ 48.566, 49.344 }, +{ 50.628, 50.835 }, +{ 50.961, 51.833 }, +{ 52.62, 53.074 }, +{ 53.199, 53.274 }, +{ 53.416, 53.983 }, +{ 57.101, 57.656 }, +{ 58.959, 59.237 }, +{ 62.221, 62.517 }, +{ 63.494, 64.667 }, +{ 64.958, 65.688 }, +{ 66.398, 68.196 }, +{ 68.369, 69.269 }, +{ 71.449, 71.689 }, +{ 71.939, 73.649 }, +{ 73.949, 74.049 }, +{ 74.309, 79.9 }, +{ 83.64, 125.93 }, +{ 126.3, 128.32 }, +{ 128.66, 129.11 }, +{ 130.6, 131.43 }, +{ 131.74, 131.92 }, +{ 132.04, 132.27 }, +{ 132.55, 132.8 }, +{ 133.05, 133.3 }, +{ 133.58, 133.88 }, +{ 134.22, 134.48 }, +{ 134.51, 134.76 }, +{ 134.78, 135 }, +{ 135.32, 135.92 }, +{ 136.11, 136.13 }, +{ 136.29, 136.69 }, +{ 136.74, 136.8 }, +{ 136.87, 137.06 }, +{ 137.73, 137.8 }, +{ 137.94, 138.17 }, +{ 138.25, 138.42 }, +{ 138.66, 138.91 }, +{ 139.59, 139.94 }, +{ 140.42, 141.64 }, +{ 142.22, 142.57 }, +{ 144, 144.64 }, +{ 145.01, 145.14 }, +{ 145.19, 146.28 }, +{ 146.54, 146.9 }, +{ 146.96, 147.72 }, +{ 148.44, 149.35 }, +{ 149.8, 151.12 }, +{ 151.17, 151.21 }, +{ 151.25, 151.32 }, +{ 151.92, 152.06 }, +{ 152.25, 152.64 }, +{ 152.93, 152.96 }, +{ 153.62, 153.87 }, +{ 154.35, 154.38 }, +{ 154.59, 154.73 }, +{ 155.01, 155.38 }, +{ 155.54, 155.85 }, +{ 156.04, 156.16 }, +{ 156.22, 156.29 }, +{ 156.39, 156.42 }, +{ 156.56, 156.69 }, +{ 156.75, 156.78 }, +{ 156.84, 156.94 }, +{ 157.04, 157.06 }, +{ 157.25, 157.4 }, +{ 157.57, 157.87 }, +{ 158.02, 158.12 }, +{ 158.36, 158.41 }, +{ 158.5, 158.6 }, +{ 158.69, 158.78 }, +{ 158.89, 159.04 }, +{ 159.07, 159.14 }, +{ 159.38, 159.43 }, +{ 159.49, 159.62 }, +{ 159.78, 159.88 }, +{ 159.91, 160.07 }, +{ 160.15, 160.18 }, +{ 160.22, 160.26 }, +{ 160.32, 160.34 }, +{ 160.37, 160.47 }, +{ 160.52, 160.55 }, +{ 160.63, 160.93 }, +{ 161.06, 161.14 }, +{ 161.21, 161.28 }, +{ 161.39, 161.43 }, +{ 161.49, 161.61 }, +{ 161.81, 161.89 }, +{ 161.96, 162.01 }, +{ 162.04, 162.06 }, +{ 162.12, 162.15 }, +{ 162.28, 162.37 }, +{ 162.43, 162.46 }, +{ 162.49, 162.55 }, +{ 162.7, 162.8 }, +{ 162.86, 162.9 }, +{ 162.92, 162.95 }, +{ 163.1, 163.16 }, +{ 163.29, 163.53 }, +{ 163.65, 163.76 }, +{ 163.85, 163.98 }, +{ 164.03, 164.18 }, +{ 164.22, 164.3 }, +{ 164.41, 164.63 }, +{ 164.69, 164.85 }, +{ 164.91, 165.08 }, +{ 165.2, 165.34 }, +{ 165.4, 165.53 }, +{ 165.65, 165.8 }, +{ 165.96, 166.08 }, +{ 166.21, 166.3 }, +{ 166.4, 166.47 }, +{ 166.51, 166.61 }, +{ 166.68, 166.72 }, +{ 166.89, 166.96 }, +{ 167.05, 167.11 }, +{ 167.33, 167.36 }, +{ 167.43, 167.51 }, +{ 167.69, 167.75 }, +{ 167.85, 167.91 }, +{ 168.01, 168.03 }, +{ 168.14, 168.24 }, +{ 168.34, 168.36 }, +{ 168.4, 168.45 }, +{ 168.49, 168.51 }, +{ 168.53, 168.57 }, +{ 168.59, 168.61 }, +{ 168.63, 168.65 }, +{ 168.68, 168.7 }, +{ 168.74, 168.8 }, +{ 168.92, 168.95 }, +{ 169.12, 169.14 }, +{ 169.23, 169.25 }, +{ 169.38, 169.47 }, +{ 169.55, 169.6 }, +{ 169.64, 169.68 }, +{ 169.74, 169.81 }, +{ 169.89, 169.93 }, +{ 169.97, 170 }, +{ 170.05, 170.08 }, +{ 170.21, 170.23 }, +{ 170.28, 170.3 }, +{ 170.37, 170.38 }, +{ 170.45, 170.45 }, +{ 170.49, 170.55 }, +{ 170.57, 170.61 }, +{ 170.64, 170.67 }, +{ -999.0, -999.0} diff --git a/src/gsfml/GST2012r.h b/src/gsfml/GST2012r.h new file mode 100644 index 00000000000..f4ea953fd07 --- /dev/null +++ b/src/gsfml/GST2012r.h @@ -0,0 +1,231 @@ +{ 0.781, 0.988 }, +{ 1.072, 1.173 }, +{ 1.185, 1.778 }, +{ 1.945, 2.128 }, +{ 2.148, 2.581 }, +{ 3.032, 3.116 }, +{ 3.207, 3.33 }, +{ 3.596, 4.187 }, +{ 4.3, 4.493 }, +{ 4.631, 4.799 }, +{ 4.896, 4.997 }, +{ 5.235, 6.033 }, +{ 6.252, 6.436 }, +{ 6.733, 7.14 }, +{ 7.212, 7.251 }, +{ 7.285, 7.454 }, +{ 7.489, 7.528 }, +{ 7.642, 7.695 }, +{ 8.108, 8.254 }, +{ 8.3, 8.771 }, +{ -1.0, -1.0 }, +{ 9.105, 9.311 }, +{ -1.0, -1.0 }, +{ 9.426, 9.647 }, +{ 9.721, 9.786 }, +{ 9.937, 9.984 }, +{ 11.056, 11.146 }, +{ 11.188, 11.592 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 11.657, -1.0 }, +{ -1.0, 12.049 }, +{ 12.174, 12.272 }, +{ 12.474, 12.735 }, +{ 12.77, 12.829 }, +{ 12.887, 13.032 }, +{ 13.183, 13.363 }, +{ 13.608, 13.739 }, +{ 14.07, 14.163 }, +{ 14.609, 14.775 }, +{ 14.87, 15.032 }, +{ 15.16, 15.974 }, +{ 16.268, 16.303 }, +{ 16.472, 16.543 }, +{ 16.721, 17.235 }, +{ 17.533, 17.717 }, +{ 17.74, 18.056 }, +{ 18.524, 18.748 }, +{ 19.722, 20.04 }, +{ 20.213, 20.439 }, +{ 20.709, 21.083 }, +{ 21.159, 21.403 }, +{ 21.483, 21.659 }, +{ 21.688, 21.767 }, +{ 21.936, 21.992 }, +{ 22.268, 22.564 }, +{ 22.754, 22.902 }, +{ 23.03, 23.233 }, +{ 23.295, 23.962 }, +{ 24, 24.109 }, +{ 24.474, 24.761 }, +{ 24.984, -1.0 }, +{ -1.0, 25.099 }, +{ 25.264, 25.304 }, +{ 25.987, 26.42 }, +{ 27.439, 27.859 }, +{ 28.087, 28.141 }, +{ 28.278, 29.183 }, +{ 29.477, 29.527 }, +{ 29.97, 30.591 }, +{ 31.034, 33.157 }, +{ 33.705, 34.999 }, +{ 35.294, 35.706 }, +{ 35.892, 36.051 }, +{ 36.7, 36.969 }, +{ 37.753, 37.872 }, +{ 38.093, 38.159 }, +{ 38.333, 38.615 }, +{ 39.627, 39.698 }, +{ 40.145, 41.154 }, +{ 41.39, 42.301 }, +{ 43.432, 45.724 }, +{ 47.349, 48.566 }, +{ 49.344, 50.628 }, +{ 50.835, 50.961 }, +{ 51.833, 52.62 }, +{ 53.074, 53.199 }, +{ 53.274, 53.416 }, +{ 53.983, 57.101 }, +{ 57.656, 58.959 }, +{ 59.237, 62.221 }, +{ 62.517, 63.494 }, +{ 64.667, 64.958 }, +{ 65.688, 66.398 }, +{ 68.196, 68.369 }, +{ 69.269, 71.449 }, +{ 71.689, 71.939 }, +{ 73.649, 73.949 }, +{ 74.049, 74.309 }, +{ 79.9, 83.64 }, +{ 125.93, 126.3 }, +{ 128.32, 128.66 }, +{ 129.11, 130.6 }, +{ 131.43, 131.74 }, +{ 131.92, 132.04 }, +{ 132.27, 132.55 }, +{ 132.8, 133.05 }, +{ 133.3, 133.58 }, +{ 133.88, 134.22 }, +{ 134.48, 134.51 }, +{ 134.76, 134.78 }, +{ 135, 135.32 }, +{ 135.92, 136.11 }, +{ 136.13, 136.29 }, +{ 136.69, 136.74 }, +{ 136.8, 136.87 }, +{ 137.06, 137.73 }, +{ 137.8, 137.94 }, +{ 138.17, 138.25 }, +{ 138.42, 138.66 }, +{ 138.91, 139.59 }, +{ 139.94, 140.42 }, +{ 141.64, 142.22 }, +{ 142.57, 144 }, +{ 144.64, 145.01 }, +{ 145.14, 145.19 }, +{ 146.28, 146.54 }, +{ 146.9, 146.96 }, +{ 147.72, 148.44 }, +{ 149.35, 149.8 }, +{ 151.12, 151.17 }, +{ 151.21, 151.25 }, +{ 151.32, 151.92 }, +{ 152.06, 152.25 }, +{ 152.64, 152.93 }, +{ 152.96, 153.62 }, +{ 153.87, 154.35 }, +{ 154.38, 154.59 }, +{ 154.73, 155.01 }, +{ 155.38, 155.54 }, +{ 155.85, 156.04 }, +{ 156.16, 156.22 }, +{ 156.29, 156.39 }, +{ 156.42, 156.56 }, +{ 156.69, 156.75 }, +{ 156.78, 156.84 }, +{ 156.94, 157.04 }, +{ 157.06, 157.25 }, +{ 157.4, 157.57 }, +{ 157.87, 158.02 }, +{ 158.12, 158.36 }, +{ 158.41, 158.5 }, +{ 158.6, 158.69 }, +{ 158.78, 158.89 }, +{ 159.04, 159.07 }, +{ 159.14, 159.38 }, +{ 159.43, 159.49 }, +{ 159.62, 159.78 }, +{ 159.88, 159.91 }, +{ 160.07, 160.15 }, +{ 160.18, 160.22 }, +{ 160.26, 160.32 }, +{ 160.34, 160.37 }, +{ 160.47, 160.52 }, +{ 160.55, 160.63 }, +{ 160.93, 161.06 }, +{ 161.14, 161.21 }, +{ 161.28, 161.39 }, +{ 161.43, 161.49 }, +{ 161.61, 161.81 }, +{ 161.89, 161.96 }, +{ 162.01, 162.04 }, +{ 162.06, 162.12 }, +{ 162.15, 162.28 }, +{ 162.37, 162.43 }, +{ 162.46, 162.49 }, +{ 162.55, 162.7 }, +{ 162.8, 162.86 }, +{ 162.9, 162.92 }, +{ 162.95, 163.1 }, +{ 163.16, 163.29 }, +{ 163.53, 163.65 }, +{ 163.76, 163.85 }, +{ 163.98, 164.03 }, +{ 164.18, 164.22 }, +{ 164.3, 164.41 }, +{ 164.63, 164.69 }, +{ 164.85, 164.91 }, +{ 165.08, 165.2 }, +{ 165.34, 165.4 }, +{ 165.53, 165.65 }, +{ 165.8, 165.96 }, +{ 166.08, 166.21 }, +{ 166.3, 166.4 }, +{ 166.47, 166.51 }, +{ 166.61, 166.68 }, +{ 166.72, 166.89 }, +{ 166.96, 167.05 }, +{ 167.11, 167.33 }, +{ 167.36, 167.43 }, +{ 167.51, 167.69 }, +{ 167.75, 167.85 }, +{ 167.91, 168.01 }, +{ 168.03, 168.14 }, +{ 168.24, 168.34 }, +{ 168.36, 168.4 }, +{ 168.45, 168.49 }, +{ 168.51, 168.53 }, +{ 168.57, 168.59 }, +{ 168.61, 168.63 }, +{ 168.65, 168.68 }, +{ 168.7, 168.74 }, +{ 168.8, 168.92 }, +{ 168.95, 169.12 }, +{ 169.14, 169.23 }, +{ 169.25, 169.38 }, +{ 169.47, 169.55 }, +{ 169.6, 169.64 }, +{ 169.68, 169.74 }, +{ 169.81, 169.89 }, +{ 169.93, 169.97 }, +{ 170, 170.05 }, +{ 170.08, 170.21 }, +{ 170.23, 170.28 }, +{ 170.3, 170.37 }, +{ 170.38, 170.45 }, +{ 170.45, 170.49 }, +{ 170.55, 170.57 }, +{ 170.61, 170.64 }, +{ 170.67, -1.0 }, +{ -999.0, -999.0} diff --git a/src/gsfml/Geek2007n.h b/src/gsfml/Geek2007n.h new file mode 100644 index 00000000000..ce8237d1d12 --- /dev/null +++ b/src/gsfml/Geek2007n.h @@ -0,0 +1,231 @@ +{ 0, 0.78 }, +{ 0.99, 1.07 }, +{ 1.201, 1.211 }, +{ 1.77, 1.95 }, +{ 2.14, 2.15 }, +{ 2.581, 3.04 }, +{ 3.11, 3.22 }, +{ 3.33, 3.58 }, +{ 4.18, 4.29 }, +{ 4.48, 4.62 }, +{ 4.8, 4.89 }, +{ 4.98, 5.23 }, +{ 5.894, 6.137 }, +{ 6.269, 6.567 }, +{ 6.935, 7.091 }, +{ 7.135, 7.17 }, +{ 7.341, 7.375 }, +{ 7.432, 7.562 }, +{ 7.65, 8.072 }, +{ 8.225, 8.257 }, +{ 8.606, 8.664 }, +{ 8.699, 9.025 }, +{ 9.097, 9.117 }, +{ 9.23, 9.308 }, +{ 9.58, 9.642 }, +{ 9.74, 9.88 }, +{ 9.92, 10.949 }, +{ 11.052, 11.099 }, +{ 11.167, 11.193 }, +{ 11.352, 11.363 }, +{ 11.476, 11.531 }, +{ 11.555, 11.584 }, +{ 11.935, 12.078 }, +{ 12.184, 12.401 }, +{ 12.678, 12.708 }, +{ 12.775, 12.819 }, +{ 12.991, 13.139 }, +{ 13.302, 13.51 }, +{ 13.703, 14.076 }, +{ 14.178, 14.612 }, +{ 14.8, 14.888 }, +{ 15.034, 15.155 }, +{ 16.014, 16.293 }, +{ 16.327, 16.488 }, +{ 16.556, 16.726 }, +{ 17.277, 17.615 }, +{ 17.793, 17.854 }, +{ 18.281, 18.781 }, +{ 19.048, 20.131 }, +{ 20.518, 20.725 }, +{ 20.996, 21.32 }, +{ 21.768, 21.859 }, +{ 22.151, 22.248 }, +{ 22.459, 22.493 }, +{ 22.588, 22.75 }, +{ 22.804, 23.069 }, +{ 23.353, 23.535 }, +{ 23.677, 23.8 }, +{ 23.999, 24.118 }, +{ 24.73, 24.781 }, +{ 24.835, 25.183 }, +{ 25.496, 25.648 }, +{ 25.678, 25.705 }, +{ 25.823, 25.951 }, +{ 25.992, 26.554 }, +{ 27.027, 27.972 }, +{ 28.283, 28.512 }, +{ 28.578, 28.745 }, +{ 29.401, 29.662 }, +{ 29.765, 30.098 }, +{ 30.479, 30.939 }, +{ 33.058, 33.545 }, +{ 34.655, 34.94 }, +{ 35.343, 35.526 }, +{ 35.685, 36.341 }, +{ 36.618, 37.473 }, +{ 37.604, 37.848 }, +{ 37.92, 38.113 }, +{ 38.426, 39.552 }, +{ 39.631, 40.13 }, +{ 41.257, 41.521 }, +{ 42.536, 43.789 }, +{ 46.264, 47.906 }, +{ 49.037, 49.714 }, +{ 50.778, 50.946 }, +{ 51.047, 51.743 }, +{ 52.364, 52.663 }, +{ 52.757, 52.801 }, +{ 52.903, 53.347 }, +{ 55.904, 56.391 }, +{ 57.554, 57.911 }, +{ 60.92, 61.276 }, +{ 62.499, 63.634 }, +{ 63.976, 64.745 }, +{ 65.578, 67.61 }, +{ 67.735, 68.737 }, +{ 71.071, 71.338 }, +{ 71.587, 73.004 }, +{ 73.291, 73.374 }, +{ 73.619, 79.075 }, +{ 83, 120.6 }, +{ 121, 123.19 }, +{ 123.55, 124.05 }, +{ 125.67, 126.57 }, +{ 126.91, 127.11 }, +{ 127.23, 127.49 }, +{ 127.79, 128.07 }, +{ 128.34, 128.62 }, +{ 128.93, 129.25 }, +{ 129.63, 129.91 }, +{ 129.95, 130.22 }, +{ 130.24, 130.49 }, +{ 130.84, 131.5 }, +{ 131.71, 131.73 }, +{ 131.91, 132.35 }, +{ 132.4, 132.47 }, +{ 132.55, 132.76 }, +{ 133.51, 133.58 }, +{ 133.73, 133.99 }, +{ 134.08, 134.27 }, +{ 134.53, 134.81 }, +{ 135.57, 135.96 }, +{ 136.49, 137.85 }, +{ 138.5, 138.89 }, +{ 140.51, 141.22 }, +{ 141.63, 141.78 }, +{ 141.88, 143.07 }, +{ 143.36, 143.77 }, +{ 143.84, 144.7 }, +{ 145.52, 146.56 }, +{ 147.06, 148.57 }, +{ 148.62, 148.67 }, +{ 148.72, 148.79 }, +{ 149.49, 149.72 }, +{ 150.04, 150.69 }, +{ 150.91, 150.93 }, +{ 151.4, 151.72 }, +{ 151.98, 152 }, +{ 152.15, 152.24 }, +{ 152.43, 153.13 }, +{ 153.43, 154 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 154.31, 155.32 }, +{ 155.55, 155.8 }, +{ 156.05, 156.19 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 156.51, 157.27 }, +{ 157.53, 157.582 }, +{ 157.653, 157.785 }, +{ 157.957, 158.063 }, +{ 158.096, 158.262 }, +{ 158.35, 158.379 }, +{ 158.424, 158.471 }, +{ 158.528, 158.553 }, +{ 158.584, 158.689 }, +{ 158.745, 158.776 }, +{ 158.866, 159.182 }, +{ 159.324, 159.408 }, +{ 159.482, 159.555 }, +{ 159.676, 159.717 }, +{ 159.773, 159.903 }, +{ 160.121, 160.206 }, +{ 160.282, 160.33 }, +{ 160.361, 160.385 }, +{ 160.444, 160.479 }, +{ 160.617, 160.714 }, +{ 160.78, 160.809 }, +{ 160.844, 160.914 }, +{ 161.069, 161.18 }, +{ 161.24, 161.286 }, +{ 161.309, 161.34 }, +{ 161.491, 161.566 }, +{ 161.698, 161.957 }, +{ 162.08, 162.199 }, +{ 162.302, 162.442 }, +{ 162.494, 162.65 }, +{ 162.693, 162.777 }, +{ 162.896, 163.131 }, +{ 163.204, 163.37 }, +{ 163.44, 163.625 }, +{ 163.745, 163.896 }, +{ 163.966, 164.1 }, +{ 164.236, 164.391 }, +{ 164.571, 164.7 }, +{ 164.833, 164.934 }, +{ 165.042, 165.113 }, +{ 165.161, 165.264 }, +{ 165.343, 165.384 }, +{ 165.572, 165.642 }, +{ 165.736, 165.805 }, +{ 166.043, 166.076 }, +{ 166.149, 166.234 }, +{ 166.429, 166.497 }, +{ 166.606, 166.669 }, +{ 166.776, 166.804 }, +{ 166.919, 167.028 }, +{ 167.138, 167.16 }, +{ 167.205, 167.257 }, +{ 167.298, 167.323 }, +{ 167.341, 167.382 }, +{ 167.406, 167.432 }, +{ 167.447, 167.476 }, +{ 167.502, 167.525 }, +{ 167.569, 167.639 }, +{ 167.768, 167.792 }, +{ 167.983, 168.008 }, +{ 168.105, 168.121 }, +{ 168.259, 168.363 }, +{ 168.448, 168.503 }, +{ 168.551, 168.585 }, +{ 168.656, 168.729 }, +{ 168.813, 168.864 }, +{ 168.908, 168.934 }, +{ 168.986, 169.023 }, +{ 169.166, 169.184 }, +{ 169.242, 169.26 }, +{ 169.337, 169.349 }, +{ 169.421, 169.431 }, +{ 169.474, 169.531 }, +{ 169.558, 169.6 }, +{ 169.638, 169.662 }, +{ -999.0, -999.0} diff --git a/src/gsfml/Geek2007r.h b/src/gsfml/Geek2007r.h new file mode 100644 index 00000000000..709e7b1976c --- /dev/null +++ b/src/gsfml/Geek2007r.h @@ -0,0 +1,231 @@ +{ 0.78, 0.99 }, +{ 1.07, 1.201 }, +{ 1.211, 1.77 }, +{ 1.95, 2.14 }, +{ 2.15, 2.581 }, +{ 3.04, 3.11 }, +{ 3.22, 3.33 }, +{ 3.58, 4.18 }, +{ 4.29, 4.48 }, +{ 4.62, 4.8 }, +{ 4.89, 4.98 }, +{ 5.23, 5.894 }, +{ 6.137, 6.269 }, +{ 6.567, 6.935 }, +{ 7.091, 7.135 }, +{ 7.17, 7.341 }, +{ 7.375, 7.432 }, +{ 7.562, 7.65 }, +{ 8.072, 8.225 }, +{ 8.257, 8.606 }, +{ 8.664, 8.699 }, +{ 9.025, 9.097 }, +{ 9.117, 9.23 }, +{ 9.308, 9.58 }, +{ 9.642, 9.74 }, +{ 9.88, 9.92 }, +{ 10.949, 11.052 }, +{ 11.099, 11.167 }, +{ 11.193, 11.352 }, +{ 11.363, 11.476 }, +{ 11.531, 11.555 }, +{ 11.584, 11.935 }, +{ 12.078, 12.184 }, +{ 12.401, 12.678 }, +{ 12.708, 12.775 }, +{ 12.819, 12.991 }, +{ 13.139, 13.302 }, +{ 13.51, 13.703 }, +{ 14.076, 14.178 }, +{ 14.612, 14.8 }, +{ 14.888, 15.034 }, +{ 15.155, 16.014 }, +{ 16.293, 16.327 }, +{ 16.488, 16.556 }, +{ 16.726, 17.277 }, +{ 17.615, 17.793 }, +{ 17.854, 18.281 }, +{ 18.781, 19.048 }, +{ 20.131, 20.518 }, +{ 20.725, 20.996 }, +{ 21.32, 21.768 }, +{ 21.859, 22.151 }, +{ 22.248, 22.459 }, +{ 22.493, 22.588 }, +{ 22.75, 22.804 }, +{ 23.069, 23.353 }, +{ 23.535, 23.677 }, +{ 23.8, 23.999 }, +{ 24.118, 24.73 }, +{ 24.781, 24.835 }, +{ 25.183, 25.496 }, +{ 25.648, 25.678 }, +{ 25.705, 25.823 }, +{ 25.951, 25.992 }, +{ 26.554, 27.027 }, +{ 27.972, 28.283 }, +{ 28.512, 28.578 }, +{ 28.745, 29.401 }, +{ 29.662, 29.765 }, +{ 30.098, 30.479 }, +{ 30.939, 33.058 }, +{ 33.545, 34.655 }, +{ 34.94, 35.343 }, +{ 35.526, 35.685 }, +{ 36.341, 36.618 }, +{ 37.473, 37.604 }, +{ 37.848, 37.92 }, +{ 38.113, 38.426 }, +{ 39.552, 39.631 }, +{ 40.13, 41.257 }, +{ 41.521, 42.536 }, +{ 43.789, 46.264 }, +{ 47.906, 49.037 }, +{ 49.714, 50.778 }, +{ 50.946, 51.047 }, +{ 51.743, 52.364 }, +{ 52.663, 52.757 }, +{ 52.801, 52.903 }, +{ 53.347, 55.904 }, +{ 56.391, 57.554 }, +{ 57.911, 60.92 }, +{ 61.276, 62.499 }, +{ 63.634, 63.976 }, +{ 64.745, 65.578 }, +{ 67.61, 67.735 }, +{ 68.737, 71.071 }, +{ 71.338, 71.587 }, +{ 73.004, 73.291 }, +{ 73.374, 73.619 }, +{ 79.075, 83 }, +{ 120.6, 121 }, +{ 123.19, 123.55 }, +{ 124.05, 125.67 }, +{ 126.57, 126.91 }, +{ 127.11, 127.23 }, +{ 127.49, 127.79 }, +{ 128.07, 128.34 }, +{ 128.62, 128.93 }, +{ 129.25, 129.63 }, +{ 129.91, 129.95 }, +{ 130.22, 130.24 }, +{ 130.49, 130.84 }, +{ 131.5, 131.71 }, +{ 131.73, 131.91 }, +{ 132.35, 132.4 }, +{ 132.47, 132.55 }, +{ 132.76, 133.51 }, +{ 133.58, 133.73 }, +{ 133.99, 134.08 }, +{ 134.27, 134.53 }, +{ 134.81, 135.57 }, +{ 135.96, 136.49 }, +{ 137.85, 138.5 }, +{ 138.89, 140.51 }, +{ 141.22, 141.63 }, +{ 141.78, 141.88 }, +{ 143.07, 143.36 }, +{ 143.77, 143.84 }, +{ 144.7, 145.52 }, +{ 146.56, 147.06 }, +{ 148.57, 148.62 }, +{ 148.67, 148.72 }, +{ 148.79, 149.49 }, +{ 149.72, 150.04 }, +{ 150.69, 150.91 }, +{ 150.93, 151.4 }, +{ 151.72, 151.98 }, +{ 152, 152.15 }, +{ 152.24, 152.43 }, +{ 153.13, 153.43 }, +{ 154, 154.31 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 155.32, 155.55 }, +{ 155.8, 156.05 }, +{ 156.19, 156.51 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ -1.0, -1.0 }, +{ 157.27, 157.53 }, +{ 157.582, 157.653 }, +{ 157.785, 157.957 }, +{ 158.063, 158.096 }, +{ 158.262, 158.35 }, +{ 158.379, 158.424 }, +{ 158.471, 158.528 }, +{ 158.553, 158.584 }, +{ 158.689, 158.745 }, +{ 158.776, 158.866 }, +{ 159.182, 159.324 }, +{ 159.408, 159.482 }, +{ 159.555, 159.676 }, +{ 159.717, 159.773 }, +{ 159.903, 160.121 }, +{ 160.206, 160.282 }, +{ 160.33, 160.361 }, +{ 160.385, 160.444 }, +{ 160.479, 160.617 }, +{ 160.714, 160.78 }, +{ 160.809, 160.844 }, +{ 160.914, 161.069 }, +{ 161.18, 161.24 }, +{ 161.286, 161.309 }, +{ 161.34, 161.491 }, +{ 161.566, 161.698 }, +{ 161.957, 162.08 }, +{ 162.199, 162.302 }, +{ 162.442, 162.494 }, +{ 162.65, 162.693 }, +{ 162.777, 162.896 }, +{ 163.131, 163.204 }, +{ 163.37, 163.44 }, +{ 163.625, 163.745 }, +{ 163.896, 163.966 }, +{ 164.1, 164.236 }, +{ 164.391, 164.571 }, +{ 164.7, 164.833 }, +{ 164.934, 165.042 }, +{ 165.113, 165.161 }, +{ 165.264, 165.343 }, +{ 165.384, 165.572 }, +{ 165.642, 165.736 }, +{ 165.805, 166.043 }, +{ 166.076, 166.149 }, +{ 166.234, 166.429 }, +{ 166.497, 166.606 }, +{ 166.669, 166.776 }, +{ 166.804, 166.919 }, +{ 167.028, 167.138 }, +{ 167.16, 167.205 }, +{ 167.257, 167.298 }, +{ 167.323, 167.341 }, +{ 167.382, 167.406 }, +{ 167.432, 167.447 }, +{ 167.476, 167.502 }, +{ 167.525, 167.569 }, +{ 167.639, 167.768 }, +{ 167.792, 167.983 }, +{ 168.008, 168.105 }, +{ 168.121, 168.259 }, +{ 168.363, 168.448 }, +{ 168.503, 168.551 }, +{ 168.585, 168.656 }, +{ 168.729, 168.813 }, +{ 168.864, 168.908 }, +{ 168.934, 168.986 }, +{ 169.023, 169.166 }, +{ 169.184, 169.242 }, +{ 169.26, 169.337 }, +{ 169.349, 169.421 }, +{ 169.431, 169.474 }, +{ 169.531, 169.558 }, +{ 169.6, 169.638 }, +{ -1.0, -1.0 }, +{ -999.0, -999.0} diff --git a/src/gsfml/README.gsfml b/src/gsfml/README.gsfml new file mode 100644 index 00000000000..205eff4ac24 --- /dev/null +++ b/src/gsfml/README.gsfml @@ -0,0 +1,53 @@ +GSFML Supplemental Package +Distributed under the GNU Lesser Public License; see file +LICENSE.TXT in main GMT directory. + +------------------------------------------------------ +Author: Paul Wessel (pwessel@hawaii.edu) + SOEST, University of Hawaii +Date: December 1, 2023 +Version: 6 (for GMT 6 release). +------------------------------------------------------ + +This directory contains: + +README.gsfml : This document +fzanalyzer.c : fzanalyser C program code +fzblender.c : fzblender C program code +mlconverter.c : mlconverter C program code +fz_analysis.h : Include file for these programs +CK1995n.h : Cande & Kent 1995 normal chron ages +Chron_Normal.h : Normal Chron identifiers +Chron_Reverse.h : Referse Chron identifiers +GST2004n.h : Gradstein et al 2004 normal chron ages +GST2012n.h : Gradstein et al 2012 normal chron ages +Geek2007n.h : Gee and Kent 2007 normal chron ages +CK1995r.h : Cande & Kent 1995 reverse chron ages +Chron_Normal2.h : Normal Chron identifiers without periods or dashes +Chron_Reverse2.h : Referse Chron identifiers without periods or dashes +GST2004r.h : Gradstein et al 2004 reverse chron ages +GST2012r.h : Gradstein et al 2012 reverse chron ages +Geek2007r.h : Gee and Kent 2007 reverse chron ages + + +This package contains 3 programs and 4 bash scripts that may be useful +to people who work with seafloor fabric and magnetic lineations. +The seven programs are + + fzanalyser - Analysis of fracture zones using crossing profiles + fzblender - Optimal refinement of fracture zone traces + mlconverter - Convert chron strings to ages using a magnetic time scale + fzinformer - Plot along-FZ statistical information + fzmapper - Make Mercator map of FZ traces and cross-profiles + fzmodeler - Make and optionally plot a synthetic FZ model profile + fzprofiler - Plot one or all FZ cross-profiles + fz_funcs.sh - Sub-functions for the 4 scripts + +REFERENCES: + +-> The hotspotting technique: + +Wessel, P., K. J. Matthews, R. D. Müller, A. Mazzoni, J. M. Whittaker, + R. Myhill, and M. T. Chandler, 2015, Semiautomatic fracture zone tracking, + Geochemistry, Geophysics, Geosystems, 10.1002/2015GC005853, + http://dx.doi.org/10.1002/2015gc005853. diff --git a/src/gsfml/fz_analysis.h b/src/gsfml/fz_analysis.h new file mode 100644 index 00000000000..f608d8b510e --- /dev/null +++ b/src/gsfml/fz_analysis.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-2023 by P. Wessel + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: http://www.soest.hawaii.edu/PT/GSFML + *-------------------------------------------------------------------- + * + * Named indices for output table for fzanalyzer trace analysis. + * + * Author: Paul Wessel + * Date: 01-DEC-2023 (requires GMT >= 6) + */ + +#ifndef _FZ_ANALYSIS_H +#define _FZ_ANALYSIS_H + +#define DEF_D_WIDTH 25.0 /* Default width of central corridor */ +#define DEF_L_MIN 0.0 /* Minimum compression for search */ +#define DEF_L_MAX 1.0 /* Maximum compression for search */ +#define DEF_L_INC 0.05 /* Increment for compression search */ +#define DEF_M_MIN 0.0 /* Minimum asymmetry for search */ +#define DEF_M_MAX 1.0 /* Maximum asymmetry for search */ +#define DEF_M_INC 0.05 /* Increment for asymmetry search */ +#define DEF_W_MIN 1.0 /* Minimum width for search */ +#define DEF_W_MAX 50.0 /* Maximum width for search */ +#define DEF_W_INC 1.0 /* Increment for width search */ + +#define N_FZ_ANALYSIS_COLS 61 /* Number of output columns for final result */ + +#define POS_XR 0 /* Longitude of raw digitizing */ +#define POS_YR 1 /* Latitude of raw digitizing */ +#define POS_DR 2 /* Distance at point along raw digitized trace */ +#define POS_AR 3 /* Azimuth at point along raw digitized trace */ +#define POS_ZR 4 /* Data value at point of raw digitizing */ +#define POS_TL 5 /* Crustal age estimate at left side of FZ (negative distances) */ +#define POS_TR 6 /* Crustal age estimate at right side of FZ (positive distances) */ +#define POS_SD 7 /* Offset of data minimum (in km) from raw line origin */ +#define POS_ST 8 /* Offset of trough model minimum (in km) from raw line origin */ +#define POS_SB 9 /* Offset of blend model minimum (in km) from raw line origin */ +#define POS_SE 10 /* Offset of blend model maximum slope (in km) from raw line origin */ +#define POS_BL 11 /* Best asymmetry value [0-1] */ +#define POS_OR 12 /* Orientation of model profile (-1 =>old on negative dist side, +1 => old on positive dist side) */ +#define POS_WD 13 /* Width of data trough */ +#define POS_WT 14 /* Width of model trough (trough) */ +#define POS_WB 15 /* Width of model trough (blend) */ +#define POS_AD 16 /* Peak-to-trough amplitude from data */ +#define POS_AT 17 /* Peak-to-trough amplitude from model (trough) */ +#define POS_AB 18 /* Peak-to-trough amplitude from model (blend) */ +#define POS_UT 19 /* Flank relative amplitude from model (trough) */ +#define POS_UB 20 /* Flank relative amplitude from model (blend) */ +#define POS_VT 21 /* Variance reduction (%) from model (trough) */ +#define POS_VB 22 /* Variance reduction (%) from model (blend) */ +#define POS_FT 23 /* F-statistic for model (trough) */ +#define POS_FB 24 /* F-statistic for model (blend) */ +#define POS_XDL 25 /* Longitude of data minimum left bounds */ +#define POS_XD0 26 /* Longitude of data minimum (trough) */ +#define POS_XDR 27 /* Longitude of data minimum right bounds */ +#define POS_YDL 28 /* Latitude of data minimum left bounds */ +#define POS_YD0 29 /* Latitude of data minimum (trough) */ +#define POS_YDR 30 /* Latitude of data minimum right bounds */ +#define POS_ZDL 31 /* Data value of data minimum left bounds */ +#define POS_ZD0 32 /* Data value of data minimum (trough) */ +#define POS_ZDR 33 /* Data value of data minimum right bounds */ +#define POS_XTL 34 /* Longitude of model minimum (trough) left bounds */ +#define POS_XT0 35 /* Longitude of model minimum (trough) */ +#define POS_XTR 36 /* Longitude of model minimum (trough) right bounds */ +#define POS_YTL 37 /* Latitude of model minimum (trough) left bounds */ +#define POS_YT0 38 /* Latitude of model minimum (trough) */ +#define POS_YTR 39 /* Latitude of model minimum (trough) right bounds */ +#define POS_ZTL 40 /* Model value at (trough) left bounds */ +#define POS_ZT0 41 /* Model value at minimum (trough) */ +#define POS_ZTR 42 /* Model value at (trough) right bounds */ +#define POS_XBL 43 /* Longitude of model minimum (blend) left bounds */ +#define POS_XB0 44 /* Longitude of model minimum (blend) */ +#define POS_XBR 45 /* Longitude of model minimum (blend) right bounds */ +#define POS_YBL 46 /* Latitude of model minimum (blend) left bounds */ +#define POS_YB0 47 /* Latitude of model minimum (blend) */ +#define POS_YBR 48 /* Latitude of model minimum (blend) right bounds */ +#define POS_ZBL 49 /* Model value at (blend) left bounds */ +#define POS_ZB0 50 /* Model value at minimum (blend) */ +#define POS_ZBR 51 /* Model value at (blend) right bounds */ +#define POS_XEL 52 /* Longitude of model max slope (blend) left bounds */ +#define POS_XE0 53 /* Longitude of model max slope (blend) */ +#define POS_XER 54 /* Longitude of model max slope (blend) right bounds */ +#define POS_YEL 55 /* Latitude of model max slope (blend) left bounds */ +#define POS_YE0 56 /* Latitude of model max slope (blend) */ +#define POS_YER 57 /* Latitude of model max slope (blend) right bounds */ +#define POS_ZEL 58 /* Model value at max slope (blend) left bounds */ +#define POS_ZE0 59 /* Model value at max slope (blend) */ +#define POS_ZER 60 /* Model value at max slope (blend) right bounds */ + +#define FZ_PAC 0 /* Array index for "Pacific" (isostatic edge dipole) model */ +#define FZ_ATL 1 /* Array index for "Atlantic" (isostatic symmetric trough) model */ +#define FZ_EMP 2 /* Array index for empirical model */ +#endif /* _FZ_ANALYSIS_H */ diff --git a/src/gsfml/fz_funcs.sh b/src/gsfml/fz_funcs.sh new file mode 100644 index 00000000000..615909a610a --- /dev/null +++ b/src/gsfml/fz_funcs.sh @@ -0,0 +1,118 @@ +#!/bin/bash +#-------------------------------------------------------------------- +# Copyright (c) 2015-2023 by P. Wessel +# See LICENSE.TXT file for copying and redistribution conditions. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; version 3 or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# Contact info: http://www.soest.hawaii.edu/PT/GSFML +#-------------------------------------------------------------------- +# Functions used by GSFML scripts +# These do not require GMT; they do basic stuff with Unix tools only +# +# Author: Paul Wessel +# Date: 01-DEC-2023 +# Mode: GMT classic mode +#-------------------------------------------------------------------- + +function fz_get_version +{ # Just echoes the current GSFML version + echo "2.0 [2023]" +} + +function fz_cleanup() { + rm -f *$$* + exit $1 +} + +function fz_get_dim +{ # Expects a dimension with trailing unit, e,g, 15c, and returns inches. Note we skip the first 2 chars which are option flag, e.g. -W[c|i] + echo $1 | awk '{if (substr($1,length($1),1) == "c") {print substr($1,3,length($1)-3)/2.54} else if (substr($1,length($1),1) == "i") {print substr($1,3,length($1)-3)} else {print substr($1,3)}}' +} + +function fz_get_arg +{ # Expects a arg. Note we skip the first 2 chars which are option flag, e.g. -W + echo $1 | awk '{print substr($1,3)}' +} + +function fz_get_item +{ # Expects a two-char name as arg2 (e.g., az or VB) and pulls out value from header record arg1 + # Must make sure arg1 is passed as one item (i.e., in double quotes) + echo $1 | tr ' ' '\n' | awk '{ if (substr($1,1,2) == "'$2'") print substr($1,4)}' +} + +function fz_col_id +{ # Returns the column number 0-60 given the tag + case $1 in + XR ) col=0 ;; + YR ) col=1 ;; + DR ) col=2 ;; + AR ) col=3 ;; + ZR ) col=4 ;; + TL ) col=5 ;; + TR ) col=6 ;; + SD ) col=7 ;; + ST ) col=8 ;; + SB ) col=9 ;; + SE ) col=10 ;; + BL ) col=11 ;; + OR ) col=12 ;; + WD ) col=13 ;; + WT ) col=14 ;; + WB ) col=15 ;; + AD ) col=16 ;; + AT ) col=17 ;; + AB ) col=18 ;; + UT ) col=19 ;; + UB ) col=20 ;; + VT ) col=21 ;; + VB ) col=22 ;; + FT ) col=23 ;; + FB ) col=24 ;; + XDL ) col=25 ;; + XD0 ) col=26 ;; + XDR ) col=27 ;; + YDL ) col=28 ;; + YD0 ) col=29 ;; + YDR ) col=30 ;; + ZDL ) col=31 ;; + ZD0 ) col=32 ;; + ZDR ) col=33 ;; + XTL ) col=34 ;; + XT0 ) col=35 ;; + XTR ) col=36 ;; + YTL ) col=37 ;; + YT0 ) col=38 ;; + YTR ) col=39 ;; + ZTL ) col=40 ;; + ZT0 ) col=41 ;; + ZTR ) col=42 ;; + XBL ) col=43 ;; + XB0 ) col=44 ;; + XBR ) col=45 ;; + YBL ) col=46 ;; + YB0 ) col=47 ;; + YBR ) col=48 ;; + ZBL ) col=49 ;; + ZB0 ) col=50 ;; + ZBR ) col=51 ;; + XEL ) col=52 ;; + XE0 ) col=53 ;; + XER ) col=54 ;; + YEL ) col=55 ;; + YE0 ) col=56 ;; + YER ) col=57 ;; + ZEL ) col=58 ;; + ZE0 ) col=59 ;; + ZER ) col=60 ;; + * ) echo "Bad tag in fz_col"; col=0 ;; + esac + echo $col +} diff --git a/src/gsfml/fzanalyzer.c b/src/gsfml/fzanalyzer.c new file mode 100644 index 00000000000..38da8335a4f --- /dev/null +++ b/src/gsfml/fzanalyzer.c @@ -0,0 +1,982 @@ +/* + * Copyright (c) 2015-2023 by P. Wessel + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: http://www.soest.hawaii.edu/PT/GSFML + *-------------------------------------------------------------------- + * + * fzanalyzer analyses a series of profiles across fracture zones + * + * Author: Paul Wessel + * Date: 01-DEC-2023 (Requires GMT >= 6) + */ + +#define THIS_MODULE_CLASSIC_NAME "fzanalyzer" +#define THIS_MODULE_MODERN_NAME "fzanalyzer" +#define THIS_MODULE_LIB "gsfml" +#define THIS_MODULE_PURPOSE "Analysis of fracture zones using crossing profiles" +#define THIS_MODULE_KEYS "DO" +#define THIS_MODULE_NEEDS "" +#define THIS_MODULE_OPTIONS "-Vb:hios>" + +#include "gmt_dev.h" +#include "fz_analysis.h" +#include "longopt/fzanalyzer_inc.h" + +#define DEF_FZ_GAP 5.0 /* Half-width of FZ gap centered on d0 where we ignore ages in fitting a + b(d-d0) + c*H(d-d0) */ + +#define FZ_G0 0 +#define FZ_G1 1 +#define FZ_G2 2 + +#define N_REQUIRED_COLS 7 + +struct FZMODELER_CTRL { + struct In { + bool active; + char *file; + } In; + struct A { /* -A// */ + bool active; + double min, max, inc; + } A; + struct C { /* -C// */ + bool active; + double min, max, inc; + } C; + struct D { /* -Dcorr_width */ + bool active; + double corr_width; + } D; + struct F { /* -F */ + bool active; + char *file; + } F; + struct I { /* -I[/] */ + bool active; + int64_t fz; + int profile; + } I; + struct S { /* -S[b|c] */ + bool active; + int mode; /* 0 = bash/sh, 1 = csh/tcsh syntax */ + } S; + struct T { /* -T */ + bool active; + char *prefix; + } T; + struct W { /* -W// */ + bool active; + double min, max, inc; + } W; +}; + +#define N_SHAPES 3 /* Number of shapes to blend (G0, G1, and G2) */ + +/* Named indices for the results array for one profile */ + +#define BEST_MODEL_B 0 /* Entry for the asymmetry parameter m [0,1] */ +#define BEST_WAY_B 1 /* Entry for the normal or reversed profile model (-1 means negative distance side is the old side in Pacific FZ model) */ +#define BEST_FZLOC_B 2 /* Entry for the distance of the FZ crossing */ +#define BEST_WIDTH_B 3 /* Entry for the best model FZ width w */ +#define BEST_FLANK_B 4 /* Entry for the best model flank relative amplitude (> 0) */ +#define BEST_AMPLT_B 5 /* Entry for the best model peak-to-trough amplitude (> 0) */ +#define BEST_VARMD_B 6 /* Entry for the best model variance reduction [0-100%] */ +#define BEST_INTER_B 7 /* Entry for the best model intercept */ +#define BEST_SLOPE_B 8 /* Entry for the best model linear slope */ +#define BEST_FSTAT_B 9 /* Entry for the best model F statistic */ +#define BEST_FZLOC_T 10 /* As BEST_FZLOC_B but for asymmetry = 0 */ +#define BEST_WIDTH_T 11 /* As BEST_WIDTH_B but for asymmetry = 0 */ +#define BEST_FLANK_T 12 /* As BEST_FLANK_B but for asymmetry = 0 */ +#define BEST_AMPLT_T 13 /* As BEST_AMPLT_B but for asymmetry = 0 */ +#define BEST_VARMD_T 14 /* As BEST_VARMD_B but for asymmetry = 0 */ +#define BEST_INTER_T 15 /* As BEST_INTER_B but for asymmetry = 0 */ +#define BEST_SLOPE_T 16 /* As BEST_SLOPE_B but for asymmetry = 0 */ +#define BEST_FSTAT_T 17 /* As BEST_FSTAT_B but for asymmetry = 0 */ +#define BEST_WIDTH_D 18 /* Entry for best data FZ width */ +#define BEST_AMPLT_D 19 /* Entry for best data peak/trough amplitude */ +#define BEST_XD_1 20 /* Entry for the raw data 1-sigma left side point longitude */ +#define BEST_XD_M 21 /* Entry for the raw data longitude at FZ crossing */ +#define BEST_XD_2 22 /* Entry for the raw data 1-sigma right side point longitude */ +#define BEST_YD_1 23 /* Entry for the raw data 1-sigma left side point latitude */ +#define BEST_YD_M 24 /* Entry for the raw data latitude at FZ crossing */ +#define BEST_YD_2 25 /* Entry for the raw data 1-sigma right side point latitude */ +#define BEST_ZD_1 26 /* Entry for the raw data 1-sigma left side point data value */ +#define BEST_ZD_M 27 /* Entry for the raw data data value at FZ crossing **/ +#define BEST_ZD_2 28 /* Entry for the raw data 1-sigma right side point data value */ +#define BEST_XT_1 29 /* Entry for the blend model 1-sigma left side point longitude */ +#define BEST_XT_M 30 /* Entry for the blend model longitude at FZ crossing */ +#define BEST_XT_2 31 /* Entry for the blend model 1-sigma right side point longitude */ +#define BEST_YT_1 32 /* Entry for the blend model 1-sigma left side point latitude */ +#define BEST_YT_M 33 /* Entry for the blend model latitude at FZ crossing */ +#define BEST_YT_2 34 /* Entry for the blend model 1-sigma right side point latitude */ +#define BEST_ZT_1 35 /* Entry for the blend model 1-sigma left side point data value */ +#define BEST_ZT_M 36 /* Entry for the blend model data value at FZ crossing **/ +#define BEST_ZT_2 37 /* Entry for the blend model 1-sigma right side point data value */ +#define BEST_XB_1 38 /* Entry for the blend model 1-sigma left side point longitude */ +#define BEST_XB_M 39 /* Entry for the blend model longitude at FZ crossing */ +#define BEST_XB_2 40 /* Entry for the blend model 1-sigma right side point longitude */ +#define BEST_YB_1 41 /* Entry for the blend model 1-sigma left side point latitude */ +#define BEST_YB_M 42 /* Entry for the blend model latitude at FZ crossing */ +#define BEST_YB_2 43 /* Entry for the blend model 1-sigma right side point latitude */ +#define BEST_ZB_1 44 /* Entry for the blend model 1-sigma left side point data value */ +#define BEST_ZB_M 45 /* Entry for the blend model data value at FZ crossing **/ +#define BEST_ZB_2 46 /* Entry for the blend model 1-sigma right side point data value */ +#define BEST_XE_1 47 /* Entry for the blend model [maximum slope] 1-sigma left side point longitude */ +#define BEST_XE_M 48 /* Entry for the blend model [maximum slope] longitude at FZ crossing */ +#define BEST_XE_2 49 /* Entry for the blend model [maximum slope] 1-sigma right side point longitude */ +#define BEST_YE_1 50 /* Entry for the blend model [maximum slope] 1-sigma left side point latitude */ +#define BEST_YE_M 51 /* Entry for the blend model [maximum slope] latitude at FZ crossing */ +#define BEST_YE_2 52 /* Entry for the blend model [maximum slope] 1-sigma right side point latitude */ +#define BEST_ZE_1 53 /* Entry for the blend model [maximum slope] 1-sigma left side point data value */ +#define BEST_ZE_M 54 /* Entry for the blend model [maximum slope] data value at FZ crossing **/ +#define BEST_ZE_2 55 /* Entry for the blend model [maximum slope] 1-sigma right side point data value */ +#define N_RESULTS 56 /* Big enough to hold all the BEST_* values */ + +/* Named indices for cross-section traces */ + +#define N_CROSS_COLS 9 /* Number of output columns (below) for cross profiles */ +#define XPOS_X 0 /* Longitudes along cross profile */ +#define XPOS_Y 1 /* Latitudes along cross profile */ +#define XPOS_D 2 /* Distances along cross profile */ +#define XPOS_A 3 /* Azimuths along cross profile */ +#define XPOS_Z 4 /* Data values along cross profile */ +#define XPOS_C 5 /* Crustal ages (C) along cross profile */ +#define XPOS_S 6 /* Distances to nearest FZ along cross profile */ +#define XPOS_T 7 /* Best-fitting Trough model (incl. trend) along cross profile */ +#define XPOS_B 8 /* Best-fitting Blend model (incl. trend) along cross profile */ + +#include "fz_analysis.h" + +#define LOC_DATA 0 /* Array id for location of minimum data value (the data trough) */ +#define LOC_TROUGH 1 /* Array id for location of fZ for m = 0 (the model trough for Atlantic signal) */ +#define LOC_BLEND_T 2 /* Array id for location of trough in fZ for best m (the model FZ location for optimal blend signal) */ +#define LOC_BLEND_E 3 /* Array id for location of max slope in fZ for best m (the model FZ location for optimal blend signal) */ + +typedef void (*PFV) (double *d, int nd, double d0, double width, int way, double *vgg); + +/* The synthetic FZ model is a blend of three Gaussian functions G0, G1, and G2: + model = A * [ a * G1 + (1 - a) * (c * G2 - G0)] + m + qx + The (G0 + c * G2) is the symmetric part (c controls amount of compression [0-1]) and + G1 is the asymmetric part. The amount of asymmetry in the model is given + by the asymmetry parameter a (0-1). We also model a linear trend m + qx. +*/ + +GMT_LOCAL void FZ_gaussian0 (double *d, int nd, double d0, double width, int i, double *vgg) +{ /* G0: Fake VGG signal over a trough [The "Atlantic" signal]. Here, + * d0 is position of FZ (the trough) and width is the Gaussian width. + * The signal is normalized to give unit amplitude. + * way is not used here since the signal is symmetric, so we call it i instead + * so we can used it for something else and shut up compiler warnings. + */ + double i_s, z, f; + f = M_SQRT2; + i_s = f / width; /* s = w/f; here we use 1/s to avoid division below */ + for (i = 0; i < nd; i++) { + z = (d[i] - d0) * i_s; /* Normalized distance */ + vgg[i] = exp (-z * z); + } +} + +GMT_LOCAL void FZ_gaussian1 (double *d, int nd, double d0, double width, int way, double *vgg) +{ /* G1: Fake VGG signal over an isostatic edge [The "Pacific" signal]. Here, + * d0 is position of FZ (steepest VGG gradient) and width is the peak-to-trough distance. + * The signal is normalized to give unit peak-to-trough amplitude. + * way is -1 or +1 and signals which side is young (we reflect the profile left/right) + * way == +1 means the left side of the profile (negative d values) is the old side. + */ + int i; + double i_s, z, f, i_A; + f = M_SQRT2; + i_s = f / width; /* s = w/f; here we use 1/s to avoid division below */ + i_A = 1.0 / (M_SQRT2 * exp (-0.5)); /* Amplitude scaling; again inverted to avoid division in loop */ + for (i = 0; i < nd; i++) { + z = (d[i] - d0) * i_s; /* Normalized distance */ + if (way == -1) z = -z; /* Since we reflect signal about the d0 axis */ + vgg[i] = z * exp (-z * z) * i_A; + } +} + +GMT_LOCAL void FZ_gaussian2 (double *d, int nd, double d0, double width, int i, double *vgg) +{ /* G2: Fake VGG signal over an FZ in compression (which raises bulges). Here, + * d0 is position of FZ (the trough) and width is the Gaussian width. + * The signal is normalized to give unit peak-to-trough amplitude. + * way is not used here since the signal is symmetric, so we call it i instead + * so we can used it for something else and shut up compiler warnings. + */ + double i_s, z, f, i_A; + f = M_SQRT2; + i_s = f / width; /* s = w/f; here we use 1/s to avoid division below */ + i_A = M_E; /* Amplitude scaling; again inverted to avoid division in loop */ + for (i = 0; i < nd; i++) { + z = (d[i] - d0) * i_s; /* Normalized distance */ + z *= z; /* z Squared */ + vgg[i] = z * exp (-z) * i_A; + } +} + +GMT_LOCAL void FZ_blendmodel (double *G0, double *G1, double *G2, double *combo, int n, double a, double c, double A) +{ /* Blend the two models using a (0-1), and c (>=0), normalize, then scale to given amplitude A */ + int i; + double one_minus_a, min = DBL_MAX, max = -DBL_MAX, scale; + one_minus_a = 1.0 - a; + for (i = 0; i < n; i++) { + combo[i] = a * G1[i] + one_minus_a * (c * G2[i] - G0[i]); /* a blend */ + if (combo[i] < min) min = combo[i]; + if (combo[i] > max) max = combo[i]; + } + scale = A / (max - min); + for (i = 0; i < n; i++) combo[i] *= scale; +} + +GMT_LOCAL int FZ_solution (struct GMT_CTRL *GMT, double *dist, double *data, double d0, double *model, int n, double *par) +{ /* LS solution for par[0] + par[1]*(dist-d0) + par[2] * model, ignoring NaNs */ + int i, m; + double d, N[9]; + + gmt_M_memset (N, 9, double); /* The 3x3 normal equation matrix */ + gmt_M_memset (par, 3, double); /* The 3x1 solution vector */ + for (i = m = 0; i < n; i++) { /* Build up N */ + if (gmt_M_is_dnan (data[i])) continue; /* Skip data points that are NaN */ + d = dist[i] - d0; + N[1] += d; + N[2] += model[i]; + N[4] += d * d; + N[5] += d * model[i]; + N[8] += model[i] * model[i]; + par[0] += data[i]; + par[1] += d * data[i]; + par[2] += data[i] * model[i]; + m++; + } + /* Finalize N for this 3x3 problem */ + N[0] = (double)m; N[3] = N[1]; N[6] = N[2]; N[7] = N[5]; + return (gmt_gaussjordan (GMT, N, 3U, par)); /* Return solution via par */ +} + +GMT_LOCAL double FZ_get_variance (double *z, int n) +{ /* Compute sum of squares, skipping NaNs */ + int i; + double var = 0.0; + for (i = 0; i < n; i++) if (!gmt_M_is_dnan (z[i])) var += z[i] * z[i]; + return (var); +} + +GMT_LOCAL void FZ_residuals (double *dist, double *data, double d0, double *model, double *residual, int n, double par[]) +{ /* Return residuals after removing best-fitting FZ shape */ + int i; + for (i = 0; i < n; i++) residual[i] = data[i] - (par[0] + par[1] * (dist[i] - d0) + par[2] * model[i]); +} + +GMT_LOCAL void FZ_trend (double *x, double *y, int n, double *intercept, double *slope, int remove) +{ /* Fits a LS line, but ignore points with NaNs in y[] */ + double sum_x, sum_xx, sum_y, sum_xy, xx, dx = 0.0; + int i, m, equidistant = 0; + + sum_x = sum_xx = sum_y = sum_xy = 0.0; + if (x == NULL) { /* If there are no x-values we assume dx is passed via intercept */ + equidistant = 1; + dx = *intercept; + } + for (i = m = 0; i < n; i++) { + if (gmt_M_is_dnan (y[i])) continue; + xx = (equidistant) ? dx*i : x[i]; + sum_x += xx; + sum_xx += xx*xx; + sum_y += y[i]; + sum_xy += xx*y[i]; + m++; + } + + *intercept = (sum_y*sum_xx - sum_x*sum_xy) / (m*sum_xx - sum_x*sum_x); + *slope = (m*sum_xy - sum_x*sum_y) / (m*sum_xx - sum_x*sum_x); + + if (remove) { + for (i = 0; i < n; i++) { + xx = (equidistant) ? dx*i : x[i]; + y[i] -= (*intercept + (*slope) * xx); + } + } +} + +GMT_LOCAL int FZ_fit_model (struct GMT_CTRL *GMT, double *d, double *vgg, int n, double corridor, double *width, int n_widths, double *asym, int n_asym, double *comp, int n_comp, double *results, PFV *FZshape) +{ + /* d = distance along crossing profile in km, with d = 0 the nominal FZ location given by digitized line. + * vgg = observed (resampled) VGG along crossing profile, possibly with NaNs at end. + * n = number of points in the profile (including any NaNs) + * corridor = half-width of the central corridor in which we try to adjust the FZ location + * widths = array with signal widths to try + * asym = array with asymmetry parameters to try + * comp = array with compression parameters to try + * results = array with parameters determined below + * + * Take observed VGG cross-profile, detrend it, and then try to fit + * a theoretical profile by shifting FZ position horizontally and + * adjusting the width of the signal. We do this for a blend of two models, and + * keep track of the best blend overall. In the end we return which + * model that fit best, its variance reduction (in %), and the parameters. */ + + int col0, w, m, ic, row, way, n_sing = 0, n_fits = 0, got_trough; + double *d_vgg = NULL, *res = NULL, *predicted_vgg = NULL, *vgg_comp[N_SHAPES] = {NULL, NULL, NULL}; + double min_var_b, min_var_t, var_model, intercept, slope, var_data, F, par[3]; + + /* The algorithms used below anticipate that vgg may have NaNs and thus skip those */ + + /* First find a LS trend and remove it from vgg */ + + d_vgg = gmt_M_memory (GMT, NULL, n, double); + res = gmt_M_memory (GMT, NULL, n, double); + for (m = 0; m < N_SHAPES; m++) vgg_comp[m] = gmt_M_memory (GMT, NULL, n, double); + predicted_vgg = gmt_M_memory (GMT, NULL, n, double); + gmt_M_memcpy (d_vgg, vgg, n, double); /* Make copy of vgg */ + FZ_trend (d, d_vgg, n, &intercept, &slope, 1); /* Find and remove linear trend just for data variance calculation */ + /* So trend = d * slope + intercept; the shift of FZ location does not change this calculation (i.e. d is original d) */ + + var_data = FZ_get_variance (d_vgg, n); /* Compute sum of squares for the detrended data */ + min_var_b = min_var_t = DBL_MAX; + got_trough = (gmt_M_is_zero (asym[0])); + for (way = -1; way < 2; way += 2) { /* Must use normal and reversed model since we dont know which side is young (-1 means old is to the left or negative d) */ + for (col0 = 0; col0 < n; col0++) { /* Search for a better fit to FZ location within +- corr km of digitized location */ + if (fabs (d[col0]) > corridor) continue; /* Outside central corridor where we allow relocation of FZ position */ + for (w = 0; w < n_widths; w++) { /* Search for best shape width from 20 to 100 km */ + for (m = 0; m < N_SHAPES; m++) FZshape[m] (d, n, d[col0], width[w], way, vgg_comp[m]); + for (ic = 0; ic < n_comp; ic++) { /* Search for best compression factor */ + for (row = 0; row < n_asym; row++) { /* Search for optimal asymmetry parameter asym */ + n_fits++; + FZ_blendmodel (vgg_comp[FZ_G0], vgg_comp[FZ_G1], vgg_comp[FZ_G2], predicted_vgg, n, asym[row], comp[ic], 1.0); /* a blend, with unit amplitude */ + if (FZ_solution (GMT, d, vgg, d[col0], predicted_vgg, n, par)) { /* LS solution for trend + scaled shape */ + n_sing++; + continue; /* Return 1 if singular */ + } + if (par[2] < 0.0) continue; /* Do not consider negative amplitudes since we have way to handle reversals */ + FZ_residuals (d, vgg, d[col0], predicted_vgg, res, n, par); /* Return residuals after removing best-fitting FZ shape */ + var_model = FZ_get_variance (res, n); /* Compute sum of squares */ + if (var_model < min_var_b) { /* A better fit was obtained, update parameters */ + min_var_b = var_model; + results[BEST_MODEL_B] = asym[row]; + results[BEST_WAY_B] = (double)way; + results[BEST_FZLOC_B] = d[col0]; + results[BEST_WIDTH_B] = width[w]; + results[BEST_FLANK_B] = comp[ic]; + results[BEST_INTER_B] = par[0]; + results[BEST_SLOPE_B] = par[1]; + results[BEST_AMPLT_B] = par[2]; + } + if (got_trough && row == 0 && var_model < min_var_t) { /* Keep separate tabs of best trough (t = 0) model */ + min_var_t = var_model; + results[BEST_FZLOC_T] = d[col0]; + results[BEST_WIDTH_T] = width[w]; + results[BEST_FLANK_T] = comp[ic]; + results[BEST_INTER_T] = par[0]; + results[BEST_SLOPE_T] = par[1]; + results[BEST_AMPLT_T] = par[2]; + } + } + } + } + } + } + F = ((var_data - min_var_b) / 4) / (min_var_b / (n - 4)); /* Compute F for best model, assuming nu = 5-1 = 4 */ + results[BEST_VARMD_B] = 100.0 * (var_data - min_var_b) / var_data; /* Variance reduction in % */ + results[BEST_FSTAT_B] = F; + if (got_trough) { /* Same results for a pure through model */ + F = ((var_data - min_var_t) / 3) / (min_var_t / (n - 3)); /* Compute F for best trough model, assuming nu = 4-1 = 3 */ + results[BEST_VARMD_T] = 100.0 * (var_data - min_var_t) / var_data; /* Variance reduction in % */ + results[BEST_FSTAT_T] = F; + } + else { /* Never requested a pure through model */ + for (w = BEST_FZLOC_T; w <= BEST_FSTAT_T; w++) results[w] = GMT->session.d_NaN; + } + gmt_M_free (GMT, d_vgg); + gmt_M_free (GMT, res); + gmt_M_free (GMT, predicted_vgg); + for (m = 0; m < N_SHAPES; m++) gmt_M_free (GMT, vgg_comp[m]); + return ((int)irint (100.0 * n_sing / n_fits)); /* Return percentage of singular solutions as a measure of trouble */ +} + +GMT_LOCAL void FZ_get_envelope (struct GMT_CTRL *GMT, double *pd, double *px, double *py, double *pz, int np, double *best_loc, int k, double *results) +{ /* Find the lon/lat of the points +/- 1-sigma from the FZ-crossing */ + int il, ir; + double sigma3, pe[3], threshold; + + /* First do data estimates. Here, pz[k] is the trough */ + threshold = 0.5 * pz[k]; /* Find where pz is first >= threshold on either side of k */ + for (il = k - 1; il >= 0 && pz[il] < threshold; il--); + results[BEST_XD_1] = (il == -1) ? GMT->session.d_NaN : px[il]; + results[BEST_YD_1] = (il == -1) ? GMT->session.d_NaN : py[il]; + results[BEST_ZD_1] = (il == -1) ? GMT->session.d_NaN : pz[il]; + results[BEST_XD_M] = px[k]; + results[BEST_YD_M] = py[k]; + results[BEST_ZD_M] = pz[k]; + for (ir = k + 1; ir < np && pz[ir] < threshold; ir++); + results[BEST_XD_2] = (ir == np) ? GMT->session.d_NaN : px[ir]; + results[BEST_YD_2] = (ir == np) ? GMT->session.d_NaN : py[ir]; + results[BEST_ZD_2] = (ir == np) ? GMT->session.d_NaN : pz[ir]; + results[BEST_WIDTH_D] = (il == -1 || ir == np) ? GMT->session.d_NaN : pd[ir] - pd[il]; + results[BEST_AMPLT_D] = 2.0 * (0.5 * (results[BEST_ZD_2] + results[BEST_ZD_1]) - results[BEST_ZD_M]); /* Twice since we used 0.5 as threshold */ + /* Then do trough model estimates */ + sigma3 = results[BEST_WIDTH_T]/2.0; /* Treat FZ width a fullwidth = 6sigma */ + pe[0] = best_loc[LOC_TROUGH] - sigma3; pe[1] = best_loc[LOC_TROUGH]; pe[2] = best_loc[LOC_TROUGH] + sigma3; + gmt_intpol (GMT, pd, px, NULL, np, 3, pe, &results[BEST_XT_1], 0.0, 1); /* Returns three longitudes starting at BEST_XT_1 location */ + gmt_intpol (GMT, pd, py, NULL, np, 3, pe, &results[BEST_YT_1], 0.0, 1); /* Returns three latitudes starting at BEST_YT_1 location */ + gmt_intpol (GMT, pd, pz, NULL, np, 3, pe, &results[BEST_ZT_1], 0.0, 1); /* Returns three data values starting at BEST_ZT_1 location */ + /* Then do blend model (at trough) estimates */ + sigma3 = results[BEST_WIDTH_B]/2.0; /* Treat FZ width a fullwidth = 6sigma */ + pe[0] = best_loc[LOC_BLEND_T] - sigma3; pe[1] = best_loc[LOC_BLEND_T]; pe[2] = best_loc[LOC_BLEND_T] + sigma3; + gmt_intpol (GMT, pd, px, NULL, np, 3, pe, &results[BEST_XB_1], 0.0, 1); /* Returns three longitudes starting at BEST_XB_1 location */ + gmt_intpol (GMT, pd, py, NULL, np, 3, pe, &results[BEST_YB_1], 0.0, 1); /* Returns three latitudes starting at BEST_YB_1 location */ + gmt_intpol (GMT, pd, pz, NULL, np, 3, pe, &results[BEST_ZB_1], 0.0, 1); /* Returns three data values starting at BEST_ZB_1 location */ + /* Last do blend model estimates for maximum slope location */ + sigma3 = results[BEST_WIDTH_B]/2.0; /* Treat FZ width a fullwidth = 6sigma */ + pe[0] = best_loc[LOC_BLEND_E] - sigma3; pe[1] = best_loc[LOC_BLEND_E]; pe[2] = best_loc[LOC_BLEND_E] + sigma3; + gmt_intpol (GMT, pd, px, NULL, np, 3, pe, &results[BEST_XE_1], 0.0, 1); /* Returns three longitudes starting at BEST_XE_1 location */ + gmt_intpol (GMT, pd, py, NULL, np, 3, pe, &results[BEST_YE_1], 0.0, 1); /* Returns three latitudes starting at BEST_YE_1 location */ + gmt_intpol (GMT, pd, pz, NULL, np, 3, pe, &results[BEST_ZE_1], 0.0, 1); /* Returns three data values starting at BEST_ZE_1 location */ +} + +GMT_LOCAL int FZ_trough_location (struct GMT_CTRL *GMT, double *dist, double *vgg_obs, double *vgg_blend, int np, double corr_width, double locations[]) +{ /* Return minimum locations of observed and best-blend profiles */ + int i, o_min = -1, b_min = -1; + double vo_min = DBL_MAX, vb_min = DBL_MAX; + for (i = 0; i < np; i++) { + if (fabs(dist[i]) > corr_width) continue; + if (!gmt_M_is_dnan (vgg_obs[i]) && vgg_obs[i] < vo_min) { + vo_min = vgg_obs[i]; + o_min = i; + } + if (!gmt_M_is_dnan (vgg_blend[i]) && vgg_blend[i] < vb_min) { + vb_min = vgg_blend[i]; + b_min = i; + } + } + /* Return the location, or NaN if everything is NaN */ + locations[LOC_DATA] = (o_min == -1) ? GMT->session.d_NaN : dist[o_min]; + locations[LOC_BLEND_T] = (b_min == -1) ? GMT->session.d_NaN : dist[b_min]; + return (o_min); +} + +GMT_LOCAL void FZ_get_ages (struct GMT_CTRL *GMT, double *dist, double *age, int np, double d0, double A[]) +{ /* Return the age on left and right side of FZ. FZ is a distance d0 */ + /* LS solution for par[0] + par[1]*(dist-d0) + par[2] * H(dist-d0), ignoring NaNs and points within DEF_FZ_GAP km of origin d0. + * We skip this gap since ages often spline from one side to the other and we seek to avoid fitting this ramp */ + int i, m; + double d, H, N[9], par[3]; + + gmt_M_memset (N, 9, double); /* The 3x3 normal equation matrix */ + gmt_M_memset (par, 3, double); /* The 3x1 solution vector */ + for (i = m = 0; i < np; i++) { /* Build up N */ + if (gmt_M_is_dnan (age[i])) continue; /* Skip data points that are NaN */ + d = dist[i] - d0; /* Distance relative to origin d0 */ + if (fabs (d) < DEF_FZ_GAP) continue; /* Skip data points within DEF_FZ_GAP km of origin */ + H = (d > 0.0) ? 1.0 : 0.0; /* Heaviside step function (d cannot be 0.0 as per test above) */ + N[1] += d; + N[2] += H; + N[4] += d * d; + N[5] += d * H; + N[8] += H * H; + par[0] += age[i]; + par[1] += d * age[i]; + par[2] += age[i] * H; + m++; + } + if (m < 3) { /* Nothing to do, return NaNs */ + A[0] = A[1] = GMT->session.d_NaN; + return; + } + /* Finalize N for this 3x3 problem */ + N[0] = (double)m; N[3] = N[1]; N[6] = N[2]; N[7] = N[5]; + (void) gmt_gaussjordan (GMT, N, 3U, par); + /* In evaluating model for d = 0 the slope does not contribute */ + A[0] = par[0]; /* Age just left of FZ */ + A[1] = A[0] + par[2]; /* Age just right of FZ */ +} + +static void *New_Ctrl (struct GMT_CTRL *GMT) { /* Allocate and initialize a new control structure */ + struct FZMODELER_CTRL *C; + + C = gmt_M_memory (GMT, NULL, 1, struct FZMODELER_CTRL); + + /* Initialize values whose defaults are not 0/false/NULL */ + C->D.corr_width = DEF_D_WIDTH; /* Only use center corridor */ + C->I.profile = -1; /* Use all profiles from current FZ */ + C->C.min = DEF_L_MIN; /* Min compression */ + C->C.max = DEF_L_MAX; /* Max compression */ + C->C.inc = DEF_L_INC; /* Sampling interval for FZ compression */ + C->A.min = DEF_M_MIN; /* Min asymmetry = Atlantic signal */ + C->A.max = DEF_M_MAX; /* Max asymmetry = Pacific signal */ + C->A.inc = DEF_M_INC; /* Sampling interval for FZ blend */ + C->T.prefix = strdup ("fztrack"); /* Default file prefix */ + C->W.min = DEF_W_MIN; /* Narrowest FZ shape width to fit */ + C->W.max = DEF_W_MAX; /* Widest FZ shape width to fit */ + C->W.inc = DEF_W_INC; /* Sampling interval for FZ shape width */ + return (C); +} + +static void Free_Ctrl (struct GMT_CTRL *GMT, struct FZMODELER_CTRL *C) { /* Deallocate control structure */ + if (!C) return; + if (C->In.file) free (C->In.file); + if (C->F.file) free (C->F.file); + if (C->T.prefix) free (C->T.prefix); + gmt_M_free (GMT, C); +} + +static int usage (struct GMTAPI_CTRL *API, int level) { + const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE); + if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR); + GMT_Usage (API, 0, "usage: %s -F [-C//] " + "[-A//] [-D] [-I[/]] " + "-S[b|c]] [-T] [%s] [-W//] " + "%s] [%s] [%s]\n", name, GMT_V_OPT, GMT_colon_OPT, GMT_b_OPT, GMT_i_OPT); + + if (level == GMT_SYNOPSIS) return (GMT_MODULE_SYNOPSIS); + + GMT_Message (API, GMT_TIME_NONE, " REQUIRED ARGUMENTS:\n"); + GMT_Usage (API, 1, "\n"); + GMT_Usage (API, -2, " is a multi-segment file with (lon,lat,dist,az,data,nn,age) in the first " + "7 columns. It is obtained via grdtrack -C based on the original track lines."); + GMT_Usage (API, 1, "\n-F"); + GMT_Usage (API, -2, " is the file with resampled track lines from grdtrack -D."); + + GMT_Message (API, GMT_TIME_NONE, "\n OPTIONAL ARGUMENTS:\n"); + + GMT_Usage (API, 1, "\n-A//"); + GMT_Usage (API, -2, "Specify how FZ blend modeling between symmetric and asymmetric parts is to be done:"); + GMT_Usage (API, 3, "%s : Minimum asymmetry value [%g].", GMT_LINE_BULLET, DEF_M_MIN); + GMT_Usage (API, 3, "%s : Maximum asymmetry value [%g].", GMT_LINE_BULLET, DEF_M_MAX); + GMT_Usage (API, 3, "%s : Increment used for blend search [%g].", GMT_LINE_BULLET, DEF_M_INC); + GMT_Usage (API, -2, "To only use a single asymmetry value, only give the argument."); + GMT_Usage (API, 1, "\n-C//]"); + GMT_Usage (API, -2, "Specify how FZ compression modeling is to be done:"); + GMT_Usage (API, 3, "%s : Minimum compression value [%g].", GMT_LINE_BULLET, DEF_L_MIN); + GMT_Usage (API, 3, "%s : Maximum compression value [%g].", GMT_LINE_BULLET, DEF_L_MAX); + GMT_Usage (API, 3, "%s : Increment used for compression search [%g].", GMT_LINE_BULLET, DEF_L_INC); + GMT_Usage (API, -2, "To only use a single compression value, only give the argument."); + GMT_Usage (API, 1, "\n-D"); + GMT_Usage (API, -2, "Sets width (in km) of central cross-profile wherein FZ shifts may be sought [%g].", DEF_D_WIDTH); + GMT_Usage (API, 1, "\n-I[/]"); + GMT_Usage (API, -2, "Specify a particular id (first FZ is 0) to analyze " + "[Default analyzes the cross-profiles of all FZs]. " + "Optionally, append the id of a particular profile in that FZ."); + GMT_Usage (API, 1, "\n-S[b|c]"); + GMT_Usage (API, -2, "Write out a parameter file with settings needed for Bourne scripts [Default, or append b]. " + "Append c to use csh/tcsh syntax instead."); + GMT_Usage (API, 1, "\n-T"); + GMT_Usage (API, -2, "Set file prefix for all output files [fztrack]."); + GMT_Option (API, "V"); + GMT_Usage (API, 1, "\n-W//"); + GMT_Usage (API, -2, "Specify parameters that control how FZ width is determined:"); + GMT_Usage (API, 3, "%s : Minimum FZ signal width (in km) for nonlinear width search [%g].", GMT_LINE_BULLET, DEF_W_MIN); + GMT_Usage (API, 3, "%s : Maximum FZ signal width (in km) for nonlinear width search [%g].", GMT_LINE_BULLET, DEF_W_MAX); + GMT_Usage (API, 3, "%s : Increment (in km) used for width search [%g].", GMT_LINE_BULLET, DEF_W_INC); + GMT_Option (API, ":,b7i,."); + + return (GMT_MODULE_USAGE); +} + +static int parse (struct GMTAPI_CTRL *API, struct FZMODELER_CTRL *Ctrl, struct GMT_OPTION *options) { + + /* This parses the options provided to grdsample and sets parameters in CTRL. + * Any GMT common options will override values set previously by other commands. + * It also replaces any file names specified as input or output with the data ID + * returned when registering these sources/destinations with the API. + */ + + int j, n_files = 0, n_errors = 0; + struct GMT_OPTION *opt = NULL; + struct GMT_CTRL *GMT = API->GMT; + char ta[GMT_LEN64], tb[GMT_LEN64], tc[GMT_LEN64]; + + for (opt = options; opt; opt = opt->next) { + switch (opt->option) { + + case '<': /* Skip input files */ + Ctrl->In.active = true; + if (n_files == 0) Ctrl->In.file = strdup (opt->arg); + n_files++; + break; + + /* Processes program-specific parameters */ + + case 'A': + n_errors += gmt_M_repeated_module_option (API, Ctrl->D.active); + j = sscanf (opt->arg, "%[^/]/%[^/]/%s", ta, tb, tc); + Ctrl->A.min = atof (ta); + Ctrl->A.max = atof (tb); + Ctrl->A.inc = atof (tc); + if (j == 1) { /* Only gave a specific asymmetry value */ + Ctrl->A.max = Ctrl->A.min; + Ctrl->A.inc = 1.0; + } + break; + case 'C': + n_errors += gmt_M_repeated_module_option (API, Ctrl->C.active); + j = sscanf (opt->arg, "%[^/]/%[^/]/%s", ta, tb, tc); + Ctrl->C.min = atof (ta); + Ctrl->C.max = atof (tb); + Ctrl->C.inc = atof (tc); + if (j == 1) { /* Only gave a specific compression value */ + Ctrl->C.max = Ctrl->C.min; + Ctrl->C.inc = 1.0; + } + break; + case 'D': + n_errors += gmt_M_repeated_module_option (API, Ctrl->D.active); + Ctrl->D.corr_width = atof (opt->arg); + break; + case 'F': + n_errors += gmt_M_repeated_module_option (API, Ctrl->F.active); + Ctrl->F.file = strdup (opt->arg); + break; + case 'I': /* Just pick a single profile for analysis */ + n_errors += gmt_M_repeated_module_option (API, Ctrl->I.active); + j = sscanf (opt->arg, "%[^/]/%s", ta, tb); + if (j == 2) { /* Got both FZ and profile numbers */ + Ctrl->I.fz = atoi (ta); + Ctrl->I.profile = atoi (tb); + } + else + Ctrl->I.fz = atoi (opt->arg); + break; + case 'S': + n_errors += gmt_M_repeated_module_option (API, Ctrl->S.active); + if (opt->arg[0] == 'c') Ctrl->S.mode = 1; + break; + case 'T': + n_errors += gmt_M_repeated_module_option (API, Ctrl->T.active); + free (Ctrl->T.prefix); + Ctrl->T.prefix = strdup (opt->arg); + break; + case 'W': + n_errors += gmt_M_repeated_module_option (API, Ctrl->W.active); + sscanf (opt->arg, "%[^/]/%[^/]/%s", ta, tb, tc); + Ctrl->W.min = atof (ta); + Ctrl->W.max = atof (tb); + Ctrl->W.inc = atof (tc); + break; + + default: /* Report bad options */ + n_errors += gmt_default_error (GMT, opt->option); + break; + } + } + + if (GMT->common.b.active[GMT_IN] && GMT->common.b.ncol[GMT_IN] == 0) GMT->common.b.ncol[GMT_IN] = 7; + n_errors += gmt_M_check_condition (GMT, !Ctrl->In.active, "GMT SYNTAX ERROR: No input file specified\n"); + n_errors += gmt_M_check_condition (GMT, n_files > 1, "GMT SYNTAX ERROR: Only specify one input file\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->C.active && Ctrl->C.min < 0.0, "GMT SYNTAX ERROR -C: Values must be >= 0 (typically in 0-1 range)\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->A.active && (Ctrl->A.min < 0.0 || Ctrl->A.max > 1.0), "GMT SYNTAX ERROR -A: Values must be 0 <= m <= 1.\n"); + n_errors += gmt_M_check_condition (GMT, !Ctrl->F.file, "GMT SYNTAX ERROR -F: Must specify input trace file.\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->D.corr_width <= 0.0, "GMT SYNTAX ERROR -D: Corridor width must be positive.\n"); + n_errors += gmt_M_check_condition (GMT, GMT->common.b.active[GMT_IN] && GMT->current.setting.io_header[GMT_IN], "GMT SYNTAX ERROR. Binary input data cannot have header -h.\n"); + n_errors += gmt_M_check_condition (GMT, GMT->common.b.active[GMT_IN] && GMT->common.b.ncol[GMT_IN] < 7, "GMT SYNTAX ERROR. Binary input data (-bi) must have at least 7 columns.\n"); + + return (n_errors ? GMT_PARSE_ERROR : GMT_NOERROR); +} + +#define bailout(code) {gmt_M_free_options (mode); return (code);} +#define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); bailout (code);} + +EXTERN_MSC int GMT_fzanalyzer (void *V_API, int mode, void *args) { + int error = 0, k, start, stop, left, right; + int n_sing, way, m; + uint64_t n_FZ_widths, n_FZ_asym, n_FZ_comp, np_cross, n_half_cross, ii; + uint64_t fz, ku, row, col, xseg; + + char buffer[BUFSIZ] = {""}, run_cmd[BUFSIZ] = {""}, add[BUFSIZ] = {""}, *cmd = NULL, *file = NULL; + + double fz_inc, corridor_half_width, cross_length, threshold, results[N_RESULTS], best_loc[4]; + double *FZ_width = NULL, *FZ_asym = NULL, *FZ_comp = NULL, ages[2], *comp[N_SHAPES]; + + PFV FZshape[N_SHAPES] = {NULL, NULL, NULL}; + + struct GMT_OPTION *options = NULL; + struct FZMODELER_CTRL *Ctrl = NULL; + struct GMT_DATASET *Fin = NULL, *Xin = NULL; + struct GMT_DATATABLE *F = NULL, *X = NULL; + struct GMT_DATASEGMENT *S = NULL; + struct GMT_CTRL *GMT = NULL, *GMT_cpy = NULL; + struct GMTAPI_CTRL *API = gmt_get_api_ptr (V_API); /* Cast from void to GMTAPI_CTRL pointer */ + + /*----------------------- Standard module initialization and parsing ----------------------*/ + + if (API == NULL) return (GMT_NOT_A_SESSION); + if (mode == GMT_MODULE_PURPOSE) return (usage (API, GMT_MODULE_PURPOSE)); /* Return the purpose of program */ + options = GMT_Create_Options (API, mode, args); if (API->error) return (API->error); /* Set or get option list */ + + if ((error = gmt_report_usage (API, options, 0, usage)) != GMT_NOERROR) bailout (error); /* Give usage if requested */ + + /* Parse the program-specific arguments */ + + if ((GMT = gmt_init_module (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_KEYS, THIS_MODULE_NEEDS, module_kw, &options, &GMT_cpy)) == NULL) + bailout (API->error); /* Save current state */ + if (GMT_Parse_Common (API, THIS_MODULE_OPTIONS, options)) Return (API->error); + Ctrl = New_Ctrl (GMT); /* Allocate and initialize a new control structure */ + if ((error = parse (API, Ctrl, options))) Return (error); + + /*---------------------------- This is the fzanalyzer main code ----------------------------*/ + + /* We know which columns are geographical */ + GMT->current.io.col_type[GMT_IN][GMT_X] = GMT->current.io.col_type[GMT_OUT][GMT_X] = GMT_IS_LON; + GMT->current.io.col_type[GMT_IN][GMT_Y] = GMT->current.io.col_type[GMT_OUT][GMT_Y] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XDL] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YDL] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XD0] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YD0] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XDR] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YDR] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XTL] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YTL] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XT0] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YT0] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XTR] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YTR] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XBL] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YBL] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XB0] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YB0] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XBR] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YBR] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XEL] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YEL] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XE0] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YE0] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][POS_XER] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][POS_YER] = GMT_IS_LAT; + + /* Assign pointer array to the three basic shapes */ + FZshape[FZ_G0] = FZ_gaussian0; FZshape[FZ_G1] = FZ_gaussian1; FZshape[FZ_G2] = FZ_gaussian2; + + /* Read in the resampled FZ track lines */ + + if (GMT_Init_IO (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_IN, GMT_ADD_DEFAULT, 0, options) != GMT_NOERROR) { /* Establishes data input */ + Return (API->error); + } + if ((error = GMT_Begin_IO (API, GMT_IS_DATASET, GMT_IN, GMT_HEADER_ON))) Return (error); /* Enables data input and sets access mode */ + if ((Fin = GMT_Read_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_READ_NORMAL, NULL, Ctrl->F.file, NULL)) == NULL) Return ((error = GMT_DATA_READ_ERROR)); + F = Fin->table[0]; /* Since there is only one table */ + if (F->segment[0]->n_columns < N_REQUIRED_COLS) { /* Trouble */ + GMT_Message (API, GMT_TIME_NONE, "GMT SYNTAX ERROR: FZ file %s does not have the %d required columns\n", Ctrl->F.file, N_REQUIRED_COLS); + Return (EXIT_FAILURE); + } + /* Read in the cross-profiles */ + + if ((Xin = GMT_Read_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_READ_NORMAL, NULL, Ctrl->In.file, NULL)) == NULL) Return ((error = GMT_DATA_READ_ERROR)); + X = Xin->table[0]; /* Since there is only one table */ + if (X->segment[0]->n_columns < N_REQUIRED_COLS) { /* Trouble */ + GMT_Message (API, GMT_TIME_NONE, "GMT SYNTAX ERROR: Cross-profile file %s does not have the %d required columns\n", Ctrl->In.file, N_REQUIRED_COLS); + Return (EXIT_FAILURE); + } + + if ((error = GMT_End_IO (API, GMT_IN, 0))) Return (error); /* Disables further data input */ + + /* Set up the array of trial FZ widths based on -W parameters */ + n_FZ_widths = gmt_M_get_n (GMT, Ctrl->W.min, Ctrl->W.max, Ctrl->W.inc, 0); + FZ_width = gmt_M_memory (GMT, NULL, n_FZ_widths, double); + for (col = 0; col < n_FZ_widths; col++) FZ_width[col] = gmt_M_col_to_x (GMT, col, Ctrl->W.min, Ctrl->W.max, Ctrl->W.inc, 0.0, n_FZ_widths); + + /* Set up array of asymmetry values (or 1) based on -A */ + n_FZ_asym = gmt_M_get_n (GMT, Ctrl->A.min, Ctrl->A.max, Ctrl->A.inc, 0); + FZ_asym = gmt_M_memory (GMT, NULL, n_FZ_asym, double); + for (col = 0; col < n_FZ_asym; col++) FZ_asym[col] = gmt_M_col_to_x (GMT, col, Ctrl->A.min, Ctrl->A.max, Ctrl->A.inc, 0.0, n_FZ_asym); + + /* Set up array of compression values (or 1) based on -C */ + n_FZ_comp = gmt_M_get_n (GMT, Ctrl->C.min, Ctrl->C.max, Ctrl->C.inc, 0); + FZ_comp = gmt_M_memory (GMT, NULL, n_FZ_comp, double); + for (col = 0; col < n_FZ_comp; col++) FZ_comp[col] = gmt_M_col_to_x (GMT, col, Ctrl->C.min, Ctrl->C.max, Ctrl->C.inc, 0.0, n_FZ_comp); + + /* Get resampling step size and zone width in degrees */ + + np_cross = X->segment[0]->n_rows; /* Since all cross-profiles have the same length */ + corridor_half_width = 0.5 * Ctrl->D.corr_width; /* Only search for trough within this zone */ + ages[0] = ages[1] = GMT->session.d_NaN; /* So we can report NaN if there are no ages */ + + for (m = 0; m < N_SHAPES; m++) comp[m] = gmt_M_memory (GMT, NULL, np_cross, double); /* Will hold normalized G0, G1, and G2 model predictions */ + + cmd = GMT_Create_Cmd (API,options); + sprintf (run_cmd, "# %s %s", GMT->init.module_name, cmd); /* Build command line argument string */ + gmt_M_free (GMT, cmd); + + if (GMT_Init_IO (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_OUT, GMT_ADD_DEFAULT, 0, options) != GMT_NOERROR) { /* Establishes data output */ + Return (API->error); + } + if ((error = GMT_Begin_IO (API, GMT_IS_DATASET, GMT_OUT, GMT_HEADER_ON))) Return (error); /* Enables data output and sets access mode */ + + GMT->current.setting.io_header[GMT_OUT] = true; /* To ensure writing of headers */ + + /* Extend the dataset of cross profiles to hold more columns */ + gmt_adjust_dataset (GMT, Xin, N_CROSS_COLS); /* Same table length as X, but with N_CROSS_COLS columns */ + for (ku = 0; ku < X->n_headers; ku++) free (X->header[ku]); + if (X->n_headers) gmt_M_free (GMT, X->header); + X->n_headers = 3; + X->header = gmt_M_memory (GMT, NULL, X->n_headers, char *); + X->header[0] = strdup ("# Equidistant cross-profiles normal to each FZ trace"); + X->header[1] = strdup (run_cmd); + strcpy (buffer, "# lon\t\tlat\tdist\taz\tdata\tage\tdist2fz\tTmodel\tBmodel"); + X->header[2] = strdup (buffer); + + /* To hold the results per FZ trace. Same number of points as the resampled trace in FZ */ + gmt_adjust_dataset (GMT, Fin, N_FZ_ANALYSIS_COLS); /* Same table length as F, but with N_FZ_ANALYSIS_COLS columns */ + for (ku = 0; ku < F->n_headers; ku++) free (F->header[ku]); + if (F->n_headers) gmt_M_free (GMT, F->header); + F->n_headers = 3; + F->header = gmt_M_memory (GMT, NULL, F->n_headers, char *); + F->header[0] = strdup ("# Analyzed FZ traces"); + F->header[1] = strdup (run_cmd); + F->header[2] = strdup ("# XR\t\tYR\tDR\tAR\tZR\tTL\tTR\tSD\tST\tSB\tSE\tBL\tOR\tWD\tWT\tWB\tAD\tAT\tAB\tUT\tUB\tVT\tVB\tFT\tFB\t" \ + "XDL\tXD0\tXDR\tYDL\tYD0\tYDR\tZDL\tZD0\tZDR\tXTL\tXT0\tXTR\tYTL\tYT0\tYTR\tZTL\tZT0\tZTR\tXBL\tXB0\tXBR\tYBL\t" \ + "YB0\tYBR\tZBL\tZB0\tZBR\tXEL\tXE0\tXER\tYEL\tYE0\tYER\tZEL\tZE0\tZER"); + + n_half_cross = (np_cross - 1) / 2; /* Number of points in a cross-profile on either side of the FZ (center point) */ + threshold = -0.1 * (X->segment[0]->data[XPOS_D][1] - X->segment[0]->data[XPOS_D][0]); /* 10% threshold lets us skip through tiny negative FZ dist steps due to round-off */ + cross_length = X->segment[0]->data[XPOS_D][np_cross-1] - X->segment[0]->data[XPOS_D][0]; /* Length of a cross-profile */ + + for (fz = xseg = 0; fz < F->n_segments; fz++) { /* For each FZ segment */ + + if (Ctrl->I.active && fz != (uint64_t)Ctrl->I.fz) { /* Skip this FZ */ + struct GMT_DATASEGMENT_HIDDEN *SH = gmt_get_DS_hidden (F->segment[fz]); + SH->mode = GMT_WRITE_SKIP; /* Ignore on output */ + xseg += F->segment[fz]->n_rows; /* Must wind past all the cross-profiles for the skipped FZ */ + continue; + } + + for (row = 0; row < F->segment[fz]->n_rows; row++, xseg++) { /* Process all the cross-profiles for this FZ */ + S = X->segment[xseg]; /* Current cross-profile */ + if (Ctrl->I.active && Ctrl->I.profile >= 0 && row != (uint64_t)Ctrl->I.profile) { /* Skip this profile */ + continue; + } + GMT_Report (API, GMT_MSG_NORMAL, "Process FZ cross-profile %s\r", S->label); + + /* Must determine if parts of the crossection is closer to a neighbor FZ; we then truncate the data. */ + start = stop = -1; + for (ku = 0, left = n_half_cross - 1, right = n_half_cross + 1; ku < n_half_cross; ku++, right++, left--) { /* March outwards from the center point which should have the smallest pn */ + if (start == -1 && !gmt_M_is_dnan (S->data[XPOS_S][left]) && (fz_inc = S->data[XPOS_S][left] - S->data[XPOS_S][left+1]) < threshold) start = left + 1; + if (stop == -1 && !gmt_M_is_dnan (S->data[XPOS_S][right]) && (fz_inc = S->data[XPOS_S][right] - S->data[XPOS_S][right-1]) < threshold) stop = right - 1; + } + /* If neighbor FZs are too close (distances start to decrease) we find the last point with an + * monotonic increase in FZ distance on either side. If there is no neighbor then start and/or + * stop will remain at -1. */ + if (start == -1) start = 0; + if (stop == -1) stop = np_cross - 1; + /* Now set the sampled grid profile to NaN if too close to a neighbor FZ */ + for (k = 0; k < start; k++) S->data[XPOS_Z][k] = GMT->session.d_NaN; + for (k = np_cross-1; k > stop; k--) S->data[XPOS_Z][k] = GMT->session.d_NaN; + /* It is now possible that the beginning and end of the cross profile will have NaNs */ + + /* Find best fit shift, width, and amplitude plus various quality factors */ + + gmt_M_memset (results, N_RESULTS, double); + n_sing = FZ_fit_model (GMT, S->data[XPOS_D], S->data[XPOS_Z], np_cross, corridor_half_width, FZ_width, n_FZ_widths, FZ_asym, n_FZ_asym, FZ_comp, n_FZ_comp, results, FZshape); + if (n_sing) GMT_Report (API, GMT_MSG_NORMAL, "Warning: Cross profile %s generated %ld %% singular solutions\n", S->label, n_sing); + + /* Evaluate the best model predictions */ + FZshape[FZ_G0] (S->data[XPOS_D], np_cross, results[BEST_FZLOC_T], results[BEST_WIDTH_T], 0, comp[FZ_G0]); /* Just need G0 & G2 for building trough model (asymmetry = 0) */ + FZshape[FZ_G2] (S->data[XPOS_D], np_cross, results[BEST_FZLOC_T], results[BEST_WIDTH_T], 0, comp[FZ_G2]); + FZ_blendmodel (comp[FZ_G0], comp[FZ_G1], comp[FZ_G2], S->data[XPOS_T], np_cross, 0.0, results[BEST_FLANK_T], results[BEST_AMPLT_T]); /* Best trough model (T) without the linear trend */ + way = irint (results[BEST_WAY_B]); /* Old side on negative distance (-1) or positive distances (+1) */ + for (m = 0; m < N_SHAPES; m++) FZshape[m] (S->data[XPOS_D], np_cross, results[BEST_FZLOC_B], results[BEST_WIDTH_B], way, comp[m]); /* Evaluate all three shapes given blend parameters */ + FZ_blendmodel (comp[FZ_G0], comp[FZ_G1], comp[FZ_G2], S->data[XPOS_B], np_cross, results[BEST_MODEL_B], results[BEST_FLANK_B], results[BEST_AMPLT_B]); /* Best blend (B) without the linear trend */ + m = FZ_trough_location (GMT, S->data[XPOS_D], S->data[XPOS_Z], S->data[XPOS_B], np_cross, corridor_half_width, best_loc); /* Determine the LOC_DATA and LOC_BLEND_T estimates of FZ location */ + best_loc[LOC_TROUGH] = results[BEST_FZLOC_T]; /* The 2nd best FZ location estimate is from the trough model */ + best_loc[LOC_BLEND_E] = results[BEST_FZLOC_B]; /* The 3rd best FZ location estimate is from the blend model */ + + /* Determine the +/- 1-sigma corridor around the best FZ trace */ + FZ_get_envelope (GMT, S->data[XPOS_D], S->data[XPOS_X], S->data[XPOS_Y], S->data[XPOS_Z], np_cross, best_loc, m, results); + /* Determine ages on left (d < 0) and right (d > 0) sides (if -A) */ + FZ_get_ages (GMT, S->data[XPOS_D], S->data[XPOS_C], np_cross, 0.0, ages); + + /* Copy the results for this cross-profile analysis to the output data set */ + F->segment[fz]->data[POS_TL][row] = ages[0]; /* Crustal age to left of FZ */ + F->segment[fz]->data[POS_TR][row] = ages[1]; /* Crustal age to right of FZ */ + F->segment[fz]->data[POS_SD][row] = S->data[XPOS_D][m]; /* Offset of data trough from digitized FZ location [0] */ + F->segment[fz]->data[POS_ST][row] = results[BEST_FZLOC_T]; /* Offset of model (trough) location from digitized FZ location */ + F->segment[fz]->data[POS_SB][row] = best_loc[LOC_BLEND_T]; /* Offset of model trough (blend) location from digitized FZ location */ + F->segment[fz]->data[POS_SE][row] = results[BEST_FZLOC_B]; /* Offset of model (blend) location from digitized FZ location */ + F->segment[fz]->data[POS_BL][row] = results[BEST_MODEL_B]; /* Best blend value at FZ location */ + F->segment[fz]->data[POS_OR][row] = results[BEST_WAY_B]; + F->segment[fz]->data[POS_WD][row] = results[BEST_WIDTH_D]; /* Best data width at FZ location */ + F->segment[fz]->data[POS_WT][row] = results[BEST_WIDTH_T]; /* Best trough model width at FZ location */ + F->segment[fz]->data[POS_WB][row] = results[BEST_WIDTH_B]; /* Best blend model width at FZ location */ + F->segment[fz]->data[POS_AD][row] = results[BEST_AMPLT_D]; /* Best data amplitude at FZ location */ + F->segment[fz]->data[POS_AT][row] = results[BEST_AMPLT_T]; /* Best trough amplitude at FZ location */ + F->segment[fz]->data[POS_AB][row] = results[BEST_AMPLT_B]; /* Best blend amplitude at FZ location */ + F->segment[fz]->data[POS_UT][row] = results[BEST_FLANK_T]; /* Best trough amplitude at FZ location */ + F->segment[fz]->data[POS_UB][row] = results[BEST_FLANK_B]; /* Best blend amplitude at FZ location */ + F->segment[fz]->data[POS_VT][row] = results[BEST_VARMD_T]; /* Best trough variance reduction at FZ location */ + F->segment[fz]->data[POS_VB][row] = results[BEST_VARMD_B]; /* Best blend variance reduction at FZ location */ + F->segment[fz]->data[POS_FT][row] = results[BEST_FSTAT_T]; /* Best trough F statistic at FZ location */ + F->segment[fz]->data[POS_FB][row] = results[BEST_FSTAT_B]; /* Best blend F statistic at FZ location */ + for (ii = BEST_XD_1, k = POS_XDL; ii <= BEST_ZE_2; ii++, k++) F->segment[fz]->data[k][row] = results[ii]; /* All 9 xyz triplets */ + + /* Update crosstrack profiles with linear trends */ + for (ii = 0; ii < np_cross; ii++) { /* Compute the best model fits as trend + scaled prediction shape. Note the trend requires BEST_FZLOC_B/T */ + S->data[XPOS_T][ii] += (results[BEST_INTER_T] + results[BEST_SLOPE_T] * (S->data[XPOS_D][ii] - results[BEST_FZLOC_T])); + S->data[XPOS_B][ii] += (results[BEST_INTER_B] + results[BEST_SLOPE_B] * (S->data[XPOS_D][ii] - results[BEST_FZLOC_B])); + } + sprintf (add, " mb=%03.2f rv=%+2d OB=%+05.1f WB=%02g UB=%04.2f AB=%05.1f VB=%2.2d FB=%05.1f OT=%+05.1f WT=%02g UT=%04.2f AT=%05.1f VT=%2.2d FT=%05.1f OD=%+05.1f WD=%02g OE=%+05.1f", + results[BEST_MODEL_B], way, best_loc[LOC_BLEND_T], results[BEST_WIDTH_B], results[BEST_FLANK_B], results[BEST_AMPLT_B], + (int)irint(results[BEST_VARMD_B]), results[BEST_FSTAT_B], best_loc[LOC_TROUGH], results[BEST_WIDTH_T], results[BEST_FLANK_T], + results[BEST_AMPLT_T], (int)irint(results[BEST_VARMD_T]), results[BEST_FSTAT_T], best_loc[LOC_DATA], + results[BEST_WIDTH_D], best_loc[LOC_BLEND_E]); + strcpy (buffer, S->header); + free (S->header); + gmt_chop (buffer); + strcat (buffer, add); + S->header = strdup (buffer); + } + } + GMT_Report (API, GMT_MSG_NORMAL, "Process FZ cross-profile %s\n", S->label); + + /* Save crosstrack profiles and models to file */ + sprintf (buffer, "%s_cross.txt", Ctrl->T.prefix); + file = strdup (buffer); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, file, Xin) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + GMT_Destroy_Data (API, &Xin); + free (file); + + /* Store FZ trace analysis */ + sprintf (buffer, "%s_analysis.txt", Ctrl->T.prefix); + file = strdup (buffer); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, file, Fin) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + GMT_Destroy_Data (API, &Fin); + free (file); + + if (Ctrl->S.active) { /* Store parameters */ + FILE *fp = NULL; + char *assign = NULL, *equal = NULL, *shell[2] = {"sh/bash", "[t]cshell"}; + sprintf (buffer, "%s_par.txt", Ctrl->T.prefix); + file = strdup (buffer); + if ((fp = fopen (file, "w")) == NULL) { + GMT_Report (API, GMT_MSG_NORMAL, "Syntax error: Unable to create file %s\n", file); + Return (EXIT_FAILURE); + } + GMT_Report (API, GMT_MSG_NORMAL, "Write modeling parameters script to File %s\n", file); + assign = (Ctrl->S.mode) ? strdup ("set ") : strdup (""); + equal = (Ctrl->S.mode) ? strdup (" = ") : strdup ("="); + fprintf (fp, "%s\n", run_cmd); + fprintf (fp, "# Parameters that may be used by %s scripts\n", shell[Ctrl->S.mode]); + fprintf (fp, "%sCORR_WIDTH%s%g\n", assign, equal, Ctrl->D.corr_width); + fprintf (fp, "%sCROSS_LENGTH%s%g\n", assign, equal, cross_length); + fprintf (fp, "%sL_MIN%s%g\n", assign, equal, Ctrl->C.min); + fprintf (fp, "%sL_MAX%s%g\n", assign, equal, Ctrl->C.max); + fprintf (fp, "%sL_INC%s%g\n", assign, equal, Ctrl->C.inc); + fprintf (fp, "%sM_MIN%s%g\n", assign, equal, Ctrl->A.min); + fprintf (fp, "%sM_MAX%s%g\n", assign, equal, Ctrl->A.max); + fprintf (fp, "%sM_INC%s%g\n", assign, equal, Ctrl->A.inc); + fprintf (fp, "%sW_MIN%s%g\n", assign, equal, Ctrl->W.min); + fprintf (fp, "%sW_MAX%s%g\n", assign, equal, Ctrl->W.max); + fprintf (fp, "%sW_INC%s%g\n", assign, equal, Ctrl->W.inc); + fprintf (fp, "%sTAG%s%s\n", assign, equal, Ctrl->T.prefix); + fclose (fp); + free (equal); + free (file); + free (assign); + } + + if ((error = GMT_End_IO (API, GMT_OUT, 0))) Return (error); /* Disables further data output */ + + /* Close files and free misc. memory */ + + for (m = 0; m < N_SHAPES; m++) gmt_M_free (GMT, comp[m]); + gmt_M_free (GMT, FZ_width); + gmt_M_free (GMT, FZ_asym); + gmt_M_free (GMT, FZ_comp); + + Return (GMT_NOERROR); +} diff --git a/src/gsfml/fzblender.c b/src/gsfml/fzblender.c new file mode 100644 index 00000000000..22055b38bbc --- /dev/null +++ b/src/gsfml/fzblender.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2015-2023 by P. Wessel + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: http://www.soest.hawaii.edu/PT/GSFML + *-------------------------------------------------------------------- + * + * fzblender reads a FZ analysis file and produces a smooth, blended trace. + * + * Author: Paul Wessel + * Date: 01-DEC-2023 (Requires GMT >= 6) + */ + +#define THIS_MODULE_CLASSIC_NAME "fzblender" +#define THIS_MODULE_MODERN_NAME "fzblender" +#define THIS_MODULE_LIB "gsfml" +#define THIS_MODULE_PURPOSE "Produce a smooth blended FZ trace" +#define THIS_MODULE_KEYS "DO" +#define THIS_MODULE_NEEDS "" +#define THIS_MODULE_OPTIONS "-Vh>" + +#include "gmt_dev.h" +#include "fz_analysis.h" +#include "longopt/fzblender_inc.h" + +#define DEF_Q_MIN 0.0 /* Minimum quality index */ +#define DEF_Q_MAX 4.0 /* Maximum quality index */ +#define DEF_Z_AMP_CUT 25.0 /* Amplitude cutoff for VGG */ +#define DEF_Z_VAR_CUT 50.0 /* Variance reduction cutoff */ +#define DEF_Z_F_CUT 50.0 /* F statistic cutoff */ +#define DEF_Z_W_CUT 15.0 /* Width cutoff */ + +#define N_BLENDS 5 /* Total number of traces available for blending */ +#define B_MODEL 0 +#define D_MODEL 1 +#define E_MODEL 2 +#define T_MODEL 3 +#define U_MODEL 4 + +#define N_LONG_COL 13 /* Number of input columns with longitudes */ +#define N_BLEND_COLS 10 /* Number of output columns */ +#define OUT_LON0 0 +#define OUT_LAT0 1 +#define OUT_DIST 2 +#define OUT_SHFT 3 +#define OUT_WDTH 4 +#define OUT_QWHT 5 +#define OUT_LONL 6 +#define OUT_LATL 7 +#define OUT_LONR 8 +#define OUT_LATR 9 + +struct FZBLENDER_CTRL { + struct In { + bool active; + char *file; + } In; + struct D { /* -D */ + bool active; + char *file; + } D; + struct E { /* -E[] sEcondary filter */ + bool active; + char *args; /* Full filter args for filter1d */ + } E; + struct F { /* -F[] Primary filter */ + bool active; + char *args; /* Full filter args for filter1d */ + } F; + struct I { /* -I */ + bool active; + int profile; + } I; + struct Q { /* -Q/ */ + bool active; + double min, max; + } Q; + struct S { /* -S[b][d][t][u][] */ + bool active; + int mode[N_BLENDS]; + int n_blend; + double weight[N_BLENDS]; + } S; + struct T { /* -T */ + bool active; + char *prefix; + char *file; + } T; + struct Z { /* -Z//] */ + bool active; + double amp_cut, var_cut, f_cut, w_cut; + } Z; +}; + +EXTERN_MSC int gmtlib_detrend (struct GMT_CTRL *GMT, double *x, double *y, uint64_t n, double increment, double *intercept, double *slope, int mode); +EXTERN_MSC int gmtlib_append_ogr_item (struct GMT_CTRL *GMT, char *name, unsigned int type, struct GMT_OGR *S); +EXTERN_MSC void gmtlib_write_ogr_header (FILE *fp, struct GMT_OGR *G); + +static void *New_Ctrl (struct GMT_CTRL *GMT) { /* Allocate and initialize a new control structure */ + struct FZBLENDER_CTRL *C; + + C = gmt_M_memory (GMT, NULL, 1, struct FZBLENDER_CTRL); + + /* Initialize values whose defaults are not 0/NULL */ + C->I.profile = -1; /* Default is to use all profiles */ + C->Q.min = DEF_Q_MIN; /* Min blend = Atlantic signal */ + C->Q.max = DEF_Q_MAX; /* Max blend = Pacitif signal */ + C->S.weight[B_MODEL] = C->S.weight[D_MODEL] = C->S.weight[E_MODEL] = C->S.weight[T_MODEL] = C->S.weight[U_MODEL] = 1.0; + C->T.prefix = strdup ("fztrack"); /* Default file prefix */ + C->Z.amp_cut = DEF_Z_AMP_CUT; /* Minimum significant amplitude */ + C->Z.var_cut = DEF_Z_VAR_CUT; /* Minimum significant variance reduction */ + C->Z.f_cut = DEF_Z_F_CUT; /* Minimum significant F value */ + C->Z.w_cut = DEF_Z_W_CUT; /* Minimum significant width */ + return (C); +} + +static void Free_Ctrl (struct GMT_CTRL *GMT, struct FZBLENDER_CTRL *C) { /* Deallocate control structure */ + if (!C) return; + if (C->In.file) free (C->In.file); + if (C->D.file) free (C->D.file); + if (C->E.args) free (C->E.args); + if (C->F.args) free (C->F.args); + if (C->T.prefix) free (C->T.prefix); + if (C->T.file) free (C->T.file); + gmt_M_free (GMT, C); +} + +static int usage (struct GMTAPI_CTRL *API, int level) { + const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE); + if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR); + GMT_Usage (API, 0, "usage: %s [-F] [-D] [-E] [-I] " + "[-Q/] [-Sbdetu[]] [-T] [%s] [-Z]\n", name, GMT_V_OPT); + + if (level == GMT_SYNOPSIS) return (GMT_MODULE_SYNOPSIS); + + GMT_Message (API, GMT_TIME_NONE, " OPTIONAL ARGUMENTS:\n"); + + GMT_Usage (API, 1, "\n-D Save filtered data to _filtered_{P|S}.txt. [Delete filtered files]."); + GMT_Usage (API, 1, "\n-E"); + GMT_Usage (API, -2, "Sets sEcondary filter. See -F for filter selections. [No secondary filtering]."); + GMT_Usage (API, 1, "\n-F"); + GMT_Usage (API, -2, "Sets primary filter. Choose from convolution and non-convolution filters " + "and append full filter (6-sigma width) in km."); + GMT_Usage (API, -2, "Convolution filters:"); + GMT_Usage (API, 3, "b: Boxcar : Weights are equal."); + GMT_Usage (API, 3, "c: Cosine arch : Weights given by cosine arch."); + GMT_Usage (API, 3, "g: Gaussian : Weights given by Gaussian function."); + GMT_Usage (API, 3, "f: Custom : Weights given in one-column file ."); + GMT_Usage (API, -2, "Non-convolution filters:"); + GMT_Usage (API, 3, "m: Median : Return the median value."); + GMT_Usage (API, 3, "p: Maximum likelihood probability (mode) estimator : Return the mode:"); + GMT_Usage (API, 4, "+l Return the lowest mode if multiple modes are found [return average mode]."); + GMT_Usage (API, 4, "+u Return the uppermost mode if multiple modes are found [return average mode]."); + GMT_Usage (API, 3, "l: Lower : Return minimum of all points."); + GMT_Usage (API, 3, "L: Lower+ : Return minimum of all positive points."); + GMT_Usage (API, 3, "u: Upper : Return maximum of all points.n"); + GMT_Usage (API, 3, "U: Upper- : Return maximum of all negative points."); + GMT_Usage (API, -2, "Upper case type B, C, G, M, P, F will use robust filter versions, " + "i.e., replace outliers (2.5 L1 scale (MAD) of median) with median during filtering."); + GMT_Usage (API, 1, "\n-I"); + GMT_Usage (API, -2, "Specify a particular id (first FZ is 0) to model " + "[Default models all FZ traces]."); + GMT_Usage (API, 1, "\n-Q/"); + GMT_Usage (API, -2, "Specifies how FZ blend modeling is to be done:"); + GMT_Usage (API, 3, "%s : Minimum blend value [%g].", GMT_LINE_BULLET, DEF_Q_MIN); + GMT_Usage (API, 3, "%s : Maximum blend value [%g].", GMT_LINE_BULLET, DEF_Q_MAX); + GMT_Usage (API, -2, "Points whose quality index is below is given zero weight, " + "while points whose quality index is above is given unity weight."); + GMT_Usage (API, 1, "\n-Sbdetu[]"); + GMT_Usage (API, -2, "Select the FZ estimates to blend by appending the desired code; " + "Repeatable; optionally, append a custom weight [1]:"); + GMT_Usage (API, 3, "b: Selects the optional trough/edge blend minimum."); + GMT_Usage (API, 3, "d: Selects the empirical data minimum."); + GMT_Usage (API, 3, "e: Selects the maximum slope blend model location."); + GMT_Usage (API, 3, "t: Selects the optional trough model mimimum."); + GMT_Usage (API, 3, "u: Selects the user's digitized original locations."); + GMT_Usage (API, 1, "\n--T"); + GMT_Usage (API, -2, "Set file prefix for all input/output files [fztrack]. " + "Note: no files are give on the command line."); + GMT_Option (API, "V"); + GMT_Usage (API, 1, "\n-Z"); + GMT_Usage (API, -2, "Specify four threshold values used to determine quality of fit:"); + GMT_Usage (API, 3, "%s is the minimum amplitude value [%g].", GMT_LINE_BULLET, DEF_Z_AMP_CUT); + GMT_Usage (API, 3, "%s is the minimum variance reduction value (in %%).", GMT_LINE_BULLET, DEF_Z_VAR_CUT); + GMT_Usage (API, 3, "%s is the minimum F value [%g].", GMT_LINE_BULLET, DEF_Z_F_CUT); + GMT_Usage (API, 3, "%s is the typical FZ width (in km) [%g].", GMT_LINE_BULLET, DEF_Z_AMP_CUT); + GMT_Option (API, "."); + + return (GMT_MODULE_USAGE); +} + +static int parse (struct GMTAPI_CTRL *API, struct FZBLENDER_CTRL *Ctrl, struct GMT_OPTION *options) { + + /* This parses the options provided to grdsample and sets parameters in CTRL. + * Any GMT common options will override values set previously by other commands. + * It also replaces any file names specified as input or output with the data ID + * returned when registering these sources/destinations with the API. + */ + + int j, n_files = 0, n_errors = 0; + char *choice = "bdetu"; + char ta[GMT_LEN64], tb[GMT_LEN64], tc[GMT_LEN64], td[GMT_LEN64]; + struct GMT_OPTION *opt = NULL; + struct GMT_CTRL *GMT = API->GMT; + + for (opt = options; opt; opt = opt->next) { + switch (opt->option) { + + case '<': /* Skip input files */ + n_files++; + break; + + /* Processes program-specific parameters */ + + case 'D': /* Save intermediate filtered results */ + n_errors += gmt_M_repeated_module_option (API, Ctrl->D.active); + break; + case 'E': + n_errors += gmt_M_repeated_module_option (API, Ctrl->E.active); + Ctrl->E.args = strdup (opt->arg); + break; + case 'F': + n_errors += gmt_M_repeated_module_option (API, Ctrl->F.active); + Ctrl->F.args = strdup (opt->arg); + break; + case 'I': /* Just pick a single profile for analysis */ + n_errors += gmt_M_repeated_module_option (API, Ctrl->I.active); + Ctrl->I.profile = atoi (opt->arg); + break; + case 'Q': + n_errors += gmt_M_repeated_module_option (API, Ctrl->Q.active); + j = sscanf (opt->arg, "%[^/]/%s", ta, tb); + Ctrl->Q.min = atof (ta); + Ctrl->Q.max = atof (tb); + break; + case 'S': + n_errors += gmt_M_repeated_module_option (API, Ctrl->S.active); + switch (opt->arg[0]) { + case 'b': j = B_MODEL; break; + case 'd': j = D_MODEL; break; + case 'e': j = E_MODEL; break; + case 't': j = T_MODEL; break; + case 'u': j = U_MODEL; break; + default: + GMT_Message (API, GMT_TIME_NONE, "Error -S: Not a valid model type [%c].\n", (int)opt->arg[0]); + n_errors++; + j = -1; + break; + } + if (j != -1) { + if (Ctrl->S.mode[j]) GMT_Message (API, GMT_TIME_NONE, "Option -S%c already selected once!\n", choice[j]); + Ctrl->S.mode[j] = 1; + if (opt->arg[1]) Ctrl->S.weight[j] = atof (&opt->arg[1]); + } + break; + case 'T': + n_errors += gmt_M_repeated_module_option (API, Ctrl->T.active); + free (Ctrl->T.prefix); + Ctrl->T.prefix = strdup (opt->arg); + break; + case 'Z': + n_errors += gmt_M_repeated_module_option (API, Ctrl->Z.active); + sscanf (opt->arg, "%[^/]/%[^/]/%[^/]/%s", ta, tb, tc, td); + Ctrl->Z.amp_cut = atof (ta); + Ctrl->Z.var_cut = atof (tb); + Ctrl->Z.f_cut = atof (tc); + Ctrl->Z.w_cut = atof (td); + + default: /* Report bad options */ + n_errors += gmt_default_error (GMT, opt->option); + break; + } + } + for (j = 0; j < N_BLENDS; j++) if (Ctrl->S.mode[j]) Ctrl->S.n_blend++; + + n_errors += gmt_M_check_condition (GMT, n_files > 0, "GMT SYNTAX ERROR: No input files should be given on command line (see -T).\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->Q.active && (Ctrl->Q.min < 0.0 || Ctrl->Q.max > 4.0), "GMT SYNTAX ERROR -Q: Values must be 0 <= w <= 4.\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->E.active && !Ctrl->E.args, "GMT SYNTAX ERROR -E: No secondary along-track filter selected.\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->E.active && !Ctrl->F.active, "GMT SYNTAX ERROR -E: Cannot have secondary without primary filter.\n"); + n_errors += gmt_M_check_condition (GMT, !Ctrl->S.active || Ctrl->S.n_blend == 0, "GMT SYNTAX ERROR -S: No traces have been selected for blending.\n"); + + return (n_errors ? GMT_PARSE_ERROR : GMT_NOERROR); +} + +GMT_LOCAL void FZ_fit_quality (struct GMT_CTRL *GMT, struct GMT_DATASEGMENT *S, int r, double a, double v, double f, double w, double *Q) +{ /* Return Q[B_MODEL]=Q[E_MODEL] for blend, Q[T_MODEL] for trough model, Q[E_MODEL] and Q[FZ_EMP] for empirical trough model for this segment's row r */ + if (S->data[POS_AB][r] > a && S->data[POS_VB][r] > v && S->data[POS_FB][r] > f) + Q[B_MODEL] = 4.0; + else if (S->data[POS_AB][r] > a && S->data[POS_VB][r] > v) + Q[B_MODEL] = 3.0; + else if (S->data[POS_VB][r] > v) + Q[B_MODEL] = 2.0; + else if (S->data[POS_AB][r] > a) + Q[B_MODEL] = 1.0; + else + Q[B_MODEL] = 0.0; + if (gmt_M_is_dnan (S->data[POS_AB][r])) Q[B_MODEL] = GMT->session.d_NaN; /* Flag as undetermined */ + Q[E_MODEL] = Q[B_MODEL]; + if (S->data[T_MODEL][r] > a && S->data[POS_VT][r] > v && S->data[POS_FT][r] > f) + Q[T_MODEL] = 4.0; + else if (S->data[POS_AT][r] > a && S->data[POS_VT][r] > v) + Q[T_MODEL] = 3.0; + else if (S->data[POS_VT][r] > v) + Q[T_MODEL] = 2.0; + else if (S->data[POS_AT][r] > a) + Q[T_MODEL] = 1.0; + else + Q[T_MODEL] = 0.0; + if (gmt_M_is_dnan (S->data[POS_AT][r])) Q[T_MODEL] = GMT->session.d_NaN; /* Flag as undetermined */ + /* For Empirical quality, we only have width and amplitude. Quality should increase with amp and decrease with width. + * We form the ratio (amplitude/amp_cut) over (width/width_cut), take atan and scale the result from 0-4, truncated to int */ + Q[D_MODEL] = irint (8.0 * atan ((S->data[POS_AD][r] / a) / (S->data[POS_WD][r]/ w)) / M_PI); + if (gmt_M_is_dnan (S->data[POS_AD][r]) || gmt_M_is_dnan (S->data[POS_WD][r])) Q[D_MODEL] = GMT->session.d_NaN; /* Flag as undetermined */ + Q[U_MODEL] = 0.0; /* This will depend on the others selected */ +} + +GMT_LOCAL void Ensure_Continuous_Longitudes (struct GMTAPI_CTRL *API, struct GMT_DATASET *D) +{ + struct GMT_DATATABLE *T = D->table[0]; /* Since there is only input one table */ + struct GMT_QUAD *Q = gmt_quad_init (API->GMT, 1); + unsigned int way, k, loncol[N_LONG_COL] = {POS_XR, POS_XDL, POS_XD0, POS_XDR, POS_XTL, POS_XT0, POS_XTR, POS_XBL, POS_XB0, POS_XBR, POS_XEL, POS_XE0, POS_XER}; + uint64_t fz, row, col; + char *txt[2] = {"-180 to +180", "0 to 360"}; + for (fz = 0; fz < T->n_segments; fz++) { /* For each FZ to determine */ + for (row = 0; row < T->segment[fz]->n_rows; row++) + gmt_quad_add (API->GMT, Q, T->segment[fz]->data[GMT_X][row]); /* Consider this longitude, the one along the fZ */ + } + way = gmt_quad_finalize (API->GMT, Q); + GMT_Report (API, GMT_MSG_VERBOSE, "Range finder %g to %g, selecting longitude formatting for range %s\n", Q[0].min[way], Q[0].max[way], txt[way]); + API->GMT->current.io.geo.range = Q[0].range[way]; /* Set longitude format based on input range to ensure no jumps in output */ + + for (fz = 0; fz < T->n_segments; fz++) { /* For each FZ to determine */ + for (row = 0; row < T->segment[fz]->n_rows; row++) { + for (k = 0; k < N_LONG_COL; k++) { + col = loncol[k]; + gmt_lon_range_adjust (Q->range[way], &T->segment[fz]->data[col][row]); + } + } + } + gmt_M_free (API->GMT, Q); +} + +#define bailout(code) {gmt_M_free_options (mode); return (code);} +#define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); bailout(code);} + +struct TREND { /* Holds slope and intercept for each segment column we need to detrend */ + double slp[N_BLEND_COLS]; + double icp[N_BLEND_COLS]; +}; + +#define N_TCOLS 10 /* Number of columns to detrend before filtering */ + +EXTERN_MSC int GMT_fzblender (void *V_API, int mode, void *args) { + unsigned int fz, row; + int error = 0, n_d, n_g, k, n, item, status, ndig; + int col[N_BLEND_COLS][N_BLENDS] = /* Columns in the analyzis file for b,d,e,t,u trace parameters */ + { + {POS_XB0, POS_XD0, POS_XE0, POS_XT0, POS_XR}, /* FZ longitudes */ + {POS_YB0, POS_YD0, POS_YE0, POS_YT0, POS_YR}, /* FZ latitudes */ + {-1, -1, -1, -1, -1}, /* Skip distances */ + {POS_SB, POS_SD, POS_SE, POS_ST, POS_SD}, /* FZ model offsets */ + {POS_WB, POS_WD, POS_WB, POS_WT, POS_WD}, /* FZ model widths */ + {-1, -1, -1, -1, -1}, /* Put quality index here */ + {POS_XBL, POS_XDL, POS_XEL, POS_XTL, POS_XDL}, /* FZ left lon */ + {POS_YBL, POS_YDL, POS_YEL, POS_YTL, POS_YDL}, /* FZ left lat */ + {POS_XBR, POS_XDR, POS_XER, POS_XTR, POS_XDR}, /* FZ right lon */ + {POS_YBR, POS_YDR, POS_YER, POS_YTR, POS_YDR} /* FZ right lat */ + }; + int tcols[N_TCOLS] = {POS_XR, POS_YR, POS_XB0, POS_YB0, POS_SB, POS_WB, POS_XBL, POS_YBL, POS_XBR, POS_YBR}; + + char buffer[BUFSIZ] = {""}, run_cmd[BUFSIZ] = {""}, *cmd = NULL; + char source[GMT_VF_LEN] = {""}, destination[GMT_VF_LEN] = {""}; + + double Q[N_BLENDS], P[N_BLENDS], q_weight[N_BLENDS], sum_P, sum_w, sum_q, i_q_range, q_model; + + struct GMT_OPTION *options = NULL; + struct FZBLENDER_CTRL *Ctrl = NULL; + struct TREND *trend = NULL; + struct GMT_DATASET *Fin = NULL, *Fout = NULL; + struct GMT_DATATABLE *Tin = NULL, *Tout = NULL; + struct GMT_CTRL *GMT = NULL, *GMT_cpy = NULL; + struct GMTAPI_CTRL *API = gmt_get_api_ptr (V_API); /* Cast from void to GMTAPI_CTRL pointer */ + + /*----------------------- Standard module initialization and parsing ----------------------*/ + + if (API == NULL) return (GMT_NOT_A_SESSION); + if (mode == GMT_MODULE_PURPOSE) return (usage (API, GMT_MODULE_PURPOSE)); /* Return the purpose of program */ + options = GMT_Create_Options (API, mode, args); if (API->error) return (API->error); /* Set or get option list */ + + if ((error = gmt_report_usage (API, options, 0, usage)) != GMT_NOERROR) bailout (error); /* Give usage if requested */ + + /* Parse the program-specific arguments */ + + if ((GMT = gmt_init_module (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_KEYS, THIS_MODULE_NEEDS, module_kw, &options, &GMT_cpy)) == NULL) + bailout (API->error); /* Save current state */ + if (GMT_Parse_Common (API, THIS_MODULE_OPTIONS, options)) Return (API->error); + Ctrl = New_Ctrl (GMT); /* Allocate and initialize a new control structure */ + if ((error = parse (API, Ctrl, options))) Return (error); + + /*---------------------------- This is the fzblender main code ----------------------------*/ + + sprintf (buffer, "%s_analysis.txt", Ctrl->T.prefix); + Ctrl->In.file = strdup (buffer); + GMT->current.setting.io_header[GMT_OUT] = 1; /* To allow writing of headers */ + + GMT_Report (API, GMT_MSG_NORMAL, "Read FZ analysis file %s\n", Ctrl->In.file); + if ((Fin = GMT_Read_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_READ_NORMAL, NULL, Ctrl->In.file, NULL)) == NULL) Return ((error = GMT_DATA_READ_ERROR)); + + Ensure_Continuous_Longitudes (API, Fin); /* Set longitude to 0-360 or -180/180 so there are no jumps */ + + /* Set up the primary GMT_filter1d cmd call */ + + if (Ctrl->F.active) { /* Wants to filter before blending */ + /* Must remove linear trends from the lon/lat columns before filtering since median fails on sloping lines */ + Tin = Fin->table[0]; /* Since there is only input one table */ + trend = gmt_M_memory (GMT, NULL, Tin->n_segments, struct TREND); + for (fz = 0; fz < Tin->n_segments; fz++) { /* For each FZ to determine */ + GMT_Report (API, GMT_MSG_VERBOSE, "Detrend FZ %s [segment %ld]\n", Tin->segment[fz]->label, fz); + if (Ctrl->I.profile >= 0 || fz == (unsigned int)Ctrl->I.profile) continue; /* Skip all but selected profile */ + for (k = 0; k < N_TCOLS; k++) { /* Detrend key columns */ + gmtlib_detrend (GMT, Tin->segment[fz]->data[POS_DR], Tin->segment[fz]->data[tcols[k]], Tin->segment[fz]->n_rows, 0.0, &trend[fz].icp[k], &trend[fz].slp[k], -1); + } + } + if (Ctrl->D.active) { + /* Save the detrended temporary file */ + sprintf (buffer, "%s_detrended.txt", Ctrl->T.prefix); + GMT_Report (API, GMT_MSG_VERBOSE, "Save detrended data to temporary file %s\n", buffer); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, buffer, Fin) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + } + + /* Register output for filter1d results */ + /* Create virtual files for using the data in filter1d and another for holding the result */ + if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_IN|GMT_IS_REFERENCE, Fin, source) != GMT_NOERROR) { + Return (API->error); + } + if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_OUT|GMT_IS_REFERENCE, NULL, destination) == GMT_NOTSET) { + Return (API->error); + } + + GMT_Report (API, GMT_MSG_NORMAL, "Perform primary filtering\n"); + //sprintf (buffer, "-F%s -E -N%d %s ->%s", Ctrl->F.args, POS_DR, p_in_string, p_out_string); + sprintf (buffer, "-F%s -N%d %s ->%s", Ctrl->F.args, POS_DR, source, destination); + GMT_Report (API, GMT_MSG_DEBUG, "Args to primary filter1d: %s\n", buffer); + if ((status = GMT_Call_Module (API, "filter1d", GMT_MODULE_CMD, buffer))) { + GMT_Report (API, GMT_MSG_NORMAL, "GMT SYNTAX ERROR: Primary filtering failed with exit code %d!\n", status); + Return (status); + } + GMT_Report (API, GMT_MSG_DEBUG, "filter1d completed\n"); + /* Close the source virtual file and destroy the data set */ + if (GMT_Close_VirtualFile (GMT->parent, source) != GMT_NOERROR) { + Return (API->error); + } + GMT_Destroy_Data (API, &Fin); + + if (Ctrl->E.active) { /* Now apply the secondary filter */ + struct GMT_DATASET *D = NULL; + char s_in_string[GMT_LEN256], s_out_string[GMT_LEN256]; + /* Retrieve the primary filtering results */ + if ((D = GMT_Read_VirtualFile (API, destination)) == NULL) { + Return (API->error); + } + /* Close the destination virtual file */ + if (GMT_Close_VirtualFile (GMT->parent, destination) != GMT_NOERROR) { + Return (API->error); + } + if (Ctrl->D.active) { + /* Save the primary filtered file */ + sprintf (buffer, "%s_primary_filter_P.txt", Ctrl->T.prefix); + GMT_Report (API, GMT_MSG_VERBOSE, "Save primary filtered detrended data to temporary file %s\n", buffer); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, buffer, D) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + } + /* Setup in/out for secondary filter */ + if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_IN|GMT_IS_REFERENCE, D, source) != GMT_NOERROR) { + Return (API->error); + } + if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_OUT|GMT_IS_REFERENCE, NULL, destination) == GMT_NOTSET) { + Return (API->error); + } + //sprintf (buffer, "-F%s -E -N%d %s ->%s", Ctrl->E.args, POS_DR, s_in_string, s_out_string); + sprintf (buffer, "-F%s -N%d %s ->%s", Ctrl->E.args, POS_DR, source, destination); + GMT_Report (API, GMT_MSG_DEBUG, "Args to secondary filter1d: %s\n", buffer); + if ((status = GMT_Call_Module (API, "filter1d", GMT_MODULE_CMD, buffer))) { + GMT_Report (API, GMT_MSG_NORMAL, "GMT SYNTAX ERROR: Secondary filtering failed with exit code %d!\n", status); + Return (status); + } + if (GMT_Close_VirtualFile (GMT->parent, source) != GMT_NOERROR) { + Return (API->error); + } + GMT_Destroy_Data (API, &D); + } + /* Retrieve the final filtering results */ + if ((Fin = GMT_Read_VirtualFile (API, destination)) == NULL) { + Return (API->error); + } + /* Close the destination virtual file */ + if (GMT_Close_VirtualFile (GMT->parent, destination) != GMT_NOERROR) { + Return (API->error); + } + if (Ctrl->D.active && Ctrl->E.active) { + /* Save the primary or secondary filtered file */ + char F = (Ctrl->E.active) ? 'S' : 'P'; + char *str = (Ctrl->E.active) ? "secondary" : "primary"; + sprintf (buffer, "%s_primary_filter_%c.txt", Ctrl->T.prefix, F); + GMT_Report (API, GMT_MSG_VERBOSE, "Save %s filtered detrended data to temporary file %s\n", str, buffer); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, buffer, Fin) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + } + + /* Now restore original trends */ + GMT_Report (API, GMT_MSG_DEBUG, "Restore original trends\n"); + Tin = Fin->table[0]; /* Since there is only input one table */ + for (fz = 0; fz < Tin->n_segments; fz++) { /* For each FZ to determine */ + GMT_Report (API, GMT_MSG_VERBOSE, "Restore trends for FZ %s [segment %ld]\n", Tin->segment[fz]->label, fz); + if (Ctrl->I.profile >= 0 || fz == (unsigned int)Ctrl->I.profile) continue; /* Skip all but selected profile */ + for (k = 0; k < N_TCOLS; k++) { /* Restore trend to key columns */ + gmtlib_detrend (GMT, Tin->segment[fz]->data[POS_DR], Tin->segment[fz]->data[tcols[k]], Tin->segment[fz]->n_rows, 0.0, &trend[fz].icp[k], &trend[fz].slp[k], +1); + } + } + gmt_M_free (GMT, trend); + } + + /* OK, all input/filtering is completed */ + + Tin = Fin->table[0]; /* Since there is only input one table */ + if (Tin->segment[0]->n_columns < N_FZ_ANALYSIS_COLS) { /* Trouble */ + GMT_Message (API, GMT_TIME_NONE, "GMT SYNTAX ERROR: %s does not have %d columns\n", Ctrl->In.file, N_FZ_ANALYSIS_COLS); + Return (EXIT_FAILURE); + } + + if (Ctrl->D.active && Ctrl->F.active) { + sprintf (buffer, "%s_filtered.txt", Ctrl->T.prefix); + Ctrl->D.file = strdup (buffer); + GMT_Report (API, GMT_MSG_NORMAL, "Filtered analysis results saved to %s\n", Ctrl->D.file); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, Ctrl->D.file, Fin) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + } + + /* Specify geographic columns where needed for blend output */ + + GMT->current.io.col_type[GMT_OUT][OUT_LON0] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][OUT_LAT0] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][OUT_LONL] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][OUT_LATL] = GMT_IS_LAT; + GMT->current.io.col_type[GMT_OUT][OUT_LONR] = GMT_IS_LON; GMT->current.io.col_type[GMT_OUT][OUT_LATR] = GMT_IS_LAT; + + GMT_Report (API, GMT_MSG_DEBUG, "Perform blending\n"); + cmd = GMT_Create_Cmd (API, options); + sprintf (run_cmd, "# %s %s", GMT->init.module_name, cmd); /* Build command line argument string */ + gmt_M_free (GMT, cmd); + + Fout = gmt_alloc_dataset (GMT, Fin, 0, N_BLEND_COLS, GMT_ALLOC_NORMAL); /* Same table length as FZ, but with N_BLEND_COLS columns */ + Tout = Fout->table[0]; + Tout->n_headers = 3; + Tout->header = gmt_M_memory (GMT, NULL, Tout->n_headers, char *); + Tout->header[0] = strdup ("# Blended FZ traces"); + Tout->header[1] = strdup (run_cmd); + Tout->header[2] = strdup ("# lon\tlat\tdist\tshift\twidth\tqweight\tlon_l\tlat_l\tlon_r\tlat_r"); + + i_q_range = 1.0 / (Ctrl->Q.max - Ctrl->Q.min); + gmt_M_memset (q_weight, N_BLENDS, double); /* So those that are not set below remain 0 */ + + for (fz = 0; fz < Tin->n_segments; fz++) { /* For each FZ to determine */ + + GMT_Report (API, GMT_MSG_NORMAL, "Process FZ %s [segment %ld]\n", Tin->segment[fz]->label, fz); + + if (Ctrl->I.profile >= 0 || fz == (unsigned int)Ctrl->I.profile) { /* Skip all but selected profile */ + struct GMT_DATASEGMENT_HIDDEN *SH = gmt_get_DS_hidden (Tout->segment[fz]); + SH->mode = GMT_WRITE_SKIP; /* Ignore on output */ + continue; + } + + ndig = irint (floor (log10 ((double)Tin->segment[fz]->n_rows))) + 1; /* Determine how many decimals are needed for largest FZ id */ + + for (row = 0; row < Tin->segment[fz]->n_rows; row++) { /* Process each point along digitized FZ trace */ + + FZ_fit_quality (GMT, Tin->segment[fz], row, Ctrl->Z.amp_cut, Ctrl->Z.var_cut, Ctrl->Z.f_cut, Ctrl->Z.w_cut, Q); /* Compute quality indeces for blend, trough, empirical models */ + for (k = n = 0, sum_q = 0.0; k < N_BLENDS-1; k++) { /* Compute quality weights for each model trace */ + if (!Ctrl->S.mode[k]) continue; + q_weight[k] = (Q[k] - Ctrl->Q.min) * i_q_range; + sum_q += q_weight[k]; + n++; /* Count the candidates selected */ + } + q_model = (n) ? sum_q / n : 0.0; + q_weight[N_BLENDS-1] = 1.0 - q_model; /* Estimate remaining q_weight for user profile */ + + /* Now compute the blended output */ + + for (item = 0; item < N_BLEND_COLS; item++) { + if (item == OUT_DIST) { /* No blending, just pass on along-track distance */ + Tout->segment[fz]->data[item][row] = Tin->segment[fz]->data[POS_DR][row]; + continue; + } + if (item == OUT_QWHT) { /* Store the quality weight for model */ + Tout->segment[fz]->data[item][row] = q_model; + continue; + } + /* Get the 4 candidates for blending */ + for (k = 0; k < N_BLENDS; k++) P[k] = Tin->segment[fz]->data[col[item][k]][row]; + if (item == OUT_SHFT) P[N_BLENDS-1] = 0.0; /* Digitized trace defines origin so offset == 0 */ + if (item == OUT_LON0 || item == OUT_LONL || item == OUT_LONR) { /* Must be careful with longitudes */ + for (k = n_g = n_d = 0; k < N_BLENDS; k++) { /* Determine if we have longs across Greenwich */ + if (P[k] > 350.0) n_d++; + if (P[k] < 10.0) n_g++; + } + if (n_d && n_g) /* Some longitudes crossing 0/360 line, switch to -180/180 mode */ + for (k = 0; k < N_BLENDS; k++) if (P[k] > 180.0) P[k] -= 360.0; + } + for (k = 0, sum_P = sum_w = 0.0; k < N_BLENDS; k++) { /* Those with q_weight == 0 or not requested won't contribute */ + if (!Ctrl->S.mode[k]) continue; + sum_P += P[k] * q_weight[k] * Ctrl->S.weight[k]; + sum_w += q_weight[k] * Ctrl->S.weight[k]; + } + Tout->segment[fz]->data[item][row] = sum_P / sum_w; + } + } + + /* Update the header */ + + sprintf (buffer, "Blend result for trace FZ -L\"%s\" [segment %d]", Tin->segment[fz]->label, fz); + Tout->segment[fz]->header = strdup (buffer); + } + + /* Store final blended profiles */ + + sprintf (buffer, "%s_blend.txt", Ctrl->T.prefix); + Ctrl->T.file = strdup (buffer); + GMT_Report (API, GMT_MSG_NORMAL, "Save FZ blend results to %s\n", Ctrl->T.file); + if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, 0, NULL, Ctrl->T.file, Fout) != GMT_NOERROR) Return ((error = GMT_DATA_WRITE_ERROR)); + + Return (GMT_NOERROR); +} diff --git a/src/gsfml/fzinformer b/src/gsfml/fzinformer new file mode 100755 index 00000000000..a9218297b09 --- /dev/null +++ b/src/gsfml/fzinformer @@ -0,0 +1,180 @@ +#!/usr/bin/env bash +#-------------------------------------------------------------------- +# Copyright (c) 2015-2023 by P. Wessel +# See LICENSE.TXT file for copying and redistribution conditions. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; version 3 or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# Contact info: http://www.soest.hawaii.edu/PT/GSFML +#-------------------------------------------------------------------- +# Script to make a plot of the statistical parameters +# for a given FZ segment +# +# Author: Paul Wessel +# Date: 01-DEC-2023 (Requires GMT >= 6) +# Mode: GMT classic mode +#-------------------------------------------------------------------- + +. fz_funcs.sh # Load in FZ-specific shell functions +if [ $# -eq 0 ]; then + version=`fz_get_version` +cat << EOF >&2 + fzinformer $version - Plot along-FZ statistical information + + Usage: fzinformer [-D] [-F] [-I][-N] [-S] [-T] [-W] + + OPTIONS: + -D selected the filtered data [raw]. + -F sets max F amplitude (log scale used) [10000]. + -I select the FZ trace to report on [0 or first]. + -N sets max VGG amplitude [200]. + -S sets max +/- shift range [25]. + -T sets the profile prefix [fztrack]. + -V Report on progress [quiet]. + -W sets max W amplitude [50]. + +EOF + exit +fi + +trap 'fz_cleanup 1' 1 2 3 15 # Set interrup handling + +# Default values +filtered=0 +verbose=0 +P=0 +amax=200 +fmax=10000 +smax=25 +wmax=50 +prefix=fztrack + +while [ ! x"$1" = x ]; do + case $1 + in + -D) filtered=1; # Used the filtered data + shift;; + -F*) fmax=`fz_get_arg $1` # max F + shift;; + -I*) P=`fz_get_arg $1` # profile argument + shift;; + -N*) amax=`fz_get_arg $1` # max amplitude + shift;; + -S*) smax=`fz_get_arg $1` # max +/- shift + shift;; + -T*) prefix=`fz_get_arg $1` # Get file prefix + shift;; + -W*) wmax=`fz_get_arg $1` # max width + shift;; + -V) verbose=1; # Gave a VGG grid + shift;; + -*) echo "$0: Unrecognized option $1" 1>&2; # Bad option argument + exit 1;; + esac +done + +if [ ${filtered} -eq 0 ]; then + AFILE=${prefix}_analysis.txt +else + AFILE=${prefix}_filtered.txt +fi +BFILE=${prefix}_blend.txt +#----------------------------------------- +ymargin=1 +xmargin=1 +spacing=0.175 +W=6.3 +H=1.2 +xu=`gmt math -Q -0.75 1 ${xmargin} SUB ADD =` +yu=`gmt math -Q -0.75 1 ${ymargin} SUB ADD =` +# Extract our segment */ +gmt convert -Q${P} ${AFILE} > /tmp/t.txt +# How many points along segment? +n_cross=`cat /tmp/t.txt | wc -l | awk '{printf "%d\n", $1-1}'` +yup=`gmt math -Q ${H} ${spacing} ADD =` +gmt info ${AFILE} -C -I1/1/2/10/0.01/1/1/5/5/5/1 > $$.info +dmin=`cut -f5 $$.info` +dmax=`cut -f6 $$.info` +gmt begin ${prefix}_stat pdf + gmt basemap -R${dmin}/${dmax}/0/1 -JX6i/8.9i -U/${xu}i/${yu}i/"${prefix}" -K -B+gwhite -X${xmargin}i -Y${ymargin}i + # Plot blend and u values + x=`fz_col_id DR` + y=`fz_col_id BL` + gmt plot ${AFILE} -i${x},${y} -R${dmin}/${dmax}/-0.05/1.05 -JX${W}i/${H}i -Bxa500f100+l"Distance along FZ"+u"km" -Bya0.2f0.1 -BWSnE -Y0.25i -W1p --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 --MAP_LABEL_OFFSET=0.05i + y=`fz_col_id UT` + gmt plot ${AFILE} -i${x},${y} -W1p,green + y=`fz_col_id UB` + gmt plot ${AFILE} -i${x},${y} -W1p,blue + echo "${dmax} 1.05 C" | gmt text-Gwhite -W0.25p -F+jTR+f9p -Dj0.05i + echo "${dmin} 1.05 A" | gmt text -Gwhite -W0.25p -F+jTL+f9p -Dj0.05i + # Plot directions + y=`fz_col_id OR` + gmt plot $AFI{LE -i${x},${y} -R${dmin}/${dmax}/-1.1/1.1 -Bxa500f100 -Bya1g5 -BWsnE -W1p -Y${yup}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 --MAP_LABEL_OFFSET=0.05i + echo "${dmax} 0 O" | gmt text Gwhite -W0.25p -F+jBR+f9p -Dj0.05i + # Plot offsets + y=`fz_col_id SD` + gmt plot ${AFILE} -i${x},${y} -R${dmin}/${dmax}/-${smax}/${smax} -Bxa500f100 -Bya5f1g100 -BWsnE -W1p,red -Y${yup}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 + y=`fz_col_id ST` + gmt plot ${AFILE} -i${x},${y} -W1p,green + y=`fz_col_id SB` + gmt plot ${AFILE} -i${x},${y} -W1p,blue + echo "$dmax $smax @~D@~" | gmt text -Gwhite -W0.25p -F+jTR+f9p -Dj0.05i + # Plot widths + y=`fz_col_id WD` + gmt plot ${AFILE} -i${x},${y} -R${dmin}/${dmax}/0/${wmax} -Bxa500f100 -Bya10f5 -BWsnE -W1p,red -Y${yup}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 + y=`fz_col_id WT` + gmt plot ${AFILE} -i${x},${y} -W1p,green + y=`fz_col_id WB` + gmt plot ${AFILE} -i${x},${y} -W1p,blue + echo "${dmax} ${wmax} W" | gmt text -Gwhite -W0.25p -F+jTR+f9p -Dj0.05i + gmt plot -W0.5p,- << EOF + ${dmin} 15 + ${dmax} 15 + EOF + # Plot amplitudes + y=`fz_col_id AD` + gmt plot ${AFILE} -i${x},${y} -R${dmin}/${dmax}/0/${amax} -Bxa500f100 -Bya50f10g1000 -BWsnE -W1p,red -Y${yup}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 + y=`fz_col_id AT` + gmt plot ${AFILE} -i${x},${y} -W1p,green + y=`fz_col_id AB` + gmt plot ${AFILE} -i${x},${y}-W1p,blue + echo "${dmax} ${amax} A" | gmt text-Gwhite -W0.25p -F+jTR+f9p -Dj0.05i + gmt plot -W0.5p,- << EOF + ${dmin} 25 + ${dmax} 25 + EOF + # Plot variance reductions + y=`fz_col_id VT` + gmt plot ${AFILE} -i${x},${y} -R${dmin}/${dmax}/-5/105 -JX${W}i/${H}i -Bxa500f100 -Bya20f5 -BWsnE -W1p,green -Y${yup}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 + y=`fz_col_id VB` + gmt plot ${AFILE} -i${x},${y} -W1p,blue + echo "${dmax} 105 V" | gmt text -Gwhite -W0.25p -F+jTR+f9p -Dj0.05i + gmt plot -W0.5p,- << EOF + ${dmin} 50 + ${dmax} 50 + EOF + # Plot F values + y=`fz_col_id FT` + gmt plot ${AFILE} -i${x},${y} -R${dmin}/${dmax}/1/${fmax} -JX${W}i/${H}il -Bxa500f100 -Bya1pf3 -BWsE -W1p,green -Y${yup}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 + echo "${dmax} ${fmax} F" | gmt text -Gwhite -W0.25p -F+jTR+f9p -Dj0.05i + y=`fz_col_id FB` + gmt plot ${AFILE} -i${x},${y} -W1p,blue + gmt plot -W0.5p,- << EOF + ${dmin} 50 + ${dmax} 50 + EOF + #grep -v '^>' ${AFILE} | cut -f3,11 | gmt plot -R${dmin}/${dmax}/0/4 -Bxa500f100 -Bya1f1+l"Q" -BWse -W1p -Y${yup}i --FONT_ANNOT_PRIMARY=10 + gmt basemap -R0/${n_cross}/0/100 -Bxa20f1+l"FZ ID ${P}" -By0 -BN --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 --MAP_LABEL_OFFSET=0.05i + if [ $verbose -eq 1 ]; then + echo "fzinformer: Final plot is called ${prefix}_stat.pdf" >&2 + fi +gmt end show + +fz_cleanup 1 diff --git a/src/gsfml/fzmapper b/src/gsfml/fzmapper new file mode 100755 index 00000000000..85c405d0b66 --- /dev/null +++ b/src/gsfml/fzmapper @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +#-------------------------------------------------------------------- +# Copyright (c) 2015-2023 by P. Wessel +# See LICENSE.TXT file for copying and redistribution conditions. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; version 3 or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# Contact info: http://www.soest.hawaii.edu/PT/GSFML +#-------------------------------------------------------------------- +# Bash script to make a single, large-format GMT map of the locations +# of all cross profiles for a given FZ segment. +# +# Author: Paul Wessel +# Date: 01-DEC-2023 (Requires GMT >= 6) +# Mode: GMT classic mode +#-------------------------------------------------------------------- + +. fz_funcs.sh # Load in FZ-specific shell functions +VGG=@earth_vgg_01m +SCL=0.1 +if [ $# -eq 0 ]; then + version=`fz_get_version` +cat << EOF >&2 + fzmapper $version - Make Mercator map of FZ traces and cross-profiles + + Usage: fzmapper [-A] [-F] [-G] [-L] [-O] [-S] [-T] [-V] [-W[c|i]] + + OPTIONS: + -A Plot the analysis results from fzanalysis, if available [no results]. + -F contains the original FZ track(s). + -G is name of global grid file [$VGG]. + -L sets how often to annotate profiles [1]. + -O Run as GMT overlay (i.e., pass -O -K) and send to stdout. + No PDF is made. + -S Plot the smooth curve from fzblender, if available [no smooth curve]. + -T sets the profile prefix [fztrack]. + -V Report on progress [quiet]. + -W specifies the map width (e.g., 10i or 50c). + Append units c or i [Default uses PROJ_LENGTH_UNIT]. + +EOF + exit +fi + +trap 'fz_cleanup 1' 1 2 3 15 # Set interrup handling +# Default values +W=6 +N=1 +F="" +blend=0 +anal=0 +OL=0 +verbose=0 +prefix=fztrack + +while [ ! x"$1" = x ]; do + case $1 + in + -A) anal=1 # Overlay analysis result if possible + shift;; + -W*) W=`fz_get_dim $1` # Width of map + shift;; + -F*) ORIG=`fz_get_arg $1`; # Original unsampled tracks + shift;; + -G*) VGG=`fz_get_arg $1`; # Name of grid file + shift;; + -L*) N=`fz_get_arg $1`; # Annotate every N'th profile + shift;; + -O) OL=1; # Plot as PS overlay to stdout + plot=1; + shift;; + -S) blend=1 # Overlay blend if possible + shift;; + -T*) prefix=`fz_get_arg $1` # Get file prefix + shift;; + -V) verbose=1; # Verbose + shift;; + -*) echo "$0: Unrecognized option $1" 1>&2; # Bad option argument + exit 1;; + esac +done + +# Make sure we convert to inches +#----------------------------------------- +CFILE=${prefix}_resampled.txt # The resampled tracks from grdtrack -D +if [ ! -f ${CFILE} ]; then # Cannot do it yet anyway + anal=0 + echo "$0: Resampled file ${CFILE} not found - cannot make plot" >&2 + exit +fi +XFILE=${prefix}_cross.txt # Crossprofiles from fzmodeler +if [ ! -f ${XFILE} ]; then # Cannot do it yet anyway + anal=0 + echo "$0: Cross-profile file ${XFILE} not found - cannot make plot" >&2 + exit +fi +TFILE=${prefix}_analysis.txt # The results from fzmodeler +if [ ! -f ${TFILE} ] && [ ${anal} -eq 1 ]; then # Cannot do it yet anyway + anal=0 + echo "$0: Analysis file ${TFILE} not found - ignored" >&2 +fi +if [ ${OL} -eq 1 ]; then + PS=/tmp/map.ps # PostScript plot file + PSargs="-O -K" +else + PS=${prefix}_map.ps # PostScript plot file + PSargs="-P -K" + PDF=${prefix}_map.pdf # Final PDF plot file +fi +. ${prefix}_par.txt # Read and assign parameters for these profiles +#------------------------------------------------------------------------------------------------------ +# All dimensions are now in inches, regardless of what the user's units are. +# Cross-profiles have lon,lat,dist,azimuth,vgg,age,fzdist columns. +# Assign variables and calculate dimensions (inches used throughout) +#------------------------------------------------------------------------------------------------------ +ymargin=0.75 # Bottom margin +xmargin=1 # Left margin +gmt set PROJ_ELLIPSOID Sphere # Since we are plotting VGG +n_cross=`gmt convert -L ${XFILE} | wc -l` # Number of cross-profiles +ndig=`gmt math -Q ${n_cross} LOG10 FLOOR 1 ADD =` # Number of digits to use for running numbers +gmt info $XFILE -C -I2/2/2/5/10/10/10/10/10 -fg > $$.info # Get clean multiples of min/max for each column +xmin=`cut -f1 $$.info` # West boundary +xmax=`cut -f2 $$.info` # East boundary +ymin=`cut -f3 $$.info` # South boundary +ymax=`cut -f4 $$.info` # North boundary +width2=`gmt math -Q ${W} 2 ${xmargin} MUL ADD =` # Width of entire plot including margins +R=-R${xmin}/${xmax}/${ymin}/${ymax} # Region -R option +height=`echo ${xmax} ${ymax} | gmt mapproject ${}R -JM${W}i -Di | cut -f2` # Map height +height2=`gmt math -Q ${height} 2 $ymargin MUL ADD =` # Plot height including margins +#------------------------------------------------------------------------------------------------------ +# Ready for plotting +if [ ${verbose} -eq 1 ]; then + echo "fzmapper: Papersize is ${width2}i by ${height2}i" >&2 +fi +#------------------------------------------------------------------------------------------------------ +if [ $OL -eq 1 ]; then + PSargs="-O -K" +else + PSargs="-P -K -X${xmargin}i -Y${ymargin}i --PS_MEDIA=${width2}ix${height2}i" +fi +gmt makecpt -Cgray -T-60/60/5 -Z > $$.cpt # Make basic -60 to + 60 Eotvos grayscale CPT +xu=`gmt math -Q -0.75 1 ${xmargin} SUB ADD =` # Placement x for -U logo and label +yu=`gmt math -Q -0.75 1 ${ymargin} SUB ADD =` # Placement y for -U logo and label +# Lay down VGG image +gmt grdimage ${VGG} -C$$.cpt ${R} -JM${W}i ${PSargs} >| $PS +# Overlay geographic basemap and set -U label +gmt psbasemap ${R} -JM${W}i -O -B5f1g90 -BWSne -K -U/${xu}i/${yu}i/"${prefix}: Map view" >> $PS +# Draw resampled FZ tracks as blue solid line +gmt psxy -R -J -O -K ${CFILE} -W0.5p,blue >> $PS +# Plot original digitized points as dark blue squares +if [ ! "X${ORIG}" = "X" ]; then + gmt psxy -R -J -O -K ${ORIG} -Ss0.04i -Gdarkblue >> $PS +fi +P=0 +# Make color table for quality weights (0-1) +gmt makecpt -Cpolar -T0/1/0.05 -Z > $$.cpt +cat << EOF >> $$.cpt2 +-0.125 red 0.125 red +0.125 orange 0.375 orange +0.375 yellow 0.625 yellow +0.625 lightgreen 0.875 lightgreen +0.875 green 1.125 green +EOF + +# Process each crossing profile individually +while [ ${P} -lt ${n_cross} ]; do + item=`echo ${P} ${ndig} | awk '{printf "%*.*d\n", $2, $2, $1}'` # Format an integer as profile identifier + gmt convert -Q$P ${XFILE} > $$.raw # Extract the next profile to plot (includes the segment header) + grep -v '>' $$.raw > $$.tmp # Get this cross profile without header + header=`head -1 $$.raw` # Get this cross profile's header + az=`fz_get_item "${header}" az` # Extract the azimuth of this profile + tail -1 $$.raw | cut -f1,2 > $$.tail # Place the end coordinates of profile in file $$.tail + + gmt psxy $$.tmp -R -J -O -K -Wfaint,lightblue >> $PS # Plot cross-profile as faint, lightblue lines + go=`gmt math -Q ${P} ${N} MOD 0 EQ =` # Determine when to annotate profiles + if [ ${go} -eq 1 ]; then # OK, want to place text ID for this cross profile + side=`gmt math -Q ${az} 180 LT =` # Determine which side to place profile label + if [ ${side} -eq 1 ]; then + awk '{ printf "%s %s %s LM %s\n", $1, $2, '"${az}"', '"${item}"'}' $$.tail | gmt pstext -R -J -A -O -K -Dj0.15i/0.05ivfaint -F+f6p,Helvetica+a+j -C0.015i -To -Gwhite -W0.5p >> $PS + else + awk '{ printf "%s %s %s RM %s\n", $1, $2, '"${az}"', '"${item}"'}' $$.tail | gmt pstext -R -J -A -O -K -Dj0.15i/0.05ivfaint -F+f6p,Helvetica+a+j -C0.015i -To -Gwhite -W0.5p >> $PS + fi + fi + P=`expr ${P} + 1` # Goto next profile +done +# Plot resampled digitized line in magenta +gmt psxy -R -J -O -K ${CFILE} -W0.25p,magenta >> $PS +# Plot empirical trough locations in red +x=`fz_col_id XD0` +y=`fz_col_id YD0` +if [ ${anal} -eq 1 ]; then + gmt psxy ${TFILE} -R -J -O -K -Sc0.02i -Gred -i${x},${y} >> $PS + # Plot blend trough locations in green + x=`fz_col_id XB0` + y=`fz_col_id YB0` + gmt psxy ${TFILE} -R -J -O -K -Sc0.02i -Ggreen3 -i${x},${y} >> $PS + # Plot edge blend locations in blue + x=`fz_col_id XE0` + y=`fz_col_id YE0` + gmt psxy ${TFILE} -R -J -O -K -Sc0.02i -Gblue -i${x},${y} >> $PS +fi +if [ ${blend} -eq 1 ]; then + BFILE=${prefix}_blend.txt # Blended solution from fzblender + if [ -f ${BFILE} ]; then + # Plot best blend model as cyan line with colored circles reflecting quality + gmt psxy ${BFILE} -R -J -O -K -W0.5p,cyan >> $PS + gmt psxy ${BFILE} -R -J -O -K -Sc0.03i -C$$.cpt2 -i0,1,5 >> $PS + # Add error bounds as dashed orange lines + gmt psxy ${BFILE} -R -J -O -K -W0.25p,orange,- -i6,7 >> $PS + gmt psxy ${BFILE} -R -J -O -K -W0.25p,orange,- -i8,9 >> $PS + else + echo "$0: Blend file ${BFILE} not found - ignored" >&2 + fi +fi +if [ ${OL} -eq 1 ]; then + cat ${PS} +else + # Finalize plot + gmt psxy -R -J -O -T >> ${PS} + # Convert the PS to a PDF file + gmt psconvert -Tf ${PS} + # Delete temporary files and the PS file + os=`uname -s` + if [ ${verbose} -eq 1 ]; then + echo "fzmapper: Final map is called ${PDF}" >&2 + fi + if [ ${os} = "Darwin" ]; then + open ${PDF} + fi +fi + +rm -f ${PS} +fz_cleanup 1 diff --git a/src/gsfml/fzmodeler b/src/gsfml/fzmodeler new file mode 100755 index 00000000000..c8aee62c023 --- /dev/null +++ b/src/gsfml/fzmodeler @@ -0,0 +1,190 @@ +#!/usr/bin/env bash +#-------------------------------------------------------------------- +# Copyright (c) 2015-2023 by P. Wessel +# See LICENSE.TXT file for copying and redistribution conditions. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; version 3 or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# Contact info: http://www.soest.hawaii.edu/PT/GSFML +#-------------------------------------------------------------------- +# Simulate a FZ based on simple Pac/Atl blend model w/wo compression +# +# Author: Paul Wessel +# Date: 01-DEC-2023 (Requires GMT >= 6) +# Mode: GMT classic mode +#-------------------------------------------------------------------- + +function G0 () { # Gaussian - The Atlantic signal. Expects: x0 x1 dx center width d2km + D2KM=$6 + gmt math -T$1/$2/$3 T ${D2KM} MUL $4 SUB $5 DIV 2 POW NEG EXP = +} +function G1 () { # d/dx Gaussian - The Pacific signal. Expects: x0 x1 dx center width d2km + D2KM=$6 + i_A=`gmt math -Q 2 SQRT -0.5 EXP MUL INV =` # Amplitude scaling + gmt math -T$1/$2/$3 T ${D2KM} MUL $4 SUB $5 DIV DUP 2 POW NEG EXP MUL ${i_A} MUL = +} +function G2 () { # d2/dx2 Gaussian - The Compression signal. Expects: x0 x1 dx center width d2km + D2KM=$6 + i_A=`gmt math -Q E =` # Amplitude scaling + gmt math -T$1/$2/$3 T ${D2KM} MUL $4 SUB $5 DIV 2 POW DUP NEG EXP MUL ${i_A} MUL = +} +function synthFZ () { # Combined signal. Expects: x0 x1 dx center width m u A km? + # Evaluate z(x) = A * [m * G1 + (1 - m) * (u * G2 - G0)] + if [ $9 -eq 1 ]; then + D2KM=1 + else + D2KM=111.1950797 + fi + m=$6 + u=$7 + m1=`gmt math -Q 1 ${m} SUB =` # (1-m) + G0 $1 $2 $3 $4 $5 ${D2KM} > /tmp/G0 + G1 $1 $2 $3 $4 $5 ${D2KM} > /tmp/G1 + G2 $1 $2 $3 $4 $5 ${D2KM} > /tmp/G2 + gmt math /tmp/G2 $u MUL /tmp/G0 SUB ${m1} MUL /tmp/G1 ${m} MUL ADD NORM $8 MUL = +} + +. fz_funcs.sh # Load in FZ-specific shell functions +name=fzprof +if [ $# -eq 0 ]; then + version=$(fz_get_version) +cat << EOF >&2 + fzmodeler ${version} - Make and optionally plot a synthetic FZ profile + + Usage: fzmodeler [-A] [-C] [-D//] [-G0|1|2] + [-M] [-N] [-O] [-S] [-T] [-W] [-P] + + OPTIONS: + -A sets FZ asymmetry between "Pacific" (1) and "Atlantic" (0) [0]. + -C sets FZ compression (0-1) [0]. + -D sets domain [-5/5/2m or -100/100/2; see -M]. + -G Only plot the specified G_i component, i = 0-2. + -M means -D is given in degrees/degrees/minutes [km]. + -N sets max VGG amplitude [100]. + -O Run as GMT overlay (i.e., pass -O -K) and send to stdout. + No PDF is made and no datafile is saved. + -P plot to fzprof.pdf. + -S sets FZ shift from origin in km [0]. + -T sets output file prefix [$name]. + Give - to write to stdout. + -V Report on progress [quiet]. + -W sets FZ width in km [25]. + +EOF + exit +fi + +trap $(fz_cleanup 1) 1 2 3 15 # Set interrupt handling +# Default values +verbose=0 +plot=0 +out=0 +asym=0 +comp=0 +code=-1 +X0=0 +amp=100 +width=25 +OL=0 +X=6i/2i +km=1 +while [ ! x"$1" = x ]; do + case $1 + in + -A*) asym=`fz_get_arg $1` # asymmetry + shift;; + -C*) comp=`fz_get_arg $1` # compression + shift;; + -D*) domain=`fz_get_arg $1` # min/max/inc domain + shift;; + -G*) code=`fz_get_arg $1` # 0-2 for G_i + shift;; + -M) km=0; # Domain given in degrees + shift;; + -N*) amp=`fz_get_arg $1` # amplitude + shift;; + -O) OL=1; # Plot as overlay to stdout + plot=1; + shift;; + -P) plot=1; # Plot and make PDF + shift;; + -S*) X0=`fz_get_arg $1`; # FZ offset + shift;; + -T*) name=`fz_get_arg $1` # file prefix + shift;; + -V) verbose=1; # Verbose + shift;; + -W*) width=`fz_get_arg $1` # FZ width + shift;; + -X*) X=`fz_get_arg $1` # Reset plot size + shift;; + *) echo "$0: Unrecognized option $1" 1>&2; # Bad option argument + exit 1;; + esac +done +#-------------- +if [ "X${domain}" = "X" ]; then # Default settings + if [ $km -eq 0 ]; then + domain=-100/100/2 + else + domain=-5/5/2 + fi +fi +if [ "X${name}" = "X-" ]; then + out=1 + name=/tmp/$$ + plot=0 +fi +w=$(echo ${domain} |cut -d'/' -f1) +e=$(echo ${domain} |cut -d'/' -f2) +dm=$(echo ${domain} |cut -d'/' -f3) +if [ ${km} -eq 0 ]; then + dx=$(gmt math -Q ${dm} 60 DIV =) + tick=2f1 +else + dx=${dm} + tick=50f10 +fi + +if [ ${code} -eq 0 ]; then # Gaussian - The Atlantic signal + G0 ${w} ${e} ${dx} ${X0} ${width} ${km} ${amp} > ${name}.txt 2> /dev/null +elif [ ${code} -eq 1 ]; then # d/dx Gaussian - The Pacific signal + G1 ${w} ${e} ${dx} ${X0} ${width} ${km} ${amp} > ${name}.txt 2> /dev/null +elif [ ${code} -eq 2 ]; then + G2 ${w} ${e} ${dx} ${X0} ${width} ${km} ${amp} > ${name}.txt 2> /dev/null +else # The blend of all + (synthFZ ${w} ${e} ${dx} ${X0} ${width} ${asym} ${comp} ${amp} ${km} > ${name}.txt) 2> /dev/null +fi +if [ ${plot} -eq 1 ]; then + if [ ${OL} -eq 1 ]; then + gmt psxy -R${w}/${e}/-${amp}/${amp} -JX${X} -Bx${tick}g100 -By50f10g50 -BWSne ${name}.txt -W2p -O -K + rm -f ${name}.txt + else + gmt begin ${name} pdf + gmt plot -R${w}/${e}/-${amp}/${amp} -JX${X} -Bafg -BWSne ${name}.txt -W2p + gmt end show + if [ $verbose -eq 1 ]; then + echo "$0: Synthetic FZ profile plotted in file ${name}.pdf" + echo "$0: Synthetic FZ profile stored in file ${name}.txt" + fi + fi +elif [ ${verbose} -eq 1 ]; then + if [ ${out} -eq 1 ]; then + cat ${name}.txt + echo "$0: Synthetic FZ profile written to stdout" + rm -f ${name}.txt + else + echo "$0: Synthetic FZ profile stored in file ${name}.txt" + fi +fi +if [ ${out} -eq 1 ]; then + cat ${name}.txt + rm -f ${name}.txt +fi diff --git a/src/gsfml/fzprofiler b/src/gsfml/fzprofiler new file mode 100755 index 00000000000..a7d91829e2c --- /dev/null +++ b/src/gsfml/fzprofiler @@ -0,0 +1,261 @@ +#!/bin/bash +#-------------------------------------------------------------------- +# Copyright (c) 2015-2023 by P. Wessel +# See LICENSE.TXT file for copying and redistribution conditions. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; version 3 or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# Contact info: http://www.soest.hawaii.edu/PT/GSFML +#-------------------------------------------------------------------- +# Bash script to make a single large-format GMT plot of all cross- +# profiles for a given FZ segment. We select the dimensions of a +# single profile panel and scale up to determine the custom paper +# needed. +# +# Author: Paul Wessel +# Date: 01-DEC-2023 (Requires GMT >= 6) +# Mode: GMT classic mode +#-------------------------------------------------------------------- + +. fz_funcs.sh # Load in FZ-specific shell functions +if [ $# -eq 0 ]; then + version=`fz_get_version` +cat << EOF >&2 + fzprofiler $version - Plot one or all FZ cross-profiles + + Usage: fzprofiler [-H[c|i]] [-I] [-L] [-N] [-T] [-V] [-W[c|i]] + + OPTIONS: + -H specify the height of each profile plot. + Append units c or i [Default uses PROJ_LENGTH_UNIT]. + -I Picks a single profile ID to plot (first is 0) [all]. + -L sets labeling increment for profiles [1]. + -N sets the number of plot columns [1]. + -T sets the profile prefix [fztrack]. + -V Report on progress [quiet]. + -W specify the width of each profile plot. + Append units c or i [Default uses PROJ_LENGTH_UNIT]. + +EOF + exit +fi + +trap 'fz_cleanup 1' 1 2 3 15 # Set interrupt handling +#default values +ncols=1 +W=6 +H=2 +inc=1 +P=-1 +verbose=0 +prefix=fztrack + +while [ ! x"$1" = x ]; do + case $1 + in + -W*) W=`fz_get_dim $1` # Width of each sub-panel with one profile + shift;; + -H*) H=`fz_get_dim $1` # Height of each sub-panel with one profile + shift;; + -I*) P=`fz_get_arg $1`; # Specific profile + shift;; + -L*) inc=`fz_get_arg $1`; # Profile increment + shift;; + -N*) ncols=`fz_get_arg $1`; # Number of sub-panel columns + shift;; + -T*) prefix=`fz_get_arg $1` # Get file prefix + shift;; + -V) verbose=1; # Gave a VGG grid + shift;; + -*) echo "$0: Unrecognized option $1" 1>&2; # Bad option argument + exit 1;; + esac +done + +XFILE=${prefix}_cross.txt # Cross-profiles file +# Make sure we convert to inches +. ${prefix}_par.txt # Read and assign parameters for these profiles +#------------------------------------------------------------------------------------------------------ +# All dimensions are now in inches, regardless of what the user's units are. +# Cross-profiles have lon,lat,dist,azimuth,vgg,age,fzdist columns. +# Assign variables and calculate dimensions (inches used throughout) +#------------------------------------------------------------------------------------------------------ +space=0.50 # Space between columns of panels +ymargin=0.75 # Bottom margin +xmargin=1 # Left margin +zone=`gmt math -Q ${CORR_WIDTH} 0.5 MUL =` # half-width of central corridor +n_cross=`gmt convert -L ${XFILE} | wc -l` # Number of cross-profiles +ndig=`gmt math -Q ${n_cross} LOG10 FLOOR 1 ADD =` # Number of digits to use for running numbers +dmin=`gmt math -Q ${CROSS_LENGTH} 0.5 MUL NEG =` # Only plot the central 50% of the cross profiles +dmax=`gmt math -Q ${CROSS_LENGTH} 0.5 MUL =` +gmt info ${XFILE} -C -I2/2/2/5/10/10/10/10/10 > $$.info # Get clean multiples of min/max for each column +vmin=`cut -f9 $$.info` # Low VGG bounds +vmax=`cut -f10 $$.info` # High VGG bounds +vinc=`gmt math -Q ${vmax} ${vmin} SUB 50 DIV CEIL 10 MUL =` # VGG scale bar length is ~1/5 the range, in multiples of 10 +vinc2=`gmt math -Q ${vinc} 2 DIV =` # +- half vinc +amin=`cut -f11 $$.info` # Low age bounds +amax=`cut -f12 $$.info` # High age bounds +range=`gmt math -Q ${vmax} ${vmin} SUB =` # VGG range for this panel +if [ ${amin} = "NaN" ]; then + got_age=0 +else + got_age=1 + arange=`gmt math -Q ${amax} ${amin} SUB =` # Age range for this panel + am=`gmt math -Q ${amin} ${arange} 0.5 MUL ADD =` # Mid-age value + am1=`gmt math -Q ${am} 5 SUB =` # am1/am2 are 1- Myr apart and will serve as age scale bar + am2=`gmt math -Q ${am} 5 ADD =` + atxt=" and ${arange} Myr (dashed orange line)" +fi +if [ $P -ge 0 ]; then # Selected to plot a single profile + nrows=1 # Obviously only a single row + single=1 # TRUE for this case + txt=" $P" # Text identifying the profile +else + P=0 # Do all profiles + nrows=`gmt math -Q ${n_cross} ${inc} DIV ${ncols} DIV CEIL =` # The number of rows depends on how many columns we have and how often we plot + single=0 # FALSE for this case + txt="s" # Text identifying all profiles (plural s) +fi +height=`gmt math -Q ${H} ${nrows} MUL =` # Height of all panels +width=`gmt math -Q ${W} ${ncols} MUL ${ncols} 1 SUB ${space} MUL ADD =` # Width of all plot columns together +width2=`gmt math -Q ${width} 2 ${xmargin} MUL ADD =` # PLot width, including margings +height2=`gmt math -Q ${height} 2 ${ymargin} MUL ADD =` # Plot height, including margins +xu=`gmt math -Q -0.75 1 ${xmargin} SUB ADD =` # Placement x for -U logo and label +yu=`gmt math -Q -0.75 1 ${ymargin} SUB ADD =` # Placement y for -U logo and label +VB=`gmt math -Q ${vmax} 0.75 MUL =` # VGG-value to use for placement of blend width indicator symbol +VT=`gmt math -Q ${vmax} 0.50 MUL =` # VGG-value to use for placement of trough width indicator symbol +VD=`gmt math -Q ${vmax} 0.25 MUL =` # VGG-value to use for placement of data width indicator symbol +#------------------------------------------------------- ----------------------------------------------- +# Ready for plotting +if [ $verbose -eq 1 ]; then + echo "fzprofiler: Papersize is ${width2}i by ${height2}i; vertical range per row panel is $range Eotvos${atxt}." >&2 +fi +#------------------------------------------------------------------------------------------------------ +# Draw the outline of the combined rowsxcols panels; add title and -U label, using a custom paper size tailored to fit the plot +gmt begin ${prefix}_cross pdf + gmt basemap -R0/$width/0/$height -Jx1i -Xa${xmargin}i -Ya${ymargin}i -B+gwhite -U/${xu}i/${yu}i/"${prefix}: Cross profile${txt}" + let row=9999 # This will be reset to 1 immediately in the loop below + let col=0 # This will be reset to 1 in the loop. We start from left-most column (1) and work to the right + while [ $P -lt $n_cross ]; do # As long as there are profiles left + if [ $verbose -eq 1 ]; then + echo "fzprofiler: Plotting profile ${P}" >&2 + fi + let row=row+1 # Go to next row (row = 1 is the first row) + if [ ${row} -gt ${nrows} ]; then # Must go to next column + let row=1 # Back to the bottom + let col=col+1 # Move to next column + let frame=1 # Time to plot a basemap again for the entire column + if [ ${col} -gt 1 ]; then # Draw the central d = 0 line for the entire column + gmt basemap -R${dmin}/${dmax}/0/${height} -JX${W}i/${height}i -Bx0g1000 -By0 -Xa${xpos}i -Ya${ymargin}i + fi + fi + xpos=`gmt math -Q $col 1 SUB $W $space ADD MUL $xmargin ADD =` # Determines the x position of the current panel's LL corner + ypos=`gmt math -Q $nrows $row SUB $H MUL $ymargin ADD =` # Determines the y position of the current panel's LL corner + xposL=`gmt math -Q $xpos 0.15 SUB =` # We will plot a VGG scale bar 0.15 inches to the left of each panel + xposR=`gmt math -Q $xpos 0.15 ADD =` # We will plot an Age scale bar 0.15 inches to the right of each panel + if [ ${frame} -eq 1 ]; then # Plot the central corridor in light blue color, annotate the distance axis + gmt plot -Glightblue -Bx20f5 -By0 -BwSne -Xa${xpos}i -Ya${ymargin}i --FONT_ANNOT_PRIMARY=10 --FONT_LABEL=14 <<- EOF + -${zone} 0 + ${zone} 0 + ${zone} $height + -${zone} $height + EOF + let frame=0 + fi + gmt convert -Q${P} ${XFILE} > $$.raw # Extract the profile to plot (includes the segment header) + header=`head -1 $$.raw` # Get this cross profile's header + # Pull out several parameter values from the segment header, via strings such as WD=25 + + az=`fz_get_item "${header}" az` # Extract the azimuth of this profile + mb=`fz_get_item "${header}" mb` # Extract the blend parameter for best-fitting model + OB=`fz_get_item "${header}" OB` # Extract the offset parameter for best-fitting blend model + WB=`fz_get_item "${header}" WB` # Extract the width parameter for best-fitting blend model + UB=`fz_get_item "${header}" UB` # Extract the compression parameter for best-fitting blend model + OT=`fz_get_item "${header}" OT` # Extract the offset parameter for best-fitting trough model + WT=`fz_get_item "${header}" WT` # Extract the width parameter for best-fitting trough model + UT=`fz_get_item "${header}" UT` # Extract the compression parameter for best-fitting trough model + OD=`fz_get_item "${header}" OD` # Extract trough location parameter for the data + WD=`fz_get_item "${header}" WD` # Extract the width estimate of the data trough + OE=`fz_get_item "${header}" OE` # Extract the offset parameter for best-fitting edge model + WT2=`gmt math -Q $WT 0.5 MUL =` # Compute half-widths + WB2=`gmt math -Q $WB 0.5 MUL =` + northsouth=`gmt math -Q $az ABS 45 LE =` # Determine if profile is mostly E-W or S-N + if [ ${northsouth} -eq 1 ]; then # It is mostly S to N + L="S" + R="N" + else # It is mostly E to W + L="W" + R="E" + fi + # Build a polygon the plot as lightcyan the +- 2 sigma uncertainty on the trough location OT + echo ${OT} ${WT} ${vmin} ${vmax} | awk '{printf "%g\t%s\n%g\t%s\n%g\t%s\n%g\t%s\n", $1-0.5*$2/3, $3, $1+0.5*$2/3, $3, $1+0.5*$2/3, $4, $1-0.5*$2/3, $4}' > $$.w + y=`gmt math -Q ${P} ${H} MUL 1 ADD =` + # Plot the uncertainty area on OT as lightcyan + gmt plot -R${dmin}/${dmax}/${vmin}/${vmax} -JX${W}i/${H}i -Bx0 -Byf1000g1000 -Bwe $$.w -Glightcyan -Xa${xpos}i -Ya${ypos}i + # Plot the data as red circles connected by a thin dotted red line + gmt plot $$.raw -i2,4 -Wthinnest,red,. -Xa${xpos}i -Ya${ypos}i + gmt plot $$.raw -i2,4 -Sc0.04i -Gred -Xa${xpos}i -Ya${ypos}i + # Plot the trough model as thin solid green3 line + gmt plot $$.raw -i2,7 -B0 -Bsn -Wthin,green3 -Xa${xpos}i -Ya${ypos}i --MAP_FRAME_PEN=faint + # Plot the blend model as thin blue line + gmt plot $$.raw -i2,8 -Wthin,blue -Xa${xpos}i -Ya${ypos}i + if [ ${got_age} -eq 1 ]; then + # Plot the crustal ages as thin dashed orange line + gmt plot $$.raw -i2,5 -R${dmin}/${dmax}/${amin}/${amax} -Wthin,orange,- -Xa${xpos}i -Ya${ypos}i + fi + # Place width error-bar and trough symbol for the blend model + echo ${OB} ${VB} ${WB2} | gmt plot -R${dmin}/${dmax}/${vmin}/${vmax} -Ex+pthin,blue -Gblue -Wthinnest -Si0.075i -Xa${xpos}i -Ya${ypos}i + # Place width error-bar and trough symbol for the trough model + echo ${OT} ${VT} ${WT2} | gmt plot -Ex+pthin,green3 -Wthinnest -Si0.075i -Ggreen3 -Xa${xpos}i -Ya${ypos}i + # Place width error-bar and max-slope (edge) symbol for the blend model + echo ${OE} 0.0 | gmt plot -Wthinnest -Sc0.075i -Gblue -Xa${xpos}i -Ya${ypos}i + if [ "${WD}" = "NaN" ] || [ "${WD}" = "nan" ]; then # Cannot do it + echo "WD is NaN - skipped" >&2 + else + WD2=`gmt math -Q $WD 0.5 MUL =` # Compute half-width + echo ${OD} ${VD} ${WD2} | gmt plot -Ex+pthin,red -Wthinnest -Si0.075i -Gred -Xa${xpos}i -Ya${ypos}i + fi + # Place profile ID in upper-left corner of panel + echo "${dmin} ${vmax} LT ${P}" | gmt text -Dj0.05i -C0.01i -F+f7p,Helvetica,white+a0+j -Gblack -To -W0.5p -Xa${xpos}i -Ya${ypos}i + # Write blend value in upper-right corner of panel + echo "${dmax} ${vmax} RT @;green3;u@-t@- = ${UT}@;; @;blue;u@-b@- = $UB m = ${mb}@;;" | gmt text -Dj0.05i -F+f7p,Helvetica+a0+j -Xa${xpos}i -Ya${ypos}i + # Write the W-E or S-N labels on left/right side of the top of the panel + echo "${dmin} ${vmax} LT ${L}" | gmt text -Dj0.05i/0.2i -F+f12p,Helvetica-Bold+a0+j -Xa${xpos}i -Ya${ypos}i + echo "${dmax} ${vmax} RT ${R}" | gmt text -Dj0.05i/0.2i -F+f12p,Helvetica-Bold+a0+j -Xa${xpos}i -Ya${ypos}i + # Draw $vinc Eotvos scale bar to the left of the panel + gmt plot -W2p,red -Xa${xposL}i -Ya${ypos}i <<- EOF + ${dmin} -${vinc2} + ${dmin} ${vinc2} + EOF + # Label the VGG scale bar with "$vinc" + echo ${dmin} 0 ${vinc} | gmt text -F+f6p,Helvetica+a0+jCM -C0.01i -Gwhite -To -W0.5p -N -Xa${xposL}i -Ya${ypos}i + if [ ${got_age} -eq 1 ]; then + # Draw 10 Myr scale bar to the right of the panel + gmt plot -R${dmin}/${dmax}/${amin}/${amax} -W2p,orange -Xa${xposR}i -Ya${ypos}i <<- EOF + ${dmax} ${am1} + ${dmax} ${am2} + EOF + # Label the age scale bar with "10" + echo ${dmax} ${am} 10 | gmt text -F+f6p,Helvetica+a0+jCM -C0.01i -Gwhite -To -W0.5p -N -Xa${xposR}i -Ya${ypos}i + fi + if [ ${single} -eq 1 ]; then # Set P to last profile so the loop will exit immediately + P=${n_cross} + else # March on to the next profile + let P=P+inc + fi + done + # Finalize plot by drawing the d = 0 line for the last panel + gmt basemap -R${dmin}/${dmax}/0/${height} -JX${W}i/${height}i -Bx0g1000 -By0 -Xa${xpos}i -Ya${ymargin}i +gmt end show +if [ ${verbose} -eq 1 ]; then + echo "fzprofiler: Final plot is called ${prefix}_cross.pdf" >&2 +fi + +fz_cleanup 1 diff --git a/src/gsfml/gsfml_glue.c b/src/gsfml/gsfml_glue.c new file mode 100644 index 00000000000..4bfe8716c4d --- /dev/null +++ b/src/gsfml/gsfml_glue.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012-2022 by the GMT Team (https://www.generic-mapping-tools.org/team.html) + * See LICENSE.TXT file for copying and redistribution conditions. + */ +/* gmt_gsfml_glue.c populates the external array of this shared lib with + * module parameters such as name, group, purpose and keys strings. + * This file also contains the following convenience functions to + * display all module purposes, list their names, or return keys or group: + * + * int gsfml_module_show_all (void *API); + * int gsfml_module_list_all (void *API); + * int gsfml_module_classic_all (void *API); + * + * These functions may be called by gmt --help and gmt --show-modules + * + * Developers of external APIs for accessing GMT modules will use this + * function indirectly via GMT_Encode_Options to retrieve option keys + * needed for module arg processing: + * + * const char * gsfml_module_keys (void *API, char *candidate); + * const char * gsfml_module_group (void *API, char *candidate); + * + * All functions are exported by the shared gsfml library so that gmt can call these + * functions by name to learn about the contents of the library. + */ + +#include "gmt_dev.h" + +/* Sorted array with information for all GMT gsfml modules */ +static struct GMT_MODULEINFO modules[] = { + {"fzanalyzer", "fzanalyzer", "gsfml", "Analysis of fracture zones using crossing profiles", "DO"}, + {"fzblender", "fzblender", "gsfml", "Produce a smooth blended FZ trace", "DO"}, + {"mlconverter", "mlconverter", "gsfml", "Convert chrons to ages using selected magnetic timescale", "DO"}, + {NULL, NULL, NULL, NULL, NULL} /* last element == NULL detects end of array */ +}; + +/* Pretty print all shared module names and their purposes for gmt --help */ +EXTERN_MSC int gsfml_module_show_all (void *API) { + return (GMT_Show_ModuleInfo (API, modules, "GMT supplemental modules for GSFML", GMT_MODULE_HELP)); +} + +/* Produce single list on stdout of all shared module names for gmt --show-modules */ +EXTERN_MSC int gsfml_module_list_all (void *API) { + return (GMT_Show_ModuleInfo (API, modules, NULL, GMT_MODULE_SHOW_MODERN)); +} + +/* Produce single list on stdout of all shared module names for gmt --show-classic [i.e., classic mode names] */ +EXTERN_MSC int gsfml_module_classic_all (void *API) { + return (GMT_Show_ModuleInfo (API, modules, NULL, GMT_MODULE_SHOW_CLASSIC)); +} + +/* Lookup module id by name, return option keys pointer (for external API developers) */ +EXTERN_MSC const char *gsfml_module_keys (void *API, char *candidate) { + return (GMT_Get_ModuleInfo (API, modules, candidate, GMT_MODULE_KEYS)); +} + +/* Lookup module id by name, return group char name (for external API developers) */ +EXTERN_MSC const char *gsfml_module_group (void *API, char *candidate) { + return (GMT_Get_ModuleInfo (API, modules, candidate, GMT_MODULE_GROUP)); +} diff --git a/src/gsfml/longopt/fzanalyzer_inc.h b/src/gsfml/longopt/fzanalyzer_inc.h new file mode 100644 index 00000000000..6fcfbe224e6 --- /dev/null +++ b/src/gsfml/longopt/fzanalyzer_inc.h @@ -0,0 +1,53 @@ +/*-------------------------------------------------------------------- + * + * Copyright (c) 1991-2023 by the GMT Team (https://www.generic-mapping-tools.org/team.html) + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: www.generic-mapping-tools.org + *--------------------------------------------------------------------*/ + +#ifndef FZANALYZER_INC_H +#define FZANALYZER_INC_H + +/* Translation table from long to short module options, directives and modifiers */ + +static struct GMT_KEYWORD_DICTIONARY module_kw[] = { + /* separator, short_option, long_option, + short_directives, long_directives, + short_modifiers, long_modifiers */ + { 0, 'A', "", + "", "", + "", "" }, + { 0, 'C', "", + "", "", + "", "" }, + { 0, 'D', "", + "", "", + "", "" }, + { 0, 'F', "", + "", "", + "", "" }, + { 0, 'I', "", + "", "", + "", "" }, + { 0, 'S', "", + "", "", + "", "" }, + { 0, 'T', "", + "", "", + "", "" }, + { 0, 'W', "", + "", "", + "", "" }, + { 0, '\0', "", "", "", "", ""} /* End of list marked with empty option and strings */ +}; +#endif /* !FZANALYZER_INC_H */ diff --git a/src/gsfml/longopt/fzblender_inc.h b/src/gsfml/longopt/fzblender_inc.h new file mode 100644 index 00000000000..a8a13f0f762 --- /dev/null +++ b/src/gsfml/longopt/fzblender_inc.h @@ -0,0 +1,53 @@ +/*-------------------------------------------------------------------- + * + * Copyright (c) 1991-2023 by the GMT Team (https://www.generic-mapping-tools.org/team.html) + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: www.generic-mapping-tools.org + *--------------------------------------------------------------------*/ + +#ifndef FZBLENDER_INC_H +#define FZBLENDER_INC_H + +/* Translation table from long to short module options, directives and modifiers */ + +static struct GMT_KEYWORD_DICTIONARY module_kw[] = { + /* separator, short_option, long_option, + short_directives, long_directives, + short_modifiers, long_modifiers */ + { 0, 'D', "", + "", "", + "", "" }, + { 0, 'E', "", + "", "", + "", "" }, + { 0, 'F', "", + "", "", + "", "" }, + { 0, 'I', "", + "", "", + "", "" }, + { 0, 'Q', "", + "", "", + "", "" }, + { 0, 'S', "", + "", "", + "", "" }, + { 0, 'T', "", + "", "", + "", "" }, + { 0, 'Z', "", + "", "", + "", "" }, + { 0, '\0', "", "", "", "", ""} /* End of list marked with empty option and strings */ +}; +#endif /* !FZBLENDER_INC_H */ diff --git a/src/gsfml/longopt/mlconverter_inc.h b/src/gsfml/longopt/mlconverter_inc.h new file mode 100644 index 00000000000..59e2b8dfc51 --- /dev/null +++ b/src/gsfml/longopt/mlconverter_inc.h @@ -0,0 +1,41 @@ +/*-------------------------------------------------------------------- + * + * Copyright (c) 1991-2023 by the GMT Team (https://www.generic-mapping-tools.org/team.html) + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: www.generic-mapping-tools.org + *--------------------------------------------------------------------*/ + +#ifndef MLCONVERTER_INC_H +#define MLCONVERTER_INC_H + +/* Translation table from long to short module options, directives and modifiers */ + +static struct GMT_KEYWORD_DICTIONARY module_kw[] = { + /* separator, short_option, long_option, + short_directives, long_directives, + short_modifiers, long_modifiers */ + { 0, 'A', "", + "", "", + "", "" }, + { 0, 'G', "", + "", "", + "", "" }, + { 0, 'S', "", + "", "", + "", "" }, + { 0, 'T', "", + "", "", + "", "" }, + { 0, '\0', "", "", "", "", ""} /* End of list marked with empty option and strings */ +}; +#endif /* !MLCONVERTER_INC_H */ diff --git a/src/gsfml/mlconverter.c b/src/gsfml/mlconverter.c new file mode 100644 index 00000000000..9cc342452a2 --- /dev/null +++ b/src/gsfml/mlconverter.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2015-2023 by P. Wessel + * See LICENSE.TXT file for copying and redistribution conditions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * Contact info: http://www.soest.hawaii.edu/PT/GSFML + *-------------------------------------------------------------------- + * + * mlconverter converts chron strings and anomaly end (y|o) to age using + * a magnetic timescale. The input files must be the OGT/GMT-formatted + * ML_*.gmt files distributed by the GSFML project. + * + * Author: Paul Wessel + * Date: 01-DEC-2023 (Requires GMT >= 6) + */ + +#define THIS_MODULE_CLASSIC_NAME "mlconverter" +#define THIS_MODULE_MODERN_NAME "mlconverter" +#define THIS_MODULE_LIB "gsfml" +#define THIS_MODULE_PURPOSE "Convert chrons to ages using selected magnetic timescale" +#define THIS_MODULE_KEYS "DO" +#define THIS_MODULE_NEEDS "" +#define THIS_MODULE_OPTIONS "-:>RVabfghior" + +#include "gmt_dev.h" +#include "fz_analysis.h" +#include "longopt/mlconverter_inc.h" + +#define ML_GEEK2007 0 +#define ML_CK1995 1 +#define ML_GST2004 2 +#define ML_GST2012 3 + +#define ML_NORMAL 0 +#define ML_REVERSE 1 +#define ML_YOUNG 0 +#define ML_OLD 1 + +struct MLCONVERTER_CTRL { + struct A { /* -A */ + bool active; + } A; + struct G { /* -G */ + bool active; + unsigned int mode; + } G; + struct S { /* -S */ + bool active; + } S; + struct T { /* -T[g|c|s] */ + bool active; + unsigned int mode; + } T; +}; + +EXTERN_MSC int gmtlib_append_ogr_item (struct GMT_CTRL *GMT, char *name, unsigned int type, struct GMT_OGR *S); +EXTERN_MSC void gmtlib_write_ogr_header (FILE *fp, struct GMT_OGR *G); + +static void *New_Ctrl (struct GMT_CTRL *GMT) { /* Allocate and initialize a new control structure */ + struct MLCONVERTER_CTRL *C; + + C = gmt_M_memory (GMT, NULL, 1, struct MLCONVERTER_CTRL); + + /* Initialize values whose defaults are not 0/false/NULL */ + return (C); +} + +static void Free_Ctrl (struct GMT_CTRL *GMT, struct MLCONVERTER_CTRL *C) { /* Deallocate control structure */ + if (!C) return; + gmt_M_free (GMT, C); +} + +static int usage (struct GMTAPI_CTRL *API, int level) +{ + const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE); + if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR); + GMT_Usage (API, 0, "usage: %s [] [-A] [-G[s]] [-S] [-Tc|g|o|s] [%s]\n", name, GMT_V_OPT); + + if (level == GMT_SYNOPSIS) return (GMT_MODULE_SYNOPSIS); + + GMT_Message (API, GMT_TIME_NONE, " OPTIONAL ARGUMENTS:\n"); + + GMT_Usage (API, 1, "\n-A Append metadata to data record as extra columns [Only write lon lat age]."); + GMT_Usage (API, 1, "\n-G Generate an extended OGR/GMT table by appending the crustal age. " + "Append s to repair any lax chron nomenclature, if needed."); + GMT_Usage (API, 1, "\n-S Strict chron nomenclature expected; report any lax use [do the best we can]"); + GMT_Usage (API, 1, "\n-Tc|g|o|s]"); + GMT_Usage (API, -2, "Select a magnetic time scale:"); + GMT_Usage (API, 3, "c: Cande and Kent, 1995."); + GMT_Usage (API, 3, "g: Gee and Kent, 2007 [Default]."); + GMT_Usage (API, 3, "o: Ogg, 2012."); + GMT_Usage (API, 3, "s: Gradstein, 2004."); + GMT_Option (API, "V,."); + + return (GMT_MODULE_USAGE); +} + +static int parse (struct GMTAPI_CTRL *API, struct MLCONVERTER_CTRL *Ctrl, struct GMT_OPTION *options) { + + /* This parses the options provided to grdsample and sets parameters in CTRL. + * Any GMT common options will override values set previously by other commands. + * It also replaces any file names specified as input or output with the data ID + * returned when registering these sources/destinations with the API. + */ + + unsigned int n_files = 0, n_errors = 0; + struct GMT_OPTION *opt = NULL; + + for (opt = options; opt; opt = opt->next) { + switch (opt->option) { + + case '<': /* Skip input files */ + n_files++; + break; + + /* Processes program-specific parameters */ + + case 'A': + n_errors += gmt_M_repeated_module_option (API, Ctrl->A.active); + break; + case 'G': + n_errors += gmt_M_repeated_module_option (API, Ctrl->G.active); + if (opt->arg[0] == 's') Ctrl->G.mode = 1; + break; + case 'S': + n_errors += gmt_M_repeated_module_option (API, Ctrl->S.active); + break; + case 'T': + n_errors += gmt_M_repeated_module_option (API, Ctrl->T.active); + switch (opt->arg[0]) { + case 'c': Ctrl->T.mode = ML_CK1995; break; + case 'g': Ctrl->T.mode = ML_GEEK2007; break; + case 'o': Ctrl->T.mode = ML_GST2012; break; + case 's': Ctrl->T.mode = ML_GST2004; break; + default: + GMT_Message (API, GMT_TIME_NONE, "Error: Not a valid time scale for option -T [%c].\n", (int)opt->arg[0]); + n_errors++; + break; + } + break; + + default: /* Report bad options */ + n_errors += gmt_default_error (API->GMT, opt->option); + break; + } + } + + n_errors += gmt_M_check_condition (API->GMT, Ctrl->A.active && Ctrl->G.active, "GMT SYNTAX ERROR: Cannot use both -A and -G.\n"); + return (n_errors ? GMT_PARSE_ERROR : GMT_NOERROR); +} + +#define bailout(code) {gmt_M_free_options (mode); return (code);} +#define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); return (code); bailout(code);} + +struct ML_CHRON { /* Holds chron and young/old ages */ + double young, old; +}; + +static int ML_lookup (char *chron, char *names[]) +{ + int k = 0; + while (names[k] && strcmp (chron, names[k])) k++; + return (names[k] ? k : -1); +} + +int GMT_mlconverter (void *V_API, int mode, void *args) { + int k, j, n_read = 0, side, polarity, error, n_lax = 0, n_bad = 0; + bool first = true; + + double age, *in = NULL; + + EXTERN_MSC void gmt_str_toupper (char *string); + char record[GMT_BUFSIZ] = {""}, chron[16] = {""}, c, **Cname[2] = {NULL, NULL}, **Cname2[2] = {NULL, NULL}; + static char *Chron_Normal[] = { +#include "Chron_Normal.h" + }; + static char *Chron_Reverse[] = { +#include "Chron_Reverse.h" + }; + static char *Chron_Normal2[] = { +#include "Chron_Normal2.h" + }; + static char *Chron_Reverse2[] = { +#include "Chron_Reverse2.h" + }; + static struct ML_CHRON Geek2007n[] = { +#include "Geek2007n.h" + }; + static struct ML_CHRON Geek2007r[] = { +#include "Geek2007r.h" + }; + static struct ML_CHRON CK1995n[] = { +#include "CK1995n.h" + }; + static struct ML_CHRON CK1995r[] = { +#include "CK1995r.h" + }; + static struct ML_CHRON GST2004n[] = { +#include "GST2004n.h" + }; + static struct ML_CHRON GST2004r[] = { +#include "GST2004r.h" + }; + static struct ML_CHRON GST2012n[] = { +#include "GST2012n.h" + }; + static struct ML_CHRON GST2012r[] = { +#include "GST2012r.h" + }; + struct ML_CHRON *M[2] = {NULL, NULL}; + struct GMT_RECORD *In = NULL, *Out = NULL; + struct MLCONVERTER_CTRL *Ctrl = NULL; + struct GMT_OPTION *options = NULL; + struct GMT_CTRL *GMT = NULL, *GMT_cpy = NULL; + struct GMTAPI_CTRL *API = gmt_get_api_ptr (V_API); /* Cast from void to GMTAPI_CTRL pointer */ + + /*----------------------- Standard module initialization and parsing ----------------------*/ + + if (API == NULL) return (GMT_NOT_A_SESSION); + if (mode == GMT_MODULE_PURPOSE) return (usage (API, GMT_MODULE_PURPOSE)); /* Return the purpose of program */ + options = GMT_Create_Options (API, mode, args); if (API->error) return (API->error); /* Set or get option list */ + + if ((error = gmt_report_usage (API, options, 0, usage)) != GMT_NOERROR) bailout (error); /* Give usage if requested */ + + /* Parse the program-specific arguments */ + + if ((GMT = gmt_init_module (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_KEYS, THIS_MODULE_NEEDS, module_kw, &options, &GMT_cpy)) == NULL) + bailout (API->error); /* Save current state */ + if (GMT_Parse_Common (API, THIS_MODULE_OPTIONS, options)) Return (API->error); + Ctrl = New_Ctrl (GMT); /* Allocate and initialize a new control structure */ + if ((error = parse (API, Ctrl, options))) Return (error); + + /*---------------------------- This is the mlconverter main code ----------------------------*/ + + switch (Ctrl->T.mode) { /* Set pointer to selected timescale young/old tables */ + case ML_GEEK2007: + M[ML_NORMAL] = Geek2007n; + M[ML_REVERSE] = Geek2007r; + break; + case ML_CK1995: + M[ML_NORMAL] = CK1995n; + M[ML_REVERSE] = CK1995r; + break; + case ML_GST2004: + M[ML_NORMAL] = GST2004n; + M[ML_REVERSE] = GST2004r; + break; + case ML_GST2012: + M[ML_NORMAL] = GST2012n; + M[ML_REVERSE] = GST2012r; + break; + } + Cname[ML_NORMAL] = Chron_Normal; /* Set pointer to the two timescale chron with strict names */ + Cname[ML_REVERSE] = Chron_Reverse; + Cname2[ML_NORMAL] = Chron_Normal2; /* Set pointer to the two timescale chron with uppercase/no period/hyphen names */ + Cname2[ML_REVERSE] = Chron_Reverse2; + + GMT->current.setting.io_header[GMT_OUT] = true; /* To allow writing of headers */ + Out = gmt_new_record (GMT, NULL, record); + + /* We know which columns are geographical */ + GMT->current.io.col_type[GMT_IN][GMT_X] = GMT->current.io.col_type[GMT_OUT][GMT_X] = GMT_IS_LON; + GMT->current.io.col_type[GMT_IN][GMT_Y] = GMT->current.io.col_type[GMT_OUT][GMT_Y] = GMT_IS_LAT; + + if ((error = GMT_Init_IO (API, GMT_IS_DATASET, GMT_IS_POINT, GMT_IN, GMT_ADD_DEFAULT, 0, options))) Return (error); /* Register data input */ + if ((error = GMT_Init_IO (API, GMT_IS_DATASET, GMT_IS_TEXT, GMT_OUT, GMT_ADD_DEFAULT, 0, options))) Return (error); /* Establishes data output */ + if ((error = GMT_Begin_IO (API, GMT_IS_DATASET, GMT_IN, GMT_HEADER_ON))) Return (error); /* Enables data input and sets access mode */ + if ((error = GMT_Begin_IO (API, GMT_IS_DATASET, GMT_OUT, GMT_HEADER_ON))) Return (error); /* Enables data output and sets access mode */ + if ((error = GMT_Set_Columns (API, GMT_OUT, 0, GMT_COL_FIX)) != GMT_NOERROR) Return (error); /* Only text records here */ + + do { /* Keep returning records until we reach EOF */ + if ((In = GMT_Get_Record (API, GMT_READ_DATA, NULL)) == NULL) { /* Read next record, get NULL if special case */ + if (gmt_M_rec_is_error (GMT)) /* Bail if there are any read errors */ + Return (GMT_RUNTIME_ERROR); + if (gmt_M_rec_is_any_header (GMT)) /* Skip all headers */ + continue; + if (gmt_M_rec_is_eof (GMT)) /* Reached end of file */ + break; + } + + /* Data record to process */ + + n_read++; + in = In->data; + + if (Ctrl->G.active && first) { /* Write out new OGR file based on the metadata and just echo the data record */ + gmtlib_append_ogr_item (GMT, "AnomalyAge", GMT_DOUBLE, GMT->current.io.OGR); + gmtlib_write_ogr_header (API->object[API->current_item[GMT_OUT]]->fp, GMT->current.io.OGR); + first = false; + } + + /* Here we have a data record and the OGR has been parsed */ + + c = GMT->current.io.OGR->tvalue[1][0]; + side = (c == 'y' || c == 'Y') ? ML_YOUNG : ML_OLD; + c = GMT->current.io.OGR->tvalue[0][strlen(GMT->current.io.OGR->tvalue[0])-1]; + polarity = (c == 'n' || c == 'N') ? ML_NORMAL : ML_REVERSE; + strcpy (chron, GMT->current.io.OGR->tvalue[0]); + k = ML_lookup (chron, Cname[polarity]); /* Try exact name standard */ + if (k == -1) { /* Did not find this. Try again without any dots or hyphens */ + k = j = 0; while ((c = GMT->current.io.OGR->tvalue[0][k++])) if (!(c == '.' || c == '-')) chron[j++] = c; + chron[j] = 0; + gmt_str_toupper (chron); + k = ML_lookup (chron, Cname2[polarity]); /* Try lax standard */ + if (k >= 0) { /* Report the problem */ + strcpy (chron, Cname[polarity][k]); + if (Ctrl->S.active) { /* Refuse to convert a lax chron */ + GMT_Report (API, GMT_MSG_NORMAL, "File has lax chron %s but standard says %s\n", GMT->current.io.OGR->tvalue[0], Cname[polarity][k]); + k = -1; + } + n_lax++; + } + } + if (k == -1) { /* Did not find this either */ + age = -1.0; + n_bad++; + strcpy (chron, GMT->current.io.OGR->tvalue[0]); + } + else { + age = (side == ML_YOUNG) ? M[polarity][k].young : M[polarity][k].old; + } + if (age < 0.0) age = GMT->session.d_NaN; + + if (Ctrl->G.active) { /* Write out a new OGR record based on the metadata and just echo the data record */ + record[0] = 0; /* Clean muzzle */ + strcat (record, "# @D"); /* OGR metadata record */ + record[0] = '#'; record[1] = ' '; record[2] = 0; /* Start a comment */ + strcat (record, (Ctrl->G.mode) ? chron : GMT->current.io.OGR->tvalue[0]); + for (k = 1; k < 6; k++) { + strcat (record, "|"); + strcat (record, GMT->current.io.OGR->tvalue[k]); + } + strcat (record, "|"); + gmt_add_to_record (GMT, record, age, GMT_Z, GMT_OUT, 0); /* Format our output age value */ + GMT_Put_Record (API, GMT_WRITE_TABLE_HEADER, record); /* Write this to output */ + GMT_Put_Record (API, GMT_WRITE_DATA, Out); /* Write this to output */ + } + else { + record[0] = 0; /* Clean muzzle */ + gmt_add_to_record (GMT, record, in[GMT_X], GMT_X, GMT_OUT, 2); /* Format our longitude */ + gmt_add_to_record (GMT, record, in[GMT_Y], GMT_Y, GMT_OUT, 2); /* Format our latitude */ + gmt_add_to_record (GMT, record, age, GMT_Z, GMT_OUT, 0); /* Format our output age value */ + if (Ctrl->A.active) {/* Append record */ + for (k = 0; k < 6; k++) { + strcat (record, GMT->current.setting.io_col_separator); + strcat (record, GMT->current.io.OGR->tvalue[k]); + } + } + GMT_Put_Record (API, GMT_WRITE_TEXT, Out); /* Write this to output */ + } + } while (true); + + gmt_M_free (GMT, Out); + + if ((error = GMT_End_IO (API, GMT_IN, 0))) Return (error); /* Disables further data input */ + if ((error = GMT_End_IO (API, GMT_OUT, 0))) Return (error); /* Disables further data input */ + + GMT_Report (API, GMT_MSG_NORMAL, "Encountered a total of %ld chrons\n", n_read); + if (n_bad) GMT_Report (API, GMT_MSG_NORMAL, "Encountered %ld chrons that could not be converted to age with current timescale\n", n_bad); + if (n_lax) GMT_Report (API, GMT_MSG_NORMAL, "Encountered %ld chrons that failed to conform to strict chron nomenclature\n", n_lax); + + Return (GMT_NOERROR); +} diff --git a/src/pstext.c b/src/pstext.c index 053abff2467..28e6aa8cb85 100644 --- a/src/pstext.c +++ b/src/pstext.c @@ -292,7 +292,7 @@ static int usage (struct GMTAPI_CTRL *API, int level) { const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE); if (level & PSTEXT_SHOW_FONTS) show_fonts = true, level -= PSTEXT_SHOW_FONTS; /* Deal with the special bitflag for showing the fonts */ if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR); - GMT_Usage (API, 0, "usage: %s [] %s %s [-A] [%s] [-C[/][+tc|C|o|O]] [-D[j|J][/][+v[]]] " + GMT_Usage (API, 0, "usage: %s [
] %s %s [-A] [%s] [-C[[/]][+tc|C|o|O]] [-D[j|J][/][+v[]]] " "[-F[+a[]][+c[]][+f[]][+h|l|r[]|+t|+z[]][+j[]]] %s " "[-G[][+n]] [-L] [-M] [-N] %s%s[-Ql|u] [-S[//][]] [%s] [%s] [-W] [%s] [%s] [-Z] " "[%s] %s[%s] [%s] [%s] [-it] [%s] [%s] [%s] [%s] [%s] [%s]\n", @@ -341,9 +341,9 @@ static int usage (struct GMTAPI_CTRL *API, int level) { GMT_Message (API, GMT_TIME_NONE, "\n OPTIONAL ARGUMENTS:\n"); GMT_Usage (API, 1, "\n-A Angles given as azimuths; convert to directions using current projection."); GMT_Option (API, "B-"); - GMT_Usage (API, 1, "\n-C[/][+tc|C|o|O]"); + GMT_Usage (API, 1, "\n-C[[/]][+tc|C|o|O]"); GMT_Usage (API, -2, "Set the clearance between characters and surrounding box. Only used " - "if -W has been set. Append units {%s} or %% of fontsize [%d%%]. " + "if -W has been set. If is not given it equals . Append units {%s} or %% of fontsize [%d%%]. " "Optionally append +t when -G and/or -W is used. Append a shape:", GMT_DIM_UNITS_DISPLAY, GMT_TEXT_CLEARANCE); GMT_Usage (API, 3, "c: Concave rectangle (requires -M)."); GMT_Usage (API, 3, "C: Convex rectangle (requires -M).");