kakearney / contourfcmap-pkg

Create a filled contour plot in Matlab, with better color-to-value clarity
MIT License
17 stars 2 forks source link

Unenclosed NaNs produce incorrectly-calculated contours and trigger poly2fv seg fault #3

Open cherry20215 opened 6 years ago

cherry20215 commented 6 years ago

Hi Kelly Kearney, Thanks for your sharing. Very useful function with unchanging the original data set. I tried the examples in your post, worked well, but I faced an issue when using my own data. Please take a look at the info below.

  1. Microsoft Windows 10 Education
  2. MATLAB Version: 8.6.0.267246 (R2015b) Java Version: Java 1.7.0_60-b19 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode

    MATLAB Version 8.6 (R2015b) Curve Fitting Toolbox Version 3.5.2 (R2015b) DSP System Toolbox Version 9.1 (R2015b) Image Processing Toolbox Version 9.3 (R2015b) MATLAB Compiler Version 6.1 (R2015b) MATLAB Compiler SDK Version 6.1 (R2015b) Mapping Toolbox Version 4.2 (R2015b) Neural Network Toolbox Version 8.4 (R2015b) Optimization Toolbox Version 7.3 (R2015b) Parallel Computing Toolbox Version 6.7 (R2015b) Signal Processing Toolbox Version 7.1 (R2015b) Statistics and Machine Learning Toolbox Version 10.1 (R2015b)

  3. I tried to plot my figure with 'method' 'recolor', got the color of figure and colorbar inconsistent. Please find the attached files for your reference. I am a beginner for matlab, hope not bother you too much on this issue. Thanks.

contour_plot.txt test

kakearney commented 6 years ago

This looks like the issue I mention in the README under R2014b updates. In any version of Matlab that uses HG2 handle graphics (i.e. anything more recent than R2014b, where graphics object handles are objects rather than doubles), the default recoloring method used by the contourfcmap function is very fragile, and has a tendency to get undone when you do things like adding a colorbar. In your example, it looks like your contour plot has been reset to the default parula colormap, likely when you added the colorbar.

Unfortunately, there's not much I can do to fix this issue... the Mathworks programmed their contourgroup objects in such a way that one needs to dive deep into the undocumented properties to try to change the color at all, and fiddling with undocumented properties always comes with a higher possibility of failure for unknown reasons.

The workaround, as mentioned in the documentation, is to use the calccontour method. Slower and more resource intensive, but it should keep all your colors in place.

cherry20215 commented 6 years ago

Hi Kelly, Thanks for your prompt reply. Actually I tried "calccontour" also. It showed matlab system error, after I clicked "Attempt to Continue". No figure came out, but only colorbar. I checked that "Mapping Toolbox Version 4.2 (R2015b)" was there.

cherry20215 commented 6 years ago

Hi Kelly, The matlab system error by using "calccontour" was "This error was detected while a MEX-file was running." Besides, another info, when I used the 'method' 'recolor', actually got errors shown below also.

Error using scatteredInterpolant The coordinates of the input points must be finite values; Inf and NaN are not permitted. Error in contourfcmap (line 480) F = scatteredInterpolant(x(:), y(:), z(:)); Error in contour_plot (line 27) h.c =contourfcmap(data.X(1:328,1:138,1),data.Y(1:328,1:138,1),data.Val,clev,cmap,...

So all the issues mentioned above could be from my data? any requirements for the data for contourfcmap.m? There is no issue when I plot my data by using "contourf". Thanks:)

kakearney commented 6 years ago

Ran a few tests, and it definitely appears to be the NaNs in the dataset that are causing the issues. In particular, what I'll refer to as "unenclosed NaNs", i.e. NaNs that lead to a blank space outside of all the contour lines. That situation was never included in my test cases, and fails spectacularly with the calccontour method.

Specifically, my method for generating contour polygons goes a bit awry when calculating the lines adjacent to NaN regions, which leads to an unclosed polygon contour being passed to poly2fv. Matlab's poly2fv function doesn't include any error checks for that sort of thing, and it passes the data on to the vectorsToGPC mex function, which cannot tolerate any improperly-formatted polygons, so it throws a segmentation fault.

A short-term solution would be to fill your NaNs with placeholder data prior to contouring... nearest-neighbor is usually a good choice to fill without adding too many artifacts to the contours. You could then add plot an image with strategic transparency to mask out your NaN bits after the fact. Here's an example of that:

[x,y,z] = peaks(100);
z(abs(z) < 0.1) = NaN;

zfill = fillnan(z);

contourfcmap(x,y,zfill,[-5 -3 -2:.5:2 3 5],jet(12), ...
             'lo', [.8 .8 .8], ...
             'hi', [.2 .2 .2], ...
             'method', 'calccontour', ...
             'flag', false);

mask = isnan(z);
c = repmat(mask, 1, 1, 3);
hold on;
hi = image(x(1,:),y(:,1),c);
set(hi, 'AlphaData', double(mask));

(I use my fillnan.m function for the NaN-filling).

cherry20215 commented 6 years ago

Hi Kelly, Thanks for your detailed explanation. How about the NaNs in x and y (lon, lat corrdinates)? I tried to use your fillnan function to x and y as following (if no applying to x and y, got same errors mentioned previous): x = data.X(1:328,1:138,1); y = data.Y(1:328,1:138,1); xfill = fillnan(x); yfill = fillnan(y);

then got Errors shown below: Cell contents indices must be greater than 0 Error in contourfcmap (line 604) S(ii).X = [S(ii).X xcorner(tbl{loc,2}) S(ii).X(1)]; Error in contour_plot_new (line 44) contourfcmap(xfill,yfill,zfill,clev,cmap,...

These errors could be from the same fillin values from contour edge to matrix edge for xfill and yfill?

kakearney commented 6 years ago

I'm not sure I understand the situation where you would have NaNs in your x- or y-coordinates... Are those associated with an actual data point in your z matrix, and if so, how do you intend to geolocate those points without any actual coordinate data?

At any rate, when you fill the x- and y-coordinates using nearest neighbor (which is what fillnan does), you suddenly have multiple data points associated with the same x/y point. I do a lot of error checking on the size of x/y/z input, but I don't really check for that situation... and it appears contour returns something my function isn't expecting in that case. Without your data, it's impossible to diagnose further.