Skip to main content

graphics - Subplots with connector lines


I am looking for advice from people who have more experience in this area on what is the best (simplest, least effort) way to create a graphic like the following:


Mathematica graphics


This is a rough mockup made in a drawing program. There is a central graph, surrounded by smaller ones, each of which is showing some information about a point in the main graph. Those points are connected to the subgraphs with lines.


Requirements:





  • Each plot must be able to have their own axes/frame




  • Proper alignments of the connector lines (red dashed lines on the mockup)---I have the coordinates of one end in the coordinate system of the central plot, while the other end must point at the smaller plots.




  • Consistent font sizes and line widths (i.e. everything must be 8 pt when printed)





  • Vector graphics (I'd like to avoid rasterizing to bitmaps)




Possible approaches:




  • GraphicsGrid with Epilog (GraphicsGrid seems to be based on Inset.)





  • Lots of Insets in a graphic (the main issue is aligning the coordinate system of the central plot with that of the whole graphic)




  • Learn to use LevelScheme (I didn't use it for anything serious yet, but when I tried it last time it seemed to have issued with alignment).




Whenever I start doing something like this, and the details must be accurate, lots of small issues tend to come up. I'd like to know which approach is likely to prove the least troublesome.




Answers summary


The main difficulty was the correct positioning of connector lines. The usual way of including subplots is by using Inset (which is also used by GraphicsGrid). One endpoint of the lines is in the main graphics coordinate system, while the other is in the central subplot coordinate system. Converting between the two is very difficult and depends on the scaling of graphics.



Heike's solution uses FullGraphics to expand the axes/frames of subplots. Then all subplots can be directly included in the main graphic and scaled to size. There will be a single coordinate system to deal with.


Chris Degnen's solution uses image processing to align the main graphic coordinate system with the inset coordinate system. It places a red dot at the desired endpoints, rasterizes the graphic, measures the position of the dot, and then uses this information to compose a vector graphic with the connector lines going between these positions. The result is a vector graphic that looks correct only at a certain scale, but can be exported to PDF.


The other solutions recommend adding the connector lines manually.



Answer



This solution uses FullGraphics to transform axes and ticks in a plot to lines which allows you to resize and translate the plot while keeping the ticks of the original plot. In raster, main is the main plot, list is the list of sub plots, pts is the list of points in the main plot corresponding to the begin points of the red lines, and {dx, dy} are the gaps between the sub plots and the main plot. The sub plots are placed in clockwise direction starting with the one in the upper right corner. The end plot is such that the plot range of the main plot is {{0, 0}, {1, 1}}.


raster[main_, list_, pts_, {dx_, dy_}] := 
Module[{fgmain, fglist, prm, prl, scmain, sclist, scpts, lines},
fgmain = FullGraphics[main];
fglist = FullGraphics /@ list;
prm = OptionValue[AbsoluteOptions[main, PlotRange][[1]],

PlotRange];
prl = OptionValue[Options[#, PlotRange][[1]], PlotRange] & /@ list;
scmain =
Translate[
Scale[fgmain[[1]], 1/(prm[[All, 2]] - prm[[All, 1]]),
prm[[All, 1]]], -prm[[All, 1]]];
scpts = Transpose[{Rescale[pts[[All, 1]], prm[[1]]],
Rescale[pts[[All, 2]], prm[[2]]]}];
sclist = MapThread[
Translate[

Scale[#, (.5 - {dx, dy}/
2)/(#2[[All, 2]] - #2[[All, 1]]), #2[[All, 1]]],
-#2[[All, 1]] + #3] &,
{fglist[[All, 1]], prl, {{-.5 - dx/2, 1 + dy},
{0, 1 + dy}, {.5 + dx/2, 1 + dy}, {1 + dx, 1 + dy},
{1 + dx, .5 + dy/2}, {1 + dx, 0}, {1 + dx, -.5 - dy/2},
{.5 + dx/2, -.5 - dy/2}, {0, -.5 - dy/2}, {-.5 - dx/2, -.5 -
dy/2},
{-.5 - dx/2, 0}, {-.5 - dx/2, .5 + dy/2}}}];
lines = Transpose[{scpts,

{{-dx, 1 + dy}, {.25 - dx/4, 1 + dy}, {.75 + dx/4,
1 + dy}, {1 + dx, 1 + dy},
{1 + dx, .75 + dy/4}, {1 + dx, .25 - dx/4}, {1 + dx, -dy},
{.75 + dx/4, -dy}, {.25 - dx/4, -dy}, {-dx, -dy},
{-dx, .25 - dy/4}, {-dx, .75 + dy/4}}}];
Graphics[{scmain, sclist, {Red, Dashed, Line[lines]}}]]

Example:


list = MapIndexed[ParametricPlot[#, {x, 0, 2 Pi}, 
Frame -> True, Axes -> False,

PlotStyle -> (ColorData[1] @@ #2)] &,
Table[{(n - 1) 2 Pi + x, n Sin[x]}, {n, 12}]];
main = Show[list, PlotRange -> All];
pts = N[Table[{(n - 1) 2 Pi + x, n Sin[x]}, {n, 12}] /. x -> Pi];

raster[main, list, pts, {.15, .15}]

Mathematica graphics


Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Adding a thick curve to a regionplot

Suppose we have the following simple RegionPlot: f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}] Now I'm trying to change the curve defined by $y=g[x]$ into a thick black curve, while leaving all other boundaries in the plot unchanged. I've tried adding the region $y=g[x]$ and playing with the plotstyle, which didn't work, and I've tried BoundaryStyle, which changed all the boundaries in the plot. Now I'm kinda out of ideas... Any help would be appreciated! Answer With f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 You can use Epilog to add the thick line: RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}, PlotPoints -> 50, Epilog -> (Plot[g[x], {x, 0, 2}, PlotStyle -> {Black, Thick}][[1]]), PlotStyle -> {Directive[Yellow, Opacity[0.4]], Directive[Pink, Opacity[0.4]],