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".]
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}]
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.
Now, with ImagePadding
on, let's place Point
s 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 Point
s stay at the corners of the graph frame.
There is ImagePadding
around the graph frame.
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}]]}]
I've drawn the plot as 300x300 to simplify the numbers. Here's the analysis.
ImagePadding
"is defined within ImageSize".ImageScaled[{.1,.1}]
, ImageScaled[{.9,.1}
, ImageScaled[{.9,.9}]
& ImageScaled[{.1,.9}]
.It's easy to work out the value for other AspectRatio
s and ImageSize
s.
One possibility is to take manual control of ImagePadding:
Plot[Sin[x], {x, 0, 10}, Frame -> True,
ImagePadding -> {{30, 5}, {20, 5}}]
ImageTake[Rasterize[%], {5, -20}, {30, -5}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With