Skip to content

Commit 3770786

Browse files
committed
Merge pull request #775 in B2/basf2 from bugfix/BIIDP-5236-pxd-hot-dead-channel-calibration-bugged-in-proc13_chunk1_rel06-00 to release/06-00
* commit 'b7a866d815314a770bf58401abfaba713142bb1d': Check PXDHits pointer before processing. Check PXDClusterCounter pointer before processing. Added empty tag for beam energy in prompt calibration. Bugfix for PXD efficiency estimation and improving plotting Bugfix for PXD calibration plotting and adding support for different track particles in gain calibration. Style fix
2 parents 563b94a + b7a866d commit 3770786

File tree

12 files changed

+111
-42
lines changed

12 files changed

+111
-42
lines changed

calibration/scripts/prompt/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"Beam Energy": {"No Beam": "No Beam",
2222
"4S": "4S",
2323
"Continuum": "Continuum",
24+
"": "",
2425
"Scan": "Scan"},
2526
"Run Type": {"beam": "beam",
2627
"cosmic": "cosmic",

calibration/scripts/prompt/calibrations/caf_pxd.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
INPUT_DATA_FILTERS["Beam Energy"]["4S"],
3838
INPUT_DATA_FILTERS["Beam Energy"]["Continuum"],
3939
INPUT_DATA_FILTERS["Beam Energy"]["Scan"],
40+
INPUT_DATA_FILTERS["Beam Energy"][""],
4041
INPUT_DATA_FILTERS["Run Type"]["physics"],
4142
INPUT_DATA_FILTERS["Data Quality Tag"]["Good Or Recoverable"]],
4243
"cosmic": [INPUT_DATA_FILTERS["Run Type"]["cosmic"]]},

