File indexing completed on 2024-06-01 07:06:28
0001
0002
0003
0004 require 'open3'
0005 require 'fileutils'
0006 require 'pycall/import'
0007
0008
0009 NumEvents = 70
0010 NumPoints = 10
0011 PoolSize = 6
0012 RunSimulation = true
0013 RunReconstruction = true
0014 UseRINDEXrange = false
0015 MaxNphot = 500
0016
0017
0018
0019
0020 if ARGV.length<2
0021 $stderr.puts """
0022 USAGE: #{$0} [d/p] [j/e]
0023 [d/p]: detector
0024 d: dRICH
0025 p: pfRICH
0026 [j/e]: reconstruction
0027 j: juggler [DEPRECATED, do not use]
0028 e: eicrecon
0029 """
0030 exit 2
0031 end
0032
0033
0034
0035 case ARGV[0]
0036 when "d"
0037 zDirection = 1
0038 xRICH = "dRICH"
0039 xrich = "drich"
0040 radiator_h = {
0041 :agl => { :id=>0, :testNum=>7, :rIndexRef=>1.0190, :rIndexRange=>[1.01852,1.02381], :maxMomentum=>20.0, :maxNPE=>20, },
0042 :gas => { :id=>1, :testNum=>8, :rIndexRef=>1.00076, :rIndexRange=>[1.00075,1.00084], :maxMomentum=>60.0, :maxNPE=>40, },
0043 }
0044 when "p"
0045 zDirection = -1
0046 xRICH = "pfRICH"
0047 xrich = "pfrich"
0048 radiator_h = {
0049 :agl => { :id=>0, :testNum=>7, :rIndexRef=>1.0190, :rIndexRange=>[1.01852,1.02381], :maxMomentum=>20.0, :maxNPE=>40, },
0050 :gas => { :id=>1, :testNum=>8, :rIndexRef=>1.0013, :rIndexRange=>[1.0013,1.0015], :maxMomentum=>60.0, :maxNPE=>40, },
0051 }
0052 else
0053 $stderr.puts "ERROR: unknown detector '#{ARGV[0]}'"
0054 exit 1
0055 end
0056
0057
0058 case ARGV[1]
0059 when "j"
0060 reconMethod = :juggler
0061 when "e"
0062 reconMethod = :eicrecon
0063 else
0064 $stderr.puts "ERROR: unknown reconstruction '#{ARGV[1]}'"
0065 exit 1
0066 end
0067
0068
0069 particle_h = {
0070 'e-' => { :mass=>0.00051, },
0071 'pi+' => { :mass=>0.13957, },
0072 'kaon+' => { :mass=>0.49368, },
0073 'proton' => { :mass=>0.93827, },
0074
0075
0076
0077
0078 }
0079
0080
0081 OutputDir = "out/momentum_scan.#{xrich}"
0082 if RunSimulation
0083 FileUtils.rm_r OutputDir, secure: true, verbose: true, force: true
0084 FileUtils.mkdir_p OutputDir
0085 end
0086 def out_file(prefix,ext)
0087 "#{OutputDir}/#{prefix}.#{ext}"
0088 end
0089
0090
0091 particle_h.keys.product(radiator_h.keys).each_slice(PoolSize) do |slice|
0092 pool = slice.map do |particle,rad_name|
0093 rad = radiator_h[rad_name]
0094
0095 sim_file = out_file particle, "sim.#{rad_name}.root"
0096 rec_file = out_file particle, "rec.#{rad_name}.root"
0097 ana_file = rec_file.sub /\.root/, '.ana.root'
0098 cmds = []
0099
0100 if RunSimulation
0101 cmds << [
0102 './simulate.py',
0103 "-t#{rad[:testNum]}",
0104 "-d#{zDirection}",
0105 "-p#{particle}",
0106 "-n#{NumEvents}",
0107 "-k#{NumPoints}",
0108 "-o#{sim_file}",
0109 ]
0110 end
0111
0112 if RunReconstruction
0113 case reconMethod
0114 when :juggler
0115 cmds << [
0116 './juggler.sh',
0117 "-#{xrich[0]}",
0118 "-i#{sim_file}",
0119 "-o#{rec_file}",
0120 ]
0121 when :eicrecon
0122 cmds << [
0123 './benchmark.rb',
0124 '-r',
0125 "--sim-file #{sim_file}",
0126 "--rec-file #{rec_file}",
0127 "--ana-file #{ana_file}",
0128 ]
0129 end
0130 end
0131
0132 plot_file = out_file particle, "rec_plots.#{rad_name}.root"
0133 cmds << [ 'root', '-b', '-q' ]
0134 case reconMethod
0135 when :juggler
0136 cmds.last << "scripts/src/momentum_scan_juggler_draw.C'(\"#{rec_file}\",\"#{plot_file}\",\"#{xrich.upcase}\",#{rad[:id]})'"
0137 when :eicrecon
0138 cmds.last << "scripts/src/momentum_scan_eicrecon_draw.C'(\"#{ana_file}\",\"#{plot_file}\",#{rad[:id]})'"
0139 end
0140
0141 Thread.new do
0142 cmds.each_with_index do |cmd,i|
0143 cmd_shell = cmd.join ' '
0144 puts cmd_shell
0145 mode = i==0 ? 'w' : 'a'
0146 Open3.pipeline(
0147 cmd_shell,
0148 out: [out_file(particle,"#{rad_name}.log.out"),mode],
0149 err: [out_file(particle,"#{rad_name}.log.err"),mode],
0150 )
0151 end
0152 end
0153 end
0154 trap 'INT' do
0155 pool.each &:kill
0156 exit 1
0157 end
0158
0159 pool.each &:join
0160 end
0161
0162
0163 if reconMethod == :eicrecon
0164 radiator_h.each do |rad_name,rad|
0165
0166
0167
0168 n_group_rebin = ( 500.0 * rad[:maxMomentum]/70.0 * 1.0/NumPoints ).to_i + 1
0169 drawArgs = [
0170 "\"#{OutputDir}/*.rec.#{rad_name}.ana.root\"",
0171 "\"#{OutputDir}/_theta_scan_2D.#{rad_name}\"",
0172 rad[:id],
0173 n_group_rebin
0174 ].join ','
0175 system "root -b -q scripts/src/momentum_scan_2D_draw.C'(#{drawArgs})'"
0176 end
0177 end
0178
0179
0180 puts "ERRORS (for one job) ======================="
0181 system "cat #{Dir.glob(OutputDir+"/*.err").first}"
0182 puts "END ERRORS ======================================"
0183
0184
0185
0186
0187
0188
0189
0190 r = PyCall.import_module 'ROOT'
0191 r.gROOT.SetBatch true
0192 r.gStyle.SetOptStat 0
0193 r.gStyle.SetLegendTextSize 0.1
0194
0195
0196 radiator_h.each do |rad_name,rad|
0197
0198
0199 default_color = r.kBlack
0200 default_marker = r.kFullCircle
0201 draw_h = particle_h.keys.map do |particle|
0202 [
0203 particle,
0204 {
0205 :root_file => r.TFile.new(out_file(particle, "rec_plots.#{rad_name}.root")),
0206 :color => default_color,
0207 :marker => default_marker,
0208 }.to_h
0209 ]
0210 end.to_h
0211 draw_h['e-'][:color] = r.kBlack if particle_h.has_key? 'e-'
0212 draw_h['pi+'][:color] = r.kBlue if particle_h.has_key? 'pi+'
0213 draw_h['kaon+'][:color] = r.kGreen+1 if particle_h.has_key? 'kaon+'
0214 draw_h['proton'][:color] = r.kMagenta if particle_h.has_key? 'proton'
0215 draw_h['e-'][:marker] = r.kFullCircle if particle_h.has_key? 'e-'
0216 draw_h['pi+'][:marker] = r.kFullSquare if particle_h.has_key? 'pi+'
0217 draw_h['kaon+'][:marker] = r.kFullTriangleUp if particle_h.has_key? 'kaon+'
0218 draw_h['proton'][:marker] = r.kFullTriangleDown if particle_h.has_key? 'proton'
0219
0220
0221 first_root_file = draw_h[particle_h.keys.first][:root_file]
0222 PyCall.iterable(first_root_file.GetListOfKeys).each do |tkey|
0223 plot_name = tkey.GetName
0224 next unless plot_name.match? /scan_pfx$/
0225
0226
0227 canv = r.TCanvas.new "#{plot_name}_#{rad_name}_canv", "#{plot_name}_#{rad_name}_canv", 1000, 800
0228 leg_hits = r.TLegend.new 0, 0.7, 1, 1
0229 canv.Divide 2,1
0230 pad_plot = r.TPad.new 'pad_plot', 'pad_plot', 0, 0, 0.75, 1
0231 pad_leg = r.TPad.new 'pad_leg', 'pad_leg', 0.75, 0, 1, 1
0232 pad_plot.SetGrid 1,1
0233 pad_plot.SetLeftMargin 0.2
0234 pad_plot.Draw
0235 pad_leg.Draw
0236
0237
0238 rad[:maxTheta] = 0
0239 draw_h.each do |particle,h|
0240
0241
0242 plot = h[:root_file].Get plot_name
0243
0244
0245 mass = particle_h[particle][:mass]
0246 rindex = rad[:rIndexRef]
0247
0248
0249 def calculate_mom_min(m,n)
0250 m / Math.sqrt(n**2-1)
0251 end
0252 mom_min = calculate_mom_min mass, rindex
0253
0254
0255 (1..plot.GetNbinsX).each do |bn|
0256 mom = plot.GetBinCenter bn
0257 if mom < mom_min
0258 plot.SetBinContent bn, 0
0259 plot.SetBinError bn, 0
0260 plot.SetBinEntries bn, 0
0261 end
0262 end
0263
0264
0265 def calculate_max_theta(n)
0266 1000 * Math.acos(1/n)
0267 end
0268 max_theta = calculate_max_theta rindex
0269 rad[:maxTheta] = [rad[:maxTheta],max_theta].max
0270
0271
0272 pad_plot.cd
0273 plot.SetMarkerStyle h[:marker]
0274 plot.SetMarkerColor h[:color]
0275 plot.SetLineColor h[:color]
0276 plot.SetMarkerSize 1.5
0277 plot.Draw 'SAME E X0'
0278 plot.GetYaxis.SetTitle 'Average ' + plot.GetTitle.sub(/ vs\..*/,'')
0279 plot.SetTitle 'Average ' + plot.GetTitle
0280 leg_hits.AddEntry plot, particle, 'PE'
0281
0282
0283 if plot_name.match?(/^theta_/)
0284 rindex_list = UseRINDEXrange ? rad[:rIndexRange] : [rindex]
0285 rindex_list.each_with_index do |n,i|
0286 ftn_theta = r.TF1.new(
0287 "ftn_theta_#{particle}_#{rad_name}_#{i}",
0288 "1000*TMath::ACos(TMath::Sqrt(x^2+#{mass}^2)/(#{n}*x))",
0289 calculate_mom_min(mass,n),
0290 plot.GetXaxis.GetXmax,
0291 )
0292 ftn_theta.SetLineColor h[:color]
0293 ftn_theta.SetLineWidth 2
0294 ftn_theta.Draw 'SAME'
0295
0296 rad[:maxTheta] = [rad[:maxTheta],calculate_max_theta(n)].max
0297 rad[:maxTheta] = [rad[:maxTheta],plot.GetMaximum].max
0298 end
0299 end
0300
0301
0302 plot.GetXaxis.SetRangeUser 0, 1.1*rad[:maxMomentum]
0303 case plot_name
0304 when /^thetaResid_/
0305 plot.GetYaxis.SetRangeUser -40, 40
0306 when /^theta_/
0307 plot.GetYaxis.SetRangeUser 0, 1.1*rad[:maxTheta]
0308 when /^npe_/
0309 plot.GetYaxis.SetRangeUser 0, rad[:maxNPE]
0310 when /^nphot_/
0311 plot.GetYaxis.SetRangeUser 0, MaxNphot
0312 end
0313
0314 end
0315
0316
0317 pad_leg.cd
0318 leg_hits.Draw
0319 if plot_name.match?(/^nphot_/)
0320 canv.SaveAs out_file("_#{plot_name}",'png') if rad_name==:gas
0321 else
0322 canv.SaveAs out_file("_#{plot_name}.#{rad_name}",'png')
0323 end
0324
0325 end
0326
0327 draw_h.values.each{ |h| h[:root_file].Close }
0328
0329 end