[DEE] Add drift times from depth calibration already in MSubModuleChargeTransport#165
[DEE] Add drift times from depth calibration already in MSubModuleChargeTransport#165fhagemann wants to merge 3 commits into
MSubModuleChargeTransport#165Conversation
| //! The drift time in ns since creation of event | ||
| double m_DriftTime; |
There was a problem hiding this comment.
Maybe the name m_DriftTime might not be correct.
It is essentially the time between the creation of the electron-hole pairs until the fast shaper on a non-charge-sharing main strip would peak, minus some offset accounting for the delay in peaking...
For non-charge-sharing main strips, this value should correspond to the drift time, but it's not the case for charge-sharing strips or nearest neighbors. Suggestions welcome ^^
| while (IterLV2 != LVHits.end()) { | ||
| if (IterLV1->m_ROE == IterLV2->m_ROE) { | ||
| IterLV1->m_Energy += IterLV2->m_Energy; | ||
| IterLV1->m_DriftTime = IterLV1->m_Energy > IterLV2->m_Energy ? IterLV1->m_DriftTime : IterLV2->m_DriftTime; |
There was a problem hiding this comment.
The way we combine timing values when merging strip hits might not be too accurate. This works well for hits that were initially close together, but might be wrong for events that are spatially more separated.
If the fast-shaper direct signals would feature two separated peaks (usually more than 50ns apart), then it would depend on if the first peak would be above threshold etc. ...
Maybe this merging can only happen during MSubModuleDepthReadout, when we know what the fast threshold is?
| // calculate σ and η, assuming t = z / v = z / (µ * E) | ||
| double Sigma = std::sqrt(2.0 * kB * Temperature * ΔZ / (ElementaryCharge * MeanElectricField)); // in cm | ||
| double Eta = std::cbrt(std::pow(InitialChargeCloudSize, 3) + 3.0 * N * ElementaryCharge * ΔZ / (4.0 * TMath::Pi() * Epsilon0 * EpsilonR * MeanElectricField)); // in cm | ||
| double Sigma = std::sqrt(2.0 * kB * Temperature * DeltaZ / (ElementaryCharge * MeanElectricField)); // in cm | ||
| double Eta = std::cbrt(std::pow(InitialChargeCloudSize, 3) + 3.0 * N * ElementaryCharge * DeltaZ / (4.0 * TMath::Pi() * Epsilon0 * EpsilonR * MeanElectricField)); // in cm |
There was a problem hiding this comment.
Here, we could also think about updating t = z / v = z / (µ * E) to using the simulated drift times. Two caveats though: the files have those simulated drift times already convolved with electronics, and this might be quite sensitive to how you apply the depth-calibration offset (e.g. adding it to the hole drift times or subtracting it from the electron hole drift times)
|
|
||
| // create MDEEStripHit for the left NN | ||
| if (NNLeftStripEnergy > IonizationEnergy) { | ||
| // if (NNLeftStripEnergy > IonizationEnergy) { |
There was a problem hiding this comment.
Here, I'm keeping all events, no matter if their energy is 0, just to keep the nearest-neighbor timing information.
| MainSH.m_ROE.SetStripID(ID); | ||
| MainSH.m_OppositeStripID = OppositeStripID; | ||
| MainSH.m_Energy = MainStripEnergy; | ||
| MainSH.m_DriftTime = DriftTime - 50 * (1 - MainStripEnergy / SH.m_SimulatedEnergy); |
There was a problem hiding this comment.
This is how to account for the difference in timing with respect to having a non-charge-sharing main strip. I know that this implementation is very simplistic, but captures what we see well for most events that are not close to the HV/LV sides.
We have one of our undergrads (Isidro) looking into this is more detail.
I would push going for higher-order implementations in a future PR.
| vector<double> Coeffs = m_Coeffs[PixelCode]; | ||
| double CTD_FWHM = Coeffs[2] * m_Coeffs_Energy / SH.m_Energy; | ||
| double CTD_Sigma = CTD_FWHM / 2.355; |
There was a problem hiding this comment.
MSubModuleDepthReadout now only smears the final timing values and applies the inverse TAC calibration. Everything else is done in MSubModuleChargeTransport now.
| if (g_Verbosity >= c_Warning) { | ||
| cout << "No depth calibration coefficients for pixel in DetID " << DetID << " HV " << (isLV ? OppositeStripID : ID) << " LV " << (isLV ? ID : OppositeStripID) << endl; | ||
| } | ||
| DriftTime = 1e10; |
There was a problem hiding this comment.
If we don't have stretch and offset available, I'm setting the drift times unreasonably high. Using a pixel-based inverse depth calibration, this can result in:
- if there is a HV strip without fast timing, all events collected on that strip would also give unreasonable drift times on the LV strips.
- If we were to use these charge drift times for diffusion/self-repulsion, this would screw the calculation up and result in gigantic amounts of charge sharing.
This would be avoided by transitioning from pixel-based to strip-based inverse depth calibration (see #158).
I'm also open to suggestions how to deal with events with no depth calibration.
| if (m_ApplyTimingResolutionCalibration == true) { | ||
| if (SH.m_IsGuardRing == false) { | ||
| unsigned int StripID = SH.m_ROE.GetStripID(); | ||
| if (SH.m_DriftTime > -200.0){ |
There was a problem hiding this comment.
This is an arbitrary number right now.
This number CAN be negative (if the charge drift time is shorter than 50ns, and the neighbor did not charge share, we might get e.g. 40ns for the main strip and -10ns for its nearest neighbor).
This PR addresses issue #111, and is a first step to add realistic nearest-neighbor timing to the DEE.
TLDR: I'm moving applying the depth splines + stretch + offset from
MSubModuleDepthReadouttoMSubModuleChargeTransport, while keeping the smearing of timing values inMSubModuleDepthReadout,while adding an extra field to
MDEEStripHitto keep track of the expected time at which the fast-shaper signal peaks.Some background information:
Scenario 1: an event where all charge is collected on one strip, the main strip.
Scenario 2: an event where the charge is shared between two neighboring strips.
To first order, the relation between when the fast-shaper signal peaks and how much energy it records is pretty linear, i.e.
t_drift = t_unipolar - 50ns * (1 - E_recorded / E_event)The drift times for the main strips can be determined from the simulated electron and hole drift times, by applying stretch and offset from the depth calibration. For main strips with no charge sharing, the "time until fast shaper peaks" should be similar to those drift times.
In order to include simulated drift times in the DEE, we need to know which strips are main strips / NN strips and if there was charge sharing present or not, because for these the "time until fast shaper peaks" is not identical to the charge drift times, and we need additional information (basically the depth,
Zand if/how much energy was charge-shared), all of which is only available inMSubModuleChargeTransport. Therefore, the determination of charge drift times + stretch + offset is moved toMSubModuleChargeTransport, and for now we apply nearest-neighbor timing by using the simplistic linear relationshipt_drift = t_unipolar - 50ns * (1 - E_recorded / E_event).