acer

16581 Reputation

29 Badges

14 years, 20 days

On google groups. (comp.soft-sys.math.maple and sci.math.symbolic)

On stackoverflow.

On math.stackexchange.com.

MaplePrimes Activity


These are Posts that have been published by acer

There have been several posts, over the years, related to visual cues about the values associated with particular 2D contours in a plot.

Some people ask or post about color-bars [1]. Some people ask or post about inlined labelling of the curves [1, 2, 3, 4, 5, 6, 7]. And some post about mouse popup/hover-over functionality [1]., which got added as general new 2D plot annotation functionality in Maple 2017 and is available for the plots:-contourplot command via its contourlabels option.

Another possibility consists of a legend for 2D contour plots, with distinct entries for each contour value. That is not currently available from the plots:-contourplot command as documented. This post is about obtaining such a legend.

Aside from the method used below, a similar effect may be possible (possibly with a little effort) using contour-plotting approaches based on individual plots:-implicitplot calls for each contour level. Eg. using Kitonum's procedure, or an undocumented, alternate internal driver for plots:-contourplot.

Since I like the functionality provided by the contourlabels option I thought that I'd highjack that (and the _HOVERCONTENT plotting substructure that plot-annotations now generate) and get a relatively convenient way to get a color-key via the 2D plotting legend.  This is not supposed to be super-efficient.

Here below are some examples. I hope that it illustrates some useful functionality that could be added to the contourplot command. It can also be used to get a color-key for use with densityplot.

restart;

contplot:=proc(ee, rng1, rng2)
  local clabels, clegend, i, ncrvs, newP, otherdat, others, tcrvs, tempP;
  (clegend,others):=selectremove(type,[_rest],identical(:-legend)=anything);
  (clabels,others):= selectremove(type,others,identical(:-contourlabels)=anything);
  if nops(clegend)>0 then
    tempP:=:-plots:-contourplot(ee,rng1,rng2,others[],
                                ':-contourlabels'=rhs(clegend[-1]));
    tempP:=subsindets(tempP,'specfunc(:-_HOVERCONTENT)',
                      u->`if`(has(u,"null"),NULL,':-LEGEND'(op(u))));
    if nops(clabels)>0 then
      newP:=plots:-contourplot(ee,rng1,rng2,others[],
                              ':-contourlabels'=rhs(clabels[-1]));
      tcrvs:=select(type,[op(tempP)],'specfunc(CURVES)');
      (ncrvs,otherdat):=selectremove(type,[op(newP)],'specfunc(CURVES)');
      return ':-PLOT'(seq(':-CURVES'(op(ncrvs[i]),op(indets(tcrvs[i],'specfunc(:-LEGEND)'))),
                          i=1..nops(ncrvs)),
                      op(otherdat));
    else
      return tempP;
    end if;
  elif nops(clabels)>0 then
    return plots:-contourplot(ee,rng1,rng2,others[],
                              ':-contourlabels'=rhs(clabels[-1]));
  else
    return plots:-contourplot(ee,rng1,rng2,others[]);
  end if;
end proc:
 

contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 9,
      size=[500,400],
      legendstyle = [location = right],
      legend=true,
      contourlabels=true,
      view=[-2.1..2.1,-2.1..2.1]
);

contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 17,
      size=[500,400],
      legendstyle = [location = right],
      legend=['contourvalue',$("null",7),'contourvalue',$("null",7),'contourvalue'],
      contourlabels=true,
      view=[-2.1..2.1,-2.1..2.1]
);

# Apparently legend items must be unique, to persist on document re-open.

contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 11,
      size=[500,400],
      legendstyle = [location = right],
      legend=['contourvalue',seq(cat($(` `,i)),i=2..5),
              'contourvalue',seq(cat($(` `,i)),i=6..9),
              'contourvalue'],
      contourlabels=true,
      view=[-2.1..2.1,-2.1..2.1]
);

contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Green","Red"],
      contours = 8,
      size=[400,450],
      legend=true,
      contourlabels=true
);

contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 13,
      legend=['contourvalue',$("null",5),'contourvalue',$("null",5),'contourvalue'],
      contourlabels=true
);

