6
$\begingroup$

Consider the following figure in .pdf format. Its .png version is below:

Enter image description here

I would like to digitize it, i.e., e.g., extract the data for the brown curve $a\to KK\pi$. How can I do this, using the fact the vector origin of the figure?

$\endgroup$

1 Answer 1

11
$\begingroup$

This answer seems to be version-dependent. It was created with

$Version

13.2.0 for Microsoft Windows (64-bit) (November 18, 2022)

Okay, let’s do this. We start off by loading the file into Mathematica while specifying that we want the graphics primitives:

imp = First@Import["a_rate.pdf", "PageGraphics"];

We notice that the graphics is mainly filled with joined curves which represents the lines. So we select them and plot this:

coordsLines = Cases[imp, _JoinedCurve, {0, Infinity}];
Graphics[coordsLines]

enter image description here

Okay cool, our sought-for line is there. Let’s filter the selection down a bit. We bet that our wanted line has a lot of coordinates. Let’s say, more than 100:

coordsLineSelected = Select[coordsLines, Length[#[[1, 1]]] > 100 &];
Graphics[coordsLineSelected]

Enter image description here

We're getting there. It’s just 21 lines left. Let’s just select them by brute force looking:

Table[Graphics[{LightGray}~Join~coordsLineSelected[[;; (i - 1)]]~Join~
   coordsLineSelected[[(i + 1) ;;]]~
   Join~{Red, coordsLineSelected[[i]],
    Text[ToString[i], {0, 0}]}], {i, 1, Length@coordsLineSelected}]

Enter image description here

Line 18 is the right one, right? So we have the coordinates. Unfortunately, they're in some coordinate system that we have to calibrate it against. However, we can extract the frame coordinates as well and thus get the minimum and maximum values of the respective components.

The x components are easy; they're linear. For y, we have to respect that it’s a log-scale.

sLineCoordinates=First[coordsLineSelected[[18,2]]]; (*get the coordinates of our line*)

frameLines=First@Select[coordsLines,2<Length[#[[1,1]]]<5&]; (*get the frame lines*)
{{xmin,xmax},{ymin,ymax}}=MinMax/@Transpose[frameLines[[2,1]]]; (*extract its coordinates*)

(*calibrate*)
x=(sLineCoordinates[[All,1]]-xmin)/(xmax-xmin)*3;
y=10^((sLineCoordinates[[All,2]]-ymin)/(ymax-ymin)*10-3);

(*plot*)
final=Transpose[{x,y}];
ListLogPlot[final,Joined->True,PlotRange->{{0,3},{10^-3,10^7}}]

Enter image description here

It should be about right.

In Total:

ListLogPlot[Table[
  currentCoords = First[coordsLineSelected[[i, 2]]];
  Transpose[{(currentCoords[[All, 1]] - xmin)/(xmax - xmin)*3,
    10^((currentCoords[[All, 2]] - ymin)/(ymax - ymin)*10 - 3)}]
  , {i, 1, Length@coordsLineSelected}]
 , Joined -> True, PlotRange -> {{0, 3}, {10^-3, 10^7}}]

enter image description here


Edit to address the question of searching for a specific color.

Funnily enough, this is as easy as the last steps. We notice, that color in the primitives is always (at least in this specific plot) imparted by a Style call. The structure seems to be always the same: Style[{JoinedCurve[..]},style1,style2,...] So, we rewrite our Cases call to incorporate this information (and while we're at it, we convert the colors to RGB)

coloredElements=Cases[imp,
    Style[{curve_JoinedCurve,___},___,color_?ColorQ]:>{PadRight[ColorConvert[color,"RGB"],4,1],curve},
{0,Infinity}];

The PadRight is there to account for uniform transparency information so we always are presented with an {r,g,b,a} vector.

Now we define a color to search for

seekedForColor = Darker@Brown;

Now its just a matter of defining a distance-norm of the color of the line and the seeked for color. Sort this list and plot it:

colorSortedLines = SortBy[
   {
      #1, #2,
      Norm[
       (List @@ #1) - (PadRight[
          List @@ ColorConvert[seekedForColor, "RGB"], 4, 1])
       ]
      } & @@@ coloredElements,
   Last];

Graphics[{#1, #2}, PlotLabel -> #1] & @@@ colorSortedLines

enter image description here

The first two lines describe the lines we want to have (they're the same color and the first is the negative infinity stretching extensions of the second data line).

We successfully selected the right lines by color.

$\endgroup$
6
  • $\begingroup$ Very interesting answer! Unfotunately Mathematica v12.2 doesn't evaluate Import["c:\\mathematica\\a_rate.pdf", "PageGraphics"] doesn't evaluate. What's your Mathematica version? Thanks $\endgroup$ Mar 1 at 9:49
  • $\begingroup$ Uhh didn't knew that this was version dependent. I'm currently on 13.2.0 for Windows. I'll add a disclaimer above. $\endgroup$ Mar 1 at 10:03
  • $\begingroup$ Thanks! Could you please tell me what would be the analog for _JoinedCurve if the curve is dashed? $\endgroup$ Mar 1 at 12:38
  • $\begingroup$ All dashed lines from your original graph are present as JoinedCurve objects. Some of them don't survive the inital filtering (below 100 pts.) though. $\endgroup$ Mar 1 at 16:22
  • 1
    $\begingroup$ nice, and upvoted, but: is there a way to extract it by color? (OP asked for "the brown curve" ...) $\endgroup$
    – davidbak
    Mar 1 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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