Skip to content
Merged
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
6 changes: 2 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ test.root
LocalRuns/**
external/lhapdf/*
external/libtorch/*
config/config.*
config/**
!config/config.default
!config/config.root
**/Skim*.json
external/**
*.onnx
Expand All @@ -15,9 +16,6 @@ external/**
!external/RoccoR
**/__pycache__/**
.DS_Store
SKFlatAnalyzer
HSNanoAnalyzer
SKNanoOutput
Run*NanoAOD*

#Temporary Added to my personal temp files
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "external/RoccoR"]
path = external/RoccoR
url = ssh://[email protected]:7999/hyseo/RoccoR.git
[submodule "external/jsonpog-integration"]
path = external/jsonpog-integration
url = ssh://[email protected]:7999/cms-nanoAOD/jsonpog-integration.git
8 changes: 4 additions & 4 deletions AnalyzerTools/src/MyCorrection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,17 @@ MyCorrection::MyCorrection(const TString &era, const TString &period, const TStr
}
JME_JES_GT["2023BPix"] = "Summer23BPixPrompt23_V3_DATA_######_AK4PFPuppi";
JME_JES_GT["2023"] = "Summer23Prompt23_V2_DATA_######_AK4PFPuppi";
JME_JES_GT["2022EE"] = "Summer22EE_22Sep2023_Run"+period+"_V2_DATA_######_AK4PFPuppi";
JME_JES_GT["2022"] = "Summer22_22Sep2023_RunCD_V2_DATA_######_AK4PFPuppi";
JME_JES_GT["2022EE"] = "Summer22EE_22Sep2023_Run"+period+"_V3_DATA_######_AK4PFPuppi";
JME_JES_GT["2022"] = "Summer22_22Sep2023_RunCD_V3_DATA_######_AK4PFPuppi";
JME_JES_GT["2018"] = "Summer19UL18_Run"+period+"_V5_DATA_######_AK4PFchs";
JME_JES_GT["2017"] = "Summer19UL17_Run"+period+"_V5_DATA_######_AK4PFchs";
JME_JES_GT["2016postVFP"] = "Summer19UL16_RunFGH_V7_DATA_######_AK4PFchs";
JME_JES_GT["2016preVFP"] = "Summer19UL16APV_Run"+period+"_V7_DATA_######_AK4PFchs";
} else { // MC
JME_JES_GT["2023BPix"] = "Summer23BPixPrompt23_V3_MC_######_AK4PFPuppi";
JME_JES_GT["2023"] = "Summer23Prompt23_V2_MC_######_AK4PFPuppi";
JME_JES_GT["2022EE"] = "Summer22EE_22Sep2023_V2_MC_######_AK4PFPuppi";
JME_JES_GT["2022"] = "Summer22_22Sep2023_V2_MC_######_AK4PFPuppi";
JME_JES_GT["2022EE"] = "Summer22EE_22Sep2023_V3_MC_######_AK4PFPuppi";
JME_JES_GT["2022"] = "Summer22_22Sep2023_V3_MC_######_AK4PFPuppi";
JME_JES_GT["2018"] = "Summer19UL18_V5_MC_######_AK4PFchs";
JME_JES_GT["2017"] = "Summer19UL17_V5_MC_######_AK4PFchs";
JME_JES_GT["2016postVFP"] = "Summer19UL16_V7_MC_######_AK4PFchs";
Expand Down
226 changes: 144 additions & 82 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,176 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

SKNanoAnalyzer is a C++ physics analysis framework for CMS (Compact Muon Solenoid) experiment data analysis. It processes NanoAOD files for Run 2 (2016-2018) and Run 3 (2022-2023) data periods, providing tools for dilepton studies, ttbar reconstruction, and systematic uncertainty evaluations.
SKNanoAnalyzer is a C++ physics analysis framework for CMS experiment NanoAOD data. Supports Run 2 (2016-2018) and Run 3 (2022-2023) periods for dilepton studies, ttbar reconstruction, and systematic uncertainty evaluations.

## Build Commands
## Quick Reference

```bash
# Initial setup (required once per session)
source setup.sh

# Build entire project
./scripts/build.sh
source setup.sh # Required once per session
./scripts/build.sh # Full clean build
./scripts/rebuild.sh # Incremental rebuild

# Incremental rebuild
./scripts/rebuild.sh
# Job submission
SKNano.py -a AnalyzerName -i 'Sample*' -e 2022 -n 10
SKNano.py -a Skim_DiLepton -i DYJets -e 2022 --skimming_mode
```

## Running Analysis
## Directory Structure

```bash
# Submit analysis jobs
SKNano.py -a AnalyzerName -i 'SamplePattern*' -e 2022 -n 10
```
SKNanoAnalyzer/
├── Analyzers/ # Analysis implementations (inherit AnalyzerCore)
├── AnalyzerTools/ # Utilities, corrections, systematic handling
├── DataFormats/ # Physics object classes
├── PyAnalyzers/ # Python postprocessing tools
├── python/ # Job submission (SKNano.py, sampleManager.py)
├── scripts/ # Build and utility scripts
├── external/ # Git submodules (RoccoR)
├── data/ # Era-specific corrections, efficiencies, samples
├── config/ # User config files (config.$USER)
├── SampleLists/ # Sample lists per era/analysis
├── templates/ # HTCondor job templates
└── CMakeLists.txt # Root build configuration
```

# Example: Run DiLepton analyzer on DYJets samples
SKNano.py -a DiLepton -i 'DYJets*' -e 2022 -n 50 --reduction 10
## Class Hierarchy

# Skimming mode for data reduction
SKNano.py -a Skim_AnalyzerName -i SampleName -e 2022 --skimming_mode
**Physics Objects:**
```
Particle (base)
├── Lepton → Muon, Electron
├── Jet, FatJet
├── Tau, Photon
└── Gen*, LHE (generator-level)
```

**Analyzer Chain:**
```
SKNanoLoader → AnalyzerCore → [DiLeptonBase, VcbBase] → User Analyzers
```

## Architecture Overview

### Core Components
- **DataFormats/**: Physics object classes (Electron, Muon, Jet, etc.) with analysis methods
- **AnalyzerTools/**: Analysis utilities, corrections, systematic helpers, ML integration
- **Analyzers/**: Specific analysis implementations inheriting from AnalyzerCore
- **External dependencies**: KinematicFitter, RoccoR, jsonpog-integration, LHAPDF, libtorch

### Key Classes
- **AnalyzerCore**: Base class providing common functionality for all analyzers
- **SKNanoLoader**: Handles NanoAOD file loading and branch management
- **SystematicHelper**: Manages systematic uncertainty variations
- **MyCorrection**: Centralized correction and scale factor application

### Data Organization
- Era-based structure: `data/{era}/` contains corrections, efficiencies, and sample metadata
- Sample information in `data/{era}/Sample/CommonSampleInfo.json`
- Systematic configurations in YAML files (DiLeptonSystematic.yaml, VcbSystematic.yaml)

## Development Patterns

### Creating New Analyzers
1. Create header in `Analyzers/include/` inheriting from `AnalyzerCore`
2. Implement in `Analyzers/src/` with required methods:
- `initializeAnalyzer()`
- `executeEvent()`
- Virtual destructor
## Creating Analyzers

1. Create `Analyzers/include/MyAnalyzer.h` inheriting from `AnalyzerCore`
2. Implement in `Analyzers/src/MyAnalyzer.cc`:
```cpp
void MyAnalyzer::initializeAnalyzer() { /* setup */ }
void MyAnalyzer::executeEvent() { /* per-event logic */ }
```
3. Add to `Analyzers/include/AnalyzersLinkDef.hpp`
4. Use enum classes for constants instead of magic numbers/strings
4. Rebuild with `./scripts/rebuild.sh`

### Systematic Uncertainties
- Use `SystematicHelper` class for systematic variations
- Implement variations using `variation` enum (nom, up, down)
- Apply corrections through `MyCorrection` class methods
## Code Patterns

### Physics Object Usage
**Enum Classes (always prefer over strings/magic numbers):**
```cpp
// Example pattern for lepton selection
RVec<Lepton *> leptons;
TString MuonID = "Tight"; // Example ID
for (auto &mu : *muons) {
if (mu.Pass(MuonID)) {
enum class Muon::BooleanID { NONE, LOOSE, MEDIUM, TIGHT };
enum class Jet::JetID { TIGHT, LOOSE };
enum class MyCorrection::variation { nom, up, down };
```

**Object Selection:**
```cpp
RVec<Lepton*> leptons;
for (auto& mu : *muons) {
if (mu.PassID(Muon::BooleanID::TIGHT) && mu.Pt() > 20.)
leptons.push_back(&mu);
}
}
```

## Dependencies and Environment
**Corrections:**
```cpp
MyCorrection::variation syst = variation::nom; // or up/down
float sf = corrections.GetMuonIDSF(key, muon, syst);
```

## Systematic Uncertainties

Configured via YAML files in `AnalyzerTools/`:
- `DiLeptonSystematic.yaml`: Full systematic list
- `noSyst.yaml`: Nominal only (quick tests)

**Types:**
- **Event-loop**: Rerun event processing (JetRes, ElectronEn)
- **Weight-only**: Reweight without reprocessing (L1Prefire, TrigSF)

Use `SystematicHelper` class with `variation` enum (nom/up/down).

## Configuration Hierarchy

1. **User config**: `config/config.$USER` - package manager, paths, Telegram
2. **Sample config**: `data/{era}/Sample/CommonSampleInfo.json` - xsec, lumi
3. **Systematic config**: YAML files in `AnalyzerTools/`

## Build System

**CMake with optional Ninja:**
```bash
./scripts/build.sh # Uses Make by default
./scripts/build.sh ninja # Use Ninja (faster)
```

**Key Environment Variables** (set by setup.sh):
- `SKNANO_VERSION`: Data version (Run3_v13_Run2_v9)
- `SKNANO_BUILDDIR`, `SKNANO_INSTALLDIR`, `SKNANO_LIB`
- `LHAPDF_*`, `LIBTORCH_*`, `CORRECTION_*`, `ONNXRUNTIME_*`

**Dependencies** (conda/mamba):
- ROOT 6.32+, correctionlib, onnxruntime-cpp, PyTorch/libtorch
- LHAPDF (auto-installed via `scripts/install_lhapdf.sh`)

### Required Packages (managed via conda/mamba)
- ROOT 6.32+
- correctionlib (CMS corrections)
- onnxruntime-cpp (ML inference)
- PyTorch/libtorch (deep learning)
- LHAPDF (auto-installed via scripts/install\_lhapdf.sh)
## Job Submission (HTCondor)

### Configuration
- Personal config: `config/config.$USER` (system type, package manager, notifications)
- Sample lists: `SampleLists/{era}/` for different analysis categories
**DAG Workflow:** Analysis jobs → Hadd (merge) → Summary

```bash
# Basic submission
SKNano.py -a DiLepton -i 'DYJets*' -e 2022 -n 50

## Job Management
# With data reduction (process 1/N events)
SKNano.py -a DiLepton -i 'DYJets*' -e 2022 -n 50 --reduction 10

### HTCondor Integration
- Jobs submitted via HTCondor with DAG workflows
- Configurable memory (default 2GB) and CPU resources
- Automatic output file management and merging
- Telegram bot notifications (optional)
# Skimming mode (recommended before full analysis)
SKNano.py -a Skim_DiLepton -i DYJets -e 2022 --skimming_mode
```

### Sample Selection
- Regex patterns for flexible sample matching
- Era-specific sample organization (2016preVFP, 2017, 2018, 2022, 2022EE, 2023, etc.)
- Cross-section and luminosity handled automatically
**Options:**
- `-a`: Analyzer name
- `-i`: Sample pattern (regex supported)
- `-e`: Era (2022, 2022EE, 2023, 2023BPix, 2016preVFP, etc.)
- `-n`: Files per job
- `--skimming_mode`: Enable skim output
- `--reduction N`: Process 1/N events

## Multi-Era Support

The framework supports unified analysis across data-taking periods:
- **Run 2**: 2016preVFP, 2016postVFP, 2017, 2018
- **Run 3**: 2022, 2022EE, 2023, 2023BPix
| Run | Eras | NanoAOD |
|-----|------|---------|
| Run 2 | 2016preVFP, 2016postVFP, 2017, 2018 | v9 |
| Run 3 | 2022, 2022EE, 2023, 2023BPix | v13 |

Era-specific data loaded automatically from `data/{SKNANO_VERSION}/{era}/`.

## CI/CD

GitHub Actions workflow (`.github/workflows/main.yml`):
- Builds on push/PR using Docker container
- Requires SSH key for RoccoR submodule (CERN GitLab)

Era-specific corrections and configurations are automatically loaded based on the `-e` flag in job submission.
## Common Tasks

**Add new physics object branch:**
1. Update `DataFormats/include/` class definition
2. Add branch in `AnalyzerTools/src/SKNanoLoader.cc`
3. Update `python/NanoAODv*.json` if needed

**Add new correction:**
1. Place correction file in `data/{era}/`
2. Implement getter in `AnalyzerTools/src/MyCorrection.cc`
3. Add systematic variation support if applicable

**Debug locally:**
```bash
root -l -b -q 'runAnalyzer.C("AnalyzerName", "input.root", "output.root")'
```
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# SKNanoAnalyzer
v1.0.0
**v1.0.1**
---

## Introduction
- If you want to engage in the development and commit to the repository, please read [Development Guide](docs/DevelopmentGuide.md) first.
- For setting up the environment and starting the analysis, please refer [Getting Started](docs/GettingStarted.md).
- If you want to engage in the development and commit to the repository, please read [Development Guide](docs/DevelopmentGuide.md) first.

## To do
### Assigned
Expand Down
Loading
Loading