Before describing extensively the VEGA
classes, methods and objects, it would be interesting to put directly hands on
the environment and see some of it's capabilities from the point of view of
gravitational waves data analysis. Concepts will be introduced as
needed.
III.1 Preparation
So, let's imagine someone has a set of frame
files that he/she wants to analyze. We will first build some tutorial files.
Copy to your home directory the "vegatutorial" directory that is in the VEGA
package. Then cd to this directory and launch a VEGA session. Then, in this
session, execute the create_testfr.C script :
vega[]
.x create_testfr.C
This will create files containing a few test
frames, starting at time (GPS) 400000000.097, till the time 400001475.097. You
will see some plots of the contents of these frames at the same time. Then, a
file named SMSdemo.F containing frames with only slow monitoring test data will
be produced.
III.2 Opening
a Frame Channel
Now that we have a few frame files, we will
need to access quickly a subset of them, if possible without bothering with
frame boundaries, just giving the start time and length of the piece we want. In
VEGA, the central notion to do such things is the "Frame Channel". Usually, the
information about the data, called metadata (location, duration, triggers,
etc...) is in one place and data itself is in another place. A frame channel
will link the two, searching for information about data where it is and using it
to access data. It will act as a data provider.
The metadata may take many forms. It may be
a metadatabase, that will be described elsewhere, it may be a bookkeeping
database, or it may be the frame files themselves that contain enough
information to be used by a frame channel. We will start by using the simplest
form, which is the direct use of the files.
Let's open such a frame channel with the
demo frame files :
vega[] fc
= new VFrameChannel("file:demo400000000.F
demo400000045.F")
The operator new, described elsewhere, is
creating an object of the class VFrameChannel, returning a pointer
fc.
The argument of the constructor (the function attached to the class that builds
the objects of this class) are the names of the frame files that will be used
(in our case " demo400000000.F and demo400000045.F "). The characters "file:"
are used to tell the frame channel which type of meta information it should use,
in this case simple files.
NOTE : Since it's annoying to always type
long names, one can use the tab completion feature of ROOT, using the
<Tab> key. Here <Tab> represents the Tab key on the keyboard, NOT
the letters "<.T.a.b.>.":
vega[]
w = new VFrameC<Tab>
and the name is completed automatically.
This is also true for names of files in the current directory. Even more, if you
write :
vega[]
w = new VFrameChannel(<tab>
You will have the list of variables used by
this method, with the default parameters, and all the possible versions. This is
VERY helpful.
One last word. Using a frame channel
connected directly to files should be done only if frames are sequentially
ordered in the files and not mixed inside several files. If the case is more
complex, one should build a metadatabase and connect the frame channel to it.
This is described later on.
III.3 Extracting
a frame using a frame channel and plotting it
Now, as advertised, you can extract a frame
from the set of files with :
vega[]
fr = w->GetFrame(400000023)
To see the contents of the frame, one can do
the standard Framelib call :
vega[]
FrameDump(fr,stdout,2)
Which gives a summary of the contents of the
frame. One can see that there is an ADC channel named MYGO_ADC1. But you can
have the same kind of information from the framechannel itself by
issuing
vega[]
w->Print()
This will print all kinds of information
about the framechannel and dump the contents of the first
frame.
To draw the previously extracted frame in
the current pad, just do :
vega[]
gVM->Draw(fr,"adc.MYGO_ADC1")
Woaw ! what is this new beast, "gVM"
?
Well, if we wanted to be consistent with the
"Object Oriented" way used in ROOT, we would have needed to use a fully C++
version of the Framelib. But this would have meant a complete change of the
habits of many people. Since people are used to the C version, and since at the
moment, the C++ version is not quite ready, we preferred to use a "manager
class" that is taking the Framelib objects and building graphical objects with
them. This class is called VManagerFrameL.
At initialization time, a global variable of
type VManagerFrameL is build, called gVM and it is available for all kinds of
management tasks, taking care of drawn plots, freeing memory when necessary,
taking care of a reference time, etc...
So, the last command we did created a plot
(graphical representation, class VSPlot) of the frame
fr
content, more specifically of the adc channel named "MYGO_ADC1". The "adc"
characters may be omitted if there is only one vector (adc proc or sim) with
that name.
Even if it is supposed to be only a
graphical representation of a vector, a VSPlot is much more than that. In fact,
it contains almost all the information contained in a time series (FrVect for
example). It can be the starting object for a truly "OO" way of doing time
series.
For the moment, let's access the VSPlot
object that was created :
vega[]
vsp = gVM->GetLastPlot()
It was said that the VManager called gVM
takes care of all the drawn plots. This instructs gVM to return us a pointer to
the last drawn plot.
Now we can do things like
vega[]
vsp->SetLineColor(4)
You can always use <Tab> to see the
available methods. Furthermore, one can click on the drawn line or plot with the
third mouse button, have a popup menu and select methods like we did for
histograms. The interactive zoom is also available.
It is also possible to plot images coming
from cameras that are included in a frame as FrVects in 2 dimensions. One uses
the same syntax as for 1D, the manager gVM will take care of producing the right
plot.
The tutorials contain a few examples of the
use of gVM (see the macros scroll2.C and peak2.C for example).
III.4 Extracting
a vector using a frame channel and plotting it
What if you don't want to take care of
frame boundaries, just want to see a vector containing MYGO_ADC1 data, beginning
at the time 400000023 and lasting 10 seconds ?
The frame channel can do that. Do
:
vega[]
ve = w->GetVect("MYGO_ADC1",400000023,10)
vega[]
gVM->Draw(ve)
The first line extracts the vector, the
second draws it. Notice that you didn't care about the frame boundaries, one of
which is around 400000024.5, the other around 400000030.
Of course, one can extract a vector as big
(or as small) as he wants, limited by the available machine memory of
course.
One note : the user should take care of
freeing the memory for all Framelib objects that are returned. Once a FrVect or
a FrameH is extracted, it is the user's responsibility to free memory in his
loops with FrameFree(fr) and FrVectFree(ve). In a future version, we will try to
do an automatic garbage collection, to free (!) the user from these tasks. For
the moment, this is not so important since the amount of created vectors/frames
is not big.
III.5 Extracting
a 2D vector (image...) from the frame channel and plotting it
The vectors
inside a frame may be two dimensional and may represent an image coming from a
camera. 2D vectors are plotted the same way as 1D vectors. For example, assuming
ve2 is a 2D vector (of type FrVect):
vega[]
gVM->Draw(ve2)
will draw it.
Let’s see a concrete example, using
the files contained or generated in the vegatutorial directory. First, open a
frame channel
vega[] fc
= new VFrameChannel("file:demo400000000.F
demo400000045.F")
second, extract the first frame using this
frame channel
vega[]
fr = fc->GetNextFrame()
third, since the name of the vector
containing the image is "MYGO_IMAGE", plot it
vega[]
gVM->Draw(fr,"MYGO_IMAGE","col")
That's it ! The option "col" used for this
drawing produces a color plot. Other options are shown in the chapter
“Representing gravitational waves data”
A few tutorials explain how to do it more
generally: “moveimage.C”, “tifrdisplay.C” for
example.
III.6 Building
a metadatabase for more complex tasks
In case one uses files containing frames
that are not sequentially ordered or wants to use a selection or condition
mechanism for the frames, the frame channel does not get enough information with
a direct file access as described above. There is a necessity to build a
metadatabase that will contain information about file location, triggers,
quality words, etc... and that will be used by the frame channel as an index to
access data. The details will be explained later but we can already build such a
metadatabase for the tutorial files that we generated:
vega[] vd
= new VFrameMetaDB("demoDB.root","CREATE","demo*")
The first argument of the constructor for a
metadatabase is the name of the ROOT file that will contain metadata, in our
case "demoDB.root", next the mode of opening ("READ" by default, but we used
"CREATE" to build a new database). The third argument is the path to the files.
As can be seen, one can use wildcards to specify frame files names. But one
could as well specify a directory name. The search is by default recursive,
which means you can set the beginning of the search to the top of a directory
tree containing directories, etc....
Now, we can try to connect a frame channel
to an existing database :
vega[]
w = new VFrameChannel("demoDB.root")
The instructions to extract a frame or
vector are the same as in the direct file access case. The only difference is
that one is assured not to have any problems in case frames are mixed in various
files or one wants to use a selected (triggered) set of frames.
III.7 Extracting
a frame with a condition or selection
Frames are generally build with a certain
set of conditions or selection parameters, coming from the online triggers or
decided by the user. A user may want to process only a subset of the frames,
corresponding to some conditions, say amplitude of the trigger
“Trig1” higher than a certain value.
When building a metadatabase, the trigger
information is read from the frame and saved. This allows for a frame channel,
when using a metadatabase, to quickly browse it searching for frames that obey a
given set of conditions.
Let’s illustrate the use of this
feature with our tutorial test files. We will suppose that
w
is the frame channel opened in the previous paragraph. The frames contained in
the tutorial files were generated with two trigger structures Trig1 and Trig2,
which have various amplitudes for the various frames.
First, we may try to see the value of a
given trigger amplitude by plotting it. The database object w has the capability
to draw it:
vega[]
w->DrawCondition("Trig1.amp","Trig1")
This will plot the amplitude of the trigger
Trig1 provided it is defined. The second string "Trig1" is a selection
expression, so one can plot only the amplitude of selected triggers if
necessary.
The second step is to define the selection
expression, with a set of conditions, which will govern the search for specific
frames. This is done by defining a new object, called a condition set (class
VConditionSet), that will contain the selection expression and serve as a
pointer to a specified position in the metadatabase. Each type of metadatabase
needs it's own type of condition sets. So we have to ask it, through the frame
channel, to create a suitable condition set:
The selection expression may use standard C
operators and the main C math functions. "sin(Trig1.amp)>0.23 ||
Trig2==0" is a valid expression.
Now, one calls repeatedly the
GetNextFrame(cs)
method of
VFrDataBase
to get all the frames corresponding to the selection. To illustrate this,
let’s load the next selected frame and see it’s beginning time
:
vega[]
fr = w->GetNextFrame(cs)
vega[]
fr->GTimeS
(unsigned
int)400000120
Do not forget that fr is a FrameH structure
and as such, we can use its internal variables, such as GTimeS, the start
time.
You see that the start time is obviously far
from the start time of the first frame (400000001). All the frames in between
were skipped since they did not obey the selection expression.
If you use repeatedly GetNextFrame, do not
forget to delete the object fr after it’s use
(with
FrameFree(fr)), otherwise your memory
will get filled by all the undeleted frames that were passed to
you.
III.8 How
to deal with slow monitoring data ?
Slow monitoring data spans a lot of frames.
Thus, it requires a special treatment. To illustrate this, let’s build a
database with frame files containing only SMS data. One such file was build by
the create_testfr macro. Its name is SMSdemo.F. Check that you have such a file.
Then, open a frame channel with for example:
vega[] v
= new VFrameChannel("file:SMSdemoDB.root")
If you want to see the contents of the
frames, do as before :
vega[]
v->Print()
You will see that there is a slow monitoring
station called MYGOSMS that contains two variables VF1 and VI2.
The special treatment we have to apply in
order to gain a simple yet efficient way of dealing with SMS data is to build a
special object called an ntuple that will contain all this data. We developed a
particular ntuple that differs from the standard ROOT one in that it is adapted
to our needs. You can think of a ntuple as a list of all the sms data put in a
tree-like structure :
The difference with a simple array is that
each leaf of the tree can be any kind of object, even a tree itself. This leads
to a hierarchy structure, like in a directory structure for a file
system.
In fact, these more general ntuples are
called trees and we will not yet work with them. In simple ntuples, each leaf is
a single float parameter.
So to build a ntuple starting from the slow
monitoring data, one can do :
vega[]
nt =
v->ExtractSMS("nt","MYGOSMS.VF1:MYGOSMS.VI2", 400000000,5000)
The first parameter
"nt"
is the name of the ntuple. Then,
"MYGOSMS.VF1:MYGOSMS.VF2"
is the list of SMS variables one wants to extract. Instead of telling every
variable, you can specify only the name of a slow monitoring station, MYGOSMS in
our case. The last two parameters are the start time from which we want the
extraction and the length, expressed in seconds.
This ntuple will have three variables, the
time being the first variable automatically inserted during extraction. If you
want to see the contents of the ntuple, do :
vega[]
nt->Print()
Now that we have a ntuple, one can easily
plot all sort of things. For example, if you want to plot the variations of VF1
with time :
vega[]
nt->DrawGraph("t:MYGOSMS.VF1","","at")
The second, empty parameter is a selection
parameter. One can overlay a second plot :
vega[]
nt->DrawGraph("t:MYGOSMS.VI2","","l")
One can also use some complicated
expressions, for example