2
$\begingroup$

Pretty new to mathematica and stack exchange, so feel free to explain it like i'm 5! Essentially, I have a (mostly) working ListLinePlot in Mathematica, but would like to change some things in the styling, and plot horizontal lines.

My code:

ListLinePlot[{dataNi59s}, 
  PlotTheme -> "Detailed", 
  PlotRange -> {{0, 7000}, {0, 25}}, 
  PlotLabel -> 
    HoldForm["Comparison of Current Yields from Nickel Cathode 59 (Interpolated)(Anomolous Points Removed)"], 
  PlotLegends -> {"Cathode 59 - Nickel"}, 
  PlotMarkers -> {●, 5}, 
  PlotStyle -> 96, 
  Axes -> True, 
  Frame -> {{True, False}, {True, False}}, 
  FrameLabel -> 
    {HoldForm["Cathode Runtime (minutes)"], 
     HoldForm["Current (μA)" ]}, LabelStyle -> {GrayLevel[0], Bold},
  ImageSize -> {850, 550}, 
  InterpolationOrder -> 2]

This, with my data set (which I can include if wanted, but is quite big and might obfuscate the question), produces this graph:

Graph Produced

What I would like to do:

  1. Is there a way to include written information (and the legend) in the graphic itself e.g. Integrated Charge = (some variable calculated elsewhere in the notebook)

  2. I would like to put a faint black line at y = 1 uA on the graph (as that is a cut off point for this experiment). I tried doing this with GridLines -> {{}{1}}, but it removed the faint grid lines that are already on the graph, which I'd like to keep.

  3. There is a large spike in my data, between these two data points ({1805, 14.5}, {1869, 21.6}), caused by something non physical, and would like to highlight it by making the line at that region dashed, but can't see how to do it without making the entire line dashed.

  4. The interpolation I used seems to add its own data points to the graph, whilst I would like to keep the line as is (using the interpolate function), I would prefer if the only actually visibly plotted data points were the ones that belonged to my data set. Is there a way i can remove the visibility of the interpolated data points?

  5. Currently my data points seem to sit on top of the line, with the bottom of the point striking the line, how can I place them so the line passes through the centre of each point?

Sorry for the very long post, and thanks for any help guys, it is much appreciated, I've been tearing my hair out on this one for a while.


By Request, the data used for the plot:

dataNi59s = {{26, 8.07}, {28, 9.12}, {36, 11.9}, {40, 13.4}, {66, 
17.5}, {69, 17.9}, {163, 18.9}, {165, 21.4}, {191, 21.3}, {200, 
21.6}, {214, 21.5}, {227, 21.2}, {260, 20.9}, {342, 20.8}, {362, 
23.4}, {497, 23.4}, {510, 23.3}, {535, 22.9}, {566, 22.4}, {577, 
22.2}, {596, 21.9}, {607, 21.7}, {671, 21.0}, {682, 20.7}, {689, 
20.5}, {700, 20.9}, {704, 20.8}, {799, 19.6}, {809, 19.5}, {823, 
19.6}, {831, 19.5}, {841, 19.3}, {852, 19.3}, {875, 19.1}, {881, 
19.1}, {901, 19.0}, {911, 19.0}, {928, 19.0}, {955, 18.8}, {973, 
18.7}, {978, 18.6}, {1048, 18.5}, {1067, 18.4}, {1090, 
19.2}, {1111, 18.1}, {1126, 18.0}, {1134, 17.9}, {1196, 
17.7}, {1200, 17.6}, {1215, 17.6}, {1227, 17.5}, {1270, 
17.4}, {1367, 16.6}, {1377, 16.6}, {1381, 16.5}, {1494, 
16.3}, {1534, 16.3}, {1584, 16.0}, {1686, 15.4}, {1700, 
15.3}, {1707, 15.3}, {1805, 14.5}, {1869, 21.6}, {1878, 
21.3}, {1905, 21.1}, {1968, 21.0}, {1980, 21.0}, {2010, 
20.9}, {2025, 20.8}, {2063, 20.5}, {2070, 20.5} , {2109, 
20.1}, {2146, 19.8}, {2232, 19.3}, {2249, 19.1}, {2280, 
18.8}, {2347, 18.1}, {2370, 17.9}, {2394, 17.8}, {2400, 
17.6}, {2416, 17.5}, {2430, 17.4}, {2452, 17.2}, {2462, 
17.1}, {2488, 17.0}, {2508, 16.8}, {2528, 16.5}, {2595, 
16.6}, {2599, 15.7}, {2604, 15.2}, {2612, 15.0}, {2637, 
14.7}, {2651, 14.6}, {2660, 14.5}, {2760, 13.6}, {2769, 
13.6}, {2805, 13.2}, {2844, 12.9}, {2880, 12.6}, {2904, 
12.4}, {3040, 12.4}, {3081, 12.1}, {3189, 11.6}, {3221, 
11.5}, {3314, 10.7}, {3602, 12.5}, {3610, 12.1}, {3624, 
12.0}, {3635, 12.0}, {3640, 11.7}, {3735, 11.1}, {3765, 
11.1}, {3797, 11.0}, {4066, 7.71}, {4072, 8.20}, {4120, 
5.91}, {4123, 5.78}, {4129, 5.61}, {4169, 4.77}, {4174, 
4.69}, {4183, 4.56}, {4188, 4.45}, {4194, 4.40}, {4200, 
4.36}, {4221, 4.13}, {4345, 4.47}, {4360, 4.39}, {4492, 
3.83}, {4501, 4.22}, {4503, 4.33}, {4550, 3.99}, {4567, 
3.94}, {4574, 3.93}, {4580, 3.92}, {4600, 3.95}, {4652, 
3.79}, {4679, 3.56}, {4794, 3.49}, {4842, 3.59}, {5049, 
4.37}, {5094, 4.47}, {5124, 3.94}, {5167, 3.11}, {5172, 
3.07}, {5210, 2.92}, {5278, 2.78}, {5314, 2.76}, {5327, 
2.75}, {5442, 2.81}, {5479, 2.79}, {5565, 2.72}, {5580, 
2.71}, {5768, 2.26}, {5929, 1.03}, {5941, 1.03}, {5948, 
1.03}, {6000, 1.01}, {6058, 0.992}, {6059, 1.14}, {6210, 
1.04}, {6328, 0.977}, {6330, 0.998}, {6333, 1.01}, {6351, 
1.01}, {6420, 1.00}, {6434, 0.964}, {6441, 1.02}, {6611, 
1.01}, {6661, 1.00}, {6696, 1.03}, {6908, 0.968}}

