0
$\begingroup$

I have a plot which is the output of a ParametricPlot command, and I want to save the data to a file, ideally with the columns x, y, parameter.

I'm aware of the methods in the answer to this question: Plot, extract data to a file, but I am having trouble adapting them to the parametric case - if I take only the first line of the Cases command, one coordinate seems to be missing, but taking all the lines, I have duplicate data, and I am not sure how the data are arranged.

Apologies if this is a stupid question, I am a Mathematica beginner.

EDIT 2: the simple, clean and robust solution posted by JimB in the comments solved my problem. It was indeed a stupid question.

EDIT: I originally posted a MWE derived from my code, and the answers I got solved the MWE. Unfortunately, my original code is still causing issues. The original MWE is at the end of this question.

This code generates the plot:

Gamma = 0.5; 
Beta = 1; 
f[w_, T_] := Exp[(-T)*I*w]/(1 + Beta*I*w); 
g[w_, T_] := Conjugate[1/f[w, T]] - Gamma*Exp[I*Arg[1/f[w, T]]]; 
h[w_, T_] := Conjugate[1/g[w, T]]; 
p = ParametricPlot[{Re[h[w, 1]], Im[h[w, 1]]}, {w, -Pi, 0}, 
   PlotRange -> {{-0.7, 2.1}, {0, 1.1}}]

This code extracts some of the data, but only the 3rd quadrant:

test1 = Cases[Normal[p], Line[pts_] :> pts, Infinity][[1]]

This code extracts all of the data, but out of order:

test2 = Reap[ParametricPlot[{Sow[{Re[h[w, 1]], Im[h[w, 1]]}]}, {w, -Pi, 0}, 
     PlotRange -> {{-0.7, 2.1}, {0, 1.1}}]]; 

This code gives an error about indices outside the range of the data:

pos = Append[Drop[Flatten[Position[p, Line]], -1], 1]
test3 = p[[Sequence @@ pos]]

Following is the original MWE

My codes is as follows:

k[w_] := Exp[(-I)*w]/(1 + I*w); 
p = ParametricPlot[{Re[k[w]], Im[k[w]]}, {w, -Pi, 0}, 
    PlotRange -> {{-0.7, 2.1}, {0, 1.1}}]; 
data = Cases[Normal[p], Line[pts_] :> pts, Infinity]; 
Export["data.txt", data, "Table"]

My second attempt is to use the technique in the answer to this question: Extract data from a Parametric2D plot. This is looking more hopeful, but the data is again in a weird order, I am not sure how to get it into a table.

data = Reap[
  ParametricPlot[{Sow[Re[k[w]]], Sow[Im[k[w]]]}, {w, -Pi, 
    0}, PlotRange -> {{-0.7, 2.1}, {0, 1.1}}]]
