DifferencePlot

by Markus Lischka

This package introduces DifferencePlot, a function based on ContourPlot emphasizing positive and negative regions by red and blue color shading as well as different contour line styles. This is especially useful for analyzing, e.g., changes in (charge) density distributions.

Reference

Title

DifferencePlot — Contour plots with marked positive and negative regions.

Author

Markus Lischka (mlischka@physik.tu-muenchen.de)

Summary

This package introduces DifferencePlot, a function based on ContourPlot emphasizing positive and negative regions by red and blue color shading as well as different contour line styles. This is especially useful for analyzing, e.g., changes in (charge) density distributions.

Copyright

© Copyright 2001, Markus Lischka.

Permission is granted to distribute this file for any purpose except for inclusion in commercial software or program collections. This copyright notice must remain intact.

Notebook Version

1.4

Mathematica Version

4.0

History

Version 1.0: Initial version (2001-02-17).

Version 1.1: Changed call to makeContourStyle so that it gets its option list as a sequence (2001-03-20).

Version 1.2: makeContourStyle now applies Chop to the list of contours so that the zero contour line is treated properly (2001-03-22).

Version 1.3: Options for ShowLegend are now set and filtered using the Legend options set (2001-04-11).

Version 1.4: Added usage documentation and examples for PlotLegend option. Initial submission to MathSource (2003-03-30).

Keywords

difference plot, contour plot, graphics

Source

Maeder, R. Programming in Mathematica, 3rd ed. Addison-Wesley, 1996.

Warnings

Note: all cells marked as "InitializationCell" will be written to the Auto-Save package. This package can then be read in programs that use it with Needs["Template`"]. Cells not intended to belong to the package should not have this property.

Limitations

The options of DifferencePlot are inherited from ContourPlot when loading the package and are thus independent of later changes to the default ContourPlot settings.
Styles of contour lines are applied to the drawn contour lines, not to the explicitly specified contour lines via the Contours option. If any specified contour lines are not plotted because they are out of the value range of the given function, styles will be mismatched! This cannot happen when using e.g. Contours->10.

Discussion

The plot legend of the difference plot is controlled via the PlotLegend option: It may assume the values None, Automatic or contain a full legend specification as described in the package Graphics`Legend`. By default, a plot legend is drawn: Its box labels ("+", "-") are fixed and cannot be modified by using any options.

Requirements

Graphics`Legend`
Utilities`FilterOptions`

Interface

This part declares the publicly visible functions, options, and values.

Set up the package context, including public imports

BeginPackage["Graphics`DifferencePlot`",
	"Graphics`Legend`", "Utilities`FilterOptions`"]

Usage messages for the exported functions and the context itself

DifferencePlot::usage = "DifferencePlot[f, {x, xmin, xmax}, {y, ymin, ymax}] generates a contour plot of f as a function of x and y. Positive regions are colored red with dashed contour lines, negative regions blue with solid contour lines. The contour line of f == 0 is drawn dotted. The absolute maximum value being represented by blue or red is given by the option MaximumDifference. The plot legend is controlled by the option PlotLegend which may either be Automatic, None, or a full legend specification."

MaximumDifference::usage = "MaximumDifference is an option for DifferencePlot that specifies above which absolute value the contour level should be represented by blue or red. The default is MaximumDifference -> 1.0.";

PlotLegend::usage = PlotLegend::usage <> " PlotLegend is also a valid option for DifferencePlot. In this case, it may either be set to Automatic, None, or a full legend specification as expected by ShowLegend.";

Implementation

This part contains the actual definitions and any auxiliary functions that should not be visible outside.

Begin the private context (implementation part)

Begin["`Private`"]

Definition of auxiliary functions and local (static) variables

makeContours[]

makeContours[max_, n_?Positive] := 
    Module[{m = Ceiling[(n-1)/2]},
        Table[max/m*i, {i, -m, m}]
    ];

makeContours[max_, any_] := any;

makeContourStyle[]

