Mathematica: Having a plot inside a loop of a module updated - dynamic

I would like to have a module like this
TestModule[n_] := Module[{{dataList = {{0, 0}, {1, 2}}}},
For[i = 1, i <= n, i++,
Pause[0.5];
Print[ ListLinePlot[dataList++]];
];
];
where a the values of a list get updated from iteration to iteration and instead of having the module producing me n plots, I rather would like to have only one plot, which is updated n times after each iteration.
I looked already at Dynamics[] and Monitor[], but could not yet find a solution with them. Any help is appreciated. :)

here is a straightforward application of Monitor:
TestModule[n_] := Module[{
dataList = {{0, 0}, {1, 2}},
plot = "starting..."
},
Monitor[
Do[
Pause[0.5];
plot = ListLinePlot[dataList++, PlotRange -> {0, n + 2}],
{i, 1, n}
],
plot
];
plot
];
Do you know mathematica.stackexchange.com? You'll get much more answers for Mathematica specific questions there...

Related

Gmsh cannot mesh element inside a volume

I'm trying to make a mesh of a piece of beam with stirrup and bars, but I'm having some trouble with stirrup, it is inside the main domain, and I do not know how to solve it. I'm attaching the .geo file, hoping someone could help. Maybe there are other way to mesh it, I do not know.
SetFactory("OpenCASCADE");
// Input
Rectangle(1) = {0, 0, 0, 300, 300, 0};
Disk(2) = {50, 50, 0, 10, 10};
Disk(3) = {50,250,0,10,10};
Disk(4) = {250,250,0,10,10};
Disk(5) = {250,50,0,10,10};
Rectangle(6) = {30,30,146,240,240,10};
Rectangle(7) = {40,40,146,220,220,10};
// Start Operations
s() = BooleanFragments{ Surface{1}; Delete; }{ Surface{2,3,4,5}; Delete;};
ext() = Extrude{0,0,300} {Surface{s()}; Layers{10}; Recombine;};
st() = BooleanFragments{ Surface{6}; Delete;}{Surface{7}; Delete;};
Recursive Delete {Surface{7}; }
Extrude{0,0,10} {Surface{22}; Layers{10}; Recombine;}
BooleanFragments{ Volume{5}; Delete;}{Volume{6}; Delete;}
// Mesh Options all elements needs to be Hexa
Mesh.RecombineAll = 2;
Not a complete answer; however, I think I identified the problem that probably causes the major troubles:
The circular extrusions (cylinders) touch the stirrup exactly at the vertices, thus creating complications to OpenCASCADE-based BooleanFragments operation.
The following code:
SetFactory("OpenCASCADE");
// Input
Rectangle(1) = {0, 0, 0, 300, 300, 0};
Disk(2) = {52, 52, 0, 10, 10};
Disk(3) = {52,248,0,10,10};
Disk(4) = {248,248,0,10,10};
Disk(5) = {248,52,0,10,10};
Rectangle(6) = {30,30,146,240,240,10};
Rectangle(7) = {40,40,146,220,220,10};
// Start Operations
s() = BooleanFragments{ Surface{1}; Delete; }{ Surface{2,3,4,5}; Delete;};
ext() = Extrude{0,0,300} {Surface{s()}; Layers{10}; Recombine;};
st() = BooleanFragments{ Surface{6}; Delete;}{Surface{7}; Delete;};
Recursive Delete {Surface{7}; }
Extrude{0,0,10} {Surface{22}; Layers{10}; Recombine;}
BooleanFragments{ Volume{5}; Delete;}{Volume{6}; Delete;}
// Mesh Options all elements needs to be Hexa
Mesh.RecombineAll = 2;
where I slightly shifted the cylinders to the inside (50->52 and 250 -> 248) should not have the meshing problem.
However, this disconnects the cylinders from the loop and modifies the problem drastically. Here is a zoom on the problematic part in the original, unmodified setup.
So, what you required from the CAD tool, is to handle the merging of those two surfaces (the loop and the cylinder) automatically using BooleanFragments, which might be problematic, especially if one has to take floating-point arithmetic aspects into account.

Formatting Manipulate output to have 2 cells in Mathematica

