diff --git a/Makefile b/Makefile index 3b715fba..ce737b58 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ endif CXX := g++ FLAGS = -Wno-deprecated -fPIC FLAGS += -fmax-errors=3 +FLAGS += -std=c++20 # FLAGS += -fvisibility=hidden # FIXME: required by pybind, but causes unresolved symbols in cling... ROOTCLING = rootcling @@ -26,9 +27,10 @@ DEP_LIBRARIES = $(shell root-config --glibs) #DEP_LIBRARIES += -lMinuit -lRooFitCore -lRooFit -lRooStats -lProof -lMathMore # Data Model (PODIO + EDM4hep + EDM4eic) -DEP_LIBRARIES += -L/usr/local/lib -ledm4hep -ledm4eic +DEP_LIBRARIES += -L/opt/local/lib -ledm4hep -ledm4eic +DEP_INCLUDES += -I/opt/local/include ifdef INCLUDE_PODIO - DEP_LIBRARIES += -L/usr/local/lib -lpodio -lpodioRootIO + DEP_LIBRARIES += -L/opt/local/lib -lpodio -lpodioRootIO FLAGS += -DINCLUDE_PODIO endif @@ -161,7 +163,7 @@ hpc-header: @echo "\n===== HPC executables =====" hpc/src/%.exe: hpc/src/%.cpp $(EPIC_ANALYSIS_LIB) @echo "----- build $@.o -----" - $(CXX) -c $< -o $@.o $(FLAGS) $(DEP_INCLUDES) $(EPIC_ANALYSIS_INCLUDES) + $(CXX) -c $< -o $@.o $(FLAGS) $(DEP_INCLUDES) $(EPIC_ANALYSIS_INCLUDES) @echo "--- make executable $@" $(CXX) -o $@ $@.o $(DEP_LIBRARIES) $(EPIC_ANALYSIS_LIBRARIES) $(RM) $@.o @@ -171,4 +173,4 @@ hpc/src/%.exe: hpc/src/%.cpp $(EPIC_ANALYSIS_LIB) ################################################################# clean: @echo "\n===== CLEAN $(PROJECT) =====" - $(RM) $(EPIC_ANALYSIS_LIB) $(PREFIX)/$(EPIC_ANALYSIS_PCM) $(EPIC_ANALYSIS_DICT) $(HPC_EXECUTABLES) + $(RM) $(EPIC_ANALYSIS_LIB) $(PREFIX)/$(EPIC_ANALYSIS_PCM) $(EPIC_ANALYSIS_DICT) $(HPC_EXECUTABLES) \ No newline at end of file diff --git a/hpc/run-local-slurm-pipeline.rb b/hpc/run-local-slurm-pipeline.rb index 6e5f78af..9c52f533 100755 --- a/hpc/run-local-slurm-pipeline.rb +++ b/hpc/run-local-slurm-pipeline.rb @@ -7,25 +7,22 @@ # Manually edit these according to your desired simulation # prefix for output -PROJECT_NAME="" +PROJECT_NAME="single_piplus_study" -CAMPAIGNS=["epic.23.10.0", - "epic.23.11.0"] +CAMPAIGNS=["epic.24.05.0"] -DETECTORS = ["epic_craterlake", - "epic_craterlake"] +DETECTORS = ["epic_craterlake"] -ENERGIES=[ ["5x41","10x100","18x275"], - ["5x41","10x100","18x275"] ] +ENERGIES=[ ["5x41","10x100","18x275"] ] # Number of Files per Q2 binning # Set this to very large number for all campaign files -NFILES = 0 +NFILES = 100000 -NROOT_FILES_PER_JOB = 0 +NROOT_FILES_PER_JOB = 40 # Points to analysis macro -PATH_TO_ANALYSIS_MACRO = "macro/MY_MACRO.C" +PATH_TO_ANALYSIS_MACRO = "macro/analysis_singlePion.C" # Path to the directory containing eic-shell PATH_TO_EIC_SHELL = "#{ENV['EIC_SHELL_PREFIX']}/../" diff --git a/hpc/src/merge_analysis_files.cpp b/hpc/src/merge_analysis_files.cpp index befd4c7b..73421ae2 100644 --- a/hpc/src/merge_analysis_files.cpp +++ b/hpc/src/merge_analysis_files.cpp @@ -95,21 +95,22 @@ int main(int argc, char** argv) { } // handle Histos objects: add all histograms to the first file's histograms - else if(TString(key->GetClassName())=="Histos") { - auto obj = (Histos*) key->ReadObj(); - if(first_file) { - fmt::print("Read Histos '{}'\n",keyName); - in_histos.insert({ keyName, obj }); - } else { - Histos *out_histos; - try { - out_histos = in_histos.at(keyName); - out_histos->AddHistos(obj); - } catch(const std::out_of_range& e) { - fmt::print(stderr,"ERROR: cannot find Histos '{}' in {}\n",keyName,in_file->GetName()); - } - } - } + // Commented out by G. Matousek on 6/10/2024 +// else if(TString(key->GetClassName())=="Histos") { +// auto obj = (Histos*) key->ReadObj(); +// if(first_file) { +// fmt::print("Read Histos '{}'\n",keyName); +// in_histos.insert({ keyName, obj }); +// } else { +// Histos *out_histos; +// try { +// out_histos = in_histos.at(keyName); +// out_histos->AddHistos(obj); +// } catch(const std::out_of_range& e) { +// fmt::print(stderr,"ERROR: cannot find Histos '{}' in {}\n",keyName,in_file->GetName()); +// } +// } +// } // handle BinSet objects: store the first file's BinSets; TODO: compare with all the others else if(TString(key->GetClassName())=="BinSet") { diff --git a/s3tools/s3tool.rb b/s3tools/s3tool.rb index 8871deb0..2e905c4f 100755 --- a/s3tools/s3tool.rb +++ b/s3tools/s3tool.rb @@ -8,8 +8,8 @@ require 'fileutils' # default versions -VersionLatest = 'epic.23.11.0' -VersionPrevious = 'epic.23.10.0' +VersionLatest = 'epic.24.07.0' +VersionPrevious = 'epic.24.05.0' # default CLI options options = OpenStruct.new @@ -28,6 +28,7 @@ # global settings CrossSectionTable = 'datarec/xsec/xsec.dat' HostURL = 'https://eics3.sdcc.bnl.gov:9000' +XROOTD_PREFIX = 'root://dtn-eic.jlab.org/' # helpers def versionNum(v) # options.version -> version number @@ -50,80 +51,101 @@ def ecceQ2range(minQ2,maxQ2) # return file path suffix, for ECCE Q2 ranges # :fileExtension => File extension (optional, defaults to 'root') # } prodSettings = { + 'epic.24.07.0' => { + :comment => 'Pythia 8: high-stats July 2024 production', + :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :energySubDir => Proc.new { "#{options.energy}" }, + :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, + }, + 'epic.24.05.0' => { + :comment => 'Pythia 8: high-stats May 2024 production', + :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :energySubDir => Proc.new { "#{options.energy}" }, + :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, + }, + 'epic.24.04.0' => { + :comment => 'Pythia 8: high-stats April 2024 production', + :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :energySubDir => Proc.new { "#{options.energy}" }, + :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, + }, 'epic.23.11.0' => { :comment => 'Pythia 8: high-stats November 2023 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.10.0' => { :comment => 'Pythia 8: high-stats November 2023 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.09.1' => { :comment => 'Pythia 8: high-stats ??? 2023 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.07.1' => { :comment => 'Pythia 8: high-stats July 2023 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.06.1' => { :comment => 'Pythia 8: high-stats June 2023 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.05.2' => { :comment => 'Pythia 8: high-stats May 2023 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.05.1' => { :comment => 'Pythia 8', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.23.03.0_pythia8' => { :comment => 'Pythia 8, small sample, 10x100, minQ2=1000 only', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, # 'epic.23.03.0_pythia6' => { # FIXME: need cross section for Q2<1 bin # :comment => 'Pythia 6, small sample, 5x41, noradcor only, Q2<1 only', # :crossSectionID => Proc.new { |minQ2,maxQ2,radDir| "pythia6:ep_#{radDir}.#{options.energy}_q2_#{minQ2}_#{maxQ2}" }, - # :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/SIDIS/pythia6" }, + # :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/SIDIS/pythia6" }, # :energySubDir => Proc.new { "ep_#{options.energy}" }, # :dataSubDir => Proc.new { |radDir| "hepmc_ip6/#{radDir}" }, # }, 'epic.23.01.0' => { :comment => 'Pythia 8', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'epic.22.11.3' => { :comment => 'Pythia 6: high-stats November 2022 production, with & without radiative corrections', :crossSectionID => Proc.new { |minQ2,maxQ2,radDir| "pythia6:ep_#{radDir}.#{options.energy}_q2_#{minQ2}_#{maxQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/SIDIS/pythia6" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/SIDIS/pythia6" }, :energySubDir => Proc.new { "ep_#{options.energy}" }, :dataSubDir => Proc.new { |radDir| if [options.energy,radDir]==['18x275','noradcor'] # correct for S3 disorganization @@ -136,14 +158,14 @@ def ecceQ2range(minQ2,maxQ2) # return file path suffix, for ECCE Q2 ranges 'epic.22.11.2' => { :comment => 'Pythia 8: high-stats November 2022 production', :crossSectionID => Proc.new { |minQ2| "pythia8:#{options.energy}/minQ2=#{minQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/RECO/#{versionNum(options.version)}/epic_#{options.detector}/DIS/NC" }, :energySubDir => Proc.new { "#{options.energy}" }, :dataSubDir => Proc.new { |minQ2| "minQ2=#{minQ2}" }, }, 'ecce.22.1' => { :comment => 'Last ECCE Production, August 2022', :crossSectionID => Proc.new { |minQ2,maxQ2| "pythia6:ep-#{options.energy}#{ecceQ2range(minQ2,maxQ2)}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/Campaigns/#{versionNum(options.version)}/SIDIS/pythia6" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/Campaigns/#{versionNum(options.version)}/SIDIS/pythia6" }, :energySubDir => Proc.new { "ep-#{options.energy}" }, :dataSubDir => Proc.new { |minQ2,maxQ2| ecceQ2range(minQ2,maxQ2) }, # (combined with :energySubDir) }, @@ -157,7 +179,7 @@ def ecceQ2range(minQ2,maxQ2) # return file path suffix, for ECCE Q2 ranges 'hepmc.pythia6' => { :comment => 'HEPMC files from Pythia 6 for ePIC, with & without radiative corrections', :crossSectionID => Proc.new { |minQ2,maxQ2,radDir| "pythia6:ep_#{radDir}.#{options.energy}_q2_#{minQ2}_#{maxQ2}" }, - :releaseSubDir => Proc.new { "S3/eictest/EPIC/EVGEN/SIDIS/pythia6" }, + :releaseSubDir => Proc.new { "/work/eic2/EPIC/EVGEN/SIDIS/pythia6" }, :energySubDir => Proc.new { "ep_#{options.energy}" }, :dataSubDir => Proc.new { |radDir| "hepmc_ip6/#{radDir}" }, :fileExtension => 'hepmc', @@ -326,6 +348,16 @@ def ecceQ2range(minQ2,maxQ2) # return file path suffix, for ECCE Q2 ranges delphesCmd = 's3tools/src/loop_run_delphes.sh' ## helper functions +def xrdfs_ls(dir) + # Use the xrdfs command to list files in the given directory + output = `xrdfs dtn-eic.jlab.org ls #{dir}` + if $?.success? + return output.split("\n") # Split into an array of file paths + else + $stderr.puts "ERROR: Failed to list directory: #{dir}" + return [] + end +end # get a list of files on S3 at `dir`; use `preFilter` to filter out things that are not in the file name (e.g., file size) def mc_ls(dir, preFilter='') ls = `mc ls #{dir}`.split(/\n/) @@ -387,7 +419,7 @@ def mc_cp(srcfile,tgtdir) prod[:targetDir] += "/"+prod[:radDir] puts "Target Dir: #{prod[:targetDir]}" # check if there are any files - if mc_ls("#{dataDir} | head").empty? + if xrdfs_ls("#{dataDir} | head").empty? $stderr.puts "ERROR: no files in this Data Dir" puts "Available Data Directory Tree (be patient...)" system "mc tree #{prod[:releaseDir]}" @@ -395,7 +427,7 @@ def mc_cp(srcfile,tgtdir) end # get the Q2 ranges puts "Getting the full list of files... be patient..." - fullList = mc_ls(dataDir).grep(/\.#{ext}$/) + fullList = xrdfs_ls(dataDir).grep(/\.#{ext}$/) prod[:q2ranges] = fullList .map{ |file| file.gsub(/.*_q2_/,'').sub(/_run.*/,'') } .uniq @@ -417,6 +449,9 @@ def mc_cp(srcfile,tgtdir) # pattern: "#{energy}/minQ2=#{minQ2}/" elsif [ + 'epic.24.07.0', + 'epic.24.05.0', + 'epic.24.04.0', 'epic.23.11.0', 'epic.23.10.0', 'epic.23.09.1', @@ -433,7 +468,7 @@ def mc_cp(srcfile,tgtdir) # print target directory puts "Target Dir: #{prod[:targetDir]}" # get list of Q2 subdirectories - q2dirList = mc_ls prod[:energyDir] + q2dirList = xrdfs_ls(prod[:energyDir]) if q2dirList.empty? $stderr.puts "ERROR: energy not found" puts "Available energies" @@ -456,8 +491,8 @@ def mc_cp(srcfile,tgtdir) prod[:dataDirs] << dataDir puts "Data Dir: #{dataDir}" fileList = readingEvGen ? - mc_ls(dataDir,/GiB/) .grep(/\.#{ext}$/) .grep(/vtxfix/) .first(options.limit) : - mc_ls(dataDir) .grep(/\.#{ext}$/) .first(options.limit) + xrdfs_ls(dataDir,/GiB/) .grep(/\.#{ext}$/) .grep(/vtxfix/) .first(options.limit) : + xrdfs_ls(dataDir) .grep(/\.#{ext}$/) .first(options.limit) puts "Files:" fileList.each{ |file| puts " #{file}" } fileList @@ -468,7 +503,7 @@ def mc_cp(srcfile,tgtdir) 'ecce.22.1' ].include? options.version prod[:radDir] = '' # not used - prod[:q2ranges] = mc_ls(prod[:releaseDir]).grep(/#{options.energy}/).grep_v(/Lambda/).map do |dir| + prod[:q2ranges] = xrdfs_ls(prod[:releaseDir]).grep(/#{options.energy}/).grep_v(/Lambda/).map do |dir| if dir.match? /-q2-high/ [100,0] elsif dir.match? /-q2-low/ @@ -482,7 +517,7 @@ def mc_cp(srcfile,tgtdir) prod[:energyDir] + prod[:dataSubDir].call(minQ2,maxQ2) end prod[:fileLists] = prod[:dataDirs].map do |dataDir| - mc_ls(dataDir) + xrdfs_ls(dataDir) .grep(/g4event_eval.root$/) .first(options.limit) end @@ -545,7 +580,10 @@ def mc_cp(srcfile,tgtdir) if readingEvGen # if reading EVGEN, be sure to use `.root` extension file.sub! /\.#{ext}$/, '.root' elsif options.mode=='s' # if streaming, make URL - file = "#{dataDir.sub(/^S3/,'s3'+HostURL)}/#{fileBase}" + # remove the "S3/eictest" portion at the start, then prepend the XRootD prefix + #file = dataDir.sub(/^S3\/eictest/, XROOTD_PREFIX) + "/#{fileBase}" + file=XROOTD_PREFIX + fileBase + puts file end localFileTable.puts "#{file} #{crossSection} #{minQ2} #{maxQ2}" end @@ -569,4 +607,4 @@ def mc_cp(srcfile,tgtdir) system "cat #{localFileTableName}" puts '\''*50 configFile = localFileTableName.sub(/\.list/,'') -system "s3tools/src/generate-config-file.rb #{configFile} #{options.energy} #{localFileTableName}" +system "s3tools/src/generate-config-file.rb #{configFile} #{options.energy} #{localFileTableName}" \ No newline at end of file diff --git a/src/Hist4D.h b/src/Hist4D.h index bd6f9dca..ae91b776 100644 --- a/src/Hist4D.h +++ b/src/Hist4D.h @@ -12,6 +12,8 @@ #include #include +using std::isnan; + // Convenience class for plotting 4d histogram. Can't derive from TH1 because // some of the virtual methods are only designed with up to 3 dimensions in // mind. diff --git a/src/Kinematics.h b/src/Kinematics.h index 2f6e83e1..d27c3f23 100644 --- a/src/Kinematics.h +++ b/src/Kinematics.h @@ -42,6 +42,7 @@ using std::map; using std::cout; using std::cerr; using std::endl; +using std::isnan; class Kinematics { diff --git a/src/KinematicsJets.h b/src/KinematicsJets.h index 5c85e817..070659b8 100644 --- a/src/KinematicsJets.h +++ b/src/KinematicsJets.h @@ -22,6 +22,7 @@ using std::map; using std::cout; using std::cerr; using std::endl; +using std::isnan; class KinematicsJets : public Kinematics {