Dear Jan,
I had a look at your code. You create a gPhysicsEventHeader array, fill it, and expect the
framework to write it to disk. But how can the framework "guess" that you want your private
global array being written? Unfortunately it cannot do magic!
Do do what you want, you have to write a "secondary" midas file yourself. I modified your
code to do that. First, I define the event storage like
BYTE gSecEvent[ MAX_EVENT_SIZE ];
EVENT_HEADER *gPhysicsEventHeader = (EVENT_HEADER *) gSecEvent;
WORD* gPhysicsEventData = ( WORD * )( gPhysicsEventHeader + 1 );
I use gSecEvent as a BYTE array, since it only contains one avent at a time, so this is more
appropriate. Then, in the BOR routine, I open a file:
sprintf(str, "sec%05d.mid", run_number);
sec_fh = open(str, O_CREAT | O_RDWR | O_BINARY, 0644);
and close it in the EOR routine
close(sec_fh);
The event routine now manually fills events into the secondary file:
/* write event to secondary .mid file */
gPhysicsEventHeader->data_size = bk_size(gPhysicsEventData);
write(sec_fh, gPhysicsEventHeader, sizeof(EVENT_HEADER)+bk_size(gPhysicsEventData));
Note that this code is placed *inside* the for() loop over nItems, so for each detector you
create and event and write it.
That's all you need, the full file adccalib.c is attached. I tried to produce a sec01220.mid
file and was able to read it back with the mdump utility.
Best regards,
Stefan |
/********************************************************************\
Name: adccalib.c
Created by: Stefan Ritt
Contents: Example analyzer module for ADC calibration. Looks
for ADC0 bank, subtracts pedestals and applies gain
calibration. The resulting values are appended to
the event as an CADC bank ("calibrated ADC"). The
pedestal values and software gains are stored in
adccalib_param structure which was defined in the ODB
and transferred to experim.h.
\********************************************************************/
/*-- Include files -------------------------------------------------*/
/* standard includes */
#include <stdio.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
/* midas includes */
#include "midas.h"
#include "experim.h"
#include "analyzer.h"
/* root includes */
#include <TH1F.h>
#include <TTree.h>
#include <TDirectory.h>
/* Local stuff, struct for handling analysis demo...
using EV01_BANK as template for bank mapping */
#define N_STRUCT_ELEMENT 6
#define N_FRONTENDS 14
/* Histo info, could be placed in ODB */
typedef struct {
char name[ 256 ];
char title[ 256 ];
INT nbins;
float xlow;
float xhigh;
} EV_HI_DEF;
EV_HI_DEF h[ N_STRUCT_ELEMENT ]={
{"AreaHG", "AreaHG" , 1024, 0.0, 1023.},
{"AreaLG", "AreaLG" , 1024, 0.0, 1023.},
{"TimeHi", "Time High", 1024, 0.0, 1023.},
{"TimeLo", "Time Low" , 1024, 0.0, 1023.},
{"Detid" , "Detector ID" , 1024, 0.0, 1023.},
{"Slope" , "Slope" , 1024, 0.0, 1023.}
};
/*-- Parameters ----------------------------------------------------*/
/* local creation of ODB struct */
GAMMA_PARAM_STR( gamma_param_str );
GAMMA_PARAM gamma_param;
/* Global ODB struct (taken care by analyzer.c) */
extern EXP_PARAM exp_param;
extern RUNINFO runinfo;
/*-- Module declaration --------------------------------------------*/
INT adc_calib( EVENT_HEADER*, void* );
INT adc_calib_init( void );
INT adc_calib_bor( INT run_number );
INT adc_calib_eor( INT run_number );
/*-- New Bank Area -------------------------------------------------*/
BYTE gSecEvent[ MAX_EVENT_SIZE ];
EVENT_HEADER *gPhysicsEventHeader = (EVENT_HEADER *) gSecEvent;
// Trick used for allocating MAX_EVENT_SIZE bytes for bank.
WORD* gPhysicsEventData = ( WORD * )( gPhysicsEventHeader + 1 );
// Pointer to start of first data record
/* file for secondary .mid file */
int sec_fh;
/* The module name "Gamma" is used for the ODB tree under
/Analyzer/Parameters. It maps the experim.h gamma struct.
*/
ANA_MODULE adc_calib_module = {
"Gamma", /* module name */
"Pierre", /* author */
adc_calib, /* event routine */
adc_calib_bor, /* BOR routine */
adc_calib_eor, /* EOR routine */
adc_calib_init, /* init routine */
NULL, /* exit routine */
&gamma_param, /* parameter structure */
sizeof(gamma_param), /* structure size */
gamma_param_str, /* initial parameters */
};
/*-- module-local variables ----------------------------------------*/
extern TDirectory *gManaHistsDir;
/* Root Histo objects */
static TH1F* gAdcHists[ N_FRONTENDS ];
/*-- init routine --------------------------------------------------*/
#define TM_N_BINS 2048
#define TM_X_LOW 0
#define TM_X_HIGH 40000
INT adc_calib_init(void)
{
char name[ 256 ];
int fe_number = 2;
int i;
char title[256];
// Some booking for demo
// Just book the crystals from frontend 2.
for (i=0; i < N_STRUCT_ELEMENT; i++)
{
sprintf(name, "%s-%2.2i" , h[i].name, fe_number);
sprintf(title, "%s-%2.2i", h[i].title, fe_number);
gAdcHists[i] = (TH1F*)gManaHistsDir->GetList()->FindObject(name);
printf("Booking Histo:%s\n", name);
if (gAdcHists[i] == NULL)
gAdcHists[i] = new TH1F(name, title, h[i].nbins, h[i].xlow, h[i].xhigh);
}
return SUCCESS;
}
/*-- BOR routine ---------------------------------------------------*/
INT adc_calib_bor(INT run_number)
{
char str[80];
sprintf(str, "sec%05d.mid", run_number);
sec_fh = open(str, O_CREAT | O_RDWR | O_BINARY, 0644);
if (sec_fh < 0)
cm_msg(MERROR, "adc_calib_bor", "Cannot open secondary .mid file \"%s\"", str);
return SUCCESS;
}
/*-- eor routine ---------------------------------------------------*/
INT adc_calib_eor(INT run_number)
{
close(sec_fh);
return SUCCESS;
}
/*-- event routine -------------------------------------------------*/
INT adc_calib(EVENT_HEADER *pheader, void *pevent)
{
INT n_items;
DWORD *pdata;
EV01_BANK *pev;
TREK_BANK *trek;
// Initialize the calculate output bank including the header.
gPhysicsEventHeader->serial_number = (DWORD) - 1;
gPhysicsEventHeader->event_id = 2;
gPhysicsEventHeader->trigger_mask = 0;
gPhysicsEventHeader->time_stamp = pheader->time_stamp;
// For demo assume each crystal in bank 2 is new event. This really isn't
// true, but it is analogous to splitting one midas event into multiple physics
// events.
/* Get there with ID = 1 -> EVxx,
For demo histo EV02 EV_BANK all elements.
Create a new bank TREK which is a structure bank.
We are testing the breaking of a single midas event
into individual physics events. Thus we will take
each crystal in EV02 and make it a separate event
in the TREK output bank.
[local:Default:S]Bank switches>set TREK 1
for output
Apply some calibration from the gamma ODB struct.
*/
/* look for EV02 bank, return if not present, skip TMxx ....
n_items: number of elements in the bank */
if ( !( n_items = bk_locate( pevent, "EV02", &pdata ) ) )
return 1;
// Loop through all items in bank.
short nItems = n_items/ sizeof( EV01_BANK );
printf( "Number of bytes %d, number of items %d\n", n_items, nItems );
pev = (EV01_BANK *)pdata;
for ( short i = 0; i < nItems; i++ )
{
/* fill histos not really elegant for now*/
gAdcHists[0]->Fill((float) pev->areahg, 1);
gAdcHists[1]->Fill((float) pev->arealg, 1);
gAdcHists[2]->Fill((float) pev->timehi, 1);
gAdcHists[3]->Fill((float) pev->timelo, 1);
gAdcHists[4]->Fill((float) pev->detid, 1);
gAdcHists[5]->Fill((float) pev->slop, 1);
// create calibrated TREK bank. Recall that this output bank mimics
// the splitting up of the midas bank into physics events.
++(gPhysicsEventHeader->serial_number); // Update serial number.
bk_init32( gPhysicsEventData ); // Initialize storage.
bk_create( gPhysicsEventData, "TREK", TID_STRUCT, &trek );
trek->one = (double) pev->areahg * 1.0;
trek->two = (float) pev->timelo * 1.0;
printf("area: %e time: %f\n", trek->one, trek->two );
bk_close( gPhysicsEventData, trek+1 );
pev++; // Loop to next crystal's data.
/* write event to secondary .mid file */
gPhysicsEventHeader->data_size = bk_size(gPhysicsEventData);
write(sec_fh, gPhysicsEventHeader, sizeof(EVENT_HEADER)+bk_size(gPhysicsEventData));
}
/* close calculated bank */
return SUCCESS;
}
|