Exporting to animated gif seems to have changed in Mathematica 8.0.1?
I normally make animated GIFs of a manipulate by simply writing:
v=Manipulate[....]
then Export["foo.gif",v];
But now it does not work. I just get one static image.
Here is an example:
v=Manipulate[
Text[t],
{{t,4,"start"},0,10,1,ControlType->Trigger,AnimationRate->1,AnimationRepetitions->10}
]
Now Export["foo.gif",v] just generate static image, as nothing was running.
But Export["foo.avi",v] works, and it does generate a running avi movie.
Also, there used to be animated GIF options I used before, but now there are not supported:
Export["foo.gif",v,ConversionOptions->{"AnimationDisplayTime"->0.5,"Loop"->True},ImageSize->{500,500}]
Export::convoptobs: ConversionOptions is obsolete.
When I go to help, I do not see options for GIF there. How does one control animation delay and such?
I thought someone here might have an idea.
thanks
--Nasser
You can export a Table to an animated GIF.
v = Table[Panel[Text[t]], {t, 0, 10, 1}];
Export["anim.gif", v, "DisplayDurations" -> 0.5]
If you absolutely want the animation to look like a Manipulate, you could do something like so.
v = Table[Manipulate[Text[t],
{{t, Mod[k, 10], "start"}, 0, 10, 1, ControlType -> Trigger}],
{k, 4, 14}];
Export["Manip.gif", v, "DisplayDurations" -> 0.5]
You can use v = Animate[
Text[t], {{t, 4, "start"}, 0, 10, 1, ControlType -> Trigger,
AnimationRate -> 1, AnimationRepetitions -> 10}]
Related
When exporting rather complicated plots (especially ListDensityPlot) as a PDF or EPS (for publication, for example), the resulting file size can be quite large. For example:
data = Flatten[Table[{f0, f, Exp[-(f - f0)^2/25^2]}, {f0, 500, 700, 5}, {f, 300,
900}], 1];
plot=ListDensityPlot[data,PlotRange->{Automatic,Automatic,{0,1}},InterpolationOrder->0]
This example data set is on the order of the size I typically work with. When I export using Export["C:\\test.pdf", plot], it generates a PDF file 23.9MB in size. If I instead try Export["C:\\test1.pdf", Rasterize[plot]] it is far smaller, but the integrity and rescalability of the image naturally suffers.
This is complicated further if my actual figure is a combined plot, such as (Edit: f goes to 900)
plot2 = Show[plot, Plot[x, {x, 500, 900}, PlotStyle -> Thick]]
(or with some usage of Epilog) where I'd love to have the background ListDensityPlot be rasterized, but keep the other markup and plots in ``vector'' form. Or at the very least, the frame labels be non-rasterized.
Is there any way to do this?
Or, to accomplish the same goal via some other clever method?
Update
I've checked out the related question, but that's gotta be way more complicated than it needs to be (essentially exporting then importing). I've been able to utilize some of the tricks in that question to extract the plot separately from the axes:
axes = Graphics[{}, Options[plot2]]
plots = Graphics[plot2[[1]]]
But, the plots term loses the AspectRatio and PlotRange, etc. plots can be hit with a Rasterize, but it needs dimensional fixing.
And then, how to combine them together?
This is exactly the kind of problem for which I wrote the function linked here:
http://pages.uoregon.edu/noeckel/computernotes/Mathematica/listContourDensityPlot.html
It's based on the same idea as in Heike's answer -- I just added some more features so that you can safely change the aspect ratio, opacity, and combine with other plots. See my comment in Heike's answer.
To try it with your data, do something like this:
plot = Show[
listContourDensityPlot[data,
PlotRange -> {Automatic, Automatic, {0, 1}},
InterpolationOrder -> 0, Contours -> None],
Graphics[Line[{{500, 500}, {700, 700}}]]]
There are a couple of similar functions linked from the parent page, too.
If you're dealing with 2D plots, you could combine a rasterized plot with vectorized axes by using Inset. For example
plot2 = ListDensityPlot[data,
PlotRange -> {Automatic, Automatic, {0, 1}},
InterpolationOrder -> 0, Axes -> False, Frame -> False,
PlotRangePadding -> 0];
plotRange = PlotRange /. AbsoluteOptions[plot2, PlotRange];
plot = Graphics[{
Inset[Image[plot2], plotRange[[All, 1]], {Left, Bottom}, Scaled[{.96, .96}]],
Line[{{500, 500}, {700, 700}}]},
Frame -> True, AspectRatio -> 1,
PlotRange -> plotRange, PlotRangePadding -> Scaled[.02]]
Export["test.pdf", plot]
produces a .pdf of about 400 KB. The frame, tick marks, and black line are still vectorized, so they stay sharp when zooming in:
If you are exporting as PDF, EPs or WMF, then the text should remain as vectors even if you have a rasterized component to the graphics.
I think the trick is to set the number of plot points to some low number in the ListDensityPlot command and then export as PDF as normal.
How about just plotting the function rather than making a list?
plot=DensityPlot[Exp[-(f - f0)^2/25^2], {f0, 500, 700}, {f, 300, 900},
Epilog -> {Thick, Line[{{500, 500}, {700, 700}}]}, PlotPoints -> 50]
Export["test.pdf", plot]
file size 1.1MB
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.
I noticed that if I rotates a 3D image using the mouse, there is a little jitter or shaking in the notebook interface itself as I rotate the image around with the mouse.
i.e. the frame where the 3D image itself is, does shift a little up and down the notebook.
I tried all the tricks I know to prevent this, from setting different ImagePadding, PlotRangePadding, ImageMargins, PlotRange, ContentSize and everything else but no luck.
Here is a small example, I just used RegionPlot3D as an example, but any 3D plot will do.
Manipulate[
RegionPlot3D[True,
{x,1,2},{y,1,2},{z,1,2},
AxesLabel-> label,
ImageSize->{340,450},
ImagePadding->10,
ImageMargins->10,
MeshStyle->Automatic,
PlotRangePadding->1,
AxesOrigin->{0,0,0},
PlotRange->{{0,2},{0,2},{0,2}},
Boxed->False],
{n,0,ControlType->None},
SynchronousUpdating->False,
ContinuousAction->False
]
Now if you run the above, and using the mouse to rotate the little cube, you'll start noticing, once you release the mouse, that the notebook did jitter a little. Feel free to try any other settings.
It is annoying, as I do not like this shaking effect. Makes me dizzy.
Any expert here might know if it is option setting that I am overlooking in the Plot command itself, or may be something else? I'd like the plot frame and the notebook itself not to shake while I am rotating the image inside with the mouse. The problem again shows up when one release the mouse.
Mathematica 8.0.1 on windows 7.
thanks
--Nasser
ps. I tried to search if this was asked before, but did not spot something.
Try:
SphericalRegion -> True
Like in:
Manipulate[
RegionPlot3D[True, {x, 1, 2}, {y, 1, 2}, {z, 1, 2},
AxesLabel -> label, SphericalRegion -> True,
ImageSize -> {340, 450}, ImagePadding -> 10, ImageMargins -> 10,
MeshStyle -> Automatic, PlotRangePadding -> 1,
AxesOrigin -> {0, 0, 0}, PlotRange -> {{0, 2}, {0, 2}, {0, 2}},
Boxed -> False], {n, 0, ControlType -> None},
SynchronousUpdating -> False, ContinuousAction -> False]
From the Help:
With SphericalRegion->True, the image of a particular object remains consistent
in size, regardless of the orientation of the object.
Edit
Usage example in this answer: How to create 2D (3D) animation in Wolfram Mathematica with the camera following the object?
HTH!
Given Graphics object, how do I determine the range of coordinates needed to include all of graphics? Basically I need something like what Show does by default, but I want to specify PlotRange,PlotRangePadding and ImagePadding explicitly.
Example, two Shows below should render the same
g = Graphics[{Thickness[1], CapForm["Round"], Line[{{0, 0}, {1, 1}}]}];
Show[g]
Show[g, PlotRange -> getPlotRange[g], PlotRangePadding->getPlotRangePadding[g], ImagePadding->getImagePadding[g]]
Motivation: fixing diagrams in this question
Update:
AbsoluteOptions gives me PlotRange but not the other two options. Explicitly specifying ImagePadding->Automatic changes appearance though it's supposedly Automatic by default.
Two images below show differently and I don't understand why
g = Graphics[{Thickness[1], CapForm["Round"], Line[{{0, 0}, {1, 1}}]}];
Show[g]
Show[g, Sequence ## AbsoluteOptions[Show[g]]]
Update 2:
A similar problem was brought up a year ago, with no solutions proposed, and not fixed as of Mathematica 8.0. To summarize
There's no way to reproduce Show[g] above with explicit setting of PlotRange
There's no way to get absolute ImagePadding used by Show[g]
Show[g,PlotRange->Automatic] looks different from Show[g]
AbsoluteOptions can give the wrong result for PlotRange
I can suggest the following Ticks hack:
pl = Plot[Sin[x], {x, 0, 10}];
Reap[Rasterize[Show[pl, Ticks -> {Sow[{##}] &, Sow[{##}] &}, ImageSize -> 0],
ImageResolution -> 1]][[2, 1]]
=> {{-0.208333, 10.2083}, {-1.04167, 1.04167}}
The trick is that real PlotRange is determined by the FrontEnd, not by the Kernel. So we must force the FrontEnd to render the graphics in order to get tick functions evaluated. This hack gives the complete PlotRange with explicit value of PlotRangePadding added.
More general solution taking into account a possibility that pl has non-standard value of DisplayFinction option and that it may have Axes option set to False:
completePlotRange[plot:(_Graphics|_Graphics3D|_Graph)] :=
Quiet#Last#
Last#Reap[
Rasterize[
Show[plot, Axes -> True, Frame -> False, Ticks -> (Sow[{##}] &),
DisplayFunction -> Identity, ImageSize -> 0], ImageResolution -> 1]]
One can get the exact PlotRange (without the PlotRangePadding added) with the following function:
plotRange[plot : (_Graphics | _Graphics3D | _Graph)] :=
Quiet#Last#
Last#Reap[
Rasterize[
Show[plot, PlotRangePadding -> None, Axes -> True, Frame -> False,
Ticks -> (Sow[{##}] &), DisplayFunction -> Identity, ImageSize -> 0],
ImageResolution -> 1]]
P.S. On the Documentation page for PlotRange under the "More information" one can read: "AbsoluteOptions gives the actual settings for options used internally by Mathematica when the setting given is Automatic or All. " (emphasis mine). So it seems that the Documentation does not even guarantee that AbsoluteOptions will give correct values for PlotRange when it is not Automatic or All.
I, too, sometimes find it confusing how to get Mathematica to display Graphics in a consistent way, particularly when insetting graphics.
For the specified graphic g, it doesn't matter what you provide for the PlotRange, because Thickness[1] always draws a line whose thickness is equal to the horizontal plot range. In your example, Show[g, ___] gives the correct result:
.
Show[g], or simply g, is anomalous.
Why?
I don't know where/if this is documented, but here are a few things that might be relevant to the question.
Obviously DisplayForm[Graphics[___]] is a raster.
We can get a raster for g using Rasterize[g]. What is the RasterSize? From trial and
error, I found that RasterSize is 10 * screen resolution (reported as 72 pixels per inch on my system). How do I know this? If I rasterize g with resolutions less than 718, I get an image with dimensions {360,361}, whereas the default image size for g is 360 pixels on my system, so I figure to Show[] a graphic, Mathematica Rasterize's it at 10x the screen resolution. Anybody know if this is true? You can get your screen resolution (at least as Mathematica sees it) from the Options Inspector.
Edit
That the following expression evaluates as True seems to show that the displayed graphic is rasterized at the ImageSize:
ImportString[ExportString[Show[g,ImageSize->100],"PNG"]]
=== ImportString[ExportString[Rasterize[g,RasterSize->100,ImageSize->100],"PNG"]
To reproduce Show[g] when using PlotRange I need to use
Show[g,PlotRange->{{0,1},{0,1}},ImagePadding->90.3]
to get it to crop to the perimeter of the line. So it seems that Mathematica is telling the truth that the PlotRange is {{0,1},{0,1}} when using AbsoluteOptions[]. It is not reporting the actual value of ImagePadding. Perhaps because ImagePadding->Automatic is based on a rule that uses the current ImageSize, PlotRangeClipping,... settings? The ImagePadding of 90.3 only works for ImageSize->360; setting ImageSize->200 makes the ImagePadding value wrong. For your graphic, ImagePadding->90.3*OptionValue[ImageSize]/360 reproduces Show[g,ImageSize->_] on my system.
That's all I've found out so far.
You can try adding a recognizable object at a known location and then see where it shows up in the exported version to provide a scale reference. I thought a vector export (SVG or EPS) would be easier to parse, but I think raster is easier after playing around a bit.
For example, add a green rectangle covering the theoretical plot range:
g = Graphics[{Blue, Thickness[1], CapForm["Round"],
Line[{{0, 0}, {1, 1}}], Green, Rectangle[{0, 0}, {1, 1}]}];
im = Rasterize[g, ImageSize -> 360];
xy = Transpose[Position[ImageData[im], {0., 1., 0.}]];
pad = Map[{Min[#1], 360 - Max[#1] } &, xy];
Show[g, ImagePadding -> pad]
The code is basically identifying where all the green pixels are.
The padding in this case is {{92, 92}, {92, 92}}, but it need not be symmetrical.
How do you plot legends for functions without using the PlotLegends package?
I, too, was disappointed by the difficulty of getting PlotLegend to work correctly. I wrote my own brief function to make my own custom figure legends:
makePlotLegend[names_, markers_, origin_, markerSize_, fontSize_, font_] :=
Join ## Table[{
Text[
Style[names[[i]], FontSize -> fontSize, font],
Offset[
{1.5*markerSize, -(i - 0.5) * Max[markerSize,fontSize] * 1.25},
Scaled[origin]
],
{-1, 0}
],
Inset[
Show[markers[[i]], ImageSize -> markerSize],
Offset[
{0.5*markerSize, -(i - 0.5) * Max[markerSize,fontSize] * 1.25},
Scaled[origin]
],
{0, 0},
Background -> Directive[Opacity[0], White]
]
},
{i, 1, Length[names]}
];
It is flexible, but not so easy to use. "names" is a list of strings to render in the legend; "markers" is a list with the same length as "names" of Graphics objects representing the plot markers or graphics to render; "origin" is a two-element list with the absolute horizontal and vertical position of the upper-left corner of the legend; "markerSize" is the number of points to scale the markers to; "fontSize" is the font size; "font" is the name of the font to use. Here is an example:
Plot[{x, x^2}, {x, 0, 2}, PlotStyle -> {Blue, Red},
Epilog -> makePlotLegend[
{x, x^2},
(Graphics[{#, Line[{{-1, 0}, {1, 0}}]}]) & /# {Blue, Red},
{0.9, 0.3},
12,
12,
"Arial"
]
]
I would also be very interested in an answer to this question.
To tell you what is wrong with PlotLegends: It is terribly unstable and in many instances doesn't work at all.
Here is an example where PlotLegends screws up completely. Output is from Mathematica 7.0:
Assume that we have measured some data points corresponding to a number of functions, and we want to show how well they compare to the ideal function, or maybe how well they match with a calculated fit. No problem! We'll just Show[] the smooth plot together with a ListPlot of the data points, right?
It could look something like this:
Show[
Plot[{Sin[x], Sinh[x]}, {x, -Pi, Pi}],
ListPlot[Join[{#, Sin[#]} & /# Range[-Pi, Pi, .5],
{#, Sinh[#]} & /# Range[-Pi, Pi, .5]]]
]
Now we'd like to put a legend on the plot, so readers will know what on earth they're looking at. Easier said than done, mister! Let's add the PlotLegend to the Plot[]:
Show[
Plot[{Sin[x], Sinh[x]}, {x, -Pi, Pi}, PlotLegend -> {Sin[x], Sinh[x]}],
ListPlot[Join[{#, Sin[#]} & /# Range[-Pi, Pi, .5],
{#, Sinh[#]} & /# Range[-Pi, Pi, .5]]]
]
This looks GREAT! Publish immediately!
For such a basic and ubiquitously needed functionality, it sure has been a lot of work to find an alternative to PlotLegend that just works. The best alternative I've found so far has been to meticulously construct a list of plotstyles, then construct the legend by hand, and finally to show it together with the plot using ShowLegend[]. (See for example here) It's possible, but a lot of work.
So if anyone knows of a workaround to make PlotLegend work, an alternative package that works better, or just a neat way to get legends that can be automated easily, I would be very grateful! It would certainly make life a little bit easier.
If you are experiencing the weird behavior described by James When you are trying to use 'Show' to combine two images, then you should play around with using the 'Overlay' function instead of 'Show'.
Alternatively, I have found that as long as both graphics have a legend then 'Show' will render the composite image correctly.
If it looks a bit silly having two legends then you can remove the one from the second graphic by using options like:
PlotLegend -> {},
LegendPosition -> {0.1, 0.1},
LegendSize -> 0.001,
LegendShadow -> None,
LegendBorder -> None
This creates an empty and invisible legend but still allows the two graphics to be composed correctly by 'Show'.