Related
I can get a colored ListLinePlot by doing something like
ListLinePlot[Range[420, 680, 20], ColorFunction -> "VisibleSpectrum", ColorFunctionScaling -> False]
However, as indicated by the help file ("ColorFunction requires at least one dataset to be Joined"), if I do the equivalent
ListPlot[Range[420, 680, 20], ColorFunction -> "VisibleSpectrum", ColorFunctionScaling -> False]
all my points are blue. Is there a nice way to get ColorFunction to work for ListPlot with Joined -> False?
That is, is there a nicer way to get something like
ListPlot[
List /# Transpose[{Range[(680 - 420)/20 + 1], Range[420, 680, 20]}],
PlotMarkers -> ({Graphics[{#, Disk[]}], 0.05} & /# ColorData["VisibleSpectrum"] /# Range[420, 680, 20])
]
?
(Also, does anyone have an explanation of why Mathematica requires Joined -> True in order to make use of ColorFunction?)
Edit: I'm also looking for a way to do a similar coloring with ErrorListPlot in the ErrorBarPlots package.
The problem is, that Joined->True draws a Line[] which can be given VertexColors for each containing point. I assume doing the same for the points when setting Joined->False leads to situations where it does not work. Nevertheless, Line[] and Point[] work pretty much the same in your case. So what is about
ListLinePlot[Range[420, 680, 20], ColorFunction -> "VisibleSpectrum",
ColorFunctionScaling -> False] /. Line[arg___] :> Point[arg]
And, by the way, if your using a ListLinePlot only, where the only Line[] directives arising are the one from your data, this should work even if you have more datasets and {x,y} coordinates
data = Transpose[Table[{{x, Sin[x]}, {x, Cos[x]}}, {x, 0, 2 Pi, 0.2}]];
ListLinePlot[data, ColorFunction -> Hue] /. Line[arg___] :> Point[arg]
You can use DiscretePlot:
data = Range[420, 680, 20];
DiscretePlot[data[[i]], {i, Length[data]},
ColorFunction -> "VisibleSpectrum", ColorFunctionScaling -> False,
Filling -> None]
If you're plotting a list of x,y points, it gets a little trickier:
data = Transpose[{Range[420, 680, 20], Range[400, 530, 10]}];
mapping = Apply[Rule, data, 2];
DiscretePlot[i/.mapping, {i, data[[;;,1]]},
ColorFunction -> "VisibleSpectrum", ColorFunctionScaling -> False,
Filling -> None]
It does seem rather odd that DiscretePlot will let you color the points differently whereas ListPlot won't. I'm sure it must have something to do with the implementation details, but I can't think of a reason why that would be the case.
I came across this problem in my work too. I assign a colour to each point in the following manner:
data = ...
ListPlot[data] /. Point[args___] :> Point[args, VertexColors -> {c1, c2, ...}]
where c1 is the colour for the first data point, and so on. The colour list may be programmatically generated, eg
ColorData["Rainbow"] /# (Range#Length#data / Length#data)
Here is the result.
The good points of this method are as follows.
It's straightforward: we have a list of pairs, then we create a corresponding list of colours.
Our original ListPlot code needs not be modified (eg, changed into ListLinePlot).
How can I label each of these lines separately :
Plot[{{5 + 2 x}, {6 + x}}, {x, 0, 10}]
There's some nice code that allows you to do this dynamically in an answer to How to annotate multiple datasets in ListPlots.
There's also a LabelPlot command defined in the Technical Note Labeling Curves in Plots
Of course, if you don't have too many images to make,
then it's not hard to manually add the labels in using Epilog, for example
fns[x_] := {5 + 2 x, 6 + x};
len := Length[fns[x]];
Plot[Evaluate[fns[x]], {x, 0, 10},
Epilog -> Table[Inset[
Framed[DisplayForm[fns[x][[i]]], RoundingRadius -> 5],
{5, fns[5][[i]]}, Background -> White], {i, len}]]
In fact, you can do something similar with Locators that allows you to move the labels wherever you want:
DynamicModule[{pos = Table[{1, fns[1][[i]]}, {i, len}]},
LocatorPane[Dynamic[pos], Plot[Evaluate[fns[x]], {x, 0, 10}],
Appearance -> Table[Framed[Text#TraditionalForm[fns[x][[i]]],
RoundingRadius -> 5, Background -> White], {i, len}]]]
In the above I made the locators take the form of the labels, although it is also possible to keep an Epilog like that above and have invisible locators that control the positions.
The locators could also be constrained (using the 2nd argument of Dynamic) to the appropriate curves... but that's not really necessary.
As an example of the above code with the functions with the labels moved by hand:
fns[x_] := {Log[x], Exp[x], Sin[x], Cos[x]};
Mathematica 9 now provides easy ways to include legends.
Plot[{{5 + 2 x}, {6 + x}}, {x, 0, 10}, PlotLegends -> "Expressions"]
You can insert legends in your plot by loading the PlotLegends package
<<PlotLegends`;
Plot[{5+2 x,6+x},{x,0,10},
PlotLegend->{"5+2x","6+x"},LegendShadow->None,
LegendPosition->{0.3,-0.5},LegendSpacing->-0,LegendSize->0.5]
However, let me also note my dislike of this package, primarily because it's extremely counterintuitive, laden with too many options and does not provide a clean experience right out of the box like most of Mathematica's functions. You will have some fiddling around to do with the options to get what you want. However, in plots and charts where you do want a legend, this can be handy. Also see the comments to this answer and this question.
Here is a problem that I don't know if can be solved in Mathematica.
(* Courtesy to Lunchtime Playground Blog *)
to3d[plot_, height_, opacity_] :=
Module[{newplot}, newplot = First#Graphics[plot];
newplot = N#newplot /. {x_?AtomQ, y_?AtomQ} -> {x, y, height} /.
Arrowheads[List[List[x_, y_, notz_]]] ->
Arrowheads[List[List[x, y]]];newplot /.GraphicsComplex[xx__] -> {Opacity[opacity], GraphicsComplex[xx]}];
(* A function to combine 2D Graphics object in Mathematica *)
test[list_]:=VectorQ[list,SameQ[Head[#],Graphics]&];
My3DPlot[list_?(test[#]&),height_?(VectorQ[#,NumberQ]&),opacity_?(VectorQ[#,NumberQ]&),opts:OptionsPattern[]]:=Block[{a},a=MapThread[Graphics3D[to3d[#1,#2,#3]]&,{list,height,opacity}];
Show[a,opts]
]
(* List of 2D graphics *)
list=Table[ContourPlot[y+Sin[x^i+i y],{x,-3,3},{y,-3,3},Contours->15,ContourLines->False,ColorFunction->RandomChoice[ColorData["Gradients"]]],{i,{1,2,3,4}}];
(* List of heights where you want to place the images *)
height={-.5,0,.5,1};
(* List of opacities you want to apply to your 2D layers *)
opacity={1,.8,.7,.5};
(* The function inherits all the options of standard Graphics3D as they are passed through the Show command *)
My3DPlot[Reverse#list,height,opacity,Lighting->"Neutral",BoxRatios->{1,1,.9},Axes->True]
Now this returns a cool picture like this one.
Here my question is if it is possible to create a filling for this 2D layers using the same color functions as are used with in the contour plots for example? Target is to fill the hollow between these 2D layers with some light or color that continuously changes according to the neighboring layer color-function.
I hope this can be done in Mathematica but my limited knowledge in Mathematica graphics is making it a difficult hurdle for me.
It should be possible. Texture can be used to generate a 3D texture. The example given in the documentation:
data = Table[{r, g, b}, {r, 0, 1, 1/20}, {g, 0, 1, 1/20}, {b, 0, 1, 1/20}];
Graphics3D[
{
Opacity[1/3],
Texture[data],
EdgeForm[],
Polygon[Table[{{0, 0, z}, {1, 0, z}, {1, 1, z}, {0, 1, z}}, {z, 0, 1, 1/20}],
VertexTextureCoordinates ->
Table[{{0, 0, s}, {1, 0, s}, {1, 1, s}, {0, 1, s}}, {s, 0, 1, 1/20}]]
},
Lighting -> "Neutral"
]
This simulates a volume by using a large set of planes. You can do the same. All you have to do is describe the 3D texture, which should interpolate between the planes you already have.Blend would be the function to be used here. For each pixel column in your cube the color varies as Blend[{col1,col2,col3,...},x] with x going from 0 to 1 and coli the color of the pixel in the ith plane given by the contour plots.
The main problem will be that a 3D semi-transparant object with fuzzy color gradients is not something that visualizes very well.
I would like to draw a rectangle (or more) which printed on paper shows the rectangle in units of cm.
So
Graphics[{Rectangle[{0, 0}, {19, 28}], Orange, Rectangle[{0, 0}, {1, 1}]}]
will print out as two rectangles which can be measured as exactly 1cm x 1cm (orange one) and the black one as 19x28 cm.
It seems that some variables are important:
The ImageSize and of course the AspectRatio.
I used AspectRatio->19/28 and for the ImageSize various settings like ImageSize->{19*27,28*27} but it keeps being not very accurate.
I export the graphics to TIFF and then print out with windows photo gallery to a full page photo. Does anyone have experience with this? There must be a formula instead of trial and error.
UPDATE:
I tried the suggestion of #Szabolcs and I used the following code:
g = Graphics[{White, EdgeForm[Directive[Thick, Black]],
Rectangle[{0, 0}, {18, 28}], Orange, Rectangle[{0, 0}, {10, 10}]}]
final = Show[g, AspectRatio -> Automatic,
PlotRange -> {{-0.5, 18.5}, {-0.5, 28.5}}]
cm = 72/2.54
Export["final.pdf", Show[final, ImageSize -> {19 cm, 29 cm}]]
This works great. The orange rectangle of 10x10cm is when measured exactly 10x10cm
the cm 72/2.54 value was not what I expected since I though Windows uses 96dpi and Mac 72dpi (reading from the www). However 72 is the value that works.
I've also beenn playing with the frames but then it gets ugly. Haven't found a way to get the right results dispite playing with all possible settings. What should work is create the frames/ticks etc myself inside the selected boundaries but that's not the path I would like to pursue..
g = Graphics[{Rectangle[{0, 0}, {19, 28}], Orange, Rectangle[{0, 0}, {1, 1}]}]
Okay, first thing you need to do is set the x and y directions to use the same units, which means
Show[g, AspectRatio -> Automatic]
But this is already the default.
Second thing you need to do is choose a size and range for your plot area. Let's make it 21 by 30 with your rectangles centred:
plotArea = {{0, 21}, {0, 30}} - {1, 1}
Show[g, AspectRatio -> Automatic, PlotRange -> plotArea]
Third thing you need to do is turning off adding any padding/margins that make the actual size of your figure larger than your plot range:
final = Show[g, AspectRatio -> Automatic, PlotRange -> plotArea, PlotRangePadding -> 0, ImagePadding -> 0]
I believe ImageMargins does not make a difference, but if it does, set that to 0 as well.
The final thing you need to do is export this to a printable format that preserves the image dimensions, and set the size of the image so that 1 cm will be 1 unit on your plot. Mathematica accepts image sizes in printer's points, so let's define:
cm = 72/2.54
Export["final.pdf", Show[final, ImageSize -> 21 cm]]
We want the plot to be 21 cm wide because it's 21 units wide. Use PDF as export format, not TIFF. The ImageSize needs to be used inside Show to work around some problems with Export ...
Now open your PDF in Adobe Reader, open the print dialogue, and make sure that Page Scaling is set to None! I don't know how to do this in other readers ... Also make sure your figure fits the paper (21 by 30 cm is too large for A4 ...)
I'm not going to do a test print, so let me know if this works for you :-) The size of the PDF generated this way is exactly 21 by 30 cm, so if something goes wrong, it must happen at the printing stage.
I believe you need to add PlotRangePadding -> None and set image dimensions appropriately.
In this case, the "bounding box" size is the same as your larger rectangle: {19, 28}
The robust way to do this is to set ImageSize to the actual required dimensions, and make use of ImageResolution, which will embed this value into the TIFF file for proper printing:
cm = 72 / 2.54;
g = Graphics[{Rectangle[{0, 0}, {19, 28}], Orange,
Rectangle[{0, 0}, {1, 1}]}, PlotRangePadding -> None,
ImageSize -> {19, 28}*cm];
Export["print.tif", g, ImageResolution -> 300]
This assumes that you want to print from a raster format (TIFF) but you can also export to other formats such as PDF with the same method.
Graph[] has a tendency to cut off vertex labels in Mathematica. I am looking for a robust workaround.
Example:
Graph[{1 -> 2, 2 -> 3, 3 -> 1}, VertexLabels -> "Name"]
My present workaround:
SetOptions[Graph, ImagePadding -> 12]
This is not robust because the value of ImagePadding needs to be manually adjusted depending on the label size.
Apparently using FullGraphics on the Graph object will fix the clipping for the purpose of display, at the expense of interactivity.
Per the comment below, Show[] works as well, and avoids modifying the graphics.
Here are two possible workarounds.
Enlarge the vertex size and place the labels within the vertex. Of course, this also depends on the length of the labels, but for shortish labels it works well, whereas your example above clips off any label of more than one character for vertex 1.
ex:
Table[Graph[{1 -> 2, 2 -> 3, 3 -> 1}, VertexSize -> 0.3,
VertexLabels -> Table[i ->
Placed["vertex" <> ToString[i], p], {i, 3}],
VertexShapeFunction -> "Square", PlotLabel -> p],
{p, {Left, Top, Right, Bottom, Center}}]
Use tooltips to store the labels instead of displaying them on the graphic. [Edit: Center probably looks the best, and then you can wrap labels by putting \n in your string if you need to, but again, depends on the label length.]
ex:
Graph[{1 -> 2, 2 -> 3, 3 -> 1}, VertexLabels -> Placed["Name", Tooltip]]
While this stops you from being able to see all the labels at the same time, you never have any clipping.