Closed MarkWieczorek closed 4 years ago
Yes, that's a big limitation of the shift_origin() function. You can't use it as your first plot command, because it needs to know projection (-J) and region (-R) from the history.
shift_origin()
is a wrapper of GMT command gmt plot -T -Xxshift -Yyshift
, so it required -J and -R set before calling the function.
I thought the function can be improved by wrapping another GMT command
gmt plot -JX1c -R0/1/0/1 -T -Xxshift -Yyshift
then shift_origin() will have its own -J and -R, so it can be used as the first call of a PyGMT figure. However, the command above will overwrite the -J and *-R** settings in gmt.history.
Setting GMT_HISTORY to false, i.e., the command below, should avoid overwriting the old settings, but it doesn't works as I expect.
gmt plot -JX1c -R0/1/0/1 -T -Xxshift -Yyshift --GMT_HISTORY=false
I've opened an issue (https://github.com/GenericMappingTools/gmt/issues/3643) and see if it's a GMT bug.
For my use case, I would be ok if shift_origin
did nothing if it was operating on a blank figure for the first time.
I have a custom plotting routine, and it takes as input a prexisting fig and optional X and Y offsets. In practice, whenever you would call the function the first time, X and Y would be None, or zero. Of course, I can easily work around this in my own code, but as a fallback option, pygmt doing nothing would be better than crashing!
Yes, I agree. It need to be improved. Let's wait for the feedback from upstream GMT first.
There is no workaround for GMT 6.1.0. PR #536 fixes the broken link in the documentation and also documents the limitation of this function.
In GMT>=6.1.1, gmt plot -T
no longer required -R and -J (see the fix in https://github.com/GenericMappingTools/gmt/pull/3672), then it should work as expected.
This issue is marked as "upstream". When PyGMT bumps the minimum required GMT version to GMT>=6.1.1, we should add a test for it and close the issue.
I just tested shift_origin
using the new GMT PRs, and it is mostly working. Nevertheless, there is still a problem when calling shift origin with values of zero before creating the first image. In essence, it appears that shift_origin()
in this case performs an absolute shift, as opposed to a relative shift. Even when you append r
to force this to be a relative shift, shift_origin performs an absolute shift.
And as far as I know, the current origin of the first plot is not (0, 0), but is rather shifted a small amount (0+dx, 0+dy) so that the labels aren't cropped. The documentation states that
prepend r [Default] to move the origin relative to its current location.
fig = pygmt.Figure()
fig.basemap(J='X10/5', R='0/360/-90/90', B='a30f30')
fig2 = pygmt.Figure()
fig2.shift_origin(xshift='0i', yshift='0i')
fig2.basemap(J='X10/5', R='0/360/-90/90', B='a30f30')
fig3 = pygmt.Figure()
fig3.shift_origin(xshift='r0i', yshift='r0i')
fig3.basemap(J='X10/5', R='0/360/-90/90', B='a30f30')
fig.savefig('default.png')
fig2.savefig('shift-zero.png')
fig3.savefig('shift-zero-r.png')
And as far as I know, the current origin of the first plot is not (0, 0), but is rather shifted a small amount (0+dx, 0+dy) so that the labels aren't cropped.
You're right. In classic mode, the dx and dy are 72 points (i.e., 1 inch). In modern mode, I believe they're 5 inches.
The three figures you shown are expected from GMT CLI.
For GMT, the first plotting command is very special. If no -X and -Y are used, the default origin is (72p, 72p). You can think that -Xr1i and -Yr1i are automatically added to the first plotting command in this case. However, if you gives -X and/or -Y in the first plotting command, they override the default values. So your -Xr0i and -Yr0i actually put the plot origin at (0,0), and the left and bottom labels are all cropped.
This is how GMT does for a long time. PyGMT can do nothing here, because PyGMT don't know if this is the first plotting command or not (although maybe we can add the counter). I'm not sure what GMT can do without backward incompatibility. @PaulWessel
Yep. Classic GMT is tied to the concept of a sheet of paper, and if you move off it that things get clipped. With modern mode we basically have no paper size (but it is there, just limited to 11x11 meters by ghostscript) and we decided to let the origin be at (5i,5i) to ensure no surprises. But even that is not foolproof. If you make your first plot and then move negatively down/left you will eventually hit the paper edge, and 5 inches is not particularly large if you are thinking in terms of paper dimensions. Perhaps we should use (1m,1m) instead so any surprise would only affect people making plots that are several meters in dimensions. We also had trouble with various bugs in ghostscript that defeated our margin settings but I think we are past that now. I think the GMT developers should consider setting that margin to (1m,1m).
However, if you gives -X and/or -Y in the first plotting command, they override the default values.
Ok. But that behavior is undocumented and not consistent with the documentation:
Prepend r for shift relative to current point (default)... prepend f to position relative to lower left corner of page.
The default is thus to always use relative offsets, so why not just use relative offsets with respect to the default origin for the first plot ? If you really wanted to place the plot at (0, 0), you would use -Xf0 -Yf0
.
I just looked at the docs and to me I think we state the case that the default shift is 0,0 unless it is the first command and then it is 72p. Those are the defaults. If you give -X0 - Y0 on the first plot then stuff fill fall off the page in classic mode. Your suggestion is not wrong, but it would be a major backwards compatibility break. We dealt with many of those breaks by introducing modern mode.
Your suggestion is not wrong, but it would be a major backwards compatibility break. We dealt with many of those breaks by introducing modern mode.
Can we introduce the change for modern mode (non-PS output) only?
Sorry if I missed the point but with a 5 inch margin already being cropped when making non-PS output, the initial origin is arbitrary anyway now so what would be achieved?
the initial origin is arbitrary anyway
I believe that's not true if you use -X0 and -Y0 in the first command. -X0 -Y0 moves the default plot origin from (5i,5i) to (0,0) in modern mode.
OK, if that is the case then we have a problem.
I just looked at the docs and to me I think we state the case that the default shift is 0,0 unless it is the first command and then it is 72p. Those are the defaults. If you give -X0 - Y0 on the first plot then stuff fill fall off the page in classic mode. Your suggestion is not wrong, but it would be a major backwards compatibility break. We dealt with many of those breaks by introducing modern mode.
Ok. I think I understand what is happening. For the first plot, the default origin is set to (0,0). Then, if you don't specify -X
and -Y
(which you probably wouldn't under normal circumstances) the values of -Xr72p -Yr72p
are passed in order to shift the plot origin to (72p, 72p).
My mistake was thinking that the default origin of the first plot was set to (72p, 72p), and that by specifying -Xr0
nothing would happen as there would be a 0p relative shift with respect to (72p, 72p).
Let me stress that this issue is not important to me! Nevertheless, one potential way to clarify things might be to (1) set the default origin to (72p, 72p), and (2) not to pass -Xr72p -Yr72p
as default values for the first plot. Please don't waste your time on this unless you think it is important :)
No worries, Mark.
The method shift origin does not work. This simple example never terminates in ipython
In a jupyter notebook, using shift origin instead kills the kernel and provides this message:
In addition to this, there is a broken link in the web documentation to a this page in gmt:
pygmt: last commit gmt: 6.1