calibration/scripts/prompt/calibrations/caf_pxd_gain.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
INPUT_DATA_FILTERS["Beam Energy"]["4S"],
3535
INPUT_DATA_FILTERS["Beam Energy"]["Continuum"],
3636
INPUT_DATA_FILTERS["Beam Energy"]["Scan"],
37+
INPUT_DATA_FILTERS["Beam Energy"][""],
3738
INPUT_DATA_FILTERS["Run Type"]["physics"],
3839
INPUT_DATA_FILTERS["Data Quality Tag"]["Good"]]},
3940
expert_config={

pxd/calibration/src/PXDAnalyticGainCalibrationAlgorithm.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ CalibrationAlgorithm::EResult PXDAnalyticGainCalibrationAlgorithm::calibrate()
5454
// Get counter histograms
5555
auto cluster_counter = getObjectPtr<TH1I>("PXDClusterCounter");
5656

57+
// Check if there is any PXD cluster
58+
if (cluster_counter == nullptr) {
59+
B2WARNING("No PXD cluster reconstructed!");
60+
if (not forceContinue)
61+
return c_NotEnoughData;
62+
else {
63+
B2WARNING("Skip processing.");
64+
return c_OK;
65+
}
66+
}
67+
5768
// Extract number of sensors from counter histograms
5869
auto nSensors = getNumberOfSensors(cluster_counter);
5970

pxd/calibration/src/PXDHotPixelMaskCalibrationAlgorithm.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ CalibrationAlgorithm::EResult PXDHotPixelMaskCalibrationAlgorithm::calibrate()
9696
auto collector_pxdhits = getObjectPtr<TH1I>("PXDHits");
9797
auto collector_pxdhitcounts = getObjectPtr<TH1I>("PXDHitCounts");
9898

99+
// Check if there is any PXD hit
100+
if (!collector_pxdhits) {
101+
if (forceContinueMasking)
102+
return c_OK;
103+
else
104+
return c_NotEnoughData;
105+
}
106+
99107
// We should have some minimum number of events
100108
auto nevents = collector_pxdhits->GetEntries();
101109
if (nevents < minEvents) {

pxd/modules/pxdPerformanceVariablesCollector/include/PXDPerformanceVariablesCollectorModule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ namespace Belle2 {
166166
PXDGainMapPar m_gainMap;
167167

168168
/** Track struct for holding required variables */
169-
PXD::Track_t track_struct;
169+
PXD::Track_t m_track_struct;
170170
/** Name of the particle list for gain calibration */
171171
std::string m_PList4GainName = "";
172172
/** Name of the particle list for efficiency study */

pxd/modules/pxdPerformanceVariablesCollector/src/PXDPerformanceVariablesCollectorModule.cc

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ void PXDPerformanceVariablesCollectorModule::collect() // Do your event() stuff
216216
StoreObjPtr<ParticleList> particles4Eff(m_PList4EffName);
217217
if (particles4Eff.isValid() && particles4Eff->getListSize() == 1)
218218
m_selected4Eff = true;
219+
const Particle* vpho4eff = particles4Eff->getParticle(0);
219220

220221
collectDeltaIP(); // using ParticleList(m_PList4ResName)
221222

@@ -228,14 +229,15 @@ void PXDPerformanceVariablesCollectorModule::collect() // Do your event() stuff
228229

229230
for (auto const& particle : *particles) {
230231
const Track* trackPtr = particle.getTrack();
232+
auto mass = particle.getMass();
231233
if (!trackPtr) return;
232234
auto recoTrackPtr = trackPtr->getRelated<RecoTrack>("");
233235
if (!recoTrackPtr) return;
234236
auto pxdIntercepts = recoTrackPtr->getRelationsTo<PXDIntercept>("");
235237
for (auto const& pxdIntercept : pxdIntercepts) {
236238
TrackCluster_t trackCluster;
237239
// Function setValues() also returns a recoTrack pointer
238-
if (!trackCluster.setValues(pxdIntercept, "", "PXDClustersFromTracks"))
240+
if (!trackCluster.setValues(pxdIntercept, "", "PXDClustersFromTracks", mass))
239241
continue;
240242

241243
auto const& cluster = trackCluster.cluster;
@@ -244,8 +246,13 @@ void PXDPerformanceVariablesCollectorModule::collect() // Do your event() stuff
244246

245247

246248
// Collect info for efficiency study
247-
if (m_selected4Eff && intersection.inside)
248-
collectEfficiencyVariables(trackCluster);
249+
if (m_selected4Eff && intersection.inside) {
250+
// check if the particle is vpho4eff's daughter
251+
for (auto const& daughter : vpho4eff->getDaughters()) {
252+
if (particle.isCopyOf(daughter))
253+
collectEfficiencyVariables(trackCluster);
254+
} // end of vpho4eff daughter loop
255+
}
249256

250257
// Collect info for gain calibration
251258
// Check for valid cluster and intersection
@@ -284,12 +291,12 @@ void PXDPerformanceVariablesCollectorModule::collectDeltaIP()
284291
const TrackFitResult* tr0 = part0->getTrack()->getTrackFitResultWithClosestMass(Const::pion);
285292
const TrackFitResult* tr1 = part1->getTrack()->getTrackFitResultWithClosestMass(Const::pion);
286293

287-
track_struct.setTrackVariables(tr0, vertex);
288-
auto d0p_0 = track_struct.d0p;
289-
auto z0p_0 = track_struct.z0p;
290-
track_struct.setTrackVariables(tr1, vertex);
291-
auto d0p_1 = track_struct.d0p;
292-
auto z0p_1 = track_struct.z0p;
294+
m_track_struct.setTrackVariables(tr0, vertex);
295+
auto d0p_0 = m_track_struct.d0p;
296+
auto z0p_0 = m_track_struct.z0p;
297+
m_track_struct.setTrackVariables(tr1, vertex);
298+
auto d0p_1 = m_track_struct.d0p;
299+
auto z0p_1 = m_track_struct.z0p;
293300

294301
m_deltaD0oSqrt2 = (d0p_0 + d0p_1) / sqrt(2.);
295302
m_deltaZ0oSqrt2 = (z0p_0 - z0p_1) / sqrt(2.);

pxd/scripts/pxd/calibration/__init__.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,15 @@ def gain_calibration(input_files, cal_name="PXDGainCalibration",
176176
**kwargs: Additional configuration to support extentions without changing scripts in calibration folder.
177177
Supported options are listed below:
178178
179-
"collector_prefix" is a string indicating which collector to be used for gain calibration. The supported
179+
"collector_prefix": a string indicating which collector to be used for gain calibration. The supported
180180
collectors are:
181181
PXDPerformanceVariablesCollector (default),
182182
PXDPerformanceCollector(using RAVE package for vertexing, obsolete)
183183
"useClusterPosition": Flag to use cluster postion rather than track point to group pixels for calibration.
184+
"particle_type": Particle type assigned to tracks. "e" by default.
185+
"track_cuts_4gain": Track cuts used for gain calibration.
186+
"track_cuts_4eff": Track cuts used for efficiency study.
187+
"track_cuts_4res": Track cuts used for resolution study.
184188
185189
Return:
186190
A caf.framework.Calibration obj.
@@ -201,6 +205,10 @@ def gain_calibration(input_files, cal_name="PXDGainCalibration",
201205
useClusterPosition = kwargs.get("useClusterPosition", False)
202206
if not isinstance(useClusterPosition, bool):
203207
raise ValueError("useClusterPosition has to be a boolean!")
208+
particle_type = kwargs.get("particle_type", "e") # rely on modular analysis for value check
209+
track_cuts_4gain = kwargs.get("track_cuts_4gain", "p > 1.0") # see above
210+
track_cuts_4eff = kwargs.get("track_cuts_4eff", "pt > 2.0") # see above
211+
track_cuts_4res = kwargs.get("track_cuts_4res", "Note2019") # NOTE-TE-2019-018
204212

205213
# Create basf2 path
206214

@@ -226,35 +234,37 @@ def gain_calibration(input_files, cal_name="PXDGainCalibration",
226234
else: # the default PXDPerformanceVariablesCollector
227235
import modularAnalysis as ana
228236
import vertex
229-
from variables import variables as vm
230237
# Particle list for gain calibration
231-
ana.fillParticleList('e+:gain', "p > 1.0", path=main)
238+
p = particle_type
239+
ana.fillParticleList(f'{p}+:gain', track_cuts_4gain, path=main)
232240

233241
# Particle list for event selection in efficiency monitoring
234242
# nSVDHits > 5 doesn't help, firstSVDLayer == 3 for < 0.1% improvement?
235-
ana.fillParticleList('e+:eff', "pt > 2.0", path=main)
243+
ana.fillParticleList(f'{p}+:eff', track_cuts_4eff, path=main)
236244
# Mass cut (9.5 < M < 11.5) below can improve efficiency by ~ 1%
237-
ana.reconstructDecay('vpho:eff -> e+:eff e-:eff', '9.5<M<11.5', path=main)
245+
ana.reconstructDecay(f'vpho:eff -> {p}+:eff {p}-:eff', '9.5<M<11.5', path=main)
238246
# < 0.1% improvement by using kfit pvalue >= 0.01 after mass cut
239247
# vertex.kFit('vpho:eff', conf_level=0.01, fit_type="fourC", daughtersUpdate=False, path=main)
240248

241249
# Particle list for studying impact parameter resolution
242250
# Alias dosn't work with airflow implementation
243251
# vm.addAlias("pBetaSinTheta3o2", "formula(pt * (1./(1. + tanLambda**2)**0.5)**0.5)")
244252
# vm.addAlias("absLambda", "abs(atan(tanLambda))")
245-
mySelection = 'pt>1.0 and abs(dz)<1.0 and dr<0.3'
246-
mySelection += ' and nCDCHits>20 and nSVDHits>=8 and nPXDHits>=1'
247-
mySelection += ' and [abs(atan(tanLambda)) < 0.5]'
248-
mySelection += ' and [formula(pt * (1./(1. + tanLambda**2)**0.5)**0.5) > 2.0]'
249-
# mySelection += ' and [absLambda<0.5]'
250-
# mySelection += ' and [pBetaSinTheta3o2>2.0]'
251-
ana.fillParticleList('e+:res', mySelection, path=main)
252-
ana.reconstructDecay('vpho:res -> e+:res e-:res', '9.5<M<11.5', path=main)
253+
track_cuts_4res_note2019 = 'pt>1.0 and abs(dz)<1.0 and dr<0.3'
254+
track_cuts_4res_note2019 += ' and nCDCHits>20 and nSVDHits>=8 and nPXDHits>=1'
255+
track_cuts_4res_note2019 += ' and [abs(atan(tanLambda)) < 0.5]'
256+
track_cuts_4res_note2019 += ' and [formula(pt * (1./(1. + tanLambda**2)**0.5)**0.5) > 2.0]'
257+
# track_cuts_4res_note2019 += ' and [absLambda<0.5]'
258+
# track_cuts_4res_note2019 += ' and [pBetaSinTheta3o2>2.0]'
259+
if track_cuts_4res == "Note2019":
260+
track_cuts_4res = track_cuts_4res_note2019
261+
ana.fillParticleList(f'{p}+:res', track_cuts_4res, path=main)
262+
ana.reconstructDecay(f'vpho:res -> {p}+:res {p}-:res', '9.5<M<11.5', path=main)
253263
# Remove multiple candidate events
254264
ana.applyCuts('vpho:res', 'nParticlesInList(vpho:res)==1', path=main)
255265
vertex.kFit('vpho:res', conf_level=0.0, path=main)
256266

257-
collector.param("PList4GainName", "e+:gain")
267+
collector.param("PList4GainName", f"{p}+:gain")
258268
collector.param("PList4EffName", "vpho:eff")
259269
collector.param("PList4ResName", "vpho:res")
260270
collector.param("maskedDistance", 3)

pxd/scripts/pxd/calibration/calibration_checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def fill_graphs(self):
221221
self.sum_graphs["hot_dead"].append(current_run, sum_hotdeadfraction / nSensors)
222222

223223
nSensors = nSensors - len(dead_checker.dbObj.getDeadSensorMap())
224-
if current_run == saved_run_occ:
224+
if current_run == saved_run_occ and nSensors > 0:
225225
self.sum_graphs["occ_masked"].append(current_run, sum_occupancymasked / nSensors)
226226
self.sum_graphs["occ_no_mask"].append(current_run, sum_occupancynomask / nSensors)
227227

pxd/scripts/pxd/utils/plots.py

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ def df_plot_errorbar(df, x, y, yerr_low, yerr_up, ax=None, *args, **kwargs):
114114
ax.legend()
115115
ax.set_xlabel(x)
116116
ax.set_ylabel(y)
117+
return ax
117118

118119

119120
# Extend pandas.DataFrame
@@ -181,7 +182,7 @@ def plot_efficiency_map(tree, exp_runs=[], num_name="hTrackClustersLayer1", den_
181182
exp_runs = sorted(exp_runs)
182183
use_exp_run_tuple = False
183184
count = 0
184-
h_num, h_den = None, None
185+
h_eff, h_num, h_den = None, None, None
185186
for i_evt in range(tree.GetEntries()):
186187
tree.GetEntry(i_evt)
187188
exp = getattr(tree, "exp")
@@ -199,14 +200,36 @@ def plot_efficiency_map(tree, exp_runs=[], num_name="hTrackClustersLayer1", den_
199200
h_den.Add(getattr(tree, den_name))
200201
count += 1
201202
if count:
202-
h_num.Divide(h_den)
203-
h_num.SetTitle(title)
204-
h_num.SetStats(False)
205-
h_num.Draw("colz")
203+
h_temp = h_den.Clone()
204+
h_temp.Divide(h_den) # h_temp bins filled to 1 if there is any counts in h_den
205+
h_eff = h_num.Clone()
206+
h_eff.Add(h_temp, 1e-9) # Added 1e-9 which shouldn't bias eff
207+
h_eff.Divide(h_den)
208+
h_eff.SetTitle(title)
209+
h_eff.SetStats(True)
210+
# default_opt_stat = ROOT.gStyle.GetOptStat()
211+
ROOT.gStyle.SetOptStat(10)
212+
h_eff.Draw("colz")
206213
canvas.Draw()
214+
s = h_eff.GetListOfFunctions().FindObject("stats")
215+
# print(s.GetX1NDC(), s.GetX2NDC())
216+
s.SetX1NDC(0.7)
217+
s.SetX2NDC(0.9)
218+
s.SetY1NDC(0.9)
219+
s.SetY2NDC(0.95)
220+
s.SetFillColorAlpha(0, 0.1)
221+
s.SetLineColorAlpha(0, 0)
222+
canvas.Update()
207223
if save_to:
224+
h_eff.GetZaxis().SetRangeUser(0.9, 1)
225+
canvas.Update()
226+
canvas.Print(save_to+".above90.png")
227+
h_eff.GetZaxis().SetRangeUser(0, 1)
228+
canvas.Update()
208229
canvas.Print(save_to)
209-
return h_num
230+
231+
# ROOT.gStyle.SetOptStat(default_opt_stat)
232+
return h_eff, h_num, h_den
210233

211234

212235
def plot_in_module_efficiency(df, pxdid=1052, figsize=(12, 16), alpha=0.7, save_to="",
@@ -303,14 +326,16 @@ def plot_module_efficiencies_in_DHHs(df, eff_var="eff_sel", phase="early_phase3"
303326
}
304327
for dhh, pxdid_list in dhh_modules_dic.items():
305328
plt.figure(figsize=figsize)
329+
ymin = 1.0
306330
for pxdid in pxdid_list:
307331
df.query(f"{eff_var}>0&pxdid=={pxdid}&{eff_var}_err_low<0.01").errorbar(
308332
y=eff_var, x="run", yerr_low=f"{eff_var}_err_low", yerr_up=f"{eff_var}_err_up", label=f"{pxdid}", alpha=0.7)
309-
plt.title(dhh + " efficiency")
310-
ymin, ymax = plt.ylim()
311-
plt.ylim(ymin, 1.0)
312-
if save_to:
313-
plt.savefig(dhh + "_" + save_to)
333+
ymin = min(plt.ylim()[0], ymin)
334+
plt.ylabel("Efficiency (selected)")
335+
plt.title(dhh + " efficiency")
336+
plt.ylim(ymin, 1.0)
337+
if save_to:
338+
plt.savefig(dhh + "_" + save_to)
314339

315340

316341
if __name__ == '__main__':

0 commit comments

Comments
 (0)