The following output code outputs an array from the manipulate statement. I would like to output the fitting and plot as two separate output cells that update dynamically. I think it should be pretty simple, but I am having trouble with it. I've tried using the CellPrint[] function, but did not get it to work.
Thanks,
Tal
temperatures(*mK*)= {300, 200, 150, 100, 75, 50, 25, 11, 10};
F[t_, \[Nu]_] := t^\[Nu];
rd (*uOhms*)= {27173.91304, 31250., 42372.88136, 200601.80542,
1.05263*10^6, 1.33333*10^7, 1.33333*10^8, 2.*10^8, 2.1*10^8};
logRd = Log10[rd];
f[\[Nu]0_] := Module[{\[Nu]},
\[Nu] = \[Nu]0;
data = Transpose[{F[temperatures, \[Nu]]*10^3, logRd}];
fitToHexatic = LinearModelFit[data[[4 ;; 6]], x, x];
plota =
Plot[fitToHexatic["BestFit"], {x, 0, data[[-1]][[1]]},
Axes -> False];
plotb = ListPlot[data, Axes -> False];
{fitToHexatic, Show[{plota, plotb}, Axes -> True]}
]
Manipulate[
f[nu],
{nu, -0.2, -1}
]
Screenshot of the output:
You don't need to use a Manipulate. You can get more control with lower level functions. E.g.
Slider[Dynamic[nu, (f[#]; nu = #) &], {-0.2, -1}]
Dynamic[Normal[fitToHexatic]]
Dynamic[Show[{plota, plotb}, Axes -> True]]
See also Prototypical Manipulate in lower level functions.

Mathematica dynamic to plot matrix data

I am trying to dynamically plot data contained in a matrix with Mathematica 7. The data is contained in it like this, obtained via a chemical model.
[year H He Li C ... C8H14+,Grain- ]
[0 0 0.03 0.009 1E-3 ... 0 ]
[100 .1 0.03 0.009 1E-3 ... 0 ]
[200 .2 0.03 0.009 1E-3 ... 0 ]
[300 .2 0.03 0.009 1E-3 ... 0 ]
[... ... ... ... ... ... ... ]
[1E6 .5 0.03 0.003 1E-8 ... 1E-25 ]
The truth is, the matrix dimensions are 2001*1476 (2000 steps and first line for name, and 1475 compounds + 1 column for year), very heavy.
I am trying to plot any compound with a concentration / year plot. This works
Manipulate[
ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]] ],
{{i, 2, "Compound"}, 2, compounds, 1}
]
where data is the matrix, and compounds a variable set at the number of modelized compounds (1475 here). "compound" is a label for the slider.
The problem is, the slider moves much to fast as a few centimeters browse through 1400+ items.
I tried to do a drop-down menu with
MenuView[
Table[
ListLogLogPlot[data[[All, {1, i}]],PlotLabel -> data[[1, i]]], {i, 2, compounds}
]
]
It also works, but this is a processor killer process (10+ minutes on a Xeon 16-core server executing 16 kernels), as Mathematica try to graph all plots before displaying any of them. Also the drop-down has no name, just a series of numbers (1 for hydrogen to 1475 for C8H14N+,Grain-), even though the plot has a name.
What I am searching a way to plot a graph only on demand, with a name display in the drop-down list (and if required H by default). OR a field where I can enter the name of the compound. This seems to be possible with Dynamic[ ] command, but I don't manage to make it work properly.
Thanks
Mike's suggestion is a good one but if you don't want to go to the effort of putting it in a database, use the ContinuousAction->False option.
testdata =
Join[{Table[ToString[series[i-1]], {i, 1475}]},
RandomReal[{1., 100.}, {2000, 1476}]];
Manipulate[
ListLogLogPlot[testdata[[All, {1, i}]],
PlotLabel -> testdata[[1, i]]], {{i, 2, "Compound"}, 2, 1475, 1},
ContinuousAction -> False]
To get a popup menu, use the {i,listofvalues} syntax for the controller specification.
Manipulate[
ListLogLogPlot[testdata[[All, {1, i}]],
PlotLabel -> testdata[[1, i]]], {i, Range[2, 1475]},
ContinuousAction -> False]
This works pretty fast on my system. (Two year old MacBook Pro)
A fancier version:
spec = Thread[Range[2, 1476] -> Table[ToString[series[i]], {i, 1475}]];
Manipulate[
ListLogLogPlot[testdata[[All, {1, i}]],
PlotLabel -> testdata[[1, i]]], {{i, 2, "Compound"}, spec},
ContinuousAction -> False]
And if all you want to do is step through the images, click on the little plus next to a slider controller to get more detailed controls.
For entering names in an InputField, you could do something like
compounds = Rest[data[[1]]];
Manipulate[
If[MemberQ[compounds, compound], i = Position[compounds, compound][[1, 1]] + 1];
ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]]],
{{i, 2}, None},
{{compound, data[[1, 2]], "Compound"}, InputField[#, String] &}]
Here, compounds is a list of all the names of the compounds. The If statement in Manipulate is to check whether the name entered in the InputField is a valid compound or not.
Others have already given you ways to create one big popup list. If you don't want to scroll through a popup list of 1475 compounds, you could consider splitting the popup list into sublists. For example, this would split the whole list of compounds into sublists of n=50 elements which might make it easier to navigate
compounds = Rest[data[[1]]];
With[{n = 50},
Manipulate[
i = 1 + Position[compounds, name][[1, 1]];
ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]]],
{{i, 2}, None},
{{indexlist, 1, "Indices"},
Table[i -> ToString[(i - 1) n + 1] <> " through " <>
ToString[Min[i n, Length[compounds]]],
{i, Ceiling[Length[compounds]/n]}], PopupMenu},
{{name, compounds[[1]], "Compound"},
compounds[[n (indexlist - 1) + 1 ;;
Min[Length[compounds], n indexlist]]], PopupMenu}
]
]
For example, for
data = Table[Join[{i}, RandomReal[{0, 1}, 1000]], {i, 1000}];
data = Join[{Prepend[Table["list " <> ToString[i], {i, 1000}], "year"]}, data];
this looks like
For data sets of this size I'd recommend (as optimal) storing it all in a database and using DatabaseLink to call stuff as required. Then link your controllers, such as popup menus, to SQLExecute code or other SQL functions. Fragments like this would be the sort of thing that would do the job:
DynamicModule[{x,data, ...},
Column[{
PopupMenu[Dynamic[x], {1 -> "category 1", 2 -> "category 2", 3 -> "category 3", ...}],
Dynamic[
data = SQLExecute[conn, "SELECT * FROM myDatabase.table WHERE my_id = `1`;", {x}];
ListLogLogPlot[data]
]
}]
]
In reality you may want to be adding additional popups and doing joins and so on.
EDIT
Alternative that doesn't use databases but uses input fields as requested:
DynamicModule[{x = "He", rules, y},
rules = Rule ### Transpose[{data[[1, All]], Range[Length[data[[1, All]]]]}];
Column[{
InputField[Dynamic[x], String],
Dynamic[
y = x /. rules;
ListLogLogPlot[data[[All, {1, y}]], PlotLabel -> data[[1, y]]]
]
}]
]
For rules lists of this size you'd probably want to use Dispatch I'd imagine. See how the timing goes for that. It looks like this is some sort of experiment you are running so my first choice remains dumping it into a DB.
FURTHER EDIT
If you're relying on input fields then you will need to account for clumsy typing by inserting a conditional so that Mma only attempts to plot if y is an integer.
If[IntegerQ[y],
ListLogLogPlot,
Spacer[0]
]