(low,high,N):=0.1,7.6,23:
conts:=[seq(low..high*1.01, (high-low)/(N-1))]:
contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = conts,
      legend=['contourvalue',$("null",floor((N-3)/2)),'contourvalue',$("null",ceil((N-3)/2)),'contourvalue'],
      contourlabels=true
);

plots:-display(
  subsindets(contplot((x^2+y^2)^(1/2), x=-2..2, y=-2..2,
                      coloring=["Yellow","Blue"],
                      contours = 7,
                      filledregions),
             specfunc(CURVES),u->NULL),
  contplot((x^2+y^2)^(1/2), x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 7, #grid=[50,50],
      thickness=0,
      legendstyle = [location=right],
      legend=true),
  size=[600,500],
  view=[-2.1..2.1,-2.1..2.1]
);

 

plots:-display(
  contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 5,
      thickness=0, filledregions),
  contplot(x^2+y^2, x=-2..2, y=-2..2,
      coloring=["Yellow","Blue"],
      contours = 5,
      thickness=3,
      legendstyle = [location=right],
      legend=typeset("<=",contourvalue)),
  size=[700,600],
  view=[-2.1..2.1,-2.1..2.1]
);

N:=11:
plots:-display(
  contplot(sin(x)*y, x=-2*Pi..2*Pi, y=-1..1,
      coloring=["Yellow","Blue"],
      contours = [seq(-1+(i-1)*(1-(-1))/(N-1),i=1..N)],
      thickness=3,
      legendstyle = [location=right],
      legend=true),
   plots:-densityplot(sin(x)*y, x=-2*Pi..2*Pi, y=-1..1,
      colorscheme=["zgradient",["Yellow","Blue"],colorspace="RGB"],
      grid=[100,100],
      style=surface, restricttoranges),
   plottools:-line([-2*Pi,-1],[-2*Pi,1],thickness=3,color=white),
   plottools:-line([2*Pi,-1],[2*Pi,1],thickness=3,color=white),
   plottools:-line([-2*Pi,1],[2*Pi,1],thickness=3,color=white),
   plottools:-line([-2*Pi,-1],[2*Pi,-1],thickness=3,color=white),
   size=[600,500]
);

N:=13:
plots:-display(
  contplot(sin(x)*y, x=-2*Pi..2*Pi, y=-1..1,
      coloring=["Yellow","Blue"],
      contours = [seq(-1+(i-1)*(1-(-1))/(N-1),i=1..N)],
      thickness=6,
      legendstyle = [location=right],
      legend=['contourvalue',seq(cat($(` `,i)),i=2..3),
              'contourvalue',seq(cat($(` `,i)),i=5..6),
              'contourvalue',seq(cat($(` `,i)),i=8..9),
              'contourvalue',seq(cat($(` `,i)),i=11..12),
              'contourvalue']),
   plots:-densityplot(sin(x)*y, x=-2*Pi..2*Pi, y=-1..1,
      colorscheme=["zgradient",["Yellow","Blue"],colorspace="RGB"],
      grid=[100,100],
      style=surface, restricttoranges),
   plottools:-line([-2*Pi,-1],[-2*Pi,1],thickness=6,color=white),
   plottools:-line([2*Pi,-1],[2*Pi,1],thickness=6,color=white),
   plottools:-line([-2*Pi,1],[2*Pi,1],thickness=6,color=white),
   plottools:-line([-2*Pi,-1],[2*Pi,-1],thickness=6,color=white),
  size=[600,500]
);

 

Download contour_legend_post.mw

 

 

 

 

While generating a 3D plot of the solution of an ODE with a parameter, I noticed that better performance could be obtained by calling the plot3d command with a procedure argument, done in a special manner.

I don't recall this being discussed before, so I'll share it. (It it has been discussed, and this is widely known, then I apologize.)

I tweaked the initial conditions of the original ODE system, to obtain a non-trivial solution. I don't think that the particular nature of the solution has a bearing on this note.

restart;

Digits := 15:

 

 

The ODE system has two parameters. One, A, will get a fixed value. The

other, U0, will be used like an independent variable for plotting.

 

 

