Skip to content

grdimage shading fails with external matrix #3408

@seisman

Description

@seisman

The issue was first reported by @liamtoney in GenericMappingTools/pygmt#364. Using the PyGMT script in that issue, he got the following error:

grdimage [ERROR]: Passing zmax <= zmin prevents automatic CPT generation!
grdimage [ERROR]: Failed to read CPT geo.

After some debugging, it seems that GMT can correctly read the matrix (i.e., the earth relief data) and can plot it correctly if shading=False (i.e., no -I+d in the command line). However, if shading=True is used (i.e., grdimage -I+d), GMT reports the error above, possibly because the matrix in memory is modified/freed/re-initialized when calling grdgradient.


The issue can be partially reproduced using the following C codes. The C code below is modified from GMT's own test code testapi_matrix_plot.c. It reads a 2d matrix and plots the matrix using grdimage.

#include "gmt.h"

int main () {
	void *API = NULL;                /* The API control structure */
	struct GMT_MATRIX *M = NULL;    /* Structure to hold input matrix */
	char input[GMT_VF_LEN] = {""};	/* String to hold virtual input filename */
	char args[128] = {""};         	/* String to hold module command arguments */
	/* Initialize the GMT session */
	API = GMT_Create_Session ("test", 2U, GMT_SESSION_EXTERNAL, NULL);
	M = GMT_Read_Data (API, GMT_IS_MATRIX, GMT_IS_FILE, GMT_IS_SURFACE, GMT_READ_NORMAL, NULL, "2d-matrix.txt", NULL);
	/* Associate our matrix with a virtual file */
	GMT_Open_VirtualFile (API, GMT_IS_GRID|GMT_VIA_MATRIX, GMT_IS_SURFACE, GMT_IN, M, input);

	/* Prepare the module arguments */
	sprintf (args, "%s -JX6i -P -Baf -Cgeo", input);
	/* Call the grdimage module */
	GMT_Call_Module (API, "grdimage", GMT_MODULE_CMD, args);

	/* Close the virtual file */
	GMT_Close_VirtualFile (API, input);
	/* Destroy session */
	if (GMT_Destroy_Session (API)) return EXIT_FAILURE;
};

The data 2d-matrix.txt is the 60m earth relief data, converted from netCDF to matrix format using following Python code. The data is attached 2d-matrix.txt.

import numpy as np
import pygmt
er = pygmt.datasets.load_earth_relief("60m")
np.savetxt("2d-matrix.txt", np.flip(er.data, axis=0), fmt='%.1f')

The C code is compiled using

gcc testapi_matrix_plot.c $(gmt-config --cflags --libs)

The output image looks correct. The coordinates are incorrect, simply because I didn't pass the geographic information.

image

Changing the grdimage arguments to:

sprintf (args, "%s -JX6i -P -Baf -Cgeo -I+d", input);

to enable shading, then the output image is:

image

This is what I expect:

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions