Center seasonal plot on winter

Hi there (again),

I have a file with monthly values such as :

  • x = 1:12 is Jan, Feb, […]
  • y = corresponding values

I plot a simple bar chart :

gmt plot -R0/13/0/100 myfile.nc?x/y -Sb0.5c

What if I want to center the values around winter (ie starts in May[5] and ends in April[4]) ?

Also, to center the bars and have the month in letter, I do :

cat << EOF > xannots.txt
0.5 ig J
1.5 ig F
2.5 ig M
3.5 ig A
4.5 ig M
5.5 ig J
6.5 ig J
7.5 ig A
8.5 ig S
9.5 ig O
10.5 ig N
11.5 ig D
12.5 ig
EOF

Can you think of a more elegant solution ?

Something like this:

gmt begin myplot pdf,png A+m0.5c
gmt gmtset TIME_EPOCH 2020-04-15T00:00:00
gmt gmtset TIME_UNIT o
gmt gmtset FORMAT_DATE_MAP o
gmt gmtset FORMAT_TIME_PRIMARY_MAP c
gmt gmtset GMT_LANGUAGE UK

gmt plot -JX15t/15 -R2020-05-01/2021-04-30/0/10 -Sb1u \
        -BWSen -Bpxf1Oa1O+l"month" -Bpyf1a2+l"value" \
        -Wthinnest,black -G200 << END
1 10
2 9
3 8
4 5
5 3
6 4
7 8
8 9
9 8
10 9
11 10
12 10
END
gmt end

There are problems with the unit of month, because a month is a variable beast. Either 28, 29, 30 or 31 days. So maybe your “inelegant” solution is better?

Also, look at the GMT_LANGUAGE options so you can make plots with a truly international flavour.

Hi @timhume,

My problem is not really about the xticks, but really on how to wrap the values around the year…

Meaning the first tick indeed starts in May but with the value associated to the 5th month (not the 1st value which is January).
Your solution associates the January “value” to May “tick”.

**What I have in my NetCDF file is : **

(J) (F) (M) (A) (M) (J) (J) (A) (S) (O) (N) (D)
y1 y2 y3 y4 y5 y6 y7 y8 y9 y10 y11 y12

**What I’d like is : **

(M) (J) (J) (A) (S) (O) (N) (D) (J) (F) (M) (A)
y5 y6 y7 y8 y9 y10 y11 y12 y1 y2 y3 y4

I didn’t notice that - I was so focused on the labels!

So the months are simply labelled 1 = Jan, 2 = Feb and so on? You want January to appear after May. For this to make sense on a time axis, January has to have a larger time value than may. I can think of two ways of doing this:

  1. Convert your months to proper dates:
    2020-05-01
    2020-06-01
    .
    .
    .
    2021-01-01
    2021-02-02 and so on

  2. Add 12 to January through April, so your time series goes like this:
    13 yjan
    14 yfeb
    15 ymar
    16 yapr
    5 ymay
    6 yjun
    .
    .
    .
    12 ydec
    And use something like the code I pasted above, but set the EPOCH to 2020-01-01 and plot the region 2020-05-01/2021-04-30/…

Alright, I’ve figured it out.

I use your idea of adding 12 to the month number, here are the different steps for future reference (If @pwessel find the solution useful, I might post-it in the ShowCase section) :

gmt select file.nc?x/y -R1/4/0/100 > TS.txt #extract January to April
gmt math TS.txt -C0 12 ADD = TS.txt #add 12 to first column
gmt select file.nc?x/y -R5/12/0/100 >> TS.txt #append May to December

Now I have a text file like this :

Month Value
13 (J) y1
14 (F) y2
15 (M) y3
16 (A) y4
5 (M) y5
6 (J) y6
12 (D) y12

Then I assigned for each x_value (month number) the letter :

cat << EOF > lab.txt
4.5 ig M
5.5 ig J
6.5 ig J
7.5 ig A
8.5 ig S
9.5 ig O
10.5 ig N
11.5 ig D
12.5 ig J
13.5 ig F
14.5 ig M
15.5 ig A
16.5 ig
EOF
(0.5 added to center the letter between two ticks)

Finally I plot the bar graph :

gmt begin bar_graph
gmt subplot begin 2x2 -Fs10c -M.5c -A(a)+JTL+o-1c/.25c -BWSen
gmt subplot set
gmt plot -R4/17/0/100 TS.txt -Sb1u -Bxclab.txt -Byaf+l"Frequency (%)" -Gred -Wthinnest,black -t50
gmt legend -DjTR+w4c+o5p/5p -F+r4p+pthinnest,gray+gwhite <<- END
S - c 0.25c red thinnest - legend_txt
END
echo titre_txt | gmt text -F+cTR -D0c/0.6c -N
gmt subplot end
gmt end show

rm -f *.txt

I think this is a reasonable solution. A time axis that starts in May and wraps around back to January is not a time axis, and converting the coordinates to actual absolute time is not going to help here.

However, what I can imagine is someone wanting to make a histogram of time-series data over many years and wanting to show the distribution versus month (e.g., average precipitation per month over the last 10 years). Given that the data are real time-series it would be nice if histogram had some option to make the bins periodic over the year so the data would stack. But then we still would be back to how to annotate a now non-absolute time with labels like months, I will ponder these challenges to see if I can think of a simpler solution.

An implicit option based on -Rx1/x2/y1/y2
if x1 > x2
then concatenate [x1 : end] , [start : x2]
?

End and Start could be given as flag in -R too (+wstart,end) ?

No, definitively not that via -R (for lots of under-the-hood reasons). This issue is a little bit like longitudes which are inherently periodic and plotting (370, 0) lands on the same spot as (10,0). Here the period is implicit (360) but for a general case the period would need to be specified. This would be a GMT-wide solution, but not sure if your single example would justify such a development. I am more open to a histogram option to allow such things since there we may have a legitimate need (e.g., averaging/stacking tiime-series over many years). Your data set is a bit artificial and hand-made in this case. Is it averages over many years or just a single year (in which case absolute time would work)?

Over many years in that case … (histogram-ish matlab function using accumarray)

And what about simply a module that would allow to manipulate files the way I did ? (concatenate)

Feel free to comment on my GitHub feature request discussion regarding non-geographic periodic data use in GMT.