eq1:= diff(r[1](t), t, t)+(.3293064114+209.6419478*U0)*(diff(r[1](t), t))
      +569.4324330*r[1](t)-0.3123434112e-2*V(t) = -1.547206836*U0^2*q(t):
eq2:= 2.03*10^(-8)*(diff(V(t), t))+4.065040650*10^(-11)*V(t)
      +0.3123434112e-2*(diff(r[1](t), t)) = 0:
eq3 := diff(q(t), t, t)+1047.197552*U0*(q(t)^2-1)*(diff(q(t), t))
       +1.096622713*10^6*U0^2*q(t) = -2822.855019*A*(diff(r[1](t), t, t)):

 

ics:=r[1](0)=0,D(r[1])(0)=1e-1,V(0)=0,q(0)=0,D(q)(0)=0:

 

res := dsolve({eq1,eq2,eq3, ics},numeric,output=listprocedure,parameters=[A,U0]):

 

I will call the procedure returned by dsolve, for evalutions of V(t), as the

dsolve numeric solution-procedure in the discussion below.

 

WV := eval(V(t), res):

 

WV(parameters=[A=1e0]):

 

 

The goal is to produce a 3D plot of V(t) as a function of t and the parameter U0.

 

 

tlo,thi := 0.0, 2.0;
U0lo,U0hi := 1e-3, 2e-1;

0., 2.0

0.1e-2, .2

 

This is the grid size used for plot3d below. It is nothing special.

 

(m,n) := 51,51;

51, 51

 

First, I'll demonstrate that a 3D plot can be produced quickly, by populating a
Matrix for floating-point evaluations of V(t), depending on t in the first
Matrix-dimension and on parameter U0 in the second Matrix-dimansion.

 

The surfdata command is used. This is similar to how plot3d works.

 

This  computes reasonably quickly.

 

But generating the numeric values for U0 and t , based on the i,j positions

in the Matrix, involves the kind of sequence generation formulas that are

error prone for people.

 

str := time[real]():
M:=Matrix(m,n,datatype=float[8]):
for j from 1 to n do
  u0 := U0lo+(j-1)*(U0hi-U0lo)/(n-1);
  WV(parameters=[U0=u0]);
  for i from 1 to m do
    T := tlo+(i-1)*(thi-tlo)/(m-1);
    try
      M[i,j] := WV(T);
    catch:
      # mostly maxfun complaint for t above some value.
      M[i,j] := Float(undefined);
    end try;
  end do:
end do:
plots:-surfdata(M, tlo..thi, U0lo..U0hi,
                labels=["t","U0","V(t)"]);
(time[real]()-str)*'seconds';

1.686*seconds

 

So let's try it using the plot3d command directly. A 2-parameter procedure
is constructed, to pass to plot3d. It's not too complicated. This procedure
will uses one of its numeric arguments to set the ODE's U0 parameter's

value for the dsolve numeric solution-procedure, and then pass along

the other numeric argument as a t value.


It's much slower than the surfdata call above..

 

VofU0 := proc(T,u0)
       WV(parameters=[U0=u0]);
       WV(T);
     end proc:

str := time[real]():
plot3d(VofU0, tlo..thi, U0lo..U0hi,
       grid=[m,n], labels=["t","U0","V(t)"]);
(time[real]()-str)*'seconds';

37.502*seconds

 

One reason why the previous attempt is slow is that the plot3d command

is changing values for U0 in its outer loop, and changing values of t in its

inner loop. The consequence is that the value for U0 changes for every

single evaluation of the plotted procedure. This makes the dsolve numeric

solution-procedure work harder, by losing/discarding prior numeric
solution details.

 

The simple 3D plot below demonstrates that the plot3d command chooses
x-y pairs by letting its second supplied independent variable be the one
that changes in its outer loop. Each time the value for y changes the counter

goes up by one.

 

glob:=0:
plot3d(proc(x,y) global glob; glob:=glob+1; end proc,
       0..3, 0..7, grid=[3,3],
       shading=zhue,  labels=["x","y","glob"]);

 

So now let's try and be clever and call the plot3d command with the two
independent variables reversed in position (in the call). That will make

the outer loop change t instead of the ODE parameter U0.

 

We can use the transform command to swap the two indepenent
axes in the plot, if we prefer the axes roles switched. Or we could use the
parametric calling sequence of plot3d for the same effect.

 

