ConvertData.cc

00001 #include "ConvertData.hh"
00002 #include "V172X_Event.hh"
00003 #include "V172X_Params.hh"
00004 #include "RootWriter.hh"
00005 #include "EventHandler.hh"
00006 #include "runinfo.hh"
00007 #include "ConfigHandler.hh"
00008 #include <vector>
00009 
00010   
00011 ConvertData::ConvertData():
00012   BaseModule(GetDefaultName(), 
00013              "Convert the binary data to useable vectors and timestamps")
00014 {
00015   RegisterParameter("offset_channels", _offsets, 
00016                     "map of channelid:offset time to apply for analysis");
00017   _v172X_params = 0;
00018   _headers_only = false;
00019 }
00020 
00021 ConvertData::~ConvertData()
00022 {
00023   
00024 }
00025 
00026 int ConvertData::Initialize()
00027 {
00028   start_time = 0;
00029   previous_event_time = 0;
00030   _id_mismatches = 0;
00031   ConfigHandler* config = ConfigHandler::GetInstance();
00032 
00033   //initialize stuff for decoding V172X events
00034   if(!_v172X_params) 
00035     _v172X_params = dynamic_cast<V172X_Params*>
00036       (config->GetParameter(V172X_Params().GetDefaultKey()));
00037     //if that didn't work, we need to load it
00038   bool err = 0;
00039   if(config->GetSavedCfgFile() != "")
00040     err = config->LoadCreateParameterList(_v172X_params);
00041   if(_v172X_params){
00042     Message(DEBUG)<<"Number of V172X boards in this run: "
00043                   <<_v172X_params->GetEnabledBoards()<<"\n";
00044     //make sure all the per-board params are set
00045     for(int i=0; i<_v172X_params->GetEnabledBoards(); i++){
00046       V172X_BoardParams& board = _v172X_params->board[i];
00047       board.UpdateBoardSpecificVariables();
00048     }
00049     //make sure some intermediate values are set
00050     _v172X_params->GetEventSize();
00051   }
00052   
00053   
00054   if(!_v172X_params){
00055      Message(ERROR)<<"Unable to load saved configuration information!\n";
00056      return 1;
00057   }
00058   
00059   _info = EventHandler::GetInstance()->GetRunInfo();
00060   
00061   return 0;
00062 }
00063 
00064 int ConvertData::Finalize()
00065 {   
00066   //reset the parameter lists
00067   _v172X_params = 0;
00068   if(_id_mismatches){
00069     Message(WARNING)<<_id_mismatches<<" events had mismatched IDs!\n";
00070   }
00071   return 0;
00072 }
00073 
00074 const uint64_t ns_per_s = 1000000000;
00075 int ConvertData::Process(EventPtr event)
00076 {
00077   RawEventPtr raw = event->GetRawEvent();
00078   EventDataPtr data = event->GetEventData();
00079   
00080   //get basic info from the headers
00081   data->event_id = raw->GetID();
00082   data->timestamp = raw->GetTimestamp();
00083   if(start_time == 0){
00084     //this is the first event
00085     start_time = data->timestamp;
00086   }
00087   //set the most basic first, other decoders can override
00088   data->event_time = 1000000000*(data->timestamp-start_time);
00089   //get the real data from datablocks
00090   data->channels.clear();
00091   for(size_t blocknum=0; blocknum<raw->GetNumDataBlocks(); blocknum++){
00092     switch(raw->GetDataBlockType(blocknum)){
00093     case RawEvent::CAEN_V172X :
00094       DecodeV172XData(raw->GetRawDataBlock(blocknum), 
00095                       raw->GetDataBlockSize(blocknum), 
00096                       data);
00097       break;
00098     case RawEvent::MONTECARLO :
00099     default :
00100       Message(ERROR)<<"Decoding has not yet been implemented for block type "
00101                     <<raw->GetDataBlockType(blocknum)<<"\n";
00102       continue;
00103     }
00104   }
00105   
00106   if(!_headers_only){
00107     data->nchans = data->channels.size();
00108     //find the max and min of each channel
00109     for(int ch=0; ch<data->nchans; ch++)
00110       {
00111         ChannelData& chdata = data->channels[ch];
00112         double* wave = chdata.GetWaveform();
00113         double* max_samp = std::max_element(wave, wave+chdata.nsamps);
00114         double* min_samp = std::min_element(wave, wave+chdata.nsamps);
00115         //data is saturated if it hit 0 or maximum range
00116         chdata.saturated = (*min_samp == 0 || 
00117                             *max_samp == chdata.GetVerticalRange());
00118         if(chdata.saturated) data->saturated = true;
00119         chdata.maximum = *max_samp;
00120         chdata.minimum = *min_samp;
00121         chdata.max_time = chdata.SampleToTime(max_samp - wave);
00122         chdata.min_time = chdata.SampleToTime(min_samp - wave);
00123         //find the single photoelectron peak for this channel
00124         
00125         int chinfo=0;
00126         //const RunDB::runinfo::channelinfo* chinfo = 
00127         //_info->GetChannelInfo(chdata.channel_id);
00128         if(chinfo)
00129           chdata.spe_mean = 1;//chinfo->spe_mean;
00130         else
00131           {
00132             chdata.spe_mean = 1;
00133             bool fail = EventHandler::GetInstance()->GetFailOnBadCal();
00134             if(fail){
00135               Message(ERROR)<<"No calibration info for channel "
00136                             <<chdata.channel_id<<" in event "
00137                             <<data->event_id<<" in run "<<data->run_id<<"\n";
00138               return -1;
00139             }
00140           }
00141 
00142         // get the PMT information for this channel
00143         //chdata.pmt.Load(_cpinfo->pmts[chdata.channel_id]);
00144       }
00145     data->nchans = data->channels.size();
00146   }// end skipped section if headers only
00147 
00148   data->dt = ( previous_event_time > 0 ? 
00149                data->event_time - previous_event_time : 0 );
00150   previous_event_time = data->event_time;
00151   
00152   //since we don't know the last event, set info for each event
00153   _info->starttime = start_time;
00154   _info->endtime = data->timestamp;
00155   _info->events = data->event_id+1;
00156   _info->triggers = data->trigger_count+1;
00157   /*
00158   if(_info->trigger_veto > 0){
00159     _info->livetime = 1.*data->event_time/ns_per_s - 
00160       _info->trigger_veto/1000. * (1.*_info->events);
00161     //should  the acquisition window be "live"????
00162   }
00163   else if(data->trigger_count)
00164     _info->livetime = 1.*_info->events / data->trigger_count * 
00165       data->event_time / ns_per_s;
00166   */
00167   return 0;
00168 }
00169 
00170 int ConvertData::DecodeV172XData(const unsigned char* rawdata, 
00171                                   uint32_t datasize, 
00172                                   EventDataPtr data)
00173 {
00174   V172XEventPtr v172X(new V172X_Event(rawdata,
00175                                       datasize, 
00176                                       _v172X_params) );
00177   const V172X_Params* params = v172X->GetParameters(); 
00178   int n_boards = v172X->GetNBoards();
00179   //estimate the number of channels and reserve size in the vector
00180   int reserve_size = (params->enabled_channels > 0 ? params->enabled_channels :
00181                       n_boards * 10 );
00182   data->channels.reserve( reserve_size + 5);
00183   bool id_mismatch=false;
00184   for(int i=0; i<n_boards; i++){
00185     const V172X_BoardData& board_data = v172X->GetBoard(i);
00186     const V172X_BoardParams& board_params = 
00187         params->board[board_data.board_id];
00188     //check for ID mismatch
00189     if(i==0)
00190       data->trigger_count = board_data.event_counter;
00191     else if(board_data.event_counter != (uint32_t)data->trigger_count){
00192       id_mismatch = true;
00193     }
00194                                                          
00195     uint64_t s_since_start = data->timestamp - start_time;
00196     //if(s_since_start > 1) s_since_start--;
00197     if(board_data.timestamp * board_params.ns_per_clocktick <
00198        board_params.GetTimestampRange()/2)
00199       s_since_start+=board_params.GetTimestampRange()/ns_per_s/4;
00200     else
00201       s_since_start-=board_params.GetTimestampRange()/ns_per_s/4;
00202     uint64_t n_resets = (s_since_start * ns_per_s)/ 
00203       ( board_params.GetTimestampRange());
00204     /*uint64_t n_resets2 = ((s_since_start+2)*ns_per_s)/
00205       ( board_params.GetTimestampRange());
00206     if( n_resets2 > n_resets && 
00207         (board_params.ns_per_clocktick*board_data.timestamp)<2*ns_per_s  
00208         && s_since_start > 1 )
00209         n_resets++;*/
00210     data->event_time = board_params.GetTimestampRange() * n_resets + 
00211       board_params.ns_per_clocktick * board_data.timestamp;
00212     for(int j=0; j<board_data.nchans; j++){
00213       if(board_data.channel_start[j] == NULL)
00214         continue;
00215       int channel_id = board_data.nchans * board_data.board_id + j;
00216       if( _skip_channels.find(channel_id) != _skip_channels.end())
00217         continue;
00218       const V172X_ChannelParams& ch_params = board_params.channel[j];
00219       data->channels.push_back(ChannelData());
00220       ChannelData& chdata = data->channels.back();
00221       chdata.board_id = board_data.board_id;
00222       chdata.board_num = i;
00223       chdata.channel_num = j;
00224       chdata.channel_id = channel_id;
00225       chdata.label = ch_params.label;
00226       chdata.timestamp = board_data.timestamp * 10; //Fix this!
00227       chdata.sample_bits = board_params.sample_bits;
00228       chdata.sample_rate = board_params.GetSampleRate();
00229       chdata.trigger_index = board_params.GetTriggerIndex() - 
00230         (int)(GetChOffset(channel_id) * chdata.sample_rate);
00231       
00232       //copy over the actual waveform information
00233       if(_headers_only) continue;
00234       chdata.channel_start = (char*)(board_data.channel_start[j]);
00235       chdata.channel_end = (char*)(board_data.channel_end[j]);
00236       if(board_params.zs_type != ZLE){
00237         // copy the data as a double 
00238         if(chdata.sample_bits < 9)
00239           chdata.waveform.assign((uint8_t*)chdata.channel_start,
00240                                  (uint8_t*)chdata.channel_end);
00241         else if (chdata.sample_bits == 10) {
00242           chdata.waveform.clear ();
00243           for (uint32_t* ptr = (uint32_t*)chdata.channel_start; 
00244                ptr < (uint32_t*)chdata.channel_end; ptr ++) {
00245             uint32_t raw_v = *ptr;
00246             const int ns = (raw_v>>30)&3;
00247             for (int i = 0; i < ns; i++) {
00248               uint16_t sample = raw_v & 0x3ff;
00249               raw_v = raw_v >> 10;
00250               chdata.waveform.push_back (sample);
00251             }
00252           }
00253         }
00254         else if(chdata.sample_bits < 17)
00255           chdata.waveform.assign((uint16_t*)chdata.channel_start,
00256                                  (uint16_t*)chdata.channel_end);
00257         else
00258           chdata.waveform.assign((uint32_t*)chdata.channel_start,
00259                                  (uint32_t*)chdata.channel_end);
00260       }
00261       else{
00262         //we need to evaluate the zero skipped data
00263         //first word is the size of this channel's data
00264         uint32_t nwords = *((uint32_t*)(chdata.channel_start));
00265         chdata.nsamps = 0;
00266         uint32_t offset = 1;
00267         std::vector<const char*> data_blocks;
00268         while(offset < nwords){
00269           //get the control word
00270           uint32_t control = *( ((uint32_t*)(chdata.channel_start)) + offset);
00271           uint32_t subwords = control & 0x1FFFFF;
00272           uint32_t subsamps = subwords * board_params.bytes_per_sample;
00273           bool good = control & 0x80000000;
00274           
00275           if(good){
00276             data_blocks.push_back( chdata.channel_start + 4*(offset+1) );
00277             std::pair<int,int> region(chdata.nsamps,
00278                                       chdata.nsamps + subsamps);
00279             chdata.unsuppressed_regions.push_back(region);
00280             offset += subwords;
00281           }
00282           
00283           chdata.nsamps += subsamps;
00284           offset += 1;
00285         }
00286         //assign all the value of 1 by default so it doesn't show as saturated
00287         chdata.waveform.assign(chdata.nsamps, 1);
00288         std::vector<double>& wave = chdata.waveform;
00289         //now try to fill all the valid samples
00290         for(size_t block=0; block < data_blocks.size(); block++){
00291           int subsamps = chdata.unsuppressed_regions[block].second - 
00292               chdata.unsuppressed_regions[block].first;
00293           if(chdata.sample_bits < 9){
00294             std::copy( (uint8_t*)data_blocks[block],
00295                        ((uint8_t*)data_blocks[block]) + subsamps,
00296                        &(wave[chdata.unsuppressed_regions[block].first]) );
00297           }
00298           else if (chdata.sample_bits < 17){
00299             std::copy( (uint16_t*)data_blocks[block],
00300                        ((uint16_t*)data_blocks[block]) + subsamps,
00301                        &(wave[chdata.unsuppressed_regions[block].first]) );
00302           }
00303           else {
00304             std::copy( (uint32_t*)data_blocks[block],
00305                        ((uint32_t*)data_blocks[block]) + subsamps,
00306                        &(wave[chdata.unsuppressed_regions[block].first]) );
00307           }
00308         }
00309         //finally set the baseline to the nearest sample
00310         for(size_t block=0; block < data_blocks.size(); block++){
00311           std::pair<int,int> region = chdata.unsuppressed_regions[block];
00312           int fill_start = (block > 0 ? 
00313                             chdata.unsuppressed_regions[block-1].second : 0 );
00314           int fill_end = region.first;
00315           if(fill_end > fill_start)
00316             std::fill( &(wave[fill_start]), &(wave[fill_end]), wave[fill_end]);
00317         }
00318         //check the last region
00319         if( !chdata.unsuppressed_regions.empty() && 
00320             chdata.unsuppressed_regions.back().second < chdata.nsamps){
00321           std::fill( &(wave[chdata.unsuppressed_regions.back().second]),
00322                      &(wave[chdata.nsamps]), 
00323                      wave[chdata.unsuppressed_regions.back().second-1] );
00324         }
00325       }// end check for zero suppressed data
00326       chdata.nsamps = chdata.waveform.size();
00327     }
00328   }
00329   if(id_mismatch){
00330     if(_id_mismatches==0){
00331       Message(WARNING)<<"Event ID mismatch found on event "
00332                       <<data->event_id<<"!\n";
00333       Message(WARNING)<<"Further mismatches will be silent.\n";
00334     }
00335     
00336     data->status |= EventData::ID_MISMATCH;
00337     _id_mismatches++;
00338   }     
00339   
00340   return 0;
00341 }
00342 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on 20 Jun 2014 for daqman by  doxygen 1.6.1