/********************************************************************\ 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 #include #include #include /* midas includes */ #include "midas.h" #include "experim.h" #include "analyzer.h" /* root includes */ #include #include #include /* 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; }