The problem is that this is still much slower!

 

VofU0rev := proc(u0,T)
       WV(parameters=[U0=u0]);
       WV(T);
     end proc:

str := time[real]():
Prev:=plot3d(VofU0rev, U0lo..U0hi, tlo..thi,
             grid=[n,m], labels=["U0","t","V(t)"]):
(time[real]()-str)*'seconds';

plots:-display(
  plottools:-transform((x,y,z)->[y,x,z])(Prev),
  labels=["t","U0","V(t)"],
  orientation=[50,70,0]);

34.306*seconds

 

There is something else to adjust, to get the quick timing while using

the plot3d command here.

 

It turns out that setting the parameter's numeric value in the
dsolve numeric solution-procedure causes the loss of previous details
of the numeric solving, even if the parameter's value is the same.

 

So calling the dsolve numeric solution-procedure to set the parameter

value must be avoided, in the case that the new value is the same as

the old value.

 

One way to do that is to have the plotted procedure first call the

dsolve numeric solution-procedure to query the current parameter

value, so as to not reset the value if it is not changed. Another way

is to use a local of an appliable module to store the running value

of the parameter, and check against that. I choose the second way.

 

And plot3d must still be called with the first independent variable-range

as denoting the ODE's parameter (instead of the ODE's independent

variable).

 

And the resulting plot is fast once more.

 

VofU0module := module()
       local ModuleApply, paramloc;
       ModuleApply := proc(par,var)
         if not (par::numeric and var::numeric) then
           return 'procname'(args);
         end if;
         if paramloc <> par then
           paramloc := par;
           WV(parameters=[U0=paramloc]);
         end if;
         WV(var);
       end proc:
end module:

 

For fun, this time I'll use the parameter calling sequence to flip the

axes, instead of plots:-transform. That's just because I want t displayed

on the first axis. But for the performance gain, what matters is that it

is U0 which gets values from the first axis plotting-range.

 

str := time[real]():
plot3d([y,x,VofU0module(x,y)], x=U0lo..U0hi, y=tlo..thi,
       grid=[n,m], labels=["t","U0","V(t)"]);
(time[real]()-str)*'seconds';

1.625*seconds

 

And, naturally, I could also use the parametric form to get a fast plot

with the axes roles switched.

 

str := time[real]():
plot3d([x,y,VofU0module(x,y)], x=U0lo..U0hi, y=tlo..thi,
       grid=[n,m], labels=["U0","t","V(t)"]);
(time[real]()-str)*'seconds';

1.533*seconds

 

Download ode_param_plot.mw

Ian Thompson has written a new book, Understanding Maple.

I've been browsing through the book and am quite pleased with what I've read so far. As a small format paperback of just over 200 pages it packs in a considerable amount of useful information aimed at the new Maple user. It says, "At the time of writing the current version is Maple 2016."

The general scope and approach of the book is explained in its introduction, which can currently be previewed from the book's page on amazon.com. (Click on the image of the book's cover, to "Look inside", and then select "First Pages" in the "Book sections" tab in the left-panel.)

While not intended as a substitute for the Maple manuals (which, together, are naturally larger and more comprehensive) the book describes some of the big landscape of Maple, which I expect to help the new user. But it also explains how Maple is working at a lower level. Here are two phrases that stuck out: "This book takes a command driven, or programmatic, approach to Maple, with the focus on the language rather than the interface", followed closely by, "...the simple building blocks that make up the Maple language can be assembled to solve complex problems in an efficient way."

 

 

 

A modified version of John May's modification of Bruce Char's animated Christmas tree, using some Maple 2015 features to automatically scale the 3D plot and automatically play the animation.

I went with the viewpoint option, and removed the blinking lights. In the worksheet the tree shows as scaled larger. Perhaps it could be a submission to walkingrandomly.

bchartree1.mw

It looks like the Online Help has now been updated for Maple 2015.

Here's the What's New in Maple 2015 Overview, which is similar to the product pages currently available here.

But we can now also link to and view the online versions of full help pages of new or enhanced commands or example worksheets. For example, dataplot.

acer

1 2 3 4 5 6 7 Last Page 1 of 29