# How to set FenceWidth in logarithmic plot?

Mathematica 12 introduced a built-in support for logarithmic plots with error bars. A plot with default styling looks as expected:

ListLogPlot[
Table[{i, Around[1 + Sin[i], 0.1 + 0.1 Cos[i]]}, {i, 0, 10, 1}],
PlotRange -> {All, {0.01, 10}}
] However, when I want to customize FenceWidth, this happens:

ListLogPlot[
Table[{i, Around[1 + Sin[i], 0.1 + 0.1 Cos[i]]}, {i, 0, 10, 1.0}],
PlotRange -> {All, {0.01, 10}},
] What is a proper way to set custom FenceWidth in logarithmic plot?

How to set FenceWidth in absolute units like in default styling, when the width of fences doesn't change when the plot is resized?

This is clearly a bug. In addition to the weird fence shape, the scaling behavior is also changed: fence widths change when the plot is resized.

A work-around is to post-process the output to straighten the fence lines and make fence widths independent of image size:

ClearAll[repairFences]
repairFences[w_] := Replace[#,  Line[x_] /; Length[Dimensions@x] ==  3 :>
(Line[{Offset[{-w 72 /2 , 0}, #[[1,1]]], Offset[{w 72/2 , 0}, #[[1,1]]]}]& /@
Partition[x, 2]), All] &

llp = ListLogPlot[Table[{i, Around[1 + Sin[i], 0.1 + 0.1 Cos[i]]}, {i, 0, 10,  1.0}],
PlotRange -> {All, {0.01, 10}},
IntervalMarkers -> "Fences",
] ;

Row[Show[repairFences[.3] @ llp, ImageSize -> #]& /@ {200, 500}, Spacer] An alternative work-around is to remove IntervalMarkersStyle -> <|"FenceWidth" -> .3|> and post-process to modify the fence lines to desired length:

llp2 = ListLogPlot[Table[{i, Around[1 + Sin[i], 0.1 + 0.1 Cos[i]]}, {i, 0, 10, 1.0}],
PlotRange -> {All, {0.01, 10}}, IntervalMarkers -> "Fences" ]


Make fences 20 printer's points long (fence length is independent of image size):

llp2 /. Offset[{a_, _}, b_] :> Offset[{10 Sign[a] , 0}, b] Make fences .3 user units long (fence length changes with image size):

llp2 /. Offset[{a_, _}, {b_, c_}] :> {b + .15 Sign[a], c} You can still use IntervalMarkersStyle to style the fences:

llp3 = ListLogPlot[Table[{i, Around[1 + Sin[i], 0.1 + 0.1 Cos[i]]}, {i, 0, 10, 1.0}],
PlotRange -> {All, {0.01, 10}},
IntervalMarkers -> "Fences",

llp3 /. Offset[{a_, _}, {b_, c_}] :> {b + .5 Sign[a], c} Update: using the second approach to make a function:

ClearAll[modifyFenceWidth]
modifyFenceWidth[arg : h_[w_] | w_] := # /.  Switch[Head[arg],
Offset, Offset[{a_, _}, b_] :> Offset[{ w  Sign[a]/2 , 0}, b],
Real, Offset[{a_, _}, {b_, c_}] :> {b + w/2 Sign[a], c},
Scaled, Offset[{a_, _}, {b_, c_}] :>
{b + w Abs[Subtract @@ PlotRange[#][]]/2 Sign[a], c}] &


Examples:

you can specify the fence width in user units, printer's points or as fraction of the plot width:

Row[Labeled[modifyFenceWidth[#] @ llp2,
Style["modifyFenceWidth @ " <> ToString[#], 18], Top] & /@
{.4, Offset @ 20, Scaled @ .1}, Spacer] 