00001 #include "TGet4HitUnpacked.h" 00002 00003 TGet4HitUnpacked::TGet4HitUnpacked( void ) 00004 { 00005 // flags which indicated whether the edge data are set 00006 // are cleared 00007 m_bLeadingEdgeSet = kFALSE; 00008 m_bTrailingEdgeSet = kFALSE; 00009 00010 uc_get4 = 0; 00011 uc_channel = 0; 00012 00013 u_EpochCycleLeading = 0; 00014 u_EpochNoLeadingEdge = 0; 00015 u_TsLeadingEdge = 0; 00016 00017 u_EpochCycleTrailing = 0; 00018 u_EpochNoTrailingEdge = 0; 00019 u_TsTrailingEdge = 0; 00020 } 00021 00022 // Copy constructor, needed for memory reason? 00023 TGet4HitUnpacked & TGet4HitUnpacked::operator=( const TGet4HitUnpacked & hitOriginal ) 00024 { 00025 if( this != &hitOriginal ) 00026 { 00027 this->Clear(); 00028 uc_get4 = hitOriginal.GetGet4Index(); 00029 uc_channel = hitOriginal.GetChannel(); 00030 00031 m_bLeadingEdgeSet = hitOriginal.IsLeadingSet(); 00032 if( kTRUE == m_bLeadingEdgeSet ) 00033 { 00034 u_EpochCycleLeading = hitOriginal.GetEpochCycleLeading(); 00035 u_EpochNoLeadingEdge = hitOriginal.GetEpochLeading(); 00036 u_TsLeadingEdge = hitOriginal.GetTsLeading(); 00037 } 00038 00039 m_bTrailingEdgeSet = hitOriginal.IsLeadingSet(); 00040 if( kTRUE == m_bTrailingEdgeSet ) 00041 { 00042 u_EpochCycleTrailing = hitOriginal.GetEpochCycleTrailing(); 00043 u_EpochNoTrailingEdge = hitOriginal.GetEpochTrailing(); 00044 u_TsTrailingEdge = hitOriginal.GetTsTrailing(); 00045 } 00046 00047 } 00048 return *this; 00049 } 00050 00051 void TGet4HitUnpacked::ClearHit( void ) 00052 { 00053 // flags which indicated whether the edge data are set 00054 // are cleared 00055 m_bLeadingEdgeSet = kFALSE; 00056 m_bTrailingEdgeSet = kFALSE; 00057 00058 uc_get4 = 0; 00059 uc_channel = 0; 00060 00061 u_EpochCycleLeading = 0; 00062 u_EpochNoLeadingEdge = 0; 00063 u_TsLeadingEdge = 0; 00064 00065 u_EpochCycleTrailing = 0; 00066 u_EpochNoTrailingEdge = 0; 00067 u_TsTrailingEdge = 0; 00068 } 00069 00070 00071 #ifndef ROC_GET4_BUILDEVENT 00072 // Definition check because ROOT did not aknowledge roc::message in 00073 // old versions 00074 // Maybe unnecessary 00075 void TGet4HitUnpacked::SetMessage( roc::Message &msgNewEdge, ULong64_t uEpoch, UInt_t epochCycleRaw ) 00076 { 00077 // first it is checked whether this is a GET4 data event. 00078 if ( msgNewEdge.getMessageType() == roc::MSG_GET4 ) 00079 { 00080 // getting the edge flag 00081 UInt_t uEdge = msgNewEdge.getGet4Edge(); 00082 if ( uEdge == 0 ) 00083 { 00084 Bool_t bLeadingErrorSet = kFALSE; 00085 if ( m_bLeadingEdgeSet ) 00086 // Error: The leading edge is already set. 00087 bLeadingErrorSet = kTRUE; // => Continue however 00088 00089 // storing the data 00090 m_bLeadingEdgeSet = kTRUE; 00091 00092 uc_get4 = msgNewEdge.getGet4Number(); 00093 uc_channel = msgNewEdge.getGet4ChNum(); 00094 u_EpochNoLeadingEdge = uEpoch; 00095 u_EpochCycleLeading = epochCycleRaw; 00096 u_TsLeadingEdge = msgNewEdge.getGet4Ts(); 00097 00098 if ( m_bTrailingEdgeSet ) 00099 { 00100 // Time Gating 00101 if( TIME_GATE*EPOCH_IN_NS < this->GetTOT() ) 00102 { 00103 Double_t temptot = this->GetTOT(); 00104 m_bTrailingEdgeSet = kFALSE; 00105 // throw CEOutOfTimeGate(); 00106 throw CEOutOfTimeGateDetail( temptot ); 00107 } 00108 00109 if( this->GetTOT() < -0.00001) 00110 { 00111 Double_t temptot = this->GetTOT(); 00112 m_bTrailingEdgeSet = kFALSE; 00113 // throw CEGivesNegativeToT(); 00114 throw CEGivesNegativeToTDetail( temptot ); 00115 } 00116 } 00117 00118 if ( kTRUE == bLeadingErrorSet ) 00119 throw CELeadingEdgeAlreadySet(); 00120 } 00121 else 00122 { 00123 // Disable this check as it could solve pb 00124 // when the signal gets down for a short time 00125 // under threshold 00126 /* 00127 if ( m_bTrailingEdgeSet ) 00128 // Error: The trailing edge is already set. 00129 throw CETrailingEdgeAlreadySet(); 00130 */ 00131 00132 // storing the data 00133 m_bTrailingEdgeSet = kTRUE; 00134 00135 uc_get4 = msgNewEdge.getGet4Number(); 00136 uc_channel = msgNewEdge.getGet4ChNum(); 00137 u_EpochNoTrailingEdge = uEpoch; 00138 u_EpochCycleTrailing = epochCycleRaw; 00139 u_TsTrailingEdge = msgNewEdge.getGet4Ts(); 00140 00141 if ( m_bLeadingEdgeSet ) 00142 { 00143 // Time Gating 00144 if( TIME_GATE*EPOCH_IN_NS < this->GetTOT() ) 00145 { 00146 Double_t temptot = this->GetTOT(); 00147 m_bLeadingEdgeSet = kFALSE; 00148 // throw CEOutOfTimeGate(); 00149 throw CEOutOfTimeGateDetail( temptot ); 00150 } 00151 00152 // Should never happen, bad messages! 00153 if( this->GetTOT() < -0.00001) 00154 { 00155 Double_t temptot = this->GetTOT(); 00156 m_bLeadingEdgeSet = kFALSE; 00157 // throw CEGivesNegativeToT(); 00158 throw CEGivesNegativeToTDetail( temptot ); 00159 } 00160 } 00161 } 00162 } 00163 else 00164 { 00165 throw CENoGET4DataEvent(msgNewEdge.getMessageType()); 00166 } 00167 } 00168 #endif // ROC_GET4_BUILDEVENT 00169 00170 Bool_t TGet4HitUnpacked::Complete( void ) const 00171 { 00172 // The hit information is complete when leading and 00173 // trailing edge information are set. 00174 return m_bLeadingEdgeSet && m_bTrailingEdgeSet; 00175 } 00176 00177 Double_t TGet4HitUnpacked::GetTOT( void ) const 00178 { 00179 // calculation of time over threshold is only possible 00180 // if the hit information is complete. 00181 if ( Complete() ) 00182 { 00183 // Time over threshold is the difference between timestamps of 00184 // trailing and leading edge multiplied by 0.05 ns. 00185 Double_t dToT = BIN_SIZE_IN_NS * (Double_t) ( (Double_t) u_TsTrailingEdge - 00186 (Double_t)u_TsLeadingEdge ); 00187 // When leading and trailing edge are not in the same epoch 00188 // the time over threshold has to be corrected 00189 if ( u_EpochNoLeadingEdge != u_EpochNoTrailingEdge ) 00190 { 00191 if( u_EpochCycleLeading != u_EpochCycleTrailing ) 00192 { 00193 dToT += EPOCH_IN_NS * (Double_t) ( (Double_t)u_EpochNoTrailingEdge - 00194 (Double_t)u_EpochNoLeadingEdge + 00195 (Double_t)CYCLE_IN_EPOCHS * (Double_t) ( (Double_t)u_EpochCycleTrailing - 00196 (Double_t)u_EpochCycleLeading ) ); 00197 } 00198 else 00199 { 00200 dToT += EPOCH_IN_NS * (Double_t) ( (Double_t)u_EpochNoTrailingEdge - 00201 (Double_t)u_EpochNoLeadingEdge ); 00202 } 00203 } 00204 // returns tot in ns. 00205 return dToT; 00206 } 00207 else 00208 throw CEHitIsNotComplete(); 00209 } 00210 Long64_t TGet4HitUnpacked::GetRawTOT( void ) const 00211 { 00212 // calculation of time over threshold is only possible 00213 // if the hit information is complete. 00214 if ( Complete() ) 00215 { 00216 // Time over threshold is the difference between timestamps of 00217 // trailing and leading edge multiplied by 0.05 ns. 00218 Long64_t iToT = (Int_t) ( (Int_t) u_TsTrailingEdge - 00219 (Int_t)u_TsLeadingEdge ); 00220 // When leading and trailing edge are not in the same epoch 00221 // the time over threshold has to be corrected 00222 if ( u_EpochNoLeadingEdge != u_EpochNoTrailingEdge ) 00223 { 00224 if( u_EpochCycleLeading != u_EpochCycleTrailing ) 00225 { 00226 iToT += EPOCH_IN_BINS * (Long64_t) ( (Long64_t)u_EpochNoTrailingEdge - 00227 (Long64_t)u_EpochNoLeadingEdge + 00228 CYCLE_IN_EPOCHS * (Int_t) ( (Int_t)u_EpochCycleTrailing - 00229 (Int_t)u_EpochCycleLeading ) ); 00230 } 00231 else 00232 { 00233 iToT += EPOCH_IN_BINS * (Long64_t) ( (Long64_t)u_EpochNoTrailingEdge - 00234 (Long64_t)u_EpochNoLeadingEdge ); 00235 } 00236 } 00237 // returns tot in bin. 00238 return iToT; 00239 } 00240 else 00241 throw CEHitIsNotComplete(); 00242 } 00243 00244 Double_t TGet4HitUnpacked::Spacing( const TGet4HitUnpacked &hitFollowing ) const 00245 { 00246 // calculation of pulse spacing is only possible 00247 // if the hit information of both hits is complete. 00248 if ( Complete() && hitFollowing.Complete() ) 00249 { 00250 // calculation is the same like for time over threshold 00251 Double_t dSpacing = BIN_SIZE_IN_NS * 00252 (Double_t) ( (Double_t)hitFollowing.u_TsLeadingEdge - 00253 (Double_t)u_TsLeadingEdge ); 00254 if ( u_EpochNoLeadingEdge != hitFollowing.u_EpochNoLeadingEdge ) 00255 { 00256 dSpacing += EPOCH_IN_NS * (Double_t) ( (Double_t)hitFollowing.u_EpochNoLeadingEdge - 00257 (Double_t)u_EpochNoLeadingEdge ); 00258 if( u_EpochCycleLeading != hitFollowing.u_EpochCycleLeading ) 00259 { 00260 dSpacing += EPOCH_IN_NS * (Double_t)CYCLE_IN_EPOCHS 00261 * (Double_t) ( (Double_t)hitFollowing.u_EpochCycleLeading - 00262 (Double_t)u_EpochCycleLeading ) ; 00263 } 00264 } 00265 // returns pulse spacing in ns. 00266 return dSpacing; 00267 } 00268 else 00269 throw CEHitIsNotComplete(); 00270 } 00271 00272 Int_t TGet4HitUnpacked::CyclesDiff( const TGet4HitUnpacked &hitFollowing ) const 00273 { 00274 return (Int_t) ( (Int_t)hitFollowing.u_EpochCycleLeading - (Int_t)u_EpochCycleLeading ) ; 00275 } 00276 Int_t TGet4HitUnpacked::EpochsDiff( const TGet4HitUnpacked &hitFollowing ) const 00277 { 00278 return (Int_t) ( (Long64_t)hitFollowing.u_EpochNoLeadingEdge - (Long64_t)u_EpochNoLeadingEdge ) ; 00279 } 00280 00281 UChar_t TGet4HitUnpacked::GetGet4Index() const 00282 { 00283 return uc_get4; 00284 } 00285 UChar_t TGet4HitUnpacked::GetChannel() const 00286 { 00287 return uc_channel; 00288 } 00289 UInt_t TGet4HitUnpacked::GetFullChan() const 00290 { 00291 return ((UInt_t)uc_get4)*4 + (UInt_t)uc_channel; 00292 } 00293 UInt_t TGet4HitUnpacked::GetEpochCycleLeading() const 00294 { 00295 return u_EpochCycleLeading; 00296 } 00297 ULong64_t TGet4HitUnpacked::GetEpochLeading() const 00298 { 00299 return u_EpochNoLeadingEdge; 00300 } 00301 UInt_t TGet4HitUnpacked::GetTsLeading() const 00302 { 00303 return u_TsLeadingEdge; 00304 } 00305 UInt_t TGet4HitUnpacked::GetEpochCycleTrailing() const 00306 { 00307 return u_EpochCycleTrailing; 00308 } 00309 ULong64_t TGet4HitUnpacked::GetEpochTrailing() const 00310 { 00311 return u_EpochNoTrailingEdge; 00312 } 00313 UInt_t TGet4HitUnpacked::GetTsTrailing() const 00314 { 00315 return u_TsTrailingEdge; 00316 } 00317 ULong64_t TGet4HitUnpacked::GetFullTime() const 00318 { 00319 return ( ( (ULong64_t) u_EpochNoLeadingEdge << 19) | (ULong64_t)(u_TsLeadingEdge & 0x7ffff) ) / 20 + 512; 00320 } 00321 ULong64_t TGet4HitUnpacked::GetFullTimeSeconds() const 00322 { 00323 return ( ( ((ULong64_t) u_EpochNoLeadingEdge << 19) | (ULong64_t)(u_TsLeadingEdge & 0x7ffff) ) / 20 + 512 ) 00324 / (ULong64_t)1000000000; 00325 } 00326 Bool_t TGet4HitUnpacked::IsLeadingSet() const 00327 { 00328 return m_bLeadingEdgeSet; 00329 } 00330 Bool_t TGet4HitUnpacked::IsTrailingSet() const 00331 { 00332 return m_bTrailingEdgeSet; 00333 } 00334 00335 00336 void TGet4HitUnpacked::SetGet4Index(UChar_t get4_indexIn) 00337 { 00338 uc_get4 = get4_indexIn; 00339 return ; 00340 } 00341 void TGet4HitUnpacked::SetChannel(UChar_t channelIn) 00342 { 00343 uc_channel = channelIn; 00344 return ; 00345 } 00346 void TGet4HitUnpacked::SetFullChan(UInt_t fullChanIn) 00347 { 00348 uc_get4 = (UChar_t)(fullChanIn/4); 00349 uc_channel = (UChar_t)(fullChanIn%4); 00350 return ; 00351 } 00352 // Used normally only for EXT_SYNC messages 00353 void TGet4HitUnpacked::SetEpochLeading(ULong64_t epochLeadingEdgeIn, UInt_t epochCycleIn) 00354 { 00355 m_bLeadingEdgeSet = kTRUE; 00356 m_bTrailingEdgeSet = kTRUE; 00357 u_EpochNoLeadingEdge = epochLeadingEdgeIn; 00358 u_EpochCycleLeading = epochCycleIn; 00359 return ; 00360 } 00361 void TGet4HitUnpacked::SetTsLeading(UInt_t tsLeadingIn) 00362 { 00363 u_TsLeadingEdge = tsLeadingIn; 00364 return ; 00365 } 00366 00367 Long64_t TGet4HitUnpacked::EpochEdgesDiff() 00368 { 00369 // Just return the distance in terms of Epochs nb between the 2 00370 // edge messages 00371 if ( this->Complete() ) 00372 return ((Long64_t)u_EpochNoTrailingEdge - (Long64_t)u_EpochNoLeadingEdge 00373 + CYCLE_IN_EPOCHS * (Int_t) ( (Int_t)u_EpochCycleTrailing - 00374 (Int_t)u_EpochCycleLeading ) ); 00375 else 00376 throw CEHitIsNotComplete(); 00377 } 00378 00379 00380 /* This is the function used to sort Hits in a list in 00381 * function TimeOrderBlock 00382 * For this, it compares 00383 * 1) The epoch index cycles 00384 * 2) The epoch indexes 00385 * 3) the leading edge timestamps 00386 */ 00387 bool TGet4HitUnpacked::operator<(const TGet4HitUnpacked &rhs) const 00388 { 00389 // Epoch counter reset between the 2 hits ? 00390 if( GetEpochCycleLeading() < rhs.GetEpochCycleLeading() ) 00391 return true; 00392 else if( GetEpochCycleLeading() > rhs.GetEpochCycleLeading() ) 00393 return false; 00394 // Same cycle => Clock counter reset between the 2 hits ? (epoch 00395 else if( GetEpochLeading() < rhs.GetEpochLeading() ) 00396 return true; 00397 else if( GetEpochLeading() > rhs.GetEpochLeading() ) 00398 return false; 00399 // Same cycle and same epoch! 00400 else if( 0.0 <= Spacing(rhs) ) 00401 return true; 00402 else return false; 00403 }