makeContourStyle[contours_?VectorQ, opts___?OptionQ] := 
    Module[{pos = 1},
        style = ContourStyle /. {opts} /. Options[DifferencePlot];
        If[MatrixQ[style],
            (* explicit styles specified via ContourStyle option, 
               so keep them unchanged: *)
            style,

            (* no style or global style specified: *)
            Which[
                # > 0, Join[{style}, {AbsoluteDashing[{6, 4}]}],
                # < 0, Join[{style}, {AbsoluteDashing[{}]}],
                # == 0, Join[{style}, {AbsoluteDashing[{1, 2}]}]
            ]& /@ Chop[contours]
        ]
    ];

color[]

This function produces a color gradient from blue (z = -1) to red (z = 1):

color[z_, max_] := 
    Module[{c}, 
        c = Min[max, Max[-max, z]] / max;
        If[c < 0.0,
            RGBColor[1.0+c, 1.0+c, 1.0],
            RGBColor[1.0, 1.0-c, 1.0-c]
        ]
    ];

Definition of the exported functions

DifferencePlot[]

ShowLegend does not have any Options set, so we use the options of Legend instead:

Options[DifferencePlot] = Join[
    Options[ContourPlot],
    Options[Legend], 
    {
        MaximumDifference -> 1.0,
        PlotLegend -> Automatic 
    }];
SetOptions[DifferencePlot, 
    ColorFunctionScaling -> False,
    LegendLabel -> None,
    LegendSpacing -> 0,
    LegendShadow -> {0,0},
    LegendSize -> {0.2,1.6},
    LegendPosition -> {1.1,-0.8}];

DifferencePlot[f__, opts___?OptionQ] := 
    Module[{opt, max, contours, colors, display, plot, legend},
        opt = Join[{opts}, Options[DifferencePlot]];
        max = MaximumDifference /. opt;
        contours = makeContours[max, Contours /. opt];
        colors = ColorFunction /. opt /. Automatic -> (color[#, max]&);
        display = DisplayFunction /. opt;

        plot = ContourPlot[f, 
            DisplayFunction -> Identity,
            Contours -> contours, 
            ContourStyle -> makeContourStyle[contours, Sequence @@ opt],
            ColorFunction -> colors,
            Evaluate[FilterOptions[ContourPlot, opt]]
        ];

        legend = PlotLegend /. opt;
        Which[
            legend === Automatic,
                ShowLegend[plot, {
                    color[0.5-#,0.5]&,
                    Length[contours],
                    "+", "-",
                    Evaluate[FilterOptions[Legend, opt]] }
                ],
            legend === None,
                Show[plot, DisplayFunction -> display],
            True, (* otherwise we expect a valid plot legend: *)
                ShowLegend[plot, legend]
        ]
    ];

End the private context

End[ ]

Epilog

This section protects exported symbols and ends the package.

Protect exported symbol

Protect all exported symbols:

Protect[Evaluate[$Context <> "*"]]

End the package context

EndPackage[ ]

Examples, Tests

Needs["Graphics`DifferencePlot`"];

?DifferencePlot

?MaximumDifference

DifferencePlot[
        Sin[x] Cos[y], {x, -π, π}, {y, -π, π}, 
        PlotPoints -> 30, MaximumDifference -> 0.5];

?PlotLegend

DifferencePlot[
        Sin[x] Cos[y], {x, -π, π}, {y, -π, π}, 
        PlotPoints -> 30, PlotLegend -> None, 
        ContourShading ->  False];

?Graphics`Legend`Legend*

DifferencePlot[
        Sin[x] Cos[y], {x, -π, π}, {y, -π, π}, 
        PlotPoints -> 30, PlotLegend -> Automatic,  
        LegendShadow -> {0.02, -0.02},  
        LegendLabel  ->  "Δn"];

DifferencePlot[
        Sin[x] Cos[y], {x, -π, π}, {y, -π, π}, 
        PlotPoints -> 30, 
        PlotLegend -> {{{RGBColor[1, 0, 0], "+"}, {RGBColor[0, 0, 
                  1], "-"}}, LegendPosition -> {1.1, 0.55}, 
            LegendShadow -> {0, 0},  LegendSize -> {0.2, 0.4}, 
            LegendLabel  ->  "Δn"} ];