// File: hrichdigitizer.cc // // Author: Laura Fabbietti // Last update by Laura Fabbietti: 03/04/17 22:02:50 // // //_HADES_CLASS_DESCRIPTION ///////////////////////////////////////////////////////////////////////////// //_______________________________________________________ // HRichDigitizer // // For each digitized pad the corresponding track numbers of the // direct hits and photons are stored in a linear category // (catRichTrack<-HRichTrack) that is made sortable by the pad address. // Each pad object of the HRichCalSim class has 2 members, nTrack1, nTrack2, // that give the indexes of the first and the last track numbers in the linear // category (catRichTrack) corresponding to a pad. // This method allows to store as many particle track numbers as the pad // " sees ". // here are listed the values of some useful variables // # means non costant value. // Each value refers to the 1 fired pad. // // realID=gHades->getEmbeddingRealTrackId() // // track Number Flag energy // Cheren. Phot. # 0 # // Feedback Phot. -5 0 0 // Direct Hits # 1 0 // Noise Hits 0 0 0 // REAL Hits (embedding) realID 0 0 //--------------------------------------------------------- // // // ----------------------- ------------- // | HRichUnpackerCal99 | | HGeantRich | // | (embedding mode) | \ ------------- // | | \ || // ----------------------- \ || input to digitizer // \ \/ // ------------- read real ------------------ // | HRichCalSim | ------------> | | // ------------- <----------- | | // | HRichDigitizer | // ------------- | | // | HRichTrack | <----------- | | // ------------- ------------------ // write output // // In the case of TRACK EMBEDDING of simulated tracks into // experimental data the real data are written by the HRichUnpackerCal99 into // HRichCalSim category. The real hits are taken into // account by the digitizer (adding of charges, adding track numbers to HRichTrack). // The embedding mode is recognized automatically by analyzing the // gHades->getEmbeddingMode() flag. // Mode ==0 means no embedding // ==1 realistic embedding (first real or sim hit makes the game) // ==2 keep GEANT tracks (as 1, but GEANT track numbers will always // win against real data. besides the tracknumber the output will // be the same as in 1) // // //////////////////////////////////////////////////////////////////////////// using namespace std; #include "hrichcalparcell.h" #include "hrichdigitizer.h" #include #include "hevent.h" #include "hmatrixcatiter.h" #include "hgeantrich.h" #include "hcategory.h" #include "hlinearcatiter.h" #include "hlocation.h" #include "hrichdigitisationpar.h" #include "hrichgeometrypar.h" #include "hrichanalysispar.h" #include "hdebug.h" #include "hades.h" #include "hrichpad.h" #include "hrichwiresignal.h" #include "hspectrometer.h" #include "hrichdetector.h" #include "hruntimedb.h" #include "hrichcalpar.h" #include "hrichcalsim.h" #include "richdef.h" #include "hrichtrack.h" #include #include #include #include #include #include "hrichpadfilter.h" #include "hrichanalysissim.h" #include ClassImp(HRichDigitizer) //---------------------------------------------------------------------------- HRichDigitizer::HRichDigitizer(Text_t *name, Text_t *title,Bool_t kNoise,Bool_t oem) : HReconstructor(name,title) { fCerIter = NULL; fDirIter = NULL; fTrackIter = NULL; fCalIter = NULL; fCerInputCat = NULL; fDirInputCat = NULL; fOutputCat = NULL; fTrackOutputCat = NULL; for (Int_t i = 0; i < 9; i++) fDigitPadMatrix[i] = 0.0F; for (Int_t i = 0; i < 1000; i++) noiseCharge[i] = 0.0F; for (Int_t i = 0; i < 6; i++) countPhotSec[i] = 0; fQupper = 0.0F; fChargePerChannel = 0.0F; fChargeScaling = 1.0F; fSigmaValue = 0.0F; fMeanPad = 0.0F; fSigmaPad = 0.0F; fFloatMean = 0.0F; fCharge = 0.0F; countNoisePad = 0; fYShift = 0.0F; isActiveNoise = 0; fFactor1 = 0.0F; fFactor2 = 0.0F; fParam1 = 0.0F; fParam2 = 0.0F; fFactor1Sig = 0.0F; fFactor2Sig = 0.0F; a1 = 0.0F; a2 = 0.0F; b1 = 0.0F; b2 = 0.0F; cont=0; if(kNoise) isActiveNoise = 1; else isActiveNoise = 0; // event embedding is always with noise off! if(gHades->getEmbeddingMode()>0) isActiveNoise = 0; if(oem) isOEM = 1; else isOEM = 0; ga = new TF1("ga","[0]*exp([1]*(x-[2])*(x-[2]))",-10,10); } //============================================================================ //---------------------------------------------------------------------------- HRichDigitizer::HRichDigitizer() { fCerIter = NULL; fDirIter = NULL; fTrackIter = NULL; fCalIter = NULL; fCerInputCat = NULL; fDirInputCat = NULL; fOutputCat = NULL; fTrackOutputCat = NULL; for (Int_t i = 0; i < 9; i++) fDigitPadMatrix[i] = 0.0F; for (Int_t i = 0; i < 1000; i++) noiseCharge[i] = 0.0F; fQupper = 0.0F; fChargePerChannel = 0.0F; fChargeScaling = 1.0F; fSigmaValue = 0.0F; fYShift = 0.0F; fMeanPad = 0.0F; fSigmaPad = 0.0F; fFloatMean = 0.0F; fCharge = 0.0F; countNoisePad = 0; fFactor1 = 0.0F; fFactor2 = 0.0F; fParam1 = 0.0F; fParam2 = 0.0F; fFactor1Sig = 0.0F; fFactor2Sig = 0.0F; param21 = 0.0F; param11 = 0.0F; a1 = 0.0F; a2 = 0.0F; b1 = 0.0F; b2 = 0.0F; // event embedding is always with noise off! if(gHades->getEmbeddingMode()>0) isActiveNoise = 0; } //============================================================================ //---------------------------------------------------------------------------- HRichDigitizer::~HRichDigitizer() { if (fCerIter) delete fCerIter; if (fDirIter) delete fDirIter; if (fTrackIter) delete fTrackIter; if (fCalIter) delete fCalIter; fChargeOnWireList.Delete(); fTrackNumberList.Delete(); } //============================================================================ //---------------------------------------------------------------------------- Bool_t HRichDigitizer::init() { lNrEvent = 0; fDigitisationPar = NULL; fGeometryPar = NULL; if(gHades->getEmbeddingMode()>0) isActiveNoise = 0; HCategory *pCat; HRichDetector *pRichDet = (HRichDetector*)gHades->getSetup() ->getDetector("Rich"); HRuntimeDb* rtdb=gHades->getRuntimeDb(); if(isActiveNoise){ cout<<"------------------------------------------------------"<getContainer("RichCalPar"); if (!pCalPar) { Error("HRichDigitizer::init()","noise mode: no calibration par supplied"); } setCalPar(pCalPar); } else { HRichCalPar *pCalPar = NULL; setCalPar(pCalPar); cout<<"------------------------------------------------------"<getContainer("RichGeometryParameters"); if (pGeomPar == NULL) { pGeomPar = new HRichGeometryPar; rtdb->addContainer(pGeomPar); } setGeometryPar(pGeomPar); if (pGeomPar == NULL) return kFALSE; HRichDigitisationPar *pDigitPar = (HRichDigitisationPar*)rtdb->getContainer("RichDigitisationParameters"); if (pDigitPar == NULL) { pDigitPar = new HRichDigitisationPar; rtdb->addContainer(pDigitPar); } setDigitisationPar(pDigitPar); if (pDigitPar == NULL) return kFALSE; pCat = gHades->getCurrentEvent()->getCategory(catRichGeantRaw); if (pCat) setCerInputCat(pCat); else Error("Digitizer init","no Cherenkov photon cat"); fCerIter = (HIterator*)getCerInputCat()->MakeIterator(); pCat = gHades->getCurrentEvent()->getCategory(catRichGeantRaw+1); if (pCat) setDirInputCat(pCat); else Error("Digitizer init","no direct hits cat"); fDirIter = (HIterator*)getDirInputCat()->MakeIterator(); pCat = gHades->getCurrentEvent()->getCategory(catRichTrack); if (pCat == NULL) { pCat = pRichDet->buildCategory(catRichTrack); if (pCat == NULL) return kFALSE; else gHades->getCurrentEvent()->addCategory(catRichTrack, pCat, "Rich"); } setTrackOutputCat(pCat); fTrackIter = (HIterator*)getTrackOutputCat()->MakeIterator(); pCat = gHades->getCurrentEvent()->getCategory(catRichCal); if (pCat == NULL) { pCat = pRichDet->buildMatrixCat("HRichCalSim",1); // ETLF 02/23/2000 if (pCat == NULL) return kFALSE; else gHades->getCurrentEvent()->addCategory(catRichCal, pCat, "Rich"); } setOutputCat(pCat); fCalIter = (HIterator*)getOutputCat()->MakeIterator(); return kTRUE; } //============================================================================ Bool_t HRichDigitizer::reinit(){ ((HRichDigitisationPar*)fDigitisationPar)->printParam(); fYShift = ((HRichGeometryPar*)fGeometryPar)->getSectorShift(); fYShift = fYShift/cos(20./57.3); distWirePads = ((HRichGeometryPar*)fGeometryPar)->getDistWiresPads(); fQupper = ((HRichDigitisationPar*)fDigitisationPar)->getQupper(); fSigmaValue = ((HRichDigitisationPar*)fDigitisationPar)->getSigmaValue(); fIncreaseNoise = ((HRichDigitisationPar*)fDigitisationPar) ->getIncreaseNoise(); fChargePerChannel = ((HRichDigitisationPar*)fDigitisationPar)->getChargePerChannel(); fChargeScaling = ((HRichDigitisationPar*)fDigitisationPar)->getChargeScaling(); fFactor1 = ((HRichDigitisationPar*)fDigitisationPar)->getFactor1(); fFactor2 = ((HRichDigitisationPar*)fDigitisationPar)->getFactor2(); fParam1 = ((HRichDigitisationPar*)fDigitisationPar)->getParameter1(); fParam2 = ((HRichDigitisationPar*)fDigitisationPar)->getParameter2(); fFactor1Sig = ((HRichDigitisationPar*)fDigitisationPar)->getFactor1Sig(); fFactor2Sig = ((HRichDigitisationPar*)fDigitisationPar)->getFactor2Sig(); param21 = 0.0F; param11 = 0.0F; // this table contains values of the inverse error function in the range // [0.95;1.] needed to create a set of random numbers following this // funcion, used in makeNoiseOnPads Float_t test[1000]={1.3859,1.38621,1.38651,1.38681,1.38712,1.38742, 1.38772,1.38803,1.38833,1.38864,1.38894,1.38925,1.38955,1.38986,1.39016, 1.39047,1.39078,1.39108,1.39139,1.3917,1.392,1.39231,1.39262,1.39293, 1.39324,1.39355,1.39386,1.39416,1.39447,1.39478,1.39509,1.3954,1.39572, 1.39603,1.39634,1.39665,1.39696,1.39727,1.39759,1.3979,1.39821,1.39852, 1.39884,1.39915,1.39946,1.39978,1.40009,1.40041,1.40072,1.40104,1.40135, 1.40167,1.40199,1.4023,1.40262,1.40294,1.40325,1.40357,1.40389,1.40421, 1.40453,1.40485,1.40516,1.40548,1.4058,1.40612,1.40644,1.40676,1.40708, 1.40741,1.40773,1.40805,1.40837,1.40869,1.40901,1.40934,1.40966,1.40998, 1.41031,1.41063,1.41096,1.41128,1.41161,1.41193,1.41226,1.41258,1.41291, 1.41323,1.41356,1.41389,1.41422,1.41454,1.41487,1.4152,1.41553,1.41586, 1.41619,1.41651,1.41684,1.41717,1.4175,1.41784,1.41817,1.4185,1.41883, 1.41916,1.41949,1.41983,1.42016,1.42049,1.42083,1.42116,1.42149,1.42183, 1.42216,1.4225,1.42283,1.42317,1.4235,1.42384,1.42418,1.42451,1.42485, 1.42519,1.42553,1.42587,1.4262,1.42654,1.42688,1.42722,1.42756,1.4279, 1.42824,1.42858,1.42892,1.42927,1.42961,1.42995,1.43029,1.43064,1.43098, 1.43132,1.43167,1.43201,1.43236,1.4327,1.43305,1.43339,1.43374,1.43408, 1.43443,1.43478,1.43512,1.43547,1.43582,1.43617,1.43652,1.43687,1.43722, 1.43757,1.43792,1.43827,1.43862,1.43897,1.43932,1.43967,1.44002,1.44038, 1.44073,1.44108,1.44144,1.44179,1.44215,1.4425,1.44286,1.44321,1.44357, 1.44392,1.44428,1.44464,1.44499,1.44535,1.44571,1.44607,1.44643,1.44679, 1.44715,1.44751,1.44787,1.44823,1.44859,1.44895,1.44931,1.44967,1.45004, 1.4504,1.45076,1.45113,1.45149,1.45185,1.45222,1.45259,1.45295,1.45332, 1.45368,1.45405,1.45442,1.45479,1.45515,1.45552,1.45589,1.45626,1.45663, 1.457,1.45737,1.45774,1.45811,1.45848,1.45886,1.45923,1.4596,1.45997, 1.46035,1.46072,1.4611,1.46147,1.46185,1.46222,1.4626,1.46297,1.46335, 1.46373,1.46411,1.46448,1.46486,1.46524,1.46562,1.466,1.46638,1.46676, 1.46714,1.46753,1.46791,1.46829,1.46867,1.46906,1.46944,1.46982,1.47021, 1.47059,1.47098,1.47136,1.47175,1.47214,1.47253,1.47291,1.4733,1.47369, 1.47408,1.47447,1.47486,1.47525,1.47564,1.47603,1.47642,1.47681,1.47721, 1.4776,1.47799,1.47839,1.47878,1.47918,1.47957,1.47997,1.48036,1.48076, 1.48116,1.48156,1.48195,1.48235,1.48275,1.48315,1.48355,1.48395,1.48435, 1.48475,1.48516,1.48556,1.48596,1.48636,1.48677,1.48717,1.48758,1.48798, 1.48839,1.4888,1.4892,1.48961,1.49002,1.49043,1.49083,1.49124,1.49165, 1.49206,1.49247,1.49289,1.4933,1.49371,1.49412,1.49454,1.49495,1.49536, 1.49578,1.49619,1.49661,1.49703,1.49744,1.49786,1.49828,1.4987,1.49912, 1.49954,1.49996,1.50038,1.5008,1.50122,1.50164,1.50207,1.50249,1.50291, 1.50334,1.50376,1.50419,1.50461,1.50504,1.50547,1.50589,1.50632,1.50675, 1.50718,1.50761,1.50804,1.50847,1.5089,1.50934,1.50977,1.5102,1.51064, 1.51107,1.5115,1.51194,1.51238,1.51281,1.51325,1.51369,1.51413,1.51457, 1.51501,1.51545,1.51589,1.51633,1.51677,1.51721,1.51765,1.5181,1.51854, 1.51899,1.51943,1.51988,1.52033,1.52077,1.52122,1.52167,1.52212,1.52257, 1.52302,1.52347,1.52392,1.52437,1.52483,1.52528,1.52573,1.52619,1.52665, 1.5271,1.52756,1.52802,1.52847,1.52893,1.52939,1.52985,1.53031,1.53077, 1.53123,1.5317,1.53216,1.53262,1.53309,1.53355,1.53402,1.53449,1.53495, 1.53542,1.53589,1.53636,1.53683,1.5373,1.53777,1.53824,1.53871,1.53919, 1.53966,1.54014,1.54061,1.54109,1.54156,1.54204,1.54252,1.543,1.54348, 1.54396,1.54444,1.54492,1.5454,1.54589,1.54637,1.54685,1.54734,1.54783, 1.54831,1.5488,1.54929,1.54978,1.55027,1.55076,1.55125,1.55174,1.55223, 1.55273,1.55322,1.55372,1.55421,1.55471,1.55521,1.5557,1.5562,1.5567, 1.5572,1.5577,1.55821,1.55871,1.55921,1.55972,1.56022,1.56073,1.56123, 1.56174,1.56225,1.56276,1.56327,1.56378,1.56429,1.5648,1.56532,1.56583, 1.56635,1.56686,1.56738,1.56789,1.56841,1.56893,1.56945,1.56997,1.57049, 1.57102,1.57154,1.57206,1.57259,1.57312,1.57364,1.57417,1.5747,1.57523, 1.57576,1.57629,1.57682,1.57735,1.57789,1.57842,1.57896,1.57949,1.58003, 1.58057,1.58111,1.58165,1.58219,1.58273,1.58328,1.58382,1.58437,1.58491, 1.58546,1.58601,1.58655,1.5871,1.58765,1.58821,1.58876,1.58931,1.58987, 1.59042,1.59098,1.59154,1.59209,1.59265,1.59321,1.59378,1.59434,1.5949, 1.59547,1.59603,1.5966,1.59717,1.59773,1.5983,1.59887,1.59945,1.60002, 1.60059,1.60117,1.60174,1.60232,1.6029,1.60348,1.60406,1.60464,1.60522, 1.6058,1.60639,1.60697,1.60756,1.60815,1.60874,1.60933,1.60992,1.61051, 1.6111,1.6117,1.6123,1.61289,1.61349,1.61409,1.61469,1.61529,1.61589, 1.6165,1.6171,1.61771,1.61832,1.61892,1.61953,1.62015,1.62076,1.62137, 1.62199,1.6226,1.62322,1.62384,1.62446,1.62508,1.6257,1.62632,1.62695, 1.62757,1.6282,1.62883,1.62946,1.63009,1.63072,1.63136,1.63199,1.63263, 1.63327,1.6339,1.63454,1.63519,1.63583,1.63647,1.63712,1.63777,1.63841, 1.63906,1.63972,1.64037,1.64102,1.64168,1.64233,1.64299,1.64365,1.64431, 1.64498,1.64564,1.64631,1.64697,1.64764,1.64831,1.64898,1.64966,1.65033, 1.65101,1.65168,1.65236,1.65304,1.65372,1.65441,1.65509,1.65578,1.65647, 1.65716,1.65785,1.65854,1.65924,1.65993,1.66063,1.66133,1.66203,1.66273, 1.66344,1.66414,1.66485,1.66556,1.66627,1.66698,1.6677,1.66841,1.66913, 1.66985,1.67057,1.67129,1.67202,1.67274,1.67347,1.6742,1.67493,1.67567, 1.6764,1.67714,1.67788,1.67862,1.67936,1.68011,1.68085,1.6816,1.68235, 1.6831,1.68386,1.68461,1.68537,1.68613,1.68689,1.68766,1.68842,1.68919, 1.68996,1.69073,1.69151,1.69228,1.69306,1.69384,1.69462,1.6954,1.69619, 1.69698,1.69777,1.69856,1.69936,1.70015,1.70095,1.70175,1.70256,1.70336, 1.70417,1.70498,1.70579,1.7066,1.70742,1.70824,1.70906,1.70988,1.71071, 1.71154,1.71237,1.7132,1.71404,1.71487,1.71571,1.71656,1.7174,1.71825, 1.7191,1.71995,1.72081,1.72166,1.72252,1.72339,1.72425,1.72512,1.72599, 1.72686,1.72774,1.72862,1.7295,1.73038,1.73127,1.73216,1.73305,1.73394, 1.73484,1.73574,1.73664,1.73755,1.73846,1.73937,1.74028,1.7412,1.74212, 1.74304,1.74397,1.7449,1.74583,1.74677,1.7477,1.74865,1.74959,1.75054, 1.75149,1.75244,1.7534,1.75436,1.75532,1.75629,1.75726,1.75823,1.75921, 1.76019,1.76117,1.76216,1.76315,1.76415,1.76514,1.76614,1.76715,1.76816, 1.76917,1.77018,1.7712,1.77223,1.77325,1.77428,1.77532,1.77635,1.7774, 1.77844,1.77949,1.78054,1.7816,1.78266,1.78373,1.7848,1.78587,1.78695, 1.78803,1.78912,1.79021,1.7913,1.7924,1.7935,1.79461,1.79572,1.79684, 1.79796,1.79909,1.80022,1.80135,1.80249,1.80363,1.80478,1.80594,1.80709, 1.80826,1.80942,1.8106,1.81178,1.81296,1.81415,1.81534,1.81654,1.81774, 1.81895,1.82017,1.82139,1.82261,1.82384,1.82508,1.82632,1.82757,1.82882, 1.83008,1.83135,1.83262,1.83389,1.83518,1.83646,1.83776,1.83906,1.84037, 1.84168,1.843,1.84433,1.84566,1.847,1.84835,1.8497,1.85106,1.85243, 1.8538,1.85518,1.85657,1.85796,1.85937,1.86078,1.86219,1.86362,1.86505, 1.86649,1.86794,1.86939,1.87086,1.87233,1.87381,1.8753,1.87679,1.8783, 1.87981,1.88133,1.88286,1.8844,1.88595,1.88751,1.88908,1.89065,1.89224, 1.89383,1.89544,1.89705,1.89868,1.90031,1.90196,1.90361,1.90528,1.90696, 1.90864,1.91034,1.91205,1.91377,1.9155,1.91725,1.919,1.92077,1.92255, 1.92434,1.92615,1.92796,1.92979,1.93163,1.93349,1.93536,1.93724,1.93914, 1.94105,1.94297,1.94491,1.94687,1.94884,1.95082,1.95282,1.95484,1.95687, 1.95892,1.96098,1.96306,1.96516,1.96728,1.96941,1.97156,1.97373,1.97592, 1.97813,1.98036,1.98261,1.98487,1.98716,1.98947,1.9918,1.99415,1.99653, 1.99892,2.00135,2.00379,2.00626,2.00875,2.01127,2.01381,2.01638,2.01898, 2.02161,2.02426,2.02694,2.02965,2.0324,2.03517,2.03797,2.04081,2.04368, 2.04658,2.04952,2.0525,2.05551,2.05856,2.06164,2.06477,2.06794,2.07115, 2.0744,2.0777,2.08105,2.08444,2.08788,2.09137,2.09491,2.09851,2.10216, 2.10587,2.10963,2.11346,2.11735,2.1213,2.12533,2.12942,2.13358,2.13783, 2.14214,2.14654,2.15103,2.1556,2.16027,2.16503,2.16989,2.17486,2.17993, 2.18512,2.19044,2.19587,2.20144,2.20716,2.21301,2.21903,2.22521,2.23156, 2.2381,2.24484,2.25179,2.25896,2.26637,2.27404,2.28199,2.29023,2.2988, 2.30773,2.31703,2.32675,2.33694,2.34763,2.35889,2.37078,2.38339,2.39679, 2.41112,2.42652,2.44316,2.46127,2.48115,2.50322,2.52803,2.5564,2.58961, 2.62974,2.68069,2.75106,2.86776}; for(int i = 0;i<1000;i++){ noiseCharge[i] = test[i]; } return kTRUE; } //---------------------------------------------------------------------------- HRichDigitizer::HRichDigitizer(const HRichDigitizer& source) { // dummy } //============================================================================ //---------------------------------------------------------------------------- HRichDigitizer& HRichDigitizer::operator=(HRichDigitizer &source) { if (this != &source) { // dummy } return *this; } //============================================================================ //---------------------------------------------------------------------------- Int_t HRichDigitizer::execute() { for (Int_t i = 0; i < 6; i++) countPhotSec[i] = 0; // // At the end of the execute() the TClonesArray that contains // the track numbers is sorted by the pad addreses. Then // every CalSim object is retrieved from the catRichCal // container to assign to each pad the corresponding nTrack1, nTrack2. // These 2 numbers are the indexes of the track nbs. in the TClonesArray // HRichTrack. // Finally the noise is calculated countNoisePad = 0; cont++; HGeantRichPhoton *pCherenkovHit; HGeantRichDirect *pDirectHit; lNrEvent++; //--------------------------------------------------------------------- // In embedding mode the trackNumber of the // real data has to be set if(gHades->getEmbeddingMode()>0) { fCalIter->Reset(); HRichCalSim *cal; while((cal = (HRichCalSim*)fCalIter->Next())) { cal->setNTrack1(1);// first hit cal->setNTrack2(0); cal->setEventNr(lNrEvent); cal->setEnergy(0); // realID Float_t dummy[2]; dummy[0]=gHades->getEmbeddingRealTrackId(); dummy[1]=0; // flag: realID==0 TVector rTrack(1,2,dummy); HLocation loc; loc.set(3,cal->getSector(),cal->getRow(),cal->getCol()); updateTrack(cal,loc,&rTrack); } } //--------------------------------------------------------------------- Int_t fCerNr = 0, fDirNr = 0; fChargeOnWireList.Delete(); fTrackNumberList.Delete(); fCerIter->Reset(); while((pCherenkovHit = (HGeantRichPhoton*)fCerIter->Next())) { fCerNr++; // for the oem measurement I have to increase the track number // of each produced photon by myself (fCerNr). This number // will be the track number od the photon. if(isOEM) digitiseCherenkovHits(pCherenkovHit,fCerNr); else digitiseCherenkovHits(pCherenkovHit,0); } fDirIter->Reset(); while((pDirectHit = (HGeantRichDirect*)fDirIter->Next())) { digitiseDirectHits(pDirectHit); fDirNr++; } digitisePads(); ((HLinearCategory*)getTrackOutputCat())->sort(); // sort track objects HRichCalSim *calsimobj; HRichTrack *trackobj; fCalIter->Reset(); Int_t temp; Int_t indTrack1 = 0; Int_t contTrack0,countTrackR; contTrack0 = countTrackR = 0; while((calsimobj = (HRichCalSim*)fCalIter->Next())) { //loop on cal sim objects. First the calsim container // contains only those pads fired by the photons. // if the electronic noise is switched a charge fluctuation // dues to the noise is added to the pad charge // and then all those pads that are below threshold // get a 0 charge if(isActiveNoise && (HRichCalPar*)getRichCalPar()){ addNoiseToCharge(calsimobj); if(!checkPad(calsimobj)) { calsimobj->setCharge(0.);//LF } } temp = 0; Int_t addPad = calsimobj->getAddress(); fTrackIter->Reset(); // in the updateCharge member for each fired pad the energy of // the "hitting" photon is added. At the same time the number // of the photons hits is stored, so that after having digizited // all pads the average photon energy for each pad can be calculated // as follows. if(calsimobj->getNTrack1()) calsimobj->setEnergy(calsimobj->getEnergy()/calsimobj->getNTrack1()); calsimobj->setNTrack1(0); while((trackobj = (HRichTrack*)fTrackIter->Next())) { // loop over tracks Int_t addTrack = trackobj->getAddress(); if (trackobj->getTrack()==0) contTrack0++; else countTrackR++; if(addPad == addTrack){ // 1st track found indTrack1 = ((HLinearCategory*)getTrackOutputCat())->getIndex(trackobj); if (temp!=addPad) { // new address: set first // and last index of range calsimobj->setNTrack1(indTrack1); calsimobj->setNTrack2(indTrack1); } else { // same address: set last index // to new value calsimobj->setNTrack2(indTrack1); } temp = addTrack; } else if(temp!=0) break; } } // end of loop on calsim object, pads fired by photons // after the charge propagation due tot he photons is completed // the electronic noise is produced. if(isActiveNoise) makeNoiseOnPads(); // all the pads with charge 0 are removed from the calsim container HRichPadFilter padFilter; ((HMatrixCategory*)getOutputCat())->filter(padFilter); return 0; } //============================================================================ //---------------------------------------------------------------------------- Float_t HRichDigitizer::GaussFun(Float_t mean, Float_t sigma) { Double_t x,y,z; do { y = gRandom->Rndm(); } while (!y); z = gRandom->Rndm(); x = z*6.2831853; return mean + sigma*float(sin(x)*sqrt(-2.0*log(y))); } //============================================================================ //---------------------------------------------------------------------------- Bool_t HRichDigitizer::calcQE(const Float_t photlen, Int_t sec) { if (photlen==100) return kTRUE; Int_t i; Float_t draw; Int_t bins = ((HRichDigitisationPar*)fDigitisationPar)->getQEBinsNr(); Float_t* photlength = ((HRichDigitisationPar*)fDigitisationPar) ->getPhotonLenArray(); Float_t* photeffic = ((HRichDigitisationPar*)fDigitisationPar) ->getPhotonEffArray(); Float_t* correction = ((HRichDigitisationPar*)fDigitisationPar) ->getCorrectionParams(sec); draw = gRandom->Rndm(); for (i = 0; i < bins; i++) if (i == 0) { if (photlen < ((photlength[i]+photlength[i+1])/2)) if (draw > photeffic[i]*correction[i]) { return kFALSE; } else { return kTRUE; } } else if (i == bins-1) { if (photlen >= ((photlength[i-1]+photlength[i])/2)) if (draw > photeffic[i]*correction[i]) { return kFALSE; } else { return kTRUE; } } else if (((photlength[i-1]+photlength[i])/2) <= photlen && ((photlength[i]+photlength[i+1])/2) > photlen) { if (draw > photeffic[i]*correction[i]) { return kFALSE; } else { return kTRUE; } } return kTRUE; } //============================================================================ //---------------------------------------------------------------------------- Int_t HRichDigitizer::getWireNr(Float_t xhit) { Int_t fWiresNr = ((HRichGeometryPar*)fGeometryPar)->getWiresPar() ->getWiresNr(); Float_t fWiresDist = ((HRichGeometryPar*)fGeometryPar)->getWiresPar() ->getDistWire(); Int_t i, nWireNr = -1; Float_t Xwir; for (i = 0; i < fWiresNr; i++) { Xwir = ((HRichGeometryPar*)fGeometryPar)->getWiresPar()->getWire(i) ->getXWire(); if ((xhit >= Xwir - fWiresDist) && (xhit < Xwir + fWiresDist)) { nWireNr = i; break; } } return nWireNr; } //============================================================================ //---------------------------------------------------------------------------- Float_t HRichDigitizer::calcChargeOnWire(Int_t sector, Float_t xhit, Float_t yhit, Float_t nTrack, Float_t nFlag ,Float_t ene) { // // this function calculates the charge on each wire and saves it in a TList // moreover, it saves the track number and the corresponding flag // (cf HRichTrack) in a second TList. // The charge is calculated according to one exponential function // obtained fitting the total charge distribution of the photon candidates // belonging to class one. //( OEM data). // That means that the so calculated charge isn't in reality the // original charge deposited on the wire but the total amount of the charge // coupled to the pads. Therefore it isn't any longer necessary to // use an additional coupling factor. ( 75%) if(nTrack>0) countPhotSec[sector]++; Int_t fHitedWireNr; Float_t fX, fY, fQ; HRichFrame *pFrame = ((HRichGeometryPar*)fGeometryPar)->getFramePar(); fX = fY = fQ = 0.0; fHitedWireNr = getWireNr(xhit); if (fHitedWireNr == -1) return -1; //does not work with root 4.03, constructor not known //TVector *gTrack1 = new TVector(1,2,nTrack,nFlag,"END"); // replace with Float_t dummy[2]; dummy[0]=nTrack; dummy[1]=nFlag; TVector *gTrack1 = new TVector(1,2,dummy); fX = ((HRichGeometryPar*)fGeometryPar)->getWiresPar() ->getWire(fHitedWireNr)->getXWire(); fY = yhit; //charge amplification for different sectors Float_t* b2 = ((HRichDigitisationPar*)fDigitisationPar)->getExpSlope(); Float_t q1,qMax; Float_t charge; qMax = ((HRichDigitisationPar*)fDigitisationPar)->getQupper(); q1 = qMax; //q1 = 400; Float_t fDraw1 = 0; Int_t cTRUE ; cTRUE = 0; while(!cTRUE){ fDraw1=gRandom->Rndm(); charge = 1/b2[sector]*(log(fDraw1*( exp(b2[sector]*q1)-1 ) + 1)); if(charge<=q1) { cTRUE = 1; } else cTRUE =0; } fQ = charge*((HRichDigitisationPar*)fDigitisationPar)->getChargePerChannel(); if (ene==100){ ene = 0.; } if (fQ > 0. && pFrame->isOut(fX, fY) == kFALSE) { fChargeOnWireList.Add(new HRichWireSignal(sector,fHitedWireNr,fQ,fX,fY,ene)); fTrackNumberList.Add(gTrack1); } return fQ; }//============================================================================ //---------------------------------------------------------------------------- void HRichDigitizer::digitiseCherenkovHits(HGeantRichPhoton *pCerHit,Int_t count) { // // for every photon hit on a pad the resulting charge on a wire // is calculated and the track number of the photon parent is stored. // (cf. calcChargeOnWire). // Float_t xHitcm = (pCerHit->getX()/10.0F);//HGeant output is in mm!!! Float_t yHitcm = (pCerHit->getY()/10.0F + fYShift); countFBphot = 0; if(count==0) processPhoton(pCerHit->getEnergy(),xHitcm,yHitcm, pCerHit->getTrack(),pCerHit->getSector()); else processPhoton(pCerHit->getEnergy(),xHitcm,yHitcm,count, pCerHit->getSector()); } void HRichDigitizer::processPhoton(Float_t ene,Float_t xPos,Float_t yPos,Int_t track,Int_t sector){ HRichFrame *pFrame = ((HRichGeometryPar*)fGeometryPar)->getFramePar(); Float_t eneFeedBack =0.; Float_t xHitcmFB = 0.; Float_t yHitcmFB = 0.; Float_t chargeOnWire = 0.; if (calcQE(ene,sector) == kTRUE && pFrame->isOut(xPos,yPos) == kFALSE){ chargeOnWire = calcChargeOnWire(sector,xPos,yPos,track,0,ene); if(calcFeedBack(sector,xPos,yPos,eneFeedBack, xHitcmFB,yHitcmFB,chargeOnWire) && countFBphot<7){ // -5 is the tracknumber assigned to all the feedback photons. processPhoton(eneFeedBack,xHitcmFB,yHitcmFB,-5,sector); } } } Bool_t HRichDigitizer::calcFeedBack(Int_t sec,Float_t xhit, Float_t yhit,Float_t &ene,Float_t &xhittFB,Float_t &yhittFB,Float_t charge){ //We assume that the feed back photon is produced on the anodic wire, the number of the feed back photon is proportional to the value A0. countFBphot++; Float_t thetaDir = 0.; Float_t phiDir = 0.; Float_t dY = 0.; Float_t dX = 0.; Float_t r = 0.; Float_t fDraw,fDraw1,fDraw2,fDraw3; fDraw = gRandom->Rndm(); if(fDraw<(charge*7.8e-6)){ fDraw3 = gRandom->Rndm(); fDraw1 = gRandom->Rndm(); fDraw2 = gRandom->Rndm(); thetaDir = fDraw1*90; phiDir = fDraw1*360; fDraw1 = gRandom->Rndm(); r = distWirePads*TMath::Tan(thetaDir/57.3); dY = r*TMath::Sin(phiDir/57.3); dX = r*TMath::Cos(phiDir/57.3); xhittFB = xhit + dX; yhittFB = yhit + dY; // the Alice TRD gives as VUV photon energies the following // values : 156nm,166nm,193nm with weights 30%,57%,13% // they correspond to :7.94 eV,7.46 eV,6.42eV. if (fDraw2<0.13) ene = 6.42; else if(fDraw2<0.43) ene = 7.94; else ene = 7.46; // ene = 100.; return kTRUE; } else{ ene = 0; xhittFB = 0; yhittFB = 0; return kFALSE; } } //============================================================================ //---------------------------------------------------------------------------- Float_t HRichDigitizer::feedBackProb(Float_t x){ Float_t par0 = -7.71138e-02; Float_t par1 = 1.40085e-02; return 1./(3.*(1./(par0 +par1*x) - 1./3.)); } //============================================================================ //---------------------------------------------------------------------------- void HRichDigitizer::digitiseDirectHits(HGeantRichDirect *pDirHit) { // // for every direct hit (charge particle hitting the RICH or ionizing // the gas near the surface of the photon detector) the // resulting charge on the wires is calculated and the track number // of the charged particle hitting the pad is stored. // (cf. calcChargeOnWire) Int_t i, fStepsNr; Float_t fStepLength, fNewX, fNewY; HRichFrame *pFrame = ((HRichGeometryPar*)fGeometryPar)->getFramePar(); Float_t xHitcm = pDirHit->getX()/10.0F;//HGeant output is in mm!!! Float_t yHitcm = pDirHit->getY()/10.0F + fYShift ; if (pDirHit->getEnergyLoss() > 0.0F && // one day it will be additional condition if it is mirror or detector pFrame->isOut(xHitcm, yHitcm) == kFALSE) { fStepsNr = (Int_t)(1+((HRichDigitisationPar*)fDigitisationPar) ->getElectronsNr()*pDirHit->getEnergyLoss()); if (fStepsNr > 5000) { fStepsNr = 5000; cerr << "Warning in : " << "Number of maximum steps exceeded!\n"; } fStepLength = pDirHit->getTrackLengthInPhotDet()/((Float_t)fStepsNr); for (i = 0; i < fStepsNr; i++) { fNewX = xHitcm + (i+1) * fStepLength * sin(pDirHit->getTheta()) * cos(pDirHit->getPhi()); fNewY = yHitcm + (i+1) * fStepLength * sin(pDirHit->getTheta()) * sin(pDirHit->getPhi()); Int_t dTrack, dId; pDirHit->getTrack( dTrack,dId); // the energy of the direct hits is set to 0 // not to modify the average energy deposited by one or more // photons on one pad. (this is very important for the OEM // analysis). calcChargeOnWire(pDirHit->getSector(), fNewX, fNewY,dTrack,1,0); } } } //============================================================================ //---------------------------------------------------------------------------- HRichPad* HRichDigitizer::translateCorners(HRichPad *pPad, Float_t dx, Float_t dy) { // check what you want to translate - probably real corners Int_t i; HRichPad *fpTranslatedPad = new HRichPad(*pPad); for (i = 0; i < fpTranslatedPad->getCornersNr(); i++) { fpTranslatedPad->getCorner(i)->setX(fpTranslatedPad->getCorner(i)->getX() - dx); fpTranslatedPad->getCorner(i)->setY(fpTranslatedPad->getCorner(i)->getY() - dy); } fpTranslatedPad->setXmin(fpTranslatedPad->getXmin() - dx); fpTranslatedPad->setYmin(fpTranslatedPad->getYmin() - dy); fpTranslatedPad->setXmax(fpTranslatedPad->getXmax() - dx); fpTranslatedPad->setYmax(fpTranslatedPad->getYmax() - dy); // the ownership of this pointer is passed to outer variable-pointer return fpTranslatedPad; } //=========================================================================== //---------------------------------------------------------------------------- void HRichDigitizer::makeNoiseOnPads() { // nbNoisePads is the number of pads on which the electronic noise // will produce a non zero signal. This number is extimated taken // into account the threshold taht has been used for the pedestals. HRichCalSim *pCalSim = NULL; HRichGeometryPar * geomPar = (HRichGeometryPar *)getGeometryPar(); Int_t maxPads = geomPar->getRows() * geomPar->getColumns(); Float_t lowLim = -10.; Float_t upLim = 10.; ga->SetRange(lowLim,upLim); Float_t par0 = 1. / ((TMath::Sqrt(2.*TMath::Pi())) * fIncreaseNoise); Float_t par1 = -1. / (2.*fIncreaseNoise*fIncreaseNoise); ga->SetParameters(par0,par1); //this variable is the probability that a given pad will have // a signal induced by the electronic noise above threshold Float_t noiseProb = (1. - 2. * (ga->Integral(0.,fSigmaValue)))/2.; //here the number of pads that will have a noise induced signal above // threshold is calculated. The number countNoisePad/6 represents // the number of pads that had already a noise signal above threshold // in each sector. Int_t nbNoisePads = (Int_t) (TMath::Floor(4800*noiseProb) - countNoisePad/6.); nbNoisePads = gRandom->Poisson(nbNoisePads); Float_t fDraw= 0; Int_t padNm = 0; Int_t col,row; col = row = 0; Int_t maxCols = geomPar->getColumns(); Int_t padOffset = 0; // a Gauss distributed signal is induced on nbNoisePads pads // for each sector. for (int i = 0; i < 6; i++){ if (geomPar->getSector(i) > 0){ for(int j = 0; j < nbNoisePads; j++){ do{ fDraw = gRandom->Rndm(); padNm = (Int_t) TMath::Floor(maxPads*fDraw); row = geomPar->calcRow(padNm); col = geomPar->calcCol(padNm); padOffset = row*maxCols; // the following condition is necessary to test that the pad // exists and is connected to the electronic }while(!geomPar->fPads.getPad(col+padOffset)->getPadActive() && colgetSigma(loc); if(fSigmaPad>0.2){ fMeanPad = ((HRichCalPar*)getRichCalPar())->getOffset(loc); fFloatMean = fMeanPad - (TMath::Floor(fMeanPad)); fCharge = calcNoiseOnPad(fSigmaPad,fFloatMean); // the noise contribution is calculated with a gauss dist. // centred in 0, hence we have to add the float part of the //mean. Hence we cast the charge to an integer, then we // subtract the float part of the mean value and finally // we add a random number between 0 and 1 to have a float. fDraw = gRandom->Rndm(); fCharge = (TMath::Floor(fCharge)) - fFloatMean + fDraw; pCalSim = (HRichCalSim*)((HMatrixCategory*)getOutputCat())->getObject(loc); // if the pad has already been fired no additional // charge is added and a new pad is drawn. if (pCalSim == NULL && fCharge>0) { pCalSim = (HRichCalSim*)((HMatrixCategory*)getOutputCat())->getSlot(loc); if (pCalSim != NULL) { pCalSim = new(pCalSim) HRichCalSim; pCalSim->setEventNr(lNrEvent); pCalSim->setSector(loc[0]); pCalSim->setCol(loc[2]); pCalSim->setRow(loc[1]); pCalSim->addCharge((fCharge+0.5)*fChargeScaling); // where is the track number for this pad ?????? } } else j--; } else j--; } } } } //=========================================================================== //---------------------------------------------------------------------------- Float_t HRichDigitizer::calcNoiseOnPad(Float_t sigma,Float_t floatMean){ // the charge induced on the pad by the electronic noise // is calculated according to a gauss function with // sigma = fSigmaPad*fIncreaseNoise and mean 0. // Anyway only values above threshold (fSigmaValue * fSigmaPad) // are drawn const Int_t cutLoop = 10; Int_t lowLim = (Int_t)(0.5 + floatMean +fSigmaValue*sigma); Float_t upLim = 100.; sigma = sigma*fIncreaseNoise; ga->SetRange(-upLim,upLim); Float_t par0 = 1. / ((TMath::Sqrt(2.*TMath::Pi())) * sigma); Float_t par1 = -1. / (2.*sigma*sigma); Float_t par2 = floatMean; ga->SetParameters(par0,par1,par2); Float_t norma = ga->Integral(lowLim,upLim); Float_t fDraw =0.; Float_t charge =0.; Int_t count = 0; do{ fDraw = gRandom->Rndm(); // the InverseErf function is defined in the array noiseCharge // with 1000 bin in the range (0.95,1). This range should be enough // to calculate the noise contribution up to a 2 sigma cut if the // variable fIncreaseNoise is 1. If the noise is increased ( e.g. // fSigmaNoise=1.9) the values are consistent with a cut of 3.9 sigma. Int_t chan = (Int_t)(((1.-2.*norma*fDraw)-0.95)/(0.05/1000.)); if(chan>=0&&chan<=999) { charge = TMath::Sqrt(2.)*sigma*noiseCharge[chan] + floatMean; } else charge = 0.; count++; }while((charge1000.)&& count10) or too small(<0.4) // then the array used to calculate the value of the charge // has not the required granularity and the previous loop // is neverending. Therefore we allow only 10 tries, that // should be sufficient for a reasonable sigma. if(count == (cutLoop)) charge = 0.; return charge; } //=========================================================================== //---------------------------------------------------------------------------- void HRichDigitizer::addNoiseToCharge(HRichCalSim* calSim){ // An additional charge is added on pads that have already // been "fired" by a photon. // This charge is drawn according to a Gauss distribution // with sigma = fSigmaPad*fIncreaseNoise and mean = 0. loc.set(3, calSim-> getSector(), calSim->getRow() , calSim->getCol() ); HRichCalParCell* pCell = ((HRichCalParCell*)((HRichCalPar*)getRichCalPar())->getObject(loc)); if (pCell) { fSigmaPad= ((HRichCalPar*)getRichCalPar())->getSigma(loc); }else fSigmaPad = 0.6; fCharge = GaussFun(0,fSigmaPad*fIncreaseNoise); if(fCharge>fSigmaPad*fSigmaValue) countNoisePad++; calSim->addCharge(fCharge*fChargeScaling); } //============================================================================ //---------------------------------------------------------------------------- Int_t HRichDigitizer::checkPad(HRichCalSim *calSim){ // this function checks if the pads fired by the photons // are above threshold. // The procedure used to calculate the threshols is the // same used for real data. The charge on the pad is composed // of the signal induced by the photon plus the noise fluctuation. // The float part of the mean value of the noise distribution // is added to the charge then // the charge value is casted to an integer and is // compared to the threshold. // If the charge is above threshold, the float part of the mean is // subtracted from the total charge and a random number between 0 and 1 // is added to the integer produce a float. Float_t charge = calSim->getCharge(); Int_t iRow = calSim->getRow(); Int_t iCol = calSim->getCol(); Int_t iSec = calSim->getSector(); loc.set(3, iSec, iRow,iCol); HRichCalParCell* pCell = ((HRichCalParCell*)((HRichCalPar*)getRichCalPar())->getObject(loc)); if (pCell) { fSigmaPad= ((HRichCalPar*)getRichCalPar())->getSigma(loc); fMeanPad = ((HRichCalPar*)getRichCalPar())->getOffset(loc); }else fSigmaPad = 0.6; fFloatMean = fMeanPad - (Int_t)fMeanPad; charge += fFloatMean; Int_t iCharge = (Int_t)( charge); Int_t iThreshold = (Int_t) (fFloatMean + fSigmaValue*fSigmaPad + 0.5); Float_t fDraw = 0; if( iCharge > iThreshold) { fDraw = gRandom->Rndm(); charge = iCharge - fFloatMean + fDraw; calSim->setCharge(charge); return iCharge; } else return 0; } //=========================================================================== //---------------------------------------------------------------------------- void HRichDigitizer::digitisePads() { // // for each wire on which some charge has been deposited // the corresponding coupled pads are calculated. // The function updateCharge creates a HRichCalSim obj if // the charge on the pad is greater than zero. // A cut off threshold is applied to each pad in the execute func. // after the digitilasation of all the hits. // If the pad is hit twice in the same event, the charges // corresponding to the 2 different hits are added. // The particle track number is passed to the function // updateCharge, too. // Int_t i, j, xcenter, ycenter; Int_t sector; Float_t energyPhot =0.; HRichPadTab *pPadsPar = ((HRichGeometryPar*)fGeometryPar)->getPadsPar(); HRichPad *pPad = NULL; HRichPad *pTmpPad = NULL; TVector * nTrackTemp =NULL; HRichWireSignal *pCharge = NULL; for (i = 0; i < fChargeOnWireList.GetSize(); i++) { for (j = 0; j < 9; j++) fDigitPadMatrix[j] = 0.; pCharge = (HRichWireSignal*)fChargeOnWireList.At(i); nTrackTemp =(TVector*)fTrackNumberList.At(i); energyPhot = pCharge->getEnergy(); sector = pCharge->getSector(); pPad = pPadsPar->getPad(pCharge->getX(), pCharge->getY()); xcenter = pPad->getPadX(); ycenter = pPad->getPadY(); // the position of the photon hit on the central pad is calculated. Float_t yRel = TMath::Abs((pCharge->getY() - pPad->getYmin())/(pPad->getYmax()-pPad->getYmin())); pTmpPad = translateCorners(pPad, pCharge->getX(), pCharge->getY()); // do not forget to delete it at the end of loop // ------------------------ central pad (0,0) param11= param21 = 0.; Float_t charge4 = 0.; if (pTmpPad->getPadFlag() == 2) { //First we calculate the charge on the central pad taking as //contributions on the side pads, 0 for the weak coupling and t //he mean for the strong one. // Then we recalculate the coupling parameter for the // strong coupling drawing a number on the landau // distribution centered in the mean value. param11 = (gRandom->Landau(fFactor1,fFactor1Sig)); param21 = GaussFun(fFactor2,fFactor2Sig); if(param21<0) param21 = 0.; charge4 = q4Calc(pCharge->getCharge(),yRel,param11,param21); if (charge4 < 0.) fDigitPadMatrix[4] = 0.; else{ updateCharge(sector, pPad,charge4 ,nTrackTemp,energyPhot); fDigitPadMatrix[4] = charge4; } } //------------------------ loop on other pads Int_t iPadInd = 0; for (Int_t n =-1;n<2;n++){ for (Int_t m =-1;m<2;m++){ if(m!=0 || n!=0 ){ if (pPadsPar->getPad(xcenter+m, ycenter+n) && pPadsPar->getPad(xcenter+m, ycenter+n)->getPadActive()) { delete pTmpPad; pTmpPad = translateCorners(pPadsPar->getPad(xcenter+m,ycenter+n),pCharge->getX(), pCharge->getY()); if (pTmpPad->getPadFlag() == 2){ fDigitPadMatrix[iPadInd] = calcIndCharge(yRel,fDigitPadMatrix[4], iPadInd,pCharge->getWireNr()); if (fDigitPadMatrix[iPadInd] <= 0.) fDigitPadMatrix[iPadInd] = 0.; else{ updateCharge(sector, pTmpPad, fDigitPadMatrix[iPadInd],nTrackTemp,energyPhot); } } } } iPadInd ++; } } delete pTmpPad; } } Float_t HRichDigitizer::calcIndCharge(float yCharge,float q4,int iPdaIndex,int iWireNr){ // iWireNr is used to determine whether the wire is // the left or the right one. // Even wire numbers correspond to right. // for the side pads a coupling costant is multiplied // by the charge on the central pad, the upper an lower // pad get an amount of charge that is position dependent. switch(iPdaIndex){ case 1: { return (qX(1-yCharge)*q4); } case 7: { return (qX(yCharge)*q4); } case 3: { if(iWireNr%2==0) return (param21* q4); else return (param11 * q4); } case 5:{ if(iWireNr%2==0) return (param11 * q4); else return ( param21* q4); } case 2:{ if(iWireNr%2==0) return ( 1.37*param11 * q4 * qX(1-yCharge)); else return ( 1.37*param21 * q4 * qX(1-yCharge)); } case 8:{ if(iWireNr%2==0) return ( 1.37*param11 * q4 * qX(yCharge)); else return ( 1.37*param21 * q4 * qX(yCharge)); } case 6:{ if(iWireNr%2==0) return ( 1.37*param21 * q4 * qX(yCharge)); else return ( 1.37*param11 * q4 * qX(yCharge)); } case 0:{ if(iWireNr%2==0) return ( 1.37*param21 * q4 * qX(1-yCharge)); else return ( 1.37*param11 * q4 * qX(1-yCharge)); } } return 0; }; Float_t HRichDigitizer::qX(Float_t pos){ //this function calculate the charge ratio between the upper/lower // pad and the central one Float_t charge = 0.; Float_t q0 = -0.03; // Float_t q0 = 0.0; Float_t integral = 1/(fParam1*fParam1*q0 + fParam1*fParam2) - 1/(fParam1*fParam1 + fParam1*fParam2); //integral = integral; charge =((q0+fParam2/fParam1)/(1-(q0+fParam2/fParam1)*fParam1*fParam1*integral*pos))-fParam2/fParam1; if (charge<0.) charge = 0.; return charge; } Float_t HRichDigitizer::q4Calc(float charge,float pos,float par1,float par2){ // This function calculate the charge induced on the central pad. //the coupling factor (75%) from the wire to the pad has // been discarded since the charge distribution on the wire //has been calculated fitting pads responses. Float_t gX = 1 + qX(pos) + qX(1-pos); Float_t gX1 = 1 + 1.37*qX(pos) + 1.37*qX(1-pos); if(gX) return charge/((par1 + par2)* gX1 + gX); else return 0; } //---------------------------------------------------------------------------- void HRichDigitizer::updateCharge(Int_t sector, HRichPad* pPad, Float_t charge,TVector * rTrack, Float_t ene) { // // this function creates an HRichCalSim obj that corresponds // to a fired pad, it calls the function updateTrack, // that stores the corresponding track numbers. // HLocation locat; Int_t fCol, fRow; HRichCalSim *pCalSim = NULL; pPad->getPadXY(&fCol, &fRow); locat.set(3, sector, fRow, fCol); pCalSim = (HRichCalSim*)((HMatrixCategory*)getOutputCat())->getObject(locat); if (pCalSim == NULL) { pCalSim = (HRichCalSim*)((HMatrixCategory*)getOutputCat())->getSlot(locat); if (pCalSim != NULL) { pCalSim = new(pCalSim) HRichCalSim; pCalSim->setEventNr(lNrEvent); pCalSim->setSector(locat[0]); pCalSim->setCol(locat[2]); pCalSim->setRow(locat[1]); updateTrack(pCalSim,locat,rTrack); } } if (pCalSim != NULL){ pCalSim->addCharge(charge * fChargeScaling / fChargePerChannel); // the feed back photon and the direct hits are assigned energy // equal to 0. Infact the energy of the other photons emitted in the // oem experiment depends on the polar emission angle theta // (dispersion in the solid radiators) and this is not true // for the feed back photons and for the direct hits. // There fore their energy isnt added to the pad they fire // and isnt taken into account in the calculation theta->Energy // because it would falsify the distribution. if(ene>0) { pCalSim->addHit(); pCalSim->addEnergy(ene); } // the track object is created for all the photon and direct hits // the feedback photons have track number -5 and flag 0. // Only the pad fired just because of electronic noise // dont correspond to any track objects. updateTrack(pCalSim,locat,rTrack); } } //============================================================================ //--------------------------------------------------------------------------- void HRichDigitizer::updateTrack(HRichCalSim *pCal,HLocation& loc,TVector * rTrack){ // // this function stores the track numbers of parent // particles of photons and of direct hits in a linear // category (HRichTrack). This category is set sortable. // HRichTrack *pRichTrack = NULL; Int_t Ad = pCal->getAddress(); fTrackIter->Reset(); while((pRichTrack = (HRichTrack*)fTrackIter->Next())) { if((pRichTrack->getTrack()==(*rTrack)(1)) && pRichTrack->getFlag()==(*rTrack)(2) && pRichTrack->getAddress() == Ad) return; } HLocation loc1; loc1.set(1,0); pRichTrack = (HRichTrack*)((HLinearCategory*)getTrackOutputCat())->getNewSlot(loc1); if (pRichTrack){ pRichTrack = new (pRichTrack) HRichTrack; pRichTrack->setEventNr(pCal->getEventNr()); //usage of TVector because of used in TList, explicit cast to integer is needed since TVector converts all arguments into double. pRichTrack->setTrack((Int_t)((*rTrack)(1))); pRichTrack->setFlag((Int_t)((*rTrack)(2))); pRichTrack->setAddress(Ad); } } Bool_t HRichDigitizer::finalize(){ return kTRUE; }