{ "cells": [ { "cell_type": "markdown", "id": "b90791b4", "metadata": {}, "source": [ "# Constructing HEP vectors and analyzing HEP data using Vector\n", "\n", "**Henry Schreiner\\*, Jim Pivarski\\*, and Saransh Chopra+ (speaker)**\n", "\n", "\\*: Princeton University +: Cluster Innovation Centre, University of Delhi" ] }, { "cell_type": "markdown", "id": "508a65da", "metadata": {}, "source": [ "**WARNING**: Not a physicist :(" ] }, { "cell_type": "markdown", "id": "4abfc623", "metadata": {}, "source": [ "## Quick links" ] }, { "cell_type": "markdown", "id": "8955f792", "metadata": {}, "source": [ "- GitHub repository (of vector) - https://github.com/scikit-hep/vector\n", "- Vector's documentation - https://vector.readthedocs.io/\n", "- GitHub repository (of this talk) - https://github.com/Saransh-cpp/PyHEP22-Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector\n", "- Binder (to run the code with us) - https://mybinder.org/v2/gh/Saransh-cpp/PyHEP22-Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector/HEAD?urlpath=lab/tree/talk.ipynb\n", "\n", "\n", "Some parts of this notebook are inspired by [vector's documentation](https://vector.readthedocs.io/en/latest/) and [vector's README](https://github.com/scikit-hep/vector#readme)." ] }, { "cell_type": "markdown", "id": "73c99460", "metadata": {}, "source": [ "## Table of contents" ] }, { "cell_type": "markdown", "id": "aedac1f4", "metadata": {}, "source": [ "1. [Introduction](#Introduction)\n", "2. [Goals](#Goals)\n", "3. [Setup](#Setup)\n", "4. [Pure Python Object vectors](#Pure-Python-Object-vectors)\n", "5. [NumPy vectors](#NumPy-vectors)\n", "6. [Awkward vectors](#Awkward-vectors)\n", "7. [Compiling vectors with Numba](#Compiling-vectors-with-Numba)\n", "8. [Uproot, Awkward, and Vector](#Uproot,-Awkward,-and-Vector)\n", "9. [Recent developments](#Recent-developments)\n", "10. [Near future development plans](#Near-future-development-plans)\n", "11. [Stuck somewhere? Reach out!](#Stuck-somewhere?-Reach-out!)\n", "12. [Cite vector](#Cite-vector)" ] }, { "cell_type": "markdown", "id": "92547b8c", "metadata": {}, "source": [ "## Introduction" ] }, { "cell_type": "markdown", "id": "71a5b83d", "metadata": {}, "source": [ "\n", "\n" ] }, { "cell_type": "markdown", "id": "7c173fe8", "metadata": {}, "source": [ "Vector allows user to create arrays of 2D, 3D, and Lorentz vectors.\n", "\n", "Was created for HEP but is not limited only to HEP!" ] }, { "cell_type": "markdown", "id": "f8819bfd", "metadata": {}, "source": [ "## Goals" ] }, { "cell_type": "markdown", "id": "8a2c16d8", "metadata": {}, "source": [ "This talk will focus on introducing Vector and its backends through a data analysis pipeline. The session will build up from pure Python Object based vectors to Awkward based vectors, ending with a demonstration of Numba support. Furthermore, we will discuss the latest developments in the library's API and showcase some recent enhancements." ] }, { "cell_type": "markdown", "id": "d9eeaf72", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "markdown", "id": "e693cb2a", "metadata": {}, "source": [ "There are two ways to follow along (or run this notebook after the talk) -\n", "\n", "1. Locally\n", "\n", " - Clone [this](https://github.com/Saransh-cpp/PyHEP22-Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector.git) repository -\n", "```bash\n", "git clone https://github.com/Saransh-cpp/PyHEP22-Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector.git\n", "```\n", "\n", " - Change directory\n", "```bash\n", "cd Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector\n", "```\n", "\n", " - Launch the classic Jupyter notebook or Jupyter lab -\n", "```bash\n", "jupyter notebook\n", "# or\n", "jupyter lab\n", "```\n", "\n", "2. On cloud (recommended)\n", "\n", " - Binder (recommended)\n", "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Saransh-cpp/PyHEP22-Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector/HEAD?urlpath=lab/tree/talk.ipynb)\n", "\n", " - Google Colab\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Saransh-cpp/PyHEP22-Constructing-HEP-vectors-and-analyzing-HEP-data-using-Vector/blob/main/talk.ipynb)\n", "\n", "We will be directly importing `vector`, `awkward`, `numpy`, `numba`, `uproot`, `matplotlib`, and `scikit-hep-testdata` in this tutorial. Hence, a user must install these packages if this notebook is being run locally or on Google Colab." ] }, { "cell_type": "code", "execution_count": 1, "id": "1bcc39c5", "metadata": {}, "outputs": [], "source": [ "# install dependencies (use Python 3.6+)\n", "# !pip install -r binder/requirements.txt\n", "\n", "import vector" ] }, { "cell_type": "markdown", "id": "00590b2d", "metadata": {}, "source": [ "## Pure Python Object vectors" ] }, { "cell_type": "markdown", "id": "a7e11f7d", "metadata": {}, "source": [ "### Generic vectors\n", "\n", "One can create `Object` type vectors using the `obj` constructor or using the -\n", "\n", "- VectorObject2D.from_xy()\n", "- VectorObject2D.from_rhophi()\n", "- VectorObject3D.from_xyz()\n", "- VectorObject3D.from_xytheta()\n", "- VectorObject3D.from_xyeta()\n", "- VectorObject3D.from_rhophiz()\n", "- ...\n", "- VectorObject4D.from_xyzt()\n", "- VectorObject4D.from_xythetat()\n", "- ...\n", "\n", "class methods.\n", "\n", "Right now a user cannot do `vector.VectorObject2D(x=1, y=2)`." ] }, { "cell_type": "code", "execution_count": 2, "id": "a541c933", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(vector.obj(x=1, y=2), vector.obj(x=1, y=2, z=3))" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v1 = vector.obj(x=1, y=2)\n", "v2 = vector.obj(x=1, y=2, z=3)\n", "\n", "v1, v2" ] }, { "cell_type": "code", "execution_count": 3, "id": "31baaa4d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(vector.obj(x=1, y=2), vector.obj(x=1, y=2, theta=3, t=4))" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v1 = vector.VectorObject2D.from_xy(1, 2)\n", "v2 = vector.VectorObject4D.from_xythetat(1, 2, 3, 4)\n", "\n", "v1, v2" ] }, { "cell_type": "markdown", "id": "f3416d03", "metadata": {}, "source": [ "### Momentum vectors\n", "\n", "The `obj` constructor has momentum overloads, which allow users to create momentum vectors using the same syntax!" ] }, { "cell_type": "code", "execution_count": 4, "id": "d3f46745", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(vector.obj(px=1, py=2), vector.obj(px=1, py=2, pz=3, mass=4))" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vm1 = vector.obj(px=1, py=2) #\n", "vm2 = vector.obj(px=1, py=2, pz=3, m=4)\n", "\n", "vm1, vm2" ] }, { "cell_type": "markdown", "id": "463562f3", "metadata": {}, "source": [ "### Inheritance and super classes" ] }, { "cell_type": "code", "execution_count": 5, "id": "3e0c50ca", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " image/svg+xml\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " Azimuthal\n", " Longitudinal\n", " Temporal\n", " AzimuthalXY\n", " AzimuthalRhoPhi\n", " TemporalT\n", " TemporalTau\n", " Planar\n", " Spatial\n", " Lorentz\n", " AzimuthalObject\n", " LongitudinalObject\n", " TemporalObject\n", " AzimuthalObjectXY\n", " AzimuthalObjectRhoPhi\n", " LongitudinalObjectZ\n", " LongitudinalObjectTheta\n", " LongitudinalObjectEta\n", " TemporalObjectT\n", " TemporalObjectTau\n", " MomentumObject4D\n", " \n", " \n", " \n", " \n", " \n", " Vector\n", " Vector3D\n", " \n", " \n", " Vector2D\n", " Vector4D\n", " \n", " Coordinates\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " VectorObject4D\n", " \n", " \n", " VectorObject3D\n", " MomentumObject3D\n", " \n", " \n", " \n", " \n", " VectorObject2D\n", " MomentumObject2D\n", " \n", " \n", " user interface methods\n", " \n", " mix-in class or superclass\n", " \n", " has data members\n", " \n", " \n", " \n", " class inheritance\n", " \n", " \n", " \n", " \n", " CoordinatesObject\n", " \n", " \n", " \n", " \n", " \n", " LongitudinalZ\n", " LongitudinalTheta\n", " LongitudinalEta\n", " \n", " \n", " VectorObject\n", " \n", " contains object as member\n", " "Object" is one backend.For other backends, replacewith "Numpy", "Awkward", etc.\n", " \n", " contains azimuthal, longitudinal, and temporal\n", " \n", " contains azimuthal\n", " \n", " contains azimuthal and longitudinal\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " Generic vector mix-insreduce objects to numbersand call a flat-function inthe "compute" modulecorresponding to itscoordinate system.\n", " Momentum mix-insprovide synonymsfor a momentuminterpretation(e.g. "rho" → "pt","tau" → "mass").\n", " \n", " Momentum\n", " \n", " \n", " \n", " PlanarMomentum\n", " SpatialMomentum\n", " LorentzMomentum\n", " \n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import SVG, display\n", "\n", "display(SVG(\"./assets/inheritance.svg\"))\n", "\n", "# better here - https://github.com/scikit-hep/vector/blob/main/docs/api/inheritance.svg" ] }, { "cell_type": "code", "execution_count": 6, "id": "b452184d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(vector.backends.object.VectorObject2D,\n", " vector.backends.object.VectorObject3D,\n", " vector.backends.object.VectorObject4D)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec2D = vector.obj(x=1., y=2.)\n", "vec3D = vector.obj(x=1., y=2., z=3.)\n", "vec4D = vector.obj(x=1., y=2., z=3. , tau=4.)\n", "\n", "type(vec2D), type(vec3D), type(vec4D)" ] }, { "cell_type": "markdown", "id": "2f883b0d", "metadata": {}, "source": [ "- All vector classes are the subclass of `Vector`.\n", "- Every backend has its own `VectorD` classes, which is a subclass of `Vector`.\n", "- All `2D` vector classes are a subclass of `Vector2D`, and so on ..." ] }, { "cell_type": "code", "execution_count": 7, "id": "de542c9b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(vec2D, (vector.Vector, vector.Vector2D, vector.VectorObject, vector.VectorObject2D)) # back to the inheritance svg" ] }, { "cell_type": "markdown", "id": "88e58ab4", "metadata": {}, "source": [ "Additionally, vector classes are also a subclass of `Planar`, `Spatial`, and/or `Temporal`." ] }, { "cell_type": "code", "execution_count": 8, "id": "ff019c73", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(True, False, True)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "isinstance(vec3D, vector.Planar), isinstance(vec2D, vector.Spatial), isinstance(vec4D, vector.Lorentz) # back to the inheritance svg" ] }, { "cell_type": "markdown", "id": "a7cfb60a", "metadata": {}, "source": [ "Similarly for `MomentumVectors` -" ] }, { "cell_type": "code", "execution_count": 9, "id": "82ffd0cf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vecm = vector.obj(px=1., py=2., pz=3., E=4.)\n", "isinstance(\n", " vecm, \n", " (\n", " vector.Momentum,\n", " vector.MomentumObject2D,\n", " vector.Vector,\n", " vector.Vector2D,\n", " vector.VectorObject2D,\n", " vector.Planar,\n", " vector.Spatial,\n", " vector.Temporal,\n", " )\n", ")" ] }, { "cell_type": "markdown", "id": "5794e376", "metadata": {}, "source": [ "And `Azimuthal`, `Longitudinal`, `Temporal` classes -" ] }, { "cell_type": "code", "execution_count": 10, "id": "2145e6e6", "metadata": {}, "outputs": [], "source": [ "vec4D = vector.obj(x=1., y=2., z=3., tau=4.)\n", "\n", "assert isinstance(\n", " vec4D.azimuthal,\n", " (\n", " vector.Azimuthal,\n", " vector.AzimuthalXY,\n", " vector.backends.object.AzimuthalObject,\n", " vector.backends.object.AzimuthalObjectXY,\n", " )\n", ")\n", "\n", "assert isinstance(\n", " vec4D.longitudinal,\n", " (\n", " vector.Longitudinal,\n", " vector.LongitudinalZ,\n", " vector.backends.object.LongitudinalObject,\n", " vector.backends.object.LongitudinalObjectZ,\n", " )\n", ")\n", "\n", "assert isinstance(\n", " vec4D.temporal,\n", " (\n", " vector.Temporal,\n", " vector.TemporalTau,\n", " vector.backends.object.TemporalObject,\n", " vector.backends.object.TemporalObjectTau,\n", " )\n", ")" ] }, { "cell_type": "markdown", "id": "7133ccfd", "metadata": {}, "source": [ "### Methods and properties" ] }, { "cell_type": "markdown", "id": "26a5bb24", "metadata": {}, "source": [ "`Vector` comes loaded with numerous methods and properties which are flowed down using inheritance or are directly defined in the child class.\n", "\n", "- `x`, `y`, `z`, `t`, `rho`, `phi`, ...\n", "\n", "- `add`, `subtract`, `cross`, `dot`, `equal`, ...\n", "\n", "- `to_xyz`, `to_xyzt`, `to_rhophithetatau`, ..., `to_Vector2D` `to_Vector3D`, ...\n", "\n", "- `azimuthal`, `longitudinal`, `temporal`\n", "\n", "- `costheta`, `cottheta`\n", "\n", "- `deltaangle`, `deltaphi`, `deltaeta`, `deltaR`, `deltaR2`\n", "\n", "- ..." ] }, { "cell_type": "code", "execution_count": 11, "id": "c72380a5", "metadata": {}, "outputs": [], "source": [ "vec3D = vector.obj(x=1., y=3., z=3.)" ] }, { "cell_type": "markdown", "id": "c6b47124", "metadata": {}, "source": [ "A great way to go through these methods and properties is to press TAB!\n", "\n", "An even greater way is to go through the documentation!\n", "\n", "A complete list of vector properties and methods is available here - https://github.com/scikit-hep/vector#vector-properties " ] }, { "cell_type": "code", "execution_count": null, "id": "b32c2a59", "metadata": {}, "outputs": [], "source": [ "vec3D." ] }, { "cell_type": "markdown", "id": "3e247405", "metadata": {}, "source": [ "Let's say we want to gather the azimuthal coordinates. We will start by obtaining the `Azimuthal` object -" ] }, { "cell_type": "code", "execution_count": 12, "id": "fac5cfa2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "AzimuthalObjectXY(x=1.0, y=3.0)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec3D.azimuthal" ] }, { "cell_type": "markdown", "id": "639cfd8d", "metadata": {}, "source": [ "Next, let's quickly go through the docs of `AzimuthalObjectXY." ] }, { "cell_type": "code", "execution_count": 13, "id": "1a156ea5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[1;31mInit signature:\u001b[0m\n", "\u001b[0mvector\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbackends\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mAzimuthalObjectXY\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m\n", "\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mForwardRef\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'float'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\n", "\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mForwardRef\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'float'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\n", "\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mDocstring:\u001b[0m \n", "Class for the ``x`` and ``y`` (azimuthal) coordinates of Object backend.\n", "Use the ``elements`` property to retrieve the coordinates.\n", "\u001b[1;31mFile:\u001b[0m c:\\users\\saransh\\saransh_softwares\\python_3.9\\lib\\site-packages\\vector\\backends\\object.py\n", "\u001b[1;31mType:\u001b[0m type\n", "\u001b[1;31mSubclasses:\u001b[0m \n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "?vector.backends.object.AzimuthalObjectXY" ] }, { "cell_type": "markdown", "id": "52810982", "metadata": {}, "source": [ "Now we know that we can use the `elements` property to access the coordinates!" ] }, { "cell_type": "code", "execution_count": 14, "id": "c73b1145", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1.0, 3.0)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec3D.azimuthal.elements" ] }, { "cell_type": "markdown", "id": "990f9a8b", "metadata": {}, "source": [ "### Allowed coordinate combinations" ] }, { "cell_type": "markdown", "id": "7899b656", "metadata": { "jupyter": { "source_hidden": true } }, "source": [ "The allowed keyword arguments for 2D vectors are:\n", "\n", "- `x` and `y` for Cartesian azimuthal coordinates,\n", "- `px` and `py` for momentum,\n", "- `rho` and `phi` for polar azimuthal coordinates,\n", "- `pt` and `phi` for momentum.\n", "\n", "For 3D vectors, you need the above and:\n", "\n", "- `z` for the Cartesian longitudinal coordinate,\n", "- `pz` for momentum,\n", "- `theta` for the spherical polar angle (from $0$ to $\\pi$, inclusive),\n", "- `eta` for pseudorapidity, which is a kind of spherical polar angle.\n", "\n", "For 4D vectors, you need the above and:\n", "\n", "- `t` for the Cartesian temporal coordinate,\n", "- `E` or `energy` to get four-momentum,\n", "- `tau` for the \"proper time\" (temporal coordinate in the vector's rest coordinate system),\n", "- `M` or `mass` to get four-momentum.\n", "\n", "All possible combinations (replace with momentum coordinates for momentum vectors)\n", "\n", "- (2D) `x` `y`\n", "- (2D) `rho` `phi`\n", "- (3D) `x` `y` `z`\n", "- (3D) `x` `y` `theta`\n", "- (3D) `x` `y` `eta`\n", "- (3D) `rho` `phi` `z`\n", "- (3D) `rho` `phi` `theta`\n", "- (3D) `rho` `phi` `eta`\n", "- (4D) `x` `y` `z` `t`\n", "- (4D) `x` `y` `z` `tau`\n", "- (4D) `x` `y` `theta` `t`\n", "- (4D) `x` `y` `theta` `tau`\n", "- (4D) `x` `y` `eta` `t`\n", "- (4D) `x` `y` `eta` `tau`\n", "- (4D) `rho` `phi` `z` `t`\n", "- (4D) `rho` `phi` `z` `tau`\n", "- (4D) `rho` `phi` `theta` `t`\n", "- (4D) `rho` `phi` `theta` `tau`\n", "- (4D) `rho` `phi` `eta` `t`\n", "- (4D) `rho` `phi` `eta` `tau`" ] }, { "cell_type": "markdown", "id": "1e377c95", "metadata": {}, "source": [ "## NumPy vectors" ] }, { "cell_type": "markdown", "id": "7014c1dc", "metadata": {}, "source": [ "`Vector` provides `vector.VectorNumpyXD` classes and `vector.array`constructor to construct `NumPy` vectors. The `VectorNumpyXD` classes are subclasses of `NumPy` array; hence they behave a lot like a structured `NumPy` array.\n", "\n", "Currently, vector only accepts structured `NumPy` arrays to construct vectors. The `NumPy` dtype of a structured array is `object`; hence, these arrays are not as fast as the conventional `NumPy` arrays. " ] }, { "cell_type": "code", "execution_count": 15, "id": "dc29cfc2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "VectorNumpy2D([(1., 2.), (3., 4.), (5., 6.), (7., 8.), (9., 10.)],\n", " dtype=[('x', '" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec = vector.awk(\n", " [\n", " [{\"x\": 1, \"y\": 1.1, \"z\": 0.1}, {\"x\": 2, \"y\": 2.2, \"z\": 0.2}],\n", " [],\n", " [{\"x\": 3, \"y\": 3.3, \"z\": 0.3}],\n", " ]\n", ")\n", "\n", "vec" ] }, { "cell_type": "code", "execution_count": 23, "id": "5da7568a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec = vector.zip({\"x\": [1, 2 ,3], \"y\": [1, 2, 3], \"z\": [1, 2, 3]})\n", "\n", "vec" ] }, { "cell_type": "markdown", "id": "ff31ddd6", "metadata": {}, "source": [ "Similar to `NumPy` and `Object` vectors, `Awkward` vectors can also access the vector properties.\n", "\n", "Note: An array of vectors returns an array of coordinates, and an awkward vector returns an awkward array of coordinates." ] }, { "cell_type": "code", "execution_count": 24, "id": "67c58684", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "AzimuthalAwkwardXY(, )" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec.azimuthal" ] }, { "cell_type": "code", "execution_count": 25, "id": "493ab762", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vec.x" ] }, { "cell_type": "markdown", "id": "c6e0c4bc", "metadata": {}, "source": [ "If you want any records named `Vector2D`, `Vector3D`, `Vector4D`, `Momentum2D`, `Momentum3D`, or `Momentum4D` to be interpreted as vectors, register the behaviors globally." ] }, { "cell_type": "code", "execution_count": 26, "id": "54ee56cb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import awkward as ak\n", "\n", "vector.register_awkward()\n", "\n", "ak.Array(\n", " [\n", " [{\"x\": 1, \"y\": 1.1, \"z\": 0.1}, {\"x\": 2, \"y\": 2.2, \"z\": 0.2}],\n", " [],\n", " [{\"x\": 3, \"y\": 3.3, \"z\": 0.3}],\n", " ],\n", " with_name=\"Vector3D\",\n", ")" ] }, { "cell_type": "markdown", "id": "3300f321", "metadata": {}, "source": [ "Momentum vectors work in the same way!" ] }, { "cell_type": "code", "execution_count": 27, "id": "0cb6e79a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vector.awk(\n", " [\n", " [{\"px\": 1, \"py\": 1.1, \"pz\": 0.1}, {\"px\": 2, \"py\": 2.2, \"pz\": 0.2}],\n", " [],\n", " [{\"px\": 3, \"py\": 3.3, \"pz\": 0.3}],\n", " ]\n", ")" ] }, { "cell_type": "markdown", "id": "083955f4", "metadata": {}, "source": [ "## Compiling vectors with Numba" ] }, { "cell_type": "markdown", "id": "36ff1cd5", "metadata": {}, "source": [ "Vector also comes loaded with `Numba-X` backends. `VectorObject`s and `VectorArray`s are currently compatible with `numba`, and `VectorNumpy` will be supported in the near future." ] }, { "cell_type": "code", "execution_count": 28, "id": "cf26d2e6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "8.0" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numba as nb\n", "\n", "\n", "@nb.njit\n", "def compute_mass(v1, v2):\n", " return (v1 + v2).mass\n", "\n", "\n", "compute_mass(vector.obj(px=1, py=2, pz=3, E=4), vector.obj(px=-1, py=-2, pz=-3, E=4))" ] }, { "cell_type": "markdown", "id": "f159c0a7", "metadata": {}, "source": [ "When the two `MomentumObject4D` objects are passed as arguments, Numba recognizes them and replaces the Python objects with low-level structs. When it compiles the function, it recognizes `+` as the 4D `add` function and recognizes `.mass` as the `tau` component of the result.\n", "\n", "Although this demonstrates that Numba can manipulate vector objects, there is no performance advantage (and a likely disadvantage) to compiling a calculation on just a few vectors. The advantage comes when many vectors are involved, in arrays." ] }, { "cell_type": "code", "execution_count": 29, "id": "d962a977", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(50,\n", " [{'px': 0.6501824294426782,\n", " 'py': -0.6763097011423066,\n", " 'pz': -0.10716060951861181,\n", " 'E': 10.92861653343253}])" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "coords = [\n", " [\n", " dict(\n", " {x: np.random.normal(0, 1) for x in (\"px\", \"py\", \"pz\")},\n", " E=np.random.normal(10, 1),\n", " ) for inner in range(np.random.poisson(1.5))\n", " ] for outer in range(50)\n", "]\n", "\n", "len(coords), coords[1]" ] }, { "cell_type": "code", "execution_count": 30, "id": "2bb79111", "metadata": {}, "outputs": [], "source": [ "array = vector.awk(coords)" ] }, { "cell_type": "code", "execution_count": 31, "id": "4f8a4d00", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(,\n", " ['x', 'y', 'z', 't'],\n", " 50 * var * Momentum4D[\"x\": float64, \"y\": float64, \"z\": float64, \"t\": float64])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "array, array.fields, array.type" ] }, { "cell_type": "code", "execution_count": 32, "id": "33a8dec2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([16.16043497, 10.88774742, 10.11909472, 0. , 0. ,\n", " 10.31790599, 10.05422508, 0. , 0. , 0. ,\n", " 0. , 19.39307991, 11.05160406, 8.67221218, 0. ,\n", " 18.35532653, 0. , 8.65994383, 0. , 19.544993 ,\n", " 19.78412696, 0. , 0. , 21.59229741, 9.87505309,\n", " 20.21759048, 7.82107001, 9.11730401, 0. , 32.34473786,\n", " 10.10019886, 0. , 19.50920867, 0. , 0. ,\n", " 22.42470467, 0. , 19.99439773, 38.99501039, 21.81337545,\n", " 11.39558804, 31.2216409 , 0. , 0. , 35.87434787,\n", " 10.06254703, 17.35314601, 28.31359567, 0. , 0. ])" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@nb.njit\n", "def compute_masses(array):\n", " out = np.empty(len(array), np.float64)\n", " for i, event in enumerate(array):\n", " total = vector.obj(px=0.0, py=0.0, pz=0.0, E=0.0)\n", " for vec in event:\n", " total = total + vec\n", " out[i] = total.mass\n", " return out\n", "\n", "\n", "compute_masses(array)" ] }, { "cell_type": "markdown", "id": "245be057", "metadata": {}, "source": [ "## Uproot, Awkward, and Vector" ] }, { "cell_type": "markdown", "id": "70cb7def", "metadata": {}, "source": [ "Let us look at how vector integrates with the rest of the HEP ecosystem! We'll start by reading a root file using `uproot`, look at its content using `awkward`, and perform some data analysis using `vector`!\n", "\n", "Let's read a data file from `scikit-hep-testdata` -" ] }, { "cell_type": "code", "execution_count": 33, "id": "bf160389", "metadata": {}, "outputs": [], "source": [ "import skhep_testdata\n", "import uproot\n", "\n", "data = uproot.open(skhep_testdata.data_path(\"uproot-HZZ.root\"))" ] }, { "cell_type": "markdown", "id": "fa46bb0d", "metadata": {}, "source": [ "Looking at the keys of the retrieved data -" ] }, { "cell_type": "code", "execution_count": 34, "id": "ad9e40f9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['events;1']" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.keys()" ] }, { "cell_type": "markdown", "id": "ed9ef54c", "metadata": {}, "source": [ "We can now extract the `TTree` using the 'Events' key -" ] }, { "cell_type": "code", "execution_count": 35, "id": "70d41d2f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree = data['events']\n", "\n", "tree" ] }, { "cell_type": "markdown", "id": "22490da9", "metadata": {}, "source": [ "Now we can extract the actual data in the form of `awkward` arrays.\n", "\n", "`Awkward` arrays are jagged arrays which are required to manipulate HEP data. `Awkward` smoothly integrates with other HEP packages, like `uproot` and `vector` which we will be seeing ahead. Additionally, `awkward` is fast; hence `Awkward` is to jagged arrays the same way `NumPy` is to regular arrays!\n", "\n", "\"Arrays are dynamically typed, but operations on them are compiled and fast. Their behavior coincides with NumPy when array dimensions are regular and generalizes when they're not.\"" ] }, { "cell_type": "code", "execution_count": 36, "id": "9f05f66b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "branches = tree.arrays() #\n", "\n", "branches # awkward array" ] }, { "cell_type": "markdown", "id": "2646e138", "metadata": {}, "source": [ "As the data is now present in the form of `awkward` arrays, we can use the properties and methods provided by `awkward`. For instance, using the `fields` property to extract the fields - " ] }, { "cell_type": "code", "execution_count": 37, "id": "f99dcde1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['NJet',\n", " 'Jet_Px',\n", " 'Jet_Py',\n", " 'Jet_Pz',\n", " 'Jet_E',\n", " 'Jet_btag',\n", " 'Jet_ID',\n", " 'NMuon',\n", " 'Muon_Px',\n", " 'Muon_Py',\n", " 'Muon_Pz',\n", " 'Muon_E',\n", " 'Muon_Charge',\n", " 'Muon_Iso',\n", " 'NElectron',\n", " 'Electron_Px',\n", " 'Electron_Py',\n", " 'Electron_Pz',\n", " 'Electron_E',\n", " 'Electron_Charge',\n", " 'Electron_Iso',\n", " 'NPhoton',\n", " 'Photon_Px',\n", " 'Photon_Py',\n", " 'Photon_Pz',\n", " 'Photon_E',\n", " 'Photon_Iso',\n", " 'MET_px',\n", " 'MET_py',\n", " 'MChadronicBottom_px',\n", " 'MChadronicBottom_py',\n", " 'MChadronicBottom_pz',\n", " 'MCleptonicBottom_px',\n", " 'MCleptonicBottom_py',\n", " 'MCleptonicBottom_pz',\n", " 'MChadronicWDecayQuark_px',\n", " 'MChadronicWDecayQuark_py',\n", " 'MChadronicWDecayQuark_pz',\n", " 'MChadronicWDecayQuarkBar_px',\n", " 'MChadronicWDecayQuarkBar_py',\n", " 'MChadronicWDecayQuarkBar_pz',\n", " 'MClepton_px',\n", " 'MClepton_py',\n", " 'MClepton_pz',\n", " 'MCleptonPDGid',\n", " 'MCneutrino_px',\n", " 'MCneutrino_py',\n", " 'MCneutrino_pz',\n", " 'NPrimaryVertices',\n", " 'triggerIsoMu24',\n", " 'EventWeight']" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "branches.fields" ] }, { "cell_type": "markdown", "id": "ec4ffebf", "metadata": {}, "source": [ "Every field corresponds to an `awkward` array too -" ] }, { "cell_type": "code", "execution_count": 38, "id": "837501db", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "branches.Muon_Px" ] }, { "cell_type": "markdown", "id": "595830dd", "metadata": {}, "source": [ "Let's construct a vector using the \"Muon\" fields. Again, `vector` provides the `vector.zip` constructor for this task, and this constructor behaves similar to the `awkward.zip` constructor!" ] }, { "cell_type": "code", "execution_count": 39, "id": "3aa31cc0", "metadata": {}, "outputs": [], "source": [ "muons = vector.zip( #\n", " {\n", " 'px': branches['Muon_Px'],\n", " 'py': branches['Muon_Py'],\n", " 'pz': branches['Muon_Pz'],\n", " 'E': branches['Muon_E']\n", " }\n", ")" ] }, { "cell_type": "markdown", "id": "f18ce999", "metadata": {}, "source": [ "We now have a `MomentumArray4D` vector!\n", "\n", "Remember, `VectorArray` classes inherit `awkward.Array`, which means we can use `awkward.Array`'s properties on it. Checking the type and fields -" ] }, { "cell_type": "code", "execution_count": 40, "id": "dcd375bd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons" ] }, { "cell_type": "code", "execution_count": 41, "id": "3cf37371", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2421 * var * Momentum4D[\"x\": float32, \"y\": float32, \"z\": float32, \"t\": float32]" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.type" ] }, { "cell_type": "code", "execution_count": 42, "id": "4a05e78f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['x', 'y', 'z', 't']" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.fields" ] }, { "cell_type": "markdown", "id": "22686b8f", "metadata": {}, "source": [ "`2421 * var * Momentum4D` here shows that we have `2421` lists of `Momentum4D` vectors with each list having a variable length." ] }, { "cell_type": "markdown", "id": "23a38ba3", "metadata": {}, "source": [ "We can also use the methods and properties (discussed above) offered by vector. Let's say we want the `azimuthal` coordinates of the created vector -" ] }, { "cell_type": "code", "execution_count": 43, "id": "13ed8044", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "AzimuthalAwkwardXY(, )" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.azimuthal" ] }, { "cell_type": "code", "execution_count": 44, "id": "b6e8ab9d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(,\n", " )" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.azimuthal.elements" ] }, { "cell_type": "markdown", "id": "acc13364", "metadata": {}, "source": [ "Similarly for other coordinate types -" ] }, { "cell_type": "markdown", "id": "52695775", "metadata": {}, "source": [ "Similarly, we can use vector methods on this `MomentumArray`. For instance, let's say we want to convert this vector's coordinates to `rho`, `phi`, **`theta`**, and **`tau`**. Just to be a 100% sure, let's also check the fields -" ] }, { "cell_type": "code", "execution_count": 45, "id": "7d4c5ece", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.to_rhophithetatau()" ] }, { "cell_type": "code", "execution_count": 46, "id": "f911ccac", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['rho', 'phi', 'theta', 'tau']" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.to_rhophithetatau().fields" ] }, { "cell_type": "markdown", "id": "3d9afbfa", "metadata": {}, "source": [ "We can also use other such methods, for example, `to_Vector2D` converts N dimensional vector to a 2D vector. Again, we can check the fields -" ] }, { "cell_type": "code", "execution_count": 47, "id": "bb3f44d5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.to_Vector2D()" ] }, { "cell_type": "code", "execution_count": 48, "id": "5e9a04b2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['x', 'y']" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons.to_Vector2D().fields" ] }, { "cell_type": "markdown", "id": "a7b73d68", "metadata": {}, "source": [ "We can also slice these lists using the regular `Python` syntax -" ] }, { "cell_type": "code", "execution_count": 49, "id": "c8eba1f9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "99 * var * Momentum4D[\"x\": float32, \"y\": float32, \"z\": float32, \"t\": float32]" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons[1:100].type" ] }, { "cell_type": "markdown", "id": "63547a90", "metadata": {}, "source": [ "Remember how these lists are of variable length (indicated by `* var`). Let's verify this quickly -" ] }, { "cell_type": "code", "execution_count": 50, "id": "faa2c70e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2)" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(muons[1]), len(muons[2])" ] }, { "cell_type": "markdown", "id": "5e4c6841", "metadata": {}, "source": [ "We could have also checked this using `awkward`'s `type` -" ] }, { "cell_type": "code", "execution_count": 51, "id": "b202d861", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1 * Momentum4D[\"x\": float32, \"y\": float32, \"z\": float32, \"t\": float32],\n", " 2 * Momentum4D[\"x\": float32, \"y\": float32, \"z\": float32, \"t\": float32])" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons[1].type, muons[2].type" ] }, { "cell_type": "markdown", "id": "0bc6f242", "metadata": {}, "source": [ "And as usual, these lists are also iterable -" ] }, { "cell_type": "code", "execution_count": 52, "id": "e6b983a0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muons[1][0]" ] }, { "cell_type": "markdown", "id": "a780d548", "metadata": {}, "source": [ "Note: the first list had only 1 element; hence, an index of `>0` should throw an error -" ] }, { "cell_type": "code", "execution_count": 53, "id": "2f625ddb", "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "in RecordArray attempting to get 1, index out of range\n\n(https://github.com/scikit-hep/awkward-1.0/blob/1.9.0/src/libawkward/array/RecordArray.cpp#L792)", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn [53], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mmuons\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\n", "File \u001b[1;32mc:\\users\\saransh\\saransh_softwares\\python_3.9\\lib\\site-packages\\awkward\\highlevel.py:991\u001b[0m, in \u001b[0;36mArray.__getitem__\u001b[1;34m(self, where)\u001b[0m\n\u001b[0;32m 579\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 580\u001b[0m \u001b[38;5;124;03mArgs:\u001b[39;00m\n\u001b[0;32m 581\u001b[0m \u001b[38;5;124;03m where (many types supported; see below): Index of positions to\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 988\u001b[0m \u001b[38;5;124;03mhave the same dimension as the array being indexed.\u001b[39;00m\n\u001b[0;32m 989\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 990\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_tracers\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m--> 991\u001b[0m tmp \u001b[38;5;241m=\u001b[39m ak\u001b[38;5;241m.\u001b[39m_util\u001b[38;5;241m.\u001b[39mwrap(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlayout\u001b[49m\u001b[43m[\u001b[49m\u001b[43mwhere\u001b[49m\u001b[43m]\u001b[49m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_behavior)\n\u001b[0;32m 992\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 993\u001b[0m tmp \u001b[38;5;241m=\u001b[39m ak\u001b[38;5;241m.\u001b[39m_connect\u001b[38;5;241m.\u001b[39m_jax\u001b[38;5;241m.\u001b[39mjax_utils\u001b[38;5;241m.\u001b[39m_jaxtracers_getitem(\u001b[38;5;28mself\u001b[39m, where)\n", "\u001b[1;31mValueError\u001b[0m: in RecordArray attempting to get 1, index out of range\n\n(https://github.com/scikit-hep/awkward-1.0/blob/1.9.0/src/libawkward/array/RecordArray.cpp#L792)" ] } ], "source": [ "muons[1][1]" ] }, { "cell_type": "markdown", "id": "94567414", "metadata": {}, "source": [ "Let us create a mask which will select all the events with 2 muons -" ] }, { "cell_type": "code", "execution_count": 54, "id": "863d37b6", "metadata": {}, "outputs": [], "source": [ "mask = ak.num(muons) == 2 #" ] }, { "cell_type": "markdown", "id": "73a298ff", "metadata": {}, "source": [ "ak.num?" ] }, { "cell_type": "code", "execution_count": 55, "id": "75ced873", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[1;31mSignature:\u001b[0m \u001b[0mak\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnum\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mhighlevel\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbehavior\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mDocstring:\u001b[0m\n", "Args:\n", " array: Data containing nested lists to count.\n", " axis (int): The dimension at which this operation is applied. The\n", " outermost dimension is `0`, followed by `1`, etc., and negative\n", " values count backward from the innermost: `-1` is the innermost\n", " dimension, `-2` is the next level up, etc.\n", " highlevel (bool): If True, return an #ak.Array; otherwise, return\n", " a low-level #ak.layout.Content subclass.\n", " behavior (None or dict): Custom #ak.behavior for the output array, if\n", " high-level.\n", "\n", "Returns an array of integers specifying the number of elements at a\n", "particular level.\n", "\n", "For instance, given the following doubly nested `array`,\n", "\n", " ak.Array([[\n", " [1.1, 2.2, 3.3],\n", " [],\n", " [4.4, 5.5],\n", " [6.6]\n", " ],\n", " [],\n", " [\n", " [7.7],\n", " [8.8, 9.9]]\n", " ])\n", "\n", "The number of elements in `axis=1` is\n", "\n", " >>> ak.num(array, axis=1)\n", " \n", "\n", "and the number of elements at the next level down, `axis=2`, is\n", "\n", " >>> ak.num(array, axis=2)\n", " \n", "\n", "The `axis=0` case is special: it returns a scalar, the length of the array.\n", "\n", " >>> ak.num(array, axis=0)\n", " 3\n", "\n", "This function is useful for ensuring that slices do not raise errors. For\n", "instance, suppose that we want to select the first element from each\n", "of the outermost nested lists of `array`. One of these lists is empty, so\n", "selecting the first element (`0`) would raise an error. However, if our\n", "first selection is `ak.num(array) > 0`, we are left with only those lists\n", "that *do* have a first element:\n", "\n", " >>> array[ak.num(array) > 0, 0]\n", " \n", "\n", "To keep a placeholder (None) in each place we do not want to select,\n", "consider using #ak.mask instead of a #ak.Array.__getitem__.\n", "\n", " >>> ak.mask(array, ak.num(array) > 0)[:, 0]\n", " \n", "\u001b[1;31mFile:\u001b[0m c:\\users\\saransh\\saransh_softwares\\python_3.9\\lib\\site-packages\\awkward\\operations\\structure.py\n", "\u001b[1;31mType:\u001b[0m function\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "?ak.num" ] }, { "cell_type": "markdown", "id": "fe0f082e", "metadata": {}, "source": [ "We can now obtain a momentum vector of these 2 muon events -" ] }, { "cell_type": "code", "execution_count": 56, "id": "d1d3067b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "two_muons = muons[mask]\n", "\n", "two_muons" ] }, { "cell_type": "code", "execution_count": 57, "id": "9bd90c0b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(,\n", " )" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "muon1 = two_muons[:, 0]\n", "muon2 = two_muons[:, 1]\n", "\n", "muon1, muon2" ] }, { "cell_type": "markdown", "id": "cf97add5", "metadata": {}, "source": [ "Using `deltaR` from `vector` -" ] }, { "cell_type": "code", "execution_count": 58, "id": "c0692ec4", "metadata": {}, "outputs": [], "source": [ "dR = muon1.deltaR(muon2)" ] }, { "cell_type": "code", "execution_count": 59, "id": "bf8ac620", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "plt.hist(dR, bins=50)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "1ae63294", "metadata": {}, "source": [ "## Recent developments" ] }, { "cell_type": "markdown", "id": "ce1c5e53", "metadata": {}, "source": [ "Vector [`v0.9.0`](https://github.com/scikit-hep/vector/releases/tag/v0.9.0) is out!\n", "- Features: improved reprs, deltaRapidityPhi, backends are public now, …\n", "- Documentation: major documentation overhaul, doctests, CITATION.cff, …\n", "- Bug fixes: type checks, fix nan_to_num, …\n", "- Maintenance: hatchling backend, support awkward._v2 in tests, build and test on Python 3.10 and 3.11-dev, …\n", "\n", "More about `v0.9.0` here - https://vector.readthedocs.io/en/latest/changelog.html#version-0-9 \n", "\n", "---\n", "\n", "Vector [`v0.10.0`](https://github.com/scikit-hep/vector/releases/tag/v0.10.0) is out too!\n", "- Removed support for Python 3.6\n", "\n", "More about `v0.10.0` here - https://vector.readthedocs.io/en/latest/changelog.html#version-0-10 " ] }, { "cell_type": "markdown", "id": "617a1439", "metadata": {}, "source": [ "## Near future development plans" ] }, { "cell_type": "markdown", "id": "ca69aee7", "metadata": {}, "source": [ "- Better constructors (under work)\n", "- A benchmarking suite\n", "- Benchmarks against Root\n", "- A complete `awkward` `v2` support (scheduled for December)\n", "- NumPy-Numba backend\n", "- Other potential backends - CuPy, TensorFlow, Torch, JAX...\n", "\n", "Vector was scheduled to have a major release (`v1.0.0`) before `PyHEP 2022`, but that was unfortunately delayed. A major release can be expected in October, which would primarily be introducing new constructors.\n", "\n", "Open for user feedback and discussions!" ] }, { "cell_type": "markdown", "id": "378cf909", "metadata": {}, "source": [ "## Stuck somewhere? Reach out!" ] }, { "cell_type": "markdown", "id": "31246241", "metadata": {}, "source": [ "- If something is not working the way it should, or if you want to request a new feature, create a [new issue](https://github.com/scikit-hep/vector/issues) on GitHub.\n", "- To discuss something related to vector, use the [discussions](https://github.com/scikit-hep/vector/discussions/) tab on GitHub or vector’s gitter ([Scikit-HEP/vector](https://gitter.im/Scikit-HEP/vector)) chat room.\n", "- Have a look at vector's [changelog](https://vector.readthedocs.io/en/latest/#changes-in-vector-s-api) to stay up-to-date!" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.0" } }, "nbformat": 4, "nbformat_minor": 5 }