├── .all-contributorsrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── config.yml │ ├── documentation.md │ └── feature-request.md ├── dependabot.yml └── workflows │ ├── build-distributions.yml │ ├── build-test.yml │ ├── deploy.yml │ ├── semantic-pr-title.yml │ └── upload-nightly-wheels.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── CITATION.cff ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── dev ├── example-objects.py └── make-models.py ├── docs-img ├── diagrams │ ├── abstraction-layers.png │ ├── abstraction-layers.svg │ ├── example-dask-graph.png │ ├── uproot-awkward-timeline.png │ └── uproot-awkward-timeline.svg ├── logo │ ├── logo-300px-white.png │ ├── logo-300px.png │ ├── logo-600px.png │ └── logo.svg └── photos │ └── switcheroo.jpg ├── docs-sphinx ├── _templates │ └── breadcrumbs.html ├── basic.rst ├── conf.py ├── index.rst ├── make_changelog.py ├── prepare_docstrings.py ├── requirements.txt └── uproot3-to-4.rst ├── pyproject.toml ├── src └── uproot │ ├── __init__.py │ ├── _awkwardforth.py │ ├── _dask.py │ ├── _util.py │ ├── behavior.py │ ├── behaviors │ ├── RNTuple.py │ ├── RooCurve.py │ ├── RooHist.py │ ├── TAxis.py │ ├── TBranch.py │ ├── TBranchElement.py │ ├── TDatime.py │ ├── TGraph.py │ ├── TGraphAsymmErrors.py │ ├── TGraphErrors.py │ ├── TH1.py │ ├── TH2.py │ ├── TH2Poly.py │ ├── TH3.py │ ├── TParameter.py │ ├── TProfile.py │ ├── TProfile2D.py │ ├── TProfile3D.py │ ├── TTree.py │ └── __init__.py │ ├── cache.py │ ├── compression.py │ ├── const.py │ ├── containers.py │ ├── deserialization.py │ ├── dynamic.py │ ├── exceptions.py │ ├── extras.py │ ├── interpretation │ ├── __init__.py │ ├── grouped.py │ ├── identify.py │ ├── jagged.py │ ├── known_forth │ │ ├── __init__.py │ │ └── atlas.py │ ├── library.py │ ├── numerical.py │ ├── objects.py │ └── strings.py │ ├── language │ ├── __init__.py │ └── python.py │ ├── model.py │ ├── models │ ├── RNTuple.py │ ├── TArray.py │ ├── TAtt.py │ ├── TBasket.py │ ├── TBranch.py │ ├── TClonesArray.py │ ├── TDatime.py │ ├── TGraph.py │ ├── TH.py │ ├── THashList.py │ ├── TLeaf.py │ ├── TList.py │ ├── TMatrixT.py │ ├── TNamed.py │ ├── TObjArray.py │ ├── TObjString.py │ ├── TObject.py │ ├── TRef.py │ ├── TString.py │ ├── TTable.py │ ├── TTime.py │ ├── TTree.py │ └── __init__.py │ ├── pyroot.py │ ├── reading.py │ ├── serialization.py │ ├── sink │ ├── __init__.py │ └── file.py │ ├── source │ ├── __init__.py │ ├── chunk.py │ ├── coalesce.py │ ├── cursor.py │ ├── file.py │ ├── fsspec.py │ ├── futures.py │ ├── http.py │ ├── object.py │ ├── s3.py │ └── xrootd.py │ ├── streamers.py │ └── writing │ ├── __init__.py │ ├── _cascade.py │ ├── _cascadentuple.py │ ├── _cascadetree.py │ ├── _dask_write.py │ ├── identify.py │ ├── interpret.py │ └── writable.py ├── tests-wasm ├── __init__.py ├── test_1272_basic_functionality.py ├── test_1365_awkwardforth_reading.py └── utils.py └── tests ├── __init__.py ├── conftest.py ├── samples └── h_dynamic.pkl ├── test_0001_source_class.py ├── test_0006_notify_when_downloaded.py ├── test_0007_single_chunk_interface.py ├── test_0008_start_interpretation.py ├── test_0009_nested_directories.py ├── test_0010_start_streamers.py ├── test_0011_generate_classes_from_streamers.py ├── test_0013_rntuple_anchor.py ├── test_0014_all_ttree_versions.py ├── test_0016_interpretations.py ├── test_0017_multi_basket_multi_branch_fetch.py ├── test_0018_array_fetching_interface.py ├── test_0022_number_of_branches.py ├── test_0023_more_interpretations_1.py ├── test_0023_ttree_versions.py ├── test_0028_fallback_to_read_streamer.py ├── test_0029_more_string_types.py ├── test_0031_test_stl_containers.py ├── test_0033_more_interpretations_2.py ├── test_0034_generic_objects_in_ttrees.py ├── test_0035_datatype_generality.py ├── test_0038_memberwise_serialization.py ├── test_0043_iterate_function.py ├── test_0044_concatenate_function.py ├── test_0046_histograms_bh_hist.py ├── test_0053_parents_should_not_be_bases.py ├── test_0058_detach_model_objects_from_files.py ├── test_0066_fix_http_fallback_freeze.py ├── test_0067_common_entry_offsets.py ├── test_0081_dont_parse_colons.py ├── test_0087_memberwise_splitting_not_implemented_messages.py ├── test_0088_read_with_http.py ├── test_0099_read_from_file_object.py ├── test_0112_fix_pandas_with_cut.py ├── test_0118_fix_name_fetch_again.py ├── test_0123_atlas_issues.py ├── test_0126_turn_unknown_emptyarrays_into_known_types.py ├── test_0167_use_the_common_histogram_interface.py ├── test_0172_allow_allocators_in_vector_typenames.py ├── test_0173_empty_and_multiprocessing_bugs.py ├── test_0182_complain_about_missing_files.py ├── test_0194_fix_lost_cuts_in_iterate.py ├── test_0220_contiguous_byte_ranges_in_http.py ├── test_0228_read_TProfiles.py ├── test_0240_read_TGraphAsymmErrors.py ├── test_0278_specializations_for_TParameter.py ├── test_0302_pickle.py ├── test_0303_empty_jagged_array.py ├── test_0320_start_working_on_ROOT_writing.py ├── test_0322_writablefile_infrastructure.py ├── test_0329_update_existing_root_files.py ├── test_0335_empty_ttree_division_by_zero.py ├── test_0341_manipulate_streamer_info.py ├── test_0344_writabledirectory_can_read.py ├── test_0345_bulk_copy_method.py ├── test_0349_write_TObjString.py ├── test_0350_read_RooCurve_RooHist.py ├── test_0351_write_TList.py ├── test_0352_write_THashList.py ├── test_0384_move_behavior_of_and_fix_383.py ├── test_0398_dimensions_in_leaflist.py ├── test_0405_write_a_histogram.py ├── test_0406_write_a_ttree.py ├── test_0407_read_TDatime.py ├── test_0412_write_multidimensional_numpy_to_ttree.py ├── test_0414_write_jagged_arrays.py ├── test_0416_writing_compressed_data.py ├── test_0418_read_TTable.py ├── test_0420_pyroot_uproot_interoperability.py ├── test_0422_hist_integration.py ├── test_0430_global_index_for_tuples_of_DataFrames.py ├── test_0438_TClonesArray_is_not_AsGrouped.py ├── test_0439_check_awkward_before_numpy.py ├── test_0442_regular_TClonesArray.py ├── test_0472_tstreamerinfo_for_ttree.py ├── test_0475_remember_to_update_freesegments.py ├── test_0484_manually_add_model_for_TMatrixTSym_double_.py ├── test_0487_implement_asdtypeinplace.py ├── test_0498_create_leaf_branch_in_extend.py ├── test_0519_remove_memmap_copy.py ├── test_0520_dynamic_classes_cant_be_abc_subclasses.py ├── test_0569_fBits_is_4_bytes.py ├── test_0576_unicode_in_names.py ├── test_0578_dask_for_numpy.py ├── test_0580_round_trip_for_no_flow_histograms.py ├── test_0589_explicitly_interpret_RVec_type.py ├── test_0603_dask_delayed_open.py ├── test_0609_num_enteries_func.py ├── test_0610_awkward_form.py ├── test_0630_rntuple_basics.py ├── test_0637_setup_tests_for_AwkwardForth.py ├── test_0643_reading_vector_pair_TLorentzVector_int.py ├── test_0651_implement_transformed_axis.py ├── test_0652_dask_for_awkward.py ├── test_0662_rntuple_stl_containers.py ├── test_0692_fsspec_reading.py ├── test_0692_fsspec_writing.py ├── test_0700_dask_empty_arrays.py ├── test_0705_rntuple_writing_metadata.py ├── test_0750_avoid_empty_TBasket_issue.py ├── test_0755_dask_awkward_column_projection.py ├── test_0791_protect_uproot_project_columns_from_dask_node_names.py ├── test_0798_DAOD_PHYSLITE.py ├── test_0808_fix_awkward_form_for_AsStridedObjects.py ├── test_0816_separate_AwkwardForth_machines_by_TBranch.py ├── test_0832_ak_add_doc_should_also_add_to_typetracer.py ├── test_0840_support_tleafG.py ├── test_0841_fix_814.py ├── test_0844_fix_delete_hist_from_root.py ├── test_0852_fix_strided_interp_extra_offsets.py ├── test_0870_writing_arrays_of_type_unknown_fix_822.py ├── test_0876_uproot_dask_blind_steps.py ├── test_0886_fix_awkward_form_breadcrumbs.py ├── test_0910_fix_906_members_non_numerical_branches.py ├── test_0911_fix_interp_array_non_numerical_objs_issue_880.py ├── test_0912_fix_pandas_and_double_nested_vectors_issue_885.py ├── test_0916_read_from_s3.py ├── test_0927_dont_assume_uproot_in_global_scope_in_TPython_Eval.py ├── test_0930_expressions_in_pandas.py ├── test_0940_feat_add_TLeafC_string_support.py ├── test_0962_rntuple_update.py ├── test_0965_inverted_axes_variances_hist_888.py ├── test_0976_path_object_split.py ├── test_1000-write-TProfiles.py ├── test_1043_const_std_string.py ├── test_1058_dask_awkward_report.py ├── test_1063_dask_distributed.py ├── test_1070_pandas_dataframe_building_performance_fix.py ├── test_1085_dask_write.py ├── test_1102_any_locks_in_models_must_be_transient.py ├── test_1114_fix_attempt_to_concatenate_numpy_with_awkward.py ├── test_1120_check_decompression_executor_pass_for_dask.py ├── test_1127_fix_allow_colon_in_key_names.py ├── test_1128_TGraph_writing.py ├── test_1146_split_ranges_for_large_files_over_http.py ├── test_1154_classof_using_relative_path.py ├── test_1159_rntuple_cluster_groups.py ├── test_1160_std_string_in_TDirectory.py ├── test_1180_read_free_floating_vector_issue_1179.py ├── test_1181_support_for_stl_list.py ├── test_1182_add_support_for_bitset.py ├── test_1183_ttime_custom.py ├── test_1186_dtype_might_raise_ValueError.py ├── test_1189_dask_failing_on_duplicate_keys.py ├── test_1191_rntuple_fixes.py ├── test_1198_coalesce.py ├── test_1207_fix_title_of_TBranch_with_counter.py ├── test_1212_dont_let_update_mess_up_file_version.py ├── test_1221_AwkwardForth_bug.py ├── test_1223_more_rntuple_types.py ├── test_1229_const_in_typename.py ├── test_1250_rntuple_improvements.py ├── test_1254_test_threadpool_executor_for_dask.py ├── test_1264_write_NumPy_array_of_strings.py ├── test_1275_fix_TStreamerLoop_code_generation.py ├── test_1282_add_known_forth_for_atlas.py ├── test_1285_rntuple_multicluster_concatenation.py ├── test_1318_dont_compare_big_endian_in_awkward.py ├── test_1321_pandas_changed_api_again.py ├── test_1347_rntuple_floats_suppressed_cols.py ├── test_1356_basic_rntuple_writing.py ├── test_1375_extend_ak_add_doc.py ├── test_1395_rntuple_writing_lists_and_structs.py ├── test_1406_improved_rntuple_methods.py ├── test_1411_rntuple_physlite_ATLAS.py └── test_1412_rntuple_dask.py /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Something seems to be broken… 4 | title: '' 5 | labels: bug (unverified) 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thank you for submitting an issue! (I know that it takes time and effort to do so.) 11 | 12 | Note that we'll be closing the issue as soon as a solution is proposed. This is not meant to be unfriendly; it's for our own bookkeeping. If you think the first answer/solution is unsatisfactory, please do continue the thread and we'll reopen it or otherwise address it. 13 | 14 | Please attach a small ROOT file that reproduces the issue! If small and public, you can drag-and-drop it into the issue—rename the extension to "txt" so that GitHub allows it. If large, you can put it on some large-file service (e.g. Dropbox). In general, we can't access XRootD URLs (most are not public). 15 | 16 | Include the version number (and update if necessary, if you're not using the [latest version](https://pypi.org/project/uproot/)). 17 | 18 | ```python 19 | >>> import uproot 20 | >>> uproot.__version__ 21 | ``` 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Start a discussion (GitHub) 4 | about: How do I…? 5 | url: https://github.com/scikit-hep/uproot5/discussions 6 | - name: 'StackOverflow: [uproot] tag' 7 | about: How do I…? 8 | url: https://stackoverflow.com/questions/tagged/uproot 9 | - name: 'Gitter: Scikit-HEP/uproot room' 10 | about: Getting help in real-time… 11 | url: https://gitter.im/Scikit-HEP/uproot 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation 3 | about: Something needs to be explained… 4 | title: '' 5 | labels: docs 6 | assignees: '' 7 | 8 | --- 9 | 10 | On the [tutorials site](https://uproot.readthedocs.io/)? 11 | 12 | In the Python docstrings? (They're presented on the same website.) 13 | 14 | What, specifically, needs more explanation? 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Some functionality needs to be added… 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | What you're looking for might already be possible as a combination of existing functions, so these requests might get converted into requests for documentation (with a corresponding change in title). 11 | 12 | Here are some links to documentation, to help you in your search. 13 | 14 | * [The tutorials site](https://uproot.readthedocs.io/) 15 | * [StackOverflow: [uproot] tag](https://stackoverflow.com/questions/tagged/uproot) 16 | * [Gitter: Scikit-HEP/uproot room](https://gitter.im/Scikit-HEP/uproot) 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: github-actions 5 | directory: / 6 | schedule: 7 | interval: weekly 8 | groups: 9 | actions: 10 | patterns: 11 | - '*' 12 | -------------------------------------------------------------------------------- /.github/workflows/build-distributions.yml: -------------------------------------------------------------------------------- 1 | name: Build sdist and wheel 2 | 3 | on: 4 | # Run on demand with workflow dispatch 5 | workflow_dispatch: 6 | # Use from other workflows 7 | workflow_call: 8 | 9 | jobs: 10 | dist: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | 17 | - uses: hynek/build-and-inspect-python-package@v2 18 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to PyPI 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: 7 | - published 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | 15 | build_dist: 16 | name: Build and upload sdist and wheel 17 | if: github.repository_owner == 'scikit-hep' 18 | uses: ./.github/workflows/build-distributions.yml 19 | 20 | publish: 21 | environment: 22 | name: pypi 23 | needs: [build_dist] 24 | runs-on: ubuntu-latest 25 | if: github.event_name == 'release' && github.event.action == 'published' 26 | permissions: 27 | id-token: write 28 | attestations: write 29 | contents: read 30 | 31 | steps: 32 | - uses: actions/download-artifact@v4 33 | with: 34 | name: Packages 35 | path: dist 36 | 37 | - name: List distributions to be deployed 38 | run: ls -lha dist/ 39 | 40 | - name: Generate artifact attestation for sdist and wheel 41 | uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0 42 | with: 43 | subject-path: dist/uproot-* 44 | 45 | - uses: pypa/gh-action-pypi-publish@release/v1 46 | with: 47 | print-hash: true 48 | -------------------------------------------------------------------------------- /.github/workflows/semantic-pr-title.yml: -------------------------------------------------------------------------------- 1 | name: Lint PR 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | workflow_dispatch: 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | main: 17 | name: Validate PR title 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: amannn/action-semantic-pull-request@v5 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.github/workflows/upload-nightly-wheels.yml: -------------------------------------------------------------------------------- 1 | name: Upload nightly wheels to Anaconda Cloud 2 | 3 | on: 4 | # Run daily at 1:23 UTC 5 | schedule: 6 | - cron: 23 1 * * * 7 | # Run on demand with workflow dispatch 8 | workflow_dispatch: 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.ref }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | 16 | build_wheel: 17 | name: Build and upload wheel 18 | if: github.repository_owner == 'scikit-hep' 19 | uses: ./.github/workflows/build-distributions.yml 20 | 21 | upload_nightly_wheels: 22 | name: Upload nightly wheels to Anaconda Cloud 23 | needs: [build_wheel] 24 | runs-on: ubuntu-latest 25 | 26 | steps: 27 | - uses: actions/download-artifact@v4 28 | with: 29 | name: Packages 30 | path: dist 31 | 32 | - name: List wheel to be deployed 33 | run: ls -lha dist/*.whl 34 | 35 | - name: Upload wheel to Anaconda Cloud as nightly 36 | uses: scientific-python/upload-nightly-action@b36e8c0c10dbcfd2e05bf95f17ef8c14fd708dbf # 0.6.2 37 | with: 38 | artifacts_path: dist 39 | anaconda_nightly_upload_token: ${{ secrets.ANACONDA_ORG_UPLOAD_TOKEN }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # hatch-vcs 2 | src/uproot/version.py 3 | 4 | # Sphinx documentation 5 | docs-sphinx/_build 6 | docs-sphinx/changelog.rst 7 | docs-sphinx/uproot.*rst 8 | docs-sphinx/*.toctree 9 | 10 | # Byte-compiled / optimized / DLL files 11 | __pycache__/ 12 | *.py[cod] 13 | *$py.class 14 | 15 | # C extensions 16 | *.so 17 | 18 | # Distribution / packaging 19 | .Python 20 | build/ 21 | develop-eggs/ 22 | dist/ 23 | downloads/ 24 | eggs/ 25 | .eggs/ 26 | lib/ 27 | lib64/ 28 | parts/ 29 | sdist/ 30 | var/ 31 | wheels/ 32 | pip-wheel-metadata/ 33 | share/python-wheels/ 34 | *.egg-info/ 35 | .installed.cfg 36 | *.egg 37 | MANIFEST 38 | 39 | # PyInstaller 40 | # Usually these files are written by a python script from a template 41 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 42 | *.manifest 43 | *.spec 44 | 45 | # Installer logs 46 | pip-log.txt 47 | pip-delete-this-directory.txt 48 | 49 | # Unit test / coverage reports 50 | htmlcov/ 51 | .tox/ 52 | .nox/ 53 | .coverage 54 | .coverage.* 55 | .cache 56 | nosetests.xml 57 | coverage.xml 58 | *.cover 59 | *.py,cover 60 | .hypothesis/ 61 | .pytest_cache/ 62 | 63 | # Translations 64 | *.mo 65 | *.pot 66 | 67 | # Django stuff: 68 | *.log 69 | local_settings.py 70 | db.sqlite3 71 | db.sqlite3-journal 72 | 73 | # Flask stuff: 74 | instance/ 75 | .webassets-cache 76 | 77 | # Scrapy stuff: 78 | .scrapy 79 | 80 | # Sphinx documentation 81 | docs/_build/ 82 | 83 | # PyBuilder 84 | target/ 85 | 86 | # Jupyter Notebook 87 | .ipynb_checkpoints 88 | 89 | # IPython 90 | profile_default/ 91 | ipython_config.py 92 | 93 | # pyenv 94 | .python-version 95 | 96 | # pipenv 97 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 98 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 99 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 100 | # install all needed dependencies. 101 | #Pipfile.lock 102 | 103 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 104 | __pypackages__/ 105 | 106 | # Celery stuff 107 | celerybeat-schedule 108 | celerybeat.pid 109 | 110 | # SageMath parsed files 111 | *.sage.py 112 | 113 | # Environments 114 | .env 115 | .venv 116 | env/ 117 | venv/ 118 | ENV/ 119 | env.bak/ 120 | venv.bak/ 121 | 122 | # Spyder project settings 123 | .spyderproject 124 | .spyproject 125 | 126 | # Rope project settings 127 | .ropeproject 128 | 129 | # mkdocs documentation 130 | /site 131 | 132 | # mypy 133 | .mypy_cache/ 134 | .dmypy.json 135 | dmypy.json 136 | 137 | # Pyre type checker 138 | .pyre/ 139 | 140 | # Local copies of skhep_testdata files 141 | skhep_testdata/ 142 | 143 | # Pyodide 144 | .pyodide* 145 | dist-pyodide/ 146 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | ci: 2 | autoupdate_commit_msg: 'chore: update pre-commit hooks' 3 | autofix_commit_msg: 'style: pre-commit fixes' 4 | autoupdate_schedule: monthly 5 | 6 | repos: 7 | - repo: https://github.com/pre-commit/pre-commit-hooks 8 | rev: v5.0.0 9 | hooks: 10 | - id: check-added-large-files 11 | - id: check-case-conflict 12 | - id: check-merge-conflict 13 | - id: check-symlinks 14 | - id: check-yaml 15 | - id: debug-statements 16 | - id: end-of-file-fixer 17 | - id: mixed-line-ending 18 | - id: requirements-txt-fixer 19 | - id: trailing-whitespace 20 | 21 | - repo: https://github.com/psf/black-pre-commit-mirror 22 | rev: 25.1.0 23 | hooks: 24 | - id: black 25 | 26 | - repo: https://github.com/astral-sh/ruff-pre-commit 27 | rev: v0.11.12 28 | hooks: 29 | - id: ruff 30 | args: [--fix, --show-fixes] 31 | 32 | 33 | - repo: https://github.com/asottile/pyupgrade 34 | rev: v3.20.0 35 | hooks: 36 | - id: pyupgrade 37 | args: [--py38-plus] 38 | 39 | - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks 40 | rev: v2.14.0 41 | hooks: 42 | - id: pretty-format-toml 43 | args: [--autofix] 44 | - id: pretty-format-yaml 45 | args: [--autofix, --indent, '2', --offset, '2'] 46 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | configuration: docs-sphinx/conf.py 5 | 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: '3.9' 10 | 11 | python: 12 | install: 13 | - requirements: docs-sphinx/requirements.txt 14 | - method: pip 15 | path: . 16 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: "Uproot" 3 | message: "If you use this software, please cite it as below." 4 | doi: "10.5281/zenodo.4340632" 5 | date-released: "2017-09-13" 6 | authors: 7 | - family-names: "Pivarski" 8 | given-names: "Jim" 9 | affiliation: "Princeton University" 10 | orcid: "https://orcid.org/0000-0002-6649-343X" 11 | email: "jpivarski@gmail.com" 12 | - family-names: "Schreiner" 13 | given-names: "Henry" 14 | affiliation: "Princeton University" 15 | orcid: "https://orcid.org/0000-0002-7833-783X" 16 | email: "henryfs@princeton.edu" 17 | - family-names: "Hollands" 18 | given-names: "Angus" 19 | affiliation: "University of Birmingham" 20 | orcid: "https://orcid.org/0000-0003-0788-3814" 21 | email: "goosey15@gmail.com" 22 | - family-names: "Das" 23 | given-names: "Pratyush" 24 | affiliation: "Purdue University" 25 | orcid: "https://orcid.org/0000-0001-8140-0097" 26 | email: "reikdas@gmail.com" 27 | - family-names: "Kothari" 28 | given-names: "Kush" 29 | affiliation: "Veermata Jijabai Technological Institute" 30 | orcid: "https://orcid.org/0000-0001-8593-722X" 31 | email: "kushkothari2001@gmail.com" 32 | - family-names: "Roy" 33 | given-names: "Aryan" 34 | affiliation: "Manipal Institute of Technology" 35 | orcid: "https://orcid.org/0000-0001-5220-8725" 36 | email: "aryanroy5678@gmail.com" 37 | - family-names: "Ling" 38 | given-names: "Jerry" 39 | affiliation: "Harvard University" 40 | orcid: "https://orcid.org/0000-0002-3359-0380" 41 | email: "jling@g.harvard.edu" 42 | - family-names: "Smith" 43 | given-names: "Nicholas" 44 | affiliation: "Fermilab" 45 | orcid: "https://orcid.org/0000-0002-0324-3054" 46 | email: "nick.smith@cern.ch" 47 | - family-names: "Burr" 48 | given-names: "Chris" 49 | affiliation: "CERN" 50 | orcid: "https://orcid.org/0000-0002-5155-1094" 51 | email: "christopher.burr@cern.ch" 52 | - family-names: "Stark" 53 | given-names: "Giordon" 54 | affiliation: "Santa Cruz Institute for Particle Physics" 55 | orcid: "https://orcid.org/0000-0001-6616-3433" 56 | email: "gstark@cern.ch" 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Scikit-HEP Project 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /docs-img/diagrams/abstraction-layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/diagrams/abstraction-layers.png -------------------------------------------------------------------------------- /docs-img/diagrams/example-dask-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/diagrams/example-dask-graph.png -------------------------------------------------------------------------------- /docs-img/diagrams/uproot-awkward-timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/diagrams/uproot-awkward-timeline.png -------------------------------------------------------------------------------- /docs-img/logo/logo-300px-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/logo/logo-300px-white.png -------------------------------------------------------------------------------- /docs-img/logo/logo-300px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/logo/logo-300px.png -------------------------------------------------------------------------------- /docs-img/logo/logo-600px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/logo/logo-600px.png -------------------------------------------------------------------------------- /docs-img/photos/switcheroo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/docs-img/photos/switcheroo.jpg -------------------------------------------------------------------------------- /docs-sphinx/_templates/breadcrumbs.html: -------------------------------------------------------------------------------- 1 | {%- extends "sphinx_rtd_theme/breadcrumbs.html" %} 2 | 3 | {% block breadcrumbs_aside %} 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /docs-sphinx/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath(".")) 16 | 17 | # -- Project information ----------------------------------------------------- 18 | 19 | project = "Uproot" 20 | copyright = "2017-2021, Jim Pivarski" 21 | author = "Jim Pivarski" 22 | 23 | # -- General configuration --------------------------------------------------- 24 | 25 | # Add any Sphinx extension module names here, as strings. They can be 26 | # extensions coming with Sphinx (named "sphinx.ext.*") or your custom 27 | # ones. 28 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon"] 29 | 30 | # Add any paths that contain templates here, relative to this directory. 31 | templates_path = ["_templates"] 32 | 33 | # List of patterns, relative to source directory, that match files and 34 | # directories to ignore when looking for source files. 35 | # This pattern also affects html_static_path and html_extra_path. 36 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 37 | 38 | # -- Options for HTML output ------------------------------------------------- 39 | 40 | # The theme to use for HTML and HTML Help pages. See the documentation for 41 | # a list of builtin themes. 42 | # 43 | html_theme = "sphinx_rtd_theme" 44 | html_logo = "../docs-img/logo/logo-300px-white.png" 45 | html_show_sourcelink = False 46 | html_theme_options = {"logo_only": True, "sticky_navigation": False} 47 | 48 | # Add any paths that contain custom static files (such as style sheets) here, 49 | # relative to this directory. They are copied after the builtin static files, 50 | # so a file named "default.css" will overwrite the builtin "default.css". 51 | html_static_path = [] # "_static" 52 | 53 | # Additional stuff 54 | master_doc = "index" 55 | 56 | exec(open("prepare_docstrings.py").read(), dict(globals())) 57 | exec(open("make_changelog.py").read(), dict(globals())) 58 | -------------------------------------------------------------------------------- /docs-sphinx/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx>=2.4.4 2 | sphinx-rtd-theme 3 | -------------------------------------------------------------------------------- /src/uproot/behaviors/TBranchElement.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the behaviors of ``TBranchElement``, which is entirely inherited from 5 | functions in :doc:`uproot.behaviors.TBranch.TBranch`. 6 | """ 7 | from __future__ import annotations 8 | 9 | import uproot 10 | 11 | 12 | class TBranchElement(uproot.behaviors.TBranch.TBranch): 13 | """ 14 | Behaviors for a ``TBranchElement``, which mostly consist of array-reading 15 | methods. 16 | 17 | Since a :doc:`uproot.behaviors.TBranchElement.TBranchElement` is a 18 | :doc:`uproot.behaviors.TBranch.HasBranches`, it is also a Python 19 | ``Mapping``, which uses square bracket syntax to extract subbranches: 20 | 21 | .. code-block:: python 22 | 23 | my_branchelement["subbranch"] 24 | my_branchelement["subbranch"]["subsubbranch"] 25 | my_branchelement["subbranch/subsubbranch"] 26 | """ 27 | -------------------------------------------------------------------------------- /src/uproot/behaviors/TDatime.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the behaviors of ``TDatime``. 5 | """ 6 | from __future__ import annotations 7 | 8 | import uproot 9 | 10 | 11 | class TDatime: 12 | """ 13 | Behaviors for TDatime: return values as py:class:`datetime.datetime` 14 | """ 15 | 16 | def to_datetime(self): 17 | return uproot._util.code_to_datetime(self._members["fDatime"]) 18 | -------------------------------------------------------------------------------- /src/uproot/behaviors/TGraph.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the behaviors of ``TGraph``. 5 | """ 6 | from __future__ import annotations 7 | 8 | import numpy 9 | 10 | 11 | class TGraph: 12 | """ 13 | Behaviors for TGraph: return values as a NumPy array 14 | """ 15 | 16 | # This is really just the `values` portion of TGraphAsymmErrors 17 | 18 | def _normalize_array(self, key): 19 | values = self.member(key) 20 | return numpy.asarray(values, dtype=values.dtype.newbyteorder("=")) 21 | 22 | def values(self, axis="both"): 23 | """ 24 | Args: 25 | axis (int or str): If ``0``, ``-2``, or ``"x"``, get the *x* axis. 26 | If ``1``, ``-1``, or ``"y"``, get the *y* axis. If ``"both"``, 27 | get ``"x"`` and ``"y"`` axes as a 2-tuple. 28 | 29 | Returns the values of all points in the scatter plot, either as a 30 | 1-dimensional NumPy array (if ``axis`` selects only one) or as a 2-tuple 31 | (if ``axis="both"``). 32 | """ 33 | if axis in [0, -2, "x"]: 34 | return self._normalize_array("fX") 35 | elif axis in [1, -1, "y"]: 36 | return self._normalize_array("fY") 37 | elif axis == "both": 38 | return (self.values("x"), self.values("y")) 39 | else: 40 | raise ValueError( 41 | "axis must be 0 (-2, 'x'), 1 (-1, 'y'), or 'both' for a TGraph" 42 | ) 43 | -------------------------------------------------------------------------------- /src/uproot/behaviors/TGraphErrors.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the behaviors of ``TGraphErrors``. 5 | """ 6 | from __future__ import annotations 7 | 8 | 9 | class TGraphErrors: 10 | """ 11 | Behaviors for TGraphErrors: get values and errors as NumPy arrays. 12 | """ 13 | 14 | # TO DO! 15 | -------------------------------------------------------------------------------- /src/uproot/behaviors/TH2Poly.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the behavior of ``TH2Poly``. 5 | """ 6 | from __future__ import annotations 7 | 8 | import uproot 9 | 10 | 11 | class TH2Poly(uproot.behaviors.TH1.Histogram): 12 | """ 13 | Behaviors for two-dimensional polygon histograms: ROOT's ``TH2Poly``. 14 | """ 15 | 16 | no_inherit = (uproot.behaviors.TH2.TH2,) 17 | 18 | @property 19 | def axes(self): 20 | return (self.member("fXaxis"), self.member("fYaxis")) 21 | 22 | def axis(self, axis): 23 | if axis == 0 or axis == -2 or axis == "x": 24 | return self.member("fXaxis") 25 | elif axis == 1 or axis == -1 or axis == "y": 26 | return self.member("fYaxis") 27 | else: 28 | raise ValueError("axis must be 0 (-2), 1 (-1) or 'x', 'y' for a TH2") 29 | -------------------------------------------------------------------------------- /src/uproot/behaviors/TParameter.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the behavior of ``TParameter``. 5 | """ 6 | from __future__ import annotations 7 | 8 | 9 | class TParameter_3c_boolean_3e_: 10 | """ 11 | Behaviors for ``TParameter``. 12 | """ 13 | 14 | @property 15 | def value(self): 16 | return bool(self.member("fVal")) 17 | 18 | def __bool__(self): 19 | return bool(self.member("fVal")) 20 | 21 | def __int__(self): 22 | return int(self.member("fVal")) 23 | 24 | def __float__(self): 25 | return float(self.member("fVal")) 26 | 27 | 28 | class TParameter_3c_integer_3e_: 29 | """ 30 | Behaviors for ``TParameter``. 31 | """ 32 | 33 | @property 34 | def value(self): 35 | return int(self.member("fVal")) 36 | 37 | def __bool__(self): 38 | return bool(self.member("fVal")) 39 | 40 | def __int__(self): 41 | return int(self.member("fVal")) 42 | 43 | def __index__(self): 44 | return int(self.member("fVal")) 45 | 46 | def __float__(self): 47 | return float(self.member("fVal")) 48 | 49 | 50 | class TParameter_3c_floating_3e_: 51 | """ 52 | Behaviors for ``TParameter``. 53 | """ 54 | 55 | @property 56 | def value(self): 57 | return float(self.member("fVal")) 58 | 59 | def __bool__(self): 60 | return bool(self.member("fVal")) 61 | 62 | def __int__(self): 63 | return int(self.member("fVal")) 64 | 65 | def __float__(self): 66 | return float(self.member("fVal")) 67 | 68 | 69 | def TParameter(specialization): 70 | """ 71 | Returns a Parameter class object for a given ``specialization``. 72 | """ 73 | if specialization in ("_3c_bool_3e_", "_3c_Bool_5f_t_3e_"): 74 | return TParameter_3c_boolean_3e_ 75 | elif specialization in ( 76 | "_3c_float_3e_", 77 | "_3c_double_3e_", 78 | "_3c_long_20_double_3e_", 79 | "_3c_Float_5f_t_3e_", 80 | "_3c_Double_5f_t_3e_", 81 | "_3c_LongDouble_5f_t_3e_", 82 | ): 83 | return TParameter_3c_floating_3e_ 84 | else: 85 | return TParameter_3c_integer_3e_ 86 | -------------------------------------------------------------------------------- /src/uproot/behaviors/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines behaviors, which are mix-in classes that provide a high-level interface 5 | to objects read from ROOT files. 6 | 7 | Behaviors do not have a required base class, and they may be used with 8 | Awkward Array's ``ak.behavior``. 9 | 10 | To add a behavior for a ROOT class: 11 | 12 | 1. Translate the ROOT class name from C++ to Python with 13 | :doc:`uproot.model.classname_encode`. For example, 14 | ``"ROOT::RThing"`` becomes ``"Model_ROOT_3a3a_RThing"``. 15 | 2. Create a submodule of ``uproot.behaviors`` without 16 | the ``"Model_"`` prefix. For example, ``"ROOT_3a3a_RThing"``. 17 | 3. Include a class in that submodule with the fully encoded 18 | name. For example, ``"Model_ROOT_3a3a_RThing"``. 19 | 20 | When Uproot reads an instance of the class, it would always create a 21 | deserialization model if one is not predefined. But if a behavior with the 22 | appropriate name exist, the new class will inherit from the behavior, giving 23 | the newly created object specialized methods and properties. 24 | 25 | See also :doc:`uproot.models`. 26 | """ 27 | -------------------------------------------------------------------------------- /src/uproot/dynamic.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module is initially empty, a repository for dynamically adding new classes. 5 | 6 | The purpose of this namespace is to allow :doc:`uproot.model.VersionedModel` 7 | classes that were automatically generated from ROOT ``TStreamerInfo`` to be 8 | pickled, with the help of :doc:`uproot.model.DynamicModel`. 9 | 10 | In `Python 3.7 and later `__, attempts 11 | to extract items from this namespace generate new :doc:`uproot.model.DynamicModel` 12 | classes, which are used as a container in which data from pickled 13 | :doc:`uproot.model.VersionedModel` instances are filled. 14 | """ 15 | from __future__ import annotations 16 | 17 | 18 | def __getattr__(name): 19 | import uproot 20 | 21 | g = globals() 22 | if name not in g: 23 | g[name] = uproot._util.new_class(name, (uproot.model.DynamicModel,), {}) 24 | 25 | return g[name] 26 | -------------------------------------------------------------------------------- /src/uproot/exceptions.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines Uproot-specific exceptions, such as 5 | :doc:`uproot.exceptions.KeyInFileError`. 6 | """ 7 | from __future__ import annotations 8 | 9 | import uproot 10 | 11 | 12 | class NameConflictWarning(Warning): 13 | pass 14 | 15 | 16 | class KeyInFileError(KeyError): 17 | """ 18 | Exception raised by attempts to find ROOT objects in ``TDirectories`` 19 | or ``TBranches`` in :doc:`uproot.behaviors.TBranch.HasBranches`, which 20 | both have a Python ``Mapping`` interface (square bracket syntax to extract 21 | items). 22 | 23 | This exception descends from Python's ``KeyError``, so it can be used in 24 | the normal way by interfaces that expect a missing item in a ``Mapping`` 25 | to raise ``KeyError``, but it provides more information, depending on 26 | availability: 27 | 28 | * ``because``: an explanatory message 29 | * ``cycle``: the ROOT cycle number requested, if any 30 | * ``keys``: a list or partial list of keys that *are* in the object, in case 31 | of misspelling 32 | * ``file_path``: a path (or URL) to the file 33 | * ``object_path``: a path to the object within the ROOT file. 34 | """ 35 | 36 | def __init__( 37 | self, key, because="", cycle=None, keys=None, file_path=None, object_path=None 38 | ): 39 | super().__init__(key) 40 | self.key = key 41 | self.because = because 42 | self.cycle = cycle 43 | self.keys = keys 44 | self.file_path = file_path 45 | self.object_path = object_path 46 | 47 | def __str__(self): 48 | because = "" if self.because == "" else " because " + self.because 49 | 50 | with_keys = "" 51 | if self.keys is not None: 52 | to_show = None 53 | keys = self.keys 54 | cut = 1 55 | while len(keys) > 1000 and cut < len(self.key): 56 | keys = [x for x in keys if x[:cut] == self.key[:cut]] 57 | cut += 1 58 | sorted_keys = sorted( 59 | keys, key=lambda x: uproot._util.damerau_levenshtein(self.key, x) 60 | ) 61 | for key in sorted_keys: 62 | if to_show is None: 63 | to_show = repr(key) 64 | else: 65 | to_show += ", " + repr(key) 66 | if len(to_show) > 200: 67 | to_show += "..." 68 | break 69 | if to_show is None: 70 | to_show = "(none!)" 71 | with_keys = f"\n\n Available keys: {to_show}\n" 72 | 73 | in_file = "" 74 | if self.file_path is not None: 75 | in_file = f"\nin file {self.file_path}" 76 | 77 | in_object = "" 78 | if self.object_path is not None: 79 | in_object = f"\nin object {self.object_path}" 80 | 81 | if self.cycle == "any": 82 | return f"not found: {self.key!r} (with any cycle number){because}{with_keys}{in_file}{in_object}" 83 | elif self.cycle is None: 84 | return f"not found: {self.key!r}{because}{with_keys}{in_file}{in_object}" 85 | else: 86 | return f"not found: {self.key!r} with cycle {self.cycle}{because}{with_keys}{in_file}{in_object}" 87 | -------------------------------------------------------------------------------- /src/uproot/interpretation/known_forth/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module provides known forth code and awkward forms for types where it is known a priori. 5 | 6 | See :doc:`uproot.interpretation.known_forth.known_forth_of` for the function 7 | that provides the lookup of known forth codes and :doc:`uproot.interpretation.known_forth.atlas.VectorVectorElementLink` for an 8 | implementation used in ATLAS (D)AODs. 9 | """ 10 | from __future__ import annotations 11 | 12 | import uproot 13 | from uproot.interpretation.known_forth.atlas import VectorVectorElementLink 14 | 15 | KNOWN_FORTH_DICT = { 16 | "std::vector>>>": VectorVectorElementLink, 17 | "std::vector>>>": VectorVectorElementLink, 18 | "std::vector>>>": VectorVectorElementLink, 19 | "std::vector>>>": VectorVectorElementLink, 20 | "std::vector>>>": VectorVectorElementLink, 21 | "std::vector>>>": VectorVectorElementLink, 22 | "std::vector>>>": VectorVectorElementLink, 23 | "std::vector>>>": VectorVectorElementLink, 24 | } 25 | 26 | 27 | def known_forth_of(model): 28 | """ 29 | Args: 30 | model: The :doc:`uproot.model.Model` to look up known forth for 31 | 32 | Returns an object with attributes `forth_code` and `awkward_form` if a known 33 | special case exists, else None 34 | """ 35 | try: 36 | typename = model.typename 37 | except AttributeError: 38 | try: 39 | typename = model.classname 40 | except AttributeError: 41 | typename = uproot.model.classname_decode(model.__name__) 42 | 43 | if typename not in KNOWN_FORTH_DICT: 44 | return 45 | 46 | return KNOWN_FORTH_DICT[typename](typename) 47 | -------------------------------------------------------------------------------- /src/uproot/language/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines languages for expressions passed to 5 | :ref:`uproot.behaviors.TBranch.HasBranches.arrays` (and similar). 6 | 7 | The default is :doc:`uproot.language.python.PythonLanguage`. 8 | 9 | All languages must be subclasses of :doc:`uproot.language.Language`. 10 | """ 11 | from __future__ import annotations 12 | 13 | 14 | class Language: 15 | """ 16 | Abstract class for all languages, which are used to compute the expressions 17 | that are passed to :ref:`uproot.behaviors.TBranch.HasBranches.arrays` (and 18 | similar). 19 | 20 | The default is :doc:`uproot.language.python.PythonLanguage`. 21 | """ 22 | -------------------------------------------------------------------------------- /src/uproot/models/TClonesArray.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines a versionless model for ``TClonesArray``. 5 | """ 6 | from __future__ import annotations 7 | 8 | from collections.abc import Sequence 9 | 10 | import uproot.models.TObjArray 11 | 12 | 13 | class Model_TClonesArray(uproot.model.VersionedModel, Sequence): 14 | """ 15 | A versionless :doc:`uproot.model.Model` for ``TObjArray``. 16 | 17 | This also satisfies Python's abstract ``Sequence`` protocol. 18 | """ 19 | 20 | def read_members(self, chunk, cursor, context, file): 21 | if uproot._awkwardforth.get_forth_obj(context) is not None: 22 | raise uproot.interpretation.objects.CannotBeForth() 23 | if self.is_memberwise: 24 | raise NotImplementedError( 25 | f"memberwise serialization of {type(self).__name__}\nin file {self.file.file_path}" 26 | ) 27 | 28 | self._bases.append( 29 | uproot.models.TObject.Model_TObject.read( 30 | chunk, 31 | cursor, 32 | context, 33 | file, 34 | self._file, 35 | self._parent, 36 | concrete=self.concrete, 37 | ) 38 | ) 39 | 40 | self._members["fName"] = cursor.string(chunk, context) 41 | 42 | classname_and_version = cursor.string(chunk, context) 43 | try: 44 | i = classname_and_version.index(";") 45 | except ValueError: 46 | self._item_classname = classname_and_version 47 | self._item_classversion = "max" 48 | else: 49 | self._item_classname = classname_and_version[:i] 50 | self._item_classversion = int(classname_and_version[i + 1 :]) 51 | 52 | self._members["fClass"] = cls = file.class_named( 53 | self._item_classname, self._item_classversion 54 | ) 55 | 56 | self._members["fSize"], self._members["fLowerBound"] = cursor.fields( 57 | chunk, uproot.models.TObjArray._tobjarray_format1, context 58 | ) 59 | 60 | self._data = [] 61 | for _ in range(self._members["fSize"]): 62 | if cursor.byte(chunk, context) != 0: 63 | self._data.append( 64 | cls.read(chunk, cursor, context, file, self._file, self._parent) 65 | ) 66 | 67 | @property 68 | def item_classname(self): 69 | return self._item_classname 70 | 71 | @property 72 | def item_classversion(self): 73 | return self._item_classversion 74 | 75 | @property 76 | def item_class(self): 77 | return self._members["fClass"] 78 | 79 | def __getitem__(self, where): 80 | return self._data[where] 81 | 82 | def __len__(self): 83 | return len(self._data) 84 | 85 | base_names_versions = [("TObjArray", 3)] 86 | member_names = [] 87 | class_flags = {} 88 | 89 | 90 | uproot.classes["TClonesArray"] = Model_TClonesArray 91 | -------------------------------------------------------------------------------- /src/uproot/models/TDatime.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines versioned models for ``TDatime``. 5 | """ 6 | from __future__ import annotations 7 | 8 | import struct 9 | 10 | import numpy 11 | 12 | import uproot 13 | import uproot.behaviors.TDatime 14 | 15 | _tdatime_format1 = struct.Struct(">I") 16 | 17 | 18 | class Model_TDatime(uproot.behaviors.TDatime.TDatime, uproot.model.Model): 19 | """ 20 | A versionless :doc:`uproot.model.Model` for ``TDatime``. 21 | """ 22 | 23 | def read_numbytes_version(self, chunk, cursor, context): 24 | pass 25 | 26 | def read_members(self, chunk, cursor, context, file): 27 | forth_obj = uproot._awkwardforth.get_forth_obj(context) 28 | if forth_obj is not None: 29 | key = uproot._awkwardforth.get_first_key_number(context) 30 | forth_stash = uproot._awkwardforth.Node( 31 | f"node{key} TDatime :prebuilt", 32 | form_details={ 33 | "class": "RecordArray", 34 | "contents": { 35 | "fDatime": { 36 | "class": "NumpyArray", 37 | "primitive": "uint32", 38 | "form_key": f"node{key}", 39 | } 40 | }, 41 | "parameters": {"__record__": "TDatime"}, 42 | }, 43 | ) 44 | forth_stash.header_code.append(f"output node{key}-data int32\n") 45 | forth_stash.pre_code.append(f"stream !I-> node{key}-data\n") 46 | forth_obj.add_node(forth_stash) 47 | forth_obj.set_active_node(forth_stash) 48 | self._members["fDatime"] = cursor.field(chunk, _tdatime_format1, context) 49 | 50 | @classmethod 51 | def strided_interpretation( 52 | cls, file, header=False, tobject_header=True, breadcrumbs=(), original=None 53 | ): 54 | members = [(None, None)] 55 | if header: 56 | members.append(("@num_bytes", numpy.dtype(">u4"))) 57 | members.append(("@instance_version", numpy.dtype(">u2"))) 58 | members.append(("fDatime", numpy.dtype(">u4"))) 59 | return uproot.interpretation.objects.AsStridedObjects( 60 | cls, members, original=original 61 | ) 62 | 63 | @classmethod 64 | def awkward_form(cls, file, context): 65 | awkward = uproot.extras.awkward() 66 | contents = {} 67 | if context["header"]: 68 | contents["@num_bytes"] = uproot._util.awkward_form( 69 | numpy.dtype("u4"), file, context 70 | ) 71 | contents["@instance_version"] = uproot._util.awkward_form( 72 | numpy.dtype("u2"), file, context 73 | ) 74 | contents["fDatime"] = uproot._util.awkward_form( 75 | numpy.dtype(">u4"), file, context 76 | ) 77 | return awkward.forms.RecordForm( 78 | list(contents.values()), 79 | list(contents.keys()), 80 | parameters={"__record__": "TDatime"}, 81 | ) 82 | 83 | base_names_versions = [] 84 | member_names = ["fDatime"] 85 | class_flags = {} 86 | class_code = None 87 | 88 | 89 | uproot.classes["TDatime"] = Model_TDatime 90 | -------------------------------------------------------------------------------- /src/uproot/models/THashList.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines a versionless model for ``THashList``. 5 | """ 6 | from __future__ import annotations 7 | 8 | import uproot 9 | 10 | 11 | class Model_THashList(uproot.model.Model): 12 | """ 13 | A versionless :doc:`uproot.model.Model` for ``THashList``. 14 | """ 15 | 16 | def read_numbytes_version(self, chunk, cursor, context): 17 | pass 18 | 19 | def read_members(self, chunk, cursor, context, file): 20 | if uproot._awkwardforth.get_forth_obj(context) is not None: 21 | raise uproot.interpretation.objects.CannotBeForth() 22 | if self.is_memberwise: 23 | raise NotImplementedError( 24 | f"""memberwise serialization of {type(self).__name__} 25 | in file {self.file.file_path}""" 26 | ) 27 | self._bases.append( 28 | uproot.models.TList.Model_TList.read( 29 | chunk, 30 | cursor, 31 | context, 32 | file, 33 | self._file, 34 | self._parent, 35 | concrete=self.concrete, 36 | ) 37 | ) 38 | 39 | def __repr__(self): 40 | if self.class_version is None: 41 | version = "" 42 | else: 43 | version = f" (version {self.class_version})" 44 | return f"<{self.classname}{version} of {len(self)} items at 0x{id(self):012x}>" 45 | 46 | def __getitem__(self, where): 47 | return self._bases[0][where] 48 | 49 | def __len__(self): 50 | return len(self._bases[0]) 51 | 52 | writable = True 53 | 54 | def _serialize(self, out, header, name, tobject_flags): 55 | assert len(self._bases) == 1, "Fatal error on THashList serialization." 56 | for x in self._bases: 57 | x._serialize(out, True, None, tobject_flags) 58 | 59 | 60 | uproot.classes["THashList"] = Model_THashList 61 | -------------------------------------------------------------------------------- /src/uproot/models/TMatrixT.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines versioned models for ``TLeaf`` and its subclasses. 5 | """ 6 | from __future__ import annotations 7 | 8 | import struct 9 | 10 | import numpy 11 | 12 | import uproot 13 | import uproot._util 14 | import uproot.model 15 | 16 | 17 | class Model_TMatrixTSym_3c_double_3e__v5(uproot.model.VersionedModel): 18 | """ 19 | A :doc:`uproot.model.VersionedModel` for ``TMatrixTSym`` version 2, 20 | which shows up as version 5 because it's reading the ``TMatrixTBase`` 21 | header. 22 | """ 23 | 24 | def read_members(self, chunk, cursor, context, file): 25 | if uproot._awkwardforth.get_forth_obj(context) is not None: 26 | raise uproot.interpretation.objects.CannotBeForth() 27 | if self.is_memberwise: 28 | raise NotImplementedError( 29 | f"memberwise serialization of {type(self).__name__}\nin file {self.file.file_path}" 30 | ) 31 | self._bases.append( 32 | file.class_named("TObject", 1).read( 33 | chunk, 34 | cursor, 35 | context, 36 | file, 37 | self._file, 38 | self._parent, 39 | concrete=self.concrete, 40 | ) 41 | ) 42 | ( 43 | self._members["fNrows"], 44 | self._members["fNcols"], 45 | self._members["fRowLwb"], 46 | self._members["fColLwb"], 47 | self._members["fNelems"], 48 | self._members["fNrowIndex"], 49 | self._members["fTol"], 50 | ) = cursor.fields(chunk, self._format0, context) 51 | 52 | num_elements = self.member("fNrows") * (self.member("fNcols") + 1) // 2 53 | self._members["fElements"] = cursor.array( 54 | chunk, num_elements, self._dtype0, context 55 | ) 56 | self._num_bytes += self._members["fElements"].nbytes 57 | 58 | _format0 = struct.Struct(">iiiiiid") 59 | _format_memberwise0 = struct.Struct(">i") 60 | _format_memberwise1 = struct.Struct(">i") 61 | _format_memberwise2 = struct.Struct(">i") 62 | _format_memberwise3 = struct.Struct(">i") 63 | _format_memberwise4 = struct.Struct(">i") 64 | _format_memberwise5 = struct.Struct(">i") 65 | _format_memberwise6 = struct.Struct(">d") 66 | _dtype0 = numpy.dtype(">f8") 67 | base_names_versions = [("TObject", 1)] 68 | member_names = [ 69 | "fNrows", 70 | "fNcols", 71 | "fRowLwb", 72 | "fColLwb", 73 | "fNelems", 74 | "fNrowIndex", 75 | "fTol", 76 | ] 77 | class_flags = {} 78 | 79 | 80 | class Model_TMatrixTSym_3c_double_3e_(uproot.model.DispatchByVersion): 81 | """ 82 | A :doc:`uproot.model.DispatchByVersion` for ``TMatrixTSym``. 83 | """ 84 | 85 | known_versions = {5: Model_TMatrixTSym_3c_double_3e__v5} 86 | 87 | 88 | uproot.classes["TMatrixTSym"] = Model_TMatrixTSym_3c_double_3e_ 89 | -------------------------------------------------------------------------------- /src/uproot/models/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines models, which are classes of objects read from ROOT files. 5 | 6 | Models must be subclasses of :doc:`uproot.model.Model`, and models for a 7 | specific version of a ROOT class must be subclasses of 8 | :doc:`uproot.model.VersionedModel`. 9 | 10 | If a C++ class has no associated model, a new model class will be generated 11 | from the ROOT file's ``TStreamerInfo``. 12 | 13 | To add a versionless model for a ROOT class: 14 | 15 | 1. Translate the ROOT class name from C++ to Python with 16 | :doc:`uproot.model.classname_encode`. For example, 17 | ``"ROOT::RThing"`` becomes ``"Model_ROOT_3a3a_RThing"``. 18 | 2. Define a class with that name. 19 | 3. Explicitly add it to ``uproot.classes``. 20 | 21 | A versionless model is instantiated for any ROOT object with a given class 22 | name, regardless of its version. The deserialization procedure may need to 23 | include version-dependent code. 24 | 25 | To add a versioned model for a ROOT class: 26 | 27 | 1. Translate the ROOT class name from C++ to Python with 28 | :doc:`uproot.model.classname_encode` with a specific ``version``. 29 | For example version ``2`` of ``"ROOT::RThing"`` becomes 30 | ``"Model_ROOT_3a3a_RThing_v2"``. 31 | 2. Define a class with that name. 32 | 3. Explicitly add it to a :doc:`uproot.model.DispatchByVersion` for that 33 | class. You might also need to add a :doc:`uproot.model.DispatchByVersion` 34 | to the ``uproot.classes``. 35 | 36 | A versioned model is only instantiated for a ROOT object with a given class 37 | name and version. Uproot has common versions of :doc:`uproot.models.TBranch` 38 | and :doc:`uproot.models.TTree` predefined so that it can usually avoid reading 39 | a ROOT file's ``TStreamerInfo``. 40 | 41 | High-level methods and properties should not be defined on the model class; 42 | add them as behavior classes. 43 | 44 | See also :doc:`uproot.behaviors`. 45 | """ 46 | -------------------------------------------------------------------------------- /src/uproot/sink/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the "physical layer" of file-writing, which interacts with local 5 | filesystems (and might one day include remote protocols). The "physical layer" 6 | manages only the act of writing and sometimes reading bytes from files. Reading is 7 | sometimes needed so that Uproot can update a preexisting file. 8 | 9 | Unlike reading, writing has no threads and the file sink can be any object with 10 | ``read``, ``write``, ``seek``, ``tell``, and ``flush`` methods. Like reading, a 11 | context manager (Python's ``with`` statement) ensures that files are properly closed 12 | (although files are flushed after every object-write). 13 | """ 14 | -------------------------------------------------------------------------------- /src/uproot/source/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines the "physical layer" of file-reading, which interacts with 5 | local filesystems or remote protocols like HTTP(S), S3 and XRootD. The 6 | "physical layer" is distinguished from "interpretation" in that the meaning of 7 | the bytes that have been read are not relevant in this layer. The 8 | "interpretation layer" interacts with the "physical layer" by requesting a 9 | :doc:`uproot.source.chunk.Chunk` from a :doc:`uproot.source.chunk.Source` and 10 | inspecting it with a :doc:`uproot.source.cursor.Cursor`. 11 | 12 | Any threads used for parallel reading are launched and shut down with the file 13 | handle or handles themselves. Context management (Python's ``with`` statement) 14 | controls both I/O resources and threads. 15 | 16 | This module includes a :doc:`uproot.source.futures` implementation that 17 | connects file handles with threads. 18 | """ 19 | -------------------------------------------------------------------------------- /src/uproot/source/s3.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines a physical layer for remote files, accessed via S3. 5 | """ 6 | 7 | from __future__ import annotations 8 | 9 | import os 10 | from urllib.parse import parse_qsl, urlparse 11 | 12 | import uproot.extras 13 | import uproot.source.http 14 | 15 | 16 | class S3Source(uproot.source.http.HTTPSource): 17 | """ 18 | Args: 19 | file_path (str): A URL of the file to open. 20 | endpoint: S3 endpoint (defaults to AWS) 21 | access_key: Access key of your S3 account 22 | secret_key: Secret key of your S3 account 23 | session_token: Session token of your S3 account 24 | secure: Flag to enable use of TLS 25 | http_client (urllib3.poolmanager.PoolManager): Instance of :doc:`urllib3.poolmanager.PoolManager` 26 | credentials (minio.credentials.Provider): Instance of :doc:`minio.credentials.Provider` 27 | options: See :doc:`uproot.source.http.HTTPSource.__init__` 28 | """ 29 | 30 | def __init__( 31 | self, 32 | file_path: str, 33 | endpoint="s3.amazonaws.com", 34 | access_key=None, 35 | secret_key=None, 36 | session_token=None, 37 | secure=True, 38 | region=None, 39 | http_client=None, 40 | credentials=None, 41 | **options, 42 | ): 43 | Minio = uproot.extras.Minio_client() 44 | 45 | self._file_path = file_path 46 | if access_key is None: 47 | access_key = os.environ.get( 48 | "S3_ACCESS_KEY", os.environ.get("AWS_ACCESS_KEY_ID", None) 49 | ) 50 | if secret_key is None: 51 | secret_key = os.environ.get( 52 | "S3_SECRET_KEY", os.environ.get("AWS_SECRET_ACCESS_KEY", None) 53 | ) 54 | if session_token is None: 55 | session_token = os.environ.get( 56 | "S3_SESSION_TOKEN", os.environ.get("AWS_SESSION_TOKEN", None) 57 | ) 58 | if region is None: 59 | region = os.environ.get("AWS_DEFAULT_REGION", None) 60 | 61 | parsed_url = urlparse(file_path) 62 | 63 | bucket_name = parsed_url.netloc 64 | assert parsed_url.path[0] == "/" 65 | object_name = parsed_url.path[1:] 66 | 67 | parsed_query = dict(parse_qsl(parsed_url.query)) 68 | # There is no standard scheme for s3:// URI query parameters, 69 | # but some are often introduced to support extra flexibility: 70 | if "endpoint" in parsed_query: 71 | endpoint = parsed_query["endpoint"] 72 | if "region" in parsed_query: 73 | region = parsed_query["region"] 74 | 75 | client = Minio( 76 | endpoint, 77 | access_key=access_key, 78 | secret_key=secret_key, 79 | session_token=session_token, 80 | secure=secure, 81 | region=region, 82 | http_client=http_client, 83 | credentials=credentials, 84 | ) 85 | 86 | url = client.get_presigned_url("GET", bucket_name, object_name) 87 | 88 | super().__init__(url, **options) 89 | -------------------------------------------------------------------------------- /src/uproot/writing/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | """ 4 | This module defines all of the classes and functions that are needed for writing ROOT 5 | files. Uproot has a strong asymmetry between reading and writing, with writing defined 6 | as a distinct task. 7 | 8 | The :doc:`uproot.writing.writable` submodule defines the entry-points for user 9 | interaction: :doc:`uproot.writing.writable.create`, :doc:`uproot.writing.writable.recreate`, 10 | and :doc:`uproot.writing.writable.update`. 11 | """ 12 | from __future__ import annotations 13 | 14 | from uproot.writing._dask_write import dask_write 15 | from uproot.writing.identify import ( 16 | to_TArray, 17 | to_TH1x, 18 | to_TH2x, 19 | to_TH3x, 20 | to_TList, 21 | to_TObjString, 22 | to_TProfile, 23 | to_TProfile2D, 24 | to_TProfile3D, 25 | to_writable, 26 | ) 27 | from uproot.writing.writable import ( 28 | WritableBranch, 29 | WritableDirectory, 30 | WritableFile, 31 | WritableTree, 32 | create, 33 | recreate, 34 | update, 35 | ) 36 | 37 | __all__ = [ 38 | "WritableBranch", 39 | "WritableDirectory", 40 | "WritableFile", 41 | "WritableTree", 42 | "create", 43 | "dask_write", 44 | "recreate", 45 | "to_TArray", 46 | "to_TH1x", 47 | "to_TH2x", 48 | "to_TH3x", 49 | "to_TList", 50 | "to_TObjString", 51 | "to_TProfile", 52 | "to_TProfile2D", 53 | "to_TProfile3D", 54 | "to_writable", 55 | "update", 56 | ] 57 | -------------------------------------------------------------------------------- /tests-wasm/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | -------------------------------------------------------------------------------- /tests-wasm/utils.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | from __future__ import annotations 3 | 4 | import os 5 | import pathlib 6 | import shutil 7 | from functools import wraps 8 | 9 | import pytest 10 | import skhep_testdata 11 | 12 | try: 13 | import pytest_pyodide 14 | from pytest_pyodide import run_in_pyodide 15 | from pytest_pyodide.decorator import copy_files_to_pyodide 16 | except ImportError: 17 | pytest.skip("Pyodide is not available", allow_module_level=True) 18 | 19 | # Disable CORS so that we can fetch files for http tests 20 | # Currently, this can only be done for Chrome 21 | selenium_config = pytest_pyodide.config.get_global_config() 22 | selenium_config.set_flags( 23 | "chrome", 24 | [ 25 | *selenium_config.get_flags("chrome"), 26 | "--disable-web-security", 27 | "--disable-site-isolation-trials", 28 | ], 29 | ) 30 | 31 | 32 | # copy skhep_testdata files to testdata directory (needed for @copy_files_to_pyodide) 33 | def ensure_testdata(filename): 34 | if not pathlib.Path("skhep_testdata/" + filename).is_file(): 35 | filepath = skhep_testdata.data_path(filename) 36 | os.makedirs("skhep_testdata", exist_ok=True) 37 | shutil.copyfile(filepath, "skhep_testdata/" + filename) 38 | 39 | 40 | def run_test_in_pyodide(test_file=None, **kwargs): 41 | def decorator(test_func): 42 | @wraps(test_func) 43 | def wrapper(selenium): 44 | if test_file is not None: 45 | ensure_testdata(test_file) 46 | 47 | @copy_files_to_pyodide( 48 | file_list=[("dist", "dist")] 49 | + ( 50 | [] 51 | if test_file is None 52 | else [("skhep_testdata/" + test_file, test_file)] 53 | ), 54 | install_wheels=True, 55 | ) 56 | def inner_func(selenium): 57 | run_in_pyodide(**kwargs)(test_func)(selenium) 58 | 59 | return inner_func(selenium) 60 | 61 | return wrapper 62 | 63 | return decorator 64 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | import shutil 3 | import subprocess 4 | import pytest 5 | import threading 6 | import contextlib 7 | import skhep_testdata 8 | from functools import partial 9 | import os 10 | import time 11 | 12 | # The base http server does not support range requests. Watch https://github.com/python/cpython/issues/86809 for updates 13 | from http.server import HTTPServer 14 | from RangeHTTPServer import RangeRequestHandler 15 | 16 | import uproot 17 | 18 | 19 | @pytest.fixture(scope="function", autouse=False) 20 | def reset_classes(): 21 | uproot.model.reset_classes() 22 | return 23 | 24 | 25 | @contextlib.contextmanager 26 | def serve_http(): 27 | # serve files from the skhep_testdata cache directory. 28 | # This directory is initially empty and files are downloaded on demand 29 | class Handler(RangeRequestHandler): 30 | def _cache_file(self, path: str): 31 | path = path.lstrip("/") 32 | if path in skhep_testdata.known_files: 33 | return skhep_testdata.data_path(path) 34 | else: 35 | raise FileNotFoundError( 36 | f"File '{path}' not available in skhep_testdata" 37 | ) 38 | 39 | def do_HEAD(self): 40 | self._cache_file(self.path) 41 | return super().do_HEAD() 42 | 43 | def do_GET(self): 44 | self._cache_file(self.path) 45 | return super().do_GET() 46 | 47 | server = HTTPServer( 48 | server_address=("localhost", 0), 49 | RequestHandlerClass=partial( 50 | Handler, directory=skhep_testdata.local_files._cache_path() 51 | ), 52 | ) 53 | server.server_activate() 54 | 55 | def serve_forever(httpd=server): 56 | with httpd: 57 | httpd.serve_forever() 58 | 59 | thread = threading.Thread(target=serve_forever, daemon=True) 60 | 61 | try: 62 | thread.start() 63 | address, port = server.server_address 64 | yield f"http://{address}:{port}" 65 | finally: 66 | # stop the server 67 | server.shutdown() 68 | thread.join() 69 | 70 | 71 | @pytest.fixture(scope="module") 72 | def http_server(): 73 | with serve_http() as server_url: 74 | yield server_url 75 | 76 | 77 | @pytest.fixture(scope="module") 78 | def tests_directory() -> str: 79 | return os.path.dirname(os.path.realpath(__file__)) 80 | 81 | 82 | @pytest.fixture(scope="module") 83 | def xrootd_server(tmpdir_factory): 84 | pytest.importorskip("XRootD") 85 | pytest.importorskip("fsspec_xrootd") 86 | 87 | server_dir = tmpdir_factory.mktemp("server") 88 | temp_path = os.path.join(server_dir, "Folder") 89 | os.mkdir(temp_path) 90 | xrootd = shutil.which("xrootd") 91 | proc = subprocess.Popen([xrootd, server_dir]) 92 | time.sleep(2) # give it some startup 93 | yield "root://localhost/" + str(temp_path), temp_path 94 | proc.terminate() 95 | proc.wait(timeout=10) 96 | shutil.rmtree(server_dir) 97 | -------------------------------------------------------------------------------- /tests/samples/h_dynamic.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scikit-hep/uproot5/61835f10456541965ec7fc6ba37ddb07ecb5cfe9/tests/samples/h_dynamic.pkl -------------------------------------------------------------------------------- /tests/test_0008_start_interpretation.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import sys 4 | 5 | import numpy 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | 12 | def tobytes(x): 13 | if hasattr(x, "tobytes"): 14 | return x.tobytes() 15 | else: 16 | return x.tostring() 17 | 18 | 19 | def test_classname_encoding(tmpdir): 20 | assert ( 21 | uproot.model.classname_encode("namespace::some.deep", 12) 22 | == "Model_namespace_3a3a_some_2e_deep_3c_templated_2c20_thing_3e__v12" 23 | ) 24 | assert ( 25 | uproot.model.classname_encode("namespace::some.deep") 26 | == "Model_namespace_3a3a_some_2e_deep_3c_templated_2c20_thing_3e_" 27 | ) 28 | 29 | assert uproot.model.classname_decode( 30 | "Model_namespace_3a3a_some_2e_deep_3c_templated_2c20_thing_3e__v12" 31 | ) == ("namespace::some.deep", 12) 32 | assert uproot.model.classname_decode( 33 | "Model_namespace_3a3a_some_2e_deep_3c_templated_2c20_thing_3e_" 34 | ) == ("namespace::some.deep", None) 35 | 36 | 37 | @pytest.mark.parametrize("use_isal", [False, True]) 38 | def test_file_header(use_isal): 39 | if use_isal: 40 | pytest.importorskip("isal") 41 | uproot.ZLIB.use_isal = use_isal 42 | filename = skhep_testdata.data_path("uproot-Zmumu.root") 43 | file = uproot.reading.ReadOnlyFile(filename) 44 | assert repr(file.compression) == "ZLIB(4)" 45 | assert not file.is_64bit 46 | assert file.fNbytesInfo == 4447 47 | assert file.hex_uuid == "944b77d0-98ab-11e7-a769-0100007fbeef" 48 | 49 | 50 | @pytest.mark.parametrize("use_deflate", [False, True]) 51 | def test_file_header(use_deflate): 52 | if use_deflate: 53 | pytest.importorskip("deflate") 54 | uproot.ZLIB.use_deflate = use_deflate 55 | filename = skhep_testdata.data_path("uproot-Zmumu.root") 56 | file = uproot.reading.ReadOnlyFile(filename) 57 | assert repr(file.compression) == "ZLIB(4)" 58 | assert not file.is_64bit 59 | assert file.fNbytesInfo == 4447 60 | assert file.hex_uuid == "944b77d0-98ab-11e7-a769-0100007fbeef" 61 | -------------------------------------------------------------------------------- /tests/test_0009_nested_directories.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import sys 4 | 5 | import numpy 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | 12 | def test(): 13 | with uproot.open(skhep_testdata.data_path("uproot-nesteddirs.root")) as directory: 14 | assert directory.keys() == [ 15 | "one;1", 16 | "one/two;1", 17 | "one/two/tree;1", 18 | "one/tree;1", 19 | "three;1", 20 | "three/tree;1", 21 | ] 22 | 23 | assert directory.path == () 24 | assert directory["one"].path == ("one",) 25 | assert directory["one/two"].path == ("one", "two") 26 | assert directory["three;1"].path == ("three",) 27 | 28 | assert len(directory) == 6 29 | assert len(directory["one"]) == 3 30 | 31 | assert "one;1/two;1" in directory 32 | 33 | with pytest.raises(KeyError): 34 | directory["whatever"] 35 | 36 | assert directory.get("whatever") is None 37 | -------------------------------------------------------------------------------- /tests/test_0028_fallback_to_read_streamer.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test_fallback_reading(): 11 | with uproot.open( 12 | skhep_testdata.data_path("uproot-small-evnt-tree-fullsplit.root") 13 | ) as f: 14 | f["tree:evt/P3/P3.Py"] 15 | assert f.file._streamers is None 16 | -------------------------------------------------------------------------------- /tests/test_0035_datatype_generality.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test_TH2_in_ttree(): 11 | with uproot.open(skhep_testdata.data_path("uproot-issue-tbranch-of-th2.root"))[ 12 | "g4SimHits/tree" 13 | ] as tree: 14 | assert ( 15 | tree["histogram"].array(library="np")[0].member("fXaxis").member("fName") 16 | == "xaxis" 17 | ) 18 | 19 | 20 | def test_iofeatures_offsets(): 21 | with uproot.open(skhep_testdata.data_path("uproot-small-dy-withoffsets.root"))[ 22 | "tree/Muon_pt" 23 | ] as withoffsets: 24 | muonpt1 = withoffsets.array(library="np", entry_start=10, entry_stop=20) 25 | assert [x.tolist() for x in muonpt1] == [ 26 | [20.60145378112793], 27 | [50.36957550048828, 41.21387481689453, 3.1869382858276367], 28 | [51.685970306396484, 35.227813720703125], 29 | [], 30 | [], 31 | [], 32 | [], 33 | [23.073759078979492], 34 | [32.921417236328125, 8.922308921813965, 4.368383407592773], 35 | [51.9132194519043, 31.930095672607422], 36 | ] 37 | 38 | with uproot.open(skhep_testdata.data_path("uproot-small-dy-nooffsets.root"))[ 39 | "tree/Muon_pt" 40 | ] as nooffsets: 41 | muonpt2 = nooffsets.array(library="np", entry_start=10, entry_stop=20) 42 | assert [x.tolist() for x in muonpt2] == [ 43 | [20.60145378112793], 44 | [50.36957550048828, 41.21387481689453, 3.1869382858276367], 45 | [51.685970306396484, 35.227813720703125], 46 | [], 47 | [], 48 | [], 49 | [], 50 | [23.073759078979492], 51 | [32.921417236328125, 8.922308921813965, 4.368383407592773], 52 | [51.9132194519043, 31.930095672607422], 53 | ] 54 | -------------------------------------------------------------------------------- /tests/test_0038_memberwise_serialization.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_read_efficiency_with_streamer(): 10 | with uproot.open(skhep_testdata.data_path("uproot-issue38c.root")) as fp: 11 | eff = fp["TEfficiencyName"] 12 | assert eff 13 | assert [pair.members for pair in eff.members["fBeta_bin_params"]] == [ 14 | {"first": -1.0, "second": -2.0}, 15 | {"first": 2.0, "second": 4.0}, 16 | {"first": 4.0, "second": 8.0}, 17 | {"first": 8.0, "second": 16.0}, 18 | {"first": 16.0, "second": 32.0}, 19 | {"first": 32.0, "second": 64.0}, 20 | {"first": 64.0, "second": 128.0}, 21 | {"first": 128.0, "second": 256.0}, 22 | {"first": 256.0, "second": 512.0}, 23 | {"first": 512.0, "second": 1024.0}, 24 | {"first": 1024.0, "second": 2048.0}, 25 | {"first": -1.0, "second": -2.0}, 26 | {"first": 1.0, "second": 1.0}, 27 | ] 28 | 29 | 30 | def test_read_efficiency_without_streamer(reset_classes): 31 | with uproot.open(skhep_testdata.data_path("uproot-issue209.root")) as fp: 32 | with pytest.raises(NotImplementedError): 33 | assert fp["TEfficiencyName"] 34 | -------------------------------------------------------------------------------- /tests/test_0044_concatenate_function.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test_concatenate_numpy(): 11 | files = skhep_testdata.data_path("uproot-sample-6.20.04-uncompressed.root").replace( 12 | "6.20.04", "*" 13 | ) 14 | arrays = uproot.concatenate({files: "sample"}, ["i8", "f8"], library="np") 15 | assert len(arrays["i8"]) == 420 16 | assert len(arrays["f8"]) == 420 17 | 18 | 19 | def test_concatenate_awkward(): 20 | awkward = pytest.importorskip("awkward") 21 | files = skhep_testdata.data_path("uproot-sample-6.20.04-uncompressed.root").replace( 22 | "6.20.04", "*" 23 | ) 24 | arrays = uproot.concatenate({files: "sample"}, ["i8", "f8"], library="ak") 25 | assert isinstance(arrays, awkward.Array) 26 | assert set(awkward.fields(arrays)) == {"i8", "f8"} 27 | assert len(arrays) == 420 28 | 29 | 30 | def test_concatenate_pandas(): 31 | pandas = pytest.importorskip("pandas") 32 | files = skhep_testdata.data_path("uproot-sample-6.20.04-uncompressed.root").replace( 33 | "6.20.04", "*" 34 | ) 35 | arrays = uproot.concatenate({files: "sample"}, ["i8", "f8"], library="pd") 36 | assert isinstance(arrays, pandas.DataFrame) 37 | assert set(arrays.columns.tolist()) == {"i8", "f8"} 38 | assert len(arrays) == 420 39 | -------------------------------------------------------------------------------- /tests/test_0058_detach_model_objects_from_files.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import copy 4 | import os 5 | import pickle 6 | import sys 7 | 8 | import numpy 9 | import pytest 10 | import skhep_testdata 11 | 12 | import uproot 13 | 14 | 15 | def test_detachment(): 16 | with uproot.open(skhep_testdata.data_path("uproot-hepdata-example.root")) as f: 17 | assert getattr(f["hpx"].file, "file_path", None) is not None 18 | assert getattr(f["hpx"].file, "source", None) is None 19 | 20 | assert getattr(f["ntuple"].file, "file_path", None) is not None 21 | assert getattr(f["ntuple"].file, "source", None) is not None 22 | 23 | with uproot.open( 24 | skhep_testdata.data_path("uproot-small-evnt-tree-nosplit.root") 25 | ) as f: 26 | array = f["tree/evt"].array(library="np", entry_stop=1) 27 | assert getattr(array[0].file, "file_path", None) is not None 28 | assert getattr(array[0].file, "source", None) is None 29 | 30 | assert isinstance( 31 | f.file.streamer_named("Event").file, uproot.reading.DetachedFile 32 | ) 33 | assert ( 34 | str(f.file.streamer_named("Event").file_uuid) 35 | == "9eebcae8-366b-11e7-ab9d-5e789e86beef" 36 | ) 37 | 38 | 39 | def test_copy(): 40 | with uproot.open(skhep_testdata.data_path("uproot-hepdata-example.root")) as f: 41 | original = f["hpx"] 42 | original_file_path = original.file.file_path 43 | 44 | reconstituted = copy.deepcopy(original) 45 | reconstituted_file_path = reconstituted.file.file_path 46 | 47 | assert original_file_path == reconstituted_file_path 48 | 49 | 50 | def test_pickle(): 51 | with uproot.open(skhep_testdata.data_path("uproot-hepdata-example.root")) as f: 52 | original = f["hpx"] 53 | original_file_path = original.file.file_path 54 | 55 | reconstituted = pickle.loads(pickle.dumps(original)) 56 | reconstituted_file_path = reconstituted.file.file_path 57 | 58 | assert original_file_path == reconstituted_file_path 59 | 60 | 61 | def test_pickle_boost(): 62 | boost_histogram = pytest.importorskip("boost_histogram") 63 | with uproot.open(skhep_testdata.data_path("uproot-hepdata-example.root")) as f: 64 | original = f["hpx"] 65 | original_boost = original.to_boost() 66 | 67 | reconstituted = pickle.loads(pickle.dumps(original)) 68 | reconstituted_boost = reconstituted.to_boost() 69 | 70 | pickle.loads(pickle.dumps(original_boost)) 71 | pickle.loads(pickle.dumps(reconstituted_boost)) 72 | -------------------------------------------------------------------------------- /tests/test_0066_fix_http_fallback_freeze.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | 5 | import uproot 6 | 7 | 8 | @pytest.mark.network 9 | def test(): 10 | pytest.importorskip("aiohttp") 11 | with uproot.open( 12 | {"http://scikit-hep.org/uproot3/examples/HZZ.root": "events"} 13 | ) as t: 14 | t["MET_px"].array(library="np") 15 | t["MET_py"].array(library="np") 16 | -------------------------------------------------------------------------------- /tests/test_0067_common_entry_offsets.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_common_offsets(): 10 | # this file has terrible branch alignment 11 | with uproot.open(skhep_testdata.data_path("uproot-hepdata-example.root")) as f: 12 | assert f["ntuple;1"].common_entry_offsets() == [0, 75000] 13 | 14 | # this file has just one branch 15 | with uproot.open(skhep_testdata.data_path("uproot-foriter.root")) as f: 16 | assert f["foriter;1"].common_entry_offsets() == [ 17 | 0, 18 | 6, 19 | 12, 20 | 18, 21 | 24, 22 | 30, 23 | 36, 24 | 42, 25 | 46, 26 | ] 27 | 28 | with uproot.open(skhep_testdata.data_path("uproot-small-dy-nooffsets.root")) as f: 29 | assert f["tree;1"].common_entry_offsets() == [0, 200, 400, 501] 30 | assert f["tree;1"].common_entry_offsets(filter_name=["Jet_pt"]) == [ 31 | 0, 32 | 200, 33 | 397, 34 | 400, 35 | 501, 36 | ] 37 | assert f["tree;1"].common_entry_offsets(filter_name=["Jet_pt", "nJet"]) == [ 38 | 0, 39 | 200, 40 | 400, 41 | 501, 42 | ] 43 | -------------------------------------------------------------------------------- /tests/test_0081_dont_parse_colons.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | pytest.importorskip("awkward") 9 | 10 | 11 | def test_open(): 12 | assert isinstance( 13 | uproot.open(skhep_testdata.data_path("uproot-issue63.root")), 14 | uproot.reading.ReadOnlyDirectory, 15 | ) 16 | assert isinstance( 17 | uproot.open( 18 | {skhep_testdata.data_path("uproot-issue63.root"): "WtLoop_nominal"} 19 | ), 20 | uproot.behaviors.TTree.TTree, 21 | ) 22 | 23 | with pytest.raises(ValueError): 24 | uproot.open([skhep_testdata.data_path("uproot-issue63.root")]) 25 | 26 | 27 | def test_concatenate(): 28 | with pytest.raises(ValueError): 29 | uproot.concatenate(skhep_testdata.data_path("uproot-issue63.root")) 30 | 31 | assert ( 32 | len( 33 | uproot.concatenate( 34 | {skhep_testdata.data_path("uproot-issue63.root"): "blah"}, 35 | allow_missing=True, 36 | ) 37 | ) 38 | == 0 39 | ) 40 | 41 | files = skhep_testdata.data_path("uproot-sample-6.16.00-uncompressed.root").replace( 42 | "6.16.00", "*" 43 | ) 44 | 45 | uproot.concatenate(files, "Ai8") 46 | uproot.concatenate({files: "sample"}, "Ai8") 47 | uproot.concatenate([files], "Ai8") 48 | uproot.concatenate([{files: "sample"}], "Ai8") 49 | 50 | 51 | def test_iterate(): 52 | with pytest.raises(ValueError): 53 | for arrays in uproot.iterate(skhep_testdata.data_path("uproot-issue63.root")): 54 | pass 55 | 56 | assert ( 57 | len( 58 | list( 59 | uproot.iterate( 60 | {skhep_testdata.data_path("uproot-issue63.root"): "blah"}, 61 | allow_missing=True, 62 | ) 63 | ) 64 | ) 65 | == 0 66 | ) 67 | 68 | files = skhep_testdata.data_path("uproot-sample-6.16.00-uncompressed.root").replace( 69 | "6.16.00", "*" 70 | ) 71 | 72 | for arrays in uproot.iterate(files, "Ai8"): 73 | pass 74 | for arrays in uproot.iterate({files: "sample"}, "Ai8"): 75 | pass 76 | for arrays in uproot.iterate([files], "Ai8"): 77 | pass 78 | for arrays in uproot.iterate([{files: "sample"}], "Ai8"): 79 | pass 80 | 81 | 82 | pathlib = pytest.importorskip("pathlib") 83 | 84 | 85 | def test_open_colon(): 86 | assert isinstance( 87 | uproot.open( 88 | skhep_testdata.data_path("uproot-issue63.root") + ":WtLoop_nominal" 89 | ), 90 | uproot.behaviors.TTree.TTree, 91 | ) 92 | 93 | with pytest.raises(FileNotFoundError): 94 | uproot.open( 95 | pathlib.Path( 96 | skhep_testdata.data_path("uproot-issue63.root") + ":WtLoop_nominal" 97 | ) 98 | ) 99 | 100 | with pytest.raises(FileNotFoundError): 101 | uproot.open( 102 | {skhep_testdata.data_path("uproot-issue63.root") + ":WtLoop_nominal": None} 103 | ) 104 | -------------------------------------------------------------------------------- /tests/test_0087_memberwise_splitting_not_implemented_messages.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_issue510b(): 10 | with pytest.raises(NotImplementedError): 11 | with uproot.open(skhep_testdata.data_path("uproot-issue510b.root"))[ 12 | "EDepSimEvents" 13 | ] as t: 14 | t["Event"]["Trajectories.Points"].array(library="np") 15 | 16 | 17 | def test_issue403(): 18 | with pytest.raises(NotImplementedError): 19 | with uproot.open(skhep_testdata.data_path("uproot-issue403.root"))[ 20 | "Model" 21 | ] as t: 22 | t["Model.collimatorInfo"].array(library="np") 23 | 24 | 25 | def test_issue475(): 26 | with pytest.raises(NotImplementedError): 27 | with uproot.open(skhep_testdata.data_path("uproot-issue475.root"))[ 28 | "Event/Elec/ElecEvent" 29 | ] as t: 30 | t["fElecChannels"].array(library="np") 31 | -------------------------------------------------------------------------------- /tests/test_0088_read_with_http.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | 5 | import uproot 6 | 7 | import skhep_testdata 8 | 9 | 10 | @pytest.mark.network 11 | def test_issue176(): 12 | pytest.importorskip("aiohttp") 13 | 14 | with uproot.open( 15 | "https://starterkit.web.cern.ch/starterkit/data/advanced-python-2019/dalitzdata.root" 16 | ) as f: 17 | data = f["tree/Y1"].array(library="np") 18 | assert len(data) == 100000 19 | 20 | 21 | @pytest.mark.network 22 | def test_issue176_again(): 23 | pytest.importorskip("aiohttp") 24 | 25 | with uproot.open( 26 | "https://starterkit.web.cern.ch/starterkit/data/advanced-python-2019/dalitzdata.root" 27 | ) as f: 28 | data = f["tree"].arrays(["Y1", "Y2"], library="np") 29 | assert len(data["Y1"]) == 100000 30 | assert len(data["Y2"]) == 100000 31 | 32 | 33 | def test_issue121(): 34 | with uproot.open(skhep_testdata.data_path("uproot-issue121.root")) as f: 35 | data = f["Events/MET_pt"].array(library="np") 36 | assert len(data) == 40 37 | -------------------------------------------------------------------------------- /tests/test_0099_read_from_file_object.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | import uproot.source.fsspec 8 | import uproot.source.object 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "handler", 13 | [None, uproot.source.object.ObjectSource], 14 | ) 15 | def test_read_from_file_like_object(handler): 16 | with open(skhep_testdata.data_path("uproot-Zmumu.root"), "rb") as f: 17 | assert uproot.open({f: "events"}, handler=handler)["px1"].array(library="np")[ 18 | :10 19 | ].tolist() == [ 20 | -41.1952876442, 21 | 35.1180497674, 22 | 35.1180497674, 23 | 34.1444372454, 24 | 22.7835819537, 25 | -19.8623073126, 26 | -19.8623073126, 27 | -20.1773731496, 28 | 71.1437106445, 29 | 51.0504859191, 30 | ] 31 | -------------------------------------------------------------------------------- /tests/test_0112_fix_pandas_with_cut.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | pandas = pytest.importorskip("pandas") 10 | 11 | 12 | def test(): 13 | with uproot.open(skhep_testdata.data_path("uproot-Zmumu.root")) as f: 14 | df = f["events"].arrays( 15 | ["px1", "pmag"], 16 | cut="pmag < 30", 17 | aliases={"pmag": "sqrt(px1**2 + py1**2)"}, 18 | library="pd", 19 | ) 20 | assert isinstance(df, pandas.DataFrame) # not an empty tuple 21 | -------------------------------------------------------------------------------- /tests/test_0123_atlas_issues.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_version(): 10 | assert uproot.classname_decode( 11 | uproot.classname_encode("xAOD::MissingETAuxAssociationMap_v2") 12 | ) == ("xAOD::MissingETAuxAssociationMap_v2", None) 13 | assert uproot.classname_decode( 14 | uproot.classname_encode("xAOD::MissingETAuxAssociationMap_v2", 9) 15 | ) == ("xAOD::MissingETAuxAssociationMap_v2", 9) 16 | -------------------------------------------------------------------------------- /tests/test_0126_turn_unknown_emptyarrays_into_known_types.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | awkward = pytest.importorskip("awkward") 12 | with uproot.open(skhep_testdata.data_path("uproot-vectorVectorDouble.root")) as f: 13 | array = f["t/x"].array(entry_stop=2) 14 | assert str(awkward.type(array)) == "2 * var * var * float64" 15 | -------------------------------------------------------------------------------- /tests/test_0172_allow_allocators_in_vector_typenames.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test(): 10 | with uproot.open(skhep_testdata.data_path("uproot-issue-172.root")) as f: 11 | t = f["events"] 12 | t.show() 13 | assert ( 14 | t["rec_part_px_VecOps"].typename == "std::vector" 15 | ) # without the allocator 16 | t["rec_part_px_VecOps"].array(library="np") 17 | -------------------------------------------------------------------------------- /tests/test_0173_empty_and_multiprocessing_bugs.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import multiprocessing 4 | 5 | import pytest 6 | import skhep_testdata 7 | 8 | import uproot 9 | 10 | 11 | def test_empty(): 12 | with uproot.open(skhep_testdata.data_path("uproot-empty.root")) as f: 13 | t = f["tree"] 14 | assert t["x"].array(library="np").tolist() == [] 15 | assert t["y"].array(library="np").tolist() == [] 16 | assert t["z"].array(library="np").tolist() == [] 17 | 18 | 19 | def read_one(filename): 20 | with uproot.open(filename, handler=uproot.source.file.MemmapSource) as f: 21 | f.decompression_executor = uproot.ThreadPoolExecutor() 22 | t = f["events"] 23 | b = t["px1"] 24 | b.array(library="np") 25 | 26 | 27 | def test_multiprocessing(): 28 | with multiprocessing.Pool(1) as pool: 29 | out = pool.map( 30 | read_one, 31 | [ 32 | skhep_testdata.data_path("uproot-Zmumu.root"), 33 | skhep_testdata.data_path("uproot-Zmumu-zlib.root"), 34 | ], 35 | ) 36 | list(out) 37 | -------------------------------------------------------------------------------- /tests/test_0182_complain_about_missing_files.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | one = skhep_testdata.data_path("uproot-sample-6.16.00-uncompressed.root") 12 | two = skhep_testdata.data_path("uproot-sample-6.18.00-uncompressed.root") 13 | bad = one.replace(".root", "-DOES-NOT-EXIST.root") 14 | okay = one.replace(".root", "-DOES-NOT-EXIST-*.root") 15 | 16 | assert len(list(uproot.iterate([one, two], step_size="1 TB", library="np"))) == 2 17 | 18 | with pytest.raises(uproot._util._FileNotFoundError): 19 | list(uproot.iterate([one, two, bad], library="np")) 20 | 21 | assert ( 22 | len(list(uproot.iterate([one, two, okay], step_size="1 TB", library="np"))) == 2 23 | ) 24 | -------------------------------------------------------------------------------- /tests/test_0194_fix_lost_cuts_in_iterate.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | with uproot.open(skhep_testdata.data_path("uproot-Zmumu.root")) as f: 12 | for arrays in f["events"].iterate( 13 | "px1", step_size=1000, cut="px1 > 0", library="np" 14 | ): 15 | assert numpy.all(arrays["px1"] > 0) 16 | -------------------------------------------------------------------------------- /tests/test_0220_contiguous_byte_ranges_in_http.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | 5 | import uproot 6 | 7 | 8 | @pytest.mark.network 9 | def test(): 10 | pytest.importorskip("aiohttp") 11 | 12 | with uproot.open( 13 | "https://starterkit.web.cern.ch/starterkit/data/advanced-python-2019/RD_distribution.root:tree" 14 | ) as f: 15 | whole_branch = f["vchi2_b"].array(library="np") 16 | assert whole_branch[0] == 5.234916687011719 17 | assert whole_branch[-1] == 12.466843605041504 18 | 19 | whole_branch = f["mu_pt_sum"].array(library="np") 20 | assert whole_branch[0] == 26.4675350189209 21 | assert whole_branch[-1] == 39.84319305419922 22 | -------------------------------------------------------------------------------- /tests/test_0228_read_TProfiles.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import skhep_testdata 5 | from numpy.testing import assert_array_equal 6 | 7 | import uproot 8 | 9 | 10 | def test_read_TProfile2D(): 11 | file = skhep_testdata.data_path("uproot-issue-227a.root") 12 | 13 | with uproot.open(file) as h: 14 | T = h["hprof2d"] 15 | 16 | assert T.kind == "MEAN" 17 | assert_array_equal(T.axis("x").edges(), np.array([1.0, 2.0, 3.0])) 18 | assert_array_equal(T.axis("y").edges(), np.array([1.0, 2.0, 3.0, 4.0])) 19 | assert np.sum(T.counts(flow=True)) == 12 20 | assert_array_equal(T.values().tolist(), [[1.0, 2.0, 0.0], [2.0, 4.0, 6.0]]) 21 | 22 | 23 | def test_read_TProfile3D(): 24 | file = skhep_testdata.data_path("uproot-issue-227b.root") 25 | 26 | with uproot.open(file) as h: 27 | T = h["hprof3d"] 28 | 29 | assert T.kind == "MEAN" 30 | assert_array_equal(T.axis("x").edges(), np.array([1.0, 2.0, 3.0])) 31 | assert_array_equal(T.axis("y").edges(), np.array([1.0, 2.0, 3.0, 4.0])) 32 | assert_array_equal(T.axis("z").edges(), np.array([1.0, 2.0, 3.0, 4.0, 5.0])) 33 | assert np.sum(T.counts(flow=True)) == 12 34 | assert_array_equal( 35 | T.values().tolist(), 36 | [ 37 | [[2.0, 0.0, 0.0, 0.0], [0.0, 4.0, 0.0, 0.0], [0.0, 0.0, 6.0, 0.0]], 38 | [[0.0, 4.0, 0.0, 0.0], [0.0, 0.0, 0.0, 8.0], [0.0, 0.0, 0.0, 0.0]], 39 | ], 40 | ) 41 | -------------------------------------------------------------------------------- /tests/test_0240_read_TGraphAsymmErrors.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | @pytest.fixture(scope="module") 11 | def datafile(tmpdir_factory): 12 | yield skhep_testdata.data_path("uproot-issue-240.root") 13 | 14 | 15 | @pytest.fixture 16 | def graph(datafile): 17 | with uproot.open(datafile) as f: 18 | yield f["Expected limit 1lbb/Graph1D_y1"] 19 | 20 | 21 | def test_interpretation(graph): 22 | assert graph.classname == "TGraphAsymmErrors" 23 | assert graph.behaviors[0] == uproot.behaviors.TGraphAsymmErrors.TGraphAsymmErrors 24 | 25 | assert "fX" in graph.all_members.keys() 26 | assert "fY" in graph.all_members.keys() 27 | assert "fEXlow" in graph.all_members.keys() 28 | assert "fEYlow" in graph.all_members.keys() 29 | assert "fEXhigh" in graph.all_members.keys() 30 | assert "fEYhigh" in graph.all_members.keys() 31 | 32 | 33 | @pytest.mark.parametrize("axis", [-2, -1, 0, 1, "x", "y"]) 34 | def test_values_single(graph, axis): 35 | values = graph.values(axis=axis) 36 | assert isinstance(values, numpy.ndarray) 37 | assert values.shape == (162,) 38 | 39 | 40 | @pytest.mark.parametrize("axis", [-2, -1, 0, 1, "x", "y"]) 41 | @pytest.mark.parametrize("which", ["low", "high", "mean", "diff"]) 42 | def test_errors_single(graph, axis, which): 43 | errors = graph.errors(axis=axis, which=which) 44 | assert isinstance(errors, numpy.ndarray) 45 | assert errors.shape == (162,) 46 | 47 | 48 | @pytest.mark.parametrize("axis", ["both"]) 49 | def test_values_double(graph, axis): 50 | values = graph.values(axis=axis) 51 | assert len(values) == 2 52 | assert all(isinstance(arr, numpy.ndarray) for arr in values) 53 | assert all(arr.shape == (162,) for arr in values) 54 | 55 | 56 | @pytest.mark.parametrize("axis", ["both"]) 57 | @pytest.mark.parametrize("which", ["low", "high", "mean", "diff"]) 58 | def test_errors_double(graph, axis, which): 59 | errors = graph.errors(axis=axis, which=which) 60 | assert len(errors) == 2 61 | assert all(isinstance(arr, numpy.ndarray) for arr in errors) 62 | assert all(arr.shape == (162,) for arr in errors) 63 | -------------------------------------------------------------------------------- /tests/test_0278_specializations_for_TParameter.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import skhep_testdata 5 | from numpy.testing import assert_array_equal 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | with uproot.open(skhep_testdata.data_path("uproot-issue64.root")) as file: 12 | p = file["events/nbevents"] 13 | assert p.value == 500 14 | assert p 15 | assert int(p) == 500 16 | assert float(p) == 500.0 17 | 18 | 19 | def test_issue_707(): 20 | with uproot.open(skhep_testdata.data_path("uproot-issue-707.root")) as file: 21 | p = file["NumberOfPrimariesEdep"] 22 | assert p.value == 100000004 23 | -------------------------------------------------------------------------------- /tests/test_0302_pickle.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pickle 4 | 5 | import pytest 6 | import skhep_testdata 7 | 8 | import uproot 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "handler", 13 | [ 14 | uproot.source.file.MemmapSource, 15 | uproot.source.fsspec.FSSpecSource, 16 | ], 17 | ) 18 | def test_pickle_roundtrip_local(handler): 19 | with uproot.open( 20 | skhep_testdata.data_path("uproot-small-dy-withoffsets.root"), handler=handler 21 | ) as f: 22 | pkl = pickle.dumps(f["tree"]) 23 | 24 | branch = pickle.loads(pkl)["Muon_pt"] 25 | muonpt1 = branch.array(library="np", entry_start=10, entry_stop=20) 26 | assert [x.tolist() for x in muonpt1] == [ 27 | [20.60145378112793], 28 | [50.36957550048828, 41.21387481689453, 3.1869382858276367], 29 | [51.685970306396484, 35.227813720703125], 30 | [], 31 | [], 32 | [], 33 | [], 34 | [23.073759078979492], 35 | [32.921417236328125, 8.922308921813965, 4.368383407592773], 36 | [51.9132194519043, 31.930095672607422], 37 | ] 38 | 39 | 40 | @pytest.mark.parametrize( 41 | "handler", 42 | [ 43 | uproot.source.http.HTTPSource, 44 | uproot.source.fsspec.FSSpecSource, 45 | ], 46 | ) 47 | @pytest.mark.network 48 | def test_pickle_roundtrip_http(handler): 49 | pytest.importorskip("aiohttp") 50 | 51 | with uproot.open( 52 | "https://scikit-hep.org/uproot3/examples/Zmumu.root", handler=handler 53 | ) as f: 54 | pkl = pickle.dumps(f["events"]) 55 | 56 | tree = pickle.loads(pkl) 57 | assert tree.num_entries == 2304 58 | assert list(tree["M"].array(entry_stop=10)) == [ 59 | 82.4626915551, 60 | 83.6262040052, 61 | 83.3084646667, 62 | 82.1493728809, 63 | 90.4691230355, 64 | 89.7576631707, 65 | 89.7739431721, 66 | 90.4855320463, 67 | 91.7737014813, 68 | 91.9488195857, 69 | ] 70 | 71 | 72 | @pytest.mark.parametrize( 73 | "handler", 74 | [ 75 | uproot.source.xrootd.XRootDSource, 76 | uproot.source.fsspec.FSSpecSource, 77 | ], 78 | ) 79 | @pytest.mark.network 80 | @pytest.mark.xrootd 81 | def test_pickle_roundtrip_xrootd(handler): 82 | pytest.importorskip("XRootD") 83 | with uproot.open( 84 | "root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/Run2012B_DoubleMuParked.root", 85 | handler=handler, 86 | ) as f: 87 | pkl = pickle.dumps(f["Events"]) 88 | 89 | tree = pickle.loads(pkl) 90 | assert tree.num_entries == 29308627 91 | assert set(tree["run"].array(entry_stop=10)) == {194778} 92 | -------------------------------------------------------------------------------- /tests/test_0303_empty_jagged_array.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import pytest 5 | import skhep_testdata 6 | from numpy.testing import assert_array_equal 7 | 8 | import uproot 9 | 10 | 11 | def test_numpy(): 12 | with uproot.open(skhep_testdata.data_path("uproot-HZZ.root")) as f: 13 | a = f["events/Muon_Px"].array(entry_start=1, entry_stop=1, library="np") 14 | assert isinstance(a, np.ndarray) 15 | assert len(a) == 0 16 | 17 | 18 | def test_awkward(): 19 | awkward = pytest.importorskip("awkward") 20 | 21 | with uproot.open(skhep_testdata.data_path("uproot-HZZ.root")) as f: 22 | a = f["events/Muon_Px"].array(entry_start=1, entry_stop=1) 23 | assert isinstance(a, awkward.Array) 24 | assert len(a) == 0 25 | -------------------------------------------------------------------------------- /tests/test_0329_update_existing_root_files.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | import uproot.writing 11 | 12 | ROOT = pytest.importorskip("ROOT") 13 | 14 | 15 | def test(tmp_path): 16 | filename = os.path.join(tmp_path, "testy.root") 17 | 18 | f = ROOT.TFile(filename, "recreate") 19 | x = ROOT.TObjString("hello") 20 | x.Write() 21 | f.Close() 22 | 23 | assert uproot.open(filename).classnames() == {"hello;1": "TObjString"} 24 | 25 | with uproot.writing.update(filename) as root_directory: 26 | root_directory.mkdir("subdir") 27 | 28 | assert uproot.open(filename).classnames() == { 29 | "hello;1": "TObjString", 30 | "subdir;1": "TDirectory", 31 | } 32 | 33 | g = ROOT.TFile(filename, "update") 34 | g.cd("subdir") 35 | y = ROOT.TObjString("there") 36 | y.Write() 37 | g.Close() 38 | 39 | assert uproot.open(filename).classnames() == { 40 | "hello;1": "TObjString", 41 | "subdir;1": "TDirectory", 42 | "subdir/there;1": "TObjString", 43 | } 44 | -------------------------------------------------------------------------------- /tests/test_0335_empty_ttree_division_by_zero.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | for arrays in uproot.iterate( 12 | skhep_testdata.data_path("uproot-issue335.root") + ":empty_tree", 13 | ["var"], 14 | library="np", 15 | ): 16 | pass 17 | -------------------------------------------------------------------------------- /tests/test_0345_bulk_copy_method.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | import uproot 9 | import uproot.writing 10 | 11 | ROOT = pytest.importorskip("ROOT") 12 | 13 | 14 | def test_deep_mkdir(tmp_path): 15 | filename = os.path.join(tmp_path, "whatever.root") 16 | 17 | with uproot.recreate(filename) as f1: 18 | f1.mkdir("/one/two/three") 19 | 20 | assert uproot.open(filename).keys() == ["one;1", "one/two;1", "one/two/three;1"] 21 | 22 | 23 | def test_bulk_copy(tmp_path): 24 | source_filename = os.path.join(tmp_path, "source.root") 25 | dest_filename = os.path.join(tmp_path, "dest.root") 26 | 27 | f_histogram = ROOT.TFile(source_filename, "recreate") 28 | f_histogram.mkdir("subdir") 29 | f_histogram.cd("subdir") 30 | x = ROOT.TH1F("hist", "title", 100, -5, 5) 31 | x.Write() 32 | f_histogram.Close() 33 | 34 | with uproot.open(source_filename) as source: 35 | with uproot.recreate(dest_filename) as dest: 36 | dest.copy_from(source, filter_name="subdir/hist") 37 | 38 | with uproot.open(dest_filename) as dest: 39 | assert dest.keys() == ["subdir;1", "subdir/hist;1"] 40 | hist = dest["subdir/hist"] 41 | assert hist.name == "hist" 42 | assert hist.title == "title" 43 | assert hist.axis().low == -5 44 | 45 | f2 = ROOT.TFile(dest_filename, "update") 46 | h2 = f2.Get("subdir/hist") 47 | assert h2.GetName() == "hist" 48 | assert h2.GetTitle() == "title" 49 | assert h2.GetNbinsX() == 100 50 | 51 | y = ROOT.TObjString("hello") 52 | y.Write() 53 | f2.Close() 54 | 55 | assert set(uproot.open(dest_filename).keys()) == { 56 | "subdir;1", 57 | "subdir/hist;1", 58 | "hello;1", 59 | } 60 | -------------------------------------------------------------------------------- /tests/test_0349_write_TObjString.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import pytest 6 | 7 | import uproot 8 | import uproot.writing 9 | 10 | ROOT = pytest.importorskip("ROOT") 11 | 12 | 13 | def test_recreate(tmp_path): 14 | filename = os.path.join(tmp_path, "whatever.root") 15 | 16 | with uproot.recreate(filename) as f1: 17 | f1["hey"] = "you" 18 | f1["subdir/there"] = "you guys" 19 | 20 | with uproot.open(filename) as f2: 21 | assert f2["hey"] == "you" 22 | assert f2["subdir/there"] == "you guys" 23 | assert list(f2.file.streamers) == ["TObjString"] 24 | 25 | f3 = ROOT.TFile(filename, "update") 26 | assert [x.GetName() for x in f3.GetStreamerInfoList()] == ["TObjString"] 27 | assert f3.Get("hey") == "you" 28 | assert f3.Get("subdir/there") == "you guys" 29 | f3.cd("subdir") 30 | x = ROOT.TObjString("wowie") 31 | x.Write() 32 | f3.Close() 33 | 34 | with uproot.open(filename) as f4: 35 | assert f4["hey"] == "you" 36 | assert f4["subdir/there"] == "you guys" 37 | assert f4["subdir/wowie"] == "wowie" 38 | assert list(f4.file.streamers) == ["TObjString"] 39 | 40 | 41 | def test_update(tmp_path): 42 | filename = os.path.join(tmp_path, "whatever.root") 43 | 44 | f1 = ROOT.TFile(filename, "recreate") 45 | f1.mkdir("subdir") 46 | f1.cd("subdir") 47 | x = ROOT.TObjString("wowie") 48 | x.Write() 49 | f1.Close() 50 | 51 | with uproot.open(filename) as f2: 52 | assert f2["subdir/wowie"] == "wowie" 53 | assert list(f2.file.streamers) == ["TObjString"] 54 | 55 | with uproot.update(filename) as f3: 56 | f3["hey"] = "you" 57 | f3["subdir/there"] = "you guys" 58 | 59 | with uproot.open(filename) as f4: 60 | assert f4["hey"] == "you" 61 | assert f4["subdir/there"] == "you guys" 62 | assert f4["subdir/wowie"] == "wowie" 63 | assert list(f4.file.streamers) == ["TObjString"] 64 | 65 | f5 = ROOT.TFile(filename, "update") 66 | assert [x.GetName() for x in f5.GetStreamerInfoList()] == ["TObjString"] 67 | assert f5.Get("hey") == "you" 68 | assert f5.Get("subdir/there") == "you guys" 69 | f5.cd("subdir") 70 | y = ROOT.TObjString("zowie") 71 | y.Write() 72 | f5.Close() 73 | 74 | with uproot.open(filename) as f6: 75 | assert f6["hey"] == "you" 76 | assert f6["subdir/there"] == "you guys" 77 | assert f6["subdir/wowie"] == "wowie" 78 | assert f6["subdir/zowie"] == "zowie" 79 | assert list(f6.file.streamers) == ["TObjString"] 80 | 81 | 82 | def test_serialization(tmp_path): 83 | filename = os.path.join(tmp_path, "whatever.root") 84 | 85 | string = "hey" 86 | tobjstring = uproot.writing.identify.to_TObjString(string) 87 | assert ( 88 | tobjstring.tojson()["_typename"] == "TObjString" 89 | ) # https://github.com/scikit-hep/uproot5/issues/762 90 | assert tobjstring.tojson()["fString"] == str(tobjstring) 91 | 92 | with uproot.recreate(filename) as f1: 93 | f1["first"] = tobjstring 94 | f1["second"] = str(tobjstring) # also checks conversion to "str" 95 | 96 | with uproot.open(filename) as f2: 97 | assert f2["first"] == f2["second"] 98 | assert str(f2["first"]) == string 99 | -------------------------------------------------------------------------------- /tests/test_0351_write_TList.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import pytest 6 | 7 | import uproot 8 | import uproot.writing 9 | 10 | 11 | def test_write_empty(tmp_path): 12 | filename = os.path.join(tmp_path, "whatever.root") 13 | 14 | tlist = uproot.writing.identify.to_TList([]) 15 | 16 | with uproot.recreate(filename) as f: 17 | f["test"] = tlist 18 | 19 | with uproot.open(filename) as f2: 20 | assert len(f2["test"]) == 0 21 | 22 | 23 | def test_write_single_key(tmp_path): 24 | filename = os.path.join(tmp_path, "whatever.root") 25 | 26 | tlist = uproot.writing.identify.to_TList( 27 | [uproot.writing.identify.to_TObjString("test string")] 28 | ) 29 | 30 | with uproot.recreate(filename) as f: 31 | f["test"] = tlist 32 | 33 | with uproot.open(filename) as f2: 34 | assert len(f2["test"]) == 1 35 | 36 | 37 | def test_write_nested(tmp_path): 38 | filename = os.path.join(tmp_path, "whatever.root") 39 | 40 | tlist_child = uproot.writing.identify.to_TList( 41 | [uproot.writing.identify.to_TObjString(s) for s in "this is a test".split()] 42 | ) 43 | 44 | entries = [ 45 | uproot.writing.identify.to_TObjString("this string goes in the front"), 46 | tlist_child, 47 | uproot.writing.identify.to_TObjString("test string"), 48 | ] 49 | 50 | tlist = uproot.writing.identify.to_TList(entries) 51 | 52 | with uproot.recreate(filename) as f: 53 | f["test"] = tlist 54 | 55 | with uproot.open(filename) as f2: 56 | parent_list = f2["test"] 57 | assert len(parent_list) == 3 58 | assert isinstance(parent_list[0], uproot.models.TObjString.Model_TObjString) 59 | assert str(parent_list[0]) == "this string goes in the front" 60 | assert str(parent_list[2]) == "test string" 61 | child_list = parent_list[1] 62 | assert isinstance(child_list, uproot.models.TList.Model_TList) 63 | assert len(child_list) == 4 64 | assert " ".join([str(s) for s in child_list]) == "this is a test" 65 | -------------------------------------------------------------------------------- /tests/test_0352_write_THashList.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import pytest 6 | 7 | import uproot 8 | import uproot.writing 9 | 10 | # THashList should be serialized the same as TList 11 | 12 | 13 | def test_write_compare_tlist(tmp_path): 14 | filename = os.path.join(tmp_path, "whatever.root") 15 | 16 | entries = [ 17 | uproot.writing.identify.to_TObjString(s) 18 | for s in "this is a test string".split() 19 | ] 20 | 21 | tlist = uproot.writing.identify.to_TList(entries) 22 | thashlist = uproot.writing.identify.to_THashList(entries) 23 | 24 | with uproot.recreate(filename) as f1: 25 | f1["tlist"] = tlist 26 | f1["thashlist"] = thashlist 27 | 28 | with uproot.open(filename) as f2: 29 | tlist_out = [] 30 | uproot.serialization._serialize_object_any(tlist_out, f2["tlist"], "test") 31 | 32 | thashlist_out = [] 33 | uproot.serialization._serialize_object_any( 34 | thashlist_out, f2["thashlist"], "test" 35 | ) 36 | 37 | assert ( 38 | tlist_out[0] != thashlist_out[0] 39 | ) # this section contains the class name which is different 40 | assert ( 41 | tlist_out[1:] == thashlist_out[1:] 42 | ) # the remaining bytes should be the same 43 | -------------------------------------------------------------------------------- /tests/test_0384_move_behavior_of_and_fix_383.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | import uproot 9 | import uproot.writing 10 | 11 | ROOT = pytest.importorskip("ROOT") 12 | 13 | 14 | def test_recreate(tmp_path): 15 | filename = os.path.join(tmp_path, "whatever.root") 16 | 17 | f1 = ROOT.TFile(filename, "recreate") 18 | mat = ROOT.TMatrixD(3, 3) 19 | mat[0, 1] = 4 20 | mat[1, 0] = 8 21 | mat[2, 2] = 3 22 | mat.Write("mat") 23 | f1.Close() 24 | 25 | with uproot.open(filename) as f2: 26 | assert f2["mat"].member("fNrows") == 3 27 | assert f2["mat"].member("fNcols") == 3 28 | assert np.array_equal( 29 | f2["mat"].member("fElements"), [0, 4, 0, 8, 0, 0, 0, 0, 3] 30 | ) 31 | -------------------------------------------------------------------------------- /tests/test_0398_dimensions_in_leaflist.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | with uproot.open(skhep_testdata.data_path("uproot-issue-398.root")) as file: 12 | assert [x.tolist() for x in file["orange/orange"].array(library="np")[0]] == [ 13 | 1, 14 | 0.05928909033536911, 15 | 0.0687987208366394, 16 | 412.7960510253906, 17 | 0.05928909033536911, 18 | 412.7960510253906, 19 | 0, 20 | 1, 21 | 0.9996464848518372, 22 | [65.1502685546875, -122.76300811767578, -153.02999877929688], 23 | 21.341833114624023, 24 | 0.9430077075958252, 25 | 28.992263793945312, 26 | 27.94194221496582, 27 | 0.10401010513305664, 28 | 1.1628128290176392, 29 | 2.410203456878662, 30 | [27.68297004699707, 31.953433990478516, 31.953433990478516], 31 | [-9.4708890914917, 17.89554214477539, 92.4335708618164, 97.2898941040039], 32 | [ 33 | -9.345060348510742, 34 | 19.61220932006836, 35 | 93.16610717773438, 36 | 97.70188903808594, 37 | ], 38 | 4.53577995300293, 39 | 999.9000244140625, 40 | 450.4504699707031, 41 | -0.011151830665767193, 42 | 0.05031048506498337, 43 | 449.5561218261719, 44 | 0.08810456097126007, 45 | 0.047824934124946594, 46 | 408.0093994140625, 47 | 0.08411796391010284, 48 | ] 49 | -------------------------------------------------------------------------------- /tests/test_0407_read_TDatime.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import datetime 4 | 5 | import numpy 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | 12 | @pytest.fixture(scope="module") 13 | def datafile(tmpdir_factory): 14 | yield skhep_testdata.data_path("uproot-issue-407.root") 15 | 16 | 17 | @pytest.fixture(params=["foo", "foo_padded"]) 18 | def _object(request, datafile): 19 | with uproot.open(datafile) as f: 20 | yield f[request.param] 21 | 22 | 23 | @pytest.fixture 24 | def tree(datafile): 25 | with uproot.open(datafile) as f: 26 | yield f["tree"] 27 | 28 | 29 | def test_streamer(_object): 30 | assert _object.members["d"].to_datetime() == datetime.datetime(2021, 1, 1, 0, 0, 0) 31 | 32 | 33 | def test_strided_interpretation(tree): 34 | assert list(tree.iterate(library="np", how=tuple))[0][0][0].member( 35 | "fDatime" 36 | ) == uproot._util.datetime_to_code(datetime.datetime(2021, 1, 1, 0, 0, 0)) 37 | -------------------------------------------------------------------------------- /tests/test_0418_read_TTable.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | from uproot.models.TTable import Model_TTable 8 | 9 | 10 | class Model_StIOEvent(uproot.model.Model): 11 | def read_members(self, chunk, cursor, context, file): 12 | self._bases.append( 13 | uproot.models.TObject.Model_TObject.read( 14 | chunk, 15 | cursor, 16 | context, 17 | file, 18 | self._file, 19 | self._parent, 20 | concrete=self.concrete, 21 | ) 22 | ) 23 | 24 | self._members["fObj"] = uproot.deserialization.read_object_any( 25 | chunk, cursor, context, file, self._file, self.concrete 26 | ) 27 | 28 | 29 | @pytest.fixture(scope="module") 30 | def datafile(): 31 | yield skhep_testdata.data_path("uproot-issue-418.root") 32 | 33 | 34 | @pytest.fixture 35 | def custom_classes(): 36 | yield dict( 37 | uproot.classes, 38 | StIOEvent=Model_StIOEvent, 39 | St_g2t_event=Model_TTable, 40 | St_particle=Model_TTable, 41 | St_g2t_vertex=Model_TTable, 42 | St_g2t_track=Model_TTable, 43 | St_g2t_pythia=Model_TTable, 44 | St_g2t_tpc_hit=Model_TTable, 45 | St_g2t_ctf_hit=Model_TTable, 46 | St_g2t_emc_hit=Model_TTable, 47 | St_g2t_vpd_hit=Model_TTable, 48 | St_dst_bfc_status=Model_TTable, 49 | ) 50 | 51 | 52 | @pytest.fixture 53 | def geant_branch(datafile, custom_classes): 54 | with uproot.open(datafile, custom_classes=custom_classes) as f: 55 | yield f["geantBranch.0000000123.0000000322"] 56 | 57 | 58 | def test_geant_dot_root(geant_branch): 59 | items = {obj.all_members["fName"]: obj for obj in geant_branch.members["fObj"]} 60 | assert items["g2t_pythia"].data["subprocess_id"] == 1 61 | -------------------------------------------------------------------------------- /tests/test_0430_global_index_for_tuples_of_DataFrames.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | pytest.importorskip("pandas") 10 | pytest.importorskip("awkward_pandas") 11 | 12 | 13 | def test(): 14 | for arrays in uproot.iterate( 15 | [skhep_testdata.data_path("uproot-HZZ-uncompressed.root") + ":events"] * 2, 16 | ["Muon_Px", "Jet_Px", "MET_px"], 17 | library="pd", 18 | ): 19 | pass 20 | -------------------------------------------------------------------------------- /tests/test_0438_TClonesArray_is_not_AsGrouped.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | 12 | def test(): 13 | with uproot.open(skhep_testdata.data_path("uproot-mc10events.root")) as file: 14 | tree = file["Events"] 15 | assert tree["Muon"].array(library="np").tolist() == [ 16 | 1, 17 | 0, 18 | 3, 19 | 3, 20 | 0, 21 | 1, 22 | 5, 23 | 0, 24 | 1, 25 | 0, 26 | ] 27 | -------------------------------------------------------------------------------- /tests/test_0439_check_awkward_before_numpy.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | 8 | import uproot 9 | 10 | ak = pytest.importorskip("awkward") 11 | 12 | 13 | def test(tmp_path): 14 | filename = os.path.join(str(tmp_path), "whatever.root") 15 | 16 | with uproot.recreate(filename) as file: 17 | file["tree"] = {"branch": ak.Array([[1, 2, 3], [4, 5, 6]])} 18 | 19 | with uproot.open(filename) as file: 20 | assert isinstance(file["tree/branch"].interpretation, uproot.AsJagged) 21 | -------------------------------------------------------------------------------- /tests/test_0442_regular_TClonesArray.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | @pytest.fixture(scope="module") 10 | def delphes_tree(): 11 | with uproot.open(skhep_testdata.data_path("uproot-delphes-pr442.root")) as f: 12 | yield f["Delphes"] 13 | 14 | 15 | def test_read_delphes_np(delphes_tree): 16 | branch = delphes_tree["Jet/Jet.SoftDroppedP4[5]"] 17 | nparray = branch.array(library="np") 18 | assert nparray.shape == (25,) 19 | assert nparray[0].shape == (2, 5) 20 | assert nparray[0][0, 0].members["fE"] == 126.46277691787493 21 | 22 | branch = delphes_tree["GenJet04/GenJet04.Constituents"] 23 | array = branch.array(library="np") 24 | assert array.shape == (25,) 25 | assert isinstance(array[0][0], uproot.models.TRef.Model_TRefArray) 26 | 27 | 28 | def test_read_delphes_ak(delphes_tree): 29 | awkward = pytest.importorskip("awkward") 30 | 31 | branch = delphes_tree["Jet/Jet.SoftDroppedP4[5]"] 32 | array = branch.array(library="ak") 33 | assert array[0, 0, 0].fE == 126.46277691787493 34 | assert awkward.all(awkward.num(array, axis=2) == 5) 35 | 36 | branch = delphes_tree["GenJet04/GenJet04.Constituents"] 37 | array = branch.array(library="ak") 38 | assert set(array.fields) == {"fSize", "fName", "refs"} 39 | -------------------------------------------------------------------------------- /tests/test_0472_tstreamerinfo_for_ttree.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import io 4 | import os 5 | 6 | import numpy as np 7 | import pytest 8 | import skhep_testdata 9 | 10 | import uproot 11 | 12 | ROOT = pytest.importorskip("ROOT") 13 | 14 | 15 | def test(tmp_path): 16 | filename = os.path.join(tmp_path, "whatever.root") 17 | 18 | with uproot.recreate(filename) as f: 19 | f["t"] = {"b": np.array([1, 2, 3], np.int64)} 20 | 21 | with uproot.open(filename) as f: 22 | output = io.StringIO() 23 | f.file.show_streamers(stream=output) 24 | assert len(output.getvalue()) > 100 25 | assert len(f.file.streamers) == 24 26 | assert f["t/b"].array(library="np").tolist() == [1, 2, 3] 27 | 28 | f = ROOT.TFile(filename) 29 | t = f.Get("t") 30 | assert [x.b for x in t] == [1, 2, 3] 31 | -------------------------------------------------------------------------------- /tests/test_0475_remember_to_update_freesegments.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import array 4 | import os 5 | 6 | import numpy as np 7 | import pytest 8 | import skhep_testdata 9 | 10 | import uproot 11 | import uproot.writing 12 | 13 | ROOT = pytest.importorskip("ROOT") 14 | 15 | 16 | def test_numpy(tmp_path): 17 | newfile = os.path.join(tmp_path, "newfile.root") 18 | 19 | with uproot.recreate(newfile, compression=None) as fout: 20 | t1 = fout.mktree("t1", {"b": "f8"}) 21 | t1.extend({"b": [1.1, 2.2, 3.3]}) 22 | 23 | t2 = fout.mktree("t2", {"b": "f8"}) 24 | t2.extend({"b": [4.4, 5.5]}) 25 | 26 | with uproot.update(newfile) as fup: 27 | t3 = fup.mktree("t3", {"b": "f8"}) 28 | t3.extend({"b": [6.6, 7.7]}) 29 | 30 | t4 = fup.mktree("t4", {"b": "f8"}) 31 | t4.extend({"b": [8.8, 9.9]}) 32 | 33 | with uproot.open(newfile) as fin: 34 | assert fin["t1/b"].array(library="np").tolist() == [1.1, 2.2, 3.3] 35 | assert fin["t2/b"].array(library="np").tolist() == [4.4, 5.5] 36 | assert fin["t3/b"].array(library="np").tolist() == [6.6, 7.7] 37 | assert fin["t4/b"].array(library="np").tolist() == [8.8, 9.9] 38 | -------------------------------------------------------------------------------- /tests/test_0484_manually_add_model_for_TMatrixTSym_double_.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import io 4 | import os 5 | 6 | import numpy as np 7 | import pytest 8 | import skhep_testdata 9 | 10 | import uproot 11 | 12 | 13 | def test(): 14 | with uproot.open(skhep_testdata.data_path("uproot-issue-359.root")) as file: 15 | matrix = file["covmatrixOCratio"] 16 | num_elements = matrix.member("fNrows") * (matrix.member("fNcols") + 1) // 2 17 | assert len(matrix.member("fElements")) == num_elements 18 | -------------------------------------------------------------------------------- /tests/test_0487_implement_asdtypeinplace.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test_inplace_tbranch_array(): 11 | with uproot.open(skhep_testdata.data_path("uproot-Zmumu.root"))["events"] as events: 12 | N = events.num_entries 13 | 14 | m_array = numpy.zeros(N, dtype=numpy.float64) 15 | m_i = events["M"].interpretation.inplace(m_array) 16 | m_res = events["M"].array(interpretation=m_i, library="np") 17 | 18 | assert m_res.base is m_array 19 | assert m_res[:5].tolist() == [ 20 | 82.4626915551, 21 | 83.6262040052, 22 | 83.3084646667, 23 | 82.1493728809, 24 | 90.4691230355, 25 | ] 26 | 27 | run_array = numpy.zeros(N, dtype=numpy.int64) 28 | run_i = events["Run"].interpretation.inplace(run_array) 29 | run_res = events["Run"].array(interpretation=run_i, library="np") 30 | 31 | assert run_res.base is run_array 32 | assert run_res[:5].tolist() == [148031, 148031, 148031, 148031, 148031] 33 | 34 | 35 | def test_inplace_ttree_arrays(): 36 | with uproot.open(skhep_testdata.data_path("uproot-Zmumu.root"))["events"] as events: 37 | N = events.num_entries 38 | 39 | m_array = numpy.zeros(N, dtype=numpy.float64) 40 | m_i = events["M"].interpretation.inplace(m_array) 41 | 42 | run_array = numpy.zeros(N, dtype=numpy.int64) 43 | run_i = events["Run"].interpretation.inplace(run_array) 44 | 45 | events.arrays(dict(M=m_i, Run=run_i), library="np") 46 | 47 | assert m_array[:5].tolist() == [ 48 | 82.4626915551, 49 | 83.6262040052, 50 | 83.3084646667, 51 | 82.1493728809, 52 | 90.4691230355, 53 | ] 54 | 55 | assert run_array[:5].tolist() == [148031, 148031, 148031, 148031, 148031] 56 | -------------------------------------------------------------------------------- /tests/test_0519_remove_memmap_copy.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test(): 10 | with uproot.open( 11 | skhep_testdata.data_path("uproot-Zmumu-uncompressed.root") 12 | ) as file: 13 | basket = file["events/px1"].basket(0) 14 | 15 | # without PR #519, this would be a segfault 16 | assert basket.data[0] == 192 17 | -------------------------------------------------------------------------------- /tests/test_0520_dynamic_classes_cant_be_abc_subclasses.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pickle 4 | import sys 5 | import os 6 | 7 | import uproot 8 | import pytest 9 | 10 | 11 | @pytest.mark.skipif( 12 | sys.version_info < (3, 7), 13 | reason="Dynamic types depend on module __getattr__, a Python 3.7+ feature.", 14 | ) 15 | def test_pickle(tests_directory): 16 | with open(os.path.join(tests_directory, "samples/h_dynamic.pkl"), "rb") as f: 17 | assert len(list(pickle.load(f).axis(0))) == 100 18 | -------------------------------------------------------------------------------- /tests/test_0569_fBits_is_4_bytes.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | with uproot.open(skhep_testdata.data_path("uproot-issue-569.root")) as f: 12 | assert f["MCTruthTree/MCTruthEvent/TObject/fBits"].array( 13 | library="np" 14 | ).tolist() == [50331648] 15 | -------------------------------------------------------------------------------- /tests/test_0576_unicode_in_names.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | ROOT = pytest.importorskip("ROOT") 12 | 13 | 14 | def test(tmp_path): 15 | filename = os.path.join(tmp_path, "whatever.root") 16 | 17 | with uproot.recreate(filename) as file: 18 | file["\u03c0"] = np.histogram(np.random.normal(0, 1, 10)) 19 | assert file["\u03c0"].name == "\u03c0" 20 | 21 | file2 = ROOT.TFile(filename) 22 | histogram = file2.Get("\u03c0") 23 | assert histogram.GetName() == "\u03c0" 24 | -------------------------------------------------------------------------------- /tests/test_0580_round_trip_for_no_flow_histograms.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | hist = pytest.importorskip("hist") 12 | 13 | 14 | def test_no_flow(tmp_path): 15 | filename = os.path.join(tmp_path, "whatever.root") 16 | 17 | h = hist.Hist(hist.axis.Regular(20, 0, 20, flow=False)).fill( 18 | np.random.normal(10, 6, 1000) 19 | ) 20 | 21 | with uproot.recreate(filename) as fout: 22 | fout["test"] = h 23 | 24 | with uproot.open(filename) as fin: 25 | h_read = fin["test"] 26 | 27 | assert np.array_equal(h.axes[0].edges, h_read.axes[0].edges()) 28 | assert np.array_equal(h.values(flow=False), h_read.values(flow=False)) 29 | 30 | 31 | def test_yes_flow(tmp_path): 32 | filename = os.path.join(tmp_path, "whatever.root") 33 | 34 | h = hist.Hist(hist.axis.Regular(20, 0, 20, flow=True)).fill( 35 | np.random.normal(10, 6, 1000) 36 | ) 37 | 38 | with uproot.recreate(filename) as fout: 39 | fout["test"] = h 40 | 41 | with uproot.open(filename) as fin: 42 | h_read = fin["test"] 43 | 44 | assert np.array_equal(h.axes[0].edges, h_read.axes[0].edges()) 45 | assert np.array_equal(h.values(flow=False), h_read.values(flow=False)) 46 | assert np.array_equal(h.values(flow=True), h_read.values(flow=True)) 47 | -------------------------------------------------------------------------------- /tests/test_0589_explicitly_interpret_RVec_type.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | 12 | def test_numpy(): 13 | with uproot.open(skhep_testdata.data_path("uproot-issue-589.root")) as file: 14 | array = file["events"]["MC_px"].array(library="np", entry_stop=2) 15 | assert array[0][7] == 30.399463653564453 16 | assert array[1][11] == 42.04872131347656 17 | 18 | 19 | pytest.importorskip("awkward") 20 | 21 | 22 | def test_awkward(): 23 | with uproot.open(skhep_testdata.data_path("uproot-issue-589.root")) as file: 24 | array = file["events"]["MC_px"].array(library="ak", entry_stop=2) 25 | assert array[0][7] == 30.399463653564453 26 | assert array[1][11] == 42.04872131347656 27 | -------------------------------------------------------------------------------- /tests/test_0603_dask_delayed_open.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | dask = pytest.importorskip("dask") 10 | da = pytest.importorskip("dask.array") 11 | dask_awkward = pytest.importorskip("dask_awkward") 12 | 13 | 14 | def test_single_delay_open(): 15 | filename1 = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 16 | ttree = uproot.open(filename1) 17 | 18 | assert uproot.dask(filename1, open_files=False, library="np")["px1"].chunks == ( 19 | (numpy.nan,), 20 | ) 21 | arr = uproot.dask(filename1, open_files=False, library="np")[ 22 | "px1" 23 | ].compute() == ttree["px1"].array(library="np") 24 | assert arr.all() 25 | 26 | 27 | def test_multiple_delay_open(): 28 | filename1 = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 29 | filename2 = skhep_testdata.data_path("uproot-Zmumu-uncompressed.root") + ":events" 30 | true_val = uproot.concatenate([filename1, filename2], library="np") 31 | 32 | assert uproot.dask([filename1, filename2], open_files=False, library="np")[ 33 | "px1" 34 | ].chunks == ((numpy.nan, numpy.nan),) 35 | arr = ( 36 | uproot.dask([filename1, filename2], open_files=False, library="np")[ 37 | "px1" 38 | ].compute() 39 | == true_val["px1"] 40 | ) 41 | assert arr.all() 42 | 43 | 44 | @pytest.mark.parametrize("open_files", [False, True]) 45 | @pytest.mark.parametrize("library", ["np", "ak"]) 46 | def test_supplied_steps(open_files, library): 47 | filename1 = skhep_testdata.data_path("uproot-Zmumu.root") 48 | filename2 = skhep_testdata.data_path("uproot-Zmumu-uncompressed.root") 49 | true_val = uproot.concatenate( 50 | [filename1 + ":events", filename2 + ":events"], "px1", library=library 51 | )["px1"] 52 | 53 | files = [filename1, filename2] 54 | daskarr = uproot.dask(files, open_files=open_files, library=library)["px1"] 55 | 56 | if library == "ak": 57 | if open_files: 58 | assert daskarr.divisions == (0, 2304, 4608) 59 | else: 60 | assert daskarr.divisions == (None, None, None) 61 | else: 62 | if open_files: 63 | assert daskarr.chunks == ((2304, 2304),) 64 | else: 65 | assert daskarr.chunks == ((numpy.nan, numpy.nan),) 66 | 67 | assert daskarr.compute().tolist() == true_val.tolist() 68 | 69 | steps1 = [0, 1000, 2304] 70 | steps2 = [[0, 1200], [1200, 2304]] 71 | files = { 72 | filename1: {"object_path": "events", "steps": steps1}, 73 | filename2: {"object_path": "events", "steps": steps2}, 74 | } 75 | daskarr = uproot.dask(files, open_files=open_files, library=library)["px1"] 76 | 77 | if library == "ak": 78 | if open_files: 79 | assert daskarr.divisions == (0, 1000, 2304, 3504, 4608) 80 | else: 81 | assert daskarr.divisions == (0, 1000, 2304, 3504, 4608) 82 | else: 83 | if open_files: 84 | assert daskarr.chunks == ((1000, 1304, 1200, 1104),) 85 | else: 86 | assert daskarr.chunks == ((1000, 1304, 1200, 1104),) 87 | 88 | assert daskarr.compute().tolist() == true_val.tolist() 89 | -------------------------------------------------------------------------------- /tests/test_0609_num_enteries_func.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import skhep_testdata 4 | 5 | import uproot 6 | 7 | 8 | def test_num_entries_single(): 9 | file1 = skhep_testdata.data_path("uproot-Zmumu.root") 10 | ttree1 = file1 + ":events" 11 | assert list(uproot.num_entries(ttree1)) == [(file1, "events", 2304)] 12 | 13 | 14 | def test_num_entries_multiple(): 15 | file1 = skhep_testdata.data_path("uproot-Zmumu.root") 16 | ttree1 = file1 + ":events" 17 | file2 = skhep_testdata.data_path("uproot-HZZ.root") 18 | ttree2 = file2 + ":events" 19 | file3 = skhep_testdata.data_path("uproot-sample-6.08.04-uncompressed.root") 20 | ttree3 = file3 + ":sample" 21 | 22 | assert list(uproot.num_entries([ttree1, ttree2, ttree3])) == [ 23 | (file1, "events", 2304), 24 | (file2, "events", 2421), 25 | (file3, "sample", 30), 26 | ] 27 | 28 | 29 | def test_num_entries_as_iterator(): 30 | file1 = skhep_testdata.data_path("uproot-Zmumu.root") 31 | ttree1 = file1 + ":events" 32 | file2 = skhep_testdata.data_path("uproot-HZZ.root") 33 | ttree2 = file2 + ":events" 34 | file3 = skhep_testdata.data_path("uproot-sample-6.08.04-uncompressed.root") 35 | ttree3 = file3 + ":sample" 36 | 37 | vals = [ 38 | (file1, "events", 2304), 39 | (file2, "events", 2421), 40 | (file3, "sample", 30), 41 | ] 42 | for i, num in enumerate(uproot.num_entries([ttree1, ttree2, ttree3])): 43 | assert num == vals[i] 44 | 45 | 46 | def test_dict_input(): 47 | file1 = skhep_testdata.data_path("uproot-Zmumu.root") 48 | file2 = skhep_testdata.data_path("uproot-HZZ.root") 49 | file3 = skhep_testdata.data_path("uproot-sample-6.08.04-uncompressed.root") 50 | 51 | vals = [ 52 | (file1, "events", 2304), 53 | (file2, "events", 2421), 54 | (file3, "sample", 30), 55 | ] 56 | for i, num in enumerate( 57 | uproot.num_entries({file1: "events", file2: "events", file3: "sample"}) 58 | ): 59 | assert num == vals[i] 60 | -------------------------------------------------------------------------------- /tests/test_0630_rntuple_basics.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import json 4 | import queue 5 | import sys 6 | 7 | import numpy 8 | import pytest 9 | import skhep_testdata 10 | 11 | import uproot 12 | 13 | pytest.importorskip("awkward") 14 | 15 | 16 | def test_flat(): 17 | filename = skhep_testdata.data_path("test_int_float_rntuple_v1-0-0-0.root") 18 | with uproot.open(filename) as f: 19 | R = f["ntuple"] 20 | assert R.keys() == ["one_integers", "two_floats"] 21 | assert [r.type_name for r in R.header.field_records] == [ 22 | "std::int32_t", 23 | "float", 24 | ] 25 | assert R.header.checksum == R.footer.header_checksum 26 | assert all(R.arrays(entry_stop=3)["one_integers"] == numpy.array([9, 8, 7])) 27 | assert all( 28 | R.arrays("one_integers", entry_stop=3)["one_integers"] 29 | == numpy.array([9, 8, 7]) 30 | ) 31 | assert all( 32 | R.arrays(entry_start=1, entry_stop=3)["one_integers"] == numpy.array([8, 7]) 33 | ) 34 | 35 | filename = skhep_testdata.data_path("test_int_5e4_rntuple_v1-0-0-0.root") 36 | with uproot.open(filename) as f: 37 | R = f["ntuple"] 38 | assert all( 39 | R.arrays(entry_stop=3)["one_integers"] == numpy.array([50000, 49999, 49998]) 40 | ) 41 | assert all(R.arrays(entry_start=-3)["one_integers"] == numpy.array([3, 2, 1])) 42 | 43 | 44 | def test_jagged(): 45 | filename = skhep_testdata.data_path( 46 | "test_int_vfloat_tlv_vtlv_rntuple_v1-0-0-0.root" 47 | ) 48 | with uproot.open(filename) as f: 49 | R = f["ntuple"] 50 | assert R.keys(recursive=False) == [ 51 | "one_integers", 52 | "two_v_floats", 53 | "three_LV", 54 | "four_v_LVs", 55 | ] 56 | -------------------------------------------------------------------------------- /tests/test_0643_reading_vector_pair_TLorentzVector_int.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_numpy(): 10 | with uproot.open(skhep_testdata.data_path("uproot-issue-643.root"))[ 11 | "ntuple0/objects" 12 | ] as t: 13 | array = t["pf"].array(entry_stop=2, library="np") 14 | assert array[1][1].member("first").member("fE") == 326.0029230449897 15 | assert array[1][1].member("second") == 22 16 | 17 | 18 | awkward = pytest.importorskip("awkward") 19 | 20 | 21 | def test_awkward(): 22 | with uproot.open(skhep_testdata.data_path("uproot-issue-643.root"))[ 23 | "ntuple0/objects" 24 | ] as t: 25 | array = t["pf"].array(entry_stop=2, library="ak") 26 | assert array[1, 1, "first", "fE"] == 326.0029230449897 27 | assert array[1, 1, "second"] == 22 28 | -------------------------------------------------------------------------------- /tests/test_0651_implement_transformed_axis.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy as np 6 | import pytest 7 | import skhep_testdata 8 | 9 | import uproot 10 | 11 | hist = pytest.importorskip("hist") 12 | 13 | 14 | def test(tmp_path): 15 | filename = os.path.join(tmp_path, "testy.root") 16 | 17 | h_reg = hist.Hist( 18 | hist.axis.Regular(19, 0.1, 1e4, transform=hist.axis.transform.log) 19 | ) 20 | h_var = hist.Hist(hist.axis.Variable(np.logspace(-1, 4, 20))) 21 | h_reg.fill([0.15, 1.5, 15, 150, 1500, 15000]) 22 | h_var.fill([0.15, 1.5, 15, 150, 1500, 15000]) 23 | 24 | expectation = [ 25 | 0.10000000000000002, 26 | 0.1832980710832436, 27 | 0.3359818286283784, 28 | 0.6158482110660265, 29 | 1.128837891684689, 30 | 2.0691380811147897, 31 | 3.79269019073225, 32 | 6.951927961775609, 33 | 12.742749857031336, 34 | 23.357214690901213, 35 | 42.81332398719395, 36 | 78.47599703514618, 37 | 143.84498882876622, 38 | 263.6650898730361, 39 | 483.2930238571756, 40 | 885.8667904100829, 41 | 1623.7767391887219, 42 | 2976.35144163132, 43 | 5455.594781168521, 44 | 10000.00000000001, 45 | ] 46 | 47 | with uproot.writing.recreate(filename) as f: 48 | f["h_reg"] = h_reg 49 | f["h_var"] = h_var 50 | 51 | with uproot.open(filename) as f: 52 | assert f["h_reg"].to_hist().axes[0].edges.tolist() == pytest.approx(expectation) 53 | assert f["h_var"].to_hist().axes[0].edges.tolist() == pytest.approx(expectation) 54 | -------------------------------------------------------------------------------- /tests/test_0662_rntuple_stl_containers.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import json 4 | import queue 5 | import sys 6 | 7 | import numpy 8 | import pytest 9 | import skhep_testdata 10 | 11 | import uproot 12 | 13 | ak = pytest.importorskip("awkward") 14 | 15 | 16 | def test_rntuple_stl_containers(): 17 | filename = skhep_testdata.data_path("test_stl_containers_rntuple_v1-0-0-0.root") 18 | with uproot.open(filename) as f: 19 | R = f["ntuple"] 20 | assert R.keys(recursive=False) == [ 21 | "string", 22 | "vector_int32", 23 | "array_float", 24 | "vector_vector_int32", 25 | "vector_string", 26 | "vector_vector_string", 27 | "variant_int32_string", 28 | "vector_variant_int64_string", 29 | "tuple_int32_string", 30 | "pair_int32_string", 31 | "vector_tuple_int32_string", 32 | "lorentz_vector", 33 | "array_lv", 34 | ] 35 | r = R.arrays() 36 | assert ak.all(r["string"] == ["one", "two", "three", "four", "five"]) 37 | 38 | assert r["vector_int32"][0] == [1] 39 | assert ak.all(r["vector_int32"][1] == [1, 2]) 40 | assert r["vector_vector_int32"][0] == [[1]] 41 | 42 | assert ak.all(r["vector_vector_int32"][1] == [[1], [2]]) 43 | 44 | assert r["vector_string"][0] == ["one"] 45 | assert ak.all(r["vector_string"][1] == ["one", "two"]) 46 | 47 | assert ak.all(r["vector_vector_string"][0] == [["one"]]) 48 | assert ak.all( 49 | r["vector_vector_string"][-1] 50 | == [["one"], ["two"], ["three"], ["four"], ["five"]] 51 | ) 52 | assert r["variant_int32_string"][0] == 1 53 | assert r["variant_int32_string"][1] == "two" 54 | 55 | assert r["vector_variant_int64_string"][0][0] == "one" 56 | assert r["vector_variant_int64_string"][1][0] == "one" 57 | assert r["vector_variant_int64_string"][1][1] == 2 58 | assert type(r["vector_variant_int64_string"][1][1]) == numpy.int64 59 | 60 | assert r["tuple_int32_string"].tolist() == [ 61 | (1, "one"), 62 | (2, "two"), 63 | (3, "three"), 64 | (4, "four"), 65 | (5, "five"), 66 | ] 67 | assert r["pair_int32_string"].tolist() == [ 68 | (1, "one"), 69 | (2, "two"), 70 | (3, "three"), 71 | (4, "four"), 72 | (5, "five"), 73 | ] 74 | 75 | assert r["vector_tuple_int32_string"][0].tolist() == [(1, "one")] 76 | assert r["vector_tuple_int32_string"][1].tolist() == [(1, "one"), (2, "two")] 77 | 78 | assert ak.all(r["array_float"][0] == [1, 1, 1]) 79 | assert ak.all(r["array_float"][-1] == [5, 5, 5]) 80 | 81 | assert ak.all(r["array_lv"][0].pt == [1.0, 1.0, 1.0]) 82 | assert ak.all(r["array_lv"][0].eta == [1.0, 1.0, 1.0]) 83 | assert ak.all(r["array_lv"][0].phi == [1.0, 1.0, 1.0]) 84 | assert ak.all(r["array_lv"][0].mass == [1.0, 1.0, 1.0]) 85 | 86 | assert ak.all(r["array_lv"][-1].pt == [5.0, 5.0, 5.0]) 87 | assert ak.all(r["array_lv"][-1].eta == [5.0, 5.0, 5.0]) 88 | assert ak.all(r["array_lv"][-1].phi == [5.0, 5.0, 5.0]) 89 | assert ak.all(r["array_lv"][-1].mass == [5.0, 5.0, 5.0]) 90 | -------------------------------------------------------------------------------- /tests/test_0700_dask_empty_arrays.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | import awkward as ak 7 | import uproot 8 | 9 | dask = pytest.importorskip("dask") 10 | dask_awkward = pytest.importorskip("dask_awkward") 11 | 12 | 13 | def test_dask_numpy_empty_arrays(): 14 | test_path = skhep_testdata.data_path("uproot-issue-697.root") + ":tree" 15 | ttree = uproot.open(test_path) 16 | 17 | np_arrays = ttree.arrays(library="np") 18 | dask_arrays = uproot.dask(test_path, library="np") 19 | 20 | assert list(dask_arrays.keys()) == list( 21 | np_arrays.keys() 22 | ), "Different keys detected in dictionary of dask arrays and dictionary of numpy arrays" 23 | 24 | for key in np_arrays.keys(): 25 | comp = dask_arrays[key].compute() == np_arrays[key] 26 | assert comp.all(), f"Incorrect array at key {key}" 27 | 28 | 29 | def test_dask_delayed_open_numpy(): 30 | test_path = skhep_testdata.data_path("uproot-issue-697.root") + ":tree" 31 | ttree = uproot.open(test_path) 32 | 33 | np_arrays = ttree.arrays(library="np") 34 | dask_arrays = uproot.dask(test_path, library="np", open_files=False) 35 | 36 | assert list(dask_arrays.keys()) == list( 37 | np_arrays.keys() 38 | ), "Different keys detected in dictionary of dask arrays and dictionary of numpy arrays" 39 | 40 | for key in np_arrays.keys(): 41 | comp = dask_arrays[key].compute() == np_arrays[key] 42 | assert comp.all(), f"Incorrect array at key {key}" 43 | 44 | 45 | def test_dask_awkward_empty_arrays(): 46 | test_path = skhep_testdata.data_path("uproot-issue-697.root") + ":tree" 47 | ttree = uproot.open(test_path) 48 | 49 | ak_array = ttree.arrays() 50 | dak_array = uproot.dask(test_path, library="ak") 51 | 52 | assert ak.almost_equal(dak_array.compute(scheduler="synchronous"), ak_array) 53 | 54 | 55 | def test_dask_delayed_open_awkward(): 56 | test_path = skhep_testdata.data_path("uproot-issue-697.root") + ":tree" 57 | ttree = uproot.open(test_path) 58 | 59 | ak_array = ttree.arrays() 60 | dak_array = uproot.dask(test_path, library="ak", open_files=False) 61 | 62 | ak.almost_equal(dak_array.compute(scheduler="synchronous"), ak_array) 63 | 64 | 65 | def test_no_common_tree_branches(): 66 | test_path1 = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 67 | test_path2 = skhep_testdata.data_path("uproot-issue-697.root") + ":tree" 68 | 69 | with pytest.raises(ValueError): 70 | dask_arrays = uproot.dask([test_path1, test_path2], library="np") 71 | 72 | with pytest.raises(ValueError): 73 | dask_arrays = uproot.dask([test_path1, test_path2]) 74 | -------------------------------------------------------------------------------- /tests/test_0705_rntuple_writing_metadata.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import json 4 | import os 5 | import queue 6 | import sys 7 | 8 | import numpy 9 | import pytest 10 | import skhep_testdata 11 | 12 | import uproot 13 | 14 | ak = pytest.importorskip("awkward") 15 | 16 | 17 | def test_header(tmp_path): 18 | filepath = os.path.join(tmp_path, "test.root") 19 | 20 | with uproot.recreate(filepath) as file: 21 | akform = ak.forms.RecordForm( 22 | [ 23 | ak.forms.NumpyForm("float64"), 24 | ak.forms.NumpyForm("int32"), 25 | ak.forms.NumpyForm("bool"), 26 | ], 27 | ["one", "two", "three"], 28 | ) 29 | file.mkrntuple("ntuple", akform) 30 | 31 | file = uproot.open(filepath)["ntuple"] 32 | 33 | header = file.header 34 | assert header.checksum == file.footer.header_checksum 35 | 36 | frs = header.field_records 37 | assert frs[0].parent_field_id == 0 38 | assert frs[1].parent_field_id == 1 39 | assert frs[2].parent_field_id == 2 40 | assert frs[0].field_name == "one" 41 | assert frs[1].field_name == "two" 42 | assert frs[2].field_name == "three" 43 | assert frs[0].type_name == "double" 44 | assert frs[1].type_name == "std::int32_t" 45 | assert frs[2].type_name == "bool" 46 | 47 | crs = header.column_records 48 | assert crs[0].type == uproot.const.rntuple_col_type_to_num_dict["real64"] 49 | assert crs[1].type == uproot.const.rntuple_col_type_to_num_dict["int32"] 50 | assert crs[2].type == uproot.const.rntuple_col_type_to_num_dict["bit"] 51 | assert crs[0].field_id == 0 52 | assert crs[1].field_id == 1 53 | assert crs[2].field_id == 2 54 | assert crs[0].nbits == uproot.const.rntuple_col_num_to_size_dict[crs[0].type] 55 | assert crs[1].nbits == uproot.const.rntuple_col_num_to_size_dict[crs[1].type] 56 | assert crs[2].nbits == uproot.const.rntuple_col_num_to_size_dict[crs[2].type] 57 | 58 | 59 | def test_writable(tmp_path): 60 | filepath = os.path.join(tmp_path, "test.root") 61 | 62 | with uproot.recreate(filepath) as file: 63 | akform = ak.forms.RecordForm( 64 | [ 65 | ak.forms.NumpyForm("int32"), 66 | ], 67 | ["one"], 68 | ) 69 | rn = file.mkrntuple("ntuple", akform) 70 | print(rn) 71 | assert type(file["ntuple"]).__name__ == "WritableNTuple" 72 | 73 | 74 | def test_ROOT(tmp_path, capfd): 75 | ROOT = pytest.importorskip("ROOT") 76 | if ROOT.gROOT.GetVersionInt() < 63500: 77 | pytest.skip("ROOT version does not support RNTuple v1.0.0.0") 78 | 79 | filepath = os.path.join(tmp_path, "test.root") 80 | 81 | with uproot.recreate(filepath) as file: 82 | akform = ak.forms.RecordForm( 83 | [ 84 | ak.forms.NumpyForm("float64"), 85 | ak.forms.NumpyForm("int32"), 86 | ], 87 | ["one", "two"], 88 | ) 89 | file.mkrntuple("ntuple", akform) 90 | RT = ROOT.Experimental.RNTupleReader.Open("ntuple", filepath) 91 | RT.PrintInfo() 92 | out = capfd.readouterr().out 93 | assert "* Field 1 : one (double)" in out 94 | assert "* Field 2 : two (std::int32_t)" in out 95 | -------------------------------------------------------------------------------- /tests/test_0750_avoid_empty_TBasket_issue.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import json 4 | import sys 5 | 6 | import numpy 7 | import pytest 8 | import skhep_testdata 9 | 10 | import uproot 11 | 12 | 13 | def test(): 14 | with uproot.open(skhep_testdata.data_path("uproot-issue-750.root"))[ 15 | "tout/Electron_eta" 16 | ] as branch: 17 | branch.array(library="np") 18 | -------------------------------------------------------------------------------- /tests/test_0755_dask_awkward_column_projection.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import awkward as ak 5 | import pytest 6 | import skhep_testdata 7 | 8 | import uproot 9 | 10 | dask = pytest.importorskip("dask") 11 | dask_awkward = pytest.importorskip("dask_awkward") 12 | 13 | 14 | def test_column_projection_sanity_check(): 15 | test_path = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 16 | ttree = uproot.open(test_path) 17 | 18 | ak_array = ttree.arrays() 19 | dak_array = uproot.dask(test_path, library="ak") 20 | 21 | assert ak.almost_equal( 22 | dak_array[["px1", "px2", "py1", "py2"]].compute(scheduler="synchronous"), 23 | ak_array[["px1", "px2", "py1", "py2"]], 24 | ) 25 | -------------------------------------------------------------------------------- /tests/test_0791_protect_uproot_project_columns_from_dask_node_names.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | pytest.importorskip("dask_awkward") 10 | 11 | 12 | def test(): 13 | da = uproot.dask(skhep_testdata.data_path("uproot-issue-791.root") + ":tree") 14 | assert da[da.int_branch < 0].compute().tolist() == [ 15 | { 16 | "int_branch": -1, 17 | "long_branch": -2, 18 | "float_branch": 3.299999952316284, 19 | "double_branch": 4.4, 20 | "bool_branch": True, 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /tests/test_0808_fix_awkward_form_for_AsStridedObjects.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | pytest.importorskip("awkward") 10 | 11 | 12 | def test(): 13 | path = skhep_testdata.data_path("uproot-HZZ-objects.root") 14 | with uproot.open(path)["events"] as tree: 15 | form = tree["jetp4"].interpretation.awkward_form(None) 16 | assert form.to_dict() == { 17 | "class": "ListOffsetArray", 18 | "offsets": "i64", 19 | "content": { 20 | "class": "RecordArray", 21 | "fields": ["fP", "fE"], 22 | "contents": [ 23 | { 24 | "class": "RecordArray", 25 | "fields": ["fX", "fY", "fZ"], 26 | "contents": [ 27 | { 28 | "class": "NumpyArray", 29 | "primitive": "float64", 30 | "inner_shape": [], 31 | "parameters": {}, 32 | "form_key": None, 33 | }, 34 | { 35 | "class": "NumpyArray", 36 | "primitive": "float64", 37 | "inner_shape": [], 38 | "parameters": {}, 39 | "form_key": None, 40 | }, 41 | { 42 | "class": "NumpyArray", 43 | "primitive": "float64", 44 | "inner_shape": [], 45 | "parameters": {}, 46 | "form_key": None, 47 | }, 48 | ], 49 | "parameters": {"__record__": "TVector3"}, 50 | "form_key": None, 51 | }, 52 | { 53 | "class": "NumpyArray", 54 | "primitive": "float64", 55 | "inner_shape": [], 56 | "parameters": {}, 57 | "form_key": None, 58 | }, 59 | ], 60 | "parameters": {"__record__": "TLorentzVector"}, 61 | "form_key": None, 62 | }, 63 | "parameters": {}, 64 | "form_key": None, 65 | } 66 | -------------------------------------------------------------------------------- /tests/test_0816_separate_AwkwardForth_machines_by_TBranch.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy as np 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | pytest.importorskip("awkward") 10 | 11 | 12 | @pytest.mark.parametrize("do_hack", [False, True]) 13 | def test(do_hack): 14 | vvvars = ["SumPtTrkPt500", "NumTrkPt1000", "TrackWidthPt1000"] 15 | with uproot.open(skhep_testdata.data_path("uproot-issue-816.root")) as f: 16 | t = f["AnalysisMiniTree"] 17 | vv_branches = [f"offline_akt4_pf_NOSYS_{var}" for var in vvvars] 18 | if do_hack: 19 | assert ( 20 | str(t[f"offline_akt4_pf_NOSYS_SumPtTrkPt500"].array().type) 21 | == "100 * var * var * float32" 22 | ) 23 | assert ( 24 | str(t[f"offline_akt4_pf_NOSYS_NumTrkPt1000"].array().type) 25 | == "100 * var * var * int32" 26 | ) 27 | assert ( 28 | str(t[f"offline_akt4_pf_NOSYS_TrackWidthPt1000"].array().type) 29 | == "100 * var * var * float32" 30 | ) 31 | 32 | jetinfo = t.arrays(vv_branches) 33 | 34 | assert ( 35 | str(jetinfo.type) 36 | == "100 * {offline_akt4_pf_NOSYS_SumPtTrkPt500: var * var * float32, offline_akt4_pf_NOSYS_NumTrkPt1000: var * var * int32, offline_akt4_pf_NOSYS_TrackWidthPt1000: var * var * float32}" 37 | ) 38 | 39 | for v in vv_branches: 40 | assert ( 41 | str(t[f"offline_akt4_pf_NOSYS_SumPtTrkPt500"].array().type) 42 | == "100 * var * var * float32" 43 | ) 44 | assert ( 45 | str(t[f"offline_akt4_pf_NOSYS_NumTrkPt1000"].array().type) 46 | == "100 * var * var * int32" 47 | ) 48 | assert ( 49 | str(t[f"offline_akt4_pf_NOSYS_TrackWidthPt1000"].array().type) 50 | == "100 * var * var * float32" 51 | ) 52 | -------------------------------------------------------------------------------- /tests/test_0832_ak_add_doc_should_also_add_to_typetracer.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | pytest.importorskip("awkward") 10 | pytest.importorskip("dask_awkward") 11 | 12 | 13 | def test(): 14 | nMuon_doc = "slimmedMuons after basic selection (pt > 15 || (pt > 3 && (passed('CutBasedIdLoose') || passed('SoftCutBasedId') || passed('SoftMvaId') || passed('CutBasedIdGlobalHighPt') || passed('CutBasedIdTrkHighPt'))))" 15 | 16 | with uproot.open(skhep_testdata.data_path("nanoAOD_2015_CMS_Open_Data_ttbar.root"))[ 17 | "Events/nMuon" 18 | ] as branch: 19 | assert branch.title == nMuon_doc 20 | 21 | assert ( 22 | str(branch.array(ak_add_doc=True).type) 23 | == f'200 * uint32[parameters={{"__doc__": "{nMuon_doc}"}}]' 24 | ) 25 | 26 | lazy = uproot.dask( 27 | skhep_testdata.data_path("nanoAOD_2015_CMS_Open_Data_ttbar.root") + ":Events", 28 | ak_add_doc=True, 29 | ) 30 | 31 | assert ( 32 | str(lazy["nMuon"].type) 33 | == f'?? * uint32[parameters={{"__doc__": "{nMuon_doc}"}}]' 34 | ) 35 | 36 | assert ( 37 | str(lazy["nMuon"].compute().type) 38 | == f'200 * uint32[parameters={{"__doc__": "{nMuon_doc}"}}]' 39 | ) 40 | -------------------------------------------------------------------------------- /tests/test_0840_support_tleafG.py: -------------------------------------------------------------------------------- 1 | from array import array 2 | import os 3 | import pytest 4 | import numpy as np 5 | import uproot 6 | 7 | ROOT = pytest.importorskip("ROOT") 8 | 9 | 10 | def test_support_leafG(tmp_path): 11 | filename = os.path.join(tmp_path, "testy.root") 12 | f = ROOT.TFile(filename, "recreate") 13 | t = ROOT.TTree("mytree", "example tree") 14 | 15 | n = np.int32(2) 16 | t.Branch("mynum", n, "mynum/I") 17 | x = np.array([[1, 2, 3], [4, 5, 6]]) 18 | t.Branch("myarrayG", x, "myarrayG[mynum][3]/G") 19 | t.Branch("myarrayL", x, "myarrayL[mynum][3]/L") 20 | 21 | nentries = 25 22 | for i in range(nentries): 23 | t.Fill() 24 | 25 | f.Write() 26 | 27 | assert t.GetLeaf("myarrayG").Class_Name() == "TLeafG" 28 | assert t.GetLeaf("myarrayL").Class_Name() == "TLeafL" 29 | 30 | with uproot.open(filename)["mytree"] as t: 31 | assert t["myarrayG"].array(library="np").tolist()[0].tolist() == [ 32 | [1, 2, 3], 33 | [4, 5, 6], 34 | ] 35 | assert t["myarrayL"].array(library="np").tolist()[0].tolist() == [ 36 | [1, 2, 3], 37 | [4, 5, 6], 38 | ] 39 | assert ( 40 | repr(t["myarrayG"].interpretation) == "AsJagged(AsDtype(\"('>i8', (3,))\"))" 41 | ) 42 | assert ( 43 | repr(t["myarrayL"].interpretation) == "AsJagged(AsDtype(\"('>i8', (3,))\"))" 44 | ) 45 | -------------------------------------------------------------------------------- /tests/test_0841_fix_814.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | import numpy 5 | import pytest 6 | import uproot 7 | 8 | ROOT = pytest.importorskip("ROOT") 9 | 10 | 11 | def test_check_file_after_snapshot(tmp_path): 12 | filename = os.path.join(tmp_path, "tfile_with_tvector3_1.root") 13 | tfile = ROOT.TFile(filename, "RECREATE") 14 | tree = ROOT.TTree("tree", "tree") 15 | tvector3 = ROOT.TVector3() 16 | tree.Branch("tvector3", tvector3) 17 | for x in range(10): 18 | tvector3.SetX(x) 19 | tree.Fill() 20 | tree.AutoSave() 21 | tfile.Write() 22 | uproot.open(filename + ":tree").arrays() 23 | 24 | tfile = ROOT.TFile(filename, "READ") 25 | tree = tfile.Get("tree") 26 | rdf = ROOT.RDataFrame(tree) 27 | branchlist = ROOT.std.vector(ROOT.std.string)() 28 | branchlist.push_back("tvector3") 29 | filename2 = os.path.join(tmp_path, "tfile_with_tvector3_2.root") 30 | rdf.Snapshot("tree", filename2, branchlist) 31 | uproot.open(filename2 + ":tree").arrays() 32 | -------------------------------------------------------------------------------- /tests/test_0844_fix_delete_hist_from_root.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | import os 3 | import numpy 4 | import pytest 5 | import uproot 6 | import struct 7 | 8 | ROOT = pytest.importorskip("ROOT") 9 | 10 | 11 | def test_delete_from_file_with_deleted_histogram_at_the_end(tmp_path): 12 | h0f = ROOT.TH1F("h0f", "Random numbers", 200, 0, 10) 13 | h1f = ROOT.TH1F("h1f", "Random numbers", 200, 0, 10) 14 | h2f = ROOT.TH1F("h2f", "Random numbers", 200, 0, 10) 15 | 16 | filename = os.path.join(tmp_path, "hist_del_test_equal.root") 17 | tfile = ROOT.TFile(filename, "RECREATE") 18 | 19 | h0f.Write() 20 | h1f.Write() 21 | h2f.Write() 22 | tfile.Close() 23 | 24 | with uproot.update(filename) as f: 25 | assert f.keys() == ["h0f;1", "h1f;1", "h2f;1"] 26 | del f["h2f;1"] 27 | del f["h1f;1"] 28 | del f["h0f;1"] 29 | assert f.keys() == [] 30 | 31 | 32 | def test_locations_recreate_update(tmp_path): 33 | filename = os.path.join(tmp_path, "uproot_test_locations.root") 34 | 35 | with uproot.recreate(filename) as f: 36 | file_size = os.path.getsize(filename) 37 | f["hnf0"] = numpy.histogram(numpy.random.normal(0, 1, 100000)) 38 | f["hnf1"] = numpy.histogram(numpy.random.normal(0, 1, 100000)) 39 | f["hnf2"] = numpy.histogram(numpy.random.normal(0, 1, 100000)) 40 | 41 | location_recreate_0 = f._cascading.data.get_key("hnf0", 1).location 42 | location_recreate_1 = f._cascading.data.get_key("hnf1", 1).location 43 | location_recreate_2 = f._cascading.data.get_key("hnf2", 1).location 44 | 45 | seek_location_recreate_0 = f._cascading.data.get_key("hnf0", 1).seek_location 46 | seek_location_recreate_1 = f._cascading.data.get_key("hnf1", 1).seek_location 47 | seek_location_recreate_2 = f._cascading.data.get_key("hnf2", 1).seek_location 48 | 49 | with uproot.update(filename) as g: 50 | assert location_recreate_0 == g._cascading.data.get_key("hnf0", 1).location 51 | assert location_recreate_1 == g._cascading.data.get_key("hnf1", 1).location 52 | assert location_recreate_2 == g._cascading.data.get_key("hnf2", 1).location 53 | 54 | assert ( 55 | seek_location_recreate_0 56 | == g._cascading.data.get_key("hnf0", 1).seek_location 57 | ) 58 | assert ( 59 | seek_location_recreate_1 60 | == g._cascading.data.get_key("hnf1", 1).seek_location 61 | ) 62 | assert ( 63 | seek_location_recreate_2 64 | == g._cascading.data.get_key("hnf2", 1).seek_location 65 | ) 66 | -------------------------------------------------------------------------------- /tests/test_0852_fix_strided_interp_extra_offsets.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import skhep_testdata 6 | 7 | 8 | def test_xyz_vector_with_headers(): 9 | file = uproot.open(skhep_testdata.data_path("uproot-issue-513.root")) 10 | trkana = file["TrkAnaNeg/trkana"] 11 | trkana["demcent/_mom"].array() 12 | -------------------------------------------------------------------------------- /tests/test_0870_writing_arrays_of_type_unknown_fix_822.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | import pytest 5 | import uproot 6 | import awkward as ak 7 | import numpy as np 8 | 9 | 10 | def test_writing_ak_arrays_of_type_unknown(tmp_path): 11 | filename = os.path.join(tmp_path, "uproot_test_empty_type_unknown.root") 12 | ak_array = ak.Array([[], [], []]) 13 | ak_array = ak.values_astype(ak_array, np.float64) 14 | 15 | tree = {"branch": ak_array} 16 | 17 | with uproot.recreate(filename) as file: 18 | file["test"] = tree 19 | -------------------------------------------------------------------------------- /tests/test_0876_uproot_dask_blind_steps.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import numpy 4 | import pytest 5 | import skhep_testdata 6 | import awkward as ak 7 | 8 | import uproot 9 | 10 | dask_awkward = pytest.importorskip("dask_awkward") 11 | 12 | 13 | @pytest.mark.parametrize("library", ["np", "ak"]) 14 | @pytest.mark.parametrize("step_size", ["100MB", uproot._util.unset]) 15 | @pytest.mark.parametrize("steps_per_file", [1, 2, 5, 10, 15, uproot._util.unset]) 16 | @pytest.mark.parametrize("open_files", [False, True]) 17 | def test_uproot_dask_steps(library, step_size, steps_per_file, open_files): 18 | test_path = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 19 | ttree = uproot.open(test_path) 20 | 21 | arrays = ttree.arrays(library=library) 22 | if not isinstance(step_size, uproot._util._Unset) and not open_files: 23 | with pytest.raises(TypeError): 24 | uproot.dask( 25 | test_path, 26 | library=library, 27 | step_size=step_size, 28 | steps_per_file=steps_per_file, 29 | open_files=open_files, 30 | ) 31 | elif not isinstance(step_size, uproot._util._Unset) and not isinstance( 32 | steps_per_file, uproot._util._Unset 33 | ): 34 | with pytest.raises(TypeError): 35 | uproot.dask( 36 | test_path, 37 | library=library, 38 | step_size=step_size, 39 | steps_per_file=steps_per_file, 40 | open_files=open_files, 41 | ) 42 | else: 43 | dask_arrays = uproot.dask( 44 | test_path, 45 | library=library, 46 | step_size=step_size, 47 | steps_per_file=steps_per_file, 48 | open_files=open_files, 49 | ) 50 | 51 | if library == "np": 52 | assert list(dask_arrays.keys()) == list( 53 | arrays.keys() 54 | ), "Different keys detected in dictionary of dask arrays and dictionary of numpy arrays" 55 | 56 | comp = [] 57 | for key in arrays.keys(): 58 | comp.append(numpy.array_equal(dask_arrays[key].compute(), arrays[key])) 59 | assert all(comp), f"Incorrect array at key {key}" 60 | 61 | else: 62 | assert ak.almost_equal( 63 | dask_arrays[["px1", "px2", "py1", "py2"]].compute( 64 | scheduler="synchronous" 65 | ), 66 | arrays[["px1", "px2", "py1", "py2"]], 67 | ) 68 | -------------------------------------------------------------------------------- /tests/test_0886_fix_awkward_form_breadcrumbs.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import uproot 4 | import skhep_testdata 5 | 6 | 7 | def test_fix_awkward_form_breadcrumbs(): 8 | file = uproot.open(skhep_testdata.data_path("uproot-issue-880.root")) 9 | tree = file["Z"] 10 | assert tree.num_entries == 116 11 | -------------------------------------------------------------------------------- /tests/test_0910_fix_906_members_non_numerical_branches.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import uproot 4 | from skhep_testdata import data_path 5 | 6 | 7 | def test_fix_906_members_non_numerical_branches(): 8 | filename = data_path("uproot-issue-798.root") # PHYSLITE example file 9 | f = uproot.open(filename) 10 | tree = f["CollectionTree"] 11 | 12 | assert ( 13 | str(tree["EventInfo"].interpretation) 14 | == "AsStridedObjects(Model_xAOD_3a3a_EventInfo_5f_v1_v1)" 15 | ) 16 | -------------------------------------------------------------------------------- /tests/test_0911_fix_interp_array_non_numerical_objs_issue_880.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import uproot 4 | import skhep_testdata 5 | 6 | 7 | def test_fix_interpretation_for_arrays_of_nonnumerical_objects_issue_880_p2(): 8 | with uproot.open(skhep_testdata.data_path("uproot-issue-880.root")) as file: 9 | branch = file["Z/Event/Cluster[6]"] 10 | array = branch.array(library="ak") 11 | interp = uproot.interpretation.identify.interpretation_of( 12 | branch, {}, False 13 | ) # AsObjects(AsArray(False, False, Model_zCluster, (6,))) 14 | 15 | assert len(array) == 116 16 | assert len(array[0][0]) == 6 # all 6 cluster can now be accessed 17 | -------------------------------------------------------------------------------- /tests/test_0912_fix_pandas_and_double_nested_vectors_issue_885.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import uproot 4 | import pytest 5 | import skhep_testdata, os 6 | import numpy as np 7 | import awkward as ak 8 | 9 | ROOT = pytest.importorskip("ROOT") 10 | 11 | 12 | def test_pandas_and_double_nested_vectors_issue_885(tmp_path): 13 | filename = os.path.join( 14 | tmp_path, "uproot_test_pandas_and_double_nested_vectors.root" 15 | ) 16 | f = ROOT.TFile(filename, "recreate") 17 | t = ROOT.TTree("mytree", "example tree") 18 | 19 | vec1 = ROOT.std.vector("double")() 20 | vec2 = ROOT.std.vector("double")() 21 | vec_vec = ROOT.std.vector(ROOT.std.vector("double"))() 22 | 23 | for i in range(3): 24 | vec1.push_back(i) 25 | for i in range(5): 26 | vec2.push_back(i) 27 | 28 | vec_vec.push_back(vec1) 29 | vec_vec.push_back(vec2) 30 | 31 | a = np.array([1, 2, 3, 4], dtype=np.uint32) 32 | avec = ROOT.std.vector("unsigned int")(a) 33 | 34 | b = np.array([[[0, 1, 3], [4, 5, 6], [7, 8, 9]]], dtype=np.uint32) 35 | bvec = ROOT.std.vector("unsigned int")(b) 36 | 37 | t.Branch("2Dvector", vec_vec) 38 | t.Branch("1Dvector", avec) 39 | t.Branch("othervector", bvec) 40 | 41 | nentries = 25 42 | for i in range(nentries): 43 | t.Fill() 44 | 45 | f.Write() 46 | 47 | with uproot.open(filename)["mytree"] as fs: 48 | u = fs.arrays(["2Dvector", "1Dvector", "othervector"], library="pd") 49 | assert isinstance(u["2Dvector"][0], ak.highlevel.Array) 50 | assert isinstance(u["1Dvector"][0], ak.highlevel.Array) 51 | assert isinstance(u["othervector"][0], ak.highlevel.Array) 52 | assert ak.to_list(u["2Dvector"][0]) == [[0, 1, 2], [0, 1, 2, 3, 4]] 53 | assert ak.to_list(u["1Dvector"][0]) == [1, 2, 3, 4] 54 | assert ak.to_list(u["othervector"][0]) == [0, 1, 3, 4, 5, 6, 7, 8, 9] 55 | 56 | branch = fs["2Dvector"] 57 | interp = uproot.interpretation.identify.interpretation_of(branch, {}, False) 58 | interp._forth = False 59 | u2 = branch.array(interp, library="pd") 60 | assert isinstance(u2[0], ak.highlevel.Array) 61 | -------------------------------------------------------------------------------- /tests/test_0916_read_from_s3.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import socket 4 | 5 | import pytest 6 | 7 | import uproot 8 | 9 | pytest.importorskip("minio") 10 | 11 | 12 | @pytest.mark.network 13 | def test_s3_fail(): 14 | with pytest.raises((FileNotFoundError, TimeoutError, socket.timeout)): 15 | # Sometimes this raises a timeout error that doesn't go away for a long time, we might as well skip it. 16 | with uproot.source.s3.S3Source( 17 | "s3://pivarski-princeton/does-not-exist", timeout=0.1 18 | ) as source: 19 | uproot._util.tobytes(source.chunk(0, 100).raw_data) 20 | 21 | 22 | @pytest.mark.network 23 | def test_read_s3(): 24 | with uproot.open( 25 | "s3://pivarski-princeton/pythia_ppZee_run17emb.picoDst.root:PicoDst", 26 | handler=uproot.source.s3.S3Source, 27 | ) as f: 28 | data = f["Event/Event.mEventId"].array(library="np") 29 | assert len(data) == 8004 30 | -------------------------------------------------------------------------------- /tests/test_0927_dont_assume_uproot_in_global_scope_in_TPython_Eval.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import random 4 | import string 5 | 6 | import pytest 7 | 8 | ROOT = pytest.importorskip("ROOT") 9 | 10 | 11 | @pytest.mark.skip(reason="segfault in ROOT: see #1237") 12 | def test(): 13 | name = "".join(random.choices(string.ascii_lowercase, k=10)) 14 | h = ROOT.TProfile3D() 15 | assert __import__("uproot").from_pyroot(h).values().shape == (1, 1, 1) 16 | -------------------------------------------------------------------------------- /tests/test_0930_expressions_in_pandas.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | import pytest 5 | import uproot 6 | 7 | 8 | def test_expressions_in_pandas(tmp_path): 9 | pandas = pytest.importorskip("pandas") 10 | filename = os.path.join(tmp_path, "uproot_test_pandas_expressions.root") 11 | # create tmp file 12 | with uproot.recreate(filename) as file: 13 | file["tree"] = {"b1": [1, 5, 9], "b2": [3, 6, 11]} 14 | 15 | with uproot.open(filename) as file: 16 | tree = file["tree"] 17 | 18 | # checking different options 19 | tree.arrays(["log(b1)"], library="pd") # arbitrary expressions work, like log 20 | tree.arrays(["where(b1 < b2, b1, b2)"], library="np") # works with np 21 | tree.arrays(["where(b1 < b2, b1, b2)"], library="pd") # should not fail with pd 22 | -------------------------------------------------------------------------------- /tests/test_0962_rntuple_update.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import awkward as ak 6 | import skhep_testdata 7 | import numpy as np 8 | 9 | 10 | def test_new_support_RNTuple_split_int32_reading(): 11 | with uproot.open( 12 | skhep_testdata.data_path("test_int_5e4_rntuple_v1-0-0-0.root") 13 | ) as f: 14 | obj = f["ntuple"] 15 | df = obj.arrays() 16 | assert len(df) == 5e4 17 | assert len(df.one_integers) == 5e4 18 | assert np.all(df.one_integers == np.arange(5e4 + 1)[::-1][:-1]) 19 | 20 | 21 | def test_new_support_RNTuple_bit_bool_reading(): 22 | with uproot.open(skhep_testdata.data_path("test_bit_rntuple_v1-0-0-0.root")) as f: 23 | obj = f["ntuple"] 24 | df = obj.arrays() 25 | assert np.all(df.one_bit == np.asarray([1, 0, 0, 1, 0, 0, 1, 0, 0, 1])) 26 | 27 | 28 | def test_new_support_RNTuple_split_int16_reading(): 29 | with uproot.open( 30 | skhep_testdata.data_path("test_int_multicluster_rntuple_v1-0-0-0.root") 31 | ) as f: 32 | obj = f["ntuple"] 33 | df = obj.arrays() 34 | assert len(df.one_integers) == 1e8 35 | assert df.one_integers[0] == 2 36 | assert df.one_integers[-1] == 1 37 | assert np.all(np.unique(df.one_integers[: len(df.one_integers) // 2]) == [2]) 38 | assert np.all(np.unique(df.one_integers[len(df.one_integers) / 2 + 1 :]) == [1]) 39 | -------------------------------------------------------------------------------- /tests/test_0965_inverted_axes_variances_hist_888.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import numpy 5 | import uproot 6 | import skhep_testdata 7 | 8 | pytest.importorskip("hist") 9 | ROOT = pytest.importorskip("ROOT") 10 | 11 | 12 | def test_axes_of_variances_to_hist_2D_weighted(): 13 | hroot2 = ROOT.TH2F("hroot2", "", 2, 0, 1, 3, 0, 1) 14 | hroot2.Sumw2() 15 | 16 | for _ in range(1000): 17 | hroot2.Fill( 18 | 5.0 * numpy.random.random(), 19 | 5.0 * numpy.random.random(), 20 | numpy.random.random(), 21 | ) 22 | 23 | huproot2 = uproot.from_pyroot(hroot2) 24 | vuproot = huproot2.variances() 25 | hhist2 = huproot2.to_hist() 26 | vhist = hhist2.variances() 27 | 28 | # check variances are equal before and after to_hist 29 | assert (vuproot == vhist).all() 30 | 31 | 32 | @pytest.mark.skip(reason="segfault in ROOT: see #1237") 33 | def test_axes_variances_to_hist_3D_weighted(): 34 | hroot3 = ROOT.TH3F("hroot3", "", 3, 0, 1, 2, 0, 1, 5, 0, 1) 35 | hroot3.Sumw2() 36 | 37 | for _ in range(2000): 38 | hroot3.Fill( 39 | 5.0 * numpy.random.random(), 40 | 5.0 * numpy.random.random(), 41 | 5.0 * numpy.random.random(), 42 | numpy.random.random(), 43 | ) 44 | 45 | huproot3 = uproot.from_pyroot(hroot3) 46 | vuproot = huproot3.variances() 47 | hhist3 = huproot3.to_hist() 48 | vhist = hhist3.variances() 49 | 50 | # check variances are equal before and after to_hist 51 | assert (vuproot == vhist).all() 52 | 53 | 54 | def test_users_2d_weighted_histogram(): 55 | with uproot.open(skhep_testdata.data_path("uproot-issue-888.root")) as f: 56 | h = f["hrecoVsgen_ll_cHel_400mttbar"] 57 | assert (h.variances() == h.to_hist().variances()).all() 58 | -------------------------------------------------------------------------------- /tests/test_1043_const_std_string.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import skhep_testdata 4 | import uproot 5 | 6 | 7 | def test(): 8 | with uproot.open(skhep_testdata.data_path("uproot-issue-1043.root")) as file: 9 | tree = file["FooBar"] 10 | assert tree["Foo"].branches[0].typename == "std::string" 11 | -------------------------------------------------------------------------------- /tests/test_1058_dask_awkward_report.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import skhep_testdata 3 | 4 | import uproot 5 | 6 | 7 | dask = pytest.importorskip("dask") 8 | dask_awkward = pytest.importorskip("dask_awkward") 9 | 10 | 11 | @pytest.mark.parametrize( 12 | "allowed", [True, (OSError,), (FileNotFoundError, RuntimeError)] 13 | ) 14 | def test_with_report(allowed): 15 | test_path1 = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 16 | test_path2 = skhep_testdata.data_path("uproot-Zmumu-uncompressed.root") + ":events" 17 | test_path3 = "/some/file/that/doesnt/exist" 18 | files = [test_path1, test_path2, test_path3] 19 | collection, report = uproot.dask( 20 | files, 21 | library="ak", 22 | open_files=False, 23 | allow_read_errors_with_report=allowed, 24 | ) 25 | _, creport = dask.compute(collection, report) 26 | assert creport[0].exception is None # test_path1 is good 27 | assert creport[1].exception is None # test_path2 is good 28 | assert creport[2].exception == "FileNotFoundError" # test_path3 is a bad file 29 | 30 | 31 | def test_with_report_exception_missed(): 32 | test_path1 = skhep_testdata.data_path("uproot-Zmumu.root") + ":events" 33 | test_path2 = skhep_testdata.data_path("uproot-Zmumu-uncompressed.root") + ":events" 34 | test_path3 = "/some/file/that/doesnt/exist" 35 | files = [test_path1, test_path2, test_path3] 36 | collection, report = uproot.dask( 37 | files, 38 | library="ak", 39 | open_files=False, 40 | allow_read_errors_with_report=( 41 | ValueError, # allow ValueErrors, but that's not what happens! 42 | ), 43 | ) 44 | with pytest.raises(FileNotFoundError): 45 | _, creport = dask.compute(collection, report) 46 | -------------------------------------------------------------------------------- /tests/test_1063_dask_distributed.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import skhep_testdata 3 | 4 | import uproot 5 | import uproot.source.file 6 | import uproot.source.fsspec 7 | 8 | dask = pytest.importorskip("dask") 9 | dask_awkward = pytest.importorskip("dask_awkward") 10 | dask_distributed = pytest.importorskip("dask.distributed") 11 | 12 | 13 | @pytest.mark.distributed 14 | @pytest.mark.parametrize( 15 | "handler", 16 | [None, uproot.source.file.MemmapSource, uproot.source.fsspec.FSSpecSource], 17 | ) 18 | def test_issue_1063(handler): 19 | file_path = skhep_testdata.data_path("uproot-issue121.root") 20 | 21 | with dask_distributed.Client(): 22 | events = uproot.dask({file_path: "Events"}, handler=handler) 23 | dask.compute(events.Muon_pt) 24 | -------------------------------------------------------------------------------- /tests/test_1070_pandas_dataframe_building_performance_fix.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | pytest.importorskip("pandas") 9 | 10 | 11 | def test_pandas_performance_many_branches(tmp_path): 12 | for array in uproot.iterate( 13 | skhep_testdata.data_path("uproot-issue-1070.root") + ":tree", 14 | step_size=100, 15 | library="pandas", 16 | ): 17 | pass 18 | -------------------------------------------------------------------------------- /tests/test_1102_any_locks_in_models_must_be_transient.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pickle 4 | 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | with uproot.open(skhep_testdata.data_path("uproot-issue232.root"))["fTreeV0"] as t: 12 | pickle.loads(pickle.dumps(t["V0Hyper.fNsigmaHe3Pos"])) 13 | -------------------------------------------------------------------------------- /tests/test_1114_fix_attempt_to_concatenate_numpy_with_awkward.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import skhep_testdata 6 | 7 | 8 | def test_partially_fix_issue_951(): 9 | 10 | with uproot.open( 11 | skhep_testdata.data_path("uproot-issue-951.root") + ":CollectionTree" 12 | ) as tree: 13 | for key, branch in tree.iteritems(filter_typename="*ElementLink*"): 14 | try: 15 | branch.interpretation._forth = True 16 | branch.array() 17 | except TypeError as e: 18 | raise e 19 | except: 20 | # ignore for now the two branches which have different issues (basket 0 has the wrong number of bytes) and (uproot.interpretation.identify.UnknownInterpretation: none of the rules matched) 21 | pass 22 | -------------------------------------------------------------------------------- /tests/test_1120_check_decompression_executor_pass_for_dask.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | pytest.importorskip("pandas") 9 | 10 | 11 | def test_decompression_executor_for_dask(): 12 | 13 | class TestExecutor(uproot.source.futures.TrivialExecutor): 14 | def __init__(self): 15 | self.submit_count = 0 16 | 17 | def submit(self, task, /, *args, **kwargs): 18 | self.submit_count += 1 19 | super().submit(task, *args, **kwargs) 20 | 21 | testexecutor = TestExecutor() 22 | 23 | a = uproot.dask( 24 | {skhep_testdata.data_path("uproot-sample-6.20.04-uncompressed.root"): "sample"}, 25 | decompression_executor=testexecutor, 26 | ) 27 | 28 | a["i4"].compute() 29 | 30 | assert testexecutor.submit_count > 0 31 | -------------------------------------------------------------------------------- /tests/test_1127_fix_allow_colon_in_key_names.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import awkward as ak 4 | import uproot 5 | import skhep_testdata 6 | import numpy 7 | import os 8 | 9 | 10 | def test_colon_in_path_and_name(tmp_path): 11 | newfile = os.path.join(tmp_path, "test_colon_in_name.root") 12 | with uproot.recreate(newfile) as f: 13 | f["one:two"] = "together" 14 | array = ak.Array(["one", "two", "three"]) 15 | f["one"] = {"two": array} 16 | 17 | with uproot.open(newfile) as f: 18 | f["one:two"] == "together" 19 | f["one"]["two"].array() == ["one", "two", "three"] 20 | 21 | 22 | def test_colon_reading_in_path(): 23 | with uproot.open( 24 | skhep_testdata.data_path("uproot-small-evnt-tree-fullsplit.root") 25 | ) as f: 26 | f["tree:evt/P3/P3.Py"].array() == numpy.arange(100) 27 | -------------------------------------------------------------------------------- /tests/test_1128_TGraph_writing.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import pytest 6 | import numpy as np 7 | 8 | import uproot 9 | 10 | pd = pytest.importorskip("pandas") 11 | ROOT = pytest.importorskip("ROOT") 12 | 13 | 14 | def test_saving_TGraph_to_file(tmp_path): 15 | newfile = os.path.join(tmp_path, "test_file.root") 16 | x = [i for i in range(10)] 17 | y = [i * 10 for i in range(10)] 18 | df = pd.DataFrame({"x": x, "y": y}) 19 | 20 | with uproot.recreate(newfile) as f: 21 | f["myTGraph"] = uproot.as_TGraph(df) 22 | 23 | with uproot.open(newfile) as f: 24 | tgraph = f["myTGraph"] 25 | 26 | x_new = tgraph.values("x") 27 | y_new = tgraph.values("y") 28 | 29 | for i in range(len(x)): 30 | assert x_new[i] == pytest.approx(x[i]) 31 | assert y_new[i] == pytest.approx(y[i]) 32 | 33 | 34 | def test_opening_TGraph_with_root(tmp_path): 35 | newfile = os.path.join(tmp_path, "test_file.root") 36 | x = [i for i in range(10)] 37 | y = [i * 10 for i in range(10)] 38 | df = pd.DataFrame({"x": x, "y": y}) 39 | tGraphName = "myTGraph" 40 | title = "My TGraph" 41 | xLabel = "xLabel" 42 | yLabel = "yLabel" 43 | 44 | with uproot.recreate(newfile) as f: 45 | f[tGraphName] = uproot.as_TGraph( 46 | df, title=title, xAxisLabel=xLabel, yAxisLabel=yLabel 47 | ) 48 | 49 | with ROOT.TFile.Open(newfile) as file: 50 | tgraph = file.Get(tGraphName) 51 | 52 | assert tgraph.GetTitle() == f"{title};{xLabel};{yLabel}" 53 | assert tgraph.GetXaxis().GetTitle() == xLabel 54 | assert tgraph.GetYaxis().GetTitle() == yLabel 55 | 56 | for i in range(len(x)): 57 | xAxis = tgraph.GetX() 58 | yAxis = tgraph.GetY() 59 | assert xAxis[i] == pytest.approx(x[i]) 60 | assert yAxis[i] == pytest.approx(y[i]) 61 | -------------------------------------------------------------------------------- /tests/test_1146_split_ranges_for_large_files_over_http.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | 6 | 7 | @pytest.mark.skip( 8 | reason="The server started requiring authentication to access the file." 9 | ) 10 | def test_split_ranges_if_large_file_in_http(): 11 | fname = ( 12 | "https://xrootd-local.unl.edu:1094//store/user/AGC/nanoAOD/TT_TuneCUETP8M1_13TeV" 13 | "-powheg-pythia8/cmsopendata2015_ttbar_19980_PU25nsData2015v1_76X_mcRun2_asymptotic" 14 | "_v12_ext3-v1_00000_0000.root" 15 | ) 16 | 17 | arrays_to_read = [ 18 | "Jet_mass", 19 | "nJet", 20 | "Muon_pt", 21 | "Jet_phi", 22 | "Jet_btagCSVV2", 23 | "Jet_pt", 24 | "Jet_eta", 25 | ] 26 | 27 | f = uproot.open( 28 | fname, handler=uproot.source.http.HTTPSource, http_max_header_bytes=21786 29 | ) 30 | assert f.file.options["http_max_header_bytes"] == 21786 31 | 32 | f["Events"].arrays(arrays_to_read) 33 | -------------------------------------------------------------------------------- /tests/test_1154_classof_using_relative_path.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import uproot 6 | import skhep_testdata 7 | import numpy as np 8 | 9 | 10 | def test_descend_into_path_classname_of(tmp_path): 11 | filename = os.path.join(tmp_path, "test.root") 12 | 13 | with uproot.recreate(filename) as f: 14 | f["Tree"] = {"x": np.array([1, 2, 3, 4, 5])} 15 | 16 | with uproot.open(filename) as f: 17 | assert f.classname_of("Tree/x") == "TBranch" 18 | assert f.title_of("Tree/x").startswith("x/") 19 | assert f.class_of("Tree/x") == uproot.models.TBranch.Model_TBranch 20 | f.streamer_of("Tree/x") 21 | 22 | # nested directories 23 | with uproot.open("https://scikit-hep.org/uproot3/examples/nesteddirs.root") as g: 24 | assert g.classname_of("one/two/tree") == "TTree" 25 | assert g.classname_of("one/two/tree/Int64") == "TBranch" 26 | 27 | # check both colon and slash 28 | with uproot.open( 29 | skhep_testdata.data_path("uproot-small-evnt-tree-fullsplit.root") 30 | ) as f: 31 | f.classname_of("tree:evt") == "TBranch" 32 | f.classname_of("tree/evt") == "TBranch" 33 | -------------------------------------------------------------------------------- /tests/test_1159_rntuple_cluster_groups.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_multiple_cluster_groups(): 10 | filename = skhep_testdata.data_path( 11 | "test_multiple_cluster_groups_rntuple_v1-0-0-0.root" 12 | ) 13 | with uproot.open(filename) as f: 14 | obj = f["ntuple"] 15 | 16 | assert len(obj.footer.cluster_group_records) == 3 17 | 18 | assert obj.footer.cluster_group_records[0].num_clusters == 5 19 | assert obj.footer.cluster_group_records[1].num_clusters == 4 20 | assert obj.footer.cluster_group_records[2].num_clusters == 3 21 | 22 | assert obj.num_entries == 1000 23 | 24 | arrays = obj.arrays() 25 | 26 | assert arrays.one.tolist() == list(range(1000)) 27 | assert arrays.int_vector.tolist() == [[i, i + 1] for i in range(1000)] 28 | -------------------------------------------------------------------------------- /tests/test_1160_std_string_in_TDirectory.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import json 4 | 5 | import skhep_testdata 6 | 7 | import uproot 8 | 9 | 10 | def test(): 11 | with uproot.open(skhep_testdata.data_path("string-example.root")) as file: 12 | assert json.loads(file["FileSummaryRecord"]) == { 13 | "LumiCounter.eventsByRun": { 14 | "counts": {}, 15 | "empty": True, 16 | "type": "LumiEventCounter", 17 | }, 18 | "guid": "5FE9437E-D958-11EE-AB88-3CECEF1070AC", 19 | } 20 | -------------------------------------------------------------------------------- /tests/test_1180_read_free_floating_vector_issue_1179.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import os 6 | import numpy as np 7 | 8 | ROOT = pytest.importorskip("ROOT") 9 | 10 | 11 | def test_read_free_floating_vector(tmp_path): 12 | newfile = os.path.join(tmp_path, "test_freevec.root") 13 | f = ROOT.TFile(newfile, "recreate") 14 | a = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float64) 15 | c = np.array([0, 1, 4, 5, 6, 7, 8, 9], dtype=np.uint32) 16 | avec = ROOT.std.vector("double")(a) 17 | bvec = ROOT.std.vector("unsigned int")(c) 18 | f.WriteObject(avec, "avec") 19 | f.WriteObject(bvec, "bvec") 20 | f.Write() 21 | f.Close() 22 | 23 | with uproot.open(newfile) as f: 24 | assert f["avec"].tolist() == [1.0, 2.0, 3.0, 4.0] 25 | assert f["bvec"].tolist() == [0, 1, 4, 5, 6, 7, 8, 9] 26 | -------------------------------------------------------------------------------- /tests/test_1181_support_for_stl_list.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | import pytest 3 | import uproot 4 | import os 5 | import numpy as np 6 | 7 | ROOT = pytest.importorskip("ROOT") 8 | 9 | 10 | def test_read_free_floating_list(tmp_path): 11 | newfile = os.path.join(tmp_path, "test_free_stl_list.root") 12 | f = ROOT.TFile(newfile, "recreate") 13 | 14 | a = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float64) 15 | b = np.array([0, 1, 4, 5, 6, 7, 8, 9], dtype=np.int32) 16 | v = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], dtype=np.float64) 17 | 18 | alist = ROOT.std.list("double")(a) 19 | blist = ROOT.std.list("int")(b) 20 | avector = ROOT.std.vector("double")(v) 21 | 22 | f.WriteObject(alist, "alist") 23 | f.WriteObject(avector, "avector") 24 | f.WriteObject(blist, "blist") 25 | 26 | f.Write() 27 | f.Close() 28 | 29 | with uproot.open(newfile) as fs: 30 | a = fs["alist"] 31 | b = fs["blist"] 32 | v = fs["avector"] 33 | 34 | assert a.tolist() == [1.0, 2.0, 3.0, 4.0] 35 | assert b.tolist() == [0, 1, 4, 5, 6, 7, 8, 9] 36 | assert isinstance(a, uproot.containers.STLList) 37 | assert isinstance(b, uproot.containers.STLList) 38 | assert isinstance(v, uproot.containers.STLVector) 39 | 40 | 41 | def test_read_list_in_tree(tmp_path): 42 | newfile = os.path.join(tmp_path, "test_ttree_stl_list.root") 43 | f = ROOT.TFile(newfile, "recreate") 44 | t = ROOT.TTree("mytree", "example tree") 45 | 46 | alist = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], dtype=np.float64) 47 | treelist = ROOT.std.list("double")(alist) 48 | 49 | avector = np.array([1.0, 2.0, 3.0], dtype=np.float64) 50 | treevector = ROOT.std.vector("double")(avector) 51 | 52 | t.Branch("avector", treevector) 53 | t.Branch("alist", treelist) 54 | 55 | for i in range(3): 56 | t.Fill() 57 | 58 | f.Write() 59 | 60 | with uproot.open(newfile)["mytree"] as fs: 61 | 62 | assert fs["alist"].array().tolist() == [ 63 | [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], 64 | [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], 65 | [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], 66 | ] 67 | assert fs["avector"].array().tolist() == [ 68 | [1.0, 2.0, 3.0], 69 | [1.0, 2.0, 3.0], 70 | [1.0, 2.0, 3.0], 71 | ] 72 | -------------------------------------------------------------------------------- /tests/test_1182_add_support_for_bitset.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import uproot 4 | import skhep_testdata 5 | 6 | 7 | def test_add_support_for_bitset(): 8 | with uproot.open(skhep_testdata.data_path("uproot-issue-40.root")) as f: 9 | assert ( 10 | repr(f["tree"]["bitset8"].interpretation) 11 | == "AsObjects(AsBitSet(True, dtype('bool')))" 12 | ) 13 | assert ( 14 | repr(f["tree"]["bitset16"].interpretation) 15 | == "AsObjects(AsBitSet(True, dtype('bool')))" 16 | ) 17 | 18 | assert f["tree"]["bitset8"].array().tolist() == [ 19 | [True, False, True, False, True, False, False, False] 20 | ] 21 | assert f["tree"]["bitset16"].array().tolist() == [ 22 | [ 23 | False, 24 | True, 25 | False, 26 | True, 27 | False, 28 | True, 29 | True, 30 | True, 31 | True, 32 | False, 33 | True, 34 | False, 35 | True, 36 | False, 37 | False, 38 | False, 39 | ] 40 | ] 41 | -------------------------------------------------------------------------------- /tests/test_1183_ttime_custom.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import skhep_testdata 6 | 7 | ROOT = pytest.importorskip("ROOT") 8 | 9 | 10 | def test_ttime_custom(): 11 | f = ROOT.TFile.Open(skhep_testdata.data_path("uproot-issue-861.root")) 12 | t1 = f.Get("RealTime_0").AsString() 13 | t2 = f.Get("LiveTime_0").AsString() 14 | f.Close() 15 | with uproot.open(skhep_testdata.data_path("uproot-issue-861.root")) as f: 16 | assert str(f["RealTime_0"].members["fMilliSec"]) == t1 17 | assert str(f["LiveTime_0"].members["fMilliSec"]) == t2 18 | -------------------------------------------------------------------------------- /tests/test_1186_dtype_might_raise_ValueError.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import pytest 6 | import numpy as np 7 | 8 | import uproot 9 | 10 | ak = pytest.importorskip("awkward") 11 | 12 | 13 | def test(tmp_path): 14 | filename = os.path.join(tmp_path, "whatever.root") 15 | 16 | pt = ak.Array([[0.0, 11, 22], [], [33, 44], [55], [66, 77, 88, 99]]) 17 | event_params = np.array( 18 | [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0]], dtype=np.uint32 19 | ) 20 | 21 | with uproot.recreate(filename) as f: 22 | f.mktree("t", {"event_params": "3 * uint32", "pt": "var * float64"}) 23 | f["t"].extend({"event_params": event_params, "pt": pt}) 24 | -------------------------------------------------------------------------------- /tests/test_1189_dask_failing_on_duplicate_keys.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | pytest.importorskip("pandas") 9 | 10 | 11 | def test_dask_duplicated_keys(): 12 | 13 | lazy = uproot.dask( 14 | skhep_testdata.data_path("uproot-metadata-performance.root") + ":Events" 15 | ) 16 | materialized = lazy.FatJet_btagDDBvLV2.compute() 17 | 18 | lazy = uproot.dask(skhep_testdata.data_path("uproot-issue513.root") + ":Delphes") 19 | materialized = lazy.Particle.compute() 20 | 21 | lazy = uproot.dask( 22 | skhep_testdata.data_path("uproot-issue443.root") + ":muonDataTree" 23 | ) 24 | materialized = lazy.hitEnd.compute() 25 | -------------------------------------------------------------------------------- /tests/test_1191_rntuple_fixes.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_schema_extension(): 10 | filename = skhep_testdata.data_path("test_extension_columns_rntuple_v1-0-0-0.root") 11 | with uproot.open(filename) as f: 12 | obj = f["ntuple"] 13 | 14 | assert len(obj.page_link_list[0]) < len(obj.page_link_list[1]) 15 | 16 | assert len(obj.column_records) > len(obj.header.column_records) 17 | assert len(obj.column_records) == 4 18 | assert obj.column_records[1].first_element_index == 200 19 | assert obj.column_records[2].first_element_index == 400 20 | 21 | arrays = obj.arrays() 22 | 23 | assert len(arrays.float_field) == 600 24 | assert len(arrays.intvec_field) == 600 25 | 26 | assert all(arrays.float_field[:200] == 0) 27 | assert all(len(l) == 0 for l in arrays.intvec_field[:400]) 28 | 29 | assert next(i for i, l in enumerate(arrays.float_field) if l != 0) == 200 30 | assert next(i for i, l in enumerate(arrays.intvec_field) if len(l) != 0) == 400 31 | 32 | 33 | def test_rntuple_cardinality(): 34 | filename = skhep_testdata.data_path( 35 | "Run2012BC_DoubleMuParked_Muons_1000evts_rntuple_v1-0-0-0.root" 36 | ) 37 | with uproot.open(filename) as f: 38 | obj = f["Events"] 39 | arrays = obj.arrays() 40 | assert arrays["nMuon"].tolist() == [len(l) for l in arrays["Muon_pt"]] 41 | 42 | 43 | def test_multiple_page_delta_encoding(): 44 | filename = skhep_testdata.data_path("test_index_multicluster_rntuple_v1-0-0-0.root") 45 | with uproot.open(filename) as f: 46 | obj = f["ntuple"] 47 | data = obj.read_col_page(0, 0) 48 | # first page has 64 elements, so this checks that data was stitched together correctly 49 | assert data[64] - data[63] == 2 50 | 51 | 52 | def test_split_encoding(): 53 | filename = skhep_testdata.data_path( 54 | "Run2012BC_DoubleMuParked_Muons_1000evts_rntuple_v1-0-0-0.root" 55 | ) 56 | with uproot.open(filename) as f: 57 | obj = f["Events"] 58 | arrays = obj.arrays() 59 | 60 | expected_pt = [10.763696670532227, 15.736522674560547] 61 | expected_charge = [-1, -1] 62 | assert arrays["Muon_pt"][0].tolist() == expected_pt 63 | assert arrays["Muon_charge"][0].tolist() == expected_charge 64 | -------------------------------------------------------------------------------- /tests/test_1198_coalesce.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from uproot.source.coalesce import CoalesceConfig, RangeRequest, _coalesce, Future 3 | 4 | 5 | @pytest.mark.parametrize( 6 | "config", 7 | [ 8 | CoalesceConfig(), 9 | CoalesceConfig(max_range_gap=2, max_request_ranges=1), 10 | ], 11 | ids=["default", "tiny"], 12 | ) 13 | @pytest.mark.parametrize( 14 | "ranges", 15 | [ 16 | [(1, 3), (4, 6), (10, 20)], 17 | [(1, 3), (10, 20), (4, 6), (9, 10)], 18 | [(1, 3), (10, 20), (6, 15)], 19 | [(1, 3), (10, 20), (6, 25)], 20 | ], 21 | ids=["sorted", "jumbled", "overlapped", "nested"], 22 | ) 23 | def test_coalesce(ranges, config): 24 | data = b"abcdefghijklmnopqurstuvwxyz" 25 | 26 | all_requests = [RangeRequest(start, stop, None) for start, stop in ranges] 27 | nreq = 0 28 | for merged_request in _coalesce(all_requests, config): 29 | future = Future() 30 | future.set_result([data[start:stop] for start, stop in merged_request.ranges()]) 31 | merged_request.set_future(future) 32 | nreq += 1 33 | 34 | if config.max_range_gap == 2: 35 | assert nreq > 1 36 | 37 | for req in all_requests: 38 | assert req.future 39 | assert req.future.result() == data[req.start : req.stop] 40 | -------------------------------------------------------------------------------- /tests/test_1207_fix_title_of_TBranch_with_counter.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import awkward as ak 6 | 7 | import uproot 8 | 9 | 10 | def test(tmp_path): 11 | filename = os.path.join(tmp_path, "file.root") 12 | 13 | with uproot.recreate(filename) as file: 14 | file["tree"] = {"branch": ak.Array([[1.1, 2.2, 3.3], [], [4.4, 5.5]])} 15 | 16 | with uproot.open(filename) as file: 17 | assert file["tree"]["branch"].title == "branch[nbranch]/D" 18 | assert ( 19 | file["tree"]["branch"].member("fLeaves")[0].member("fTitle") 20 | == "branch[nbranch]" 21 | ) 22 | -------------------------------------------------------------------------------- /tests/test_1212_dont_let_update_mess_up_file_version.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import uproot 6 | 7 | 8 | def test(tmp_path): 9 | filename = os.path.join(tmp_path, "whatever.root") 10 | 11 | with uproot.recreate(filename) as file: 12 | file["one"] = "one" 13 | 14 | with uproot.update(filename) as file: 15 | file["two"] = "two" 16 | 17 | with uproot.open(filename) as file: 18 | assert file.file.fVersion == uproot.writing._cascade.FileHeader.class_version 19 | -------------------------------------------------------------------------------- /tests/test_1221_AwkwardForth_bug.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import skhep_testdata 6 | 7 | 8 | def test(): 9 | with uproot.open(skhep_testdata.data_path("uproot-issue-1221.root")) as file: 10 | record = file["TrkAna"]["trkana"]["demtsh"].array()[-1, -1, -1] 11 | assert record.tolist() == { 12 | "wdot": -0.6311486959457397, 13 | "dhit": True, 14 | "poca": { 15 | "fCoordinates": { 16 | "fX": -526.5504760742188, 17 | "fY": -195.0541534423828, 18 | "fZ": 1338.90771484375, 19 | } 20 | }, 21 | "dactive": True, 22 | } 23 | -------------------------------------------------------------------------------- /tests/test_1223_more_rntuple_types.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import skhep_testdata 4 | 5 | import uproot 6 | 7 | 8 | def test_atomic(): 9 | filename = skhep_testdata.data_path("test_atomic_bitset_rntuple_v1-0-0-0.root") 10 | with uproot.open(filename) as f: 11 | obj = f["ntuple"] 12 | 13 | a = obj.arrays("atomic_int") 14 | 15 | assert a.atomic_int.tolist() == [1, 2, 3] 16 | 17 | 18 | def test_bitset(): 19 | filename = skhep_testdata.data_path("test_atomic_bitset_rntuple_v1-0-0-0.root") 20 | with uproot.open(filename) as f: 21 | obj = f["ntuple"] 22 | 23 | a = obj.arrays("bitset") 24 | 25 | assert len(a.bitset) == 3 26 | assert len(a.bitset[0]) == 42 27 | assert a.bitset[0].tolist()[:6] == [0, 1, 0, 1, 0, 1] 28 | assert all(a.bitset[0][6:] == 0) 29 | assert a.bitset[1].tolist()[:16] == [ 30 | 0, 31 | 1, 32 | 0, 33 | 1, 34 | 0, 35 | 1, 36 | 0, 37 | 1, 38 | 0, 39 | 1, 40 | 0, 41 | 1, 42 | 0, 43 | 1, 44 | 0, 45 | 1, 46 | ] 47 | assert all(a.bitset[1][16:] == 0) 48 | assert a.bitset[2].tolist()[:16] == [ 49 | 0, 50 | 0, 51 | 0, 52 | 1, 53 | 0, 54 | 0, 55 | 0, 56 | 1, 57 | 0, 58 | 0, 59 | 0, 60 | 1, 61 | 0, 62 | 0, 63 | 0, 64 | 1, 65 | ] 66 | assert all(a.bitset[2][16:] == 0) 67 | 68 | 69 | def test_empty_struct(): 70 | filename = skhep_testdata.data_path( 71 | "test_emptystruct_invalidvar_rntuple_v1-0-0-0.root" 72 | ) 73 | with uproot.open(filename) as f: 74 | obj = f["ntuple"] 75 | 76 | a = obj.arrays("empty_struct") 77 | 78 | assert a.empty_struct.tolist() == [(), (), ()] 79 | 80 | 81 | def test_invalid_variant(): 82 | filename = skhep_testdata.data_path( 83 | "test_emptystruct_invalidvar_rntuple_v1-0-0-0.root" 84 | ) 85 | with uproot.open(filename) as f: 86 | obj = f["ntuple"] 87 | 88 | a = obj.arrays("variant.*") 89 | 90 | assert a.variant.tolist() == [1, None, {"i": 2}] 91 | -------------------------------------------------------------------------------- /tests/test_1229_const_in_typename.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | from uproot.interpretation.identify import parse_typename 8 | 9 | 10 | @pytest.fixture(scope="module") 11 | def datafile(tmpdir_factory): 12 | yield skhep_testdata.data_path("uproot-issue-1229.root") 13 | 14 | 15 | @pytest.fixture 16 | def tree(datafile): 17 | with uproot.open(datafile) as f: 18 | yield f["tree"] 19 | 20 | 21 | def test_const_in_typename(tree): 22 | assert tree["branch/pointer"].typename == "TFooMember*" 23 | assert tree["branch/const_pointer"].typename == "TFooMember*" 24 | 25 | 26 | def test_const_parse_typename(): 27 | assert parse_typename("TH1I*") == parse_typename("const TH1I*") 28 | -------------------------------------------------------------------------------- /tests/test_1250_rntuple_improvements.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | 9 | def test_field_class(): 10 | filename = skhep_testdata.data_path("test_nested_structs_rntuple_v1-0-0-0.root") 11 | with uproot.open(filename) as f: 12 | obj = f["ntuple"] 13 | my_struct = obj["my_struct"] 14 | assert len(my_struct) == 2 15 | 16 | sub_struct = my_struct["sub_struct"] 17 | assert len(my_struct) == 2 18 | 19 | sub_sub_struct = sub_struct["sub_sub_struct"] 20 | assert len(sub_sub_struct) == 2 21 | 22 | v = sub_sub_struct["v"] 23 | assert len(v) == 1 24 | 25 | 26 | def test_array_methods(): 27 | filename = skhep_testdata.data_path( 28 | "Run2012BC_DoubleMuParked_Muons_1000evts_rntuple_v1-0-0-0.root" 29 | ) 30 | with uproot.open(filename) as f: 31 | obj = f["Events"] 32 | nMuon_array = obj["nMuon"].array() 33 | Muon_pt_array = obj["Muon_pt"].array() 34 | assert nMuon_array.tolist() == [len(l) for l in Muon_pt_array] 35 | 36 | nMuon_arrays = obj["nMuon"].arrays() 37 | assert len(nMuon_arrays.fields) == 1 38 | assert len(nMuon_arrays) == 1000 39 | assert nMuon_arrays["nMuon"].tolist() == nMuon_array.tolist() 40 | 41 | 42 | def test_iterate(): 43 | filename = skhep_testdata.data_path( 44 | "Run2012BC_DoubleMuParked_Muons_1000evts_rntuple_v1-0-0-0.root" 45 | ) 46 | with uproot.open(filename) as f: 47 | obj = f["Events"] 48 | for i, arrays in enumerate(obj.iterate(step_size=100)): 49 | assert len(arrays) == 100 50 | if i == 0: 51 | expected_pt = [10.763696670532227, 15.736522674560547] 52 | expected_charge = [-1, -1] 53 | assert arrays["Muon_pt"][0].tolist() == expected_pt 54 | assert arrays["Muon_charge"][0].tolist() == expected_charge 55 | 56 | for i, arrays in enumerate(obj.iterate(step_size="10 kB")): 57 | if i == 0: 58 | assert len(arrays) == 188 59 | expected_pt = [10.763696670532227, 15.736522674560547] 60 | expected_charge = [-1, -1] 61 | assert arrays["Muon_pt"][0].tolist() == expected_pt 62 | assert arrays["Muon_charge"][0].tolist() == expected_charge 63 | elif i in (1, 2, 3, 4): 64 | assert len(arrays) == 188 65 | elif i == 5: 66 | assert len(arrays) == 60 67 | else: 68 | assert False 69 | 70 | Muon_pt = obj["Muon_pt"] 71 | for i, arrays in enumerate(Muon_pt.iterate(step_size=100)): 72 | assert len(arrays) == 100 73 | if i == 0: 74 | expected_pt = [10.763696670532227, 15.736522674560547] 75 | assert arrays["Muon_pt"][0].tolist() == expected_pt 76 | 77 | for i, arrays in enumerate(Muon_pt.iterate(step_size="5 kB")): 78 | if i == 0: 79 | assert len(arrays) == 611 80 | expected_pt = [10.763696670532227, 15.736522674560547] 81 | assert arrays["Muon_pt"][0].tolist() == expected_pt 82 | elif i == 1: 83 | assert len(arrays) == 389 84 | else: 85 | assert False 86 | -------------------------------------------------------------------------------- /tests/test_1254_test_threadpool_executor_for_dask.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import skhep_testdata 3 | 4 | import uproot 5 | 6 | pytest.importorskip("pandas") 7 | 8 | 9 | def test_decompression_threadpool_executor_for_dask(): 10 | 11 | class TestThreadPoolExecutor(uproot.source.futures.ThreadPoolExecutor): 12 | def __init__(self, max_workers=None): 13 | super().__init__(max_workers=max_workers) 14 | self.submit_count = 0 15 | 16 | def submit(self, task, /, *args, **kwargs): 17 | self.submit_count += 1 18 | super().submit(task, *args, **kwargs) 19 | 20 | implicitexecutor = TestThreadPoolExecutor(max_workers=None) 21 | 22 | a = uproot.dask( 23 | {skhep_testdata.data_path("uproot-sample-6.20.04-uncompressed.root"): "sample"}, 24 | decompression_executor=implicitexecutor, 25 | ) 26 | 27 | a["i4"].compute() 28 | 29 | assert implicitexecutor.max_workers > 0 30 | 31 | assert implicitexecutor.submit_count > 0 32 | 33 | explicitexecutor = TestThreadPoolExecutor(max_workers=1) 34 | 35 | b = uproot.dask( 36 | {skhep_testdata.data_path("uproot-sample-6.20.04-uncompressed.root"): "sample"}, 37 | decompression_executor=explicitexecutor, 38 | ) 39 | 40 | b["i4"].compute() 41 | 42 | assert explicitexecutor.max_workers == 1 43 | 44 | assert explicitexecutor.submit_count > 0 45 | -------------------------------------------------------------------------------- /tests/test_1264_write_NumPy_array_of_strings.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import os 6 | import numpy as np 7 | 8 | 9 | def test(tmp_path): 10 | newfile = os.path.join(tmp_path, "example.root") 11 | 12 | with uproot.recreate(newfile) as f: 13 | f["t"] = {"x": np.array(["A", "B"]), "y": np.array([1, 2])} 14 | f["t"].extend({"x": np.array(["A", "B"]), "y": np.array([1, 2])}) 15 | 16 | with uproot.open(newfile) as f: 17 | assert f["t"]["x"].array().tolist() == ["A", "B", "A", "B"] 18 | assert f["t"]["y"].array().tolist() == [1, 2, 1, 2] 19 | -------------------------------------------------------------------------------- /tests/test_1275_fix_TStreamerLoop_code_generation.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import uproot 5 | import skhep_testdata 6 | 7 | 8 | def test_ttime_custom(): 9 | filename = skhep_testdata.data_path("uproot-issue-1275.root") 10 | 11 | with uproot.open(filename) as file: 12 | spline = file["spline"] 13 | 14 | assert spline.member("fPoly")[0].member("fX") == 1.0 15 | assert spline.member("fPoly")[0].member("fY") == 1.0 16 | assert spline.member("fPoly")[0].member("fB") == 2.5 17 | assert spline.member("fPoly")[0].member("fC") == 0.0 18 | assert spline.member("fPoly")[0].member("fD") == 0.5 19 | 20 | assert spline.member("fPoly")[1].member("fX") == 2.0 21 | assert spline.member("fPoly")[1].member("fY") == 4.0 22 | assert spline.member("fPoly")[1].member("fB") == 4.0 23 | assert spline.member("fPoly")[1].member("fC") == 1.5 24 | assert spline.member("fPoly")[1].member("fD") == -0.5 25 | 26 | assert spline.member("fPoly")[2].member("fX") == 3.0 27 | assert spline.member("fPoly")[2].member("fY") == 9.0 28 | assert spline.member("fPoly")[2].member("fB") == 5.5 29 | assert spline.member("fPoly")[2].member("fC") == 1.0 30 | assert spline.member("fPoly")[2].member("fD") == 1.7142857142857144 31 | -------------------------------------------------------------------------------- /tests/test_1282_add_known_forth_for_atlas.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import awkward 4 | import pytest 5 | import skhep_testdata 6 | import uproot 7 | 8 | VECTOR_VECTOR_ELEMENTLINK_BRANCHES = [ 9 | "AnalysisHLT_e12_lhloose_nod0_2mu10AuxDyn.TrigMatchedObjects", 10 | "AnalysisElectronsAuxDyn.caloClusterLinks", 11 | "AnalysisPhotonsAuxDyn.vertexLinks", 12 | "TruthMuonsAuxDyn.childLinks", 13 | "AnalysisElectronsAuxDyn.trackParticleLinks", 14 | "PrimaryVerticesAuxDyn.neutralParticleLinks", 15 | "AnalysisTauJetsAuxDyn.tauTrackLinks", 16 | ] 17 | 18 | 19 | @pytest.mark.parametrize("key", VECTOR_VECTOR_ELEMENTLINK_BRANCHES) 20 | def test_pickup_vector_vector_elementlink(key): 21 | with uproot.open( 22 | {skhep_testdata.data_path("uproot-issue-123a.root"): "CollectionTree"} 23 | ) as tree: 24 | branch = tree[key] 25 | assert branch.interpretation._complete_forth_code is not None 26 | assert branch.interpretation._form is not None 27 | 28 | 29 | def test_consistent_library_np_vector_vector_elementlink(): 30 | arrays_np = {} 31 | with uproot.open( 32 | {skhep_testdata.data_path("uproot-issue-123a.root"): "CollectionTree"} 33 | ) as tree: 34 | for key in VECTOR_VECTOR_ELEMENTLINK_BRANCHES: 35 | arrays_np[key] = tree[key].array(library="np") 36 | arrays_ak = {} 37 | with uproot.open( 38 | {skhep_testdata.data_path("uproot-issue-123a.root"): "CollectionTree"} 39 | ) as tree: 40 | for key in VECTOR_VECTOR_ELEMENTLINK_BRANCHES: 41 | arrays_ak[key] = tree[key].array() 42 | for key in arrays_np: 43 | array_ak = arrays_ak[key] 44 | array_np = uproot.interpretation.library._object_to_awkward_array( 45 | awkward, array_ak.layout.form.to_dict(), arrays_np[key] 46 | ) 47 | for field in array_ak.fields: 48 | assert awkward.all(array_np[field] == array_ak[field]) 49 | -------------------------------------------------------------------------------- /tests/test_1285_rntuple_multicluster_concatenation.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import skhep_testdata 4 | import numpy as np 5 | 6 | import uproot 7 | 8 | 9 | def test_schema_extension(): 10 | filename = skhep_testdata.data_path("test_index_multicluster_rntuple_v1-0-0-0.root") 11 | with uproot.open(filename) as f: 12 | obj = f["ntuple"] 13 | 14 | arrays = obj.arrays() 15 | int_vec_array = arrays["int_vector"] 16 | 17 | for j in range(2): 18 | for i in range(100): 19 | assert int_vec_array[i + j * 100, 0] == i 20 | assert int_vec_array[i + j * 100, 1] == i + j 21 | -------------------------------------------------------------------------------- /tests/test_1318_dont_compare_big_endian_in_awkward.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import pytest 6 | import awkward as ak 7 | 8 | import uproot 9 | 10 | 11 | def test(tmp_path): 12 | filename = os.path.join(tmp_path, "whatever.root") 13 | 14 | nMuon_pt = ak.Array([1, 2, 3]) 15 | Muon_pt = ak.Array([[1.1], [2.2, 3.3], [4.4, 5.5, 6.6]]) 16 | 17 | with uproot.recreate(filename) as file: 18 | file["tree"] = {"nMuon_pt": nMuon_pt, "Muon_pt": Muon_pt} 19 | -------------------------------------------------------------------------------- /tests/test_1321_pandas_changed_api_again.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | import uproot 6 | 7 | pytest.importorskip("pandas") 8 | 9 | 10 | def test(): 11 | assert ( 12 | len( 13 | uproot.concatenate( 14 | skhep_testdata.data_path("uproot-Zmumu.root"), 15 | library="pd", 16 | cut="Run > 148029", 17 | ) 18 | ) 19 | == 1580 20 | ) 21 | -------------------------------------------------------------------------------- /tests/test_1356_basic_rntuple_writing.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import json 4 | import os 5 | import queue 6 | import sys 7 | 8 | import numpy 9 | import pytest 10 | import skhep_testdata 11 | 12 | import uproot 13 | 14 | ak = pytest.importorskip("awkward") 15 | 16 | 17 | def test_flat_arrays(tmp_path): 18 | filepath = os.path.join(tmp_path, "test.root") 19 | 20 | with uproot.recreate(filepath) as file: 21 | data = ak.Array({"one": [1, 2, 3], "two": [1.1, 2.2, 3.3]}) 22 | obj = file.mkrntuple("ntuple", data.layout.form) 23 | obj.extend(data) 24 | 25 | obj = uproot.open(filepath)["ntuple"] 26 | arrays = obj.arrays() 27 | 28 | assert arrays.one.tolist() == data.one.tolist() 29 | assert arrays.two.tolist() == data.two.tolist() 30 | 31 | 32 | def test_flat_arrays_ROOT(tmp_path, capfd): 33 | ROOT = pytest.importorskip("ROOT") 34 | 35 | filepath = os.path.join(tmp_path, "test.root") 36 | 37 | with uproot.recreate(filepath) as file: 38 | data = ak.Array({"one": [1, 2, 3], "two": [1.1, 2.2, 3.3]}) 39 | obj = file.mkrntuple("ntuple", data.layout.form) 40 | obj.extend(data) 41 | 42 | RT = ROOT.Experimental.RNTupleReader.Open("ntuple", filepath) 43 | RT.PrintInfo() 44 | RT.Show(0) 45 | RT.Show(2) 46 | out = capfd.readouterr().out 47 | assert "* N-Tuple : ntuple" in out 48 | assert "* Entries : 3" in out 49 | assert "* Field 1 : one (std::int64_t)" in out 50 | assert "* Field 2 : two (double)" in out 51 | assert ' "one": 1,' in out 52 | assert ' "two": 1.1' in out 53 | assert ' "one": 3' in out 54 | assert ' "two": 3.3' in out 55 | -------------------------------------------------------------------------------- /tests/test_1375_extend_ak_add_doc.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import pytest 4 | import skhep_testdata 5 | 6 | import uproot 7 | 8 | dask = pytest.importorskip("dask") 9 | dask_awkward = pytest.importorskip("dask_awkward") 10 | 11 | file = skhep_testdata.data_path("nanoAOD_2015_CMS_Open_Data_ttbar.root") 12 | tree = "Events" 13 | 14 | to_test = { 15 | "Electron_r9": { 16 | "title": "R9 of the supercluster, calculated with full 5x5 region", 17 | "typename": "float[]", 18 | }, 19 | "luminosityBlock": {"title": "luminosityBlock/i", "typename": "uint32_t"}, 20 | "Tau_jetIdx": { 21 | "title": "index of the associated jet (-1 if none)", 22 | "typename": "int32_t[]", 23 | }, 24 | } 25 | 26 | 27 | @pytest.mark.parametrize("file", [file]) 28 | @pytest.mark.parametrize("tree", [tree]) 29 | @pytest.mark.parametrize("open_files", [True, False]) 30 | @pytest.mark.parametrize( 31 | "ak_add_doc_value", 32 | [ 33 | False, 34 | True, 35 | {"__doc__": "title"}, 36 | {"title": "title"}, 37 | {"typename": "typename"}, 38 | {"__doc__": "title", "typename": "typename"}, 39 | ], 40 | ) 41 | def test_extend_ak_add_doc(file, tree, open_files, ak_add_doc_value): 42 | 43 | events = uproot.dask( 44 | file + ":" + tree, open_files=open_files, ak_add_doc=ak_add_doc_value 45 | ) 46 | for branch_name in to_test.keys(): 47 | if isinstance(ak_add_doc_value, bool): 48 | if ak_add_doc_value: 49 | assert events[branch_name].form.parameters == { 50 | "__doc__": to_test[branch_name]["title"] 51 | } 52 | if isinstance(ak_add_doc_value, dict): 53 | assert events[branch_name].form.parameters == { 54 | key: to_test[branch_name][val] for key, val in ak_add_doc_value.items() 55 | } 56 | -------------------------------------------------------------------------------- /tests/test_1412_rntuple_dask.py: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License; see https://github.com/scikit-hep/uproot5/blob/main/LICENSE 2 | 3 | import os 4 | 5 | import numpy 6 | import pytest 7 | 8 | import uproot 9 | 10 | ak = pytest.importorskip("awkward") 11 | dask = pytest.importorskip("dask") 12 | 13 | data = ak.Array( 14 | { 15 | "ints": [1, 2, 3, 4, 5], 16 | "floats": [1.1, 2.2, 3.3, 4.4, 5.5], 17 | "strings": ["one", "two", "three", "four", "five"], 18 | } 19 | ) 20 | 21 | 22 | def test_dask(tmp_path): 23 | filepath1 = os.path.join(tmp_path, "test1.root") 24 | filepath2 = os.path.join(tmp_path, "test2.root") 25 | 26 | with uproot.recreate(filepath1) as file: 27 | file.mkrntuple("ntuple", data) 28 | 29 | with uproot.recreate(filepath2) as file: 30 | file.mkrntuple("ntuple", data) 31 | 32 | dask_arr = uproot.dask(f"{tmp_path}/test*.root:ntuple") 33 | 34 | arr = dask_arr.compute() 35 | 36 | assert ak.array_equal(arr[:5], data) 37 | assert ak.array_equal(arr[5:], data) 38 | --------------------------------------------------------------------------------