VertexCoordinate Rules and VertexList from GraphPlot Graphic - wolfram-mathematica

Is there any way of abstracting the vertex order that GraphPlot applies to VertexCoordinate Rules from the (FullForm or InputForm) of the graphic produced by GraphPlot? I do not want to use the GraphUtilities function VertexList. I am also aware of GraphCoordinates, but both of these functions work with the graph, NOT the graphics output of GraphPlot.
For example,
gr1 = {1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 1};
gp1 = GraphPlot[gr1, Method -> "CircularEmbedding",
VertexLabeling -> True];
Last#(gp1 /. Graphics[Annotation[x___], ___] :> {x})
gives the following list of six coordinate pairs:
VertexCoordinateRules -> {{2., 0.866025}, {1.5, 1.73205}, {0.5,
1.73205}, {0., 0.866025}, {0.5, 1.3469*10^-10}, {1.5, 0.}}
How do I know which rule applies to which vertex, and can I be certain that this is
the same as that given by VertexList[gr1]?
For example
Needs["GraphUtilities`"];
gr2 = SparseArray#
Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]];
VertexList[gr2]
gives {1, 2, 3, 4, 5}
But ....
gp2 = GraphPlot[gr2, VertexLabeling -> True,
VertexCoordinateRules ->
Thread[VertexList[gr1] ->
Last#(gp1 /. Graphics[Annotation[x___], ___] :> {x})[[2]]]];
Last#(gp2 /. Graphics[Annotation[x___], ___] :> {x})
gives SIX coordinate sets:
VertexCoordinateRules -> {{2., 0.866025}, {1.5, 1.73205}, {0.5,
1.73205}, {0., 0.866025}, {0.5, 1.3469*10^-10}, {1.5, 0.}}
How can I abstract the correct VertexList for VertexCoordinateRules for gr2, for example?
(I am aware that I can correct things by taking the VertexList after generating gr2 as follows, for example)
VertexList#
SparseArray[
Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]], {6, 6}]
{1, 2, 3, 4, 5, 6}
but the information I need appears to be present in the GraphPlot graphic: how can I obtain it?
(The reason I convert the graph to an adjacency matrix it that, as pointed out by Carl Woll of Wolfram, it allows me to include an 'orphan' node, as in gp2)

