Skip to content
Snippets Groups Projects

feat: dRICH benchmarks

Merged Christopher Dilks requested to merge irt-algo into master
1 file
+ 155
0
Compare changes
  • Side-by-side
  • Inline
+ 155
0
 
#!/usr/bin/ruby
 
# Copyright 2023, Christopher Dilks
 
# Subject to the terms in the LICENSE file found in the top-level directory.
 
 
require 'optparse'
 
require 'ostruct'
 
 
###################################
 
# constants:
 
IdealTheta = 23.5 # [degrees]
 
IdealEnergy = 20.0 # [GeV]
 
IdealParticle = 'pi+'
 
###################################
 
 
# setup
 
# ---------------------------------------------------
 
 
# default opt
 
opt = OpenStruct.new
 
opt.evgen = ''
 
opt.sim_file = 'sim.edm4hep.root'
 
opt.rec_file = 'rec.edm4hep.root'
 
opt.ana_file = 'ana.edm4hep.root'
 
opt.run_sim = true
 
opt.run_rec = true
 
opt.run_ana = true
 
opt.num_events = 10
 
opt.algos = Array.new
 
opt.plots = Array.new
 
opt.verbosity = 0
 
opt.dry_run = false
 
 
# available event generation modes
 
avail_evgens = [
 
'idealAngle',
 
'minTheta',
 
'maxTheta',
 
]
 
 
# parse options
 
OptionParser.new do |o|
 
o.banner = "USAGE: #{$0} [OPTIONS]..."
 
o.separator ''
 
o.separator 'required options:'.upcase
 
o.on("-e", "--evgen [EVGEN_MODE]", "Event generation mode, one of:") do |a|
 
unless avail_evgens.include? a
 
$stderr.puts "ERROR: unknown event generation mode '#{a}'"
 
exit 1
 
end
 
opt.evgen = a
 
end
 
avail_evgens.each{ |i| o.separator i.rjust 50 }
 
o.separator ''
 
o.separator 'optional options:'.upcase
 
o.on("--sim-file", "simulation file name", "default = #{opt.sim_file}") { |a| opt.sim_file=a }
 
o.on("--rec-file", "reconstruction file name", "default = #{opt.rec_file}") { |a| opt.rec_file=a }
 
o.on("--ana-file", "analysis file name", "default = #{opt.ana_file}") { |a| opt.ana_file=a }
 
o.separator ''
 
o.on("-n", "--num-events [NUM_EVENTS]", Integer, "Number of events", "default = #{opt.num_events}") { |a| opt.num_events=a }
 
o.separator ''
 
o.on("--[no-]sim", "simulation on/off", "default = #{opt.run_sim ? 'on' : 'off'}") { |a| opt.run_sim=a }
 
o.on("--[no-]rec", "reconstruction on/off", "default = #{opt.run_rec ? 'on' : 'off'}") { |a| opt.run_rec=a }
 
o.on("--[no-]ana", "analysis on/off", "default = #{opt.run_ana ? 'on' : 'off'}") { |a| opt.run_ana=a }
 
o.separator ''
 
o.on("-a", "--algos [ALGORITHMS]...", Array, "List of analysis algorithms to run", "default = all") { |a| opt.algos=a }
 
o.on("-p", "--plots [PLOTS]...", Array, "List of plots to draw", "default = all") { |a| opt.plots=a }
 
o.separator ''
 
o.on("-v", "Increase verbosity (-vv for more verbose)") { |a| opt.verbosity+=1 }
 
o.on("-d", "--dry-run" "Dry run (just print commands)") { |a| opt.dry_run=true }
 
o.separator ''
 
o.on_tail("-h", "--help", "Show this message") do
 
puts o
 
exit 2
 
end
 
end.parse!(ARGV.length>0 ? ARGV : ['--help'])
 
 
# get compact file
 
if ENV['DETECTOR_PATH'].nil? or ENV['DETECTOR_CONFIG'].nil?
 
$stderr.puts "ERROR: unknown DETECTOR_PATH or DETECTOR_CONFIG"
 
exit 1
 
end
 
compact_file = "#{ENV['DETECTOR_PATH']}/#{ENV['DETECTOR_CONFIG']}.xml"
 
 
 
# helper functions
 
# ---------------------------------------------------
 
def theta2xyz(theta)
 
rad = theta * Math::PI / 180
 
[ Math.sin(rad), 0.0, Math.cos(rad) ]
 
end
 
 
# fixed angle particle gun
 
evgen_fixed_angle = Proc.new do |theta, energy, particle|
 
[
 
'npsim',
 
'--runType', 'batch',
 
'--compactFile', compact_file,
 
'--outputFile', opt.sim_file,
 
'--enableGun',
 
'--numberOfEvents', opt.num_events,
 
'--gun.particle', particle,
 
'--gun.energy', "#{energy}*GeV",
 
'--gun.direction', "(#{theta2xyz(theta).join ', '})",
 
]
 
end
 
 
 
# define event generator command
 
# ---------------------------------------------------
 
evgen_cmd = Array.new
 
case opt.evgen
 
when 'idealAngle'
 
evgen_cmd = evgen_fixed_angle.call IdealTheta, IdealEnergy, IdealParticle
 
else
 
exit 1 # error already handled above
 
end
 
 
 
# define reconstruction command
 
# ---------------------------------------------------
 
output_collections = [
 
"DRICHHits",
 
"MCParticles",
 
"DRICHRawHits",
 
"DRICHRawHitsAssociations",
 
"DRICHAerogelTracks",
 
"DRICHGasTracks",
 
"DRICHAerogelIrtCherenkovParticleID",
 
"DRICHGasIrtCherenkovParticleID",
 
"DRICHMergedIrtCherenkovParticleID",
 
]
 
recon_cmd = [
 
'eicrecon',
 
"-Ppodio:output_include_collections=\"#{output_collections.join ','}\""
 
'-Pjana:nevents="0"',
 
'-Pjana:debug_plugin_loading="1"',
 
'-Pacts:MaterialMap="calibrations/materials-map.cbor"',
 
"-Ppodio:output_file=\"#{opt.rec_file}\"",
 
opt.sim_file,
 
]
 
 
# execute commands
 
# NOTE: `raise` exits with non-zero exit code, if the `system` command failed
 
# ---------------------------------------------------
 
exe = Proc.new |cmd_args, name|
 
cmd = cmd_args.join ' '
 
puts "#{name} command:".upcase
 
unless opt.dry_run
 
system cmd or raise "#{name} failed!"
 
end
 
puts '-'*50
 
end
 
puts '-'*50
 
exe.call evgen_cmd
 
exe.call recon_cmd
Loading