Can we decrease Bar size width in BarChart in Mathematica?

dalist = {901, 503, 522, 1305}
cogColors = {RGBColor[0, 0, 1], RGBColor[1, 0, 0], RGBColor[0, 1, 0], RGBColor[1, 1, 0]}
BarChart[dalist, ChartStyle -> cogColors]
Is it possible to decrease the Bars Width ?
I may be missing the point, but cannot you merely change the aspect ratio?
BarChart[dalist, ChartStyle -> cogColors, AspectRatio -> 3, ImageSize -> 120]
BarChart is not intended to do that. You can only change the spacings.
Use RectangleChart instead if you need finer control:
RectangleChart[{{{1, 1}, {1, 1}, {1, 1}}, {{2, 2}, {2, 2}, {2, 2}}}]
Rather than changing the bar chart width, you can increase the bar spacing.
BarChart[dalist, ChartStyle -> cogColors, BarSpacing -> 1]
See Heike's answer to my earlier question. You need to use RectangleChart. If you want to keep a constant distance between bar centres, so that the bar-plus-spacing takes up a constant space, you can use the ChartElementFunction option together with an auxiliary function, as shown in Heike's answer. (This might also do what you want using BarChart, but I'd still recommend RectangleChart.)

dynamic interactivity problem

I am trying to have two panels, the left showing a graphic and two locators, the right one a zoomed-in version in the area defined by the locators.
I've tried
ClearAll[mndpt];
mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
Module[{z, iters},
iters = 0.;
z = c;
While[(iters < maxiter) && (Abs#z < 2),
iters++;
z = z^2 + c];
Sqrt[iters/maxiter]],
{{z, _Complex}},
CompilationTarget \[Rule] "C",
RuntimeOptions \[Rule] "Speed"];
and do
Manipulate[
Grid[
{{DensityPlot[mndpt[x + y*I, 200],
{x, -2, 1}, {y, -1.5, 1.5},
PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80,
ColorFunction \[Rule] "Rainbow"],
DensityPlot[mndpt[x + y*I, 200],
Dynamic#{x, p1[[1]], p2[[1]]}, Dynamic#{y, p1[[2]], p2[[2]]},
PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80,
ColorFunction \[Rule] "Rainbow"]}}],
{{p1, {-1, -1}}, Locator}, {{p2, {0, 1}}, Locator}]
The right panel does not then work:
My question is, why is this so? As you can see, it complains that "DensityPlot::pllim: Range specification {x,-1,0} is not of the form {x, xmin, xmax}. " which I find puzzling. In fact I am generally puzzled. What is going on? Some sort of scoping issue? Evaluation issue? And how can I get it to work? This is probably simple, but I never really understood this frontend stuff.
EDIT: It turns out that this question was due to a (hopefully momentary) sharp increase in stupidity on my part. As pointed out by Simon in a comment, removing the two Dynamics
(which I had added in a blind effort to make this work) makes everything work fine. That is,
Manipulate[
Grid[
{{DensityPlot[mndpt[x + y*I, 200],
{x, -2, 1}, {y, -1.5, 1.5},
PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80,
ColorFunction \[Rule] "Rainbow"],
DensityPlot[mndpt[x + y*I, 200],
{x, p1[[1]], p2[[1]]},{y, p1[[2]], p2[[2]]},
PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80,
ColorFunction \[Rule] "Rainbow"]}}],
{{p1, {-1, -1}}, Locator}, {{p2, {0, 1}}, Locator}]
does the right thing:
So, who knows why else I did the first few times so that it didn't work.
On the other hand, the message in the original case, namely, "DensityPlot::pllim: Range specification {x,-1,0} is not of the form {x, xmin, xmax}. " was more puzzling. I think it's been explained by Leonid, also in a comment (in brief, try ClearAttributes[Dynamic, ReadProtected] then ??Dynamic and you can see that there is a definition Dynamic/:MakeBoxes[BoxForm`x$_Dynamic,StandardForm]:= etc). As my understanding of frontend programming is negligible I won't try to explain it here, so if anybody does post an answer explaining that, it would be appreciated.
As discussed in the comments to the question, the code works fine if the Dynamics are removed from the ranges in the second DensityPlot. The Dynamics are not normally needed in the body of a Manipulate as it is automatically wrapped in a dynamic construct. Although, for a more fine grained control of which parts of an expression update, it can be useful to use Dynamic inside of a Manipulate.
The reason an error was created was because the range of a plot should be of the form {x, xmin, xmax} with x a Symbol and xmin and xmax numeric. Wrapping Dynamic around the list changes the head and breaks the plot.
The reason that the error was not obvious to spot is because the error message was a little confusing:
Range specification {x,-1,0} is not of the form {x, xmin, xmax}.
Which, on the surface looks crazy, but makes sense once you realise (as pointed out by Leonid) that Dynamic is a wrapper that has a MakeBoxes definition that makes it invisible when outputted to the notebook. To see this, look at
In[1]:= FormatValues[Dynamic]
Out[1]= {HoldPattern[MakeBoxes[BoxForm`x$_Dynamic, StandardForm]] :> (DynamicModule;
DynamicDump`ControlToBoxes[BoxForm`x$, StandardForm]),
<<snip: same but for TraditionalForm>>}
and ControlToBoxes in turn, creates a DynamicBox object. This can also be seen by entering Dynamic[x] and using the cell menu or shortcut to Show Expression of the produced output cell - you can also look at the underlying expression of the error message and see the DynamicBox construction there. It's also possible to Unprotect and remove the MakeBoxes definition of Dynamic, but that breaks most of the dynamic functionality in Mathematica...
Finally, here's my version of the code:
mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
Module[{z = c, iters = 0.0},
While[(iters < maxiter) && (Abs#z < 2), iters++; z = z^2 + c];
Sqrt[iters/maxiter]], CompilationTarget -> "C",
RuntimeOptions -> "Speed"];
opts = Sequence[PlotPoints -> 80, ColorFunction -> "Rainbow",
ImageSize -> Medium, ImagePadding -> {{30, 5}, {20, 5}}];
fixed = DensityPlot[mndpt[x + y*I, 200], {x, -2, 1}, {y, -1.5, 1.5},
PlotPoints -> 120, Evaluate[opts]];
Manipulate[Grid[{{fixed, DensityPlot[mndpt[x + y*I, 200],
{x, p[[1, 1]], p[[2, 1]]}, {y, p[[1, 2]], p[[2, 2]]}, Evaluate[opts]]}}],
{{p, {{-1, -1}, {0, 1}}}, Locator, ContinuousAction -> False}]