acer

32313 Reputation

29 Badges

19 years, 314 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

@Claybourne It looks as if you might (still) have GUI-based numeric formatting on that output?

(It's difficult to tell because you didn't attach the corresponding worksheet; you gave just an image of output, which is not very useful.)

@tomleslie Tom, you wrote,

  "When you write i[`1d`]  in Maple you are creating a TABLE with (so far)
    one indexed entry, whose index is the name '1d'."

That is not true. A table is not created merely by making an indexed reference.

(A table is created by assigning to an indexed reference of an otherwise unassigned name, but it is not created merely by using such an indexed name.)

An alternative approach, using the procedural colorscheme functionality available in Maple 2016 and later.

The plot3d command can produce a MESH that gets rendered here like a space-curve, but it doesn't render the color. So the MESH (of double necessary size, in one dimension) can be turned into the appropriate CURVES substructure, and the color data re-utilized.

This allows either HUE (single procedure) or RGB (three procedures) colorspaces. The procedures take three arguments (for x,y,z values) and thus can be quite general and efficient.

The memoization (option remember) on the returned dsolve procedures is added because plot3d needs at least 2 for the second (dummy) parameter, specified in the grid option.

restart:

kernelopts(version);

`Maple 2016.2, X86 64 LINUX, Jan 13 2017, Build ID 1194701`

sys := {diff(x(t),t)=v(t), diff(v(t), t)=cos(t), x(0)=-1, v(0)=0}:

sol := dsolve(sys, numeric, output=listprocedure):
X,V := eval([x(t),v(t)], sol)[]:

 

X:=subsop(3=[remember,system][],eval(X)):

V:=subsop(3=[remember,system][],eval(V)):

 

# Hue procedure

Hfunc3:=proc(t,xt,vt)
  piecewise(xt>=0 and vt>=0, 0.333,
            xt>=0, 0.0, vt>=0, 0.667, 0.140);
end proc:

CodeTools:-Usage(

  subsindets(plot3d([t,X(t),V(t)], t=0..4*Pi, __r=0..1,
                    grid=[200,2], thickness=5,
                    colorscheme=["xyzcoloring",(x,y,z)->Hfunc3(x,y,z)]),
             specfunc(MESH),M->CURVES(op(1,M)[..,1,..],
                                      COLOR(HUE,op([2,2],M)[..,1])))

);

memory used=4.62MiB, alloc change=32.00MiB, cpu time=66.00ms, real time=65.00ms, gc time=0ns

restart:

sys := {diff(x(t),t)=v(t), diff(v(t), t)=cos(t), x(0)=-1, v(0)=0}:

sol := dsolve(sys, numeric, output=listprocedure):
X,V := eval([x(t),v(t)], sol)[]:

 

X:=subsop(3=[remember,system][],eval(X)):

V:=subsop(3=[remember,system][],eval(V)):

 

# Red, Green, and Blue procedures

Rfun,Gfun,Bfun:=
  (x,y,z)->piecewise(y>=0 and z>=0, 0.0,
                     y>=0, 1.0, z>=0, 0.0, 1.0),
  (x,y,z)->piecewise(y>=0 and z>=0, 1.0,
                     y>=0, 0.0, z>=0, 0.0, 0.8),
  (x,y,z)->piecewise(y>=0 and z>=0, 0.0,
                     y>=0, 0.0, z>=0, 1.0, 0.0):

CodeTools:-Usage(

  subsindets(plot3d([t,X(t),V(t)], t=0..4*Pi, __r=0..1,
                    grid=[200,2], thickness=5,
                    colorscheme=["xyzcoloring",[Rfun,Gfun,Bfun]]),
             specfunc(MESH),M->CURVES(op(1,M)[..,1,..],
                                      COLOR(RGB,op([2,2],M)[..,1,..])))

);

memory used=4.57MiB, alloc change=32.00MiB, cpu time=48.00ms, real time=48.00ms, gc time=0ns

 

Download spacecurve_shaded_3.mw

I'd like to mention that I think dharr's workaround using tubeplot is ingenious. I have long admired his good responses on this forum. I simply felt that a topic as basic as coloring a 3D curve might be addressed slightly better.

I'll add that the syntax and usage of my solution (using some code developed long ago) is already a reasonably close match to what the OP described in the original Question.

And I'll also note that I too have found that that the ISOSURFACE plotting structure cannot properly be generally colored. (I have previously submitted a bug report on that.)

You are welcome, as always.

