GenericMappingTools / gmt

The Generic Mapping Tools
https://www.generic-mapping-tools.org
Other
853 stars 357 forks source link

Discussion: Improve -B for GMT 6 via long-format options #254

Open PaulWessel opened 5 years ago

PaulWessel commented 5 years ago

The complicated -B option has been with us since GMT 1. In GMT 5 we broke it up into several -B options that set different aspects of basemap specifications. However, it remains a very busy and unclear option. Let us see what needs to be set when a basemap is required in GMT:

1. The Canvas/Frame

2. Axes

Each of the axes we selected have many sub-settings. Furthermore, there are potentially two separate annotation/tick/gridline systems per axis: p - primary (Default, closest to axis) and s - secondary (farther from axis). Each system has many settings:

3. Intervals

Draft proposal for discussion:

Introduce additional long-format --option=* options to clarify how to give basemap specifics. They do not replace -B but can be used instead of -B. Like the other long-format options (#230) they will be available to both classic and modern mode.

  1. Canvas/frame:
  1. Axis: (below, int can be none, auto, a numerical value with optional appended unit character, or name of file with custom annotations, tickmarks, and gridspacings) The first set apply to the primary (or only) axes system:

The labels are given their own long option per axis to avoid difficulties in parsing free-form text separated by slashes (which could be part of the text); this is also why --title is a separate option.

The defaults are the same as before but needs a trigger --frame=default (like -Baf is needed today):

--frame= --annotations=auto --ticks=auto --gridlines=none

There is some duplications here: --frame=none is the same as --annotations=none --ticks=none A few simple examples:

    -Baf 
    -BWSne+gred -Baf
    -Bx30f10g5 -By2f1
    -B+glightgray+t"My plot" -Bxaf+l"X-axis" -Byaf+l"Y-axis"

would become

    --frame=default
    --frame=WSen+fill=red
    --annotations=30/2 --ticks=10/1 --gridlines=5/none
    --frame=default+fill=lightgray --xlabel="X-axis" --ylabel="Y-axis" --title="My plot"

Pre-parsing of these long-format options in gmt_init_module will result in a series of corresponding short -B options that the standard GMT parser can handle.

Note that external interfaces may break these down further (e.g., 'x-annotations', [1 3 15 19]) but can then concatenate these separate axis settings to the required --annotations=argument format.

Please give feedback on the chosen long-options and suggest improvements. The goal is to converge on the right set of long-format options and house the parsing of these in the C API and thus relieve the external interfaces from doing tedious parsing when preparing calls to GMT via GMT_Call_Module.

joa-quim commented 5 years ago

I surely like this and I think it will really help the command line users. But I don't see how it can be of use for external interfaces. The fact that longoptions start with -- is a killing feature. One cannot name variables starting with a minus (Julia, Matlab, Python, R, etc), so external wrappers will still need to entirely implement their own parsing.

Sure that, at least in Julia, even without any further changes, it will be possible to say frame="--annotations=30/2 --ticks=10/1 --gridlines=5/none" but again, those -- look awful.

On the other hand frame (or axis, like in matplotlib and other Julia plotting libs) is what I called in Julia to the entire -B option, and here it is used in a much more reduced context, so mixing the two would be very confusing.

--secondary-annotations and alike for the secondary axis is so loooong. An alternative is to introduce a frame2 (or a axes2 like I do in Julia) and then just keep using annotations, ticks, etc to mean specifications of the secondary axis.

PaulWessel commented 5 years ago

Thanks. However, I did not imagine the external interfaces using --. My thought was that they would supply keyword/arguments, e.g., 'frame=WSne+fill=red' or (..., frame, 'WSne+fill=red', ...) and then your parser would add the leading -- when passing the command string to GMT. You would not have to reassemble all these pieces into a valid -B option as they would be done in the C API.

As for the very long --secondary-annotations, etc. Well, to be discussed. One purpose of having long arguments is to make it very clear what they are. This one does, of course, but axis2 requires more documentation. Anyway, perhaps we can have aliases like annotations2 that is the same as secondary-annotations (and --primary-annotations is the same as annotations), for instance.

joa-quim commented 5 years ago

Well, the point for me is that I already wrote a parser that does all that (and more, like allow specifying the axis separately, does not use any + sub-options because they can the their own keyword (this allows expanding pen, etc)).

I was think in proposing to use strncp() in the parser so both annot and annotations would do (same for grid vs gridlines) and that won't work with the annotations2 idea.

PaulWessel commented 5 years ago

Sure, part of the complication is that the GMT team did not have this discussion before the external interface work started. I still think it is a good goal to standardize on a set of keywords and to put as much of any long-format parsing into GMT API as possible. However, I am not sure if it makes sense to decouple modifier arguments into separate options since there will be collisions between two or more pens or colors on the same command line. It would surely complicate the parser to know what module is needing what.

joa-quim commented 5 years ago

Yes, sure that have a standardized name for the keywords is a good thing, but it's more complicated to standardize the rest. For example, in Julia I can (do) have

decorated(n_symbols=5, symbol=:star, symbsize=1, pen=(0.5,:green), fill=:blue, quoted=1)

which is only the argument to-S~. As you see the +p is here expanded in pen=(0.5,:green) and there is no risk to clash with other pens of other args because it's isolated in its context. We cannot do the same in command line.