Basic data ingestion and processing
Basic data ingestion and processing
The end of the last lesson saw you progress to writing a monitor that wrote “success” each time it ingested a couple of seconds worth of frame data. Today we will make some rudimentary changes to allow you to ingest and process the data in a simple way. The two files you will need to change are exmon.cc and exmon.hh . I will use a very basic style of C++ in this first example - even if this means the code being slower than it might be, and even if it means not being graceful. My strategy will be to declare a new private data variable in exmon.hh: bool mDataArrayAssigned. This variable is initialized to false when the constructor for the exmon class is invoked. This is done at the top of the constructor exmon::exmon, by inserting
:mDataArrayAssigned(false)
after the parentheses at the top of the function definition. Also in exmon.hh, a second private variable double* mpdata is declared. This is a C-style pointer to a double. The idea is to use dynamic memory allocation the first time data is read from a frame to allocate enough memory to hold all the data ingested per call to ProcessData() as doubles. This means copying all the data which slows down the process, but the copying process also casts all the data into doubles, which makes the code robust against other data types (floats or shorts) that are common products of the LIGO data acquisition system.
The process data function will then first determine how many data elements it has read (this is needed for every new data segment ingested), then it will do a test to see if mDataArrayAssigned is false. If it is false, then a second new private data variable in exmon.hh: double* mpdata, is assigned to an address on the stack big enough to hold the data, using mpdata = new double [ndata_per_frame]. The variable mDataArrayAssigned is set to true in the loop, so memory is only allocated on the first call to ProcessData - the same address is re-used on subsequent calls. This array is deallocated upon a call to
the destructor exmon::~exmon(), but only if mDataArrayAssigned is true, because it may be that the program exits before ProcessData is called, in which case we would not wish to deallocate a pointer that had not yet been allocated.
Finally, the member function GetData of the timeseries object *ts holding the data is called to copy the data to the allocated memory, and the 100th element is printed to standard output as a test that it is working.
To check that this all works for you, alter your exmon.cc and exmon.hh files as prescribed above; I have included links to my code so you can check that you are doing the right thing. Now save changes, and in the exmon directory, do make, followed by make install. If the make does not work first time, I suggest you look through the output and try to figure out any errors.
If you wish to try implementing the moving average filter I showed you last time, this should not be too hard. The only extra ingredients code-wise that you will need are a private variable to hold the previous value of the filter output (this can be defined in exmon.hh like the other two
variables) and a loop over the data that has been ingested that applies the algorithm to each
data point in turn. Recall that the algorithm is
where w is a weighting factor much smaller than 1, and if tau is the sampling period (time between samples), then tau/w is the response time of the averaging algorithm. It would be interesting to run this on the data in the file, then write both the unprocessed and processed data to a text file and plot the outputs next to each other to see how they compare. I can show you how to make nice plots in root if you have time, but use gnuplot or excel or whatever if you do not have time to do this.