# How can I set the ratio of the axis to 1:1 when plotrange->1 or how can I scale a rectangle according to the axis

I have a ListPlot function

lp2 :=
ListPlot[{#} & /@ #1,
PlotMarkers -> {Graphics@{Rectangle[]}, #2},
AspectRatio -> 1,
AxesOrigin -> {0, 0},
PlotRange -> All,
PlotStyle -> Hue /@ RandomReal[1, {Length@#1}],
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, Line@#1},
Frame -> True,
FrameTicks -> All
] &


which attempts to add a unit rectangle centered on each point however this relies on having constant axis to scale the unit rectangle to fit the axis. When PlotRange->All the axis ignores the aspect ratio and pretty much everything else. Is it possible to alter this behavior or scale the rectangle to the size of the axis chosen by Mathematica?

-
"unit rectangle" - I don't understand; as a rectangle has width and height, there should be two parameters, no? What dimensions were you expecting for these rectangles? –  Ｊ. Ｍ. Feb 15 '12 at 11:46
@J.M. I assume he means a unit square: the default shape of Rectangle[]. –  Mr.Wizard Feb 15 '12 at 12:01
Ooops, yeah, a unit square is defined as Rectangle[] in mathematica sorry for the confusion. –  user1170304 Feb 15 '12 at 12:15
@user Please review my answer below and tell me if that is what you want. If it is, I will also suggest a way to do this bypassing ListPlot and using Graphics primitives directly. –  Mr.Wizard Feb 15 '12 at 12:19
Looks like this is related to this SO question and my answer there. to change the markers from squares to rectangles with aspect ratio that matches the aspect ratio of the plot, you need to use a second argument to the Graphics that define the plot markers: instead of Graphics@{Rec..} use Graphics[{Rectangle[]},AspectRatio->.5 (say). –  kguler Feb 15 '12 at 12:38

Depending on your needs is may be both simpler and more flexible to bypass ListPlot completely and do this directly in Graphics. Here is a simple example:

dat = RandomReal[11, {15, 2}];

Graphics[{
{Hue @ RandomReal[], Rectangle[# - 0.5]} & /@ #,
{GrayLevel[.3], PointSize[.02], Point@#, Thick, Line@#}
},
AspectRatio -> 0.5,
Frame -> True
] & @ dat


-
This was perfect, thanks! –  user1170304 Feb 15 '12 at 14:20

/. Inset -> (Inset[#, #2, Automatic, 1] &)


Like:

lp2[args] /. Inset -> (Inset[#, #2, Automatic, 1] &)


This works by post-processing the Graphics object that in generated by ListPlot. The function Infix is used to place the PlotMarkers. Normally it is using without the size argument to keep the plot markers an absolute size. You want the markers unit size which can be done with:
Inset[_, _, _, 1].

You should get something like this:

You can of course include this in your definition of lp2 but I am not sure of your syntax so I did not want to make the change myself.

You can specify an explicit aspect ratio for the PlotMarkers while using this, e.g. (in the definition of lp2):

PlotMarkers -> {Graphics[{Rectangle[]}, AspectRatio -> 0.5]}


If you need help rolling this into your function let me know.

As a side note you do not need SetDelayed (:=) when defining a pure function (&); use Set (=).

-

Although I'm a bit late in answering this, I thought it's worth pointing out for completeness that there's actually a built-in function that is basically designed to do exactly what this question asks for: ErrorListPlot as shown below where I just modify the given definition slightly in the first few lines:

Needs["ErrorBarPlots"]

lp3 = ErrorListPlot[{#, ErrorBar[{}]} & /@ #1,
ErrorBarFunction ->
Function[{coords, errs}, {EdgeForm[Orange], LightOrange,
Rectangle[coords - #2/2, coords + #2/2]}],
AspectRatio -> 1, AxesOrigin -> {0, 0},
PlotStyle -> Hue /@ RandomReal[1, {Length@#1}],
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick,
Line@#1}, Frame -> True, FrameTicks -> All] &;


The function allows you to specify the option ErrorBarFunction, and there is an example in the documentation showing how a rectangle can be constructed based on the errors in the data. Here I adapted that example to use a constant error in both horizontal and vertical directions.

Here is a set of test data - using differently scaled real numbers instead of integers:

data = {30, 10} # & /@ RandomReal[1, {15, 2}]

(*
==> {{15.0817, 8.63497}, {29.1274, 4.68834}, {3.86173,
2.3385}, {14.3022, 0.452592}, {2.81023, 9.56299}, {27.9932,
1.82105}, {1.35937, 0.0468926}, {9.20839, 2.01352}, {2.8601,
7.20318}, {11.0419, 1.71997}, {19.9694, 6.43578}, {10.9362,
6.84062}, {6.76464, 8.23109}, {21.5031, 4.1016}, {28.083, 6.58259}}
*)

lp3[data, 1]


Edit

Since the original question had variable colors, I should also add that to my solution. Here I color the edge according to the distance from the origin, and the inside according to the angle with the $x$ axis:

lp4 = ErrorListPlot[{#, ErrorBar[{}]} & /@ #1,
ErrorBarFunction ->
Function[{coords, errs}, {EdgeForm[Hue[Norm[coords]/20]],
Hue[2/Pi ArcTan @@ coords],
Rectangle[coords - #2/2, coords + #2/2]}], AspectRatio -> 1,
AxesOrigin -> {0, 0},
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick,
Line@#1}, Frame -> True, FrameTicks -> All] &;

lp4[data, 2]
`

-