MathGroup Archive 2004

[Date Index] [Thread Index] [Author Index]

Search the Archive

RE: ListContourPlot and missing data


Why don't you use a density plot instead of a contour plot? Then you could
do something like the following. In the sample data I used imaginary I
instead of Null for the missing data because ListDensityPlot does not like
nonnumeric data.

data = Table[If[x^2 + y^2 < 2, I, N[Sin[x*y]]],
    {x, 0, Pi, Pi/40}, {y, 0, Pi, Pi/40}];

colorfunc[z_] := Which[z == I, Hue[0.5, 1, 0], True,
   Hue[(z + 1)/2, 1, 1]]

ListDensityPlot[data, MeshRange ->
    {{0, Pi}, {0, Pi}}, ColorFunctionScaling ->
    False, ColorFunction -> colorfunc,
   Mesh -> False];

Or if you would rather use Null, then you could use a RasterArray.

data = Table[If[x^2 + y^2 < 2, Null, N[Sin[x*y]]],
    {x, 0, Pi, Pi/40}, {y, 0, Pi, Pi/40}];

colorfunc2[z_] := Which[z === Null, Hue[0.5, 1, 0],
   True, Hue[(z + 1)/2, 1, 1]]

colorraster = Map[colorfunc2, data, {2}];

     {{0, 0}, {Pi, Pi}}]], AspectRatio -> Automatic,
   Frame -> True];

If you want a contour plot, and want the Nulls to define the masking region,
there is a way to this can be done using the TrimPolygons function in the
DrawGraphics package at my web site. The idea is to make a standard contour
plot and then superimpose masking polygons. This will only work well if the
Null regions are a set reasonably contiguous blobs and not just a lot of
randomly scattered points. Here is the code.


data = Table[If[x^2 + y^2 < 2, Null, N[Sin[x*y]]],
    {x, 0, Pi, Pi/40}, {y, 0, Pi, Pi/40}];

In the following, data1 will be the data for the contour plotting function
and data2 will be the data for a masking function.

data1 = data /. Null -> 0;
data2 = data /. _?NumberQ -> 1 /. Null -> 0;

Now I make InterpolatingFunctions for the flow and for the masking.

flowfunc = ListInterpolation[data1,
   {{0, Pi}, {0, Pi}}]

maskfunc = ListInterpolation[data2,
   {{0, Pi}, {0, Pi}}, InterpolationOrder -> 1]

I'd rather make the contour plot from a function than an array because then
the xy ranges are handled correctly.

Now we make a grid of Polygons that cover the region.

grid = N[MakePolyGrid[{41, 41},
     {{0, 0}, {Pi, Pi}}]];

And we trim them by the masking function to contain only the 0 regions.

maskgrid = grid // TrimPolygons[maskfunc, {-0.1, 0.999}];

This throws out all polygons that don't have all four corners in the 0
region, and trims the edges of polygons that overlap the edge.

We can then draw the contours and put the mask on top of it.

  {ContourDraw[flowfunc[x, y], {x, 0, Pi}, {y, 0, Pi}, ColorFunction ->
   Black, maskgrid},
  AspectRatio -> Automatic,
  Frame -> True];

Still, the mask did not come out a perfect segment of a circle because the
original data did not render it that way. Generally you might obtain nicer
plots if you can define the boundaries more precisely than using Nulls in
the data array.

David Park
djmp at

From: Gareth Owen [mailto:usenet at]
To: mathgroup at

I've a rectangular array containing numerical data as some entries, and
Null in other entries (which represent
the boundaries and solid regions of an irregularly shaped fluid flow domain.

For a rectangular domain (with no Nulls)
I plot my scalar field data (temperature), with

          Contours->20, ColorFunction->(RGBColor[1-#,0,#] &)]

which shades the warm areas red, and the cold areas blue. Is there some way
can plot the irregular data, with the Null elements coloured black.

Obviously, the Nulls could easily be replaced by anything else.

  • Prev by Date: Re: Symbolic use of numerical function FindRoot via ?NumericQ
  • Next by Date: Re: Scriptable Mathematica tools for auto-editing text?
  • Previous by thread: ListContourPlot and missing data
  • Next by thread: using iFFT on a Continuous Time Transfer Function