Back to home page

Project CMSSW displayed by LXR

 
 

    


Warning, /RecoLocalCalo/EcalRecProducers/plugins/EcalRecHitBuilderKernels.cu is written in an unsupported language. File is not indexed.

0001 #include <cuda.h>
0002 
0003 #include "CUDADataFormats/EcalRecHitSoA/interface/EcalRecHit.h"
0004 #include "CUDADataFormats/EcalRecHitSoA/interface/EcalUncalibratedRecHit.h"
0005 
0006 #include "EcalRecHitBuilderKernels.h"
0007 #include "KernelHelpers.h"
0008 
0009 namespace ecal {
0010   namespace rechit {
0011 
0012     // uncalibrecHit flags
0013     enum UncalibRecHitFlags {
0014       kGood = -1,  // channel is good (mutually exclusive with other states)  setFlagBit(kGood) reset flags_ to zero
0015       kPoorReco,   // channel has been badly reconstructed (e.g. bad shape, bad chi2 etc.)
0016       kSaturated,  // saturated channel
0017       kOutOfTime,  // channel out of time
0018       kLeadingEdgeRecovered,  // saturated channel: energy estimated from the leading edge before saturation
0019       kHasSwitchToGain6,      // at least one data frame is in G6
0020       kHasSwitchToGain1       // at least one data frame is in G1
0021     };
0022 
0023     // recHit flags
0024     enum RecHitFlags {
0025       RecHitFlags_kGood = 0,  // channel ok, the energy and time measurement are reliable
0026       RecHitFlags_kPoorReco,  // the energy is available from the UncalibRecHit, but approximate (bad shape, large chi2)
0027       RecHitFlags_kOutOfTime,  // the energy is available from the UncalibRecHit (sync reco), but the event is out of time
0028       RecHitFlags_kFaultyHardware,  // The energy is available from the UncalibRecHit, channel is faulty at some hardware level (e.g. noisy)
0029       RecHitFlags_kNoisy,      // the channel is very noisy
0030       RecHitFlags_kPoorCalib,  // the energy is available from the UncalibRecHit, but the calibration of the channel is poor
0031       RecHitFlags_kSaturated,             // saturated channel (recovery not tried)
0032       RecHitFlags_kLeadingEdgeRecovered,  // saturated channel: energy estimated from the leading edge before saturation
0033       RecHitFlags_kNeighboursRecovered,   // saturated/isolated dead: energy estimated from neighbours
0034       RecHitFlags_kTowerRecovered,        // channel in TT with no data link, info retrieved from Trigger Primitive
0035       RecHitFlags_kDead,                  // channel is dead and any recovery fails
0036       RecHitFlags_kKilled,                // MC only flag: the channel is killed in the real detector
0037       RecHitFlags_kTPSaturated,           // the channel is in a region with saturated TP
0038       RecHitFlags_kL1SpikeFlag,           // the channel is in a region with TP with sFGVB = 0
0039       RecHitFlags_kWeird,                 // the signal is believed to originate from an anomalous deposit (spike)
0040       RecHitFlags_kDiWeird,               // the signal is anomalous, and neighbors another anomalous signal
0041       RecHitFlags_kHasSwitchToGain6,      // at least one data frame is in G6
0042       RecHitFlags_kHasSwitchToGain1,      // at least one data frame is in G1
0043       //
0044       RecHitFlags_kUnknown  // to ease the interface with functions returning flags.
0045     };
0046 
0047     // status code
0048     enum EcalChannelStatusCode_Code {
0049       kOk = 0,
0050       kDAC,
0051       kNoLaser,
0052       kNoisy,
0053       kNNoisy,
0054       kNNNoisy,
0055       kNNNNoisy,
0056       kNNNNNoisy,
0057       kFixedG6,
0058       kFixedG1,
0059       kFixedG0,
0060       kNonRespondingIsolated,
0061       kDeadVFE,
0062       kDeadFE,
0063       kNoDataNoTP
0064     };
0065 
0066     __global__ void kernel_create_ecal_rehit(
0067         // configuration
0068         int const* ChannelStatusToBeExcluded,
0069         uint32_t ChannelStatusToBeExcludedSize,
0070         bool const killDeadChannels,
0071         bool const recoverEBIsolatedChannels,
0072         bool const recoverEEIsolatedChannels,
0073         bool const recoverEBVFE,
0074         bool const recoverEEVFE,
0075         bool const recoverEBFE,
0076         bool const recoverEEFE,
0077         float const EBLaserMIN,
0078         float const EELaserMIN,
0079         float const EBLaserMAX,
0080         float const EELaserMAX,
0081         // for flags setting
0082         int const* expanded_v_DB_reco_flags,  // FIXME AM: to be checked
0083         uint32_t const* expanded_Sizes_v_DB_reco_flags,
0084         uint32_t const* expanded_flagbit_v_DB_reco_flags,
0085         uint32_t expanded_v_DB_reco_flagsSize,
0086         uint32_t flagmask,
0087         // conditions
0088         float const* adc2gev,
0089         float const* intercalib,
0090         uint16_t const* status,
0091         float const* apdpnrefs,
0092         float const* alphas,
0093         // input for transparency corrections
0094         float const* p1,
0095         float const* p2,
0096         float const* p3,
0097         edm::TimeValue_t const* t1,
0098         edm::TimeValue_t const* t2,
0099         edm::TimeValue_t const* t3,
0100         // input for linear corrections
0101         float const* lp1,
0102         float const* lp2,
0103         float const* lp3,
0104         edm::TimeValue_t const* lt1,
0105         edm::TimeValue_t const* lt2,
0106         edm::TimeValue_t const* lt3,
0107         // time, used for time dependent corrections
0108         edm::TimeValue_t const event_time,
0109         // input
0110         uint32_t const* did_eb,
0111         uint32_t const* did_ee,
0112         ::ecal::reco::StorageScalarType const* amplitude_eb,  // in adc counts
0113         ::ecal::reco::StorageScalarType const* amplitude_ee,  // in adc counts
0114         ::ecal::reco::StorageScalarType const* time_eb,
0115         ::ecal::reco::StorageScalarType const* time_ee,
0116         ::ecal::reco::StorageScalarType const* chi2_eb,
0117         ::ecal::reco::StorageScalarType const* chi2_ee,
0118         uint32_t const* flags_eb,
0119         uint32_t const* flags_ee,
0120         // output
0121         uint32_t* didEB,
0122         uint32_t* didEE,
0123         ::ecal::reco::StorageScalarType* energyEB,  // in energy [GeV]
0124         ::ecal::reco::StorageScalarType* energyEE,  // in energy [GeV]
0125         ::ecal::reco::StorageScalarType* timeEB,
0126         ::ecal::reco::StorageScalarType* timeEE,
0127         ::ecal::reco::StorageScalarType* chi2EB,
0128         ::ecal::reco::StorageScalarType* chi2EE,
0129         uint32_t* flagBitsEB,
0130         uint32_t* flagBitsEE,
0131         uint32_t* extraEB,
0132         uint32_t* extraEE,
0133         // other
0134         int const nchannels,
0135         uint32_t const nChannelsBarrel,
0136         uint32_t const offsetForHashes) {
0137       //
0138       //    NB: energy   "type_wrapper<reco::StorageScalarType, L>::type" most likely std::vector<float>
0139       //
0140 
0141       for (int ch = threadIdx.x + blockDim.x * blockIdx.x; ch < nchannels; ch += blockDim.x * gridDim.x) {
0142         bool isEndcap = (ch >= nChannelsBarrel);
0143 
0144         int const inputCh = isEndcap ? ch - nChannelsBarrel : ch;
0145 
0146         uint32_t const* didCh = isEndcap ? did_ee : did_eb;
0147 
0148         // arrange to access the right ptrs
0149 #define ARRANGE(var) auto* var = isEndcap ? var##EE : var##EB
0150         ARRANGE(did);
0151         ARRANGE(energy);
0152         ARRANGE(chi2);
0153         ARRANGE(flagBits);
0154         ARRANGE(extra);
0155 #undef ARRANGE
0156 
0157         // only two values, EB or EE
0158         // AM : FIXME : why not using "isBarrel" ?    isBarrel ? adc2gev[0] : adc2gev[1]
0159         float adc2gev_to_use = isEndcap ? adc2gev[1]   // ee
0160                                         : adc2gev[0];  // eb
0161 
0162         // first EB and then EE
0163 
0164         ::ecal::reco::StorageScalarType const* amplitude = isEndcap ? amplitude_ee : amplitude_eb;
0165 
0166         ::ecal::reco::StorageScalarType const* chi2_in = isEndcap ? chi2_ee : chi2_eb;
0167 
0168         uint32_t const* flags_in = isEndcap ? flags_ee : flags_eb;
0169 
0170         // simple copy
0171         did[inputCh] = didCh[inputCh];
0172 
0173         auto const did_to_use = DetId{didCh[inputCh]};
0174 
0175         auto const isBarrel = did_to_use.subdetId() == EcalBarrel;
0176         auto const hashedId = isBarrel ? ecal::reconstruction::hashedIndexEB(did_to_use.rawId())
0177                                        : offsetForHashes + ecal::reconstruction::hashedIndexEE(did_to_use.rawId());
0178 
0179         float const intercalib_to_use = intercalib[hashedId];
0180 
0181         // get laser coefficient
0182         float lasercalib = 1.;
0183 
0184         //
0185         // AM: ideas
0186         //
0187         //    One possibility is to create the map of laser corrections once on CPU
0188         //    for all crystals and push them on GPU.
0189         //    Then only if the LS is different, update the laser correction
0190         //    The variation within a LS is not worth pursuing (<< 0.1% !!)
0191         //    and below the precision we can claim on the laser corrections (right?).
0192         //    This will save quite some time (also for the CPU version?)
0193         //
0194 
0195         int iLM = 1;
0196 
0197         if (isBarrel) {
0198           iLM = ecal::reconstruction::laser_monitoring_region_EB(did_to_use.rawId());
0199         } else {
0200           iLM = ecal::reconstruction::laser_monitoring_region_EE(did_to_use.rawId());
0201         }
0202 
0203         long long t_i = 0, t_f = 0;
0204         float p_i = 0, p_f = 0;
0205         long long lt_i = 0, lt_f = 0;
0206         float lp_i = 0, lp_f = 0;
0207 
0208         // laser
0209         if (event_time >= t1[iLM - 1] && event_time < t2[iLM - 1]) {
0210           t_i = t1[iLM - 1];
0211           t_f = t2[iLM - 1];
0212           p_i = p1[hashedId];
0213           p_f = p2[hashedId];
0214         } else if (event_time >= t2[iLM - 1] && event_time <= t3[iLM - 1]) {
0215           t_i = t2[iLM - 1];
0216           t_f = t3[iLM - 1];
0217           p_i = p2[hashedId];
0218           p_f = p3[hashedId];
0219         } else if (event_time < t1[iLM - 1]) {
0220           t_i = t1[iLM - 1];
0221           t_f = t2[iLM - 1];
0222           p_i = p1[hashedId];
0223           p_f = p2[hashedId];
0224 
0225         } else if (event_time > t3[iLM - 1]) {
0226           t_i = t2[iLM - 1];
0227           t_f = t3[iLM - 1];
0228           p_i = p2[hashedId];
0229           p_f = p3[hashedId];
0230         }
0231 
0232         // linear corrections
0233         if (event_time >= lt1[iLM - 1] && event_time < lt2[iLM - 1]) {
0234           lt_i = lt1[iLM - 1];
0235           lt_f = lt2[iLM - 1];
0236           lp_i = lp1[hashedId];
0237           lp_f = lp2[hashedId];
0238         } else if (event_time >= lt2[iLM - 1] && event_time <= lt3[iLM - 1]) {
0239           lt_i = lt2[iLM - 1];
0240           lt_f = lt3[iLM - 1];
0241           lp_i = lp2[hashedId];
0242           lp_f = lp3[hashedId];
0243         } else if (event_time < lt1[iLM - 1]) {
0244           lt_i = lt1[iLM - 1];
0245           lt_f = lt2[iLM - 1];
0246           lp_i = lp1[hashedId];
0247           lp_f = lp2[hashedId];
0248 
0249         } else if (event_time > lt3[iLM - 1]) {
0250           lt_i = lt2[iLM - 1];
0251           lt_f = lt3[iLM - 1];
0252           lp_i = lp2[hashedId];
0253           lp_f = lp3[hashedId];
0254         }
0255 
0256         // apdpnref and alpha
0257         float apdpnref = apdpnrefs[hashedId];
0258         float alpha = alphas[hashedId];
0259 
0260         // now calculate transparency correction
0261         if (apdpnref != 0 && (t_i - t_f) != 0 && (lt_i - lt_f) != 0) {
0262           long long tt = event_time;  // never subtract two unsigned!
0263           float interpolatedLaserResponse =
0264               p_i / apdpnref + float(tt - t_i) * (p_f - p_i) / (apdpnref * float(t_f - t_i));
0265 
0266           float interpolatedLinearResponse =
0267               lp_i / apdpnref + float(tt - lt_i) * (lp_f - lp_i) / (apdpnref * float(lt_f - lt_i));  // FIXED BY FC
0268 
0269           if (interpolatedLinearResponse > 2.f || interpolatedLinearResponse < 0.1f) {
0270             interpolatedLinearResponse = 1.f;
0271           }
0272           if (interpolatedLaserResponse <= 0.) {
0273             // AM :  how the heck is it possible?
0274             //             interpolatedLaserResponse = 0.0001;
0275             lasercalib = 1.;
0276 
0277           } else {
0278             float interpolatedTransparencyResponse = interpolatedLaserResponse / interpolatedLinearResponse;
0279 
0280             // ... and now this:
0281             lasercalib = 1.f / (std::pow(interpolatedTransparencyResponse, alpha) * interpolatedLinearResponse);
0282           }
0283         }
0284 
0285         //
0286         // Check for channels to be excluded from reconstruction
0287         //
0288         // Default energy not to be updated if "ChannelStatusToBeExcluded"
0289         // Exploited later by the module "EcalRecHitConvertGPU2CPUFormat"
0290         energy[inputCh] = -1;  //un-physical default
0291 
0292         // truncate the chi2
0293         if (chi2_in[inputCh] > 64)
0294           chi2[inputCh] = 64;
0295         else
0296           chi2[inputCh] = chi2_in[inputCh];
0297 
0298         // default values for the flags
0299         flagBits[inputCh] = 0;
0300         extra[inputCh] = 0;
0301 
0302         static const int chStatusMask = 0x1f;
0303         // ChannelStatusToBeExcluded is a "int" then I put "dbstatus" to be the same
0304         int dbstatus = EcalChannelStatusCode_Code((status[hashedId]) & chStatusMask);
0305         if (ChannelStatusToBeExcludedSize != 0) {
0306           bool skip_this_channel = false;
0307           for (int ich_to_check = 0; ich_to_check < ChannelStatusToBeExcludedSize; ich_to_check++) {
0308             if (ChannelStatusToBeExcluded[ich_to_check] == dbstatus) {
0309               skip_this_channel = true;
0310               break;
0311             }
0312           }
0313           if (skip_this_channel) {
0314             // skip this channel
0315             continue;
0316           }
0317         }
0318 
0319         // Take our association map of dbstatuses-> recHit flagbits and return the apporpriate flagbit word
0320 
0321         //
0322         // AM: get the smaller "flagbit_counter" with match
0323         //
0324 
0325         uint32_t temporary_flagBits = 0;
0326 
0327         int iterator_flags = 0;
0328         bool need_to_exit = false;
0329         int flagbit_counter = 0;
0330         while (!need_to_exit) {
0331           iterator_flags = 0;
0332           for (unsigned int i = 0; i != expanded_v_DB_reco_flagsSize; ++i) {
0333             // check the correct "flagbit"
0334             if (expanded_flagbit_v_DB_reco_flags[i] == flagbit_counter) {
0335               for (unsigned int j = 0; j < expanded_Sizes_v_DB_reco_flags[i]; j++) {
0336                 if (expanded_v_DB_reco_flags[iterator_flags] == dbstatus) {
0337                   temporary_flagBits = 0x1 << expanded_flagbit_v_DB_reco_flags[i];
0338                   need_to_exit = true;
0339                   break;  // also from the big loop!!!
0340                 }
0341                 iterator_flags++;
0342               }
0343             } else {
0344               // if not, got to the next bunch directly
0345               iterator_flags += expanded_Sizes_v_DB_reco_flags[i];
0346             }
0347 
0348             if (need_to_exit) {
0349               break;
0350             }
0351           }
0352           flagbit_counter += 1;
0353         }
0354 
0355         flagBits[inputCh] = temporary_flagBits;
0356 
0357         if ((flagmask & temporary_flagBits) && killDeadChannels) {
0358           // skip this channel
0359           continue;
0360         }
0361 
0362         //
0363         // multiply the adc counts with factors to get GeV
0364         //
0365 
0366         //         energy[ch] = amplitude[inputCh] * adc2gev_to_use * intercalib_to_use ;
0367         energy[inputCh] = amplitude[inputCh] * adc2gev_to_use * intercalib_to_use * lasercalib;
0368 
0369         // Time is not saved so far, FIXME
0370         //         time[ch] = time_in[inputCh];
0371 
0372         // NB: calculate the "flagBits extra"  --> not really "flags", but actually an encoded version of energy uncertainty, time unc., ...
0373 
0374         //
0375         // extra packing ...
0376         //
0377 
0378         uint32_t offset;
0379         uint32_t width;
0380         uint32_t value;
0381 
0382         float chi2_temp = chi2[inputCh];
0383         if (chi2_temp > 64)
0384           chi2_temp = 64;
0385         // use 7 bits
0386         uint32_t rawChi2 = lround(chi2_temp / 64. * ((1 << 7) - 1));
0387 
0388         offset = 0;
0389         width = 7;
0390         value = 0;
0391 
0392         uint32_t mask = ((1 << width) - 1) << offset;
0393         value &= ~mask;
0394         value |= (rawChi2 & ((1U << width) - 1)) << offset;
0395 
0396         // rawEnergy is actually "error" !!!
0397         uint32_t rawEnergy = 0;
0398 
0399         // AM: FIXME: this is not propagated currently to the uncalibrecHit collection SOA
0400         //            if you want to store this in "extra", we need first to add it to the uncalibrecHit results
0401         //            then it will be something like the following
0402         //         amplitudeError[inputCh] * adc2gev_to_use * intercalib_to_use * lasercalib
0403         //
0404         //
0405 
0406         float amplitudeError_ch = 0.;  // amplitudeError[ch];
0407 
0408         if (amplitudeError_ch > 0.001) {
0409           static constexpr float p10[] = {1.e-2f, 1.e-1f, 1.f, 1.e1f, 1.e2f, 1.e3f, 1.e4f, 1.e5f, 1.e6f};
0410           int b = amplitudeError_ch < p10[4] ? 0 : 5;
0411           for (; b < 9; ++b)
0412             if (amplitudeError_ch < p10[b])
0413               break;
0414 
0415           uint16_t exponent = b;
0416 
0417           static constexpr float ip10[] = {1.e5f, 1.e4f, 1.e3f, 1.e2f, 1.e1f, 1.e0f, 1.e-1f, 1.e-2f, 1.e-3f, 1.e-4};
0418           uint16_t significand = lround(amplitudeError_ch * ip10[exponent]);
0419           // use 13 bits (3 exponent, 10 significand)
0420           rawEnergy = exponent << 10 | significand;
0421         }
0422 
0423         offset = 8;
0424         width = 13;
0425         // value from last change, ok
0426 
0427         mask = ((1 << width) - 1) << offset;
0428         value &= ~mask;
0429         value |= (rawEnergy & ((1U << width) - 1)) << offset;
0430 
0431         uint32_t jitterErrorBits = 0;
0432         jitterErrorBits = jitterErrorBits & 0xFF;
0433 
0434         offset = 24;
0435         width = 8;
0436         // value from last change, ok
0437 
0438         mask = ((1 << width) - 1) << offset;
0439         value &= ~mask;
0440         value |= (jitterErrorBits & ((1U << width) - 1)) << offset;
0441 
0442         //
0443         // now finally set "extra[ch]"
0444         //
0445         extra[inputCh] = value;
0446 
0447         //
0448         // additional flags setting
0449         //
0450         // using correctly the flags as calculated at the UncalibRecHit stage
0451         //
0452         // Now fill flags
0453 
0454         bool good = true;
0455 
0456         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kLeadingEdgeRecovered))) {
0457           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kLeadingEdgeRecovered));
0458           good = false;
0459         }
0460 
0461         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kSaturated))) {
0462           // leading edge recovery failed - still keep the information
0463           // about the saturation and do not flag as dead
0464           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kSaturated));
0465           good = false;
0466         }
0467 
0468         //
0469         // AM: why do we have two tests one after the other checking almost the same thing???
0470         // Please clean up the code, ... also the original one!
0471         //
0472         // uncalibRH.isSaturated() --->
0473         //
0474         //                                   bool EcalUncalibratedRecHit::isSaturated() const {
0475         //                                     return EcalUncalibratedRecHit::checkFlag(kSaturated);
0476         //                                   }
0477         //
0478         //
0479 
0480         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kSaturated))) {
0481           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kSaturated));
0482           good = false;
0483         }
0484 
0485         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kOutOfTime))) {
0486           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kOutOfTime));
0487           good = false;
0488         }
0489         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kPoorReco))) {
0490           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kPoorReco));
0491           good = false;
0492         }
0493         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kHasSwitchToGain6))) {
0494           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kHasSwitchToGain6));
0495         }
0496         if (flags_in[inputCh] & (0x1 << (UncalibRecHitFlags::kHasSwitchToGain1))) {
0497           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kHasSwitchToGain1));
0498         }
0499 
0500         if (good) {
0501           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kGood));
0502         }
0503 
0504         if ((isBarrel && (lasercalib < EBLaserMIN || lasercalib > EBLaserMAX)) ||
0505             (!isBarrel && (lasercalib < EELaserMIN || lasercalib > EELaserMAX))) {
0506           flagBits[inputCh] |= (0x1 << (RecHitFlags::RecHitFlags_kPoorCalib));
0507         }
0508 
0509         // recover, killing, and other stuff
0510 
0511         //
0512         // Structure:
0513         //  EB
0514         //  EE
0515         //
0516         //
0517         //  - single MVA
0518         //  - democratic sharing
0519         //  - kill all the other cases
0520         //
0521 
0522         bool is_Single = false;
0523         bool is_FE = false;
0524         bool is_VFE = false;
0525 
0526         bool is_recoverable = false;  // DetIdToBeRecovered
0527 
0528         if (dbstatus == 10 || dbstatus == 11 || dbstatus == 12) {
0529           is_recoverable = true;
0530         }
0531 
0532         if (is_recoverable) {
0533           if (dbstatus == EcalChannelStatusCode_Code::kDeadVFE) {
0534             is_VFE = true;
0535           } else if (dbstatus == EcalChannelStatusCode_Code::kDeadVFE) {
0536             is_FE = true;
0537           } else {
0538             is_Single = true;
0539           }
0540 
0541           // EB
0542           if (isBarrel) {
0543             if (is_Single || is_FE || is_VFE) {
0544               // single MVA
0545               if (is_Single && (recoverEBIsolatedChannels || !killDeadChannels)) {
0546               }
0547               // decmocratic sharing
0548               else if (is_FE && (recoverEBFE || !killDeadChannels)) {
0549               }
0550               // kill all the other cases
0551               else {
0552                 energy[inputCh] = 0.;  // Need to set also the flags ...
0553               }
0554             }
0555           }
0556           // EE
0557           else {
0558             if (is_Single || is_FE || is_VFE) {
0559               // single MVA
0560               if (is_Single && (recoverEBIsolatedChannels || !killDeadChannels)) {
0561               }
0562               // decmocratic sharing
0563               else if (is_FE && (recoverEBFE || !killDeadChannels)) {
0564                 //
0565                 //  Code is definitely too long ...
0566                 //
0567 
0568               }
0569               // kill all the other cases
0570               else {
0571                 energy[inputCh] = 0.;  // Need to set also the flags ...
0572               }
0573             }
0574           }
0575         }
0576 
0577       }  // end channel
0578     }
0579 
0580     // host version, to be called by the plugin
0581     void create_ecal_rehit(EventInputDataGPU const& eventInputGPU,
0582                            EventOutputDataGPU& eventOutputGPU,
0583                            //     eventDataForScratchGPU_,
0584                            ConditionsProducts const& conditions,
0585                            ConfigurationParameters const& configParameters,
0586                            uint32_t const nChannelsBarrel,
0587                            edm::TimeValue_t const event_time,
0588                            cudaStream_t cudaStream) {
0589       int nchannels = eventInputGPU.ebUncalibRecHits.size + eventInputGPU.eeUncalibRecHits.size;
0590 
0591       unsigned int nchannels_per_block = 16;
0592       unsigned int threads_min = nchannels_per_block;
0593       unsigned int blocks_min = (nchannels + threads_min - 1) / threads_min;  // TEST : to be optimized (AM)
0594 
0595       //
0596       // kernel create rechit
0597       //
0598 
0599       kernel_create_ecal_rehit<<<blocks_min, threads_min, 0, cudaStream>>>(
0600           // configuration
0601           configParameters.ChannelStatusToBeExcluded,
0602           configParameters.ChannelStatusToBeExcludedSize,
0603           configParameters.killDeadChannels,
0604           configParameters.recoverEBIsolatedChannels,
0605           configParameters.recoverEEIsolatedChannels,
0606           configParameters.recoverEBVFE,
0607           configParameters.recoverEEVFE,
0608           configParameters.recoverEBFE,
0609           configParameters.recoverEEFE,
0610           configParameters.EBLaserMIN,
0611           configParameters.EELaserMIN,
0612           configParameters.EBLaserMAX,
0613           configParameters.EELaserMAX,
0614           // for flags setting
0615           configParameters.expanded_v_DB_reco_flags,
0616           configParameters.expanded_Sizes_v_DB_reco_flags,
0617           configParameters.expanded_flagbit_v_DB_reco_flags,
0618           configParameters.expanded_v_DB_reco_flagsSize,
0619           configParameters.flagmask,
0620           // conditions
0621           conditions.ADCToGeV.adc2gev,
0622           conditions.Intercalib.values,
0623           conditions.ChannelStatus.status,
0624           conditions.LaserAPDPNRatiosRef.values,
0625           conditions.LaserAlphas.values,
0626           // input for transparency corrections
0627           conditions.LaserAPDPNRatios.p1,
0628           conditions.LaserAPDPNRatios.p2,
0629           conditions.LaserAPDPNRatios.p3,
0630           conditions.LaserAPDPNRatios.t1,
0631           conditions.LaserAPDPNRatios.t2,
0632           conditions.LaserAPDPNRatios.t3,
0633           // input for linear corrections
0634           conditions.LinearCorrections.p1,
0635           conditions.LinearCorrections.p2,
0636           conditions.LinearCorrections.p3,
0637           conditions.LinearCorrections.t1,
0638           conditions.LinearCorrections.t2,
0639           conditions.LinearCorrections.t3,
0640           // time, used for time dependent corrections
0641           event_time,
0642           // input
0643           eventInputGPU.ebUncalibRecHits.did.get(),
0644           eventInputGPU.eeUncalibRecHits.did.get(),
0645           eventInputGPU.ebUncalibRecHits.amplitude.get(),
0646           eventInputGPU.eeUncalibRecHits.amplitude.get(),
0647           eventInputGPU.ebUncalibRecHits.jitter.get(),
0648           eventInputGPU.eeUncalibRecHits.jitter.get(),
0649           eventInputGPU.ebUncalibRecHits.chi2.get(),
0650           eventInputGPU.eeUncalibRecHits.chi2.get(),
0651           eventInputGPU.ebUncalibRecHits.flags.get(),
0652           eventInputGPU.eeUncalibRecHits.flags.get(),
0653           // output
0654           eventOutputGPU.recHitsEB.did.get(),
0655           eventOutputGPU.recHitsEE.did.get(),
0656           eventOutputGPU.recHitsEB.energy.get(),
0657           eventOutputGPU.recHitsEE.energy.get(),
0658           eventOutputGPU.recHitsEB.time.get(),
0659           eventOutputGPU.recHitsEE.time.get(),
0660           eventOutputGPU.recHitsEB.chi2.get(),
0661           eventOutputGPU.recHitsEE.chi2.get(),
0662           eventOutputGPU.recHitsEB.flagBits.get(),
0663           eventOutputGPU.recHitsEE.flagBits.get(),
0664           eventOutputGPU.recHitsEB.extra.get(),
0665           eventOutputGPU.recHitsEE.extra.get(),
0666           // other
0667           nchannels,
0668           nChannelsBarrel,
0669           conditions.offsetForHashes);
0670     }
0671 
0672   }  // namespace rechit
0673 
0674 }  // namespace ecal