1
$\begingroup$

I wanted to created callout for my plot, the plot is created by:

data with na22: https://ufile.io/6gw0s2aq

peaks = {{398, 0.511}, {495, 0.662}, {819, 1.173}, {921, 1.332}};

lm = LinearModelFit[peaks, x, x]

ListPlot[{lm[First[#]], Last[#]} & /@ na22, 
 PlotRange -> {{0, All}, All}, 
 FrameLabel -> {"Energy (MeV)", "Counts"}, 
 RotateLabel -> True, Frame -> {{True, False}, {True, False}}, 
 PlotLegends -> 
  Placed[{"\!\(\*SuperscriptBox[\(\[InvisiblePrefixScriptBase]\), \
\(22\)]\)Na"}, Above]]

But after adding callout: Callout[4680,"Peak",Above] I get an error:

error

How label should be created?

$\endgroup$
0
3
$\begingroup$

EDIT: Using your data, the solution is the same: Callout is a wrapper ("Callout[data, expr, ...] can be used as a wrapper in visualization functions ...") not a ListPlot option.

na22 = Import["/Users/roberthanlon/Downloads/na22.txt", "Table"];

peaks = {{398, 0.511}, {495, 0.662}, {819, 1.173}, {921, 1.332}};

lm = LinearModelFit[peaks, x, x];

data = {lm[First[#]], Last[#]} & /@ na22;

maxPt = Select[data, #[[2]] == Max[data[[All, 2]]] &][[1]]

(* {0.51043, 4680} *)

ListPlot[
 data /. maxPt :> Callout[maxPt, "Peak", Above],
 FrameLabel -> {"Energy (MeV)", "Counts"},
 RotateLabel -> True,
 Frame -> {{True, False}, {True, False}},
 ImageSize -> Large]

enter image description here

EDIT 2: For multiple peaks use FindPeaks

Manipulate[
 Module[{peaks, n, repl},
  peaks = ReverseSortBy[
    data[[FindPeaks[data[[All, 2]], 4, Automatic, threshold][[All, 
        1]]]], Last];
  n = 1;
  repl = (# -> Callout[#, "Peak " <> ToString[n++], Above] & /@ peaks);
  ListPlot[data /. repl,
   FrameLabel -> {"Energy (MeV)", "Counts"},
   RotateLabel -> True,
   Frame -> {{True, False}, {True, False}},
   ImageSize -> Large]],
 {{threshold, 2000}, {5, 15, 20, 25} 100,
  ControlType -> SetterBar}]

enter image description here

EDIT 3: For arbitrary points with arbitrary labels:

Module[{peaks, repl, labels},
 peaks = Select[data, #[[2]] == 4680 || #[[2]] == 507 &];
 labels = {
   StringForm["`` label", Superscript["1", "st"]], 
   StringForm["`` label", Superscript["2", "nd"]]};
 repl = (#[[1]] -> Callout[#[[1]], #[[2]], Above] & /@
    Transpose[{peaks, labels}]);
 ListPlot[data /. repl,
  FrameLabel -> {"Energy (MeV)", "Counts"},
  RotateLabel -> True,
  Frame -> {{True, False}, {True, False}},
  ImageSize -> Large]]
$\endgroup$
6
  • $\begingroup$ Is it possible to easy add second "peak" label to another point? $\endgroup$ Nov 16 '21 at 0:29
  • $\begingroup$ In the Manipulate, set the threshold to 2000 and only the highest two peaks will be labeled. Or extract the Module and replace threshold in the extracted code with 2000 $\endgroup$
    – Bob Hanlon
    Nov 16 '21 at 14:57
  • $\begingroup$ You edited the answer. I just wanted to label two peaks manually from the list without using manipulate, just list: peaks = {{0.51043, 4680}}, {{1.26648, 507}}; $\endgroup$ Nov 16 '21 at 14:57
  • $\begingroup$ Extract the Module. In the extracted code replace the definition of peaks with your definition of peaks $\endgroup$
    – Bob Hanlon
    Nov 16 '21 at 15:05
  • $\begingroup$ It works, but how to use own name for each peak? $\endgroup$ Nov 16 '21 at 15:10

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.