Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -161,7 +163,7 @@ hpc-header:
@echo "\n===== HPC executables ====="
hpc/src/%.exe: hpc/src/%.cpp $(EPIC_ANALYSIS_LIB)
@echo "----- build [email protected] -----"
$(CXX) -c $< -o [email protected] $(FLAGS) $(DEP_INCLUDES) $(EPIC_ANALYSIS_INCLUDES)
$(CXX) -c $< -o [email protected] $(FLAGS) $(DEP_INCLUDES) $(EPIC_ANALYSIS_INCLUDES)
@echo "--- make executable $@"
$(CXX) -o $@ [email protected] $(DEP_LIBRARIES) $(EPIC_ANALYSIS_LIBRARIES)
$(RM) [email protected]
Expand All @@ -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)
17 changes: 7 additions & 10 deletions hpc/run-local-slurm-pipeline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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']}/../"
Expand Down
31 changes: 16 additions & 15 deletions hpc/src/merge_analysis_files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down
88 changes: 63 additions & 25 deletions s3tools/s3tool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
},
Expand All @@ -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',
Expand Down Expand Up @@ -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/)
Expand Down Expand Up @@ -387,15 +419,15 @@ 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]}"
exit 1
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
Expand All @@ -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',
Expand All @@ -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"
Expand All @@ -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
Expand All @@ -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/
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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}"
2 changes: 2 additions & 0 deletions src/Hist4D.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <TFrame.h>
#include <stdexcept>

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.
Expand Down
1 change: 1 addition & 0 deletions src/Kinematics.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using std::map;
using std::cout;
using std::cerr;
using std::endl;
using std::isnan;

class Kinematics
{
Expand Down
1 change: 1 addition & 0 deletions src/KinematicsJets.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using std::map;
using std::cout;
using std::cerr;
using std::endl;
using std::isnan;

class KinematicsJets : public Kinematics
{
Expand Down
Loading