Open GENIE Graphics Tutorial
In order to begin creating your own graphics, you must first open a graphics device. This is most commonly wanted to be displayed on screen, however in some circumstances it may be required to put the final drawing into a postscript file. For this reason a graphics device has 5 different types, they can be:
X windows
postscript
colour postcript
vertical postscript
colour vertical postscript
By default the device is set to the X Windows device (one which prints onto the screen). You can also define the width and height of the device, by default the width is set to 8.0 and the height is set to 8.0.
To open a device with the name, device1, you need to type:
device1=DEVICE:OPEN() - default device
device1=DEVICE:OPEN (type, width, height) - customised
device
A device automatically creates a picture, the next job is to create a window, a window can either be: Scaled, Unscaled, AutoScaled, TwoD and Multiplot.
The Autoscaled, Multiplot and TwoD windows are used mainly for plots, we will use these later on.
First of all we will try out the Unscaled Window. The parameters needed for this are, device co-ordinates and colour.
The device co-ordinates places the window on the points specified. The points of the graphical device range from 0.0 and 1.0
There are 15 different colours, to specify each colour, say you wanted to create a red window with the co-ordinates (0.1,0.9) (0.1,0.9), with the name window1, you type:
window1=WIN_UNSCALED(0.1, 0.9, 0.1, 0.9, $RED) - the default window co-ordinates are
0.1 0.9 0.1 0.9 with the colour black.
Now we have created a red window, now lets draw some axes, and give it a name, say axes1, we want the axes to be linear, and coloured white, so we need to type:
axes1=AXES:DRAW:XLINEAR:YLINEAR($WHITE)
or you could just type
axes1=AXES:DRAW()
As you can see, the Unscaled window ranges from 0.0 to 1.0, there is not much you can draw on a scaled window, (unless of course the points of a graph all range between 0.0 and 1.0), what you can do is draw a polygon, a polygon can be anything from a triangle to an object with 100 sides. Say we want to draw a triangle, triangle1, coloured green, we type:
x=dimensions(3) note: we need to define both an x and y
y=dimensions(3) array before creating a polygon
x[1]=0.0;x[2]=0.5;x[3]=1.0
y[1]=0.0;y[2]=1.0;y[3]=0.0
triangle1=POLYGON:DRAW:FILLED(x, y, $GREEN)
You could now write some text by the polygon, lets create a text object called text1, and let it contain the words "This is a triangle",
text1=TEXT/DRAW(0.0,0.0,"This is a triangle",0,1.5,45.0,$roman)
(The parameters are: respectively x co-ordinate, y co-ordinate, text, colour, font size, angle, font)
Now lets say you want to draw a plot, you cannot do this unless you want to scrap the picture you have created, in order to keep the picture, what we do is create another picture, called picture1,
picture1=PICTURE()
In order to plot a graph, or a histogram we can use either a Scaled Window or an AutoScaled window. We will use a Scaled Window to begin with, a problem with using a Scaled window is that you need to know the minimum and maximum values, to be able to give the world co-ordinates.
The plot example which I will use is 12k_a.cal, this can be found in the directory of /genie/examples/prisma, if you do not know which directory you are in simple type:
pwd
I will be making the assumption that I am in genie/src, if you are in the same directory then there will be no problem, however if you are in a different directory then you will need to modify the code slightly.
To be able to create a Scaled window you need the device co-ordinates (see above) and the global
co-ordinates - the global co-ordinates are the co-ordinates of the maximum and minimum points of the plot you are planning to plot - in this case the maximum and minimum points are: -5.0, 44.0, 0.0, 3.0 and the colour, this time we will use the default colour, lets call this window scaled1, you need to type:
scaled1=WIN_SCALED(0.1,0.9,0.1,0.4, -5.0, 44.0, 0.0, 3.0)
As mentioned above we will be plotting the data from 12k_a.cal, to do this we simply dissect the file to get the x y and e arrays, this is done by:
values=READ:ASCII:COLUMNS("../examples/data/si9394.in2","x,y,e")
x=values.x
y=values.y
e=values.e
Note: The world co-ordinates where found by typing the following:
max(x)
min(x)
max(y)
min(y)
Now we can create the graph:
plot1=GRAPH:DRAW(x,y)
To make this look a bit more professional, it might be an idea to create an axes, a title, and a set of x and y labels. This time lets call the axes axes2:
axes2=AXES:DRAW()
Now lets create a title called title1
title1=TITLE:DRAW("Sampling the Graphics Title")
Now lets create the labels, lets call them lables1:
labels1=LABELS:DRAW("X Label","Y Label")
As you can see there is a space on the graphics device, this is room enough for another plot, lets cheat a little, and use the same plot, but instead of drawing a histogram, lets draw error bars.
We need to create another Window, this time lets make an autoscaled window. For this window you do not need to know the minimum and maximum co-ordinates, instead you just pass the x y and e array, of the data you are planning to plot. Lets draw a line graph (plot2), using the data from the prs_001.obs file (found in the directory /genie/examples/prisma).
values=READ:ASCII:COLUMNS("../examples/prisma/prs_001.obs","x,y,e")
x=values.x
y=values.y
e=values.e
autoscaled=WIN_AUTOSCALED(0.1,0.9,0.6,0.9,x,y,e)
plot2=DRAW:PLOT(x,y)
Now lets compare this data with the data from the file prs__001_lmf.cor (found in the same directory), lets plot the data using markers.
values=READ:ASCII:COLUMNS("../examples/prisma/prs_001_lmf.cor","x,y,e")
x=values.x
y=values.y
e=values.e
markers1=DRAW:MARKERS(x,y,$cross)
Note: the predefined marker symbols are - $cross, $point, $star, $plus, $circle and $box
Now lets spruce it up!
graticule1=GRATICULE:DRAW() - oops the graticule is not numbered
graticule1=GRATICULE:ALTER:XNUM:YNUM()
title2=TITLE:DRAW("CsNiCrF \\d6\\u at 2k")
labels2=LABEL:DRAW("WaveVector, Q(\\A\\u-1\\d)", "Intensity")
Now lets create the error bars, using the values from plot2:
errors1=ERRORS:DRAW:VERTICAL(earray=e) note: you can also have
horizontal error bars.
You do not need to specify
the x&y arrays, once they
have already been declared
in a plot, histogram, errors
or markers.
Now say, you want to draw a multiplot, again there is no more space on the picture, so we need to create another one:
picture2=PICTURE()
Multiplot is awkward to use, first we need to create a multiplot, then create a multiplot window, then add the relavent spectra, then, and only then can we draw it on the screen !!
Lets use the data file si9394.in2 (/genie/examples/data).
SET/FILE "../examples/data/si9394.in2"
w=GET(1:17)
multiplot=MULTI_PLOT:CREATE(w.x,10,_,_,1.0,3)
multiwin=WIN_MULTIPLOT(0.1,0.9,0.1,0.9)
multiplot=MULTI_PLOT:SPECTRA(w.y)
multiplot=MULTI_PLOT:DRAW()
axes3=AXES:DRAW()
labels3=LABELS:DRAW("Time-of-flight (\\u\\s)","Neutron Counts (\\u\\s)")
title3=TITLE:DRAW("Si 640a 298k 2m.a=5")
A quicker way of drawing a multiplot is to put in the spectra numbers you wish to display (rather than passing in the y arrays one at a time. First we need to delete the current multiplot:
DELETE multiplot
array=dimensions(10)
fill array 0 1
multiplot=MUTI_PLOT:CREATE(w.x,10,_,_,1,0,3)
multiwin=WIN_MULTIPLOT(0.1,0.9,0.1,0.9)
multiplot=MULTI_PLOT:SPECTRA(array)
multiplot=MULTI_PLOT:DRAW()
axes3=AXES:DRAW()
labels3=LABELS:DRAW("Time-of-flight (\\u\\s)","Neutron Counts (\\u\\s)")
title3=TITLE:DRAW("Si 640a 298k 2m.a=5")
Now lets create some two dimensional plots. We are going to have to create another picture:
picture4=PICTURE()
Now we need to create a Two dimensional window (win_twoD), to do this we again need the x,y and e arrays:
aFile="../examples/data/mar03137.sqe"
data=FIELDS() - creating a workspace
DATA.FILE=aFile - putting contents of aFile into
- the workspace field file
MODULE/LOAD"../examples/librarymari.so" - loads the shared library mari.so
res=MODULE:EXECUTE("g_get_2d_file",data) - executes a routine in mari.so
unfix res.s 1000.0 - indicates the undefined values
to be 1000.0
twod=WIN_TWOD(0.1,0.9,0.1,0.9,res.x,res.y) - creating the two dimensional
window
contvals=dimensions(1) - defines the contour level
contvals[1]=13.0
contour1=CONTOUR_ARRAY:DRAW(res.s,contvals,_,res.x,res.y)
axes4=AXES:DRAW()
labels4=LABELS:DRAW("Momentum Transfer (\\A\\u-1\\d)","Energy Transfer")
title4=TITLE:DRAW("Sample Open Genie Plot")
Now lets create annotate a cell_array plot ontop of contour. First we need to create a colour table, you can either create one of your own or use one which is already loaded:
colour=READ:ASCII:COLUMNS("../examples/report/rainbow.dat","R,G,B")
table=COLOURTABLE:CREATE(colour.r,colour.g,colour.b,80,1.0,1.0)
this how you load in the file which contains the colours you have specified
table=COLOURTABLE:CREATE:RAINBOW(_,_,_,80,1.0,1.0)
cell=CELL_ARRAY:DRAW:SQRT:SMOOTH(res.s,table,res.x,res.y,valmax=30.0)
We can now add a cell wedge, for this you need to create another window, it can be either scaled or two dimensional, then you just need to specify which cell plot you want the wedge for:
unscaled2=WIN_UNSCALED(0.1,0.9,0.05,0.1)
wedge=CELL_WEDGE:VERTICAL(cell)
As it is you cannot see all of the pictures which you have created, one way to get around this is to use the redraw command, where, lets say, you wanted to see pic1, you would type:
REDRAW picture1
But what about the first picture you ever drew (the one with a triangle in it), is there any way of accessing items (an item can be a drawableObject [i.e axes], window, or a picture) which does not have a name. The answer is yes.
Basically you need to remember where about the item was created:
REDRAW pic(1)
This is all well and good, but what if you wanted to see two plots, which are on different pictures, at the same time. You can simply open another device, then redraw that picture into that device:
device2=DEVICE:OPEN()
REDRAW picture2
device3=DEVICE:OPEN()
device4=DEVICE:OPEN()
REDRAW picture3 device3
REDRAW picture4 device4
Is there any easy way of changing the DrawableObjects, once they have already been created? Yes.
Say you wanted to alter 9 objects:
These would be implemented by typing the following:
triangle1=POLYGON:ALTER(object=triangle1,colour=$cyan)
text1=TEXT:ALTER(object=text1,angle=90.0)
plot1=GRAPH:ALTER(object=plot1,colour=$green,line_type=$dot_dash)
title1=TITLE:ALTER(font=$script,object=title2)
errors1=ERRORS:ALTER:HORIZONTAL(object=errors1)
markers1=MARKERS:ALTER(symbol=$circle,colour=$blue,object=markers1)
contour1=CONTOUR_ARRAY:ALTER(line_type=$dash,object=contour1)
cell=CELL_ARRAY:ALTER:RAW(object=cell,valmax=0.0)
wedge=CELL_WEDGE:ALTER:HORIZONTAL(object=wedge)
If you wanted to undraw an item (it can be an object window or a picture), but did not want to delete it (yet), then you would use the undraw command. Say you wanted to undraw markers1 (and say, you forgot what you called it, but you knew when you drew it), you would type:
UNDRAW obj(2,2,1) - where obj takes the parameters picture, window, object
If you knew the name then you would simply type:
UNDRAW markers1
To get the item back you would simply redraw the picture. But if you decided that you did not want it then you could delete it, this is done by:
DELETE obj(2,2,1) or
DELETE markers1
There is also a method which allows you to copy items to wherever it is needed (as long as it is sensible, ie. You cannot copy a window into a window)
Say you wanted to copy autoscaled into a new device you would type:
device4=DEVICE:OPEN
picture=PICTURE() - optional
PIC_ADD autoscaled dest=picture -where dest stands for destination