With vertex labeling, one way is to get coordinates of the labels. Notice that output of GraphPlot is in GraphicsComplex where coordinates of coordinate aliases are as first label, you can get it as
points = Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // First
Looking at FullForm you'll see that labels are in text objects, extract them as
labels = Cases[gp1, Text[___], Infinity]
The actual label seems to be two levels deep so you get
actualLabels = labels[[All, 1, 1]];
Coordinate alias is the second parameter so you get them as
coordAliases = labels[[All, 2]]
Actual coordinates were specified in GraphicsComplex, so we get them as
actualCoords = points[[coordAliases]]
There a 1-1 correspondence between list of coordinates and list of labels, so you can use Thread to return them as list of "label"->coordinate pairs.
here's a function that this all together
getLabelCoordinateMap[gp1_] :=
Module[{points, labels, actualLabels, coordAliases, actualCoords},
points =
Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] //
First;
labels = Cases[gp1, Text[___], Infinity];
actualLabels = labels[[All, 1, 1]];
coordAliases = labels[[All, 2]];
actualCoords = points[[coordAliases]];
Thread[actualLabels -> actualCoords]
];
getLabelCoordinateMap[gp1]
Not that this only works on labelled GraphPlot. For ones without labels you could try to extract from other graphics objects, but you may get different results depending on what objects you extract the mapping from because there seems to be a bug which sometimes assigns line endpoints and vertex labels to different vertices. I've reported it. The way to work around the bug is to either always use explicit vertex->coordinate specification for VertexCoordinateList, or always use "adjacency matrix" representation. Here's an example of discrepancy
graphName = {"Grid", {3, 3}};
gp1 = GraphPlot[Rule ### GraphData[graphName, "EdgeIndices"],
VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"],
VertexLabeling -> True]
gp2 = GraphPlot[GraphData[graphName, "AdjacencyMatrix"],
VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"],
VertexLabeling -> True]
BTW, as an aside, here are the utility functions I use for converting between adjacency matrix and edge rule representation
edges2mat[edges_] := Module[{a, nodes, mat, n},
(* custom flatten to allow edges be lists *)
nodes = Sequence ### edges // Union // Sort;
nodeMap = (# -> (Position[nodes, #] // Flatten // First)) & /#
nodes;
n = Length[nodes];
mat = (({#1, #2} -> 1) & ### (edges /. nodeMap)) //
SparseArray[#, {n, n}] &
];
mat2edges[mat_List] := Rule ### Position[mat, 1];
mat2edges[mat_SparseArray] :=
Rule ### (ArrayRules[mat][[All, 1]] // Most)

If you execute FullForm[gp1] you'll get a bunch of output which I won't post here. Near the start of the output you'll find a GraphicsComplex[]. This is, essentially, a list of points and then a list of uses of those points. So, for your graphic gp1 the beginning of the GraphicsComplex is:
GraphicsComplex[
List[List[2., 0.866025], List[1.5, 1.73205], List[0.5, 1.73205],
List[0., 0.866025], List[0.5, 1.3469*10^-10], List[1.5, 0.]],
List[List[RGBColor[0.5, 0., 0.],
Line[List[List[1, 2], List[2, 3], List[3, 4], List[4, 5],
List[5, 6], List[6, 1]]]],
The first outermost list defines the positions of 6 points. The second outermost list defines a bunch of lines between those points, using the numbers of the points within the first list. It's probably easier to understand if you play around with this.
EDIT: In response to OP's comment, if I execute:
FullForm[GraphPlot[{3 -> 4, 4 -> 5, 5 -> 6, 6 -> 3}]]
I get
Graphics[Annotation[GraphicsComplex[List[List[0.`,0.9997532360813222`],
List[0.9993931236462025`,1.0258160108662504`],List[1.0286626995939243`,
0.026431169015735057`],List[0.02872413637035287`,0.`]],List[List[RGBColor[0.5`,0.`,0.`],
Line[List[List[1,2],List[2,3],List[3,4],List[4,1]]]],List[RGBColor[0,0,0.7`],
Tooltip[Point[1],3],Tooltip[Point[2],4],Tooltip[Point[3],5],Tooltip[Point[4],6]]],
List[]],Rule[VertexCoordinateRules,List[List[0.`,0.9997532360813222`],
List[0.9993931236462025`,1.0258160108662504`],
List[1.0286626995939243`,0.026431169015735057`],List[0.02872413637035287`,0.`]]]],
Rule[FrameTicks,None],Rule[PlotRange,All],Rule[PlotRangePadding,Scaled[0.1`]],
Rule[AspectRatio,Automatic]]
The list of vertex positions is the first list inside the GraphicsComplex. Later in the FullForm you can see the list where Mathematica adds tooltips to label the vertices with the identifiers you supplied in the original edge list. Since what you are now looking at is the code describing a graphic there's only an indirect relationship between your vertices and what will be plotted; the information is all there but not entirely straightforward to unpack.

p2 = Normal#gp1 // Cases[#, Line[points__] :> points, Infinity] &;
p3 = Flatten[p2, 1];
ListLinePlot[p3[[All, 1 ;; 2]]]
V12.0.0

Related

How to choose the numbers shown on the axes of a plot in mathemetica?

I have already checked all the examples and settings in the Mathematica documentation center, but couldn't find any example on how to choose the numbers that will be shown on the axes.
How do I change plot axis numbering like 2,4,6,.. to PI,2PI,3PI,...?
Howard has already given the correct answer in the case where you want the labels Pi, 2 Pi etc to be at the values Pi, 2 Pi etc.
Sometimes you might want to use substitute tick labels at particular values, without rescaling data.
One of the other examples in the documentation shows how:
Plot[Sin[x], {x, 0, 10},
Ticks -> {{{Pi, 180 \[Degree]}, {2 Pi, 360 \[Degree]}, {3 Pi,
540 \[Degree]}}, {-1, 1}}]
I have a suite of small custom functions for formatting Ticks the way I want them. This is probably too much information if you are just starting out, but it is worth knowing that you can use any number format and substitute anything into your ticks if desired.
myTickGrid[min_, max_, seg_, units_String, len_?NumericQ,
opts : OptionsPattern[]] :=
With[{adj = OptionValue[UnitLabelShift], bls = OptionValue[BottomLabelShift]},
Table[{i,
If[i == max,
DisplayForm[AdjustmentBox[Style[units, LineSpacing -> {0, 12}],
BoxBaselineShift -> If[StringCount[units, "\n"] > 0, adj + 2, adj]]],
If[i == min,
DisplayForm#AdjustmentBox[Switch[i, _Integer,
NumberForm[i, DigitBlock -> 3,
NumberSeparator -> "\[ThinSpace]"], _, N[i]],
BoxBaselineShift -> bls],
Switch[i, _Integer, NumberForm[i, DigitBlock -> 3,
NumberSeparator -> "\[ThinSpace]"], _, N[i]]]], {len, 0}}, {i,
If[Head[seg] === List, Union[{min, max}, seg], Range[min, max, seg]]}]]
And setting:
Options[myTickGrid] = {UnitLabelShift -> 1.3, BottomLabelShift -> 0}
SetOptions[myTickGrid, UnitLabelShift -> 1.3, BottomLabelShift -> 0]
Example:
Plot[Erfc[x], {x, -2, 2}, Frame -> True,
FrameTicks -> {myTickGrid[-2, 2, 1, "x", 0.02, UnitLabelShift -> 0],
myTickGrid[0, 2, {0.25, .5, 1, 1.8}, "Erfc(x)", 0.02]}]
You can find an example here:
Ticks -> {{Pi, 2 Pi, 3 Pi}, {-1, 0, 1}}
Ticks also accepts a function, which will save you the trouble of listing the points manually or having to change the max value each time. Here's an example:
xTickFunc[min_, max_] :=
Table[{i, i, 0.02}, {i, Ceiling[min/Pi] Pi, Floor[max/Pi] Pi, Pi}]
Plot[Sinc[x], {x, -5 Pi, 5 Pi}, Ticks -> {xTickFunc, Automatic},
PlotRange -> All]
If you want more flexibility in customizing your ticks, you might want to look into LevelScheme.

Mathematica: 3D wire frames

Does Mathematica support hidden line removal for wire frame images? If this isn't the case, has anybody here ever come across a way to do it? Lets start with this:
Plot3D[Sin[x+y^2], {x, -3, 3}, {y, -2, 2}, Boxed -> False]
To create a wire frame we can do:
Plot3D[Sin[x+y^2], {x, -3, 3}, {y, -2, 2}, Boxed -> False, PlotStyle -> None]
One thing we can do to achieve the effect is to color the all the surfaces white. This however, is undesirable. The reason is because if we export this hidden line wire frame model to pdf we will have all of those white polygons that Mathematica uses to render the image. I want to be able to obtain a wire frame with hidden line removal in pdf and/or eps format.
UPDATE:
I have posted a solution to this problem. The problem is that the code runs very slow. In its current state it is unable to generate the wireframe for the image in this question. Feel free to play with my code. I added a link to it at the end of my post. You can also find the code in this link
Here I present a solution. First I will show how to use the function that generates the wire frame, then I will proceed to explain in detail the rest of the functions that compose the algorithm.
wireFrame
wireFrame[g_] := Module[{figInfo, opt, pts},
{figInfo, opt} = G3ToG2Info[g];
pts = getHiddenLines[figInfo];
Graphics[Map[setPoints[#] &, getFrame[figInfo, pts]], opt]
]
The input of this function is a Graphics3D object preferably with no axes.
fig = ListPlot3D[
{{0, -1, 0}, {0, 1, 0}, {-1, 0, 1}, {1, 0, 1}, {-1, 1, 1}},
Mesh -> {10, 10},
Boxed -> False,
Axes -> False,
ViewPoint -> {2, -2, 1},
ViewVertical -> {0, 0, 1},
MeshStyle -> Directive[RGBColor[0, 0.5, 0, 0.5]],
BoundaryStyle -> Directive[RGBColor[1, 0.5, 0, 0.5]]
]
Now we apply the function wireFrame.
wireFrame[fig]
As you can see wireFrame obtained most of the lines and its colors. There is a green line that was not included in the wireframe. This is most likely due to my threshold settings.
Before I proceed to explain the details of the functions G3ToG2Info, getHiddenLines, getFrame and setPoints I will show you why wire frames with hidden line removal can be useful.
The image shown above is a screenshot of a pdf file generated by using the technique described in rasters in 3D graphics combined with the wire frame generated here. This can be advantageous in various ways. There is no need to keep the information for the triangles to show a colorful surface. Instead we show a raster image of the surface. All of the lines are very smooth, with the exception of the boundaries of the raster plot not covered by lines. We also have a reduction of file size. In this case the pdf file size reduced from 1.9mb to 78kb using the combination of the raster plot and the wire frame. It takes less time to display in the pdf viewer and the image quality is great.
Mathematica does a pretty good job at exporting 3D images to pdf files. When we import the pdf files we obtain a Graphics object composed of line segments and triangles. In some cases this objects overlap and thus we have hidden lines. To make a wire frame model with no surfaces we first need to remove this overlap and then remove the polygons. I will start by describing how to obtain the information from a Graphics3D image.
G3ToG2Info
getPoints[obj_] := Switch[Head[obj],
Polygon, obj[[1]],
JoinedCurve, obj[[2]][[1]],
RGBColor, {Table[obj[[i]], {i, 1, 3}]}
];
setPoints[obj_] := Switch[Length#obj,
3, Polygon[obj],
2, Line[obj],
1, RGBColor[obj[[1]]]
];
G3ToG2Info[g_] := Module[{obj, opt},
obj = ImportString[ExportString[g, "PDF", Background -> None], "PDF"][[1]];
opt = Options[obj];
obj = Flatten[First[obj /. Style[expr_, opts___] :> {opts, expr}], 2];
obj = Cases[obj, _Polygon | _JoinedCurve | _RGBColor, Infinity];
obj = Map[getPoints[#] &, obj];
{obj, opt}
]
This code is for Mathematica 8 in version 7 you would replace JoinedCurve in the function getPoints by Line. The function getPoints assumes that you are giving a primitive Graphics object. It will see what type of object it recieves and then extract the information it needs from it. If it is a polygon it gets a list of 3 points, for a line it obtains a list of 2 points and if it is a color then it gets a list of a single list containing 3 points. This has been done like this in order to maintain consistency with the lists.
The function setPoints does the reverse of getPoints. You input a list of points and it will determine if it should return a polygon, a line or a color.
To obtain a list of triangles, lines and colors we use G3ToG2Info. This function will use
ExportString and ImportString to obtain a Graphics object from the Graphics3D version. This info is store in obj. There is some clean up that we need to perform, first we get the options of the obj. This part is necessary because it may contain the PlotRange of the image. Then we obtain all the Polygon, JoinedCurve and RGBColor objects as described in obtaining graphics primitives and directives. Finally we apply the function getPoints on all of these objects to get a list of triangles, lines and colors. This part covers the line {figInfo, opt} = G3ToG2Info[g].
getHiddenLines
We want to be able to know what part of a line will not be displayed. To do this we need to know point of intersection between two line segments. The algorithm I'm using to find the intersection can be found here.
lineInt[L_, M_, EPS_: 10^-6] := Module[
{x21, y21, x43, y43, x13, y13, numL, numM, den},
{x21, y21} = L[[2]] - L[[1]];
{x43, y43} = M[[2]] - M[[1]];
{x13, y13} = L[[1]] - M[[1]];
den = y43*x21 - x43*y21;
If[den*den < EPS, Return[-Infinity]];
numL = (x43*y13 - y43*x13)/den;
numM = (x21*y13 - y21*x13)/den;
If[numM < 0 || numM > 1, Return[-Infinity], Return[numL]];
]
lineInt assumes that the line L and M do not coincide. It will return -Infinity if the lines are parallel or if the line containing the segment L does not cross the line segment M. If the line containing L intersects the line segment M then it returns a scalar. Suppose this scalar is u, then the point of intersection is L[[1]] + u (L[[2]]-L[[1]]). Notice that it is perfectly fine for u to be any real number. You can play with this manipulate function to test how lineInt works.
Manipulate[
Grid[{{
Graphics[{
Line[{p1, p2}, VertexColors -> {Red, Red}],
Line[{p3, p4}]
},
PlotRange -> 3, Axes -> True],
lineInt[{p1, p2}, {p3, p4}]
}}],
{{p1, {-1, 1}}, Locator, Appearance -> "L1"},
{{p2, {2, 1}}, Locator, Appearance -> "L2"},
{{p3, {1, -1}}, Locator, Appearance -> "M1"},
{{p4, {1, 2}}, Locator, Appearance -> "M2"}
]
Now that we know how to far we have to travel from L[[1]] to the line segment M we can find out what portion of a line segment lies within a triangle.
lineInTri[L_, T_] := Module[{res},
If[Length#DeleteDuplicates[Flatten[{T, L}, 1], SquaredEuclideanDistance[#1, #2] < 10^-6 &] == 3, Return[{}]];
res = Sort[Map[lineInt[L, #] &, {{T[[1]], T[[2]]}, {T[[2]], T[[3]]}, {T[[3]], T[[1]]} }]];
If[res[[3]] == Infinity || res == {-Infinity, -Infinity, -Infinity}, Return[{}]];
res = DeleteDuplicates[Cases[res, _Real | _Integer | _Rational], Chop[#1 - #2] == 0 &];
If[Length#res == 1, Return[{}]];
If[(Chop[res[[1]]] == 0 && res[[2]] > 1) || (Chop[res[[2]] - 1] == 0 && res[[1]] < 0), Return[{0, 1}]];
If[(Chop[res[[2]]] == 0 && res[[1]] < 0) || (Chop[res[[1]] - 1] == 0 && res[[2]] > 1), Return[{}]];
res = {Max[res[[1]], 0], Min[res[[2]], 1]};
If[res[[1]] > 1 || res[[1]] < 0 || res[[2]] > 1 || res[[2]] < 0, Return[{}], Return[res]];
]
This function returns the the portion of the line L that needs to be deleted. For instance, if it returns {.5, 1} this means that you will delete 50 percent of the line, starting from half the segment to the ending point of the segment. If L = {A, B} and the function returns {u, v} then this means that the line segment {A+(B-A)u, A+(B-A)v} is the section of the line that its contained in the triangle T.
When implementing lineInTri you need to be careful that the line L is not one of the edges of T, if this is the case then the line does not lie inside the triangle. This is where rounding erros can be bad. When Mathematica exports the image sometimes a line lies on the edge of the triangle but these coordinates differ by some amount. It is up to us to decide how close the line lies on the edge, otherwise the function will see that the line lies almost completely inside the triangle. This is the reason of the first line in the function. To see if a line lies on an edge of a triangle we can list all the points of the triangle and the line, and delete all the duplicates. You need to specify what a duplicate is in this case. In the end, if we end up with a list of 3 points this means that a line lies on an edge. The next part is a little complicated. What we do is check for the intersection of the line L with each edge of the triangle T and store this the results in a list. Next we sort the list and find out what section, if any, of the line lies in the triangle. Try to make sense out of it by playing with this, some of the tests include checking if an endpoint of the line is a vertex of the triangle, if the line is completely inside the triangle, partly inside or completely outside.
Manipulate[
Grid[{{
Graphics[{
RGBColor[0, .5, 0, .5], Polygon[{p3, p4, p5}],
Line[{p1, p2}, VertexColors -> {Red, Red}]
},
PlotRange -> 3, Axes -> True],
lineInTri[{p1, p2}, {p3, p4, p5}]
}}],
{{p1, {-1, -2}}, Locator, Appearance -> "L1"},
{{p2, {0, 0}}, Locator, Appearance -> "L2"},
{{p3, {-2, -2}}, Locator, Appearance -> "T1"},
{{p4, {2, -2}}, Locator, Appearance -> "T2"},
{{p5, {-1, 1}}, Locator, Appearance -> "T3"}
]
lineInTri will be used to see what portion of the line will not be drawn. This line will most likely be covered by many triangles. For this reason, we need to keep a list of all the portions of each line that will not be drawn. These lists will not have an order. All we know is that this lists are one dimensional segments. Each one consisting of numbers in the [0,1] interval. I'm not aware of a union function for one dimensional segments so here is my implementation.
union[obj_] := Module[{p, tmp, dummy, newp, EPS = 10^-3},
p = Sort[obj];
tmp = p[[1]];
If[tmp[[1]] < EPS, tmp[[1]] = 0];
{dummy, newp} = Reap[
Do[
If[(p[[i, 1]] - tmp[[2]]) > EPS && (tmp[[2]] - tmp[[1]]) > EPS,
Sow[tmp]; tmp = p[[i]],
tmp[[2]] = Max[p[[i, 2]], tmp[[2]]]
];
, {i, 2, Length#p}
];
If[1 - tmp[[2]] < EPS, tmp[[2]] = 1];
If[(tmp[[2]] - tmp[[1]]) > EPS, Sow[tmp]];
];
If[Length#newp == 0, {}, newp[[1]]]
]
This function would be shorter but here I have included some if statements to check if a number is close to zero or one. If one number is EPS apart from zero then we make this number zero, the same applies for one. Another aspect that I'm covering here is that if there is a relatively small portion of the segment to be displayed then it is most likely that it needs to be deleted. For instance if we have {{0,.5}, {.500000000001}} this means that we need to draw {{.5, .500000000001}}. But this segment is very small to be even noticed specially in a large line segment, for all we know those two numbers are the same. All of this things need to be taken into account when implementing union.
Now we are ready to see what needs to be deleted from a line segment. The next requires the list of objects generated from G3ToG2Info, an object from this list and an index.
getSections[L_, obj_, start_ ] := Module[{dummy, p, seg},
{dummy, p} = Reap[
Do[
If[Length#obj[[i]] == 3,
seg = lineInTri[L, obj[[i]]];
If[Length#seg != 0, Sow[seg]];
]
, {i, start, Length#obj}
]
];
If[Length#p == 0, Return[{}], Return[union[First#p]]];
]
getSections returns a list containing the portions that need to be deleted from L. We know that obj is the list of triangles, lines and colors, we know that objects in the list with a higher index will be drawn on top of ones with lower index. For this reason we need the index start. This is the index we will start looking for triangles in obj. Once we find a triangle we will obtain the portion of the segment that lies in the triangle using the function lineInTri. At the end we will end up with a list of sections which we can combine by using union.
Finally, we get to getHiddenLines. All this requires is to look at each object in the list returned by G3ToG2Info and apply the function getSections. getHiddenLines will return a list of lists. Each element is a list of sections that need to be deleted.
getHiddenLines[obj_] := Module[{pts},
pts = Table[{}, {Length#obj}];
Do[
If[Length#obj[[j]] == 2,
pts[[j]] = getSections[obj[[j]], obj, j + 1]
];
, {j, Length#obj}
];
Return[pts];
]
getFrame
If you have manage to understand the concepts up to here I'm sure you know what will be done next. If we have the list of triangles, lines and colors and the sections of the lines that need to be deleted we need to draw only the colors and the sections of the lines that are visible. First we make a complement function, this will tell us exactly what to draw.
complement[obj_] := Module[{dummy, p},
{dummy, p} = Reap[
If[obj[[1, 1]] != 0, Sow[{0, obj[[1, 1]]}]];
Do[
Sow[{obj[[i - 1, 2]], obj[[i, 1]]}]
, {i, 2, Length#obj}
];
If[obj[[-1, 2]] != 1, Sow[{obj[[-1, 2]], 1}]];
];
If[Length#p == 0, {}, Flatten# First#p]
]
Now the getFrame function
getFrame[obj_, pts_] := Module[{dummy, lines, L, u, d},
{dummy, lines} = Reap[
Do[
L = obj[[i]];
If[Length#L == 2,
If[Length#pts[[i]] == 0, Sow[L]; Continue[]];
u = complement[pts[[i]]];
If[Length#u > 0,
Do[
d = L[[2]] - L[[1]];
Sow[{L[[1]] + u[[j - 1]] d, L[[1]] + u[[j]] d}]
, {j, 2, Length#u, 2 }]
];
];
If[Length#L == 1, Sow[L]];
, {i, Length#obj}]
];
First#lines
]
Final words
I'm somewhat happy with the results of the algorithm. What I do not like is the execution speed. I have written this as I would in C/C++/java using loops. I tried my best to use Reap and Sow to create growing lists instead of using the function Append. Regardless of all of this I still had to use loops. It should be noted that the wire frame picture posted here took 63 seconds to generate. I tried doing a wire frame for the picture in the question but this 3D object contains about 32000 objects. It was taking about 13 seconds to compute the portions that need to be displayed for a line. If we assume that we have 32000 lines and it takes 13 seconds to do all the computations that will be about 116 hours of computational time.
I'm sure this time can be reduced if we use the function Compile on all of the routines and maybe finding a way not to use the Do loops. Can I get some help here Stack Overflow?
For your convinience I have uploaded the code to the web. You can find it here. If you can apply a modified version of this code to the plot in the question and show the wire frame I will mark your solution as the answer to this post.
Best,
J Manuel Lopez
This isn't right, but somewhat interesting:
Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, Boxed -> False,
PlotStyle -> {EdgeForm[None], FaceForm[Red, None]}, Mesh -> False]
With a FaceForm of None, the polygon isn't rendered. I'm not sure there's a way to do this with the Mesh lines.

Is it possible to create polar CountourPlot/ListCountourPlot/DensityPlot in Mathematica?

I am looking to plot something like the whispering gallery modes -- a 2D cylindrically symmetric plot in polar coordinates. Something like this:
I found the following code snippet in Trott's symbolics guidebook. Tried running it on a very small data set; it ate 4 GB of memory and hosed my kernel:
(* add points to get smooth curves *)
addPoints[lp_][points_, \[Delta]\[CurlyEpsilon]_] :=
Module[{n, l}, Join ## (Function[pair,
If[(* additional points needed? *)
(l = Sqrt[#. #]&[Subtract ## pair]) < \[Delta]\[CurlyEpsilon], pair,
n = Floor[l/\[Delta]\[CurlyEpsilon]] + 1;
Table[# + i/n (#2 - #1), {i, 0, n - 1}]& ## pair]] /#
Partition[If[lp === Polygon,
Append[#, First[#]], #]&[points], 2, 1])]
(* Make the plot circular *)
With[{\[Delta]\[CurlyEpsilon] = 0.1, R = 10},
Show[{gr /. (lp : (Polygon | Line))[l_] :>
lp[{#2 Cos[#1], #2 Sin[#1]} & ###(* add points *)
addPoints[lp][l, \[Delta]\[CurlyEpsilon]]],
Graphics[{Thickness[0.01], GrayLevel[0], Circle[{0, 0}, R]}]},
DisplayFunction -> $DisplayFunction, Frame -> False]]
Here, gr is a rectangular 2D ListContourPlot, generated using something like this (for example):
data = With[{eth = 2, er = 2, wc = 1, m = 4},
Table[Re[
BesselJ[(Sqrt[eth] m)/Sqrt[er], Sqrt[eth] r wc] Exp[
I m phi]], {r, 0, 10, .2}, {phi, 0, 2 Pi, 0.1}]];
gr = ListContourPlot[data, Contours -> 50, ContourLines -> False,
DataRange -> {{0, 2 Pi}, {0, 10}}, DisplayFunction -> Identity,
ContourStyle -> {Thickness[0.002]}, PlotRange -> All,
ColorFunctionScaling -> False]
Is there a straightforward way to do cylindrical plots like this?.. I find it hard to believe that I would have to turn to Matlab for my curvilinear coordinate needs :)
Previous snippets deleted, since this is clearly the best answer I came up with:
With[{eth = 2, er = 2, wc = 1, m = 4},
ContourPlot[
Re[BesselJ[(Sqrt[eth] m)/Sqrt[er], Sqrt[eth] r wc] Exp[I phi m]]/.
{r ->Norm[{x, y}], phi ->ArcTan[x, y]},
{x, -10, 10}, {y, -10, 10},
Contours -> 50, ContourLines -> False,
RegionFunction -> (#1^2 + #2^2 < 100 &),
ColorFunction -> "SunsetColors"
]
]
Edit
Replacing ContourPlot by Plot3D and removing the unsupported options you get:
This is a relatively straightforward problem. The key is that if you can parametrize it, you can plot it. According to the documentation both ListContourPlot and ListDensityPlot accept data in two forms: an array of height values or a list of coordinates plus function value ({{x, y, f} ..}). The second form is easier to deal with, such that even if your data is in the first form, we'll transform it into the second form.
Simply, to transform data of the form {{r, t, f} ..} into data of the form {{x, y, f} ..} you doN[{#[[1]] Cos[ #[[2]] ], #[[1]] Sin[ #[[2]] ], #[[3]]}]& /# data, when applied to data taken from BesselJ[1, r/2] Cos[3 t] you get
What about when you just have an array of data, like this guy? In that case, you have a 2D array where each point in the array has known location, and in order to plot it, you have to turn it into the second form. I'm partial to MapIndexed, but there are other ways of doing it. Let's say your data is stored in an array where the rows correspond to the radial coordinate and the columns are the angular coordinate. Then to transform it, I'd use
R = 0.01; (*radial increment*)
T = 0.05 Pi; (*angular increment*)
xformed = MapIndexed[
With[{r = #2[[1]]*R, t = #2[[1]]*t, f = #1},
{r Cos[t], r Sin[t], f}]&, data, {2}]//Flatten[#,1]&
which gives the same result.
If you have an analytic solution, then you need to transform it to Cartesian coordinates, like above, but you use replacement rules, instead. For instance,
ContourPlot[ Evaluate[
BesselJ[1, r/2]*Cos[3 t ] /. {r -> Sqrt[x^2 + y^2], t -> ArcTan[x, y]}],
{x, -5, 5}, {y, -5, 5}, PlotPoints -> 50,
ColorFunction -> ColorData["DarkRainbow"], Contours -> 25]
gives
Two things to note: 1) Evaluate is needed to ensure that the replacement is performed correctly, and 2) ArcTan[x, y] takes into account the quadrant that the point {x,y} is found in.

Mathematica: How to obtain data points plotted by plot command?

When plotting a function using Plot, I would like to obtain the set of data points plotted by the Plot command.
For instance, how can I obtain the list of points {t,f} Plot uses in the following simple example?
f = Sin[t]
Plot[f, {t, 0, 10}]
I tried using a method of appending values to a list, shown on page 4 of Numerical1.ps (Numerical Computation in Mathematica) by Jerry B. Keiper, http://library.wolfram.com/infocenter/Conferences/4687/ as follows:
f = Sin[t]
flist={}
Plot[f, {t, 0, 10}, AppendTo[flist,{t,f[t]}]]
but generate error messages no matter what I try.
Any suggestions would be greatly appreciated.
f = Sin[t];
plot = Plot[f, {t, 0, 10}]
One way to extract points is as follows:
points = Cases[
Cases[InputForm[plot], Line[___],
Infinity], {_?NumericQ, _?NumericQ}, Infinity];
ListPlot to 'take a look'
ListPlot[points]
giving the following:
EDIT
Brett Champion has pointed out that InputForm is superfluous.
ListPlot#Cases[
Cases[plot, Line[___], Infinity], {_?NumericQ, _?NumericQ},
Infinity]
will work.
It is also possible to paste in the plot graphic, and this is sometimes useful. If,say, I create a ListPlot of external data and then mislay the data file (so that I only have access to the generated graphic), I may regenerate the data by selecting the graphic cell bracket,copy and paste:
ListPlot#Transpose[{Range[10], 4 Range[10]}]
points = Cases[
Cases[** Paste_Grphic _Here **, Point[___],
Infinity], {_?NumericQ, _?NumericQ}, Infinity]
Edit 2.
I should also have cross-referenced and acknowledged this very nice answer by Yaroslav Bulatov.
Edit 3
Brett Champion has not only pointed out that FullForm is superfluous, but that in cases where a GraphicsComplex is generated, applying Normal will convert the complex into primitives. This can be very useful.
For example:
lp = ListPlot[Transpose[{Range[10], Range[10]}],
Filling -> Bottom]; Cases[
Cases[Normal#lp, Point[___],
Infinity], {_?NumericQ, _?NumericQ}, Infinity]
gives (correctly)
{{1., 1.}, {2., 2.}, {3., 3.}, {4., 4.}, {5., 5.}, {6., 6.}, {7.,
7.}, {8., 8.}, {9., 9.}, {10., 10.}}
Thanks to Brett Champion.
Finally, a neater way of using the general approach given in this answer, which I found here
The OP problem, in terms of a ListPlot, may be obtained as follows:
ListPlot#Cases[g, x_Line :> First#x, Infinity]
Edit 4
Even simpler
ListPlot#Cases[plot, Line[{x__}] -> x, Infinity]
or
ListPlot#Cases[** Paste_Grphic _Here **, Line[{x__}] -> x, Infinity]
or
ListPlot#plot[[1, 1, 3, 2, 1]]
This evaluates to True
plot[[1, 1, 3, 2, 1]] == Cases[plot, Line[{x__}] -> x, Infinity]
One way is to use EvaluationMonitor option with Reap and Sow, for example
In[4]:=
(points = Reap[Plot[Sin[x],{x,0,4Pi},EvaluationMonitor:>Sow[{x,Sin[x]}]]][[2,1]])//Short
Out[4]//Short= {{2.56457*10^-7,2.56457*10^-7},<<699>>,{12.5621,-<<21>>}}
In addition to the methods mentioned in Leonid's answer and my follow-up comment, to track plotting progress of slow functions in real time to see what's happening you could do the following (using the example of this recent question):
(* CPU intensive function *)
LogNormalStableCDF[{alpha_, beta_, gamma_, sigma_, delta_}, x_] :=
Block[{u},
NExpectation[
CDF[StableDistribution[alpha, beta, gamma, sigma], (x - delta)/u],
u \[Distributed] LogNormalDistribution[Log[gamma], sigma]]]
(* real time tracking of plot process *)
res = {};
ListLinePlot[res // Sort, Mesh -> All] // Dynamic
Plot[(AppendTo[res, {x, #}]; #) &#
LogNormalStableCDF[{1.5, 1, 1, 0.5, 1}, x], {x, -4, 6},
PlotRange -> All, PlotPoints -> 10, MaxRecursion -> 4]
etc.
Here is a very efficient way to get all the data points:
{plot, {points}} = Reap # Plot[Last#Sow#{x, Sin[x]}, {x, 0, 4 Pi}]
Based on the answer of Sjoerd C. de Vries, I've now written the following code which automates a plot preview (tested on Mathematica 8):
pairs[x_, y_List]:={x, #}& /# y
pairs[x_, y_]:={x, y}
condtranspose[x:{{_List ..}..}]:=Transpose # x
condtranspose[x_]:=x
Protect[SaveData]
MonitorPlot[f_, range_, options: OptionsPattern[]]:=
Module[{data={}, plot},
Module[{tmp=#},
If[FilterRules[{options},SaveData]!={},
ReleaseHold[Hold[SaveData=condtranspose[data]]/.FilterRules[{options},SaveData]];tmp]]&#
Monitor[Plot[(data=Union[data, {pairs[range[[1]], #]}]; #)& # f, range,
Evaluate[FilterRules[{options}, Options[Plot]]]],
plot=ListLinePlot[condtranspose[data], Mesh->All,
FilterRules[{options}, Options[ListLinePlot]]];
Show[plot, Module[{yrange=Options[plot, PlotRange][[1,2,2]]},
Graphics[Line[{{range[[1]], yrange[[1]]}, {range[[1]], yrange[[2]]}}]]]]]]
SetAttributes[MonitorPlot, HoldAll]
In addition to showing the progress of the plot, it also marks the x position where it currently calculates.
The main problem is that for multiple plots, Mathematica applies the same plot style for all curves in the final plot (interestingly, it doesn't on the temporary plots).
To get the data produced into the variable dest, use the option SaveData:>dest
Just another way, possibly implementation dependent:
ListPlot#Flatten[
Plot[Tan#t, {t, 0, 10}] /. Graphics[{{___, {_, y__}}}, ___] -> {y} /. Line -> List
, 2]
Just look into structure of plot (for different type of plots there would be a little bit different structure) and use something like that:
plt = Plot[Sin[x], {x, 0, 1}];
lstpoint = plt[[1, 1, 3, 2, 1]];

tips for creating Graph diagrams

I'd like to programmatically create diagrams like this
(source: yaroslavvb.com)
I imagine I should use GraphPlot with VertexCoordinateRules, VertexRenderingFunction and EdgeRenderingFunction for the graphs. What should I use for colored beveled backgrounds?
Edit
Using mainly Simon's ideas, here's a simplified "less robust" version I ended up using
Needs["GraphUtilities`"];
GraphPlotHighlight[edges_, verts_, color_] := Module[{},
vpos = Position[VertexList[edges], Alternatives ## verts];
coords = Extract[GraphCoordinates[edges], vpos];
(* add .002 because end-cap disappears when segments are almost colinear *)
AppendTo[coords, First[coords] + .002];
Show[Graphics[{color, CapForm["Round"], JoinForm["Round"],
Thickness[.2], Line[coords], Polygon[coords]}],
GraphPlot[edges], ImageSize -> 150]
]
SetOptions[GraphPlot,
VertexRenderingFunction -> ({White, EdgeForm[Black], Disk[#, .15],
Black, Text[#2, #1]} &),
EdgeRenderingFunction -> ({Black, Line[#]} &)];
edges = GraphData[{"Grid", {3, 3}}, "EdgeRules"];
colors = {LightBlue, LightGreen, LightRed, LightMagenta};
vsets = {{8, 5, 2}, {7, 5, 8}, {9, 6, 3}, {8, 1, 2}};
MapThread[GraphPlotHighlight[edges, #1, #2] &, {vsets, colors}]
(source: yaroslavvb.com)
Generalising Samsdram's answer a bit, I get
GraphPlotHighlight[edges:{((_->_)|{_->_,_})..},hl:{___}:{},opts:OptionsPattern[]]:=Module[{verts,coords,g,sub},
verts=Flatten[edges/.Rule->List]//.{a___,b_,c___,b_,d___}:>{a,b,c,d};
g=GraphPlot[edges,FilterRules[{opts}, Options[GraphPlot]]];
coords=VertexCoordinateRules/.Cases[g,HoldPattern[VertexCoordinateRules->_],2];
sub=Flatten[Position[verts,_?(MemberQ[hl,#]&)]];
coords=coords[[sub]];
Show[Graphics[{OptionValue[HighlightColor],CapForm["Round"],JoinForm["Round"],Thickness[OptionValue[HighlightThickness]],Line[AppendTo[coords,First[coords]]],Polygon[coords]}],g]
]
Protect[HighlightColor,HighlightThickness];
Options[GraphPlotHighlight]=Join[Options[GraphPlot],{HighlightColor->LightBlue,HighlightThickness->.15}];
Some of the code above could be made a little more robust, but it works:
GraphPlotHighlight[{b->c,a->b,c->a,e->c},{b,c,e},VertexLabeling->True,HighlightColor->LightRed,HighlightThickness->.1,VertexRenderingFunction -> ({White, EdgeForm[Black], Disk[#, .06],
Black, Text[#2, #1]} &)]
EDIT #1:
A cleaned up version of this code can be found at http://gist.github.com/663438
EDIT #2:
As discussed in the comments below, the pattern that my edges must match is a list of edge rules with optional labels. This is slightly less general than what is used by the GraphPlot function (and by the version in the above gist) where the edge rules are also allowed to be wrapped in a Tooltip.
To find the exact pattern used by GraphPlot I repeatedly used Unprotect[fn];ClearAttributes[fn,ReadProtected];Information[fn] where fn is the object of interest until I found that it used the following (cleaned up) function:
Network`GraphPlot`RuleListGraphQ[x_] :=
ListQ[x] && Length[x] > 0 &&
And##Map[Head[#1] === Rule
|| (ListQ[#1] && Length[#1] == 2 && Head[#1[[1]]] === Rule)
|| (Head[#1] === Tooltip && Length[#1] == 2 && Head[#1[[1]]] === Rule)&,
x, {1}]
I think that my edges:{((_ -> _) | (List|Tooltip)[_ -> _, _])..} pattern is equivalent and more concise...
For simple examples where you are only connecting two nodes (like your example on the far right), you can draw lines with capped end points like this.
vertices = {a, b};
Coordinates = {{0, 0}, {1, 1}};
GraphPlot[{a -> b}, VertexLabeling -> True,
VertexCoordinateRules ->
MapThread[#1 -> #2 &, {vertices, Coordinates}],
Prolog -> {Blue, CapForm["Round"], Thickness[.1], Line[Coordinates]}]
For more complex examples (like second from the right) I would recommend drawing a polygon using the vertex coordinates and then tracing the edge of the polygon with a capped line. I couldn't find a way to add a beveled edge directly to a polygon. When tracing the perimeter of the polygon you need to add the coordinate of the first vertex to the end of the line segment that the line makes the complete perimeter of the polygon. Also, there are two separate graphics directives for lines CapForm, which dictates whether to bevel the ends of the line, and JoinForm, which dictates whether to bevel the intermediate points of the line.
vertices = {a, b, c};
Coordinates = {{0, 0}, {1, 1}, {1, -1}};
GraphPlot[{a -> b, b -> c, c -> a}, VertexLabeling -> True,
VertexCoordinateRules ->
MapThread[#1 -> #2 &, {vertices, Coordinates}],
Prolog -> {Blue, CapForm["Round"], JoinForm["Round"], Thickness[.15],
Line[AppendTo[Coordinates, First[Coordinates]]],
Polygon[Coordinates]}]
JoinForm["Round"] will round the joins of line segments.
You'll want a filled polygon around the centers of the vertices in the colored region, then a JoinForm["Round"], ..., Line[{...}] to get the rounded corners.
Consider
foo = GraphPlot[{a -> b, a -> c, b -> d, b -> e, b -> f, c -> e, e -> f},
VertexRenderingFunction ->
({White, EdgeForm[Black], Disk[#, .1], Black, Text[#2, #1]} &)]
Show[
Graphics[{
RGBColor[0.6, 0.8, 1, 1],
Polygon[foo[[1, 1, 1, 1, 1, {2, 5, 6, 2}]]],
JoinForm["Round"], Thickness[0.2],
Line[foo[[1, 1, 1, 1, 1, {2, 5, 6, 2}]]]
}],
foo
]
where foo[[1,1,1,1,1]] is the list of vertex centers and {2,5,6} pulls out the {b,e,f} vertices. ({2,5,6,2} closes the line back at its starting point.)
There's plenty of room for prettifying, but I think this covers the ingredient you didn't mention above.

Resources