And the additional information i wanted to display in question 1 was:

Integrate[
  Interpolation[dataNi59s, InterpolationOrder -> 1][x], 
  {x, dataNi59s[[1, 1]], dataNi59s[[-1, 1]]}] /
(Subtract @@ dataNi59s[[{-1, 1}, 1]])

Which comes out to be 10.63 for this data set. It's the average current, I wanted to display something along the lines of 'Average Current: 10.63 uA' in some of the empty space of the plot, probably near the top right.

$\endgroup$

1 Answer 1

6
$\begingroup$

I can give some advice, but without the data needed to recreate the plot, I can't show you the actual code for implementing my suggestions.

  1. This request is unclear but the answer is most likely 'yes', but I would need more information to give any useful advice.

  2. This is easy. Look at Epilog and InfiniteLine in the docs.

  3. Break your plot into two data sets at the discontinuity. Add a dashed line between the two points you call out, again with Epilog.

  4. Don't use plot markers -- add your points with Point, again with Epilog.

  5. Answer to 4 takes care of this.

P.S. You don't need HoldForm wrapper for strings, they are atomic and don't need to be protected from evaluation.

Update

With data at hand, I can post code.

{Ni59s[1], Ni59s[2]} = SplitBy[dataNi59s, #[[1]] < 1850 &];
avgCurrent = 
  Integrate[
    Interpolation[dataNi59s, InterpolationOrder -> 1][x], 
    {x, dataNi59s[[1, 1]], dataNi59s[[-1, 1]]}]/(Subtract @@ dataNi59s[[{-1, 1}, 1]]);
ListLinePlot[
  {Callout[Ni59s[1], "Ni59s ≤ 1805", {1500, 22.5}, Ni59s[1][[34]]],
   Callout[Ni59s[2], "Ni59s ≥ 1869", {3365, 17}, Ni59s[2][[33]]]},
  PlotRange -> {{0, 7000}, {0, 25}},
  PlotStyle -> {Directive[Darker[Cyan, .23], AbsoluteThickness[2.5]]},
  PlotTheme -> "Detailed",
  Epilog ->
    {{Dashed, Line[{{1805, 14.5}, {1869, 21.6}}]},
     {Red, AbsolutePointSize[4], Point[dataNi59s]},
     {GrayLevel[.5], InfiniteLine[{{0, 1}, {1, 1}}]},
     Inset[
       Framed[
         Row[{"Average Current: ", avgCurrent, " μA"}],
         Background -> White, RoundingRadius -> 5],
       Scaled[{.85, .9}]]},
  PlotLabel -> "Comparison of Current Yields from Nickel Cathode 59 (Interpolated)(Anomolous Points Removed)",  
  LabelStyle -> {Black, Bold},
  Frame -> {{True, False}, {True, False}},
  FrameLabel -> {"Cathode Runtime (minutes)", "Current (\[Mu]A)"},
  ImageSize -> {850, 550},
  InterpolationOrder -> 2]

plot

I think you can see from this the important role Epilog plays in styling plots.

$\endgroup$
4
  • $\begingroup$ Hi m_goldberg,Thanks for the edits and reply. 1. I've added in the data set and a clarification for question 1 2. I did have a play around with Epilog after seeing it in another answer, but didn't manage to produce anything with it. I think I have found a way to do it using Show. I'll have another look at Epilog. 3. Is there any way to do it by keeping the full data set as one, as I imagine breaking the data set in two will make do any analytical things with the data as a whole set harder. 4. I'm not sure I understand this one, or the HoldForm thing. Cheers $\endgroup$
    – Epideme
    Nov 30, 2017 at 12:20
  • 1
    $\begingroup$ @Epideme. I have added code that implements the items you requested $\endgroup$
    – m_goldberg
    Nov 30, 2017 at 13:18
  • $\begingroup$ Okay - Epilog seems pretty useful. Consider that point well made. Thank you for your help, you've probably saved me many hours of headache. Also the solution of splitting the data was implemented far more elegantly than i was trying to do that. Can i include a legend in the graphic using Epilog also? (I have a similiar version of this graph but with 3 traces) $\endgroup$
    – Epideme
    Nov 30, 2017 at 14:27
  • $\begingroup$ Yes, it's possible place just about any kind of annotation in an Epilog option by using Inset. But there are other ways to identify traces in a multiple trace plot. Consider using Callout or Tooltip wrappers on the trace data. I have updated my plot to show the use of Callout, which I often find does a better job of conveying trace identity to the viewer. $\endgroup$
    – m_goldberg
    Nov 30, 2017 at 20:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.