7

The wonderful error bar log plots package ErrorBarLogPlots from V6 no longer positions labels correctly (since v9 or maybe v8) so I used the same function with Prolog to place a list of labels.

Then in v10 beta PlotRangePadding no longer works either and I can't find a work around for that, so I tried to go back to basics and use the very elegant solution by Belisarius' et.al in:

Plotting Error Bars on a Log Scale

I was able to modify this to make asymmetric $Y$ error bars, then I tried to add $X$-errors and got tied up in knots with the Joined and Filling commands.

The aim is to plot a set of $5$ lists of xy values, {xy, xyP, xyM, xPy, xMy} where P and M refer to the plus and minus error of the $x$ or $y$ value preceding it, with a Filling / Joined statement that joins the first point to the other 4 points.

Ideally the plot symbols should also switch between vertical and horizontal bars for the $x$ and $y$ error points and something else for the $x, y$ point. (I asked Support about including an errorlistlogplot command in Mathematica but I expect it won't make it into v10).

The lines below generate and plot the 5 sets of points. Is there a straightforward combination of Filling / Joined statements to achieve this?

SeedRandom[1234]
dataX = Sort@RandomReal[{0.5, 1}, 10];
dataY = RandomReal[{0.5, 1}, 10];
{errorYP, errorYM, errorXP, errorXM} = RandomReal[.5, {4, 10}];
dataYP = dataY + errorYP;
dataYM = dataY - errorYM;
dataXP = dataX + errorXP;
dataXM = dataX - errorXM;
xy = Transpose[{dataX, dataY}];
xyP = Transpose[{dataX, dataYP}];
xyM = Transpose[{dataX, dataYM}];
xPy = Transpose[{dataXP, dataY}];
xMy = Transpose[{dataXM, dataY}];

ePlot[plotFun_, data_] := plotFun[data, Filling -> Automatic, PlotRange -> All,
                                        Joined -> {False, False, False, False, False}];

ePlot[ListLogPlot, {xy, xyP, xyM, xPy, xMy}]

enter image description here

DrBubbles
  • 1,391
  • 9
  • 17
  • I suppose you can't ask for solution on V10 since it is not released yet. So you want the solution for nonsymetric errorbars in x and y axis without PlotRangePadding? – Kuba Feb 12 '14 at 07:26
  • Yes v9. The PlotRangePadding command works in V10 with the inbuilt ListLog plots etc, but not with plots created using the external package ErrorBarLogPlots. So a v9 solution is likely a v10 solution also. – DrBubbles Feb 12 '14 at 19:36

1 Answers1

6

README: This answer is not correct scientifically, I just transformed error bars to log scale instead of doing a correct error propagation. Didn't have time to fix it yet :(


Here's a minimal example:

data = {{20, 100}, {30, 10}, {100, 1000}, {500, 1000}};
xer = {{10, 10}, {20, 300}, {50, 50}, {100, 200}};
yer = {{50, 50}, {5, 50}, {100, 500}, {300, 100}};

errorPlot[#, data, xer, yer] & /@ {ListPlot, ListLogPlot, ListLogLogPlot, ListLogLinearPlot};

enter image description here

Code:

errorPlot[plot_, data_, xer_, yer_] := With[{
       tr = Transpose@data,
       arrow = Graphics[{Red, Line[{{0, 1/2}, {0, -1/2}}]}]},
      Module[{PlusMinus, limits, limitsRescaled, dataRescaled, lines, scale},
   scale = plot /. {ListPlot -> {# &, # &}, ListLogPlot -> {# &, Log}, 
                    ListLogLogPlot -> {Log, Log}, ListLogLinearPlot -> {Log, # &}};

   PlusMinus[a_, b_] := {a - b[[1]], a + b[[2]]};
   limits =  MapThread[MapThread[PlusMinus, {#, #2}] &,
                       {tr, {xer, yer}}];

   limitsRescaled = MapThread[Compose, {scale, limits}];   
   dataRescaled = MapThread[Compose, {scale, tr}];

   lines = Flatten[
            MapAt[Reverse, 
                  MapThread[{{#2[[1]], #}, {#2[[2]], #}} &, 
                            {Reverse@dataRescaled, limitsRescaled}, 2], 
                  {2, ;; , ;;}], 1];   

    Show[
     plot[data, PlotStyle -> AbsolutePointSize@7, Axes -> False, Frame -> True, 
                BaseStyle -> 18, ImageSize -> 500],
     Graphics[{Arrowheads[{{-.02, 0, arrow}, {.02, 1, arrow}}], Thick, Arrow[lines]}]
     ,
     PlotRange -> ({Min[#], Max[#]} & /@ Transpose@Flatten[lines, 1])]]]

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • This works great with Show[errorPlot[ListLogPlot,data[[#]],xer[[#]],yer[[#]]]&/@Range[Length[data]] for plotting multiple series on the same plot. To apply different formatting for each series we can pass a list of #'d formatting options. I wasn't able to figure out how to arrange the 'data' and err lists to pass multiple data sets in one command (multiple series on one plot without Show); some form of Transpose[data,{?,?}], and Transpose[xer,{?,?}]. Would that be more efficient than using Show to get multiple series on one plot? Great solution either way. – DrBubbles Feb 12 '14 at 19:32
  • @DrBubbles I'll try to make it more usefull. I will tell you when I'm done ;) – Kuba Feb 12 '14 at 20:00
  • I moved the arrow heads inside the plot command to add multiple data sets with Tooltips: Show[plot[Tooltip[data[[#]], ttips[[#]]] & /@ Range[Length[data]], PlotStyle -> AbsolutePointSize@7, Axes -> False, Frame -> True, BaseStyle -> 18, ImageSize -> 500, Prolog -> {Arrowheads[{{-.02, 0, arrow}, {.02, 1, arrow}}], Thick, Arrow[lines]}], PlotRange -> ({Min[#], Max[#]} & /@ Transpose@Flatten[lines, 1])] and called the function with errorPlot[plot_, data_, xer_, yer_, ttips_] and multiple data sets. Show overplots the multiple series with tooltips but only one set of error bars. – DrBubbles Feb 12 '14 at 21:45
  • Sorry, I can't format the comments properly. – DrBubbles Feb 12 '14 at 21:49
  • @Kuba It would be great if the code could be modified to accommodate also without x axis error bars case. – Al Guy Sep 03 '16 at 03:25
  • @AlGuy I must say it is very unlikely that I will make an edit here in a near future but if you want to, feel free to improve this answer. – Kuba Sep 06 '16 at 05:19