Group Abstract Group Abstract

Message Boards Message Boards

Can I print and use data generated by Streamplot?

GROUPS:
 I need to trace a pattern onto a substrate. The pattern is easily definable by a vector field. My idea was to produce a streamline plot, and then use the data points that define each stream to make the pattern. I need from StreamPlot  to produce uniform streams with a given average spacing, and then make the data points from each stream available for printing to a file. I don't care where the starting points are, just that the streams are uniform. 

Mathematica does a beautiful job of creating the streamplot, but I can't find any way to retreive the data. I was hoping to avoid having to write a semi complicated routine in another language.

Thanks!   
POSTED BY: Bryce Murray
Answer
1 year ago
This can be done by a slightly "hacky" way WITHIN Mathematica. You may find the data info behind the graphics obj by hitting shift+ctrl+E (on mac: use cmd instead of ctrl) after you choose the graphics. Please follow the short example: 
plt = StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3}]
Now you should have a plot stored in the variable "plt". Then use the Part function ([[ ]]) to extract the information from the data list, which is “plt“ as well. The actual index may vary depends upon the graphics object you have. In this paticular case, you can see the data for one stream line 
plt[[1, 2, 1, 2]]
You may see the single stream line with graphics command:

 To find all such lines, you can use Manipulate to sweep over all possibilities: 
Manipulate[
Graphics[plt[[1, 2, n, 2]], PlotRange -> {{-3, 3}, {-3, 3}}]
, {n, 1, 65, 1}]

Eventually, you may use the following subroutine to extract the actual data points : 
DeleteCases[
Flatten[plt[[1, 2, 1, 2]] //. {Arrowheads[_] -> Null, Arrow[x_] -> List[x]}, 3], Null]
Basically it first replaces the Arrowheads objects with Null and Arrow objects with List. It deletes the Null's and converts the list to a proper form with the Flatten function.  

The final result 
POSTED BY: Shenghui Yang
Answer
1 year ago
Shenghui Yang gave you a very nice answer showing that in Mathematica Everything Is an Expression,, including graphics objetcs. I just would like to mention a few related things. For example you can look inside them simply with InputForm function that will show you how original analytic expression got transformed into graphics primitives.
StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3}] // InputForm
I think simplest way to show point array of underlying dtata is
pts = StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3}, PerformanceGoal -> "Speed"][[1, 2, 1]];

Graphics[Point[pts]]


Another thought came to mind. I am not sure what kind of "pattern onto a substrate" you dealing with. But few most beautiful stream patterns I've seen were produced with LineIntegralConvolutionPlot:
LineIntegralConvolutionPlot[{{Cos[x^2 + y^3],
   Cos[y^2 + x^3]}, {Automatic, 500, 64}}, {x, -3, 3}, {y, -3, 3},
ColorFunction -> "Rainbow", LightingAngle -> 0, Frame -> False]
POSTED BY: Vitaliy Kaurov
Answer
1 year ago
@Vitaliy, I am thinking about making a rug that looks like the picture in your post ! :-)
POSTED BY: Shenghui Yang
Answer
1 year ago
Thanks Shanghui Yang, this is exactly what I was looking for.
It looks like InputForm can be used to look inside the plot object to see how it is indexed, so that is very useful as well. At first glance, though, the output from that command looks messy. 

If you don't mind a follow up question, there was one more thing I needed to make this work. I need to pack the streams in pretty tight, tighter than mathematica wants to do on its own. It will make a really ugly plot, to be fair. Can I specify a maximum distance between lines, or a very tight average spacing goal for StreamPlot? I have tried using StreamPoints, but the documentation only describes how to specify a minimum distance between points.  
POSTED BY: Bryce Murray
Answer
1 year ago
The easiest way is to add many random points in the range of plot. Remember the definition of the stream lines that they do not touch other, so you can just scatter points in the plotting field to make them the points that must be passed by a stream line. An improved vector field plot is like this:
  StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3},StreamPoints->RandomReal[{-3,3},{5000,2}]]
The problem with this method is the low efficiency, the more points in a closed space, the more likely some of them falls on the same stream line. On the other hand, this also tells you that it is very computationally expensive to create a global dense stream plot. If you run the following code:
neighboringPoints = RandomReal[{-0.1, 0.1}, 100];
StreamPlot[{-1 - x^2 + y, 1 + x - y^2}, {x, -3, 3}, {y, -3, 3},
StreamPoints -> ({1, -0.9 + #} & /@ neighboringPoints),
PlotRange -> {{0.5, 1.5}, {-1.5, -0.5}}]
you will find that Mathematica actually prevents itself from plotting a extremely compact field. If not, the process might kill the front end kernel. 
POSTED BY: Shenghui Yang
Answer
1 year ago