/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 #include "ROsFeeReadoutTool.h" 00002 #include "ROsFadcReadoutTool.h" 00003 00004 #include "Conventions/Detectors.h" 00005 #include "Conventions/Electronics.h" 00006 #include "Conventions/Trigger.h" 00007 #include "Conventions/Site.h" 00008 00009 #include "Event/SimReadoutHeader.h" 00010 #include "Event/ReadoutPmtCrate.h" 00011 #include "Event/ReadoutTriggerDataPkg.h" 00012 00013 #include "Event/ElecCrateHeader.h" 00014 #include "Event/ElecFeeCrate.h" 00015 #include "Event/ElecFeeChannel.h" 00016 00017 #include "Event/SimTrigCommand.h" 00018 #include "Event/SimTrigCommandHeader.h" 00019 #include "Event/SimTrigCommandCollection.h" 00020 00021 #include "DataSvc/ICalibDataSvc.h" 00022 00023 #include <set> 00024 #include <vector> 00025 00026 ROsFeeReadoutTool::ROsFeeReadoutTool(const std::string& type, 00027 const std::string& name, 00028 const IInterface* parent) 00029 : GaudiTool(type,name,parent) 00030 { 00031 declareInterface< IROsReadoutTool >(this) ; 00032 // for now add all but RPC's as default. 00033 m_detectorsToProcess.push_back("DayaBayAD1"); 00034 m_detectorsToProcess.push_back("DayaBayAD2"); 00035 m_detectorsToProcess.push_back("DayaBayIWS"); 00036 m_detectorsToProcess.push_back("DayaBayOWS"); 00037 m_detectorsToProcess.push_back("LingAoAD1"); 00038 m_detectorsToProcess.push_back("LingAoAD2"); 00039 m_detectorsToProcess.push_back("LingAoIWS"); 00040 m_detectorsToProcess.push_back("LingAoOWS"); 00041 m_detectorsToProcess.push_back("FarAD1"); 00042 m_detectorsToProcess.push_back("FarAD2"); 00043 m_detectorsToProcess.push_back("FarAD3"); 00044 m_detectorsToProcess.push_back("FarAD4"); 00045 m_detectorsToProcess.push_back("FarIWS"); 00046 m_detectorsToProcess.push_back("FarOWS"); 00047 00048 declareProperty("SimDataSvcName",m_simDataSvcName="StaticSimDataSvc", 00049 "Name of service to provide FEE channel properties for simulation"); 00050 declareProperty("DetectorsToProcess",m_detectorsToProcess, 00051 "List of detectors to process with this tool"); 00052 declareProperty("EnablePeakReadout",m_enablePeakReadout=true, 00053 "Switch on/off peak readout mode"); 00054 declareProperty("EnableWaveformReadout",m_enableWaveformReadout=false, 00055 "Switch on/off waveform readout mode"); 00056 declareProperty("EnableFadcReadout", m_enableFadcReadout=false, 00057 "Switch on/off FADC readout mode"); 00058 declareProperty("WaveformTool", m_waveformToolName="ROsFeeAdcMultiTool", 00059 "Name of waveform readout tool"); 00060 declareProperty("TdcTool", m_tdcToolName="ROsFeeTdcTool", 00061 "Name of tdc readout tool"); 00062 declareProperty("FadcTool", m_fadcToolName="ROsFadcReadoutTool", 00063 "Name of fadc readout tool"); 00064 00065 //Changed readout Length : (1200/1.5625 = 768) 00066 declareProperty("ReadoutLength",m_readoutLength=780, 00067 "Length of readout window in 640Mhz clock cycles"); 00068 //Changed trigger Latency to 980 (why ?) 00069 declareProperty("TriggerLatency",m_triggerLatency=966, 00070 "Trigger latency in 640Mhz clock cycles"); 00071 //Changed readout offset (200/1.5625 = 128) 00072 declareProperty("ReadoutOffset",m_readoutOffset=198, 00073 "Offset of readout window from trigger tdc in 640Mhz clock cycles"); 00074 00075 00076 declareProperty("PeakFindingLength",m_peakFindingLength=12, 00077 "Length of peak finding window in 40Mhz clock cycles"); 00078 declareProperty("PeakFindingOffset",m_peakFindingOffset=0, 00079 "Offset of peak finding window from corresponding hit in 40Mhz clock cycles"); 00080 declareProperty("PeakFindingOverlap",m_peakFindingOverlap=true, 00081 "Allow overlapping peakfinding for consecutive hits"); 00082 declareProperty("PreAdcOffset",m_preAdcOffset=4, 00083 "Offset of first PreADC cycle from start of ADC peak finding window in 40Mhz clock cycles"); 00084 declareProperty("NhitCycles", m_nhitCycles = DayaBay::NhitCycles, "Nhit cycles"); 00085 declareProperty("EsumCycles", m_eSumCycles = DayaBay::EsumCycles, "Esum cycles"); 00086 declareProperty("FADCOffset", m_fadcOffset = 250, "FADC offset"); 00087 declareProperty("FADCLength", m_fadcLength = 120, "FADC readout window legth"); 00088 declareProperty("MaxFineAdc",m_maxFineAdc=3500, 00089 "Maximum fine-range ADC value before using the coarse range"); 00090 } 00091 00092 ROsFeeReadoutTool::~ROsFeeReadoutTool(){} 00093 00094 StatusCode ROsFeeReadoutTool::initialize() 00095 { 00096 std::vector<std::string>::iterator it; 00097 for(it=m_detectorsToProcess.begin();it!=m_detectorsToProcess.end();++it){ 00098 short int detId = DayaBay::Detector::siteDetPackedFromString(*it); 00099 DayaBay::Detector det(detId); 00100 m_detectors.insert(det); 00101 } 00102 00103 try { 00104 m_waveformTool = tool<IROsFeeWaveformTool>(m_waveformToolName) ; 00105 debug() << "Using \"" << m_waveformToolName 00106 << "\" for waveform readout " << endreq; 00107 } 00108 catch(const GaudiException& exg) { 00109 fatal() << "Failed to get Readout Tool: \"" 00110 << m_waveformToolName << "\"" << endreq; 00111 return StatusCode::FAILURE; 00112 } 00113 try { 00114 m_tdcTool = tool<IROsFeeTdcTool>(m_tdcToolName) ; 00115 debug() << "Using \"" << m_tdcToolName 00116 << "\" for TDC readout " << endreq; 00117 } 00118 catch(const GaudiException& exg) { 00119 fatal() << "Failed to get Readout Tool: \"" << m_tdcToolName << "\"" << endreq; 00120 return StatusCode::FAILURE; 00121 } 00122 try { 00123 m_fadcTool = tool<IROsFadcReadoutTool>(m_fadcToolName) ; 00124 debug() << "Using \"" << m_fadcToolName 00125 << "\" for fadc readout " << endreq; 00126 } 00127 catch(const GaudiException& exg) { 00128 fatal() << "Failed to get Readout Tool: \"" 00129 << m_waveformToolName << "\"" << endreq; 00130 return StatusCode::FAILURE; 00131 } 00132 00133 // Get PMT simulation input data service 00134 m_simDataSvc = svc<ISimDataSvc>(m_simDataSvcName,true); 00135 00136 if( !m_enablePeakReadout && !m_enableWaveformReadout ) { 00137 error() << "All readout modes switched off" << endreq; 00138 return StatusCode::FAILURE; 00139 } 00140 if( m_enablePeakReadout ) 00141 info() << "Peak readout mode enabled" << endreq; 00142 if( m_enableWaveformReadout ) 00143 info() << "Waveform readout mode enabled" << endreq; 00144 00145 return StatusCode::SUCCESS; 00146 } 00147 00148 StatusCode ROsFeeReadoutTool::finalize() 00149 { 00150 return StatusCode::SUCCESS; 00151 } 00152 00153 StatusCode ROsFeeReadoutTool::makeReadouts(DayaBay::SimReadoutHeader* roHeader, 00154 std::vector<DayaBay::ReadoutTriggerDataPkg*>& trigDataPkg, 00155 const DayaBay::ElecHeader& elecHeader) 00156 { 00157 debug() << "running makeReadouts() in FeeReadoutTool" << endreq; 00158 00159 DayaBay::SimReadoutHeader::SimReadoutContainer& outputReadouts 00160 = roHeader->readouts(); 00161 00162 Context context = roHeader->context(); 00163 //Get Crate Map 00164 const DayaBay::ElecCrateHeader *ech = elecHeader.crateHeader(); 00165 const DayaBay::ElecCrateHeader::CrateMap crMap = ech->crates(); 00166 DayaBay::ElecCrateHeader::CrateMap::const_iterator crIt; 00167 00168 std::vector<DayaBay::ReadoutTriggerDataPkg*>::iterator pkgIt; 00169 00170 //Loop over All trigger data packages 00171 for(pkgIt = trigDataPkg.begin(); pkgIt != trigDataPkg.end(); ++pkgIt) 00172 { 00173 DayaBay::Detector det((*pkgIt)->detector()); 00174 if(m_detectors.find(det) != m_detectors.end()){ 00175 crIt = crMap.find(det); 00176 const DayaBay::ElecFeeCrate *crate; 00177 if(crIt == crMap.end()){ 00178 if((*pkgIt)->frames().size()==0){ 00179 fatal() << "Trying to process a trigger for " << det.detName() 00180 << " But Package Has No Frames" << endreq; 00181 return StatusCode::FAILURE; 00182 }else{ 00183 fatal() << "Trying to process a trigger for " << det.detName() 00184 << " But no crate exists -- skipping" << endreq; 00185 return StatusCode::FAILURE; 00186 } 00187 crate = 0; 00188 }else{ 00189 crate = dynamic_cast<const DayaBay::ElecFeeCrate*>(crIt->second); 00190 debug() << "Processing a trigger for " << det.detName() 00191 << " found crate at " << crate << endreq; 00192 } 00193 if(crate != 0){ // if the crate exists read it out. 00194 debug()<<"Reading out 1 trigger with: " 00195 <<((*pkgIt)->frames().size())-1 00196 <<" masked triggers."<<endreq; 00197 00198 const DayaBay::ReadoutTriggerDataFrame *tdf = (*pkgIt)->frames().at(0); 00199 00200 DayaBay::ReadoutPmtCrate *crateReadout = readoutCrate(tdf,crate,context); 00201 00202 outputReadouts.push_back(new DayaBay::SimReadout(crateReadout, 00203 roHeader)); 00204 00206 (*pkgIt)->setReadout(crateReadout); 00207 crateReadout->setTriggerDataPkg(*pkgIt); 00208 00209 verbose() << "set readout:\n" << (**pkgIt) << endreq; 00210 00211 if( m_enableFadcReadout ) 00212 { 00213 debug() << " Trying FADC Readout " << endreq; 00214 00215 unsigned int triggerCycle = tdf->cycle(); 00216 00217 int start = int((triggerCycle*m_eSumCycles)/m_nhitCycles)+m_fadcOffset; 00218 00219 int stop = start+m_fadcLength; 00220 00221 m_fadcTool->readoutFADC(crate,crateReadout,start,stop); 00222 debug() << "readout map size: " << (crateReadout->fadcReadout()).size() << endreq; 00223 00224 debug() << " Done reading out FADC" << endreq; 00225 } 00226 } 00227 }else{ 00228 verbose() << "Found Trigger For " << det.detName() 00229 << "but this tool is not supposed " 00230 << "to process that detector type " 00231 << "check properties to configure." 00232 << endreq; 00233 } 00234 } 00235 return StatusCode::SUCCESS; 00236 } 00237 00238 DayaBay::ReadoutPmtCrate* ROsFeeReadoutTool::readoutCrate(const DayaBay::ReadoutTriggerDataFrame *tdf, 00239 const DayaBay::ElecFeeCrate *cr, Context context) 00240 { 00241 TimeStamp triggerTime(cr->header()->header()->earliest()); 00242 triggerTime.Add( tdf->cycle() / double(DayaBay::NhitFrequencyHz) ); 00243 DayaBay::ReadoutPmtCrate *out_readout 00244 = new DayaBay::ReadoutPmtCrate(cr->detector(),0, triggerTime, tdf->triggerType()); 00245 00246 DayaBay::ReadoutPmtCrate::PmtChannelReadouts ro_chMap; 00247 00248 const DayaBay::ElecFeeCrate::ChannelData& chmap = cr->channelData(); 00249 DayaBay::ElecFeeCrate::ChannelData::const_iterator chIt; 00250 00251 for(chIt = chmap.begin(); chIt != chmap.end() ; ++chIt){ 00252 DayaBay::ReadoutPmtChannel *ro_ch = readoutChannel(tdf,&(chIt->second), 00253 chIt->first,context); 00254 if (ro_ch == 0) continue; // test to see if channel has readout 00255 ro_ch->setChannelId(chIt->first); // set these here since an ElecFeeChannel 00256 ro_ch->setReadout(out_readout); // does not know about them 00257 ro_chMap[chIt->first] = *ro_ch; // copy the value by it's address to the map 00258 ro_ch->setReadout(0); // reset Readout, to avoid double deletion 00259 delete ro_ch; // delete unnecessary copy 00260 } 00261 00262 out_readout->setChannelReadout(ro_chMap); 00263 return out_readout; 00264 } 00265 00266 DayaBay::ReadoutPmtChannel* ROsFeeReadoutTool::readoutChannel( 00267 const DayaBay::ReadoutTriggerDataFrame *tdf, 00268 const DayaBay::ElecFeeChannel *feeChannel, 00269 DayaBay::FeeChannelId channelId, 00270 Context context) 00271 { 00272 // Get the simulation properties for this channel 00273 int task = 0; 00274 ServiceMode svcMode(context, task); 00275 const DayaBay::FeeSimData* feeSimData = 00276 m_simDataSvc->feeSimData(channelId, svcMode); 00277 if(!feeSimData){ 00278 error() << "No Simulation input properties for FEE channel: " 00279 << channelId << endreq; 00280 } 00281 00282 // convert trigger clock cycle from NhitFrequencyHz to TdcFrequencyHz 00283 DayaBay::ReadoutPmtChannel *ro_ch = new DayaBay::ReadoutPmtChannel(); 00284 int nHitTrigCycle = tdf->cycle(); 00285 int tdcTrigCyc = (int)(double(nHitTrigCycle) * 00286 double(DayaBay::TdcCycles)/double(DayaBay::NhitCycles) + 0.5); 00287 verbose() << "Conv TDC Clock Cycle: " << tdcTrigCyc << endreq; 00288 std::vector<int> hit = feeChannel->hit(); 00289 int tdcSize = hit.size() *(1+int(DayaBay::TdcCycles/DayaBay::NhitCycles)); 00290 00291 // Find clock cycle of readout window start and end in TDC frequency 00292 int tdcFirst; 00293 if( (int)tdcTrigCyc - m_readoutOffset < 0){ 00294 verbose() << "Invalid Readout TDC Start Cycle " 00295 << (int)tdcTrigCyc - m_readoutOffset 00296 << " Using 0" << endreq; 00297 tdcFirst = 0; 00298 } else tdcFirst = tdcTrigCyc - m_readoutOffset; 00299 verbose() << "TDC First in ns: " << tdcFirst *1.5625 << endreq; 00300 00301 int tdcLast; 00302 if( tdcTrigCyc - m_readoutOffset + m_readoutLength > tdcSize){ 00303 verbose() << "Invalid Readout TDC Last Cycle " 00304 << tdcTrigCyc - m_readoutOffset + m_readoutLength 00305 << " Using " << tdcSize << endreq; 00306 tdcLast = tdcSize; 00307 } else tdcLast = tdcTrigCyc - m_readoutOffset + m_readoutLength; 00308 verbose() << "TDC Last in ns: " << tdcLast *1.5625 << endreq; 00309 verbose() << "reading out tdc window [ " 00310 << tdcFirst << "," << tdcLast << " )" << endreq; 00311 00312 // Compute common stop clock cycle for TDC values 00313 int tdcStopCycle = tdcTrigCyc + m_triggerLatency; 00314 const DayaBay::DigitalSignal* adc; 00315 int adcFirst; 00316 int adcLast; 00317 int adcPedFirst; 00318 00319 // Compute variables for peak readout mode 00320 if ( m_enablePeakReadout ){ 00321 // Read out clock numbers which represent the time when signal crosses threshold 00322 const std::vector<int>& tdcOrg = feeChannel->tdc(); 00323 std::vector<int> tdc_vec; 00324 StatusCode sc = m_tdcTool->readoutTdc(tdcOrg,tdcFirst,tdcLast,tdc_vec); 00325 if( !sc.isSuccess() || tdc_vec.empty() ) { 00326 delete ro_ch; 00327 return 0; 00328 } 00329 00330 // Loop over TDC values to compute corresponding peak ADC values and peaking clock cycles 00331 int nTdc = tdc_vec.size(); 00332 std::vector<int> tdc_out(nTdc); 00333 std::vector<int> tdcHitCount_out(nTdc); 00334 std::vector<int> adc_out(nTdc); 00335 std::vector<int> adcCycle_out(nTdc); 00336 std::vector<int> adcRange_out(nTdc); 00337 std::vector<int> preAdc_out(nTdc); 00338 00339 DayaBay::FeeGain::FeeGain_t gain; 00340 int currentAdc; 00341 00342 int currentTdc = -1000; 00343 00344 for ( int i = 0; i < nTdc; i++ ){ 00345 // Check if preceeding peak finding is finished 00346 if ( tdc_vec[i] - currentTdc > m_peakFindingLength * 16 || m_peakFindingOverlap == true){ 00347 00348 // Assume the high gain ADC will be read out 00349 adc = &(feeChannel->adcHigh()); 00350 gain = DayaBay::FeeGain::kHigh; 00351 verbose() << "Maximum available ADC window [ " << 0 << "," << adc->size() 00352 << " )" << endreq; 00353 00354 // Search for peak within 300 ns window from corresponding TDC clock cycle 00355 currentTdc = tdc_vec[i]; 00356 currentAdc = (int) (double(currentTdc) * double(DayaBay::AdcCycles)/double(DayaBay::TdcCycles) ); 00357 00358 if( currentAdc - m_peakFindingOffset < 0){ 00359 verbose() << "Invalid ADC Peak Finding Start Cycle " 00360 << currentAdc - m_peakFindingOffset 00361 << " Using 0" << endreq; 00362 adcFirst = 0; 00363 } 00364 else adcFirst = currentAdc - m_peakFindingOffset; 00365 verbose() << "ADC First in ns: " << adcFirst * 25. << endreq; 00366 00367 if( currentAdc - m_peakFindingOffset + m_peakFindingLength > adc->size() ){ 00368 verbose() << "Invalid ATDC Peak Finding Last Cycle " 00369 << currentAdc - m_peakFindingOffset + m_peakFindingLength 00370 << " Using " << adc->size() -1 << endreq; 00371 adcLast = adc->size() -1; 00372 } 00373 else adcLast = currentAdc - m_peakFindingOffset + m_peakFindingLength; 00374 verbose() << "ADC Last in ns: " << adcLast * 25. << endreq; 00375 00376 verbose() << "Reading out peak finding window [ " 00377 << adcFirst << "," << adcLast +1 << ")" << endreq; 00378 00379 // Check if high gain assumption was correct 00380 for( int j = adcFirst; j < adcLast; ++j ){ 00381 if( adc->at(j) >= m_maxFineAdc ){ 00382 gain = DayaBay::FeeGain::kLow; 00383 adc = &(feeChannel->adcLow()); 00384 debug() << "Switching to Low gain ADC since High was saturated" 00385 << endreq; 00386 break; 00387 } 00388 } // end check high gain adc 00389 00390 verbose() << "Ready to readout ADC's" << endreq; 00391 00392 // Find Peak ADC value 00393 int adcPeak = -1; 00394 int adcPeakCycle = 0; 00395 for(int adcCycle = (int)adcFirst; adcCycle < (int)adcLast; ++adcCycle){ 00396 if( adc->at(adcCycle) > adcPeak ){ 00397 // Peak clock cycle will be read out wrt start of the peak finding window 00398 adcPeak = adc->at(adcCycle); 00399 adcPeakCycle = adcCycle-adcFirst; 00400 verbose() << "Found New Max ADC at " << adcPeakCycle << endreq; 00401 } 00402 } 00403 00404 // Compute PreADC value 00405 int preAdc = 0; 00406 adcPedFirst = adcFirst - m_preAdcOffset; 00407 for(int adcCycle = adcPedFirst; adcCycle<adcPedFirst + 4; adcCycle++){ 00408 if(adcCycle < 0) { 00409 verbose() << "Invalid PreADC Cycle " 00410 << adcCycle 00411 << " Using standard baseline value" << endreq; 00412 if(gain == DayaBay::FeeGain::kHigh) preAdc += int(feeSimData->m_adcBaselineHigh); 00413 if(gain == DayaBay::FeeGain::kLow) preAdc += int(feeSimData->m_adcBaselineLow); 00414 } 00415 else preAdc += adc->at(adcCycle); 00416 } 00417 verbose() << "First PreADC cycle in ns: " << adcPedFirst * 25. << endreq; 00418 preAdc = preAdc & 0x0fff; 00419 verbose() << "Reading out adc " << adcPeak 00420 << " at cycle " << adcPeakCycle << endreq; 00421 verbose() << "Reading out preADC " << preAdc << endreq; 00422 00423 adc_out[i] = adcPeak; 00424 adcCycle_out[i] = adcPeakCycle; 00425 adcRange_out[i] = gain; 00426 preAdc_out[i] = preAdc; 00427 00428 } //end if -- check if preceding peak find alg is finished 00429 else { 00430 verbose() << "No peak finding (previous not finished)" << endreq; 00431 // Fill adc vectors with zeros 00432 adc_out[i] = 0; 00433 adcCycle_out[i] = 0; 00434 adcRange_out[i] = 0; 00435 preAdc_out[i] = 0; 00436 } // end else 00437 00438 // TDC will be read out wrt common stop time 00439 tdc_out[i] = tdcStopCycle - tdc_vec[i]; 00440 tdcHitCount_out[i] = nTdc - i; 00441 }// end tdc forloop 00442 00443 // finalize peaking mode variables for current channel 00444 ro_ch->setTdc(tdc_out); 00445 ro_ch->setTdcHitCount(tdcHitCount_out); 00446 ro_ch->setAdc(adc_out); 00447 ro_ch->setAdcCycle(adcCycle_out); 00448 ro_ch->setAdcRange(adcRange_out); 00449 ro_ch->setPedestal(preAdc_out); 00450 } 00451 00452 // Compute variables for waveform readout mode 00453 if ( m_enableWaveformReadout ){ 00454 adcFirst = (int) (double(tdcFirst) * double(DayaBay::AdcCycles)/double(DayaBay::TdcCycles) + 0.5); 00455 adcLast = (int) (double(tdcLast) * double(DayaBay::AdcCycles)/double(DayaBay::TdcCycles) + 0.5); 00456 int adcStopCycle = (int) (double(tdcStopCycle) * double(DayaBay::AdcCycles)/double(DayaBay::TdcCycles) + 0.5); 00457 00458 std::vector<int> waveAdcLow_out; 00459 std::vector<int> waveAdcHigh_out; 00460 std::vector<int> waveAdcCycle_out; 00461 00462 // readout low gain waveform 00463 adc = &(feeChannel->adcLow()); 00464 StatusCode sc = m_waveformTool->readoutWaveform(*adc, adcFirst, adcLast, adcStopCycle, waveAdcLow_out, waveAdcCycle_out); 00465 if( !sc.isSuccess() || waveAdcLow_out.empty() ) { 00466 delete ro_ch; 00467 return 0; 00468 } 00469 waveAdcCycle_out.clear(); 00470 00471 // readout high gain waveform 00472 adc = &(feeChannel->adcHigh()); 00473 sc = m_waveformTool->readoutWaveform(*adc, adcFirst, adcLast, adcStopCycle, waveAdcHigh_out, waveAdcCycle_out); 00474 if( !sc.isSuccess() || waveAdcHigh_out.empty() ){ 00475 delete ro_ch; 00476 return 0; 00477 } 00478 00479 // finalize waveform mode variables for current channel 00480 ro_ch->setWaveAdcLow(waveAdcLow_out); 00481 ro_ch->setWaveAdcHigh(waveAdcHigh_out); 00482 ro_ch->setWaveAdcCycle(waveAdcCycle_out); 00483 } 00484 return ro_ch; 00485 } 00486 00487 // provide mutate to satisfy interface IROsReadoutTool. 00488 StatusCode ROsFeeReadoutTool::mutate(DayaBay::SimReadoutHeader* roHeader, 00489 std::vector<DayaBay::ReadoutTriggerDataPkg*>& trigDataPkg, 00490 const DayaBay::ElecHeader& elecHeader) 00491 { 00492 verbose() << "calling ROsFeeReadoutTool.mutate()" << endreq; 00493 return makeReadouts(roHeader,trigDataPkg,elecHeader); 00494 }