I'd like to mention that I consider this (which you cited) as a relative poor programming technique for such extraction from the listprocedure:
   T,X,V,PX,PV:=rhs~(sol)[ ] )
The problem is that is depends on matching the order of terms in the list. If that order were changed (ie. lexicographically) inadvertantly later on then a mismatch could produce wrong results. I much prefer using 2-argument eval to extract rhs's in a targeted manner.

I consider using tubeplot here to be somewhat of a kludge for a proper 3D curve.

The color procedures provided by dharr involve even more calls to X(t) and V(t) and using memoization there can bring an even greater relative improvement. (Though it's still not as fast as can be done by building a curve, and that difference increases with numpoints.)


 

restart:

kernelopts(version);

`Maple 2015.2, X86 64 LINUX, Dec 20 2015, Build ID 1097895`

 

SpaceCurve:=proc( T::list, trng::name=range(realcons),
          {numpoints::posint:=3, colorfunc::procedure:=NULL} )

  local M, C, t, a, b, i;

  t:=lhs(trng);

  a,b:=op(evalf(rhs(trng)));

  M:=[seq(eval(T,t=a+i*(b-a)/(numpoints-1)),i=0..numpoints-1)];

  if colorfunc=NULL then C:=NULL; else

    C:=:-COLOUR(':-RGB',
                hfarray([seq(colorfunc(a+(i-1)*(b-a)/(numpoints-1)),
                                       i=1..numpoints)]));

  end if;

  plots:-display(:-PLOT3D(:-CURVES(M,C),':-THICKNESS'(5)), _rest);

end proc:

 

# You could also write out this `cfunc` manually, if you
# already knew the RGB values, eg. for gold...

cfunc:=subs('gold'=[ColorTools:-Color("Gold")[]],
            'green'=[ColorTools:-Color("green")[]],
            'red'=[ColorTools:-Color("red")[]],
            'blue'=[ColorTools:-Color("blue")[]],
  proc(tt) local xt,vt;
    xt,vt := X(tt),V(tt);
    piecewise(xt>=0 and vt>=0, green,
              xt>=0, red, vt>=0, blue, gold);
end proc);

proc (tt) local xt, vt; xt, vt := X(tt), V(tt); piecewise(0 <= xt and 0 <= vt, [0., 1.00000000, 0.], 0 <= xt, [1.00000000, 0., 0.], 0 <= vt, [0., 0., 1.00000000], [1.00000000, .84313725, 0.]) end proc

 

sys := {diff(x(t),t)=v(t), diff(v(t), t)=cos(t), x(0)=-1, v(0)=0}:

sol := dsolve(sys, numeric, output=listprocedure):
X,V := eval([x(t),v(t)], sol)[]:

 


# Improving efficiency further.

X:=subsop(3=[remember,system][],eval(X)):

V:=subsop(3=[remember,system][],eval(V)):

 

CodeTools:-Usage(

  SpaceCurve([t, X(t), V(t)], t=0..4*Pi, colorfunc=cfunc,
             numpoints=200, labels=["t","x(t)","v(t)"])

);

memory used=4.90MiB, alloc change=32.00MiB, cpu time=67.00ms, real time=68.00ms, gc time=0ns

restart;

sys := {diff(x(t), t) = v(t), diff(v(t), t) = cos(t),
        x(0) = -1, v(0) = 0}:
sol := dsolve(sys, [x(t),v(t)], numeric,output=listprocedure):


# This is inferior to extracting with `eval`, since it
# relies on matching the lexicographic.

T,X,V:=rhs~(sol)[]:

cols:=table():
cols[1,1]:=[0,255,0]:#"Green":
cols[1,-1]:=[255,0,0]:#"Red":
cols[-1,1]:=[0,0,255]:#"Blue":
cols[-1,-1]:=[255,215,0]:#"Gold":

#
# In the absence of memoization this is (relatively)
# considerably worse, since it involves calling X(t)
# and V(t) more times.

fR := t->cols[signum(X(t)),signum(V(t))][1]:
fG := t->cols[signum(X(t)),signum(V(t))][2]:
fB := t->cols[signum(X(t)),signum(V(t))][3]:


# I use numpoints=200, to match the SpaceCurve use above.
# For the default (49) points the curve appears ragged.
# The timing for `tubeplot` grows faster than does that of
# `SpaceCurve`, as `numpoints` increases.
#
# Also, the colored curve below appears flat when viewed
# from certain angles, ie. not round.

CodeTools:-Usage(

  plots:-tubeplot([t, X(t), V(t)], t=0..4*Pi, radius=0.05,
                  color=[fR(t),fG(t),fB(t)],
                  style=surface, lightmodel=none,
                  numpoints=200, labels=["t","x(t)","v(t)"])

);

memory used=85.52MiB, alloc change=32.00MiB, cpu time=609.00ms, real time=610.00ms, gc time=37.86ms

restart;

sys := {diff(x(t), t) = v(t), diff(v(t), t) = cos(t),
        x(0) = -1, v(0) = 0}:
sol := dsolve(sys, [x(t),v(t)], numeric,output=listprocedure):


# This is inferior to extracting with `eval`, since it
# relies on matching the lexicographic.

T,X,V:=rhs~(sol)[]:

# Improving efficiency.

T:=subsop(3=[remember,system][],eval(T)):
X:=subsop(3=[remember,system][],eval(X)):

V:=subsop(3=[remember,system][],eval(V)):

 

cols:=table():
cols[1,1]:=[0,255,0]:#"Green":
cols[1,-1]:=[255,0,0]:#"Red":
cols[-1,1]:=[0,0,255]:#"Blue":
cols[-1,-1]:=[255,215,0]:#"Gold":

#
# In the absence of memoization this is (relatively)
# considerably worse, since it involves calling X(t)
# and V(t) more times.

fR := t->cols[signum(X(t)),signum(V(t))][1]:
fG := t->cols[signum(X(t)),signum(V(t))][2]:
fB := t->cols[signum(X(t)),signum(V(t))][3]:


# I use numpoints=200, to match the SpaceCurve use above.
# For the default (49) points the curve appears ragged.
# The timing for `tubeplot` grows faster than does that of
# `SpaceCurve`, as `numpoints` increases.
#
# Also, the colored curve below appears flat when viewed
# from certain angles, ie. not round.

CodeTools:-Usage(

  plots:-tubeplot([t, X(t), V(t)], t=0..4*Pi, radius=0.05,
                  color=[fR(t),fG(t),fB(t)],
                  style=surface, lightmodel=none,
                  numpoints=200, labels=["t","x(t)","v(t)"])

);

memory used=20.80MiB, alloc change=32.00MiB, cpu time=161.00ms, real time=162.00ms, gc time=0ns

 

Download spacecurve_shaded_2.mw

@janhardo It's not clear what you're trying to say, or ask, in your most recent Reply/Comment.

It seems to be some kind of duplication of your querying here.

@Kitonum One should not use evalc for simplification unless one is willing to restrict the solution to the condition that the unknown names are purely real.

For this example that first step can be accomplished without using evalc, and without imposing that restriction. Eg,

   evala(rationalize(w));

@janhardo A single apostrophe can be used in 2D Input mode as the prime-notation for entering an ordinary derivative.

That syntax for entering a derivative cannot be used in 1D plaintext (so-called Maple Notation) mode. I doubt that will change any time soon, if ever.

@dharr The behaviour described in your Answer changed for Maple 2017.

There is some description of that change on that version's compatibility page.

@janhardo 

That return value of the Typesetting:-Settings is the previous value (which was just changed). That behaviour has some programmatic advantages.

But is also means that you should not look at the output of that command to "see" whether it worked as you expected. Instead, if you want to check that it worked and that the setting is changed then I'd recommend calling it again, for example,

restart;

kernelopts(version);

`Maple 2021.1, X86 64 LINUX, May 19 2021, Build ID 1539851`

Typesetting:-Settings(typesetprime);

false

Typesetting:-Settings(typesetprime=true):

Typesetting:-Settings(typesetprime);

true

Download TSSusage.mw

@mvms271091 You may use an empty string "" for the second legend item, which will get suppressed. For example,

f := (3*t)/(1 + t^3):
g := (3*t^2)/(1 + t^3):
plot([[f,g,t=-40..-1.5],[f,g,t=-0.6..40]],
     style=point,symbol=cross,symbolsize=12,
     colour=coral,legend=[foo,""]);

You could do the same thing using, say,
  `[]`~(f,g,t=~[-40..-1.5,-0.6..40])
instead of,
  [[f,g,t=-40..-1.5],[f,g,t=-0.6..40]]

@Ivi Please don't post duplicate Question threads for this, though it might not yet be answered here to your satisfaction.

Here is an example of doing it with a procedure.

The scaling=constrained is needed so that the icon doesn't get distorted. An alternative that would estimate the plot assembly's final size (aspect ratio) -- and use that to adjust the icon -- could become tricky in general.

restart;

with(ImageTools):

img := Scale(Read(cat(currentdir(),"/smdrone.jpg")),1..75)[1..70]:

R := Rotate(img,':-right'):

M := Matrix(70,70,'datatype'=':-float[8]'):

 

Qf := (x0::realcons,y0::realcons,h::realcons) ->
  PLOT(GRID(evalf(x0-h/2)..evalf(x0+h/2),
            evalf(y0-h/2)..evalf(y0+h/2),
            M, COLOR(RGB,R)),STYLE(PATCHNOGRID)):

 

plots:-display(
  seq(Qf(a,sin(a)+0.2,0.3), a=[seq(i*Pi/4, i=1..7)]),

  plot(sin(x),x=0..2*Pi),

  scaling=constrained, size=[700,300],
  xtickmarks=[seq(i*Pi/4=i*Pi/4,i=0..4)]);

Download image_plot2.mw

Yet another alternative is to build a background image for the whole plot-window, with instances of the icon as carefully placed subimages. Then the aspect-ratio of the icon images could be handled based on any forced size option choice. This approach wouldn't allow the icons to be laid over a densityplot example, however.

@mmcdara In terms of (kernel, at least) efficiency an improvement would be a procedure.

It could accept, say an x,y pair as center point and width/length (or two opposite corner x,y positions). It could then construct that PLOT(GRID(...)..) structure directly. The only thing needing computation would be the two ranges that are the first two arguments of the GRID(...) substructure.

That would be more efficient than `plottools` commands `transform` or `translate`. It would also allow the two float[8] rtables to remain as such, which might even be kinder to the GUI.

@mvms271091 In my Answer I already gave,

DocumentTools:-Tabulate(widthmode = percentage, width = 75,
                                          [[seq([seq(p[3*(i - 1) + j], j = 1 .. 3)], i = 1 .. iquo(11, 3))],
                                           [seq(p[3*iquo(11, 3) + i], i = 1 .. irem(11, 3))]]):

where that latter part,
    [seq(p[3*iquo(11, 3) + i], i = 1 .. irem(11, 3))]
provides the 10th and 11th plots in a fourth row. It's harder to get that last row center-aligned without resorting to the building-blocks in which Tabulate is written (which is done in one manner in my Answer's second example).

