diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..563513d04 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,59 @@ +name: docs + +# build the documentation whenever there are new commits on main +on: + push: + branches: + - main +# build documentation for tags. +# on: +# push: +# tags: +# - '*' + +# security: restrict permissions for CI jobs. +permissions: + contents: read + +jobs: + # Build the documentation and upload the static HTML files as an artifact. + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version-file: "pyproject.toml" + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + version: 0.8.9 + + - name: Install project + run: uv sync --locked --all-extras --dev + + - name: build docs + run: | + uv run sphinx-build -M dirhtml docs/source docs/build + + - uses: actions/upload-pages-artifact@v3 + with: + path: docs/build/dirhtml + + # Deploy the artifact to GitHub pages. + # This is a separate job so that only actions/deploy-pages has the necessary permissions. + deploy: + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index c3b83bed7..9d83a9be2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ Unfolding/Unfolder stv_root_dict_rdict.pcm *.o *~ + +# documentation build paths +docs/build diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..faf5089f8 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= uv run sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/source/adding-selection.rst b/docs/source/adding-selection.rst new file mode 100644 index 000000000..be931f8b8 --- /dev/null +++ b/docs/source/adding-selection.rst @@ -0,0 +1,143 @@ +Writing Your Own Selection +========================== + +.. attention:: + + This documentation page is incomplete. Please view tutorial materiel for + this framework for now. + +Organising Your Selection +------------------------- + +Here we describe a selection called ``YourSelection``. This looks like a class that + +.. cpp:class:: YourSelection : SelectionBase + + YourSelection is a class that implements all of the required methods + (described below) that SelectionBase and the framework requires to operate a + cross-section analysis. + + This class should also have member variables added that correspond to any + desired additional branches you'd like available in the output tree. + + .. cpp:function:: void define_constants() + + Here you should define any particular constants that might be helpful, + e.g. + + - Threshold values that your selection cuts depends upon. + - PDG codes of interest. + + .. cpp:function:: bool define_signal(AnalysisEvent* event) + + This method returns a boolean indicating if :cpp:var:`event` passed a + signal definition. + + Truth information should be used to define the signal. + + .. cpp:function:: int categorize_event(AnalysisEvent* event) + + Here you can add logic that classifies events via their + truth-information. + + A classification scheme can be as coarse or finely defined as you want, + using MC interaction codes, final-state particles or a combination of + both. + + .. cpp:function:: bool selection(AnalysisEvent* event) + + This method should contain logic to operate your selection cut on an + event. + + This method can be run for files with and without truth-information. + + .. cpp:function:: void compute_reco_observables(AnalysisEvent* event) + .. cpp:function:: void compute_true_observables(AnalysisEvent* event) + .. cpp:function:: void define_output_branches() + .. cpp:function:: void reset() + + Run after each event is processed, this should reset any class variables + to default values so the values for the previous event are not persisted + into the new event. + + +Event Variables in ``AnalysisEvent`` +------------------------------------ + +.. rubric:: ``include/XSecAnalyzer/AnalysisEvent.hh`` + +.. cpp:class:: AnalysisEvent + + Represents a single interaction event with all the associated event + variables as class instance members. + + Initially read from the PeLEE ntuples. + + .. cpp:member:: float topological_score_ + .. cpp:member:: float cosmic_impact_parameter_ + .. cpp:member:: float contained_fraction_ + + .. cpp:member:: float nu_completeness_from_pfp_ + .. cpp:member:: float nu_purity_from_pfp_ + .. cpp:member:: int nu_pdg_ + + .. cpp:member:: int nslice_ + + Number of neutrino slices identified by the SliceID. Allowed values + are zero or one. + + .. cpp:member:: float nu_vx_ + + Reco neutrino vertex coordinates (cm). Space charge corrections have + been applied for these. + .. cpp:member:: float nu_vy_ + .. cpp:member:: float nu_vz_ + + .. cpp:member:: int num_pf_particles_ + .. cpp:member:: int num_tracks_ + .. cpp:member:: int num_showers_ + +NuMI-Specific Configuration +--------------------------- + +Several changes need to be made to change from the default BNB-specific +operating mode to a NuMI-specific mode. + +Beamline Geometry Weights +^^^^^^^^^^^^^^^^^^^^^^^^^ + +NuMI flux systematics have additional variations on the beamline geometry (such +as the state of the focussing horns and the target positioning). These are +reflected in the appropriate NuMI systematics definition configuration at +:file:`configs/systcalc_numi.conf`. + +The process of adding these weights requires a ROOT file containing the +systematic variations as a function of neutrino flavour, energy and +beamline-neutrino angle. That can be used in tandem with the +:ref:`exec-addbeamlinegeometryweights` program to add beamline geometry weights +to PeLEE ntuples. This should be done for all PeLEE ntuple files before +processing them with ``ProcessNTuples``. + +Adding Mock Weights to NuMI Dirt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +NuMI Dirt files must have additional mock systematic weights added. +``xsec_analyzer`` expects a full set of systematic weights for all input PeLEE +ntuples. While BNB dirt files have a full set of weights included, NuMI dirt +files do not (instead a large uncertainty is applied). + +In order to apply these additional mock weights to NuMI dirt files, the +:ref:`exec-addfakeweights` program can be invoked. The new dirt file should be +used in the remaining workflow. + +Compile Time Switch +^^^^^^^^^^^^^^^^^^^ + +At compile-time a variable should be changed in the framework: + +.. rubric:: ``include/XSecAnalyzer/Constants.hh`` + +.. cpp:var:: bool useNuMI = true + :no-contents-entry: + + Enable NuMI processing mode for the framework. diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 000000000..b3bb08c21 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,75 @@ +from datetime import datetime +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'xsec_analyzer' +copyright = f'{datetime.now().year}, Steven Gardiner, Burke Irwin, Liang Lu, et. al.' +author = 'Steven Gardiner, Burke Irwin, Liang Lu, et. al.' + +show_authors = True + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.extlinks', +] + +extlinks = { + 'github': ('https://github.com/%s', + None), + 'docdb': ( + 'https://microboone-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=%s', + None + ) +} + +templates_path = ['_templates'] +exclude_patterns = [] + +# hawkmoth_root = os.path.abspath('../../include/') +# hawkmoth_clang = [ +# '-I/home/niam/phd/code/xsec_analyzer/include', +# '-I/home/niam/Downloads/root/include' +# ] +# hawkmoth_source_uri = "https://github.com/uboone/xsec_analyzer/tree/main/include/{source}#L{line}" + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'furo' +html_static_path = ['_static'] +html_theme_options = { + "source_repository": "https://github.com/uboone/xsec_analyzer/", + "source_branch": "main", + "source_directory": "docs/source/" +} + + +# -- For theme = 'alabaster' ----------- +# html_theme = 'alabaster' +# html_static_path = ['_static'] +# html_sidebars = { +# '**': [ +# 'about.html', +# 'navigation.html', +# 'relations.html', +# 'searchfield.html', +# ] +# } +# html_theme_options = { +# 'description': 'A framework for MicroBooNE cross-sections', +# 'github_user': 'uboone', +# 'github_repo': 'xsec_analyzer', +# 'page_width': '60rem', +# 'sidebar_width': '15rem', +# 'extra_nav_links': { +# "GitHub Repository": "https://github.com/uboone/xsec_analyzer" +# } +# } diff --git a/docs/source/configuration-files.rst b/docs/source/configuration-files.rst new file mode 100644 index 000000000..d122a0d23 --- /dev/null +++ b/docs/source/configuration-files.rst @@ -0,0 +1,254 @@ +Configuration Files +=================== + +Several text-configuration files are used to control the operation of the +framework. + +.. _config-file-properties: + +``file_properties.txt`` +----------------------- + +This file declares a series of input files produced by the ``ProcessNTuples`` +program. + +Example +^^^^^^^ + +.. code-block:: + + # Full beam-on data + /home/me/data/CrossSections/XSec_Analyzer/xsec-ntuples/xsec-ana-numi_beam_on_pion_ntuples_run1_fhc.root 1 onBNB 5748692 2.192e+20 + # Beam-off data + /home/me/data/CrossSections/XSec_Analyzer/xsec-ntuples/xsec-ana-numi_beam_off_pion_ntuples_run1_fhc.root 1 extBNB 4582248 0 + +Format +^^^^^^ + +Here variables to replace are labelled as ``{such}``. This can be repeated on +each line for each declared file. + +.. code-block:: + + # a comment (ignored by the framework) + {file-path} {run-number} {file-type} [{triggers} {POT}] + ... + +.. option:: file-path + + An absolute path to an ``stv-tree`` ntuple file as produced by + :ref:`exec-processntuples`. + +.. option:: run-number + + An integer corresponding to a MicroBooNE running period. Between 1 and 5 + inclusive. + +.. option:: file-type + + A string corresponding to a category describing the input file. One of + :ref:`sample-type-table`. Only one of a single file type can be declared in + the configuration file. + + .. _sample-type-table: + + .. table:: ``file-type`` options + + +--------------------+-------------------------------------+ + | Identifier | Description | + +====================+=====================================+ + | ``onBNB`` | Beam-on data (BNB or NuMI) | + +--------------------+-------------------------------------+ + | ``extBNB`` | Beam-off data (BNB or NuMI) | + +--------------------+-------------------------------------+ + | ``numuMC`` | MC files containing :math:`\nu_\mu` | + | | interactions | + +--------------------+-------------------------------------+ + | ``nueMC`` | MC files containing :math:`\nu_e` | + | | interactions | + +--------------------+-------------------------------------+ + | ``dirtMC`` | MC files with neutrino interactions | + | | occuring outside of the fiducial | + | | volume | + +--------------------+-------------------------------------+ + | ``detVarCV`` | Detector variation file with the | + | | central value prediction | + +--------------------+-------------------------------------+ + | ``detVarLYatten`` | Detector variation file with the | + | | attenuated light yield | + +--------------------+-------------------------------------+ + | ``detVarLYdown`` | NtupleFileType::kDetVarMCLYdown | + +--------------------+-------------------------------------+ + | ``detVarLYrayl`` | NtupleFileType::kDetVarMCLYrayl | + +--------------------+-------------------------------------+ + | ``detVarRecomb2`` | Detector variation with alternate | + | | recombination model | + +--------------------+-------------------------------------+ + | ``detVarSCE`` | NtupleFileType::kDetVarMCSCE | + +--------------------+-------------------------------------+ + | ``detVarWMAngleXZ``| NtupleFileType::kDetVarMCWMAngleXZ | + +--------------------+-------------------------------------+ + | ``detVarWMAngleYZ``| NtupleFileType::kDetVarMCWMAngleYZ | + +--------------------+-------------------------------------+ + | ``detVarWMdEdx`` | NtupleFileType::kDetVarMCWMdEdx | + +--------------------+-------------------------------------+ + | ``detVarWMX`` | NtupleFileType::kDetVarMCWMX | + +--------------------+-------------------------------------+ + | ``detVarWMYZ`` | NtupleFileType::kDetVarMCWMYZ | + +--------------------+-------------------------------------+ + | ``detVarCVExtra`` | NtupleFileType::kDetVarMCCVExtra | + +--------------------+-------------------------------------+ + | ``altCVMC`` | NtupleFileType::kAltCVMC | + +--------------------+-------------------------------------+ + +The remaining options are only valid for data (beam-on or -off) or fake data +files: + +.. option:: triggers + + The number of recorded triggers for the data file. + +.. option:: POT + + The protons-on-target for the data file, this is the POT value all other + MC-simulated samples are scaled to. + + - For data files this is normally extracted via a script. + - For MC files this should be empty. + - For beam-off data files this is 0. + +.. _config-bin-config: + +``bin-config.txt`` +------------------ + +This file defines a binning scheme, marking the start and end values for each +histogram bin, these are given for each kinematic variable. + +.. tip:: + + Instead of writing this file by hand, you can have it generated for you via + the :ref:`exec-binscheme` command. See its documentation for more + information. + +Example +^^^^^^^ + +.. code-block:: + + nuecc_bin_config + stv_tree + NuMICC1e + 15 + 0 0 "MC_Signal && mc_electron_energy >= 0.03 && mc_electron_energy < 0.3" + 0 0 "MC_Signal && mc_electron_energy >= 0.3 && mc_electron_energy < 0.47" + 0 0 "MC_Signal && mc_electron_energy >= 0.47 && mc_electron_energy < 0.70" + 0 0 "MC_Signal && mc_electron_energy >= 0.70 && mc_electron_energy < 0.99" + 0 0 "MC_Signal && mc_electron_energy >= 0.99 && mc_electron_energy < 1.43" + 0 0 "MC_Signal && mc_electron_energy >= 1.43 && mc_electron_energy < 3.0" + 0 0 "MC_Signal && mc_electron_energy >= 3.0" + 0 1 "MC_Signal" + 1 -1 "EventCategory == 1" + 1 -1 "EventCategory == 2" + 1 -1 "EventCategory == 3" + 1 -1 "EventCategory == 4" + 1 -1 "EventCategory == 5" + 1 -1 "EventCategory == 6" + 1 -1 "EventCategory == 7" + 8 + 0 0 "sel_nu_e_cc && reco_electron_energy >= 0.03 && reco_electron_energy < 0.3" + 0 0 "sel_nu_e_cc && reco_electron_energy >= 0.3 && reco_electron_energy < 0.47" + 0 0 "sel_nu_e_cc && reco_electron_energy >= 0.47 && reco_electron_energy < 0.70" + 0 0 "sel_nu_e_cc && reco_electron_energy >= 0.70 && reco_electron_energy < 0.99" + 0 0 "sel_nu_e_cc && reco_electron_energy >= 0.99 && reco_electron_energy < 1.43" + 0 0 "sel_nu_e_cc && reco_electron_energy >= 1.43 && reco_electron_energy < 3.0" + 0 0 "sel_nu_e_cc && reco_electron_energy >= 3.0" + 0 1 "sel_nu_e_cc" + + +Format +^^^^^^ + +.. code-block:: + + {output-tdirectory} + {ttree-name} + {selection-name} + {number-of-true-bins} + {true-bin-type} {block-index} {cut-condition} + ... repeated {number-of-true-bins} times ... + {number-of-reco-bins} + {reco-bin-type} {block-index} {cut-condition} + ... repeated {number-of-reco-bins} times ... + + +.. option:: output-tdirectory + + The name of the output TDirectory that resulting systematics histograms will + be written to. + +.. option:: ttree-name + + The name of the TTree to read entries from. + + For the standard ``ProcessNTuples`` output this should be ``stv-tree``. + However if you have modified this, use your modified name here instead. + +.. option:: selection-name + + The name of a selection as defined in + :file:`src/selections/SelectionFactory.cxx`. This is where event categories + are extracted from. + +.. option:: number-of-true-bins + + The number of defined true bins. + +.. option:: true-bin-type + + Used to label the current true bin. Options are: + + - ``0`` -- noting a signal true bin containing true events that match the + signal definition. + - ``1`` -- noting a background true bin containing true events that do not + match the signal definition. + +.. option:: block-index + + An index that groups bins that measure the same kinematic variable + distribution. This is only meaningful for signal true bins. For background + bins this should be ``-1``. + + For example, a binning scheme using variables of :math:`\cos \theta_p` and + :math:`p_p` would have indices of ``0`` and ``1`` respectively. + +.. option:: cut-condition + + A full expression for selecting and isolating the content of the bin, + matching the format of the same expression that would be passed into the + ``TTree::Draw()`` method. + + When used in lines that define reconstructed bins, care should be taken to + avoid using truth-level information. + +.. option:: number-of-reco-bins + + The number of defined reco bins. + +.. option:: reco-bin-type + + Used to label the current reco bin. Options are: + + - ``0`` -- noting an ordinary bin that will be used to extract a cross-section. + - ``1`` -- noting a sideband reco bin that will be used to constrain the background. + +.. _config-syst-config: + +``syst-config.txt`` +------------------- + +Example +^^^^^^^ + +Format +^^^^^^ diff --git a/docs/source/examples.rst b/docs/source/examples.rst new file mode 100644 index 000000000..a77f9f28f --- /dev/null +++ b/docs/source/examples.rst @@ -0,0 +1,10 @@ +Examples +======== + +This section describes several example use-cases of the ``xsec_analyzer`` framework. + +.. toctree:: + :maxdepth: 2 + + examples/liang + examples/analysis-workflow diff --git a/docs/source/examples/analysis-workflow.rst b/docs/source/examples/analysis-workflow.rst new file mode 100644 index 000000000..f278e777e --- /dev/null +++ b/docs/source/examples/analysis-workflow.rst @@ -0,0 +1,283 @@ +Analysis Workflow +================= + +.. sectionauthor:: Liang Liu + +The entire :math:`{\rm CC}0\pi Np` analysis is based on the ROOT ntuple files +produced by the PeLEE team's `searchingfornues +`_ framework. A list of +pre-made PeLEE ntuple files for beam data, cosmic data, central-value Monte +Carlo (MC), and detector variation MC samples is maintained in +:file:`configs/files_to_process.txt`, and the samples themselves are described +in the :math:`{\rm CC}0\pi Np` analysis note `MCC9 Double-differential CCNp +cross sections +`_. Any +processing of data or MC samples into new PeLEE ntuple files must be handled +upstream of the `stv-analysis-new +`_ tools. + +Assuming that the user has all needed PeLEE ntuple files already processed, the +major steps for performing a measurement are outlined in the following +subsections. + +Ntuple post-processing +---------------------- + +What does ``ProcessNTuples`` do? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``ProcessNTuples`` converts the ROOT ntuple files produced by PeLEE team's +`searchingfornues `_ framework +into a new, post-processed ntuple file. + +- Define signal and background +- Apply selection criteria (using a bool to label the survived events instead + of applying a filter) +- Compute true observables +- Compute reconstruction observables +- Categorize event + +1. SelectionBase + + `SelectionBase + `_ + is the base class of all selection classes in analyzer framework. It + provides the common interface for operations such as setup input branches, + define signal, selection, define output branches ... + + .. code-block:: cpp + + virtual bool selection( AnalysisEvent* event ) = 0; + virtual int categorize_event( AnalysisEvent* event ) = 0; + virtual void compute_reco_observables( AnalysisEvent* event ) = 0; + virtual void compute_true_observables( AnalysisEvent* event ) = 0; + virtual void define_output_branches() = 0; + virtual bool define_signal( AnalysisEvent* event ) = 0; + virtual void define_constants() = 0; + virtual void define_category_map() = 0; + virtual void reset() = 0; + virtual void define_additional_input_branches(TTree& etree) = 0; + + +2. SelectionFactory + + `SelectionFactory + `_ + implements a factory design pattern to dynamically create objects of + different selection classes (CC1mu1p0pi, CC1mu2p0pi, etc.) based on a + string input. It provides a centralized way to manage the creation of these + objects while ensuring that unsupported requests are handled with an error + message and exception. + + Users need to put their own selection classes into + ``SelectionFactory::CreateSelection`` + + .. code-block:: cpp + + SelectionBase* SelectionFactory::CreateSelection( + const std::string& selection_name ) + { + SelectionBase* sel; + if ( selection_name == "CC1mu1p0pi" ) { + sel = new CC1mu1p0pi; + } + else if ( selection_name == "CC1mu2p0pi" ) { + sel = new CC1mu2p0pi; + } + else if ( selection_name == "CC1muNp0pi" ) { + sel = new CC1muNp0pi; + } + else if ( selection_name == "Dummy" ) { + sel = new DummySelection; + } + else { + std::cerr << "Selection name requested: " << selection_name + << " is not implemented in " << __FILE__ << '\n'; + throw; + } + +Input ntuples +~~~~~~~~~~~~~ + +Ntuple files from PeLEE include two ``TTree``: +``nuselection/NeutrinoSelectionFilter`` and ``nuselection/SubRun``. + +1. ``nuselection/NeutrinoSelectionFilter`` contains more than 700 branchs for + each event. These branchs include the information of reconstructed showers, + tracks, cosmic rays, such as the MC truth, particle identification, + reconstructed four momentum, position of vertex, etc. + `Branches.hh + `_ + provide helper function to read the information from the event TTree. The + object `AnalysisEvent + `_ + will hold the information for the procedures in next step. + +.. code-block:: cpp + + void set_event_branch_addresses(TTree& etree, AnalysisEvent& ev){ + + // ...... + + // Reconstructed neutrino vertex position (with corrections for + // space charge applied) + SetBranchAddress(etree, "reco_nu_vtx_sce_x", &ev.nu_vx_ ); + SetBranchAddress(etree, "reco_nu_vtx_sce_y", &ev.nu_vy_ ); + SetBranchAddress(etree, "reco_nu_vtx_sce_z", &ev.nu_vz_ ); + + // ...... + } + +.. _pelee-to-analysis-event: + +.. table:: Mapping between PeLEE ntuple branch and AnalysisEvent member. + :width: 100% + + ============================ ============================== ======= ========================================================================================================== + Branch AnalysisEvent Type Description + ============================ ============================== ======= ========================================================================================================== + slpdg ev.nu_pdg_ int Reco PDG code of primary PFParticle in slice (i.e., the neutrino candidate) + nslice ev.nslice_ int Number of neutrino slices identified by the SliceID. Allowed values are zero or one. + topological_score ev.topological_score_ float A score which assesses to what extent the slice looks like a neutrino interaction in the TPC + CosmicIP ev.cosmic_impact_parameter_ float 3D distance of shower start from closest spacepoint of primary muon (i.e. cosmic) + reco_nu_vtx_sce_x ev.nu_vx_ float x component of reconstructed neutrino vertex position (with corrections for space charge applied) + reco_nu_vtx_sce_y ev.nu_vy_ float y component of reconstructed neutrino vertex position (with corrections for space charge applied) + reco_nu_vtx_sce_z ev.nu_vz_ float z component of reconstructed neutrino vertex position (with corrections for space charge applied) + n_pfps ev.num_pf_particles_ int Number of Pandora final particles + n_tracks ev.num_tracks_ int Number of tracks in Pandora final particles + n_showers ev.num_showers_ int Number of showers in Pandora final particles + nu_pdg ev.mc_nu_pdg_ int PDG id of the neutrino (MC truth) + true_nu_vtx_x ev.mc_nu_vx_ float x component of truth neutrino vertex coordinates + true_nu_vtx_y ev.mc_nu_vy_ float y component of truth neutrino vertex coordinates + true_nu_vtx_z ev.mc_nu_vz_ float z component of truth neutrino vertex coordinates + nu_e ev.mc_nu_energy_ float True neutrino energy + ccnc ev.mc_nu_ccnc_ int Whether the event is CC (0) or NC (1) + interaction ev.mc_nu_interaction_type_ int Interaction code from GENIE + true_nu_vtx_sce_x ev.mc_nu_sce_vx_ int x component of truth neutrino vertex position (with corrections for space charge applied) + true_nu_vtx_sce_y ev.mc_nu_sce_vy_ int y component of truth neutrino vertex position (with corrections for space charge applied) + true_nu_vtx_sce_z ev.mc_nu_sce_vz_ int z component of truth neutrino vertex position (with corrections for space charge applied) + weightSpline ev.spline_weight_ int GENIE weights + weightTune ev.tuned_cv_weight_ int GENIE weights + nu_completeness_from_pfp ev.nu_completeness_from_pfp_ int Completeness of the backtracked hits in the neutrino slice + nu_purity_from_pfp ev.nu_purity_from_pfp_ int Purity of the backtracked hits in the neutrino slice + pfp_generation_v ev.pfp_generation_ int generation, 1 is primary + pfp_trk_daughters_v ev.pfp_trk_daughters_count_ int number of track daughters + pfp_shr_daughters_v ev.pfp_shr_daughters_count_ int number of shower daughters + trk_score_v ev.pfp_track_score_ int + pfpdg ev.pfp_reco_pdg_ int PDG code of pfp in slice + pfnhits ev.pfp_hits_ int number of hits in pfp + pfnplanehits_U ev.pfp_hitsU_ int number of hits in pfp plane U + pfnplanehits_V ev.pfp_hitsV_ int number of hits in pfp plane V + pfnplanehits_Y ev.pfp_hitsY_ int number of hits in pfp plane Y + backtracked_pdg ev.pfp_true_pdg_ int PDG code of backtracked particle + backtracked_e ev.pfp_true_E_ int energy of backtracked particle + backtracked_px ev.pfp_true_px_ int px of backtracked particle + backtracked_py ev.pfp_true_py_ int py of backtracked particle + backtracked_pz ev.pfp_true_pz_ int pz of backtracked particle + shr_pfp_id_v ev.shower_pfp_id_ int Shower properties + shr_start_x_v ev.shower_startx_ int Shower properties + shr_start_y_v ev.shower_starty_ int Shower properties + shr_start_z_v ev.shower_startz_ int Shower properties + shr_dist_v ev.shower_start_distance_ int Shower properties + trk_pfp_id_v ev.track_pfp_id_ int Track properties + trk_len_v ev.track_length_ int Track properties + trk_sce_start_x_v ev.track_startx_ int Track properties + trk_sce_start_y_v ev.track_starty_ int Track properties + trk_sce_start_z_v ev.track_startz_ int Track properties + trk_distance_v ev.track_start_distance_ int Track properties + trk_sce_end_x_v ev.track_endx_ int Track properties + trk_sce_end_y_v ev.track_endy_ int Track properties + trk_sce_end_z_v ev.track_endz_ int Track properties + trk_dir_x_v ev.track_dirx_ int Track properties + trk_dir_y_v ev.track_diry_ int Track properties + trk_dir_z_v ev.track_dirz_ int Track properties + trk_theta_v ev.track_theta_ int Track properties + trk_phi_v ev.track_phi_ int Track properties + trk_energy_proton_v ev.track_kinetic_energy_p_ int Track properties + trk_range_muon_mom_v ev.track_range_mom_mu_ int Track properties + trk_mcs_muon_mom_v ev.track_mcs_mom_mu_ int Track properties + trk_pid_chipr_v ev.track_chi2_proton_ int Track properties + trk_llr_pid_v ev.track_llr_pid_ int Track properties + trk_llr_pid_u_v ev.track_llr_pid_U_ int Track properties + trk_llr_pid_v_v ev.track_llr_pid_V_ int Track properties + trk_llr_pid_y_v ev.track_llr_pid_Y_ int Track properties + trk_llr_pid_score_v ev.track_llr_pid_score_ int Track properties + mc_pdg ev.mc_nu_daughter_pdg_ int MC truth information for the final-state primary particles + mc_E ev.mc_nu_daughter_energy_ int MC truth information for the final-state primary particles + mc_px ev.mc_nu_daughter_px_ int MC truth information for the final-state primary particles + mc_py ev.mc_nu_daughter_py_ int MC truth information for the final-state primary particles + mc_pz ev.mc_nu_daughter_pz_ int MC truth information for the final-state primary particles + weights ev.mc_weights_map_ int General systematic weights + ============================ ============================== ======= ========================================================================================================== + + +2. ``nuselection/SubRun`` contains the informations of proton on target (POT) + for the current sub run + +====== ====== =============================================== +Branch Type Description +====== ====== =============================================== +run int Run number +subRun int subRun number +pot float The total amount of POT for the current sub run +====== ====== =============================================== + + + +Selection +~~~~~~~~~ + + + +- Event Category + + Enum used to label event categories of interest for analysis plots in + analyses. The enum is defined in header, e.g. `EventCategoriesXp.hh + `_ + A map that associates specific event categories with a descriptive label + and a color code for visualization purposes is defined in + `EventCategoriesXp.cxx + `_ + + To use your event category + + .. code-block:: cpp + + void CC1muNp0pi::define_category_map() { + // Use the shared category map for 1p/2p/Np/Xp + categ_map_ = CC1muXp_MAP; + } + + * Interaction codes and the corresponding processes + +==== ================================= +Code Process +==== ================================= +0 NULL +1 QES (QuasiElastic) +2 1Kaon (Single Kaon) +3 DIS (Deep Inelastic) +4 RES (Resonant) +5 COH (Coherent Production) +6 DFR (Diffractive) +7 NuEEL (Nu Electron Elastic) +8 IMD (Inverse Mu Decay) +9 AMNuGamma +10 MEC (Meson Exchange) +11 CEvNS (Coherent Elastic) +12 IBD (Inverse Beta Decay) +13 GLR (Glashow Resonance) +14 IMDAnh (IMD Annihilation) +15 PhotonCOH (Photon Coherent) +16 PhotonRES (Photon Resonance) +101 DMEL (Dark Matter Elastic) +102 DMDIS (Dark Matter Deep Inelastic) +103 DME (Dark Matter Electron) +104 Norm +-100 Unknown to GENIE +==== ================================= + + +- MircoBooNE tune + + ``ev.spline_weight_`` and ``ev.tuned_cv_weight_`` are diff --git a/docs/source/examples/liang.rst b/docs/source/examples/liang.rst new file mode 100644 index 000000000..4816db382 --- /dev/null +++ b/docs/source/examples/liang.rst @@ -0,0 +1,237 @@ +Liang's Analysis Note +===================== + +.. sectionauthor:: Liang Liu + +.. _installation: + +Installation +------------ + +The `xsec-analyzer `_ +framework is designed to be installed and run on the uboonegpvms. In principle +it can be used elsewhere if you have access to the 'PeLEE' ntuples. The only +external dependency is ROOT. To install the code, navigate to a writeable area +in your local area or (if one the :abbr:`GPVMs (general purpose virtual +machines)`) :file:`/exp/uboone/app` area. + +.. code-block:: console + + $ cd your_workarea + $ git clone https://github.com/uboone/xsec_analyzer.git + $ git checkout –t origin/tutorial-umn + $ source setup_xsec_analyzer.sh + $ make + +The setup script will attempt to set up ROOT. It will auto-detect whether +you're running :abbr:`SL7 (Scientific Linux 7)` or :abbr:`AL9 (AlmaLinux 9)`. +If you're running SL7, the setup script will set up ROOT via uboonecode. If +you're running AL9, ROOT will be set up by spack. + +The setup script will set the path to source code in the environment variable +``XSEC_ANALYZER_DIR``. This is used by the framework to find certain files, add +``${XSEC_ANALYZER_DIR}/bin`` into the environment variable ``PATH``, add +``${XSEC_ANALYZER_DIR}/lib`` into the environment variable ``LD_LIBRARY_PATH``. + +On a fresh login, just navigate to the same folder and source the +``setup_xsec_analyzer.sh`` script. + +Workflow +-------- + +The `xsec-analyzer `_ +provides six major analysis tools. They are executables in +``${XSEC_ANALYZER_DIR}/bin``: + +.. code-block:: console + + $ ls ${XSEC_ANALYZER_DIR}/bin + BinScheme ProcessNTuples SlicePlots StandaloneUnfold Unfolder univmake + +Here, I use ``CC1muXp0pi`` channel as an example to show the workflow of +xsec-analyzer. + +``ProcessNTuples`` +^^^^^^^^^^^^^^^^^^ + +The basic usage of ``ProcessNtuples``: + +.. code-block:: console + + $ ProcessNTuples INPUT_PELEE_NTUPLE_FILE CC1mu1p0pi OUTPUT_FILE + +Here, I use a script to handle the all the different type of ntuples for +different runs. + +.. code-block:: console + + $ ./ReprocessNTuples.sh -h + Usage: ./ReprocessNTuples.sh [-o ] [-v version] [-r runnumbers] [-s samples] + -c configure A text file includes all the PeLEE samples. + -s selection Name of your selection algorithm. + -o directory Specify the output directory. It should be in your data area e.g. /exp/uboone/data/users/liangliu + -r run # Specify runs to process (comma-separated, e.g., 1,2,3). + -v version Specify the version in teck note (e.g. v00_00_01) + -t type Specify the type of ntuples (e.g., numuMC,nueMC,dirtMC,extBNB,onBNB,openBNB,detVarCV ... ) + -h help Print help info + # Post-process the nu overlay of run 1 + $ ./ReprocessNTuples.sh -s CC1muXp0pi -r 1 -t numuMC + numuMC,File Name: /exp/uboone/data/users/liangliu/hadd/run1/run1_bnb_nu_overlay_generator_resc_ntuple_ntuple_ana.root + Index: 1 + Sample Type: numuMC + Number of Events: + Scaling Factor: + Output file name: /exp/uboone/data/users/liangliu/xsec/xsec_CC1muXp0pi_v00_00_01_run1_bnb_nu_overlay_generator_resc_ntuple_ntuple_ana.root + time ProcessNTuples /exp/uboone/data/users/liangliu/hadd/run1/run1_bnb_nu_overlay_generator_resc_ntuple_ntuple_ana.root CC1muXp0pi /exp/uboone/data/users/liangliu/xsec/xsec_CC1muXp0pi_v00_00_01_run1_bnb_nu_overlay_generator_resc_ntuple_ntuple_ana.root + -------------------------------- + # Post-process all the ntuples + $ ./ReprocessNTuples.sh + +The configuration file which collects all the PeLEE ntuples for my +``CC1muXp0pi`` analysis is +``${XSEC_ANALYZER_DIR}/configs/files_to_process_liangliu.txt`` + +- ``INPUT_PELEE_NTUPLE_FILE`` should be a PeLEE ntuples, e.g. `PeLEE Samples + 2023 + `_ + +- The second input argument is the name of selection algorithm. The + ``CC1mu1p0pi`` is implemented in: + + - :file:`$XSEC_ANALYZER_DIR/include/XSecAnalyzer/Selections/CC1mu1p0pi.hh` + - :file:`$XSEC_ANALYZER_DIR/src/selections/CC1mu1p0pi.cxx` + +- ``OUTPUT_FILE`` is the post-processed ntuple. It includes a TParameter called + ``summed_pot`` and a TTree called ``stv_tree`` + + For MC samples, the ``summed_pot`` gives the simulated POT needed to + scale to data. For real data, it is always zero. The POT and trigger + counts for real data files are stored elsewhere (more on that later). + This scaling is handled automatically by later parts of the framework, + so no need to worry much about this item. + + Many branches in ``stv_tree`` are copied over directly from the PeLEE + ntuples, some are new and analysis-specific. Name is a hold-over from a + much older incarnation of the code + +``BinScheme`` +^^^^^^^^^^^^^ + +Plot the smearing matrix + +.. code-block:: console + + $ BinScheme -c TutorialBinScheme + +Save binning configuration into text files + +.. code-block:: console + + $ BinScheme -s TutorialBinScheme + + ------------------------------------------------------------------ + | Welcome to ROOT 6.28/12 https://root.cern | + | (c) 1995-2024, The ROOT Team; conception: R. Brun, F. Rademakers | + | Built for linuxx8664gcc on Jan 30 2024, 08:17:35 | + | From tags/v6-28-12@v6-28-12 | + | With g++ (Spack GCC) 12.2.0 | + | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q' | + ------------------------------------------------------------------ + + non-option ARGV-elements: CCXp0piBinScheme + muon_2d_bin + stv_tree + CC1muXp0pi + 174 + 0 0 "CC1muXp0pi_MC_Signal && CC1muXp0pi_sig_mc_num_proton_in_momentum_range >= 0.000 && CC1muXp0pi_sig_mc_num_proton_in_momentum_range < 1.000" + 0 0 "CC1muXp0pi_MC_Signal && CC1muXp0pi_sig_mc_num_proton_in_momentum_range >= 1.000 && CC1muXp0pi_sig_mc_num_proton_in_momentum_range < 2.000" + 0 0 "CC1muXp0pi_MC_Signal && CC1muXp0pi_sig_mc_num_proton_in_momentum_range >= 2.000 && CC1muXp0pi_sig_mc_num_proton_in_momentum_range < 3.000" + 0 0 "CC1muXp0pi_MC_Signal && CC1muXp0pi_sig_mc_num_proton_in_momentum_range >= 3.000 && CC1muXp0pi_sig_mc_num_proton_in_momentum_range < 10.000" + ...... + 163 1 164 + 164 1 165 + 165 1 166 + 166 1 167 + Save universes bin configuration into => /exp/uboone/app/users/liangliu/analysis-code/tutorial/xsec_analyzer_eaf/configs/ccxp0pi_TKI_2D_bin_config.txt + Save slice configuration into => /exp/uboone/app/users/liangliu/analysis-code/tutorial/xsec_analyzer_eaf/configs/ccxp0pi_TKI_2D_slice_config.txt + root [0] + + +``univmake`` +^^^^^^^^^^^^ + +Using the output from step 1 and 2 to run univmake + +.. code-block:: console + + # Usage: + # univmake LIST_FILE UNIVMAKE_CONFIG_FILE OUTPUT_ROOT_FILE + $ univmake $XSEC_ANALYZER_DIR/configs/file_properties_CC1muXp0pi_v00_00_01.txt $XSEC_ANALYZER_DIR/configs/ccxp0pi_TKI_2D_bin_config.txt /exp/uboone/data/users/liangliu/ntuple/ + +``SlicePlots`` +^^^^^^^^^^^^^^ + +Once the unimake finished, we can plot the distributions that we configured +in Bin Scheme. + +.. code-block:: console + + # Usage: + # SlicePlots FILE_PROPERTIES SYS_CALC_CONF SLICE_CONF UNIV_FILE SLICE_OUTPUT_DIR + $ SlicePlots ${XSEC_ANALYZER_DIR}/configs/file_properties_fsi_current_run3.txt ${XSEC_ANALYZER_DIR}/configs/systcalc.conf ${XSEC_ANALYZER_DIR}/configs/ccxp0pi_TKI_2D_slice_config.txt /exp/uboone/data/users/liangliu/workarea/fsi/univmake_tki_2d/univmake_tki_2d.root `pwd`/output + +.. note:: + ``FILE_PROPERTIES`` is similar to ``LIST_FILE`` but they are different. + ``LIST_FILE`` is just tell the analyzer framework the available samples and + make universe for each of them. In ``FILE_PROPERTIES``, you need to + configure the universe, to be precise, the universe of detvars to plot the + distributions. + + - Runs 3, 4 and 5 have 9 different detvars + - Run 2 have no detvar ntuples, we use run 1 and run3 to estimate run 2 detvars + - Run 1 doesn't need LY Attenuation + - MC generated for Run 4a with a special flux that models the misalignment of + the beam -- so it's important to use the specific MC for that period weighted + to the Run 4a POT (from Patrick) + + +``Unfolder`` +^^^^^^^^^^^^ + +Subtract backgrounds, correct for inefficiency and bin-to-bin-smearing, +convert to cross-section units. + +.. code-block:: console + + # Usage: + # Unfolder XSEC_CONF SLICE_CONF XSEC_OUTPUT_ROOT_FILE + $ Unfolder xsec_config_fakedata_dagostini.txt ${XSEC_ANALYZER_DIR}/configs/ccxp0pi_TKI_2D_slice_config.txt xsec_muon_proton_fakedata_dagostini.root + +.. code-block:: console + + UnivFile /exp/uboone/data/users/liangliu/workarea/fsi/univmake_tki_2d/univmake_tki_2d.root + SystFile /exp/uboone/app/users/liangliu/analysis-code/tutorial/xsec_analyzer_eaf/configs/systcalc.conf + FPFile /exp/uboone/app/users/liangliu/analysis-code/tutorial/xsec_analyzer_eaf/configs/file_properties_fsi_current_run12345_fakedata.txt + Unfold DAgostini fm 0.025 + #Unfold WienerSVD 1 second-deriv + Prediction uBTune "MicroBooNE Tune" univ CV + Prediction FakeData "Fake data" univ FakeData + #Prediction gv2 "GENIE 2.12.10" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-gv2.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction gv3 "GENIE 3.0.6" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-gv3.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction g1802a "GENIE 3.2.0 G18_02a" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-gv3-g1802a.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction g2111a "GENIE 3.2.0 G21_11a" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-gv3-g2111a.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction g2111b "GENIE 3.2.0 G21_11b" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-gv3-g2111b.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction neut "NEUT 5.4.0.1" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-neut.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction nuwro "NuWro 19.02.1" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/comp-all/comp-nuwro.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + #Prediction gibuu "GiBUU 2021.1" file /exp/uboone/app/users/gardiner/temp-gen/BuildEventGenerators/ubmc/mygibuu3.root MicroBooNE_CC1MuNp_XSec_2D_PpCosp_nu_MC + + +StandaloneUnfold +"""""""""""""""" + +Steven has presented `Standalone unfolding tutorial slides +`_ +at a MicroBooNE analysis retreat. + + + diff --git a/docs/source/executables.rst b/docs/source/executables.rst new file mode 100644 index 000000000..75c03dbf7 --- /dev/null +++ b/docs/source/executables.rst @@ -0,0 +1,320 @@ +Executables +=========== + +``xsec_analyzer`` provides several binaries that guide the workflow for the +framework. The sources for these are compiled from :file:`src/app/`. + +The configuration of input files and their properties is provided in a +declarative manner, the formats of these files are provided in +:doc:`configuration-files`. + +.. _exec-processntuples: + +``ProcessNTuples`` +------------------ + +``ProcessNTuples`` takes an input PeLEE ntuple, processes it through a chosen +selection, and then produces a new ntuple with an ``stv_tree`` TTree containing +selection values and kinematic variables. + +:Source: :file:`src/app/ProcessNTuples.C` + +Usage +^^^^^ + +.. code-block:: + + ProcessNTuples INPUT_PELEE_NTUPLE_FILE FILE_TYPE SELECTION_NAMES OUTPUT_FILE + +.. program:: ProcessNTuples + +.. option:: INPUT_PELEE_NTUPLE_FILE + + A path to the PeLEE ntuple to be processed. + +.. option:: FILE_TYPE + + The type of the input file. One of: + + ``nueMC`` or ``nueDV`` + Represents an `intrinsic` sample containing :math:`\nu_e` interactions. + Skips non-:math:`\nu_e` events to avoid double-counting as part of a full + selection. + + ``numuMC`` + Represents an `intrinsic` sample containing :math:`\nu_\mu` interactions. + Skips non-:math:`\nu_\mu` events to avoid double-counting as part of a + full selection. + + ``dirtMC`` + When :cpp:var:`useNuMI` is ``true``, sets the sample's event weights to + 0.65 in accordance with NuMI dirt weighting procedures. + When :cpp:var:`useNuMI` is ``false``, this has no effect. + + ``other`` + Any other value chosen has no special effect. + All present events are processed and have a base weighting of ``1.0``. + +.. option:: SELECTION_NAMES + + One or more selections that have: + + - A header file (``.hh``) in: :file:`include/XSecAnalyzer/Selections/` + - An implementation file (``.cxx``) in :file:`src/selections/` + - And have been added to :cpp:expr:`SelectionFactory` in + :file:`src/selections/SelectionFactory.cxx` + + Multiple selections can be processed by passing ``NAME1,NAME2,...``. + +.. option:: OUTPUT_FILE + + A path to where the output processed ntuple should be written. + +.. _exec-binscheme: + +``BinScheme`` +------------- + +``BinScheme`` takes a histogram binning scheme defined in a header and +implementation source file. It aides the binning process by printing response +matrices and allows a binning configuration file to be outputted. + +Running this program is optional but it takes the tedium out of writing a bin +scheme configuration file by hand. + +:Source: :file:`src/app/binscheme.C` + +Usage +^^^^^ + +.. code-block:: + + BinScheme [options] BIN_SCHEME_NAME + +.. program:: binscheme + +.. option:: BIN_SCHEME_NAME + + A binning scheme name that has: + + - A header file in: :file:`include/XSecAnalyzer/Binning`. + - An implementation file in: :file:`src/binning/`. + - And has been added to :cpp:expr:`BinSchemeFactory` in + :file:`src/binning/BinSchemeFactory.cxx`. + +.. option:: -h, --help + + Prints the usage for the program. + +.. option:: -s, --save + + Save binning scheme to a configuration text file. This can be fed into + latter stages of the framework. + +.. option:: -c, --config + + Plot/print a response matrix, facilitating binning schemes. + +``univmake`` +------------ + +.. attention:: + + This program has not been documented here yet. Please see the source file. + +:Source: :file:`src/app/univmake.C` + +Usage +^^^^^ + +.. code-block:: + + univmake LIST_FILE UNIVMAKE_CONFIG_FILE OUTPUT_ROOT_FILE [FILE_PROPERTIES_CONFIG_FILE] + +.. program:: univmake + +.. option:: LIST_FILE + + A newline delimited list of paths to ``stv-tree`` ntuple files. + + Instead, a :ref:`config-file-properties` file can be used here and only the + first item on each line will be used as the file path. + +.. option:: UNIVMAKE_CONFIG_FILE + + A file defining the binning scheme for each kinematic variable. Defined by + :ref:`config-bin-config`. This file can also be generated by BinScheme. + +.. option:: OUTPUT_ROOT_FILE + + The path to where the output file from this program should be created. + +.. option:: FILE_PROPERTIES_CONFIG_FILE + + A file matching :ref:`config-file-properties`. This particular argument uses + all information present in that file. + +``SlicePlots`` +-------------- + +This program takes the prepared sample files and their systematic universe +variations from ``univmake`` in addition to the kinematic variable bin +configuration file. It produces several plots of the distributions of kinematic +variables as defined in ``SLICE_Config``, placing them into the folder given by +``Plot_OutputDir``. + +:Source: :file:`src/app/Slice_Plots.C` + +Usage +^^^^^ + +.. code-block:: + + SlicePlots FPM_CONFIG SYST_Config SLICE_Config Univ_Output Plot_OutputDir + +.. program:: SlicePlots + +.. option:: FPM_CONFIG + + A path to a :ref:`config-file-properties` configuration file. + +.. option:: SYST_Config + + A file describing the systematic variations used by SlicePlots. + +.. option:: SLICE_Config + + A file describing the binning configuration for all kinematic variables. + +.. option:: Univ_Output + + The location of the output file containing the systematic universes created + by ``univmake``. + +.. option:: Plot_OutputDir + + The output directory for where produced plots will be saved. + + +``Unfolder`` +------------ + +.. attention:: + + This program has not been fully documented here yet. Please see the source + file. + +:Source: :file:`src/app/Unfolder.C` + +Usage +^^^^^ + +.. code-block:: + + Unfolder XSEC_CONFIG SLICE_CONFIG OUTPUT_FILE + +.. program:: Unfolder + +.. option:: XSEC_CONFIG + + ... + +.. option:: SLICE_CONFIG + + ... + +.. option:: OUTPUT_FILE + + ... + + +Auxiliary Programs +------------------ + +.. _exec-addfakeweights: + +``AddFakeWeights`` +^^^^^^^^^^^^^^^^^^ + +``AddFakeWeights`` takes a NuMI PeLEE dirt file with a partial set of +systematic weights, a PelEE ntuple file with a full set of systematic weights, +and an output file name. + +:Source: :file:`src/app/NuMI/addFakeWeights.cpp` + +Usage +..... + +.. code-block:: + + AddFakeWeights INPUT_FILE INPUT_FULL_WEIGHTS_FILE OUTPUT_FILE + +.. program:: AddFakeWeights + +.. option:: INPUT_FILE + + A PeLEE ntuple file that contains a partial set of systematic weights. + + This is intended to be a NuMI dirt file. + +.. option:: INPUT_FULL_WEIGHTS_FILE + + A PeLEE ntuple file that contains a full set of systematic weights to be + used as a template for adding missing weights. + +.. option:: OUTPUT_FILE + + The file to be outputted with a full set of systematic weights. + +.. _exec-addbeamlinegeometryweights: + +``AddBeamlineGeometryWeights`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``AddBeamlineGeometryWeights`` takes any NuMI PELEE ntuple, the NuMI operating mode, +an output file name and a hard-coded path to a NuMI beamline geometry weights +file. + +.. attention:: + + The use of this program requires a ROOT file containing all NuMI flux + beamline geometry variations, contained on MicroBooNE GPVMs. The path to the + file is hard-coded into the executable's source file. + + The default location expected by this program is + :file:`src/app/NuMI/NuMI_Geometry_Weights_Histograms.root`. However this can + be changed by editing the source file. + +:Source: :file:`src/app/NuMI/addBeamlineGeometryWeightsToMap.cpp` + +Usage +..... + +.. code-block:: + + AddBeamlineGeometryWeights INPUT_FILE HORN_CURRENT_MODE OUTPUT_FILE + +.. program:: AddBeamlineGeometryWeights + +.. option:: INPUT_FILE + + A PeLEE ntuple file without any NuMI beamline geometry weights. + + The program checks for the presence of the weight map key ``Horn_2kA`` as an + indicator that beamline geometry weights already exist in the file. + +.. option:: HORN_CURRENT_MODE + + The curent mode configuration of the NuMI beamline represented by the input + PeLEE ntuple. One of the following options: + + ``RHC`` + Reverse Horn Current + + ``FHC`` + Forward Horn Current + +.. option:: OUTPUT_FILE + + The output path where PeLEE ntuples with additional beamline geometry + weights should be written to. diff --git a/docs/source/glossary.rst b/docs/source/glossary.rst new file mode 100644 index 000000000..7e5a44a69 --- /dev/null +++ b/docs/source/glossary.rst @@ -0,0 +1,28 @@ +Glossary +======== + +.. glossary:: + :sorted: + + PeLEE + The Pandora electron Low Energy Excess, corresponding to both a + MicroBooNE physics analysis and the associated data production workflows + used for that analysis. + + detvar + Detector variation files produced for a series of alternative physics + models that can be used to simulate detector response. These form part of + the characterisation of systematic uncertainties in cross-section + analyses. + + ``stv-tree`` ntuple + A ROOT TTree/NTuple produced from the ProcessNTuples program. + + Pandora + The Pandora Multi-algorithm Pattern Recognition Framework, designed to + reconstruct track and shower objects from ionisation energy depositions + in the TPC. + + .. Unfolding + .. The process of correcting for detector-induced effects on the measured + .. cross-section. These effects lead to events in diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 000000000..cec338901 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,51 @@ +.. xsec_analyzer documentation master file, created by + sphinx-quickstart on Thu Aug 28 16:49:36 2025. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +xsec_analyzer +============= + +A framework for operating MicroBooNE [#ub]_ cross-section analyses. + +This framework uses the PeLEE-format ROOT ntuples produced by the relevant +groups in MicroBooNE and provides scaffolding for physics analyzers. + +This allows analyzers to write code to define their targeted signal using true +variables and select their events of interest from reconstructed quantities. +The framework also handles propagating systematic uncertainties from different +sources and carries out the process of cross-section unfolding across +user-defined kinematic variables. + +The general approach taken by the framework towards extracting neutrino-argon +cross-sections is described mathematically in Section B. of [Gardiner]_. + +Getting Started +--------------- + +- Find out about the :doc:`executables` that the framework provides and how to + use them. +- View the :ref:`PeLEE branch to AnalysisEvent member mapping + ` to see how to access event variables. +- See existing :doc:`examples`. + +.. toctree:: + :maxdepth: 2 + :hidden: + + Introduction + executables + configuration-files + adding-selection + examples + glossary + +.. rubric:: Errata + +.. [#ub] The `Micro Booster Neutrino Experiment `_. + +.. rubric:: References + +.. [Gardiner] + Steven Gardiner -- `Mathematical Methods for Cross-Section Extraction` 2025, + `arXiv:2401.04065 `_ [hep-ex] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..856ebac1e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[project] +name = "docs" +version = "0.1.0" +requires-python = "~=3.12.0" +dependencies = [ + "furo>=2025.7.19", + "sphinx>=8.2.3", + "sphinx-autobuild>=2025.8.25", +] diff --git a/uv.lock b/uv.lock new file mode 100644 index 000000000..1c61ae661 --- /dev/null +++ b/uv.lock @@ -0,0 +1,477 @@ +version = 1 +revision = 3 +requires-python = "==3.12.*" + +[[package]] +name = "accessible-pygments" +version = "0.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/c1/bbac6a50d02774f91572938964c582fff4270eee73ab822a4aeea4d8b11b/accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872", size = 1377899, upload-time = "2024-05-10T11:23:10.216Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7", size = 1395903, upload-time = "2024-05-10T11:23:08.421Z" }, +] + +[[package]] +name = "alabaster" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, +] + +[[package]] +name = "anyio" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.13.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/2e/3e5079847e653b1f6dc647aa24549d68c6addb4c595cc0d902d1b19308ad/beautifulsoup4-4.13.5.tar.gz", hash = "sha256:5e70131382930e7c3de33450a2f54a63d5e4b19386eab43a5b34d594268f3695", size = 622954, upload-time = "2025-08-24T14:06:13.168Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/eb/f4151e0c7377a6e08a38108609ba5cede57986802757848688aeedd1b9e8/beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a", size = 105113, upload-time = "2025-08-24T14:06:14.884Z" }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "docs" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "furo" }, + { name = "sphinx" }, + { name = "sphinx-autobuild" }, +] + +[package.metadata] +requires-dist = [ + { name = "furo", specifier = ">=2025.7.19" }, + { name = "sphinx", specifier = ">=8.2.3" }, + { name = "sphinx-autobuild", specifier = ">=2025.8.25" }, +] + +[[package]] +name = "docutils" +version = "0.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, +] + +[[package]] +name = "furo" +version = "2025.7.19" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "accessible-pygments" }, + { name = "beautifulsoup4" }, + { name = "pygments" }, + { name = "sphinx" }, + { name = "sphinx-basic-ng" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/69/312cd100fa45ddaea5a588334d2defa331ff427bcb61f5fe2ae61bdc3762/furo-2025.7.19.tar.gz", hash = "sha256:4164b2cafcf4023a59bb3c594e935e2516f6b9d35e9a5ea83d8f6b43808fe91f", size = 1662054, upload-time = "2025-07-19T10:52:09.754Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/34/2b07b72bee02a63241d654f5d8af87a2de977c59638eec41ca356ab915cd/furo-2025.7.19-py3-none-any.whl", hash = "sha256:bdea869822dfd2b494ea84c0973937e35d1575af088b6721a29c7f7878adc9e3", size = 342175, upload-time = "2025-07-19T10:52:02.399Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "roman-numerals-py" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017, upload-time = "2025-02-22T07:34:54.333Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "snowballstemmer" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/e6/21ccce3262dd4889aa3332e5a119a3491a95e8f60939870a3a035aabac0d/soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f", size = 103472, upload-time = "2025-08-27T15:39:51.78Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" }, +] + +[[package]] +name = "sphinx" +version = "8.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "roman-numerals-py" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" }, +] + +[[package]] +name = "sphinx-autobuild" +version = "2025.8.25" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "sphinx" }, + { name = "starlette" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/3c/a59a3a453d4133777f7ed2e83c80b7dc817d43c74b74298ca0af869662ad/sphinx_autobuild-2025.8.25.tar.gz", hash = "sha256:9cf5aab32853c8c31af572e4fecdc09c997e2b8be5a07daf2a389e270e85b213", size = 15200, upload-time = "2025-08-25T18:44:55.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/20/56411b52f917696995f5ad27d2ea7e9492c84a043c5b49a3a3173573cd93/sphinx_autobuild-2025.8.25-py3-none-any.whl", hash = "sha256:b750ac7d5a18603e4665294323fd20f6dcc0a984117026d1986704fa68f0379a", size = 12535, upload-time = "2025-08-25T18:44:54.164Z" }, +] + +[[package]] +name = "sphinx-basic-ng" +version = "1.0.0b2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/0b/a866924ded68efec7a1759587a4e478aec7559d8165fac8b2ad1c0e774d6/sphinx_basic_ng-1.0.0b2.tar.gz", hash = "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9", size = 20736, upload-time = "2023-07-08T18:40:54.166Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/dd/018ce05c532a22007ac58d4f45232514cd9d6dd0ee1dc374e309db830983/sphinx_basic_ng-1.0.0b2-py3-none-any.whl", hash = "sha256:eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b", size = 22496, upload-time = "2023-07-08T18:40:52.659Z" }, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, +] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, +] + +[[package]] +name = "starlette" +version = "0.47.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/15/b9/cc3017f9a9c9b6e27c5106cc10cc7904653c3eec0729793aec10479dd669/starlette-0.47.3.tar.gz", hash = "sha256:6bc94f839cc176c4858894f1f8908f0ab79dfec1a6b8402f6da9be26ebea52e9", size = 2584144, upload-time = "2025-08-24T13:36:42.122Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/fd/901cfa59aaa5b30a99e16876f11abe38b59a1a2c51ffb3d7142bb6089069/starlette-0.47.3-py3-none-any.whl", hash = "sha256:89c0778ca62a76b826101e7c709e70680a1699ca7da6b44d38eb0a7e61fe4b51", size = 72991, upload-time = "2025-08-24T13:36:40.887Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, + { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, + { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, + { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, + { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, + { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, + { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +]