# How to extract data from contour plot as a text file?

I have the following expression from which I want to extract data for a contour plot.

a = (r^2/2 + (r BesselI[1, 2 r])/(
2 BesselI[0,
2 (1 + 0.24 z + 0.2 Sin[6.2834 z])])) (1.386371389484812 +
0.4367320268554276 (2.289733608959785 -
0.7936052912509126 (1 + 0.24 z +
0.2 Sin[6.2834 z])^2) + (-45.44 BesselI[0,
2 (1 + 0.24 z + 0.2 Sin[6.2834 z])] -
4 (1.386371389484812 +
0.4367320268554276 (2.289733608959785 -
0.7936052912509126 (1 + 0.24 z +
0.2 Sin[6.2834 z])^2) +
0.346592847371203 (1 + 0.24 z +
0.2 Sin[6.2834 z])^2) (4 BesselI[1,
2 (1 + 0.24 z + 0.2 Sin[6.2834 z])] (1 + 0.24 z +
0.2 Sin[6.2834 z]) -
4 BesselI[0,
2 (1 + 0.24 z + 0.2 Sin[6.2834 z])] (1 + 0.24 z +
0.2 Sin[6.2834 z])^2))/(4 (BesselI[1,
2 (1 + 0.24 z + 0.2 Sin[6.2834 z])] -
4 BesselI[0,
2 (1 + 0.24 z + 0.2 Sin[6.2834 z])] (1 + 0.24 z +
0.2 Sin[6.2834 z])^2)) +
0.346592847371203 (1 + 0.24 z + 0.2 Sin[6.2834 z])^2);

ContourPlot[a, {z, 0, 1.5}, {r, 3, 5.5},
PlotPoints -> 180, Frame -> True, FrameStyle -> {Thickness[0.0005]},
Axes -> False, FrameStyle -> {Thickness[0.0005]}, ContourShading -> False]


The output should be a text file.

-
Related: (19859) –  Mr.Wizard Apr 17 at 17:20

## Original answer

For getting points of individual lines one can use Normal:

points = Cases[Normal@plot, Line[pts_, ___] :> pts, Infinity];


(I assumed here that each Line primitive contains exactly one line, as it is true for the current ContourPlot implementation. Generally, a Line primitive can contain several lines and for this case this code should be rewritten, for example:

points = Cases[Normal@plot, Line[pts_, ___] :> Flatten[pts, Depth[pts] - 3], Infinity];


)

To convert this list of lists of points into multicolumn table one can use:

multicolumnTable = Flatten /@ Flatten[PadRight[points, Automatic, ""], {2}];


Here is how it looks:

TableForm[multicolumnTable[[;; 10, ;; 6]],
TableHeadings -> {None, Flatten@Array[{x@#, y@#} &, Length[points]]}]


Exporting the multicolumn table:

Export["table.tsv", multicolumnTable]


## Extracting the values of the objective function (per request in comments)

The 2D Graphics object generated by ContourPlot does not necessarily contain information on the values of the objective function (Z-coordinate). The only source of this information are contour labels which are generated according to the ContourLabels option. With the default value ContourLabels->Automatic each contour is wrapped by Tooltip with second argument being the contour label providing information on the value of the objective function. In the current ContourPlot implementation the label is simply a number and the contour is one or more Line primitives each containing exactly one actual line. Assuming that the plot does not contain any other Tooltips, it is straightforward to extract the data:

points = Flatten[
Cases[Normal@plot,
Tooltip[contour_, label_] :>
Cases[contour, l_Line :> ArrayPad[First@l, {{0}, {0, 1}}, label]],
Infinity], 1];
multicolumnTable = Flatten /@ Flatten[PadRight[points, Automatic, ""], {2}];
TableForm[multicolumnTable[[;; 10, ;; 6]],
TableHeadings -> {None, Flatten@Array[{x@#, y@#, z@#} &, Length[points]]}]
Export["table.tsv", multicolumnTable]


-
This is working fine. THx to you and to Nasser. –  MMM Sep 8 '13 at 12:15
how to treat the contourplot as a 3D plot and extract the data having three columns with r, z, and a(r,z)? –  MMM Aug 16 '14 at 1:44
@MMM What you want is generally impossible to achieve because the Graphics object generated by ContourPlot not necessarily contains information on the values of the objective function. The only place where it can be is created by ContourLabels function which is (in general) arbitrary. –  Alexey Popkov Aug 16 '14 at 2:35
@MMM Probably it would be simpler to use Plot3D with options MeshFunctions->{#3&}, Mesh->5 and then apply the approach described in my answer for extracting the mesh lines. Everything should be the same with exception to the TableForm where instead of Array[{x@#, y@#} &, Length[points]] you should have Array[{x@#, y@#, z@#} &, Length[points]]. –  Alexey Popkov Aug 16 '14 at 2:36
@MMM But if you insist on using ContourPlot it is also possible to extract the values of the objective function when the default setting ContourLabels->Automatic is used (at least with the current implementation of ContourPlot). I'll add a method to my answer. –  Alexey Popkov Aug 16 '14 at 2:48

Update

If you want the coordinates, then

SetDirectory[NotebookDirectory[]];
data = Cases[plot, GraphicsComplex[pts__] :> pts, Infinity];
Export["data.txt", data[[1]]];

Dimensions[data[[1]]]
(* {55340, 2} *)
data[[1, 1 ;; 10, All]] // MatrixForm


FullForm of the plot shows the GraphicsComplex

and GraphicsComplex has this form

Original answer

plot = ContourPlot[a, {z, 0, 1.5}, {r, 3, 5.5}, PlotPoints -> 180,
Frame -> True, Axes -> False, ContourShading -> False];
data = Cases[plot, Line[pts_] :> pts, Infinity];
SetDirectory[NotebookDirectory[]];
Export["data.txt", data];


-
Well, @Nasser thx for your response. Its seems to me that the output is not in the correct format. The output should be in two columns r and z. –  MMM Sep 8 '13 at 6:28
You asked for contour data. The above is the contour data. There are 11 rows. One for each contour. –  Nasser Sep 8 '13 at 6:30
You are right but I need to have the data in 2 columns format. –  MMM Sep 8 '13 at 6:37
@MMM I do not follow you. Where did this 2 columns come from and what they represent? May be all what you needed then is a simple Table command. You have to be clear what is it you want as I am not really following you. –  Nasser Sep 8 '13 at 6:41
Let me try to make it clear, I want the data in following format. r z (say contour 1) r z (say contour 2) r z (say contour 3) Output in two columns for each contour. Clear? –  MMM Sep 8 '13 at 6:45