-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Committing TS Firmware Hit Reconstruction Stagger for the Purpose of …
…Triggering Studies (#1473) In my last pull request, I added the validated processor which stagged analysis digi objects to be inserted into our most current version of cluster reconstruction. In this pull request, I am adding the validate processor which inserts the most currect validated version of hit reconstruction into the analysis chain so that Elizabeth may play with it. It is a little different from the S30XL implementation primarily in that its input FIFO pragmas mean that it would need to run around 5 clock cycles as written (though LK said we would likely integrate over 3) and would need 5 copies to run continuously; the S30XL runs continuously and if we were to do that here the pragma structure would need to be altered a little bit. This is all unnecessary detail, just note that this is the first validated piece of hit making firmware designed for the full LDMX environment that emulates LK's original manner of reconstruction. This is done in TrigScintFirmwareHitProducer, which takes in QIEDigis and outputs TrigScintHit objects. The processor will ultimately be adopted to emulate the NumericalHitProcessor of Andrew and Niramay as that seems the easiest to reproduce in something that can run in firmware. I am including it here because it is the "official" processor I will use to emulate in firmware. If it needs some refashioning or being made pretty, please lmk. I can also include it in a latter pull request alongside the firmware pileUp processor if necessary. Here are proofs that the firmware emulates the software hits (from QIE adcs and tdcs) faithfully. Note that our ap_int resolution here means that if you fiddle with the gains (i.e. make them bigger) you will note get the right hit PE amplitudes: SAMPLE OUTPUT: Analysis barID: 2, PE Number: 59.4437 Analysis barID: 3, PE Number: 97.9569 Analysis barID: 22, PE Number: 79.7444 Analysis barID: 23, PE Number: 89.955 Analysis barID: 35, PE Number: 158.878 Analysis barID: 36, PE Number: 61.3231 DID I GET HERE 3 DID I GET HERE 4 DID I GET HERE 5 Firmware barID: 2, PE Number: 59 Firmware barID: 3, PE Number: 98 Firmware barID: 22, PE Number: 79 Firmware barID: 23, PE Number: 90 Firmware barID: 35, PE Number: 159 Firmware barID: 36, PE Number: 61 Firmware barID: 49, PE Number: 8 DID I GET HERE 6 Note that the reason there is an extra hit printed in the Firmware in bar 49 in this case is because I didn't print analysis hits with amplitude below 30. I can fix that, but I have seen enough of the output to know that the firmware is replicating the software appropriattely. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: rodwyer100
- Loading branch information
1 parent
8efa112
commit 6e4d9f7
Showing
8 changed files
with
585 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
#!/bin/python | ||
|
||
import sys | ||
import os | ||
import json | ||
|
||
# we need the ldmx configuration package to construct the object | ||
|
||
from LDMX.Framework import ldmxcfg | ||
|
||
# set a 'pass name' | ||
passName="sim" | ||
p=ldmxcfg.Process(passName) | ||
|
||
#import all processors | ||
from LDMX.SimCore import generators | ||
from LDMX.SimCore import simulator | ||
from LDMX.Biasing import filters | ||
|
||
from LDMX.Detectors.makePath import * | ||
from LDMX.SimCore import simcfg | ||
|
||
#pull in command line options | ||
nEle=4 # simulated beam electrons | ||
runNum=10 | ||
version="ldmx-det-v14" | ||
outputNameString= "ldmxdetv14gap10mm_firmware.root" #sample identifier | ||
outDir= "" #sample identifier | ||
|
||
# | ||
# Instantiate the simulator. | ||
# | ||
sim = simulator.simulator("test") | ||
|
||
# | ||
# Set the path to the detector to use (pulled from job config) | ||
# | ||
sim.setDetector( version, True ) | ||
sim.scoringPlanes = makeScoringPlanesPath(version) | ||
|
||
outname=outputNameString #+".root" | ||
print("NAME = " + outname) | ||
|
||
# | ||
# Set run parameters. These are all pulled from the job config | ||
# | ||
p.run = runNum | ||
p.maxEvents = 100 | ||
nElectrons = nEle | ||
beamEnergy = 4.0; #in GeV | ||
|
||
sim.description = "Inclusive "+str(beamEnergy)+" GeV electron events, "+str(nElectrons)+"e" | ||
#sim.randomSeeds = [ SEED1 , SEED2 ] | ||
sim.beamSpotSmear = [20., 80., 0] | ||
|
||
|
||
mpgGen = generators.multi( "mgpGen" ) # this is the line that actually creates the generator | ||
mpgGen.vertex = [ -44., 0., -880. ] # mm | ||
mpgGen.nParticles = nElectrons | ||
mpgGen.pdgID = 11 | ||
mpgGen.enablePoisson = False #True | ||
|
||
import math | ||
theta = math.radians(5.45) | ||
beamEnergyMeV=1000*beamEnergy | ||
px = beamEnergyMeV*math.sin(theta) | ||
py = 0.; | ||
pz= beamEnergyMeV*math.cos(theta) | ||
mpgGen.momentum = [ px, py, pz ] | ||
|
||
# | ||
# Set the multiparticle gun as generator | ||
# | ||
sim.generators = [ mpgGen ] | ||
|
||
#reconstruction and vetoes | ||
|
||
#Ecal and Hcal hardwired/geometry stuff | ||
#import LDMX.Ecal.EcalGeometry | ||
import LDMX.Ecal.ecal_hardcoded_conditions | ||
from LDMX.Ecal import EcalGeometry | ||
#egeom = EcalGeometry.EcalGeometryProvider.getInstance() | ||
#Hcal hardwired/geometry stuff | ||
from LDMX.Hcal import HcalGeometry | ||
import LDMX.Hcal.hcal_hardcoded_conditions | ||
#hgeom = HcalGeometry.HcalGeometryProvider.getInstance() | ||
|
||
|
||
from LDMX.Ecal import digi as eDigi | ||
from LDMX.Ecal import vetos | ||
from LDMX.Hcal import digi as hDigi | ||
from LDMX.Hcal import hcal | ||
|
||
from LDMX.Recon.simpleTrigger import TriggerProcessor | ||
|
||
from LDMX.TrigScint.trigScint import TrigScintDigiProducer | ||
from LDMX.TrigScint.trigScint import TrigScintClusterProducer | ||
from LDMX.TrigScint.trigScint import trigScintTrack | ||
from LDMX.TrigScint.trigScint import TrigScintFirmwareTracker | ||
|
||
tsSimColls=[ "TriggerPad2SimHits", "TriggerPad3SimHits", "TriggerPad1SimHits" ] | ||
|
||
# ecal digi chain | ||
# ecalDigi =eDigi.EcalDigiProducer('EcalDigis') | ||
# ecalReco =eDigi.EcalRecProducer('ecalRecon') | ||
# ecalVeto =vetos.EcalVetoProcessor('ecalVetoBDT') | ||
|
||
# #hcal digi chain | ||
# hcalDigi =hDigi.HcalDigiProducer('hcalDigis') | ||
# hcalReco =hDigi.HcalRecProducer('hcalRecon') | ||
# hcalVeto =hcal.HcalVetoProcessor('hcalVeto') | ||
# #hcalDigi.inputCollName="HcalSimHits" | ||
#hcalDigi.inputPassName=passName | ||
|
||
# TS digi + clustering + track chain | ||
tsDigisTag =TrigScintDigiProducer.pad2() | ||
tsDigisTag.input_collection = tsSimColls[0]# +"_"+passName | ||
tsDigisTag.input_pass_name = "sim" | ||
tsDigisUp =TrigScintDigiProducer.pad3() | ||
tsDigisUp.input_collection = tsSimColls[1]# +"_"+passName | ||
tsDigisUp.input_pass_name = "sim" | ||
tsDigisDown=TrigScintDigiProducer.pad1() | ||
tsDigisDown.input_collection = tsSimColls[2]# +"_"+passName | ||
tsDigisDown.input_pass_name = "sim" | ||
|
||
tsClustersTag =TrigScintClusterProducer.pad2() | ||
tsClustersUp =TrigScintClusterProducer.pad1() | ||
tsClustersDown =TrigScintClusterProducer.pad3() | ||
|
||
|
||
tsDigisUp.verbosity=0 | ||
tsClustersUp.verbosity=1 | ||
trigScintTrack.verbosity=1 | ||
|
||
trigScintTrack.delta_max = 0.75 | ||
|
||
trigFirm = TrigScintFirmwareTracker( "trigFirm" ) | ||
trigFirm.input_pass_name = "sim" | ||
trigFirm.digis1_collection = "trigScintDigisPad1" | ||
trigFirm.digis2_collection = "trigScintDigisPad2" | ||
trigFirm.digis3_collection = "trigScintDigisPad3" | ||
trigFirm.output_collection = "TriggerPadTracksFirmware" | ||
|
||
from LDMX.Recon.electronCounter import ElectronCounter | ||
eCount = ElectronCounter( nElectrons, "ElectronCounter") # first argument is number of electrons in simulation | ||
eCount.use_simulated_electron_number = False | ||
eCount.input_collection="TriggerPadTracks" | ||
eCount.input_pass_name=passName | ||
|
||
from LDMX.TrigScint.trigScint import TrigScintFirmwareHitProducer | ||
from LDMX.TrigScint.trigScint import TrigScintQIEDigiProducer | ||
from LDMX.TrigScint.trigScint import TrigScintRecHitProducer | ||
|
||
qieDigi = TrigScintQIEDigiProducer.pad3() | ||
rechit = TrigScintRecHitProducer.pad3() | ||
hitFirm = TrigScintFirmwareHitProducer( "hitFirm" ) | ||
hitFirm.verbose = True | ||
|
||
|
||
|
||
# # p.sequence=[ sim, ecalDigi, ecalReco, ecalVeto, hcalDigi, hcalReco, hcalVeto, tsDigisTag, tsDigisUp, tsDigisDown, tsClustersTag, tsClustersUp, tsClustersDown, trigScintTrack, eCount ] | ||
# #hcal digi keeps crashing in config step | ||
p.sequence=[ sim, tsDigisTag, tsDigisUp, tsDigisDown, tsClustersTag, tsClustersUp, tsClustersDown, trigScintTrack, trigFirm, eCount, qieDigi, rechit, hitFirm] | ||
# p.sequence=[sim] | ||
|
||
p.outputFiles=[outname] | ||
|
||
p.termLogLevel = 0 # default is 2 (WARNING); but then logFrequency is ignored. level 1 = INFO. | ||
|
||
#print this many events to stdout (independent on number of events, edge case: round-off effects when not divisible. so can go up by a factor 2 or so) | ||
logEvents=20 | ||
if p.maxEvents < logEvents : | ||
logEvents = p.maxEvents | ||
p.logFrequency = int( p.maxEvents/logEvents ) | ||
|
||
json.dumps(p.parameterDump(), indent=2) | ||
|
||
with open('parameterDump.json', 'w') as outfile: | ||
json.dump(p.parameterDump(), outfile, indent=4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#ifndef HITPRODUCER_H | ||
#define HITPRODUCER_H | ||
|
||
#include "objdef.h" | ||
|
||
#ifdef TS_NOT_EMULATION | ||
void copyHit1(Hit One, Hit Two); | ||
void copyHit2(Hit One, Hit Two); | ||
void hitproducer_ref(ap_uint<14> FIFO[NHITS][5], Hit outHit[NHITS], | ||
ap_uint<8> Peds[NHITS]); | ||
#endif | ||
void hitproducer_hw(ap_uint<14> FIFO[NHITS][5], Hit outHit[NHITS], | ||
ap_uint<8> Peds[NHITS]); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
TrigScint/include/TrigScint/TrigScintFirmwareHitProducer.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/** | ||
* @file TrigScintFirmwareHitProducer.h | ||
* @brief Staging of Real Hits | ||
* @author Lene Kristian Bryngemark, Stanford University | ||
*/ | ||
|
||
#ifndef TRIGSCINT_TRIGSCINTFIRMWAREHITPRODUCER_H | ||
#define TRIGSCINT_TRIGSCINTFIRMWAREHITPRODUCER_H | ||
|
||
/*~~~~~~~~~~*/ | ||
/* ROOT */ | ||
/*~~~~~~~~~~*/ | ||
#include "TRandom3.h" | ||
|
||
// LDMX | ||
#include "DetDescr/TrigScintID.h" | ||
#include "Recon/Event/EventConstants.h" | ||
#include "Tools/NoiseGenerator.h" | ||
#include "TrigScint/Event/TrigScintHit.h" | ||
#include "TrigScint/Event/TrigScintQIEDigis.h" | ||
|
||
/*~~~~~~~~~~~~~~~*/ | ||
/* Framework */ | ||
/*~~~~~~~~~~~~~~~*/ | ||
#include "Framework/Configure/Parameters.h" | ||
#include "Framework/EventProcessor.h" | ||
|
||
/*~~~~~~~~~~~*/ | ||
/* TrigScint */ | ||
/*~~~~~~~~~~~*/ | ||
#include "TrigScint/Firmware/objdef.h" | ||
#include "TrigScint/SimQIE.h" | ||
|
||
namespace trigscint { | ||
|
||
/** | ||
* @class TrigScintFirmwareHitProducer | ||
* @brief | ||
*/ | ||
class TrigScintFirmwareHitProducer : public framework::Producer { | ||
public: | ||
TrigScintFirmwareHitProducer(const std::string& name, | ||
framework::Process& process) | ||
: Producer(name, process) {} | ||
|
||
void configure(framework::config::Parameters& ps) override; | ||
|
||
void produce(framework::Event& event) override; | ||
|
||
/** | ||
* add a hit at index idx to a cluster | ||
*/ | ||
|
||
private: | ||
/// Name of the input collection containing the sim hits | ||
std::string inputCollection_; | ||
|
||
/// Name of the pass that the input collection is on (empty string means take | ||
/// any pass) | ||
std::string inputPassName_; | ||
|
||
/// Name of the output collection that will be used to stored the | ||
/// digitized trigger scintillator hits | ||
std::string outputCollection_; | ||
|
||
/// SiPM gain | ||
double gain_{1e6}; | ||
|
||
/// QIE pedestal | ||
double pedestal_{6.0}; | ||
|
||
/// Total MeV per MIP | ||
double mevPerMip_{1.40}; | ||
|
||
/// Total number of photoelectrons per MIP | ||
double pePerMip_{13.5}; | ||
|
||
/// Total number of photoelectrons per MIP | ||
int sample_of_interest_{2}; | ||
|
||
std::string testCollection_; | ||
|
||
bool doTest_{true}; | ||
}; | ||
|
||
} // namespace trigscint | ||
|
||
#endif /* TRIGSCINT_TRIGSCINTFIRMWAREHITPRODUCER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.