Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the coordinates of the Frame/Axes in the final display area of a plot

If I do a Plot with Frame->True is there a way I can find the coordinates of the corners of the Frame in the absolute coordinates of the image? I have the numerical values of PlotRange and PlotRangePadding but note that I don't want to tamper with the actual plot in any way, just find out where in the full display area Mathematica chooses to place the frame/axes of the plot.

As pointed out by Brett Champion, I'm looking for the coordinates {x,y} such that Scaled[{0,0}] == ImageScaled[{x,y}].

[Note that I edited this question to remove my confusing misuse of the term "scaled coordinates".]

like image 589
dreeves Avatar asked Apr 08 '11 02:04

dreeves


3 Answers

The corners of the frame are at Scaled[{0,0}] and Scaled[{1,1}].

The corners of the full graphic (including labels) are at ImageScaled[{0,0}] and ImageScaled[{1,1}].

Converting between them is hard, although in theory it's possible to convert Scaled and user (unscaled) coordinates if you know the actual, numeric, settings for PlotRange and PlotRangePadding.

Depending on your application, you might also be able to use MousePosition, which knows these things as well.

Rasterize (and HTML export) also know how to find bounding boxes of annotations, in a bitmap/pixel coordinate system:

In[33]:= Rasterize[
 Plot[Sin[x], {x, 0, 10}, Frame -> True, 
  Prolog -> {LightYellow, 
    Annotation[Rectangle[Scaled[{0, 0}], Scaled[{1, 1}]], "One", 
     "Region"]}], "Regions"]

Out[33]= {{"One", "Region"} -> {{22., 1.33573}, {358.9, 209.551}}}

Here's how dreeves used that Rasterize trick to make a function to return exactly what he was looking for (note the assumption of a global variable imgsz which gives the ImageSize option for rasterizing the plot -- the coordinates of the frame depend on that value):

(* Returns the geometry of the frame of the plot: 
   {width, height, x offset, y offset, total width, total height}. *)
geom[p_Graphics] := Module[{q, x1, y1, x2, y2, xmax, ymax},
  q = Show[p, Prolog->{Annotation[Rectangle[Scaled[{0,0}], Scaled[{1,1}]], 
                                  "MAGIC00","MAGIC11"]}];
  {{x1,y1}, {x2,y2}} = Rasterize[q, "Regions", ImageSize->imgsz][[1,2]];
  {xmax,ymax} = Rasterize[p, "RasterSize", ImageSize->imgsz];
  {x2-x1, y2-y1, x1, y1, xmax, ymax}]
like image 146
Brett Champion Avatar answered Sep 27 '22 17:09

Brett Champion


The coordinates of the upper left corner of the frame are always Scaled[{0,1}]. The coordinates of the lower right corner of the frame are always Scaled[{1,0}].

Let's place large points at the upper left and lower right corners:

Plot[Cos[x], {x, 0, 10}, Frame -> True, 
Epilog -> {PointSize[.08], Point[Scaled[{0, 1}]], Point[Scaled[{1, 0}]]} ]

When I click on the graph (see below) , it is obvious that there is no padding around the frame of the plot.

no padding

Now, with ImagePadding on, let's place Points in the same corners:

Plot[Cos[x], {x, 0, 10}, Frame -> True,  
ImagePadding -> {{37, 15}, {20, 48}}, 
Epilog -> {PointSize[.08], Point[Scaled[{0, 1}]],  Point[Scaled[{1, 0}]]} ]

The Points stay at the corners of the graph frame. There is ImagePadding around the graph frame.

with padding

EDIT: Based on the clarification of the question by dreeves.

Plot[Cos[x], {x, 1, 9}, ImageSize -> 300, AspectRatio -> 1, 
Frame -> True, ImagePadding -> 30, 
FrameTicks -> {Range[9], Automatic}, 
Epilog -> {PointSize[.08], Point[Scaled[{0, 1}]], Point[Scaled[{1, 0}]]}]

Frameticks

I've drawn the plot as 300x300 to simplify the numbers. Here's the analysis.

  1. Documentation states that ImagePadding "is defined within ImageSize".
  2. The image shown above has a width and height of 300 pixels.
  3. There is a 30 pixel margin drawn around the frame; this corresponds to 10% of the width and height.
  4. So the frame corners should be, starting from the origin, at ImageScaled[{.1,.1}], ImageScaled[{.9,.1}, ImageScaled[{.9,.9}] & ImageScaled[{.1,.9}].

It's easy to work out the value for other AspectRatios and ImageSizes.

like image 39
DavidC Avatar answered Sep 27 '22 15:09

DavidC


One possibility is to take manual control of ImagePadding:

Plot[Sin[x], {x, 0, 10}, Frame -> True, 
 ImagePadding -> {{30, 5}, {20, 5}}]

enter image description here

ImageTake[Rasterize[%], {5, -20}, {30, -5}]

enter image description here

like image 45
Mr.Wizard Avatar answered Sep 27 '22 17:09

Mr.Wizard