-
Notifications
You must be signed in to change notification settings - Fork 368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle matrix via reference for grid input #3829
Conversation
Testing is done via testapi_matrix_360_ref.c Seems to work but raises an issue related to memory freeing. Since the matrix data is only pointed to by the grid, I set the grid alloc_mode to external. However, that also means that the x and y arrays that are created when creating the grid is left unfreed at the end. We could just ignore this rare memory leak or do something about it. One way is to add info to the struct HIDDEN so that we free those arrays even those the matrix is left untouched.
I can confirm that GenericMappingTools/pygmt#515 now works for BTW, there is another grdimage bug from PyGMT (GenericMappingTools/pygmt#390). I thought it's caused by the same reason as GenericMappingTools/pygmt#515. But, this PR works for GenericMappingTools/pygmt#515, not for GenericMappingTools/pygmt#390. |
Could you tell me the grdcut arguments? I assume input is a global grid and the subset is not global? If so then I am not sure why it would break since it would enter the S_obj->region if-test which was there all along. |
Here is the core PyGMT code. It reads the 01d pixel-registered earth relief global grid into an xarray, and extract the subregion of the grid. grid = load_earth_relief(registration="pixel")
grdcut(grid, outgrid=tmpfile.name, region="0/180/0/90") |
PyGMT issue 390 fails since GMT 6.0, and is worse (crashes or black images) in GMT 6.1, and this PR doesn't fix it. |
I see the report for 390 about zmax < zmin. This is puzzling since when we just request header info in grdimage, for a matrix, it scans the entire matrix for min/max to be sure it is set. |
And the grdcut case uses reference or duplicate? |
It usually means zmin=zmax=0.0.
I already know how to debug PyGMT and C code in Xcode. It's just like what you do with Matlab: run a python console, attach the process id, and run PyGMT codes in the Python console and xcode will stop at the breakpoint. But I don't know where to debug, since the C API is too complicated to understand. |
Currently, PyGMT always uses Both |
OK, let me give it a try then. I can check out the pyGMT master on macOS. Can you give me a quick guide for how to install and select my particular GMT build? |
First of all, you need to install PyGMT dependencies and PyGMT itself. PyGMT will tries to find the system GMT library from the LD_LIBRARY_PATH. For debugging purpose, you can just set the environmental variable
then PyGMT will find the GMT library in this path first. In the Python console, you can run following commands to verify your GMT library:
|
I am looking for even more basic info. I dont see anything on the pyGMT site of installing anything. I think I need to install conda which I have not used. Is there an INSTALL page or similar I can just follow? Sorry to be such a newbie. |
PyGMT has an installation page. I think you can follow the instruction, but when installing dependencies:
You can leave the "gmt", because you don't need the gmt package from conda. |
OK, thanks. Do I first install the full Anaconda or is miniconda OK? |
miniconda is OK. |
OK, microconda installed, dependencies installed. How does python find pygmt on import? Must be some path setting since I get errors if i just run python and enter the import command. |
Run
|
|
It seems you're using the base (the default) conda environment. If you follow the PyGMT install instruction, you should have created a new environment called "pygmt". Just run |
Sorry, got side-tracked. OK, verified it found the xcode-built lib. Trying to run a test by copy paste from test_grdcut.py. COUld import os, numby but not pytest which is not found. |
Those tests are designed to be run by pytest. You can use this one instead: import pygmt
from pygmt.datasets import load_earth_relief
grid = load_earth_relief(registration="pixel")
pygmt.grdcut(grid, outgrid="out.grd", region="0/180/0/90") |
Thanks for your help, up and running in Xcode now. |
Does this mean one have to load the full grid first and only than extract a sub-region? Tried to reproduce this on Win but it looks my pygmt doesn't work anymore
Note, I refuse to install condas to make py things work (and it worked already) |
For this example, it's yes. But
Perhaps you're using an old pygmt?
Yes, conda is not necessary for PyGMT. |
Lots of errors there as well and probalby never accessed.
Also fix the region assignment
I've made some additional revisions to this part of the code, especially when we grab the entire matrix. I also applied what we have learned for the matrix duplicate case to the grid duplicate case which I dont think we are using but it was clearly wrong, just like the matrix initially was clearly wrong. Let me know if there is any changes from this on the python side. The tests pass on command line. |
I think your changes have fixed most issues with matrix. Here is one which doesn't make sense to me: import pygmt
from pygmt.datasets import load_earth_relief
grid = load_earth_relief()
fig = pygmt.Figure()
fig.grdimage(grid, region='g', projection='Q0/0/6i', cmap='geo', frame='a90f30g30')
fig.grdimage(grid, region='g', projection='Q180/0/6i', cmap='geo', X='7i', frame='a90f30g30')
fig.savefig("earth.png") The figures are the same, but the longitudes of the right figure are wrong: |
Will have a look. I just added another update but unlikely to affect the case above. |
And this is with REFERENCE in session,py? |
REFERENCE and DUPLICATE give the same wrong results |
Soemthing else I need to set?
|
Yes, when debugging, it seems GMT incorrectly determines the GMT_SHAREDIR, so you need to change GMT_SHAREDIR to the correct GMT/share directory. |
The 180 plot does not work because in this case there is no need for a projection but I cannot rotate the grid without projecting. So need to find a way to set need_to_project to true when the grid is by reference. |
Your example works for now now. Let me know if this branch can be merged and I will remove the WIP. |
Find one more crash with The script reads the file import pygmt
import xarray as xr
pygmt.show_versions()
fig = pygmt.Figure()
fname = pygmt.which("@tut_relief.nc", download='a')
dem = xr.open_dataarray(fname)
fig.grdimage(dem, frame='af', projection='M6i', cmap='geo', shading=True, V='d')
fig.savefig("shading.png") |
Unable to reproduce any crash - plot looks good. Intermittent? |
It always gives me a crash. Anyway, I think this PR already fixes the PyGMT issues 390 and 515, and this PR is already very large. I think we can merge this PR first. Later I can provide a detailed bug report for the crash above. |
Yes, I was going to suggest something like that as well. Better to focus on a specific - this PR solves many things but possibly not all. |
* Handle matrix vai reference for grid input Testing is done via testapi_matrix_360_ref.c Seems to work but raises an issue related to memory freeing. Since the matrix data is only pointed to by the grid, I set the grid alloc_mode to external. However, that also means that the x and y arrays that are created when creating the grid is left unfreed at the end. We could just ignore this rare memory leak or do something about it. One way is to add info to the struct HIDDEN so that we free those arrays even those the matrix is left untouched. * Add PS orig * Update gmt_api.c * Update gmt_grdio.c * Fix output ij * Handle a switch from reference to duplicate * make sure we set min/max when needed and not reset it * use lessons learned from MATRIX/DUPLICATE to GRID/DUPLICATE Lots of errors there as well and probalby never accessed. * Use duplcate for 360 adn ref for 360_ref Also fix the region assignment * Apply same logic for finding min/max as for duplicate * handle non-projection in grdimage when a referenced global grid
* Handle matrix vai reference for grid input Testing is done via testapi_matrix_360_ref.c Seems to work but raises an issue related to memory freeing. Since the matrix data is only pointed to by the grid, I set the grid alloc_mode to external. However, that also means that the x and y arrays that are created when creating the grid is left unfreed at the end. We could just ignore this rare memory leak or do something about it. One way is to add info to the struct HIDDEN so that we free those arrays even those the matrix is left untouched. * Add PS orig * Update gmt_api.c * Update gmt_grdio.c * Fix output ij * Handle a switch from reference to duplicate * make sure we set min/max when needed and not reset it * use lessons learned from MATRIX/DUPLICATE to GRID/DUPLICATE Lots of errors there as well and probalby never accessed. * Use duplcate for 360 adn ref for 360_ref Also fix the region assignment * Apply same logic for finding min/max as for duplicate * handle non-projection in grdimage when a referenced global grid Co-authored-by: Paul Wessel <[email protected]>
The passing of a matrix masquerading as a grid via GMT_IS_DUPLICATE [the default mode] now seems to work. However passing such grids by reference is also allowed, but I suspect there are cases where it cannot be done (since we would need to do something special to the matrix). Testing is done via testapi_matrix_360_ref.c. Seems to work (please verify if this works from PyGMT, @seisman) but raises an issue related to memory freeing. Since the matrix data is only pointed to by the grid, I set the grid alloc_mode to external so both of them do not try to free the memory. However, that also means that the x and y arrays that were created when creating the grid is left at the end. We could just ignore this rare memory leak or do something about it. One way is to add info to the struct GMT_GRID_HEADER_HIDDEN so that we can free those arrays even those the matrix is left untouched.
I don't know if @joa-quim is wrapping the gmt_hidden.h file in Julia and so adding a new variable will cause trouble.