def EventAnalysis(self): """Main event analysis function, called for each event.""" # Require a good data quality flag if self.DAQ.ND280OffFlag > 0: return if self.trigger and self.trigger == "FGD": if (not self.BasicHeader.FGDCosmicEvent ) or self.BasicHeader.TripTCosmicEvent: return if self.ReconPerfEval.NGlobalReconObject > 25: return self.numEvents["All"] += 1 for obj in self.ReconPerfEval.GlobalReconObject: if obj.SetOK and obj.StatusString.find("success") != -1: # FV and timing cuts, if requested. if self.cuttype: isMC = (self.BasicHeader.RunID > 100000) if not timing_cuts.PassesCut(isMC, self.BasicHeader.RunID, obj.Position.T()): continue if not volume_cuts.IsInVolume(obj.Position.Vect(), self.cuttype): continue # The matching_chi2Info object contains a TClonesArray of objects relating to # the matching at various stages of combining consittuents to get to the global object. # Only the matches that have a Matching Chi2 value set are stored. for match in obj.MatchingChi2Info: if match.SetOK: # The subdetectors each constituent was in det1 = match.Det1 det2 = match.Det2 # Whether the objects were showers sh1 = match.IsShower1 sh2 = match.IsShower2 # The Matching Chi2 value when matching the two objects. val = match.MatchingChi2 if det2.find("TPC") != -1 or det2.find("FGD") != -1: det1, det2 = det2, det1 sh1, sh2 = sh2, sh1 # Always add to the main document. self.Fillmatching_chi2Plots(det1, det2, sh1, sh2, val, False) # If the topology meets certain criteria, also add to the summary document. if grtf_tools.IsOnlyTracker( det1) and det2 == "(DSECal)": self.Fillmatching_chi2Plots( "(TRACKER)", "(DSECal)", sh1, sh2, val, True) if grtf_tools.IsOnlyTracker(det1) and ( det2 == "(LTECal)" or det2 == "(TTECal)" or det2 == "(BTECal)" or det2 == "(RTECal)"): self.Fillmatching_chi2Plots( "(TRACKER)", "(xTECal)", sh1, sh2, val, True) if grtf_tools.IsOnlyTracker(det1) and ( det2 == "(LPECal)" or det2 == "(TPECal)" or det2 == "(BPECal)" or det2 == "(RPECal)"): self.Fillmatching_chi2Plots( "(TRACKER)", "(xPECal)", sh1, sh2, val, True) if grtf_tools.IsOnlyTracker(det1) and ( det2 == "(LSMRD)" or det2 == "(TSMRD)" or det2 == "(BSMRD)" or det2 == "(RSMRD)"): self.Fillmatching_chi2Plots( "(TRACKER)", "(xSMRD)", sh1, sh2, val, True) if grtf_tools.IsOnlyTracker(det1) and det2 == "(P0D)": self.Fillmatching_chi2Plots( "(TRACKER)", "(P0D)", sh1, sh2, val, True) if det1 == "(TPC3)" and det2 == "(DSECal)": self.Fillmatching_chi2Plots( "(TPC3)", "(DSECal)", sh1, sh2, val, True) if det1 == "(TPC1)" and det2 == "(P0D)": self.Fillmatching_chi2Plots( "(TPC1)", "(P0D)", sh1, sh2, val, True) if (det1 == "(TPC1)" or det1 == "(TPC2)" or det1 == "(TPC3)") and (det2 == "(LTECal)" or det2 == "(TTECal)" or det2 == "(BTECal)" or det2 == "(RTECal)"): self.Fillmatching_chi2Plots( "(TPCn)", "(xTECal)", sh1, sh2, val, True) return
def EventAnalysis(self): """Main event analysis function, called for each event.""" # Require a good data quality flag if self.DAQ.ND280OffFlag > 0: return if self.trigger and self.trigger == "FGD": if (not self.BasicHeader.FGDCosmicEvent ) or self.BasicHeader.TripTCosmicEvent: return if self.ReconPerfEval.NGlobalReconObject > 25: return self.numEvents["All"] += 1 for obj in self.ReconPerfEval.GlobalReconObject: if obj.SetOK and obj.StatusString.find("success") != -1: # FV and timing cuts, if requested. if self.cuttype: isMC = (self.BasicHeader.RunID > 100000) if not timing_cuts.PassesCut(isMC, self.BasicHeader.RunID, obj.Position.T()): continue if not volume_cuts.IsInVolume(obj.Position.Vect(), self.cuttype): continue # Only look at forwards-going objects as the reversal changes the momentum greatly. if obj.NDownToTrackerConstituents > 0 and obj.Direction.Z( ) > 0: # Get the tracker-only constituent, which is the last entry in DownToTrackerConstituents. trackerCon = obj.DownToTrackerConstituents[-1] tracker = { "Det": trackerCon.DetectorName, "Mom": trackerCon.Momentum } # Get the TPC constituents, and plot the TPC-Tracker differences. for i_con, con in enumerate(obj.Constituents): if con.DetectorName.find("TPC") != -1: tpc = { "Det": con.DetectorName, "Mom": con.GlobalReconConsFirstNodeState.Momentum } self.Filltpc_tracker_momPlots( tracker["Det"], tracker["Mom"], tpc["Det"], tpc["Mom"], "tpc_vs_tracker_mom", obj.ParticleID) # Also plot the difference between the respective TPC momenta for i_con2, con2 in enumerate(obj.Constituents): tpc1 = tpc if con2.DetectorName.find( "TPC") != -1 and i_con != i_con2: tpc2 = { "Det": con2.DetectorName, "Mom": con2.GlobalReconConsFirstNodeState. Momentum } if tpc["Det"] == "(TPC3)" or tpc2[ "Det"] == "(TPC1)": tpc1, tpc2 = tpc2, tpc1 self.Filltpc_tracker_momPlots( tpc2["Det"], tpc2["Mom"], tpc1["Det"], tpc1["Mom"], "inter_tpc_mom", obj.ParticleID) return
def EventAnalysis(self): """Main event analysis function, called for each event.""" # Require a good data quality flag. if self.DAQ.ND280OffFlag > 0: return if self.trigger and self.trigger == "FGD": if (not self.BasicHeader.FGDCosmicEvent ) or self.BasicHeader.TripTCosmicEvent: return if self.ReconPerfEval.NGlobalReconObject > 25: return self.numEvents["All"] += 1 for obj in self.ReconPerfEval.GlobalReconObject: if obj.SetOK and obj.StatusString.find("success") != -1: # FV and timing cuts, if requested. if self.cuttype: isMC = (self.BasicHeader.RunID > 100000) if not timing_cuts.PassesCut(isMC, self.BasicHeader.RunID, obj.Position.T()): continue if not volume_cuts.IsInVolume(obj.Position.Vect(), self.cuttype): continue base = "ERR" fgd = "ERR" # Ensure we have either an FGD1 or FGD2 constituent to compare to. if obj.SubdetectorString.find("FGD1") != -1: base = "HasFGD1" fgd = "(FGD1)" elif obj.SubdetectorString.find("FGD2") != -1: base = "NoFGD1" fgd = "(FGD2)" else: continue # Store the time of all constituents in this track. times = {} for rawdet in grtf_tools.detStrings: det = "(" + rawdet + ")" times[det] = [] for con in obj.Constituents: det = con.DetectorName time = con.GlobalReconConsState.Position.T() if con.AverageHitTime != -10000: time = con.AverageHitTime times[det].append(time) if len(times[fgd]) == 0: raise UserWarning( "No " + fgd + " times, but obj has " + fgd + " constituent", times) # Choose the earliest FGD time, and compute the time difference for # all other constituents. fgdtime = min(times[fgd]) for det, timelist in times.iteritems(): for dettime in timelist: self.histos["timing_offsets"][base][det].Fill(dettime - fgdtime) return
def FillTPCMatching(self, det1, det2): """ Test the matching efficiency for this pair of detectors. The testing works by looking for objects with constituents in the two detectors of interest. The TPC constituent must extrapolate to the inner face of the other subdetector. If we find constituents that are part of the same global object then they are matched, otherwise they are unmatched. Keyword arguments: det1 - The TPC to look for objects in. det2 - THe other module to look for objects in. """ # Global objects containing matched/unmatched objects. matched = [] tpcUnmatched = [] otherUnmatched = [] for obj in self.ReconPerfEval.GlobalReconObject: # For these plots, require the global object to have been successfully fitted. if obj.SetOK and obj.StatusString.find("success") != -1: # FV and timing cuts if requested. if self.cuttype: isMC = (self.BasicHeader.RunID > 100000) if not timing_cuts.PassesCut(isMC, self.BasicHeader.RunID, obj.Position.T()): continue if not volume_cuts.IsInVolume(obj.Position.Vect(), self.cuttype): continue tpcCons = [] otherCons = [] # Search for constituents that are in the right subdetectors. for con in obj.Constituents: if con.DetectorName.find(det1) != -1: # TPC constituents must also extrapolate to the inner face of the otehr module. if det2 == "DSECal" or det2 == "P0D": if det2 == "DSECal": [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.DSECALExtent) extrap = con.StateAtDSECal.Position else: [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.P0DExtent) extrap = con.StateAtP0D.Position if (min.X() < extrap.X() < max.X()) and ( min.Y() < extrap.Y() < max.Y()): tpcCons.append(con) elif det2 == "LTECal" or det2 == "RTECal": if det2 == "RTECal": [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL2Extent) extrap = con.StateAtRTECal.Position else: [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL5Extent) extrap = con.StateAtLTECal.Position if (min.Y() < extrap.Y() < max.Y()) and ( min.Z() < extrap.Z() < max.Z()): tpcCons.append(con) elif det2 == "BTECal" or det2 == "TTECal": if det2 == "BTECal": [minmod1, maxmod1] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL1Extent) [minmod2, maxmod2] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL4Extent) extrap = con.StateAtBTECal.Position else: [minmod1, maxmod1] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL3Extent) [minmod2, maxmod2] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL6Extent) extrap = con.StateAtTTECal.Position if ((minmod1.X() < extrap.X() < maxmod1.X()) and (minmod1.Z() < extrap.Z() < maxmod1.Z())) or ( (minmod2.X() < extrap.X() < maxmod2.X()) and (minmod2.Z() < extrap.Z() < maxmod2.Z())): tpcCons.append(con) if con.DetectorName.find(det2) != -1: # Non-TPC constituents must start / end in the appropriate section of the module. startPos = con.GlobalReconConsFirstNodeState.Position endPos = con.GlobalReconConsLastNodeState.Position gap = 100 if det2 == "DSECal": [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.DSECALExtent) if startPos.Z() < (min.Z() + gap) or endPos.Z() < ( min.Z() + gap): otherCons.append(con) elif det2 == "P0D": [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.P0DActive) if startPos.Z() > (max.Z() - gap) or endPos.Z() > ( max.Z() - gap): otherCons.append(con) elif det2 == "RTECal": [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL2Extent) if startPos.X() > (max.X() - gap) or endPos.X() > ( max.X() - gap): otherCons.append(con) elif det2 == "LTECal": [min, max] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL5Extent) if startPos.X() < (min.X() + gap) or endPos.X() < ( min.X() + gap): otherCons.append(con) elif det2 == "BTECal": [minmod1, maxmod1] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL1Extent) if startPos.Y() > (maxmod1.Y() - gap) or endPos.Y( ) > (maxmod1.Y() - gap): otherCons.append(con) elif det2 == "TTECal": [minmod1, maxmod1] = grtf_tools.GetMinMax( self.GeometrySummary.TECAL3Extent) if startPos.Y() < (minmod1.Y() + gap) or endPos.Y( ) < (minmod1.Y() + gap): otherCons.append(con) # See if this object meets our (un)matched criteria. if len(tpcCons) > 0 and len(otherCons) > 0: matched.append({"TPC": tpcCons, "Other": otherCons}) elif len(tpcCons) > 0: tpcUnmatched.append({"TPC": tpcCons}) elif len(otherCons) > 0: otherUnmatched.append({"Other": otherCons}) # We're not interested in any of the global objects - break out. if len(matched) == 0 and len(otherUnmatched) == 0: return # Fill the histograms. self.numEvents[det1 + det2] += 1 self.histos[det1 + "-" + det2]["NumObjects"]["NMatched"].Fill( len(matched)) self.histos[det1 + "-" + det2]["NumObjects"]["NUnmatched" + det1].Fill( len(tpcUnmatched)) self.histos[det1 + "-" + det2]["NumObjects"]["NUnmatched" + det2].Fill( len(otherUnmatched)) for obj in matched: for con in obj["TPC"]: self.FillPositions( getattr(con, "StateAt" + det2).Position, self.histos[det1 + "-" + det2]["Positions"]["Matched"][det1]) for con in obj["Other"]: pos = self.GetPositionToPlot( con.GlobalReconConsFirstNodeState.Position, con.GlobalReconConsLastNodeState.Position, det2) self.FillPositions( pos, self.histos[det1 + "-" + det2]["Positions"]["Matched"][det2]) for tpcCon in obj["TPC"]: state = getattr(tpcCon, "StateAt" + det2) tpcPos = state.Position for otherCon in obj["Other"]: otherPos = self.GetPositionToPlot( con.GlobalReconConsFirstNodeState.Position, con.GlobalReconConsLastNodeState.Position, det2).Vect() self.FillOffsets( tpcPos - otherPos, self.histos[det1 + "-" + det2]["Offsets"]["Matched"]) for obj in tpcUnmatched: for con in obj["TPC"]: self.FillPositions( getattr(con, "StateAt" + det2).Position, self.histos[det1 + "-" + det2]["Positions"]["Unmatched"][det1]) for obj in otherUnmatched: for con in obj["Other"]: pos = self.GetPositionToPlot( con.GlobalReconConsFirstNodeState.Position, con.GlobalReconConsLastNodeState.Position, det2) self.FillPositions( pos, self.histos[det1 + "-" + det2]["Positions"]["Unmatched"][det2]) for obj in tpcUnmatched: for tpcCon in obj["TPC"]: tpcPos = getattr(tpcCon, "StateAt" + det2).Position for obj2 in otherUnmatched: for otherCon in obj2["Other"]: otherPos = self.GetPositionToPlot( otherCon.GlobalReconConsFirstNodeState.Position, otherCon.GlobalReconConsLastNodeState.Position, det2).Vect() self.FillOffsets( tpcPos - otherPos, self.histos[det1 + "-" + det2]["Offsets"]["Unmatched"]) return
def EventAnalysis(self): """ Main event analysis function, called for each event. """ # Require a good data quality flag if self.DAQ.ND280OffFlag > 0: return if self.trigger and self.trigger == "FGD": if (not self.BasicHeader.FGDCosmicEvent) or self.BasicHeader.TripTCosmicEvent: return if self.ReconPerfEval.NGlobalReconObject > 25: return self.numEvents["All"] += 1 for obj in self.ReconPerfEval.GlobalReconObject: if obj.SetOK and obj.StatusString.find("success") != -1: # FV and timing cuts, if requested. if self.cuttype: isMC = (self.BasicHeader.RunID > 100000) if not timing_cuts.PassesCut(isMC, self.BasicHeader.RunID, obj.Position.T()): continue if not volume_cuts.IsInVolume(obj.Position.Vect(), self.cuttype): continue # Require tracks that are forwards-going and contain ECal or SMRD constituents. We explicitly require there # to NOT be a P0D constituent as that changes the momentum greatly. if obj.Direction.Z() > 0 and (obj.SubdetectorString.find("ECal") != -1 or obj.SubdetectorString.find("SMRD") != -1): if obj.SubdetectorString.find("P0D") == -1: if obj.NDownToTrackerConstituents > 0 and grtf_tools.IsInFGDFV(self.GeometrySummary, obj.Position): prev = {} new = {} # The DownToTrackerConstituents object contains information on all # intermediate constituents between the global object and the # tracker-only object. As we iterate through it, we get closer to the # tracker-only object. for ii, con in enumerate(obj.DownToTrackerConstituents): new = { "Det" : con.DetectorName, "Mom" : con.Momentum } # Note any objects that have odd topologies. The tracks are supposed to start # in the FGD FV and be forwards going, so if they have a TPC1 constituent, for # example, things are quite possibly broken. if new["Det"].find("SMRD") != -1 and new["Det"].find("DSECal") != -1: grtf_tools.PrintEvent(self, "_SMRD+DSECal_FGDFV_Forwards.txt", new["Det"]) if new["Det"].find("TPC1") != -1: grtf_tools.PrintEvent(self, "_TPC1_FGDFV_Forwards.txt", new["Det"]) if new["Det"].count("SMRD") == 2: grtf_tools.PrintEvent(self, "_TwoSMRDs_FGDFV_Forwards.txt", new["Det"]) if ii > 0: # Always fill a non-summary plot. self.Filltracker_global_momPlots(prev["Det"], prev["Mom"], new["Det"], new["Mom"], False) # For certain topologies, we record in a summary plot too. This makes it easier to # see the general state of things without diving in to a several hundred page PDF. if grtf_tools.IsOnlyTracker(new["Det"]) and prev["Det"].find("DSECal") != -1: self.Filltracker_global_momPlots("(TRACKER+DSECal)", prev["Mom"], "(TRACKER)", new["Mom"], True) if grtf_tools.IsOnlyTracker(new["Det"]) and prev["Det"].find("TECal") != -1: self.Filltracker_global_momPlots("(TRACKER+TECal)", prev["Mom"], "(TRACKER)", new["Mom"], True) if grtf_tools.IsOnlyTracker(new["Det"]) and prev["Det"].find("SMRD") != -1: self.Filltracker_global_momPlots("(TRACKER+SMRD)", prev["Mom"], "(TRACKER)", new["Mom"], True) if new["Det"].find("TECal") != -1 and new["Det"].find("SMRD") == -1 and prev["Det"].find("SMRD") != -1: self.Filltracker_global_momPlots("(TRACKER+TECal+SMRD)", prev["Mom"], "(TRACKER+TECal)", new["Mom"], True) prev = new return
def EventAnalysis(self): """Main event analysis function, called for each event.""" # Require a good data quality flag if self.DAQ.ND280OffFlag > 0: return if self.trigger and self.trigger == "FGD": if (not self.BasicHeader.FGDCosmicEvent ) or self.BasicHeader.TripTCosmicEvent: return if self.ReconPerfEval.NGlobalReconObject > 25: return self.numEvents["All"] += 1 for obj in self.ReconPerfEval.GlobalReconObject: if obj.SetOK and obj.StatusString.find("success") != -1: # FV and timing cuts, if requested. if self.cuttype: isMC = (self.BasicHeader.RunID > 100000) if not timing_cuts.PassesCut(isMC, self.BasicHeader.RunID, obj.Position.T()): continue if not volume_cuts.IsInVolume(obj.Position.Vect(), self.cuttype): continue path = obj.SubdetectorString new = False prev = False preprev = False summary = grtf_tools.ConvertPathToSummary(path) if path not in self.percentages["ByPos"]: self.percentages["ByPos"][path] = {"Total": 0, "Fail": 0} self.percentages["ByPos"][path]["Total"] += 1 failedByPos = False # Loop over the nodes and check for any that show bad kinks. for node in obj.GlobalNodes: new = node.NodeState if not new.SetOK: break if preprev: ok = self.FillByPosPlot(summary, preprev, prev, new, obj) if not ok: failedByPos = True preprev = prev prev = new # Print the details of this track if it contains a bad track. if failedByPos: self.percentages["ByPos"][path]["Fail"] += 1 if grtf_tools.ContainsTracker(obj.SubdetectorString): grtf_tools.PrintEvent(self, "TRACKER-Failures.txt", path) return