List Archives > 
Maple User Group List Archive > 
Archive by date > 
This Month By Date > 
This Month By Topic
[MUG] Re: Iterative Plotting in Maple
| [MUG] Re: Iterative Plotting in Maple |
|
Author: J B W Webber
Posted: 02/01/2001 23:49:15 GMT
|
>> From: "J.B.W.Webber" "J.B.W.Webber"
This is an answer to the following question by Gaurav Suri :
Question : how can I open a plotting window from Maple,
so that I may incrementally calculate points
and add each new point to the graph as it is calculated ?
When this question was first asked, Robert Israel gave an answer that
it may be possible on a unix system to call an external grapher, and
use it to plot the points.
I then gave a brief answer (being very busy) that this sort of thing was
indeed possible in principle, that I do it from the array manipulation
language Apl.
Two things kept worrying me - one that Robert Israel used the word 'may' -
I regard him as an oracle when it comes to Maple - if he used 'may'
then perhaps I ought to check further. The other was that my reply,
while, correct, was nowhere near as helpful as it could have been.
................................
On Wed, 25 Oct 2000, Gaurav Suri wrote:
| I am using MAPLE to write code for an iterative algorithm. At the end
| of each iteration, I want to plot a point (the result of the iteration) to a
| separate window - so that I can see how the iteration is progressing.
| I have figured out how to use the plotsetup command to send plots to
| separate window, instead of inline. The problem is that at the end of every
| iteration, when I send the plot command, it opens up a new plot window.
| Is there some way to send subsequent plots to the same window?
Well, maybe there's a way to accomplish what you want, but it will require
resources outside Maple. It's most likely to be feasible on a Unix
system. What you'd want to do is set up a pipe from Maple to some other
process that can do incremental plotting, reading in points from the pipe
as they become available and plotting them.
Robert Israel
................................
Why me (beau webber) :
I first added a multiprocessing construct 'pipe' to Apl in the early 80s
and published it (it is now incorporated into IBM's Apl2), and
recently added this and another construct 'spawn' to an Apl to C compiler.
The above question has forced me to look at what multiprocessing
facilities are currently available in the main high-level languages out there,
such as Maple, Matlab, Apl, and in the programs that they might
wish to interact with.
I am building a detailed argument as to what facilities I believe should
be available in such high-level languages, and the subsiduary graphical
front-end tools (like Tcl/Tk, xterm) and back end display tools like
gnuplot, ghostview, xv, xterm.
However this will take a while to prepare, and I would like to discuss
points with the main developers in Maple, Matlab, gnuplot, xv ....
(so if you are such a person, please contact me ....)
and then subject it to peer review and publish it, before releasing it
to the web in general.
What I will present here, however, is a robust method to do the
plotting described above, from within Maple.
I currently believe that three high-level constructs are needed in
a high-level language such as Maple, for flexible multi-processing :
I call these : 'system', 'pipe', 'spawn', together with a complete set of
capabilities on the standard file handling utilities, access to the
system Julian time, and a sleep that accesses micro/nanosleep.
At present V6 Maple appears to have 'system', and something called
'ssystem', which acts like one half of what I call 'pipe' (which in a Maple
context might need to be re-named as perhaps 'shellpipe').
In addition it has primitive pipe, dup, etc. - one could use these
to implement a complete high-level pipe and spawn as Maple procedures,
but I believe it would be far quicker to just re-use the C code I have
put into Apl2c - I certainly do not have the time to re-write it in Maple.
Answering the original question :
Although more advanced multiprocess facilities make things neater and
simpler, it is indeed possible from existing versions of Maple to do
incremental plotting to an external graph window,
using only 'system', file reading and writing, and 'sleep'.
We use files for communicating with the external program.
The residual problems of this approach are :
1) that on older systems, shutting all the processes down afterwards
can become messy,
2) if things die you are left with unwanted files, and
3) 'sleep' only waits integer seconds, when milliseconds are usually
a quite sufficient delay, slowing things down. unnecessarily
I give four examples of graphing, first repeatedly drawing graphs with
new data, usig xv as the display - this is the simplest case as xv
can be sent a signal to re-display its data file, after we have changed it.
In the second case we use gnuplot, but have to set up a mechanism to
feed the data and commands to it as they are changed - actually harder is
to ensure that everything is tidied away when we are finished.
The third and fourth case similarly use xv and gnuplot, but now we are
actually incrementally calculating our data points and re-plotting each
time into the same window, as was requested.
........................................................
# To start with: a simple example of using 'system' to repeatedly plot
# to a graph window external to Maple; we will use Maple's own plot,
# to produce a jpeg file which we will view using xv.
# set everything up, plot first graph:
> plotsetup(jpeg,plotoutput=`plot.jpg`);
Warning, plotoutput file set to plot.jpg
> PlotData := cos(0*x) + sin(x):
> plot(PlotData,x=0..2*Pi,Y=-2..2);
> system( "xv plot.jpg & echo $! > procNo" );
0
> ProcNo := readdata ( procNo, string );
ProcNo := ["25961"]
> KillCmd := cat ("kill ", ProcNo[1]);
KillCmd := "kill 25961"
> UpdateCmd := cat ("kill -QUIT ", ProcNo[1]);
UpdateCmd := "kill -QUIT 25961"
# go into loop plotting successive graphs :
> for N from 1 to 10 do
> PlotData := cos(N*x) + sin(x):
> plot(PlotData,x=0..2*Pi,Y=-2..2):
> system( UpdateCmd ):
> end do ; # things do not seem to work with a : here
PlotData := cos(x) + sin(x)
0
PlotData := cos(2 x) + sin(x)
.....
PlotData := cos(10 x) + sin(x)
0
# to kill the display window when we are done with it :
> system( KillCmd):
Note:
the above example uses a jpeg file which is lossy - much better is to
use a postscript file, as this is lossless, and for line drawing usually
much smaller - and compressed ps even much smaller. It also has the
advantage that you then have a file that may be directly printed
to a postscript printer, or to any printer using ghostscript.
I have not put in the above code as on some Suns xv does not support
postscript.
Thus if your xv does, I suggest for plotsetup :
plotsetup(cps,plotoutput=`plot.ps`,plotoptions=`colour=rgb,portrait`);
........................................................
# Now an example of using 'system' to repeatedly plot
# to a graph window external to Maple; we will write data files
# and use gnuplot to do the plotting. This is more complicated, as
# using only 'system' we can not connect a pipe to gnuplot's
# standard in, but must write data and command files, and
# ensure gnuplot keeps reading them.
# set everything up, plot first graph:
> Nx := 100;
Nx := 100
> Rx := 2*Pi;
Rx := 2 Pi
> N := 0;
N := 0
> PlotData := convert([[Rx*x/Nx, sin(N*Rx*x/Nx)+cos(Rx*x/Nx)] $x=0..Nx],
float):
> writedata('plotdata',PlotData,float);
> close('plotdata');
> PlotCmd := ["plot [0:2*pi] [-2:2] 'plotdata' w l"];
PlotCmd := ["plot [0:2*pi] [-2:2] 'plotdata' w l"]
> writedata( 'plotcmd', PlotCmd, string );
> close( 'plotcmd' );
> ShellCmd := " ( tail -f plotcmd --pid=$! | gnuplot ) & echo $! > procNo " ;
> system (ShellCmd);
> ProcNo := readdata ( procNo, string );
ProcNo := ["12816"]
> KillCmd := cat ("kill ", ProcNo[1]);
KillCmd := "kill 12816"
# repeatedly plot new graphs in same window :
> for N from 1 to 10 do
> PlotData := convert([[Rx*x/Nx, sin(N*Rx*x/Nx)+cos(Rx*x/Nx)] $x=0..Nx],
float):
> writedata('plotdata',PlotData,float):
> close('plotdata'):
> writedata[APPEND]( 'plotcmd', PlotCmd, string ):
> close( 'plotcmd' ):
> system( "sleep 1" ):
> end do:
# to close the plot window when done, and kill the tail command pipeline :
> PlotCmd := ["quit"]:
> writedata[APPEND]( 'plotcmd', PlotCmd, string ):
> close( 'plotcmd' ):
> system( KillCmd):
........................................................
# Now an example of using 'system' to incrementally plot new points
# to a graph window external to Maple. We will use Maple's own plot,
# to produce a jpeg file which we will view using xv.
# set everything up, plot first graph:
> Sx := 20;
Sx := 20
> Nx := 10;
Nx := 10
> Rx := Pi;
Rx := Pi
> N := 3;
N := 3
> PlotData := convert([[Rx*x/Sx, sin(N*Rx*x/Sx)+cos(Rx*x/Sx)] $x=0..Nx],
float):
> plotsetup(jpeg,plotoutput=`plot.jpg`);
Warning, plotoutput file set to plot.jpg
> plot(PlotData,x=0..Pi,Y=-2..2);
> system( "xv plot.jpg & echo $! > procNo" );
0
> ProcNo := readdata ( procNo, string );
ProcNo := ["26444"]
> KillCmd := cat ("kill ", ProcNo[1]);
KillCmd := "kill 26444"
> UpdateCmd := cat ("kill -QUIT ", ProcNo[1]);
UpdateCmd := "kill -QUIT 26444"
# plot more points as they are calculated :
> for Nx from 11 to 20 do
> PlotData := convert([[Rx*x/Sx, sin(N*Rx*x/Sx)+cos(Rx*x/Sx)] $x=0..Nx],
float):
> plot(PlotData,x=0..Pi,Y=-2..2):
> system( UpdateCmd ):
> end do;
PlotData := [[0., 1.], [.1570796327, 1.441678840],
[.3141592654, 1.760073511], [.4712388981, 1.878694865],
[.6283185308, 1.760073511], [.7853981635, 1.414213562],
[.9424777962, .8968022466], [1.099557429, .2975560344],
[1.256637062, -.2787682586], [1.413716694, -.7345720591],
[1.570796327, -1.], [1.727875960, -1.047440990]]
..................
# to close the display window :
> system( KillCmd):
........................................................
# Now an example of using 'system' to incrementally plot new points
# to a graph window external to Maple; we will write data files
# and use gnuplot to do the plotting. This is more complicated, as
# using only 'system' we can not connect a pipe to gnoplot's
# standard in, but must write data and command files, and
# ensure gnuplot keeps reading them.
# set everything up, plot first graph:
> Nx := 10 ;
Nx := 10
> Sx := 100;
Sx := 100
> Rx := 2*Pi;
Rx := 2 Pi
> N := 3;
N := 3
> PlotData := convert([[Rx*x/Sx, sin(N*Rx*x/Sx)+cos(Rx*x/Sx)] $x=0..Nx],
float):
> writedata('plotdata',PlotData,float);
> close('plotdata');
> PlotCmd := ["plot [0:2*pi] [-2:2] 'plotdata' w l"];
PlotCmd := ["plot [0:2*pi] [-2:2] 'plotdata' w l"]
> writedata( 'plotcmd', PlotCmd, string );
> close( 'plotcmd' );
> ShellCmd := " ( tail -f plotcmd --pid=$! | gnuplot ) & echo $! > procNo " :
> system (ShellCmd);
0
> ProcNo := readdata ( procNo, string );
ProcNo := ["22622"]
> KillCmd := cat ("kill ", ProcNo[1]);
KillCmd := "kill 22622"
# plot more points as they are calculated :
> for Nx from 11 to 100 do
> PlotData := convert([[Rx*x/Sx, sin(N*Rx*x/Sx)+cos(Rx*x/Sx)] $x=0..Nx],
float):
> writedata('plotdata',PlotData,float):
> close('plotdata'):
> writedata[APPEND]( 'plotcmd', PlotCmd, string ):
> close( 'plotcmd' ):
> system( "sleep 1" ):
> end do:
# to close the plot window when done, and kill the tail command pipeline :
> PlotCmd := ["quit"]:
> writedata[APPEND]( 'plotcmd', PlotCmd, string ):
> close( 'plotcmd' ):
> system( KillCmd):
........................................................
All the above would also usually need code in the close-down/tidy-up
section, to remove the data and command files - however for demonstration
purposes it is often useful to view them, so this is left as an excercise
for the student :-)
Hope that the above helps, if you want more help with multiprocessing,
ask and I may be able to help.
cheers,
beau webber "J.B.W.Webber"
|
Previous by date: [MUG] Varimax in maple, CT
Next by date: [MUG] Series for Bessel functions, Ilya Ponomarev
Previous thread: [MUG] Indexed Variables: What is a valid index?, Nathan Sokalski
Next thread: [MUG] Series for Bessel functions, Ilya Ponomarev
|