$\endgroup$
10
  • $\begingroup$ For me the first code seems to work fine, where the srgData[[1]] is the resulting table. The second could be midfield to data = Reap[ ParametricPlot[{Sow[{Re[k[w]], Im[k[w]]}]}, {w, -Pi, 0}, PlotRange -> {{-0.7, 2.1}, {0, 1.1}}]] and then data[[2,1]] is the table. $\endgroup$ – Andrzej Jun 16 at 14:32
  • $\begingroup$ Apologies @Moo, I've edited it to fix that. $\endgroup$ – chaffdog Jun 16 at 15:05
  • $\begingroup$ @Andrzej, you are right. It works fine. It seems that in constructing a MWE, I've accidentally made it work... looking into it now $\endgroup$ – chaffdog Jun 16 at 15:13
  • 2
    $\begingroup$ Why not just generate a table of points? p = Table[{w, Re[k[w]], Im[k[w]]}, {w, -Pi, 0, Pi/500}]; p = Select[p, 0 <= #[[3]] <= 1.1 && -0.7 <= #[[2]] <= 2.1 &]; I know the "spacing" of the points is nicer with ParametricPlot but does that really matter for what you want to do? $\endgroup$ – JimB Jun 16 at 15:23
  • $\begingroup$ I agree with Jim, especially if you're a beginner. Why not use something clean, robust and simple instead of a fragile hack? $\endgroup$ – Szabolcs Jun 16 at 15:39
1
$\begingroup$

You might consider just generating a table of points. The downside is that the spacing of the points might not be as optimal as what you get with harvesting the points from ParametricPlot.

Using your example with 500 points:

k[w_] := Exp[(-I)*w]/(1 + I*w);
p = Table[{w, Re[k[w]], Im[k[w]]}, {w, -Pi, 0, Pi/500}];
p = Select[p, 0 <= #[[3]] <= 1.1 && -0.7 <= #[[2]] <= 2.1 &];
ListPlot[p[[All, {2, 3}]], Joined -> True]

Plot of table of points

You might have to play with the number of points as using just 50 points might not be adequate for the function of interest. Here's what you get with your function and 50 points without connecting the points:

k[w_] := Exp[(-I)*w]/(1 + I*w);
p = Table[{w, Re[k[w]], Im[k[w]]}, {w, -Pi, 0, Pi/50}];
p = Select[p, 0 <= #[[3]] <= 1.1 && -0.7 <= #[[2]] <= 2.1 &];
ListPlot[p[[All, {2, 3}]], PlotStyle -> Red, PlotRangeClipping -> False]

Plot of table of points with just 50 points

$\endgroup$
2
$\begingroup$

In this case, I would do as follows. Here is your plot:

k[w_] := Exp[(-I)*w]/(1 + I*w);
p = ParametricPlot[{Re[k[w]], Im[k[w]]}, {w, -Pi, 0}, 
  PlotRange -> {{-0.7, 2.1}, {0, 1.1}}];

This is the position of the line you are looking for in the form of a list:

Position[p, Line] // Flatten

(*  {1, 1, 1, 3, 1, 2, 0}  *)

One only needs to replace the figure 0 at the end of this list by 1 in order to point to the list staying under the Line, rather than the head Line:

pos = Append[Drop[Position[p, Line] // Flatten, -1], 1]

(*  {1, 1, 1, 3, 1, 2, 1}  *)

Now here is your data:

data = p[[Sequence @@ pos]]

You can export it in any form of your liking.

Have fun!

Edit: In your edited case do the following:

pos1 = Append[Drop[Position[p, Line][[2]], -1], 1];
pos2 = Append[Drop[Position[p, Line][[3]], -1], 1];
data = Join[p[[Sequence @@ pos1]], p[[Sequence @@ pos2]]];

Let us check:

ListPlot[data]

yields

enter image description here

as expected.

Have fun!

$\endgroup$
6
  • $\begingroup$ Hi Alexei, thanks very much! This works well for the MWE I posted in the example. Sadly, I didn't realise that I had changed something important in the MWE, and my original issue is still not sorted. I'm going to update the question now. Very sorry for this. $\endgroup$ – chaffdog Jun 16 at 15:27
  • $\begingroup$ Also, I don't really have any idea what "the line I'm looking for" is, could you explain a little? $\endgroup$ – chaffdog Jun 16 at 15:27
  • 1
    $\begingroup$ Have a look at the edit. $\endgroup$ – Alexei Boulbitch Jun 16 at 19:57
  • $\begingroup$ Cases[p, Line[p_] :> p, All][[1]] gives the complete list of points $\endgroup$ – Ulrich Neumann Jun 17 at 8:13
  • $\begingroup$ @Ulrich Neumann In general, I also thought like this. However, if you do the following: lst = Cases[p, Line[p_] :> p, All][[1]]; ListPlot[lst] you will see the difference between the plot obtained like this and the original one. Only take care that p should be taken from the newly edited OP code. $\endgroup$ – Alexei Boulbitch Jun 17 at 11:06

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.