The code I wrote over the summer can be roughly divided into two: splot, and the smaller, more modular code written after it.
Splot turned into an all-in-one programme for plotting pulse shapes and performing basic analysis on FCal data soon after been collected. It was useful for quickly displaying plots using gnuplot. Much of it was written in an ad hoc way, to analyse a particular problem. In this way it is rather restrictive as it is more a set of specific tools than a versatile analysis package.
Towards the middle of the test-beam run, splot was becoming frustratingly clunky and difficult to modify because it was a single programme performing many different tasks. It was at this stage that I began writing sets of C++ classes that could be used to write concise, customised programmes for analysing the testbeam data. These classes recycle much of the code from splot.
The runfile class unpacks data from the run files and can be accessed for the raw data. It is designed in such a way that a programme using it can access raw data without knowing anything about the actual data structure of the run files.
The plotdata and gnuplot classes are used to display plots in gnuplot. They can be used independently of any of the other classes I wrote. The g2wrapper class is used to draw graphics primitives in a window.
The process class is designed to sit on top of the runfile class and process the raw data. It subtracts pedestals and multiplies by the correct gain, and can provide information on the timing of a pulse.
There is also a file of utilities (utils) which provides functions and classes for useful, often repeated tasks, such as passing a parabola through three points, or filling a histogram.
Each of the classes included in this help file has an example file. Studied in order, they should provide instructive, and in themselves are useful tools.
Monitor is a programme that makes use of these classes to provide a quick, graphical look at which channels in which modules have been hit, as well as some information on the timing and gain-switching.
PPlot is a that can be used to plot pulses.
As splot is not fully functional any more, and since most of its
analysis can be quickly done using the later-written classes, it is probably
not of much interest to anybody. Monitor and PPlot are
useful stand-alone programmes. The set of classes outlined above are handy
for doing quick, simple analysis, and may be useful as a starting block for
more sophisticated studies.
All the files reside on pcfcal01 at CERN. They are all off of the main directory
/home/fcaltbmon/adam/ in logically named directories.
The files should make easily enough on other computers. They use the standard C++
libraries as well as some others which are listed in the appendix, all open
source/freeware and available online (or from pcfcal01).
Each directory has a Makefile which can be consulted to see what the necessary links
and libraries are.
Interaction with splot (Shape Plotter) is done with a tree of menus. Changes to
the menu are saved in a file (.splotsettings) so that values are remembered when the
programme is restarted.
The programme can plot pulses, either averaging events together, or displaying them one by a
time. This can now be done by a new pulse shape programme. These
functions are tasks A, B, and D in the Change Task menu.
It can also create histograms showing which channels are being hit. The more recent monitoring programme is better at this task. Histograms are plotted using task
C in the Change Task menu.
The channels and run files to plot are specified in the Data Source menu. Option D,
Number of Events, specifies how many events are to be averaged over at a time, when
grouped together. The channels are specified using a complicated syntax, explained if you
type help after selecting option G.
The Display Settings menu is used to specify how the plots look and is
self-explanatory. Other menus should also be self-explanatory.
The runfile class provides easy access to FCal run file data. It is an extension in
C++ of Petr Gorbunov's C libraries for reading run files. The details
of the reading and unpacking are managed by the class in the background so that users need know
nothing about the actual data structure. It can be used to read information from the run header,
to return a channel's ADC values and gain, the TTC delay values, etc. It is also very fast: a 200
MB run file can be read and unpacked in a few seconds.
See the example to get a better understanding of how it is used.
The plotdata class and the gnuplot
class are designed to work together. The plotdata class is a container for plot
information, fed to it in arrays of doubles. The plots can be grouped together, and given
titles in this class. The gnuplot class is essentially a wrapper for the gnuplot_i C library, which provides a C interface to gnuplot. The
gnuplot class is fed plotdata which it displays in a separate window. The user
has the ability to vary the style of the plots somewhat, and can output them to the screen, a
postscript file, or a printer.
The g2wrapper class is a wrapper for the g2 C graphic library, and provides functions for drawing graphic primitives
in a window.
This is a simple class. The user feds it arrays of doubles containing the x,
y, and error in y variables for a plot, which it stores. Pointers to various
elements of the plots can be requested, and plots can be subtracted from one another.
A plotdata object can be visualised in gnuplot using this class, while the programme is running. It makes
use of the C library gnuplot_i and makes it a bit quicker to use,
sacrificing flexibility for ease of use.
This class is a very simple C++ wrapper for the g2 C library. It is
used to draw graphic primitives to a window. I have added a more easy-to-use colour management
system. Another substantial addition by me is a function (drawtgif) which reads in a tgif image and draws it to the
window. This is useful in conjunction with tgif output from the gnuplot
class (see GP_TGIF) -- this is how the inset
plots in the monitor programme are created.
The idea of this class is to automate the most generic, basic analyses and processing of
runfiles. The class can currently perform three tasks:
Active channels (channels that receive substantial energies) are also identified, but currently
the user has no direct access to these data through this class. A class in the utils library can be used instead.
The class is designed in a way that it should be relatively easy to add new tasks, as should be
apparent from looking at the header file.
Run files are only analysed once for pedestals, TTC timing information and active channels. The
first time they are accessed they are analysed and the information is written to a file. The files
are stored in a directory structure, described below, and read each
subsequent time the run file is accessed. This makes processing of the data faster.
The algorithms for finding pedestals and determining timing are
described below.
The class does not read in the run files independantly. It requires a runfile object to work -- see the example to see
how it works.
Active channel information, pedestals, timing data, and intergain values are all stored in
separate directories off of a main directory. On pcfcal01, this is
/home/fcaltbmon/adam/rundata. The directories are specified using defined values
beginning with PROC_DIR_ — see process.h.
All files are ASCII text files. The first line gives the version number of the algorithm used
to generate it; it will be replaced if out of date next time its associated run file is accessed.
Files are given the run file name appended by "peds", e.g., run1555.dat has
pedestal file run1555.dat.peds. The file format is:
Files are given the run file name appended by "chans", e.g., run1555.dat has
active channels file run1555.dat.chans. The first three lines specify, in order:
There is one file, intergain.dat. The three lines are the factors the ADC values must
be multiplied to account for the gains, in the order low, medium and high. The high-gain data are
considered already normalised; the multiplicative value is 1. The medium-gain value (9.4)
was determined using calibration files. The low-gain value was not properly determined and in this
file is merely 9.42.
There is one file of constants, constants.dat. It contains four values, in order,
There are also files, associated with run files. They are named by appending the run file name
by "chans", e.g., run1555.dat has timing file run1555.dat.tim. values
listed are, in order (see algorithms below for terminology) :
Pedestals are calculated for each channel at each gain – 1024 x 3 in total. To
to so, the run file is read through at least three times, once for each gain.
For a given gain, the file is searched for pedestal events. (In-spill and out-of-spill events
are not distinguished.) If pedestal events for the given gain exist, the pedestal is calculated by
averaging together all the samples from these events. If they do not exist, the file is read
again, and this time the first sample from physics and/or calibration events are used instead to
find the pedestals. In both cases the RMS of each pedestal is calculated; this is the channel's
noise.
This process is repeated three times, once for each gain.
Pedestals vary significantly between channel to channel and gain to gain. However, by comparing
the pedestal for one channel at a specified gain calculated from run files spread over time, I
found that it does not vary significantly. For this reason, it is sufficient to use the pedestals
calculated from a single run file, usually a pedestal file, for any run. This can be done by
specifying a "master pedestal file", either in the constructor or
by calling usemasterpedfile. Calculating pedestals for
each run file is still useful to monitor the noises, which can be looked at in the output files.
I have written a separate paper on how the timing is calculated, Reconstructing the Trigger Delay from the TTC Values for FCal Physics Data.
This class fills a histogram, without the user needing to specify upper or lower limits before
hand. All it requires is a bin size, and then the user keeps sending it values using the add function. The values are automatically binned. The histogram can
be returned to the user using the get function, which writes array of
doubles to provided pointers.
The histogram storage is not optimal in terms of memory efficiency, but should cause no problems
for reasonable data.
This class examines a run file to see which channels are receiving significant energies. It
creates a list of these channels with some basic statistics on the channels' activities.
The user specifies a number of events in the constructor or with
setnumevents. The file is read until this number of
events has been looked at. For these events, any channels whose maximum samples exceed a threshold
energy (specified in the constructor or with setminamplitude are recorded. A running total of each of
these channel's energy and the number of times it was hit is also recorded.
The run file to read and the display options are specified on the command line, with the syntax:
The three optional flags are:
Some examples:
Two windows are opened when the programme is finished. One contains plots of the ADC spectra of
the medium and high gains. By "ADC spectrum" it is meant a histogram of the frequency that
channels reach the plotted ADC values. The energies shown on these plots are for individual
channels, and have not been summed at all. Only channels which are highlighted in the second
window contribute to these plots. These plots are meant to give an indication of how well the gain
switching is working.
The second window draws the three modules face on and highlights the channels that have been
hit. A beam centre is shown as a green target, and is the average position of the hit channels,
weighted by their relative energies.
The numbers in the legend at the top right of the screen are not very meaningful and should only
be used to give an indication of relative energies between the channels. (They represent a
channel's accumulated energy over events from the beginning of the run file.)
Each module has a small plot labelled "Timing". The x-axis is the sample number, and
the histogram records the frequency that a sample is the maximum for an event. Pulses are supposed
to peak at the fourth sample, so for well-timed runs, there should be a big peak at the fourth
sample.
The "Num. Hits" item in the three menus is the number of events that saw at least one channel
being hit. The "Avg. Peak Centre" item begins labeling samples at 0, so an average peak
centre of 3 means the fourth sample.
The file params.dat in the monitor directory can be modified to change the
monitor's settings. (A back-up of this file, default.params.dat is in the directory also
in case you make changes you don't know how to undo.) The options are:
PPlot is a programme for drawing pulses. It is probably buggy because it was the most recent
thing I created, and in a hurry. But it is useful for quickly looking at pulses.
PPlot requires a configuration file to run, which specifies the run files and channels to look
at, as well as settings for the output plots. There is a programme called pfile, described below,
which allows configuration files to be interactively created.
PFile is used to interactively create configuration files. It is run simply by entering
./pfile at the command prompt. All configuration files are placed in the directory
pconfig. Once created, they can be edited from here and should be simple to decode as
they are ASCII text-files. Beware, as pplot does not check thoroughly for valid input, so if, for
example, a file is missing a line, it will do strange things.
Below is example input into pfile, with comments preceded by "//".
Resulting configuration file:
The command line syntax is ./pplot <configfilename>. The pulse is plotted,
starting at the first event (FirstEvent in the configuration file), with a number of
adjacent events averaged together (NumEvents). Error-bars represent the RMS of this
average.
The plot is actually a weighted histogram. That is, each sample of each event is added to a bin
depending on its delay. After the NumEvents events have elapsed, each bin is divided by
the number of samples added to it, to get the average amplitude for that bin. The default bin-size
is 25 ns in pfile, which ends up plotting the samples without any
delay worked in. But if, for example, you want to see a more detailed pulse shape, a bin size of,
say, 1 ns can be specified, with a large NumEvents. The smallest possible bin size is
0.05 ns, which is the resolution of the timing.
After a plot has been displayed, it can be zoomed, printed or written to a postscript. The next
NumEvents events can then be displayed.
Adcgain
Noise
Pulse
Quickstudies
My runfile class, as well as splot, make use of C
libraries written by Petr Gorbunov for reading and unpacking run files.
Originals of these can be found (at the time of writing) on pcfcal01 in
/home/daq/Daq/src.
This is the freeware plotting programme used to create plots with my programmes. It is quite
basic, but easy to use. I was using version 3.7; I don't know if earlier versions will work. Its
website is http://www.gnuplot.info, with a good manual at http://www.ucc.ie/gnuplot/gnuplot.html.
This is a C library which calls gnuplot directly during run time. It was written by N.
Devillard and is freely available at
http://ndevilla.free.fr/gnuplot/. It is used by my gnuplot class.
N.B.: I added one function to this library called gnuplot_adamxy. The gnuplot class requires this function.
An GPL C library which can be used to create 2D graphics primitives. It is used by my g2wrapper class. It is well documented and can be downloaded from http://g2.sourceforge.net/. I used version 0.49a.
My gnuplot class uses this perl script by Tom Sato to concatinate
multiple plots into one file. This is necessary because gnuplot outputs files individually. The
script was found at http://member.nifty.ne.jp/tsato/tools/psjoin.html.
My sort and associatedsort
functions use the well-known quicksort algorithm. I modified slightly a version written by Matt
Whitlock, available at http://www.whitsoftdev.com/qsort/.
1.1 Files and Directories
2 Splot
2.1 Description
2.2 Practical Information
3 Runfile Class
3.1 Description
3.2   Public Functions
runfile()
runfile(char *filename)
runfile(char **filenames, int numfiles)
bool runfile::start(char *filename)
bool runfile::start(char **filenames, int numfiles)
void runfile::getheaderparam(char *key, char *str, int valnum, int maxlen)
int runfile::readnext()
int runfile::unpack()
int runfile::adc(int feb, int chan, int gai, int samp, bool ped)
int runfile::gain(int feb, int chan, int gai)
double runfile::intergain(int feb, int chan, int gai)
double runfile::intergain(int gai)
int runfile::numgains()
int runfile::numsamples()
int runfile::type()
int runfile::runtype()
int runfile::dac()
int runfile::caldelay()
int runfile::dirttc()
int runfile::delttc()
bool runfile::chanpulsed(int chan)
int runfile::eventnum()
double runfile::delay()
bool runfile::triggerbit(int bit)
bool runfile::flagbit(int flag)
bool *runfile::currfilename()
bool runfile::~runfile()
3.3   Defined Constants
3.4   Practical Information
3.4   Example
/*******************************************************************************
*------------------------------------------------------------------------------
* rundata_example.cpp
*------------------------------------------------------------------------------
*
* A basic example showing how to use the runfile class. In this example, the
* ADC values of one channel are printed out for every 2500th event.
*
* A make file is included in this directory.
*
* Adam Hincks
* 26 August 2003
*****************************************************************************/
#include <runfile.h>
#define STRING_LEN 16
int main(int argc, char *argv[]) {
runfile *rf;
/* We will look at three files. */
char *files[64] = {"/raid/data/phys/2100-2199/run2119.dat",
"/raid/data/phys/2100-2199/run2121.dat",
"/raid/data/phys/2100-2199/run2125.dat"};
const int numfiles = 3;
int i;
char momentum1[STRING_LEN], momentum2[STRING_LEN], particle[STRING_LEN];
/* Initialise the runfile object. */
rf = new runfile(files, numfiles);
/* Print out some information from the run header. */
rf->getheaderparam("BeamMomentum", momentum1, 0, STRING_LEN);
rf->getheaderparam("BeamMomentum", momentum2, 1, STRING_LEN);
rf->getheaderparam("BeamParticle", particle, 1, STRING_LEN);
printf("\n");
printf("This run was taken with %s %s %s.\n", momentum1, momentum2,
particle);
printf("Press enter to continue . . .\n");
getchar();
/* Loop until all the files have been read. */
while (rf->readnext() >= 0) {
/* Let's only look at every 2500 events, and only if it's a
* physics event. */
if (rf->type() == EVENT_PHYS && rf->eventnum() % 2500 == 0) {
rf->unpack(); /* Unpack the event. */
/* Print out the ADC data for FEB 7, channel 89. We will use a gain index
* of 0 since these are auto-gain runs. Also print out the gain of the
* channel. */
printf("\n");
printf("Event %d has gain %d.\n", rf->eventnum(), rf->gain(7, 89, 0));
printf("FEB 7, Channel 89 ADC values: \n");
for (i = 0; i < rf->numsamples(); i++)
printf(" %d -- %d\n", i, rf->adc(7, 89, 0, i, false));
}
}
/* That's it! */
return 1;
}
4 Plotting & Graphics Classes
4.1 Overview
4.2 Practical Information
4.3 Plotdata Class
4.3.1 Description
4.3.2 Public Functions
void plotdata::clear()
int plotdata::num()
int plotdata::numgroups()
double *plotdata::x(int n, int m)
double *plotdata::y(int n, int m)
double *plotdata::dy(int n, int m)
int plotdata::npoints(int n)
const char *plotdata::gettitle(int n)
void plotdata::add(double *xin, double *yin, double *dyin, int numin, int groupnum, char
*tit)
void plotdata::add(double *xin, double *yin, double *dyin, int numin, int groupnum, char
*tit, int febin, int gainin, int dacin, int chanin)
void plotdata::add(double *xin, double *yin, double *dyin, double stretch, int shift, int
numin, int groupnum, char *tit)
bool plotdata::loadfile(char *filename)
bool plotdata::hasdata()
void plotdata::subtract(double y, double dy)
void plotdata::subtract(double *y, double *dy, int n)
void plotdata::getchaninfo(int n, int *febout, int *gainout, int *dacout, int *chanout)
4.4 Gnuplot Class
4.4.1 Description
4.4.2 Public Functions
gnuplot::gnuplot()
void gnuplot::draw(plotdata *plot, double *topy, double *topx, double *boty, double *botx)
void gnuplot::draw(plotdata *plot)
gnuplot::close()
void gnuplot::setstyle(bool xn, bool yn, char *xl, char *yl, char ti, char ou, char ori,
bool er, char *pr, bool ma, char li, int lw)
void gnuplot::setpoints(char poi)
void gnuplot::setcolours(bool cols)
void gnuplot::setoutput(char ou)
bool setxrange(char *parsestr)
bool setyrange(char *parsestr)
4.4.3   Defined Constants
4.5   Plotting + Gnuplot Example
/*******************************************************************************
*------------------------------------------------------------------------------
* rundata_example.cpp
*------------------------------------------------------------------------------
*
* The pulses from 4 channels are plotted event by event. This example shows
* how a short programme can be written to rapidly visualise events -- without
* comments there are less than 50 lines of code.
*
* A make file is included in this directory.
*
* Adam Hincks
* 26 August 2003
*****************************************************************************/
#include <runfile.h>
#include <plotting.h>
int main(int argc, char *argv[]) {
int i, j;
double **x, **y, **dy;
char temptitle[80];
runfile *rf;
plotdata *p = new plotdata(); /* These objects can always be constructed */
gnuplot *gp = new gnuplot(); /* right away. */
/* We'll plot some pulse shapes from a run file. */
rf = new runfile("/raid/data/phys/1500-1599/run1555.dat");
/* Allocate the arrays for the data points. We'll make four plots.*/
x = new double*[4];
y = new double*[4];
dy = new double*[4];
for (i = 0; i < 4; i++) {
x[i] = new double[rf->numsamples()];
y[i] = new double[rf->numsamples()];
dy[i] = new double[rf->numsamples()];
}
while (rf->readnext() >= 1) {
/* Unpack only physics events. */
if (rf->type() == EVENT_PHYS) {
rf->unpack();
/* Fill up our arrays with the data points. We'll look at FEB 6, channels
* 22-25, using gain index 0 since this is an auto-gain run. */
for (i = 0; i < rf->numsamples(); i++) {
for (j = 0; j < 4; j++) {
x[j][i] = i * PERIOD;
y[j][i] = rf->adc(6, 22 + j, 0, i, false);
dy[j][i] = i * 10 + j; /* Assign a phony error in this example. */
}
}
/* Clear the plotdata object of any previous plots. */
p->clear();
/* Fill the plotdata objects with our four plots. */
for (i = 0; i < 4; i++) {
sprintf(temptitle, "FEB 6, Channel %d, Event %d", 22 + i,
rf->eventnum());
/* Let's group the plots in two. By using (int)(i / 2) for the group
* number, we place plots i = 0, 1 in one set of axes, and i = 2, 3 in
* another. */
p->add(x[i], y[i], dy[i], rf->numsamples(), (int)(i / 2), temptitle);
}
/* Now set the styles for gnuplot. See the documentation for details on
* this function. */
gp->setstyle(true, true, "Time (ns)", "Raw ADC", GP_TITINSIDE, GP_SCREEN,
GP_ROWS, true, "40-1D-COR", true, GP_HISTOGRAM, 1);
/* Set the range of the y-axis to something reasonable. */
gp->setyrange("500:2000");
/* Only look at the first few samples. */
gp->setxrange("0:250");
/* Distinguish overlayed plots with different colours. */
gp->setcolours(true);
/* Draw the graph. */
gp->draw(p);
/* Wait for user input before moving to next event. */
printf("Press enter to move to the next event, or ctrl-c to exit. ");
fflush(stdout);
getchar();
}
}
return 1;
}
4.6 G2Wrapper Class
4.6.1 Description
4.6.2 Public Functions
g2wrapper::g2wrapper(int xsize, int ysize, int xpos, int ypos, char *title, char *icon,
char *icondata, int icon_width, int icon_height)
g2wrapper::g2wrapper(int xsize, int ysize, int xpos, int ypos, char *title, char *icon,
char *icondata, int icon_width, int icon_height, char dest)
g2wrapper::g2wrapper()
void g2wrapper::openwind(int xsize, int ysize, int xpos, int ypos, char *title, char *icon,
char *icondata, int icon_width, int icon_height)
void openpsfile(enum g2_PS_paper pare, enum g2_PS_orientation ori)
bool g2wrapper::createcolour(char *name, double re, double gr, double bl)
bool g2wrapper::drawtgif(char *filename, double xpos, double ypos, double xstretch, double
ystretch)
void g2wrapper::rectangle(double x1, double y1, double x2, double y2, char *colour, bool
filled)
void g2wrapper::ellipse(double x, double y, double rx, double ry, char *colour, bool
filled)
void g2wrapper::polygon(int numvectors, double *coords, char *colour, bool filled)
void g2wrapper::void line(double x1, double y1, double x2, double y2, char *colour)
void g2wrapper::void text(char *txt, double x, double y, double size, char *colour)
g2wrapper::~g2wrapper
4.6.3   Defined Constants
4.6.4   Example
/*******************************************************************************
*------------------------------------------------------------------------------
* g2wrapper_example.cpp
*------------------------------------------------------------------------------
*
* Demo for the features in the g2wrapper class.
*
* A make file is included in this directory.
*
* A sample tgif file (sample.tgif) is included in this directory.
*
* Adam Hincks
* 28 August 2003
******************************************************************************/
#include <plotting.h>
#include <utils.h>
int main(int argc, char *argv[]) {
char tmpcolour[G2_COLOURLEN];
double poly[] = {100, 350, 110, 300, 200, 290, 210, 390, 150, 350};
const int polynum = 5;
int i, j;
g2wrapper *g;
g = new g2wrapper(400, 400, 0, 0, "Demo: g2wrapper", "", "", 0, 0);
/* These colours are specified in the tgif file. If we don't declare them, it
* will draw in black any unrecognised colour names. */
g->createcolour("black", 0, 0, 0);
g->createcolour("red", 1, 0, 0);
g->createcolour("green", 0, 1, 0);
g->createcolour("blue", 0, 0, 1);
g->createcolour("magenta", 1, 0, 1);
g->createcolour("cyan", 0, 1, 1);
g->createcolour("yellow", 1, 1, 0);
g->createcolour("DarkSeaGreen", 0, 0.5, 1);
g->createcolour("HotPink", 1, 0.5, 0);
g->createcolour("coral", 0.5, 1, 0);
/* Let's make a gradation of blue colours. */
for (i = 10; i > 0; i--) {
sprintf(tmpcolour, "blue%d", i);
g->createcolour(tmpcolour, 0, 0, (double)(i / 10.0));
}
/* Draw some simple shapes. */
g->ellipse(350, 200, 30, 120, "yellow", true);
g->line(0, 0, 200, 350, "cyan");
g->rectangle(20, 25, 200, 50, "red", false);
g->polygon(polynum, poly, "magenta", true);
/* Play with our blue gradation. */
for (i = 10; i > 0; i--) {
sprintf(tmpcolour, "blue%d", i);
for (j = 0; j < 3; j++)
g->line(230, i * 3 + j, 399, i * 3 + j, tmpcolour);
}
/* Draw a tgif image. */
if (!g->drawtgif("./sample.tgif", 50, 50, 0.4, 0.4))
printf("Someone must have removed the \"sample.tgif\" file from this "
"directory.\n");
/* Wait for user input to end. Graphics windows close automatically when
* programme terminates. */
printf("Press enter to end.\n");
getchar();
return 1;
}
5 Process Class
5.1 Overview
5.2 Directory Structure and File Formats
Pedestals
Active channels
Subsequent entries follow the format:
Intergain
Timing
5.3 Algorithms
5.3.1 Pedestals
5.3.2 Timing
5.3.3 Hit Channels
See the description of the hitchans class.
5.4 Public Functions
process::process()
process::process(bool pedson, bool igainson, bool timeingon)
process::process(bool pedson, char *masterpedfile, bool igainson, bool timeingon)
void process::pedson()
void process::pedsoff()
void process::usemasterpedfile(char *filename)
void process::useeachpedfile()
void process::intergainon()
void process::intergainoff()
void process::timingon()
void process::timingoff()
void process::init(runfile *runf)
double process::adc(int feb, int chan, int gai, int samplenum)
double process::delaytime()
5.5 Practical Information
5.6 Example
/*******************************************************************************
*------------------------------------------------------------------------------
* process_example.cpp
*------------------------------------------------------------------------------
*
* In this example, ten run files are read, and scanned for events where the
* maximum sample of FEB 6, Chan 23 is at least 1500 ADC counts. The pulses
* from all the events are overlayed on one another to create a coarse pulse
* shape.
*
* A make file is included.
*
* Adam Hincks
* 29 August 2003
******************************************************************************/
#include <runfile.h>
#include <process.h>
#include <plotting.h>
int main(int argc, char *argv[]) {
int i;
double delay;
double x[100000], y[100000];
double *samples;
int numpoints = 0;
char **files;
const int numfiles = 10;
runfile *rf;
process *pr;
plotdata *p = new plotdata();
gnuplot *gp = new gnuplot();
/* We will read in a sequence of ten run files, run1555.dat - run1564.dat.
* These are 32 sample physics runs. */
files = new char*[numfiles];
for (i = 0; i < numfiles; i++) {
files[i] = new char[64];
sprintf(files[i], "/raid/data/phys/1500-1599/run%d.dat", 1555 + i);
}
rf = new runfile(files, numfiles);
/* We enable pedestal subtraction, gain multiplication, and timing
* information. We specify a master pedestal file in the second argument. */
pr = new process(true, "/raid/data/pedestal/ped3400.dat", true, true);
samples = new double[rf->numsamples()];
/* Always remember to initialise the process object by telling it which run
* file is being used. */
pr->init(rf);
/* Read through the run files. */
while (rf->readnext() >= 0) {
/* If rf->type() returns 0, it means that a file has just been finished and
* the next one in the list opened. We need to initialise the process
* object again so that it knows a new file has been opened. */
if (!rf->type())
pr->init(rf);
else if (rf->type() == EVENT_PHYS) {
rf->unpack();
/* If we can't get a delay, discard the event. */
if ((delay = pr->delaytime()) == NO_TIMING)
continue;
/* Get the pulse information for this event. We look at FEB 6, channel
* 23, using a gain index of 0 since these are auto-gain runs. */
for (i = 0; i < rf->numsamples(); i++)
samples[i] = pr->adc(6, 23, 0, i);
/* Only consider events with a sizeable amplitude so that the pulse shape
* looks cleaner. */
if (samples[maxvalueindex(samples, i)] < 1500)
continue;
/* Record the points for this event. */
for (i = 0; i < rf->numsamples(); i++) {
/* Add the delay to the time axis. */
x[numpoints] = i * PERIOD + delay;
/* Use the process::adc function. It automatically subtracts the
* pedestals and mulitplies by the correct gain. */
y[numpoints++] = pr->adc(6, 23, 0, i);
}
}
}
/* Plot x and y. */
p->add(x, y, NULL, numpoints, 0, "");
gp->setstyle(true, true, "Time (ns)", "Amplitude (ADC)", GP_TITABOVE,
GP_SCREEN, GP_ROWS, false, "40-1D-COR", true, GP_DOTS, 1);
gp->draw(p);
printf("Press enter to end.\n");
getchar();
return 1;
}
6 Utility Classes and Functions
6.1 Miscellaneous Functions and Structures
struct channel
bool isnumber(char *str, bool neg, bool dec)
void sort(double *left, double *right)
void associatedsort(double *left, double *right, double **aleft, double **aright, int anum)
int maxvalueindex(double *list, int num)
void fitparabola(double *x, double *y, double *a, double *b, double *c)
double parabolaheight(double a, double b, double c)
double parabolacentre(double a, double b, double c)
bool lininterpolate(double x, double *y, double *dy, double *fx, double *fy, double *fdy,
int num)
int truncate(double value)
6.2 Histogram Class
6.2.1 Description
6.2.2 Public Functions
histogram::histogram()
histogram::histogram(double binsize)
void histogram::setbinsize(double binsize)
void histogram::clear()
double histogram::add(double value)
double histogram::add(double value, double weight)
double histogram::max()
double histogram::min()
int histogram::numbins()
double histogram::binsize()
void histogram::get(double **x, double **y, int *size)
void histogram::get(double **x, double **y, int *size, double min, double max)
6.3 Hitchans Class
6.3.1 Description
6.3.2 Public Functions
hitchans::hitchans()
hitchans::hitchans(double minamplitude, int numevents)
hitchans::hitchans(char *filename, double minamplitude, int numevents)
void hitchans::setminamplitude(double minamp)
void hitchans::setnumevents(int numevents)
hitchans::hitchans(char *filename, double minamplitude, int numevents)
channel hitchans::list(int index)
int hitchans::numhit()
channel hitchans::maxenergychan()
int hitchans::maxenergyindex()
double hitchans::totalenergy(int index)
double hitchans::avgenergy(int index)
int hitchans::numtimeshit(int index)
6.4 Practical Information
6.5 Example
/*******************************************************************************
*------------------------------------------------------------------------------
* utils_example.cpp
*------------------------------------------------------------------------------
*
* This example shows the hitchans and histogram class from the utils library,
* as well as some of its other functions.
*
* The hitchans class is used to identify the channels in one of the FEBS which
* have been hit with particles. A histogram is drawn showing the relative
* energies received by the hit channels.
*
* The run file is then read through and the amplitude of the hottest channel is
* studied. Another histogram is plotted showing the energy distribution for
* this channel.
*
* This example makes use of the runclass, plotdata, gnuplot and process
* classes. Example files for them are in this directory.
*
* A make file is included.
*
* Adam Hincks
* 29 August 2003
******************************************************************************/
#include <runfile.h>
#include <process.h>
#include <plotting.h>
#include <utils.h>
int main(int argc, char *argv[]) {
int i, j;
char runfilename[] = {"/raid/data/phys/1500-1599/run1555.dat"};
char tmpstr[80];
double *histox, *histoy;
double *samples, *times;
double a, b, c;
int histosize;
channel hotchan;
runfile *rf;
process *pr;
histogram *h;
hitchans *hc;
plotdata *p = new plotdata();
gnuplot *gp = new gnuplot();
/* Initialise the object, and search runfilename for the hit channels. */
hc = new hitchans(runfilename, 50, 250);
/* Prepare a histogram with a bin width of 1. */
h = new histogram(1);
/* Look through the hit channels in FEB 6. Fill a histogram with their total
* energies over the 250 events. */
for (i = 0; i < hc->numhit(); i++) {
if (hc->list(i).feb == 6)
h->add(hc->list(i).chan, hc->totalenergy(i));
}
/* Extract the histogram into the arrays histox[] and histoy[], filling them
* from 0 to 127. */
h->get(&histox, &histoy, &histosize, 0, 127);
/* Plot. */
p->add(histox, histoy, NULL, histosize, 0,
"Total Energy Received by Channels for FEB 6 (250 events)");
gp->setstyle(true, true, "Channel", "Total Energy (ADC)", GP_TITABOVE,
GP_SCREEN, GP_ROWS, false, "40-1D-COR", true, GP_HISTOGRAM, 1);
gp->setxrange("-1:128");
gp->draw(p);
printf("\nPress enter to continue. ");
fflush(stdout);
getchar();
/* Now let's look at the most active channel. */
hotchan = hc->maxenergychan();
/* This time we'll plot the ADC distribution for the hot channel. Clear the
* histogram and set the bin width to 50 ADC. */
h->clear();
h->setbinsize(50);
/* Prepare the runfile and process classes. */
pr = new process(true, true, true);
rf = new runfile(runfilename);
samples = new double[rf->numsamples()];
times = new double[rf->numsamples()];
pr->init(rf);
while (rf->readnext() >= 0) {
/* Look only at physics events. */
if (rf->type() == EVENT_PHYS) {
rf->unpack();
/* Get the samples and timing for this event for the hot channel. */
for (i = 0; i < rf->numsamples(); i++) {
samples[i] = pr->adc(hotchan.feb, hotchan.chan, hotchan.gain, i);
times[i] = i * PERIOD + pr->delaytime();
}
/* Require that the maximum sample for this event be at least 50 ADC
* counts, so that we safely eliminate non-hit events. */
j = maxvalueindex(samples, rf->numsamples());
if (samples[j] < 50)
continue;
/* Draw a parabola through the top three samples. The top sample is
* sample[j], so the top three points are (times[j - 1], samples[j - 1]),
* (times[j], sample[j]) and (times[j + 1], sample[j + 1]). */
fitparabola(times + j - 1, samples + j - 1, &a, &b, &c);
/* Add the amplitude determined from the peak of the parabola to the
* histogram. */
h->add(parabolaheight(a, b, c));
}
}
/* We must deallocate these pointers if we want to use them again. */
delete histox;
delete histoy;
h->get(&histox, &histoy, &histosize);
/* Clear p and plot the new histogram. */
p->clear();
p->add(histox, histoy, NULL, histosize, 0,
"Energy Distribution of Hottest Channel on FEB 6");
sprintf(tmpstr, "%f:%f", histox[0], histox[histosize - 1]);
gp->setxrange(tmpstr);
gp->setstyle(true, true, "Amplitude (ADC)", "Frequency", GP_TITABOVE,
GP_SCREEN, GP_ROWS, false, "40-1D-COR", true, GP_HISTOGRAM, 1);
gp->draw(p);
printf("\nPress enter to end. ");
fflush(stdout);
getchar();
return 1;
}
7 Monitoring Programme
7.1 Running the Monitor
7.2 What is Displayed
7.3 Changing Settings
8 Pulse Plotting Programme
8.1 Overview
8.2 Creating Configuration Files
+--------------------------------------------------------------------------+
| WELCOME TO PFILE |
| |
| PFile is used to create configuration files for pplot. Here, you |
| specify runs and channels for pplot to plot pulses from. You also edit |
| the styles and output that pplot uses. |
| |
+--------------------------------------------------------------------------+
Enter a file name for this configuration: test // No path should be entered
Enter the run file(s) (with full path) you want to use. To enter multiple
files, put each file name on a new line, ending each line with a comma
(','). The first line not terminated by a comma is the last file in the
list.
-> /raid/data/phys/1500-1599/run1555.dat, // A final comma means
-> /raid/data/phys/1500-1599/run1556.dat, // that there is another file
-> /raid/data/phys/1500-1599/run1557.dat // coming
// The run header of the first file is read and some information given to you
Reading /raid/data/phys/1500-1599/run1555.dat . . .
Physics run:
* 200 GeV/c e- at spot unknown (-1)
* 32 samples, gain 0 (autogain)
Enter the channel(s) in the format "FEB Chan Gain" (gain 0 = autogain).
Multiple channels can be entered the same was as run files.
-> 6 23 1
Gain 1 is not recorded in this run file. // Smart input.
-> g
Gain 1 is not recorded in this run file.
-> 6 23 0, // Again, a list entered using commas
-> 6 24 0
Look only at physics events for physics runs (y/n)? [Y] y
Use pedestals calculated from the run itself (y/n)? [N] n
Starting event number: [1] 299
Number of events to average together (enter 0 to use all events): [1] 10
Orient plots in <R>ows or <C>olumns? [R] // Entering nothing keeps the default
Put titles <I>nside or on <T>op of plots? [T]
Plot with <L>ines, <D>ots or <H>istograms? [L]
Enter a bin size for histogramming (ns): [25.00]
Discard events with ambiguous timing (y/n)? [Y] n
Show error bars on plots (y/n)? [Y] n
File successfully saved. To view plots with it, run ./pplot test
NumFiles 3
/raid/data/phys/1500-1599/run1555.dat
/raid/data/phys/1500-1599/run1556.dat
/raid/data/phys/1500-1599/run1557.dat
NumChannels 2
6 23 0
6 24 0
Dac -1
OnlyPhysEvents 1
FirstEvent 299
NumEvents 10
Orientation R
TitPosition T
PlotStyle L
HistoSize 25.000000
MasterPed 1
DiscardBadTiming 1
ShowErrBars 1
8.3 Running PPlot
9 Other Programmes
There are several small programmes I wrote to do on-the-spot analysis. They provided me with lots
of interesting information, but they are quite messy, with little commenting, and were not written
with the intention of being versitile tools. I outline them briefly. They are collected in a
directory called other.
Appendix: Software Credits
Petr Gorbunov's Libraries
Gnuplot
Gnuplot_i Library
G2 Library
PsJoin
Quicksort algorithm