How-to position ContourLabel outside the Frame and Overlay ArrayPlot with ListContourPlot

I thought it would be interesting to see how one could use DataRange to align the ArrayPlot with the contour plot using Show.

It could have been straight forward. Let lcp be the contour plot, then:

{xrange, yrange} = PlotRange /. Options[lcp];

ap = ArrayPlot[
      grid
      , Mesh -> All
      , DataRange -> {xrange, yrange}
      ];
Show[lcp, ap, lcp]

Output

Alas, the squares are centered on their values, so half of the outer squares are outside of the view. (Actually a bit less than half, considering the plot range padding.)

{xrange, yrange}

{{0.02, 1.}, {4., 7.}}

The DataRange option is currently saying that we should place, on the x-axis, the middle of the leftmost square at 0.02 and the middle of the rightmost square at 1, and correspondingly for the y-axis.

We can fix this by adjusting the data range. Currently, we have a total of four squares in view, covering $1 - 0.02 = 0.98$ units of length along the x-axis.

We need to offset the middle of the square along the x-axis precisely the amount it takes to move the entire square into the view. We can set up an equation to figure out what the amount shoud be:

$$ (1 - x) - (0.02 +x) = \frac{4}{5} (1 - 0.02)\implies x = 0.098 $$

and similarly for the y-axis:

$$ (7 - x) - (4 + x) = \frac{4}{5} (7 - 4)\implies x = 0.3 $$

Putting these offsets into the code, we get

ap = ArrayPlot[
      grid
      , Mesh -> All
      , DataRange -> {xrange + {0.098, -0.098}, yrange + {0.3, -0.3}}
      ];
Show[lcp, ap, lcp]

Output


It is quite difficult to get the alignments right using Overlay. You can use one of the following approaches instead:

Inset

You can use a combination of Prolog and Inset:

ap = ArrayPlot[grid, Mesh -> All];

ListContourPlot[data3, Frame -> True, ImageSize -> Large, 
 Contours -> {300000, 600000, 900000, 1600000, 2200000}, 
 PlotRange -> {{0, 1}, All},
 ContourStyle -> {{Thick, Dashed, Black}}, 
 ContourLabels -> (Text[Framed[#3], {#1, #2}, Background -> White] &),
 ContourShading -> None, ScalingFunctions -> {None, "Log10"}, 
 Prolog -> Inset[ap, Scaled[{.5, .5}], Scaled[{.5, .5}], Scaled[1]]]

enter image description here

RescalingTransform

An alternative approach: Rescale the graphics primitives of ap using the PlotRanges of ap and lcp:

lcp = ListContourPlot[data3, Frame -> True, ImageSize -> Large, 
   Contours -> {300000, 600000, 900000, 1600000, 2200000}, 
   ContourStyle -> {{Thick, Dashed, Black}}, 
   PlotRange -> {{0, 1}, All},
   ContourLabels -> (Text[Framed[#3], {#1, #2}, 
       Background -> White] &), ContourShading -> None, 
   ScalingFunctions -> {None, "Log10"}];

rT = RescalingTransform[PlotRange[ap], PlotRange[lcp]];

rescaledap = MapAt[GeometricTransformation[#, rT] &, ap, {1}];

Show[lcp, Prolog -> First @ rescaledap]

![enter image description here

Raster

A much simpler way is to use Raster and use GridLines instead of Mesh:

Show[lcp, Prolog -> 
  Raster[Reverse@grid /. RGBColor -> List, Transpose@PlotRange[lcp]], 
 GridLines -> (Subdivide[##, 5] & @@@ PlotRange[lcp])]

enter image description here

Modifying contour labels

Using a slight modification of the function modifyLabels from this answer we can place the contour labels nest to the right frame:

Needs["GraphUtilities`"]

ClearAll[modifyLabels]
modifyLabels[styles__: 14] := Quiet[Normal[#] /. {Text[__] :> Sequence[], 
     t : Tooltip[a_, b_] :> 
       {t, Text[Framed[Style[b, {a[[-2]], styles}], Background -> White], 
        LineScaledCoordinate[SortBy[First]@a[[-1, 1]], 1], Right]}}] &

modifyLabels[] @ ListContourPlot[data3, Frame -> True, ImageSize -> Large, 
  Contours -> {300000, 600000, 900000, 1600000, 2200000}, 
  PlotRange -> {{0,1}, All},
  ContourStyle -> {{Thick, Dashed, Black}}, ContourLabels -> All, 
  ContourShading -> None, ScalingFunctions -> {None, "Log10"}, 
  Prolog -> Inset[ap, Scaled[{.5, .5}], Scaled[{.5, .5}], Scaled[1]]]

enter image description here

With further tweaking:

ClearAll[modifyLabels2]
modifyLabels2[styles__: 14] := 
 Quiet[Normal[#] /. {Text[__] :> Sequence[], 
     t : Tooltip[a_, b_] :> {t, 
       Text[Pane[Framed[Style[b, {a[[-2]], styles}], Background -> White], 
         ImageMargins -> {{12, 0}, {0, 0}}], 
        LineScaledCoordinate[SortBy[First]@a[[-1, 1]], 1], Left]}}] &

modifyLabels2[]@
 ListContourPlot[data3, Frame -> True, ImageSize -> Large, 
  Contours -> {300000, 600000, 900000, 1600000, 2200000}, 
  ContourStyle -> {{Thick, Dashed, Black}}, ContourLabels -> All, 
  ContourShading -> None, ScalingFunctions -> {None, "Log10"}, 
  Prolog -> Inset[ap, Scaled[{.5, .5}], Scaled[{.5, .5}], Scaled[1]], 
  PlotRangeClipping -> False, PlotRange -> {{0, 1}, All},
  ImagePadding -> {{Automatic, 90}, {Automatic, Automatic}}]

enter image description here

Tags:

Plotting