Yes, your fresh attempt using,
   [seq([seq(p[i], i = (j-1)*iquo(11,3) + 1..j*iquo(11,3))], j = 1..iquo(11,3)+1)]
does not work because for the fourth row it refereces member p[12] which is not a plot. That is the whole point of the code fragment in my previous paragraph here.

Another terse way is something like,

DocumentTools:-Tabulate(widthmode = percentage, width = 75,
                        [[seq([seq(p[3*(i - 1) + j], j = 1 .. 3)], i = 1 .. 3)],
                         [p[10], "", p[11]]]):

where the middle cell now appears empty.

An alternative to the above is, say,

plots:-display(Array([seq([seq(p[3*(i-1)+j],j=1..3)],i=1..3),
                      [p[10], plot(axes = none), p[11]]]));

where the empty cell gets an empty plot.

Getting the last (fourth) row to be spaced exactly as you showed is trickier. That is why I also showed as a second example like this:

with(DocumentTools): with(DocumentTools:-Layout): with(DocumentTools:-Components):

InsertContent(Worksheet(Table(widthmode=pixels,width=600,alignment=center,interior=none,
                              seq(Row(seq(Cell(InlinePlot(p[3*(i-1)+j])),j=1..3)),i=1..iquo(11,3)),
                              Row(Cell(Table(exterior=none,interior= none,alignment=center,
                                             widthmode=pixels,width=400,
                                             Row(seq(Cell(InlinePlot(p[3*iquo(11, 3) + i]),padding = 0),
                                                     i=1..irem(11,3)))),padding=0,columnspan=3))))):

 

[edit] The general idea above is to use iquo and irem to construct first the 3 rows or 3, and then a row of the remaining items. Those are common techniques for splitting N objects into groups. Here's another way. If you are ok with using plots:-display, and don't need the botton row to have (center-aligned) fewer cells, then for a list p of N=11 plots you could also get it rendered in 3 columns as follows: question5_acc.mw

plots:-display(Matrix(ceil(11/3), 3,
                      (i, j) -> `if`(3*(i-1) + j > 11,
                                     plot(axes = none),
                                     p[3*(i - 1) + j])));
First 114 115 116 117 118 119 120 Last Page 116 of 591