diff --git a/01-nanoevents.ipynb b/01-nanoevents.ipynb index ce7f023..996286d 100644 --- a/01-nanoevents.ipynb +++ b/01-nanoevents.ipynb @@ -8,7 +8,7 @@ "\n", "This is a rendered copy of [nanoevents.ipynb](https://github.com/CoffeaTeam/coffea/blob/master/binder/nanoevents.ipynb). You can optionally run it interactively on [binder at this link](https://mybinder.org/v2/gh/coffeateam/coffea/master?filepath=binder%2Fnanoevents.ipynb)\n", "\n", - "NanoEvents is a Coffea utility to wrap flat nTuple structures (such as the CMS [NanoAOD](https://www.epj-conferences.org/articles/epjconf/pdf/2019/19/epjconf_chep2018_06021.pdf) format) into a single awkward array with appropriate object methods (such as Lorentz vector methods$^*$), cross references, and nested objects, all lazily accessed$^\\dagger$ from the source ROOT TTree via uproot. The interpretation of the TTree data is configurable via [schema objects](https://coffeateam.github.io/coffea/modules/coffea.nanoevents.html#classes), which are community-supplied for various source file types. These schema objects allow a richer interpretation of the file contents than the [uproot.lazy](https://uproot4.readthedocs.io/en/latest/uproot4.behaviors.TBranch.lazy.html) methods. Currently available schemas include:\n", + "NanoEvents is a Coffea utility to wrap flat nTuple structures (such as the CMS [NanoAOD](https://www.epj-conferences.org/articles/epjconf/pdf/2019/19/epjconf_chep2018_06021.pdf) format) into a single awkward array with appropriate object methods (such as Lorentz vector methods$^*$), cross references, and nested objects, all accessed in delayed$^\\dagger$ mode from the source ROOT TTree via uproot. The interpretation of the TTree data is configurable via [schema objects](https://coffeateam.github.io/coffea/modules/coffea.nanoevents.html#classes), which are community-supplied for various source file types. These schema objects allow a richer interpretation of the file contents than the [uproot.dask](https://uproot.readthedocs.io/en/latest/uproot._dask.dask.html) methods. Currently available schemas include:\n", "\n", " - `BaseSchema`, which provides a simple representation of the input TTree, where each branch is available verbatim as `events.branch_name`, effectively the same behavior as `uproot.lazy`. Any branches that uproot supports at \"full speed\" (i.e. that are fully split and either flat or single-jagged) can be read by this schema;\n", " - `NanoAODSchema`, which is optimized to provide all methods and cross-references in CMS NanoAOD format;\n", @@ -21,7 +21,7 @@ "\n", "$^*$ Vector methods are currently made possible via the [coffea vector](https://coffeateam.github.io/coffea/modules/coffea.nanoevents.methods.vector.html) methods mixin class structure. In a future version of coffea, they will instead be provided by the dedicated scikit-hep [vector](https://vector.readthedocs.io/en/latest/) library, which provides a more rich feature set. The coffea vector methods predate the release of the vector library.\n", "\n", - "$^\\dagger$ _Lazy_ access refers to only fetching the needed data from the (possibly remote) file when a sub-array is first accessed. The sub-array is then _materialized_ and subsequent access of the sub-array uses a cached value in memory. As such, fully materializing a `NanoEvents` object may require a significant amount of memory.\n", + "$^\\dagger$ _delayed_ access refers to only fetching the needed data from the (possibly remote) file when you're ready to compute the entire set of outputs. Until then, a minimal amount of metadata is used to trace the operations to eventually be performed (frequently called \"lazily\" \"booking\" operations in RDataFrame's approach to this)\n", "\n", "\n", "In this demo, we will use NanoEvents to read a small CMS NanoAOD sample. The events object can be instantiated as follows:" @@ -30,7 +30,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "import awkward as ak\n", @@ -38,9 +40,10 @@ "\n", "fname = \"https://raw.githubusercontent.com/CoffeaTeam/coffea/master/tests/samples/nano_dy.root\"\n", "events = NanoEventsFactory.from_root(\n", - " fname,\n", + " {fname: \"Events\"}, # We pass a dictionary of {filename1: treename1, filename2: treename2, ...} to load from\n", " schemaclass=NanoAODSchema.v6,\n", " metadata={\"dataset\": \"DYJets\"},\n", + " delayed=False, # You can turn this to True and insert `` commands at the end of variables\n", ").events()" ] }, @@ -68,7 +71,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.Generator.id1" @@ -77,7 +82,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# all names can be listed with:\n", @@ -103,7 +110,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.Generator.id1?" @@ -119,7 +128,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.GenJet.fields" @@ -135,7 +146,20 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "events.GenJet.energy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.GenJet.energy" @@ -151,7 +175,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# find distance between leading jet and all electrons in each event\n", @@ -162,17 +188,22 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# find minimum distance\n", - "ak.min(dr, axis=1)" + "drmin = ak.min(dr, axis=1)\n", + "drmin" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# a convenience method for this operation on all jets is available\n", @@ -191,7 +222,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(events.Jet.jetId)\n", @@ -208,7 +241,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(f\"Raw status flags: {events.GenPart.statusFlags}\")\n", @@ -225,7 +260,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.Electron.matched_gen.pdgId" @@ -234,7 +271,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.Muon[ak.num(events.Muon)>0].matched_jet.pt" @@ -250,7 +289,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.GenPart.parent.pdgId" @@ -266,7 +307,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.GenPart.parent.children.pdgId\n", @@ -283,7 +326,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "events.GenPart[\n", @@ -302,18 +347,22 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "mmevents = events[ak.num(events.Muon) == 2]\n", - "zmm = mmevents.Muon[:, 0] + mmevents.Muon[:, 1]\n", + "zmm = (mmevents.Muon[:, 0] + mmevents.Muon[:, 1])\n", "zmm.mass" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# a convenience method is available to sum vectors along an axis:\n", @@ -322,7 +371,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [] + }, "source": [ "As expected for this sample, most of the dimuon events have a pair invariant mass close to that of a Z boson. But what about the last event? Let's take a look at the generator information:" ] @@ -330,7 +381,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(mmevents[-1].Muon.matched_gen.pdgId)\n", @@ -349,7 +402,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "mmevents[-1].Muon.matched_gen.parent.pdgId" @@ -365,7 +420,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(mmevents.Muon.matched_gen.sum().mass[-1])\n", @@ -386,12 +443,73 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "mmevents[\"Electron\", \"myvariable\"] = mmevents.Electron.pt + zmm.mass\n", "mmevents.Electron.myvariable" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import dask\n", + "\n", + "# We'll use the latest dask_capable schema to load the same events in delayed (dask) mode\n", + "NanoAODSchema.warn_missing_crossrefs=False\n", + "\n", + "fname = \"https://raw.githubusercontent.com/CoffeaTeam/coffea/master/tests/samples/nano_dy.root\"\n", + "devents = NanoEventsFactory.from_root(\n", + " {fname: \"Events\"},\n", + " schemaclass=NanoAODSchema, #we'll not use the v6 schema here\n", + " metadata={\"dataset\": \"DYJets\"},\n", + " delayed=True,\n", + ").events()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "devents.Jet.nearest(devents.Electron)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "a, b = dask.compute(devents.Jet.jetId, devents.Jet.isTight)\n", + "print(a)\n", + "print(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dmmevents = devents[ak.num(devents.Muon) == 2]\n", + "dzmm = (dmmevents.Muon[:, 0] + dmmevents.Muon[:, 1]).compute() # we insert the compute on the intermediate array\n", + "zmm.mass" + ] } ], "metadata": { @@ -410,9 +528,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.10.12" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/02-applying_corrections.ipynb b/02-applying_corrections.ipynb index 7227f44..9ddd4f1 100644 --- a/02-applying_corrections.ipynb +++ b/02-applying_corrections.ipynb @@ -8,9 +8,9 @@ "\n", "Here we will show how to apply corrections to columnar data using:\n", "\n", - "- the `coffea.lookup_tools` package, which is designed to read in ROOT histograms and a variety of data file formats popular within CMS into a standardized lookup table format;\n", - "- CMS-specific extensions to the above, for jet corrections (`coffea.jetmet_tools`) and b-tagging efficiencies/uncertainties (`coffea.btag_tools`);\n", - "- the [correctionlib](https://cms-nanoaod.github.io/correctionlib/) package, which provides a experiment-agnostic serializable data format for common correction functions." + "- the `coffea.lookup_tools` package, which was designed to read in ROOT histograms and a variety of data file formats popular within CMS into a standardized lookup table format; \n", + "- CMS-specific extensions to the above, for jet corrections (`coffea.jetmet_tools`) and b-tagging efficiencies/uncertainties (`coffea.btag_tools`); while some subtools have been deprecated in favor of correctionlib, you may still come across older formats until everyone has fully transitioned.\n", + "- the [correctionlib](https://cms-nanoaod.github.io/correctionlib/) package, which provides an experiment-agnostic serializable data format for common correction functions. This format is the preferred format moving forward, as CMS has standardized on this." ] }, { @@ -24,7 +24,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "import awkward as ak\n", @@ -32,9 +34,10 @@ "\n", "fname = \"https://raw.githubusercontent.com/CoffeaTeam/coffea/master/tests/samples/nano_dy.root\"\n", "events = NanoEventsFactory.from_root(\n", - " fname,\n", + " {fname: \"Events\"},\n", " schemaclass=NanoAODSchema.v6,\n", " metadata={\"dataset\": \"DYJets\"},\n", + " delayed=False,\n", ").events()" ] }, @@ -50,7 +53,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.lookup_tools import extractor" @@ -59,7 +64,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "%%bash\n", @@ -86,7 +93,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "ext = extractor()\n", @@ -106,7 +115,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(\"Electron eta:\", events.Electron.eta)\n", @@ -126,7 +137,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "import numpy as np\n", @@ -166,7 +179,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.lookup_tools.dense_lookup import dense_lookup\n", @@ -197,7 +212,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "ptvals = np.random.exponential(scale=10.0, size=10000) + np.random.exponential(scale=15.0, size=10000)\n", @@ -236,7 +253,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.jetmet_tools import FactorizedJetCorrector, JetCorrectionUncertainty\n", @@ -276,7 +295,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "name_map = jec_stack.blank_name_map\n", @@ -296,7 +317,7 @@ "name_map['massRaw'] = 'mass_raw'\n", "name_map['Rho'] = 'rho'\n", " \n", - "events_cache = events.caches[0]\n", + "# events_cache = events.caches[0] # for coffea 0.7\n", "corrector = FactorizedJetCorrector(\n", " Fall17_17Nov2017_V32_MC_L2Relative_AK4PFPuppi=evaluator['Fall17_17Nov2017_V32_MC_L2Relative_AK4PFPuppi'],\n", ")\n", @@ -305,7 +326,8 @@ ")\n", "\n", "jet_factory = CorrectedJetsFactory(name_map, jec_stack)\n", - "corrected_jets = jet_factory.build(jets, lazy_cache=events_cache)\n", + "corrected_jets = jet_factory.build(jets)\n", + "#corrected_jets = jet_factory.build(jets, lazy_cache=events_cache)\n", "\n", "print('starting columns:', set(ak.fields(jets)))\n", "print('new columns:', set(ak.fields(corrected_jets)) - set(ak.fields(jets)))" @@ -318,20 +340,30 @@ "Below we show that the corrected jets indeed have a different $p_T$ and mass than we started with" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Transition Note\n", + "The JEC tools will daskify inputs, such that even if your inputs are loaded into memory (non-delayed), the outputs will be in delayed mode. As such, you'll need to explicitly call compute on them, as done below, to see the results." + ] + }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print('untransformed pt ratios', jets.pt/jets.pt_raw)\n", "print('untransformed mass ratios', jets.mass/jets.mass_raw)\n", "\n", - "print('transformed pt ratios', corrected_jets.pt/corrected_jets.pt_raw)\n", - "print('transformed mass ratios', corrected_jets.mass/corrected_jets.mass_raw)\n", + "print('transformed pt ratios', (corrected_jets.pt/corrected_jets.pt_raw).compute())\n", + "print('transformed mass ratios', (corrected_jets.mass/corrected_jets.mass_raw).compute())\n", "\n", - "print('JES UP pt ratio', corrected_jets.JES_jes.up.pt/corrected_jets.pt_raw)\n", - "print('JES DOWN pt ratio', corrected_jets.JES_jes.down.pt/corrected_jets.pt_raw)" + "print('JES UP pt ratio', (corrected_jets.JES_jes.up.pt/corrected_jets.pt_raw).compute())\n", + "print('JES DOWN pt ratio', (corrected_jets.JES_jes.down.pt/corrected_jets.pt_raw).compute())" ] }, { @@ -345,7 +377,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.btag_tools import BTagScaleFactor\n", @@ -370,7 +404,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "scrolled": false + "tags": [] }, "outputs": [], "source": [ @@ -406,7 +440,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "ceval = cset.to_evaluator()\n", @@ -418,19 +454,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "At the time of writing, correctionlib does not support jagged arrays. But we can work around this using awkward utilities `flatten` and `unflatten`, as shown below" + "The latest version `2.5.0` of correctionnlib supports dask arrays more seamlessly, which will not be demonstrated here (as the current environment's version is slightly behind)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "def myJetSF(jets):\n", - " j, nj = ak.flatten(jets), ak.num(jets)\n", - " sf = ceval[\"gen2_to_gen1\"].evaluate(np.array(j.pt), np.array(j.eta))\n", - " return ak.unflatten(sf, nj)\n", + " # Older correctionlib did not handle jagged arrays\\\n", + " # the solution for flattening and unflattening is left commented below\n", + " #j, nj = ak.flatten(jets), ak.num(jets)\n", + " #sf = ceval[\"gen2_to_gen1\"].evaluate(np.array(j.pt), np.array(j.eta))\n", + " #return ak.unflatten(sf, nj)\n", + " return ceval[\"gen2_to_gen1\"].evaluate(jets.pt, jets.eta)\n", "\n", "myJetSF(events.Jet)" ] @@ -452,9 +493,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.10.12" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/03-accumulators.ipynb b/03-analysis-tools.ipynb similarity index 58% rename from 03-accumulators.ipynb rename to 03-analysis-tools.ipynb index 25a0bb7..304ff97 100644 --- a/03-accumulators.ipynb +++ b/03-analysis-tools.ipynb @@ -4,11 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Analysis tools and accumulators\n", + "# Analysis tools\n", "\n", - "This is a rendered copy of [accumulators.ipynb](https://github.com/CoffeaTeam/coffea/blob/master/binder/accumulators.ipynb). You can optionally run it interactively on [binder at this link](https://mybinder.org/v2/gh/coffeateam/coffea/master?filepath=binder%2Faccumulators.ipynb)\n", - "\n", - "Now that we know how to access data with NanoEvents and apply corrections, let's go through some useful columnar analysis tools and idioms for building _accumulators_, namely, the eventual output of a coffea processor that has natural \"merge\" semantics. The most familiar type of accumulator is the histogram, but other types are useful in certain contexts.\n", + "Now that we know how to access data with NanoEvents and apply corrections, let's go through some useful columnar analysis tools and idioms for building collections of results, namely, the eventual output of a coffea callable (or processor). The most familiar type of output may be the histogram (one type of accumulator).\n", "\n", "We'll use our small sample file to demonstrate the utilities, although it won't be very interesting to analyze" ] @@ -16,18 +14,47 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "import numpy as np\n", "import awkward as ak\n", + "import dask\n", + "from hist.dask import Hist\n", "from coffea.nanoevents import NanoEventsFactory, NanoAODSchema\n", "\n", + "NanoAODSchema.warn_missing_crossrefs = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "delayed=False\n", + "if delayed:\n", + " this_schema = NanoAODSchema\n", + "else:\n", + " this_schema = NanoAODSchema.v6" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "fname = \"https://raw.githubusercontent.com/CoffeaTeam/coffea/master/tests/samples/nano_dy.root\"\n", "events = NanoEventsFactory.from_root(\n", - " fname,\n", - " schemaclass=NanoAODSchema.v6,\n", + " {fname: \"Events\"},\n", + " schemaclass=this_schema,\n", " metadata={\"dataset\": \"DYJets\"},\n", + " delayed=delayed,\n", ").events()" ] }, @@ -41,7 +68,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.lookup_tools import extractor\n", @@ -65,19 +94,24 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.analysis_tools import Weights\n", "\n", - "weights = Weights(len(events))\n", + "if delayed:\n", + " weights = Weights(None, storeIndividual=False)\n", + "else:\n", + " weights = Weights(len(events), storeIndividual=False)\n", "\n", "weights.add(\"genWeight\", events.genWeight)\n", "\n", "weights.add(\n", " \"alphaS\",\n", " # in NanoAOD, the generator weights are already stored with respect to nominal\n", - " weight=np.ones(len(events)),\n", + " weight=ak.ones_like(events.run),\n", " # 31 => alphas(MZ)=0.1165 central value; 32 => alphas(MZ)=0.1195\n", " # per https://lhapdfsets.web.cern.ch/current/PDF4LHC15_nnlo_30_pdfas/PDF4LHC15_nnlo_30_pdfas.info\n", " # which was found by looking up the LHA ID in events.LHEPdfWeight.__doc__\n", @@ -106,7 +140,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "weights.weightStatistics" @@ -122,7 +158,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "weights.weight()" @@ -138,7 +176,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "weights.weight(\"eleSFUp\")" @@ -154,7 +194,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "weights.variations" @@ -174,20 +216,22 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "from coffea.analysis_tools import PackedSelection\n", "\n", "selection = PackedSelection()\n", "\n", - "selection.add(\"twoElectron\", ak.num(events.Electron) == 2)\n", + "selection.add(\"twoElectron\", ak.num(events.Electron, axis=1) == 2)\n", "selection.add(\"eleOppSign\", ak.sum(events.Electron.charge, axis=1) == 0)\n", - "selection.add(\"noElectron\", ak.num(events.Electron) == 0)\n", + "selection.add(\"noElectron\", ak.num(events.Electron, axis=1) == 0)\n", "\n", - "selection.add(\"twoMuon\", ak.num(events.Muon) == 2)\n", + "selection.add(\"twoMuon\", ak.num(events.Muon, axis=1) == 2)\n", "selection.add(\"muOppSign\", ak.sum(events.Muon.charge, axis=1) == 0)\n", - "selection.add(\"noMuon\", ak.num(events.Muon) == 0)\n", + "selection.add(\"noMuon\", ak.num(events.Muon, axis=1) == 0)\n", "\n", "\n", "selection.add(\n", @@ -209,7 +253,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "selection.all(\"twoElectron\", \"noMuon\", \"leadPt20\")" @@ -225,7 +271,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "selection.require(twoElectron=True, noMuon=True, eleOppSign=False)" @@ -241,57 +289,61 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "allCuts = {\"twoElectron\", \"noMuon\", \"leadPt20\"}\n", + "results = {}\n", "for cut in allCuts:\n", - " nev = selection.all(*(allCuts - {cut})).sum()\n", - " print(f\"Events passing all cuts, ignoring {cut}: {nev}\")\n", + " nev = ak.sum(selection.all(*(allCuts - {cut})), axis=0)\n", + " results[cut] = nev\n", + " \n", + "results[\"None\"] = ak.sum(selection.all(*allCuts), axis=0)\n", + "\n", + "c_results, *_ = dask.compute(results)\n", "\n", - "nev = selection.all(*allCuts).sum()\n", - "print(f\"Events passing all cuts: {nev}\")" + "for cut, nev in c_results.items():\n", + " print(f\"Events passing all cuts, ignoring {cut}: {nev}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Accumulator semantics\n", - "\n", - "Prior to coffea 0.7.2, accumulators were more explicit in that they inherited from [AccumulatorABC](https://coffeateam.github.io/coffea/api/coffea.processor.AccumulatorABC.html). Such accumulators are still supported, but now the requirements for an acuumulator output of a processor have been relaxed to the protocol:\n", - "```python\n", - "class Addable(Protocol):\n", - " def __add__(self: T, other: T) -> T:\n", - " ...\n", + "### Builtin Cutflows and N-1\n", + "In CalVer coffea, special [Cutflow](https://coffeateam.github.io/coffea/api/coffea.analysis_tools.Cutflow.html#coffea.analysis_tools.Cutflow) and [NMinus](https://coffeateam.github.io/coffea/api/coffea.analysis_tools.NminusOne.html#coffea.analysis_tools.NminusOne) classes exist to help streamline your code, and they can be extracted from the PackedSelection objects you instantiate.\n", "\n", - "\n", - "Accumulatable = Union[Addable, MutableSet, MutableMapping]\n", - "```\n", - "\n", - "Essentially, any item that can be added, any set, or any dictionary of the above, can be used as an accumulator:" + "#### Cutflows\n", + "Available methods include `result`, `to_npz` (to save cutflow), `yieldhist` (to create a histogram of the cutflow instead of list of events) and `plot_vars` (which permits passing a dictionary of variables, histogram configuration, and creating a cutflow plot of the intended variable)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "from coffea.processor import accumulate\n", - "\n", - "accumulate([\n", - " {\"num\": 0, \"val\": 3.1},\n", - " {\"num\": 2, \"val\": 4.0, \"thing\": {\"a\", \"b\"}},\n", - " {\"num\": 2, \"val\": 4.0, \"thing\": {\"a\", \"c\"}},\n", - "])" + "cutflow = selection.cutflow(*allCuts)\n", + "hcf = cutflow.yieldhist()" ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], "source": [ - "Since `hist` histograms are addable, they can be used as well:" + "from matplotlib import pyplot as plt\n", + "fig, ax = plt.subplots()\n", + "hcf[1].plot(label=\"sequential\")\n", + "hcf[0].plot(label=\"individual\")\n", + "ax.legend()" ] }, { @@ -300,17 +352,7 @@ "metadata": {}, "outputs": [], "source": [ - "import hist\n", - "\n", - "def makehist():\n", - " return hist.Hist.new.Reg(10, 0, 1).Double()\n", - "\n", - "h = accumulate([\n", - " makehist().fill([0.1, 0.1, 0.3]),\n", - " makehist().fill([0.1, 0.3, 0.5]),\n", - "])\n", - "print(h.values())\n", - "h" + "cutflow" ] }, { @@ -319,81 +361,133 @@ "source": [ "### Bringing it together\n", "\n", - "Let's build an output accumulator that stores, per dataset:\n", + "Let's build a callable function that books a few results, per dataset:\n", " - the sum of weights for the events processed, to use for later luminosity-normalizing the yields;\n", " - a histogram of the dilepton invariant mass, with category axes for various selection regions of interest and systematics; and\n", " - the weight statistics, for debugging purposes\n", + "And, additionally, we'll switch to delayed mode and compute the results with an explicit call through dask's interface\n", " " ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "regions = {\n", - " \"ee\": {\"twoElectron\": True, \"noMuon\": True, \"leadPt20\": True, \"eleOppSign\": True},\n", - " \"eeSS\": {\"twoElectron\": True, \"noMuon\": True, \"leadPt20\": True, \"eleOppSign\": False},\n", - " \"mm\": {\"twoMuon\": True, \"noElectron\": True, \"leadPt20\": True, \"muOppSign\": True},\n", - " \"mmSS\": {\"twoMuon\": True, \"noElectron\": True, \"leadPt20\": True, \"muOppSign\": False},\n", - "}\n", + "fname = \"https://raw.githubusercontent.com/CoffeaTeam/coffea/master/tests/samples/nano_dy.root\"\n", + "devents = NanoEventsFactory.from_root(\n", + " {fname: \"Events\"},\n", + " schemaclass=NanoAODSchema,\n", + " metadata={\"dataset\": \"DYJets\"},\n", + " delayed=True,\n", + ").events()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def results_tg(events):\n", "\n", - "masshist = (\n", - " hist.Hist.new\n", - " .StrCat(regions.keys(), name=\"region\")\n", - " .StrCat([\"nominal\"] + list(weights.variations), name=\"systematic\")\n", - " .Reg(60, 60, 120, name=\"mass\", label=\"$m_{ll}$ [GeV]\")\n", - " .Weight()\n", - ")\n", + " regions = {\n", + " \"ee\": {\"twoElectron\": True, \"noMuon\": True, \"leadPt20\": True, \"eleOppSign\": True},\n", + " \"eeSS\": {\"twoElectron\": True, \"noMuon\": True, \"leadPt20\": True, \"eleOppSign\": False},\n", + " \"mm\": {\"twoMuon\": True, \"noElectron\": True, \"leadPt20\": True, \"muOppSign\": True},\n", + " \"mmSS\": {\"twoMuon\": True, \"noElectron\": True, \"leadPt20\": True, \"muOppSign\": False},\n", + " }\n", "\n", - "for region, cuts in regions.items():\n", - " goodevent = selection.require(**cuts)\n", + " masshist = (\n", + " Hist.new\n", + " .StrCat(regions.keys(), name=\"region\")\n", + " .StrCat([\"nominal\"] + list(weights.variations), name=\"systematic\")\n", + " .Reg(60, 60, 120, name=\"mass\", label=\"$m_{ll}$ [GeV]\")\n", + " .Weight()\n", + " )\n", "\n", - " if region.startswith(\"ee\"):\n", - " mass = events.Electron[goodevent].sum().mass\n", - " elif region.startswith(\"mm\"):\n", - " mass = events.Muon[goodevent].sum().mass\n", + " for region, cuts in regions.items():\n", + " goodevent = selection.require(**cuts)\n", + "\n", + " if region.startswith(\"ee\"):\n", + " leptons = events.Electron[goodevent]\n", + " elif region.startswith(\"mm\"):\n", + " leptons = events.Muon[goodevent]\n", + " lep1 = leptons[:, 0]\n", + " lep2 = leptons[:, 1]\n", + " mass = (lep1 + lep2).mass\n", "\n", - " masshist.fill(\n", - " region=region,\n", - " systematic=\"nominal\",\n", - " mass=mass,\n", - " weight=weights.weight()[goodevent],\n", - " )\n", - " for syst in weights.variations:\n", " masshist.fill(\n", " region=region,\n", - " systematic=syst,\n", + " systematic=\"nominal\",\n", " mass=mass,\n", - " weight=weights.weight(syst)[goodevent],\n", + " weight=weights.weight()[goodevent],\n", " )\n", - "\n", - "out = {\n", - " events.metadata[\"dataset\"]: {\n", - " \"sumw\": ak.sum(events.genWeight),\n", - " \"mass\": masshist,\n", - " \"weightStats\": weights.weightStatistics,\n", + " for syst in weights.variations:\n", + " masshist.fill(\n", + " region=region,\n", + " systematic=syst,\n", + " mass=mass,\n", + " weight=weights.weight(syst)[goodevent],\n", + " )\n", + "\n", + " out = {\n", + " events.metadata[\"dataset\"]: {\n", + " \"sumw\": ak.sum(events.genWeight, axis=0),\n", + " \"mass\": masshist,\n", + " \"weightStats\": weights.weightStatistics,\n", + " }\n", " }\n", - "}\n", - "\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "out = results_tg(devents)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ "out" ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], "source": [ - "The cell below demonstrates that indeed this output is accumulatable. So if we were to return such a result from a coffea processor, we would be all ready to process thousands of files!" + "c_out, *_ = dask.compute(out)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "accumulate([out, out])" + "c_out" ] }, { @@ -406,10 +500,12 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "out[\"DYJets\"][\"mass\"][sum, \"nominal\", :]" + "c_out[\"DYJets\"][\"mass\"][sum, \"nominal\", :]" ] } ], @@ -429,9 +525,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.10.12" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/04-processing.ipynb b/04-processing.ipynb new file mode 100644 index 0000000..346f8af --- /dev/null +++ b/04-processing.ipynb @@ -0,0 +1,483 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Coffea Processors\n", + "Coffea relies mainly on [uproot](https://github.com/scikit-hep/uproot) to provide access to ROOT files for analysis.\n", + "As a usual analysis will involve processing tens to thousands of files, totalling gigabytes to terabytes of data, there is a certain amount of work to be done to build a parallelized framework to process the data in a reasonable amount of time. \n", + "\n", + "In coffea up to 0.7 (SemVer), a `coffea.processor` module was provided to encapsulate the core functionality of the analysis, which could be run locally or distributed via a number of Executors. This allowed users to worry just about the actual analysis code and not about how to implement efficient parallelization, assuming that the parallization is a trivial map-reduce operation (e.g. filling histograms and adding them together).\n", + "\n", + "In coffa 2024 (CalVer), integration with `dask` is deeper (via `dask_awkward` and `uproot.dask`), and whether an analysis is to be executed on local or distributed resources, a TaskGraph encapsulating the analysis is created (with a bypass functionality for an eager version still possible when the scale of your input data is sufficiently small). We will demonstrate how to use callable code to build these TGs. \n", + "\n", + "(Sidenote: with some adaptations for the new version of scikit-hep/coffea, a SemVer coffea processor module's `process` function can serve as the callable function - we will follow this model for convenience as we are transitioning from SemVer to CalVer coffea)\n", + "\n", + "\n", + "Let's start by writing a simple processor class that reads some CMS open data and plots a dimuon mass spectrum.\n", + "We'll start by copying the [ProcessorABC](https://coffeateam.github.io/coffea/api/coffea.processor.ProcessorABC.html#coffea.processor.ProcessorABC) skeleton and filling in some details:\n", + "\n", + " * Remove `flag`, as we won't use it\n", + " * Adding a new histogram for $m_{\\mu \\mu}$\n", + " * Building a [Candidate](https://coffeateam.github.io/coffea/api/coffea.nanoevents.methods.candidate.PtEtaPhiMCandidate.html#coffea.nanoevents.methods.candidate.PtEtaPhiMCandidate) record for muons, since we will read it with `BaseSchema` interpretation (the files used here could be read with `NanoAODSchema` but we want to show how to build vector objects from other TTree formats) \n", + " * Calculating the dimuon invariant mass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import awkward as ak\n", + "from coffea import processor\n", + "from coffea.nanoevents.methods import candidate\n", + "import hist\n", + "import dask\n", + "from hist.dask import Hist\n", + "\n", + "class MyProcessor(processor.ProcessorABC):\n", + " def __init__(self):\n", + " pass\n", + "\n", + " def process(self, events):\n", + " dataset = events.metadata['dataset']\n", + " muons = ak.zip(\n", + " {\n", + " \"pt\": events.Muon_pt,\n", + " \"eta\": events.Muon_eta,\n", + " \"phi\": events.Muon_phi,\n", + " \"mass\": events.Muon_mass,\n", + " \"charge\": events.Muon_charge,\n", + " },\n", + " with_name=\"PtEtaPhiMCandidate\",\n", + " behavior=candidate.behavior,\n", + " )\n", + "\n", + " h_mass = (\n", + " Hist.new\n", + " .StrCat([\"opposite\", \"same\"], name=\"sign\")\n", + " .Log(1000, 0.2, 200., name=\"mass\", label=\"$m_{\\mu\\mu}$ [GeV]\")\n", + " .Int64()\n", + " )\n", + "\n", + " cut = (ak.num(muons) == 2) & (ak.sum(muons.charge, axis=1) == 0)\n", + " # add first and second muon in every event together\n", + " dimuon = muons[cut][:, 0] + muons[cut][:, 1]\n", + " h_mass.fill(sign=\"opposite\", mass=dimuon.mass)\n", + "\n", + " cut = (ak.num(muons) == 2) & (ak.sum(muons.charge, axis=1) != 0)\n", + " dimuon = muons[cut][:, 0] + muons[cut][:, 1]\n", + " h_mass.fill(sign=\"same\", mass=dimuon.mass)\n", + "\n", + " return {\n", + " \"entries\": ak.num(events, axis=0),\n", + " \"mass\": h_mass,\n", + " }\n", + " \n", + " def postprocess(self, accumulator):\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we were to just use bare uproot to execute this processor, we could do that with the following example, which:\n", + "\n", + " * Opens a CMS open data file\n", + " * Creates a NanoEvents object using `BaseSchema` (roughly equivalent to the output of `uproot.lazy`)\n", + " * Creates a `MyProcessor` instance\n", + " * Runs the `process()` function, which returns our accumulators\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import uproot\n", + "from coffea.nanoevents import NanoEventsFactory, BaseSchema\n", + "\n", + "filename = \"root://xcache//store/user/ncsmith/opendata_mirror/Run2012B_DoubleMuParked.root\"\n", + "#file = uproot.open(filename)\n", + "events = NanoEventsFactory.from_root(\n", + " {filename: \"Events\"},\n", + " entry_stop=10000,\n", + " metadata={\"dataset\": \"DoubleMuon\"},\n", + " schemaclass=BaseSchema,\n", + " delayed=True,\n", + ").events()\n", + "p = MyProcessor()\n", + "taskgraph = p.process(events)\n", + "taskgraph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dask.visualize(taskgraph['mass'], optimize_graph=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dask.visualize(taskgraph['mass'], optimize_graph=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "out, *_ = dask.compute(taskgraph)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "fig, ax = plt.subplots()\n", + "out[\"mass\"].plot1d(ax=ax)\n", + "ax.set_xscale(\"log\")\n", + "ax.legend(title=\"Dimuon charge\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Filesets\n", + "We'll need to construct a fileset to run over\n", + "\n", + "## Users without access\n", + "Uncomment the `eospublic` files in the following dictionary and comment out the `xcache` files, such that you still have one file per dataset (`DoubleMuon` and `ZZ to 4mu`), these should be reachable from anywhere" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "initial_fileset = {\n", + " \"DoubleMuon\": {\n", + " \"files\": {\n", + " \"root://xcache//store/user/ncsmith/opendata_mirror/Run2012B_DoubleMuParked.root\": \"Events\",\n", + " #\"root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/Run2012B_DoubleMuParked.root\": \"Events\",\n", + " },\n", + " \"metadata\": {\n", + " \"is_mc\": False,\n", + " },\n", + " },\n", + " \"ZZ to 4mu\": {\n", + " \"files\": {\n", + " \"root://xcache//store/user/ncsmith/opendata_mirror/ZZTo4mu.root\": \"Events\",\n", + " #\"root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/ZZTo4mu.root\": \"Events\",\n", + " },\n", + " \"metadata\": {\n", + " \"is_mc\": True,\n", + " }\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Preprocessing\n", + "There are dataset discovery tools inside of coffea to help construct such datasets. Those will not be demonstrated here. For now, we'll take the above `initial_fileset` and preprocess it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from coffea.dataset_tools import apply_to_fileset, max_chunks, max_files, preprocess" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "preprocessed_available, preprocessed_total = preprocess(\n", + " initial_fileset,\n", + " step_size=100_000,\n", + " align_clusters=None,\n", + " skip_bad_files=True,\n", + " recalculate_steps=False,\n", + " files_per_batch=1,\n", + " file_exceptions=(OSError,),\n", + " save_form=True,\n", + " uproot_options={},\n", + " step_size_safety_factor=0.5,\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Preprocessed fileset\n", + "Lets have a look at the contents of the preprocessed_available part of the fileset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "preprocessed_available" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Saving a preprocessed fileset\n", + "We can use the gzip, pickle, and json modules/libraries to both save and reload datasets directly. We'll do this short example below" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import gzip, pickle, json\n", + "output_file = \"processing_fileset\"\n", + "with gzip.open(f\"{output_file}_available.json.gz\", \"wt\") as file:\n", + " json.dump(preprocessed_available, file, indent=2)\n", + " print(f\"Saved available fileset chunks to {output_file}_available.json.gz\")\n", + "with gzip.open(f\"{output_file}_all.json.gz\", \"wt\") as file:\n", + " json.dump(preprocessed_total, file, indent=2)\n", + " print(f\"Saved complete fileset chunks to {output_file}_all.json.gz\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could then reload these filesets and quickly pick up where we left off. Often we'll want to preprocess again \"soon\" before analyzing data because this will let us catch which files are accessible now and which are not. The saved filesets may be useful for tracking, and we may have enough stability to reuse it for some period of time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with gzip.open(f\"{output_file}_available.json.gz\", \"rt\") as file:\n", + " reloaded_available = json.load(file)\n", + "with gzip.open(f\"{output_file}_all.json.gz\", \"rt\") as file:\n", + " reloaded_all = json.load(file)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Slicing chunks and files\n", + "Given this preprocessed fileset, we can test our processor on just a few chunks of a handful of files. To do this, we use the max_files and max_chunks functions from the dataset tools" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "test_preprocessed_files = max_files(preprocessed_available, 1)\n", + "test_preprocessed = max_chunks(test_preprocessed_files, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "test_preprocessed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "small_tg, small_rep = apply_to_fileset(data_manipulation=MyProcessor(),\n", + " fileset=test_preprocessed,\n", + " schemaclass=BaseSchema,\n", + " uproot_options={\"allow_read_errors_with_report\": (OSError, KeyError)},\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dask.visualize(small_tg, optimize_graph=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "small_computed, small_rep_computed = dask.compute(small_tg, small_rep)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "small_rep_computed['DoubleMuon']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "small_computed" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we can scale out to the full fileset and compute the taskgraph and report from that" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "full_tg, rep = apply_to_fileset(data_manipulation=MyProcessor(),\n", + " fileset=preprocessed_available,\n", + " schemaclass=BaseSchema,\n", + " uproot_options={\"allow_read_errors_with_report\": (OSError, KeyError)},\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "out, rep = dask.compute(full_tg, rep)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "out" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(10, 6))\n", + "out[\"DoubleMuon\"][\"mass\"].plot1d(ax=ax)\n", + "ax.set_xscale(\"log\")\n", + "ax.legend(title=\"Dimuon charge\")" + ] + } + ], + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/04-processor.ipynb b/04-processor.ipynb deleted file mode 100644 index c1f5f3d..0000000 --- a/04-processor.ipynb +++ /dev/null @@ -1,552 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Coffea Processors\n", - "This is a rendered copy of [processor.ipynb](https://github.com/CoffeaTeam/coffea/blob/master/binder/processor.ipynb). You can optionally run it interactively on [binder at this link](https://mybinder.org/v2/gh/coffeateam/coffea/master?filepath=binder%2Fprocessor.ipynb)\n", - "\n", - "Coffea relies mainly on [uproot](https://github.com/scikit-hep/uproot) to provide access to ROOT files for analysis.\n", - "As a usual analysis will involve processing tens to thousands of files, totalling gigabytes to terabytes of data, there is a certain amount of work to be done to build a parallelized framework to process the data in a reasonable amount of time. Of course, one can work directly within uproot to achieve this, as we'll show in the beginning, but coffea provides the `coffea.processor` module, which allows users to worry just about the actual analysis code and not about how to implement efficient parallelization, assuming that the parallization is a trivial map-reduce operation (e.g. filling histograms and adding them together). The module provides the following key features:\n", - "\n", - " * A `ProcessorABC` abstract base class that can be derived from to implement the analysis code;\n", - " * A [NanoEvents](https://coffeateam.github.io/coffea/notebooks/nanoevents.html) interface to the arrays being read from the TTree as inputs;\n", - " * A generic `accumulate()` utility to reduce the outputs to a single result, as showin in the accumulators notebook tutorial; and\n", - " * A set of parallel executors to access multicore processing or distributed computing systems such as [Dask](https://distributed.dask.org/en/latest/), [Parsl](http://parsl-project.org/), [Spark](https://spark.apache.org/), [WorkQueue](https://cctools.readthedocs.io/en/latest/work_queue/), and others.\n", - "\n", - "Let's start by writing a simple processor class that reads some CMS open data and plots a dimuon mass spectrum.\n", - "We'll start by copying the [ProcessorABC](https://coffeateam.github.io/coffea/api/coffea.processor.ProcessorABC.html#coffea.processor.ProcessorABC) skeleton and filling in some details:\n", - "\n", - " * Remove `flag`, as we won't use it\n", - " * Adding a new histogram for $m_{\\mu \\mu}$\n", - " * Building a [Candidate](https://coffeateam.github.io/coffea/api/coffea.nanoevents.methods.candidate.PtEtaPhiMCandidate.html#coffea.nanoevents.methods.candidate.PtEtaPhiMCandidate) record for muons, since we will read it with `BaseSchema` interpretation (the files used here could be read with `NanoAODSchema` but we want to show how to build vector objects from other TTree formats) \n", - " * Calculating the dimuon invariant mass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import awkward as ak\n", - "from coffea import processor\n", - "from coffea.nanoevents.methods import candidate\n", - "import hist\n", - "\n", - "class MyProcessor(processor.ProcessorABC):\n", - " def __init__(self):\n", - " pass\n", - "\n", - " def process(self, events):\n", - " dataset = events.metadata['dataset']\n", - " muons = ak.zip(\n", - " {\n", - " \"pt\": events.Muon_pt,\n", - " \"eta\": events.Muon_eta,\n", - " \"phi\": events.Muon_phi,\n", - " \"mass\": events.Muon_mass,\n", - " \"charge\": events.Muon_charge,\n", - " },\n", - " with_name=\"PtEtaPhiMCandidate\",\n", - " behavior=candidate.behavior,\n", - " )\n", - "\n", - " h_mass = (\n", - " hist.Hist.new\n", - " .StrCat([\"opposite\", \"same\"], name=\"sign\")\n", - " .Log(1000, 0.2, 200., name=\"mass\", label=\"$m_{\\mu\\mu}$ [GeV]\")\n", - " .Int64()\n", - " )\n", - "\n", - " cut = (ak.num(muons) == 2) & (ak.sum(muons.charge, axis=1) == 0)\n", - " # add first and second muon in every event together\n", - " dimuon = muons[cut][:, 0] + muons[cut][:, 1]\n", - " h_mass.fill(sign=\"opposite\", mass=dimuon.mass)\n", - "\n", - " cut = (ak.num(muons) == 2) & (ak.sum(muons.charge, axis=1) != 0)\n", - " dimuon = muons[cut][:, 0] + muons[cut][:, 1]\n", - " h_mass.fill(sign=\"same\", mass=dimuon.mass)\n", - "\n", - " return {\n", - " dataset: {\n", - " \"entries\": len(events),\n", - " \"mass\": h_mass,\n", - " }\n", - " }\n", - "\n", - " def postprocess(self, accumulator):\n", - " pass" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we were to just use bare uproot to execute this processor, we could do that with the following example, which:\n", - "\n", - " * Opens a CMS open data file\n", - " * Creates a NanoEvents object using `BaseSchema` (roughly equivalent to the output of `uproot.lazy`)\n", - " * Creates a `MyProcessor` instance\n", - " * Runs the `process()` function, which returns our accumulators\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import uproot\n", - "from coffea.nanoevents import NanoEventsFactory, BaseSchema\n", - "\n", - "filename = \"root://xcache//store/user/ncsmith/opendata_mirror/Run2012B_DoubleMuParked.root\"\n", - "file = uproot.open(filename)\n", - "events = NanoEventsFactory.from_root(\n", - " file,\n", - " entry_stop=10000,\n", - " metadata={\"dataset\": \"DoubleMuon\"},\n", - " schemaclass=BaseSchema,\n", - ").events()\n", - "p = MyProcessor()\n", - "out = p.process(events)\n", - "out" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "fig, ax = plt.subplots()\n", - "out[\"DoubleMuon\"][\"mass\"].plot1d(ax=ax)\n", - "ax.set_xscale(\"log\")\n", - "ax.legend(title=\"Dimuon charge\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One could expand on this code to run over several chunks of the file, setting `entry_start` and `entry_stop` as appropriate. Then, several datasets could be processed by iterating over several files. However, the processor [Runner](https://coffeateam.github.io/coffea/api/coffea.processor.Runner.html) can help with this! One lists the datasets and corresponding files, the processor they want to run, and which executor they want to use. Available executors derive from `ExecutorBase` and are listed [here](https://coffeateam.github.io/coffea/modules/coffea.processor.html#classes). Since these files are very large, we limit to just reading the first few chunks of events from each dataset with `maxchunks`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fileset = {\n", - " 'DoubleMuon': [\n", - " 'root://xcache//store/user/ncsmith/opendata_mirror/Run2012B_DoubleMuParked.root',\n", - " 'root://xcache//store/user/ncsmith/opendata_mirror/Run2012C_DoubleMuParked.root',\n", - " ],\n", - " 'ZZ to 4mu': [\n", - " 'root://xcache//store/user/ncsmith/opendata_mirror/ZZTo4mu.root'\n", - " ]\n", - "}\n", - "\n", - "iterative_run = processor.Runner(\n", - " executor = processor.IterativeExecutor(compression=None),\n", - " schema=BaseSchema,\n", - " maxchunks=4,\n", - ")\n", - "\n", - "out = iterative_run(\n", - " fileset,\n", - " treename=\"Events\",\n", - " processor_instance=MyProcessor(),\n", - ")\n", - "out" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, if we want to use more than a single core on our machine, we simply change [IterativeExecutor](https://coffeateam.github.io/coffea/api/coffea.processor.IterativeExecutor.html) for [FuturesExecutor](https://coffeateam.github.io/coffea/api/coffea.processor.FuturesExecutor.html), which uses the python [concurrent.futures](https://docs.python.org/3/library/concurrent.futures.html) standard library. We can then set the most interesting argument to the `FuturesExecutor`: the number of cores to use (2):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "futures_run = processor.Runner(\n", - " executor = processor.FuturesExecutor(compression=None, workers=2),\n", - " schema=BaseSchema,\n", - " maxchunks=4,\n", - ")\n", - "\n", - "out = futures_run(\n", - " fileset,\n", - " \"Events\",\n", - " processor_instance=MyProcessor()\n", - ")\n", - "out" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Hopefully this ran faster than the previous cell, but that may depend on how many cores are available on the machine you are running this notebook and your connection to `eospublic.cern.ch`. At least the output will be prettier now:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots(figsize=(10, 6))\n", - "out[\"DoubleMuon\"][\"mass\"].plot1d(ax=ax)\n", - "ax.set_xscale(\"log\")\n", - "ax.legend(title=\"Dimuon charge\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Getting fancy\n", - "Let's flesh out this analysis into a 4-muon analysis, searching for diboson events:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from collections import defaultdict\n", - "import numba\n", - "\n", - "\n", - "@numba.njit\n", - "def find_4lep(events_leptons, builder):\n", - " \"\"\"Search for valid 4-lepton combinations from an array of events * leptons {charge, ...}\n", - " \n", - " A valid candidate has two pairs of leptons that each have balanced charge\n", - " Outputs an array of events * candidates {indices 0..3} corresponding to all valid\n", - " permutations of all valid combinations of unique leptons in each event\n", - " (omitting permutations of the pairs)\n", - " \"\"\"\n", - " for leptons in events_leptons:\n", - " builder.begin_list()\n", - " nlep = len(leptons)\n", - " for i0 in range(nlep):\n", - " for i1 in range(i0 + 1, nlep):\n", - " if leptons[i0].charge + leptons[i1].charge != 0:\n", - " continue\n", - " for i2 in range(nlep):\n", - " for i3 in range(i2 + 1, nlep):\n", - " if len({i0, i1, i2, i3}) < 4:\n", - " continue\n", - " if leptons[i2].charge + leptons[i3].charge != 0:\n", - " continue\n", - " builder.begin_tuple(4)\n", - " builder.index(0).integer(i0)\n", - " builder.index(1).integer(i1)\n", - " builder.index(2).integer(i2)\n", - " builder.index(3).integer(i3)\n", - " builder.end_tuple()\n", - " builder.end_list()\n", - "\n", - " return builder\n", - "\n", - "\n", - "class FancyDimuonProcessor(processor.ProcessorABC):\n", - " def __init__(self):\n", - " pass\n", - " \n", - " def process(self, events):\n", - " dataset_axis = hist.axis.StrCategory([], growth=True, name=\"dataset\", label=\"Primary dataset\")\n", - " mass_axis = hist.axis.Regular(300, 0, 300, name=\"mass\", label=r\"$m_{\\mu\\mu}$ [GeV]\")\n", - " pt_axis = hist.axis.Regular(300, 0, 300, name=\"pt\", label=r\"$p_{T,\\mu}$ [GeV]\")\n", - " \n", - " h_nMuons = hist.Hist(\n", - " dataset_axis,\n", - " hist.axis.IntCategory(range(6), name=\"nMuons\", label=\"Number of good muons\"),\n", - " storage=\"weight\", label=\"Counts\",\n", - " )\n", - " h_m4mu = hist.Hist(dataset_axis, mass_axis, storage=\"weight\", label=\"Counts\")\n", - " h_mZ1 = hist.Hist(dataset_axis, mass_axis, storage=\"weight\", label=\"Counts\")\n", - " h_mZ2 = hist.Hist(dataset_axis, mass_axis, storage=\"weight\", label=\"Counts\")\n", - " h_ptZ1mu1 = hist.Hist(dataset_axis, pt_axis, storage=\"weight\", label=\"Counts\")\n", - " h_ptZ1mu2 = hist.Hist(dataset_axis, pt_axis, storage=\"weight\", label=\"Counts\")\n", - " \n", - " cutflow = defaultdict(int)\n", - " \n", - " dataset = events.metadata['dataset']\n", - " muons = ak.zip({\n", - " \"pt\": events.Muon_pt,\n", - " \"eta\": events.Muon_eta,\n", - " \"phi\": events.Muon_phi,\n", - " \"mass\": events.Muon_mass,\n", - " \"charge\": events.Muon_charge,\n", - " \"softId\": events.Muon_softId,\n", - " \"isolation\": events.Muon_pfRelIso03_all,\n", - " }, with_name=\"PtEtaPhiMCandidate\", behavior=candidate.behavior)\n", - " \n", - " # make sure they are sorted by transverse momentum\n", - " muons = muons[ak.argsort(muons.pt, axis=1)]\n", - " \n", - " cutflow['all events'] += len(muons)\n", - " \n", - " # impose some quality and minimum pt cuts on the muons\n", - " muons = muons[\n", - " muons.softId\n", - " & (muons.pt > 5)\n", - " & (muons.isolation < 0.2)\n", - " ]\n", - " cutflow['at least 4 good muons'] += ak.sum(ak.num(muons) >= 4)\n", - " h_nMuons.fill(dataset=dataset, nMuons=ak.num(muons))\n", - " \n", - " # reduce first axis: skip events without enough muons\n", - " muons = muons[ak.num(muons) >= 4]\n", - " \n", - " # find all candidates with helper function\n", - " fourmuon = find_4lep(muons, ak.ArrayBuilder()).snapshot()\n", - " if ak.all(ak.num(fourmuon) == 0):\n", - " # skip processing as it is an EmptyArray\n", - " return {\n", - " 'nMuons': h_nMuons,\n", - " 'cutflow': {dataset: cutflow},\n", - " }\n", - " fourmuon = [muons[fourmuon[idx]] for idx in \"0123\"]\n", - " fourmuon = ak.zip({\n", - " \"z1\": ak.zip({\n", - " \"lep1\": fourmuon[0],\n", - " \"lep2\": fourmuon[1],\n", - " \"p4\": fourmuon[0] + fourmuon[1],\n", - " }),\n", - " \"z2\": ak.zip({\n", - " \"lep1\": fourmuon[2],\n", - " \"lep2\": fourmuon[3],\n", - " \"p4\": fourmuon[2] + fourmuon[3],\n", - " }),\n", - " })\n", - " \n", - " cutflow['at least one candidate'] += ak.sum(ak.num(fourmuon) > 0)\n", - " \n", - " # require minimum dimuon mass\n", - " fourmuon = fourmuon[(fourmuon.z1.p4.mass > 60.) & (fourmuon.z2.p4.mass > 20.)]\n", - " cutflow['minimum dimuon mass'] += ak.sum(ak.num(fourmuon) > 0)\n", - " \n", - " # choose permutation with z1 mass closest to nominal Z boson mass\n", - " bestz1 = ak.singletons(ak.argmin(abs(fourmuon.z1.p4.mass - 91.1876), axis=1))\n", - " fourmuon = ak.flatten(fourmuon[bestz1])\n", - " \n", - " h_m4mu.fill(\n", - " dataset=dataset,\n", - " mass=(fourmuon.z1.p4 + fourmuon.z2.p4).mass,\n", - " )\n", - " h_mZ1.fill(\n", - " dataset=dataset, \n", - " mass=fourmuon.z1.p4.mass,\n", - " )\n", - " h_mZ2.fill(\n", - " dataset=dataset, \n", - " mass=fourmuon.z2.p4.mass,\n", - " )\n", - " h_ptZ1mu1.fill(\n", - " dataset=dataset,\n", - " pt=fourmuon.z1.lep1.pt,\n", - " )\n", - " h_ptZ1mu2.fill(\n", - " dataset=dataset,\n", - " pt=fourmuon.z1.lep2.pt,\n", - " )\n", - " return {\n", - " 'nMuons': h_nMuons,\n", - " 'mass': h_m4mu,\n", - " 'mass_z1': h_mZ1,\n", - " 'mass_z2': h_mZ2,\n", - " 'pt_z1_mu1': h_ptZ1mu1,\n", - " 'pt_z1_mu2': h_ptZ1mu2,\n", - " 'cutflow': {dataset: cutflow},\n", - " }\n", - "\n", - " def postprocess(self, accumulator):\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import time\n", - "\n", - "tstart = time.time()\n", - "\n", - "fileset = {\n", - " 'DoubleMuon': [\n", - " 'root://xcache//store/user/ncsmith/opendata_mirror/Run2012B_DoubleMuParked.root',\n", - " 'root://xcache//store/user/ncsmith/opendata_mirror/Run2012C_DoubleMuParked.root',\n", - " ],\n", - " 'ZZ to 4mu': [\n", - " 'root://xcache//store/user/ncsmith/opendata_mirror/ZZTo4mu.root'\n", - " ]\n", - "}\n", - "\n", - "\n", - "run = processor.Runner(\n", - " executor = processor.FuturesExecutor(compression=None, workers=4),\n", - " schema=BaseSchema,\n", - " chunksize=100_000,\n", - " maxchunks=10, # total 676 chunks\n", - ")\n", - "\n", - "output = run(\n", - " fileset,\n", - " \"Events\",\n", - " processor_instance=FancyDimuonProcessor(),\n", - ")\n", - "\n", - "elapsed = time.time() - tstart\n", - "print(output)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nevt = output['cutflow']['ZZ to 4mu']['all events'] + output['cutflow']['DoubleMuon']['all events']\n", - "print(\"Events/s:\", nevt / elapsed)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What follows is just us looking at the output, you can execute it if you wish" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# scale ZZ simulation to expected yield\n", - "lumi = 11.6 # 1/fb\n", - "zzxs = 7200 * 0.0336**2 # approximate 8 TeV ZZ(4mu)\n", - "nzz = output['cutflow']['ZZ to 4mu']['all events']\n", - "\n", - "scaled = {}\n", - "for name, h in output.items():\n", - " if isinstance(h, hist.Hist):\n", - " scaled[name] = h.copy()\n", - " scaled[name].view()[0, :] *= lumi * zzxs / nzz" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "scaled['nMuons'].plot1d(ax=ax, overlay='dataset')\n", - "ax.set_yscale('log')\n", - "ax.set_ylim(1, None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "scaled['mass'][:, ::hist.rebin(4)].plot1d(ax=ax, overlay='dataset');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "scaled['mass_z1'].plot1d(ax=ax, overlay='dataset');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "scaled['mass_z2'].plot1d(ax=ax, overlay='dataset')\n", - "ax.set_xlim(2, 300)\n", - "# ax.set_xscale('log')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "scaled['pt_z1_mu1'].plot1d(ax=ax, overlay='dataset');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "scaled['pt_z1_mu2'].plot1d(ax=ax, overlay='dataset');" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/05-samplegame.ipynb b/05-samplegame.ipynb deleted file mode 100644 index d3f2b7f..0000000 --- a/05-samplegame.ipynb +++ /dev/null @@ -1,128 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The sample guessing game\n", - "In this game, we analyze 6 files, `sample[0-6].root` that are each a small 500k event sample of a CMS NanoAOD dataset. All generator-level branches have been removed. Your task is to figure out which file came from which dataset. To make it a bit easier, here are the 6 possible datasets:\n", - "\n", - " * `DY2JetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8`, producing $Z(\\to \\ell\\ell)+2j$ events via QCD processes;\n", - " * `ST_t-channel_4f_leptonDecays_TuneCP5_PSweights_13TeV-amcatnlo-pythia8`, producing single-top events through W boson exchange between a light and $b$ quark, where the $W$ boson from the top decay itself decays leptonically;\n", - " * `GluGluHToWWTo2L2Nu_M125_13TeV_powheg2_JHUGenV714_pythia8`, producing Higgs boson events through gluon fusion, where the Higgs boson decays via $H\\to WW^{*}\\to 2\\ell2\\nu$;\n", - " * `GluGluHToZZTo2L2Q_M125_13TeV_powheg2_JHUGenV7011_pythia8`, producing Higgs boson events through gluon fusion, where the Higgs boson decays via $H\\to ZZ^{*}\\to 2\\ell2q$;\n", - " * `TTTo2L2Nu_TuneCP5_13TeV-powheg-pythia8`, producing di-top events, where both $W$ bosons from the top quark decays must decay leptonically; and\n", - " * `WWTo2L2Nu_NNPDF31_TuneCP5_13TeV-powheg-pythia8`, producing WW diboson events, where both W bosons decay leptonically $W\\to \\ell\\nu$.\n", - " \n", - "In all cases, the lepton can be any flavor, $\\ell\\in\\{e,\\mu,\\tau\\}$. All 6 datasets were produced with the `RunIIAutumn18NanoAODv7-Nano02Apr2020_102X_upgrade2018_realistic_v21` conditions tag." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import awkward as ak\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import hist\n", - "from coffea.nanoevents import NanoEventsFactory" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "prefix = 'root://xcache//store/user/ncsmith/samplegame/'\n", - "samples = [\n", - " NanoEventsFactory.from_root(prefix + \"sample%d.root\" % i).events()\n", - " for i in range(6)\n", - "]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here's an example of plotting all 6 samples together for one variable (here `Jet.pt`)\n", - "Let your physics intuition guide you, and good luck!" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAEKCAYAAADpfBXhAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAABGPklEQVR4nO2de3iU1bX/PzuTSULIBUOIISQhIJgAQhXxwhE82EqLVguoFbH1gq1gqz29nVPtsadIT6voqf7qrR6wirYW1NNWUVSs1rulBRRFCIkgBDKQkISRXJhMMjPZvz/eeSdvhkkyk5lJyGR9nidP3nfPO3v2jrKy8l1rr6W01giCIAiJRdJAL0AQBEGIPWLcBUEQEhAx7oIgCAmIGHdBEIQERIy7IAhCApI80AsAyM3N1SUlJQO9DEEQhEHFBx980KC1HhXqtRPCuJeUlLB169aBXoYgCMKgQim1v7vXBlSWUUpdqpRa3djYOJDLEARBSDgG1LhrrV/UWi/Nzs4eyGUIgiAkHBJQFQRBSEBOCM1dEAShP/F4PDgcDtxu90AvJSzS0tIoLCzEbreH/R4x7oIgDDkcDgeZmZmUlJSglBro5fSI1pojR47gcDgYN25c2O8TWUYQhCGH2+1m5MiRJ7xhB1BKMXLkyIj/yhDjLgjCkGQwGHaTvqw14WWZd5/9lIbqlsB9blEGs688dQBXJAiCEH8S3nNvqG6hwWEY9wZHSxdDLwiCYPKrX/2KKVOmMG3aNE4//XT++c9/xu2z5syZE/eDmzH33JVSScB/A1nAVq31k7H+jEio3/UBNk8HqZ/cT9KY71PfnARMH8glCYJwgrFp0yY2bNjAhx9+SGpqKg0NDbS3tw/0sqIiLM9dKfW4UqpOKbUjaHyeUqpSKbVHKXWbf3g+MAbwAI7YLjdy2lzbOeZ+n/1Zoznmfp821/aBXpIgCCcYNTU15ObmkpqaCkBubi4FBQX84he/4KyzzuK0005j6dKlmJ3r5syZww9/+EPOP/98Jk2axJYtW7jsssuYOHEiP/vZzwCoqqqirKyM6667jmnTpnHFFVfgcrmO++y//vWvzJw5k+nTp/P1r3+dlpbYqAvhyjJPAPOsA0opG/AwcBEwGVislJoMlAKbtNY/Ar4Tk1VGga+jCQ9N5HzhLDw04etoGuglCYJwgvHlL3+Z6upqTj31VL773e/y9ttvA3DLLbewZcsWduzYQWtrKxs2bAi8JyUlhXfeeYebbrqJ+fPn8/DDD7Njxw6eeOIJjhw5AkBlZSVLly5l+/btZGVl8dvf/rbL5zY0NPDLX/6S119/nQ8//JAZM2Zw3333xWRPYRl3rfU7gDNo+Gxgj9Z6r9a6HXgaw2t3AJ/7n/F1N6dSaqlSaqtSamt9fX3kK48Am8pm0fKV2JSUORAE4XgyMjL44IMPWL16NaNGjWLRokU88cQTvPnmm5xzzjlMnTqVN954g507dwbe87WvfQ2AqVOnMmXKFEaPHk1qairjx4+nuroagKKiIs477zwAvvnNb/Lee+91+dx//OMflJeXc95553H66afz5JNPsn9/t7XAIiIazX0MUG25dwDnAPcDDyqlZgPvdPdmrfVqYDXAjBkzpEu3IAgDis1mY86cOcyZM4epU6eyatUqtm/fztatWykqKuKOO+7okmtuSjhJSUmBa/Pe6/UCx6cwBt9rrZk7dy7r1q2L+X6iyZYJlXiptdYurfW3tNbf01o/3OMEUhVSEIQTgMrKSnbv3h24/+ijjygtLQUM/b2lpYU//elPEc974MABNm3aBMC6deuYNWtWl9fPPfdc3n//ffbs2QOAy+Xi008/7es2uhCN5+4Aiiz3hcChSCbQWr8IvDhjxowbo1iHIAhCVLS0tPC9732Po0ePkpyczIQJE1i9ejUjRoxg6tSplJSUcNZZZ0U876RJk3jyySdZtmwZEydO5Dvf6RqGHDVqFE888QSLFy+mra0NgF/+8pecemr0Z3GUGf3t9UGlSoANWuvT/PfJwKfAl4CDwBbgaq31zm4nOX7OS4FLJ0yYcKP1t2Ys+c1V1wHwg6ef7HItCMLQZdeuXUyaNCmun1FVVcUll1zCjh07en84DEKtWSn1gdZ6Rqjnw02FXAdsAkqVUg6l1Le01l7gFuBVYBfwbCSGHaSeuyAIQrwIS5bRWi/uZvxl4OW+frjFc+/rFIIgCCckJSUlMfPa+4J0YhIEQUhABrRw2EB47jophefu/RCQImKCICQuQ8pzT9JtqI52GhzN1Hx2VIqICYKQsCR8VUgrdk89qe0Obpx2D6OHV4Nz70AvSRCEQcSiVZtYtGrTQC8jLAbUuPf3ISaNwu6BV9dW4axr5UhdcEUFQRCE/mXjxo2UlpYyYcIEVq5cGbN5h5Qs47an4LYn4SINezuodql6IAjCwOHz+bj55pt55ZVXKC8vZ926dZSXl8dk7iEly3jzJlA/aiJPX/EQHvvgabElCEJisnnzZiZMmMD48eNJSUnhqquuYv369TGZO+Hb7FkZm5tOfdU+Jteup6a9BltS1kAvSRCEE4AVL+6k/NDx5cDLa7qOudqMgmBT73i1y/jk0cfbkskFWSy/dEqPn3vw4EGKijqruBQWFsasA9SQSoXMGzs+cO3TjdDRLx8rCIIQklDlX2LVuHtAjXt/Fw674PqlgWuzzowgCEJvHraJmSnzzLKZMfncwsLCQO13AIfDQUFBQUzmHlKyTDDWA00gh5oEQehfzjrrLHbv3s2+ffsYM2YMTz/9NGvXro3J3EPWuCfpNjo6oMHR7B+RAKsgCP1LcnIyDz30EF/5ylfw+XzccMMNTJkS3l8Rvc4dk1kGIXaP0drvxmn3APBc+ZXgHA5MH8BVCYIw1Lj44ou5+OKLYz7vkAqoWtEoUts15U8cAMBd7ELb2/t9HYIgDB5ipbX3B0PqEJMVd0oyrSmK1qMdtB7twOtVtHklfUYQhMRgyMoyHWNG4vS6eGipkWP6L+uG2IkuQRASmiFr3IuyDKP+83lGLYfH1q0ayOUIgiDElCFr3EPRnjKGp77/GACpme18/Zff6eUdgiAIJyZD2rjXV+3jmRW3AXDMXYXyjIL003G150Fz3QCvThCEE441XzW+L3lpYNcRBkPWuFtLEQD4dBNZzQ3MtjXyHufRkawCp9HCqREhCIIQKTfccAMbNmwgLy8v5v1Wh2wqpLUUAcADV19Ee6o/pOqFLxf8lstq6yjXY6lvPBUufbLf1ygIQmJz/fXXc8stt3DttdfGfO4hVVumJ46OSsPlcXHH12zMWqf4i/OX5HccwdfWAk1O8eIFQYg5559/PlVVVXGZe8jKMsGkJ6cHrm3tDjI8GjeZNFFCtjeJnx/5D1ztPvHiBSEReeU2qP3k+PHa7V3v248Z3+8q6jqeP+349+ZPhYti11kpUiS1209RVhGlOaWsmbcGW+a75DU+xr+4N5JxzIHusDFldDaT1X7Gej8b6KUKgiD0injuFszsmX3DRlB+di5fWf57/n7jWpqScnjO+d8cc25jtK0C7pwFQPOISZz73UcHeNWCIERNuB62ZMsMPqzZM2lOb+A6u8NJh8uFu8JJC/nU+nzk526iqP0zqo8OwEIFQRDCQGQZPxdcv5RFy1eyaPlK3DnJuDwulmxcwhHbnyk+9hT/4t5IpquGJFsGU/7zPapTTqGsfaehva35qqHZCYIgRMDixYuZOXMmlZWVFBYW8thjj8VsbvHcQ2ANrj4ypy2gxf/9xrV0uFzsv+Za2qrb2ZFVTPK5mUzZ/x7sf68zIDPAgRRBEAYH69ati9vcMTfuSqk5wH8DO4GntdZvxfoz4k1RVhH1Vfso/efJjHMepTWnBeZBUno6TUk5/L1jHt6C2dDRxIaR/8IlNQ8wPaWaKRA64i4IQmIwCLR2k7BkGaXU40qpOqXUjqDxeUqpSqXUHqWUqUtooAVIAxyxXW7/kDd2PKNKxgGG/j7Mr8EXnDeZvFPzSCsrw5VZRJItm3vee4Tc91p55R9TWNT+M3bqYtyOjwypRuQaQRAGiHA99yeAh4DfmwNKKRvwMDAXw4hvUUq9ALyrtX5bKXUycB/wjZiuuB+wnl79xfcXBq6t/VWf+f7zdHSkgxsKGqq577yvUlvTxIcUQQrixQuCMKCEZdy11u8opUqChs8G9mit9wIopZ4G5muty/2vfw6kdjenUmopsBSguLg4wmX3L/aGtoCRH1Ywiv+4dTUp/jWP/fHVcM21PLT5UdLKyiivaWXzqDOY8p8PGp577Sed6VOixQuC0E9Eo7mPAaot9w7gHKXUZcBXgBEY3n5ItNargdUAM2bM0FGsI64MKxhFK0a/VXtDW+AaoMHRwnP3fkh7zmVkTnMwpX0z+fUHONbmZdGqTVzXmMtk+3hKQLx4QRD6lWiMuwoxprXWfwH+EtYEA1g4LFz+49bVgetffH8haU4vz6y4jca6VpRtFHAxTUk5pEwuZuyPb6Hq4ssZ3u4D4FbX1UwencUzS2aKFy8ICcCSjUsAWDNvzQCvpHeiyXN3ANYCC4XAoUgmGMgeqn2hNScZd47x+7DdVUvWyBYW/ng6uYUZgWdKRg5nfOMh7nnvEe557xHmvbXWeCF/qvEFhpEXT14QhjzV1dVccMEFTJo0iSlTpnD//ffHbO5oPPctwESl1DjgIHAVcHUkEwwGz91K7TkZVDor2ZczgnHOdtxN1cc9kzqpLHBtlWhgPpMLrjEqSooXLwgCkJyczL333sv06dNpbm7mzDPPZO7cuUyePDn6ucN5SCm1DpgD5CqlHMByrfVjSqlbgFcBG/C41npnJB9+IpX8DYeynE7D7fK4AhJNQ3ULKen5wHTy//M/A89UXXw5pxzcx/X/dzfH2rw0F46DSx/s9OBBPHhBGMKMHj2a0aNHA5CZmcmkSZM4ePBg/xl3rfXibsZfBl7u64cPNs/91rNvDVz/9J9fx2038t/bXbV0qFk8+sO3yS3MJLcog9lXnkrprDNp2zWcHMC5fQe19f4ft9VLFy9eEAacuzffTYWz4rjx4DGX1wXAzLUzu4xbHT/rmNVm9EZVVRXbtm3jnHPOCfs9PSHNOvpI7TmGzv7zeStZffP38bS9R27hDTQ4WgLPWL348gsXWCQaS9MP8eIFYcjT0tLC5Zdfzm9+8xuysrJiMqfUlokB2XnDqK/aR3vLs7Q3t9Cw35BorKSn2MivP3C8RCNevCAMOOF62PHIlvF4PFx++eV84xvf4LLLLovZvEO2h2os2Fa3jZlrZzKHQkbmpACGRBOKbiUaK+LFC8KQQmvNt771LSZNmsSPfvSjmM4tskwfsWpsb0+spDSnlH+ft5KHv31LyOeDJZpRh/fzyoULAGgvmcD83/1avHhBGGK8//77/OEPf2Dq1KmcfvrpANx5551cfPHFUc8tskwfsf4ZZ/6pZuJp8/HcvR8CBIKrVtpLJgTOuY46vN9y5tWCePGCkPDMmjULreNzQF9kmRhjT7XR7qrl0K7H8bT5aNg/htlX/qzLM/N/9+vA9SvdBVrFixeEE47BcDLVRGSZGFHprGTJxiXk57UwMi2V3KwMDlXuod1l6/F93QZarYgXLwhChIgsEwO66u8He9XfrYQVaBUvXhCECBHjHgN60t/bXbU8s8Jo2JE3dnyXWvEQZi58lzeIFy8IQu+I5h5HUtLzDd29uoV2Vy2Nda1ccH33z4cl0YgXLwhCGIjmHkfKZl1JQ7VxYnX/R4/iafP1+HxYEo0V8eIFoV/Zf821AIz9w+97eXLgEVkmDpjBVbKgbLZRX+Lhb9tiL9GIFy8Igxq32835559PW1sbXq+XK664ghUrVsRkbjHuMaYsp4wKZwUVzgqUpZ+JUTXSoL5qX6/zhCXRWBEvXhAGHampqbzxxhtkZGTg8XiYNWsWF110Eeeee27Uc4vmHmNuPfvWQIDVGlzNHWucOFv44+kB770ngiWazxyIFy8ICYZSiowMowihx+PB4/GgVKgmd5Ejmns/YvZcbahuweMOX6Lpti58d4gXLwgRUXvnnbTtOr7kr7ui61iHyyj5W3nW2V3G08qOL/mbOqmsy7/j7vD5fJx55pns2bOHm2++OTFK/g4lcosyaHA00+BopqNjJPY0Yzwcicb04tMrKvC2HONAai//2cSLF4RBg81m46OPPuLo0aMsXLiQHTt2cNppp0U9rxj3ONMluLrYCK4+d28mEL5EY/3t3225gm7fLF68IPRGOB42xDdbZsSIEcyZM4eNGzeKcT/RsZ5crXRWdvtcfdW+HiUaKxEHWoO9eEEQThjq6+ux2+2MGDGC1tZWXn/9dW69NfzuTT0hxj2O9HRy1SRv7PjAdSQSTdiB1mBEohGEE4aamhquu+46fD4fHR0dXHnllVxyySUxmVuM+wBhBldhBgWT5jD7ylMjlmiqLr6c4e3GwajymqbeP1QkGkE4oZg2bRrbtm2Ly9ySCjkA5BZlBK6tPVchMommZORw3BUV3PPeI5TXNFE7qgiWzez2+ZCB1ruKjPvTvyFevCD0wmA4mWoiqZD9SKiTq2ZTD+iUaOqq9uJxu3udL3VSp6afX3+AY21ept7xKgBXnFkYWaBVPHlBSChEluknwgmuWr30vkg0pxzcxz3vPWIEWisjDLSKFi8ICYUY934inOBqNEQVaBUtXhASDjHuJwA1nx3l0R++TW5hZpeeq/VV+3hwyZUAnPavF/aov4cKtJbXNOFq8/a+gJ60+Pxp4skLwiBEjPsA011wNThFsm7/3rDnNAOtf3rpv3C1efloynk9B1qtWL14EE9eECyYMbKFP54+wCvpHTHuA8S2um3MXDuTspyykMHVYP09kiwaa6DVtX0HmY594Qdagz100eMFIa74fD5mzJjBmDFj2LBhQ8zmFeM+AIR7ctUk0oNOUQVaj5tM9HhBiCf3338/kyZNoqkpjLMqERAX466UGg68AyzXWsfuV1GC0FNwtfNwEwH9PdIsGitRn2iVrBpBiBsOh4OXXnqJ22+/nfvuuy+mc4dl3JVSjwOXAHVa69Ms4/OA+wEb8Duttfkv/Vbg2ZiudAjQ0+EmK5FINFGdaD1uMvHihcTk3Wc/DbTEtNLgaO5yb7bKfPSHb3cZzy3MPO691uSI7vjBD37APffcQ3Nzc4/P9YVwPfcngIeAwPEspZQNeBiYCziALUqpF4ACoBxIi+lKE5je9HcrkUo0VsxA6y9+931cbV7+VnIWi/yviRcvCP3Lhg0byMvL48wzz+Stt96K+fxhGXet9TtKqZKg4bOBPVrrvQBKqaeB+UAGMByYDLQqpV7WWnfEbsmJRU/6ezgSTV8Dre5PdjLFdZgtiBcvCL152CaxzJZ5//33eeGFF3j55Zdxu900NTXxzW9+k6eeeirquSE6zX0MUG25dwDnaK1vAVBKXQ80dGfYlVJLgaUAxcXFUSxjcNOd/m5KNA2O5sCfgsFEE2jlmmtJs3jxEaVLgnjxghAld911F3fddRcAb731Fr/+9a9jZtghOuMeqtGfDlxo/URPb9ZarwZWA8yYMUP39OxQorf6M1aiCbRGlS4ZjHjxgnDCEY1xdwBFlvtC4FAkEwzVqpDdEWmKZDDRBFrNdMmmVg97N49h0aHOvyJ61eODvfgDm4wTrnK6VRDCYs6cOcyZMyemc0Zj3LcAE5VS44CDwFXA1TFZ1RAl0hRJK9EEWq3pkq4tW5h2ZC9vbD8LgGXb1/fe7cmK1Yvf/57xZXrzYuiFQc5gOJlqEm4q5DpgDpCrlHJg5K8/ppS6BXgVIxXyca31zkg+fKiV/O0r4aRIRhNotXrxZhf4hzY/CoCr3UttfQQ+gNV4v3IbfPRHqN1OaBVPEIR4EW62zOJuxl8GXo7pioQAkejvVqLx4oMbBUfckNvKRSs7jb30bxWEfkU6MZ2gRJoiaSWaQGswETfk7gnR4gWh35BOTCcovaVIQs+nWK1EUjo4mKjLF5iIFi8I/Yp47oOEWEk0kZQOhuOzataMuYD27TsiD7QGa/GmYZfUSWEQYf4lvGj5ie+MiOc+CIilRBNJoDWY0lln8ttdm8ENzqZDfffi5QCUIAQoKSkhMzMTm81GcnIyW7dujcm8UvJ3EBAs0ZhefJFvBrnZY4CMsCSaaAKtcLwXn3bkKN9Y83Pa7al91+LlAJQg8Oabb5KbmxvTOUWWGWSYXnyFs4Jt+ds4I+8M/m3emrAkmlBefHRafAVg5MZT/xmvXLgAgPaSCcz/3a/Dm0gOQAlCXBBZZpDR20EnsxRp2czRPRZDiqUWv/7b/47a8TG0HKPgWAP1Ec1knVS8eGFgePOJ1SH/DdRVdR3zuN0AAafIJK9kPMGEK3sqpfjyl7+MUoply5axdGn4TlZPiCwzyAmWaIoyi2lwtISsTW0lllq81UuPOi/eRLR4YYjw/vvvU1BQQF1dHXPnzqWsrIzzzz8/6nnFuA9irIHW1wv/SGlOaUCi6S3QaiVaLd5KeoqN4oO7ue3hm/ksuyA2WrykTgpxJlxnJh7ZMgUFBQDk5eWxcOFCNm/ePPiNu2ju0RFNuWArPWnxeSXjI/LkS2edSdvI4QCkxUqLN1Mna7dD+7Hw3i8Ig4Bjx47R0dFBZmYmx44d469//Ss///nPYzK3aO4JRF9z4a1YvXiIrnzB+m//O8Wb3yC/7gA+rfuuxYtcIyQohw8fZuHChQB4vV6uvvpq5s2bF5O5RZZJEKxZNK3e1i6vRRJoDfbQo9Hjg7X4ooOfsm3adGrziiPz4q1I0FVIIMaPH8/HH38cl7nFuCcIveXChxtoDSZWenx7yYRA267c2v3sbfVI0FUYdAyGk6kmYtwTkN4CreF68RC7rBqrl/72xZczPNYHoCToKghdkIBqAhJu0bG+ePF1VXupq9pLu8uFo3xHIDc44qCr/wCUc/uOyOrFW+ku6NrWJIZe6BWtNUoNjj4DWkfeiVQCqkOASmclM9caza8XzF7Qp0ArGF68acDffGI1O95+nbqqvagIG3FYg67lFy7A29zMC+fOxZ4xvO9avGTXCBGQlpbGkSNHGDly5Alv4LXWHDlyhLS0tIjeJ7JMghNcdKzCWRG4j1SisWI19NHINe0lE0ip2gNAiaMSHJVsm/ZGdEFX0eWFXigsLMThcFBf3+ccrn4lLS2NwsLCiN4jxj3BCRVonbl2JmlZmSzM/i5FmcUc2n2U7W84AjJNb4eegrHKNZF68Vbjvf7b/85DqaUA3PXOb/ueOmnF1OXFixcs2O12xo0bN9DLiCuqL1pOrJkxY4aOVZnLYH5z1XUA/ODpJ+My/2Di7s13Bzz3SmclpTmlrJm3hnef/TRg2BscLeQWZvS5EbDpxY8qMf7hRFrKwMRMnfTY06Lz4q2YXrxp8MWLFwY5SqkPtNYzQr0mnvsQort0yWgOPQUTjRdvpb1kAj8sNaSUB/52Hzgq2X9NHQCpk8qO6/UaFpJdIwwhxLgPUcI99JRbmBmRTBOsxR+sKOfBJVdGXMZg/u9+zXz/9ZrF28l07GNV1mxS2tv4yXtvkh/WLEFI0FUYQkgq5BAlHC0ewu/TGgrrAShH+Y4+p04euPomyg81kQNc9vtfkt54iG3TDNnowNlflKCrIIRAUiGFrhk1VLLt3PX827w1ADx374fUfHaUR3/4dp+8eJNoUietp1fXb5lEQ5UdgFGH9wcybaLCGnSVHHkhQZCAqtAF04vXGP9fzHV8k1zXmEBWDUDKMFvEht6KKdfY09IilmusvHLhAkYd3s9Pz/8uALe0VUYfdA2Wa4pnwpKXoptTEOKEBFSFsLF68QCv01m+IDirpq/Esl5NPfCjypeMHHmIPugqco2QIIhxF7pg1eKh56yaSBqCWIlHvZo1i79HpmMfp3y8gxRPG1VHjvUt6Gqlpxx508O3PiuGXziBEOMu9IjVk996eCtbD2+lwllBkW8Ged6JNDg0RJHyGOuga3lNE6Nq97Psk/V9qzpppScvfv97xvfULKLZvyDECzHuQo9YPfm7N9/N83uep8JZQWVhJaXTjENQsfLiYxV0ffviy8lqqeEba36OBlIyhrP/2SwgBjnytduN72NndXrrpsEXhBMICagKfcKsNmmecK3YVANAe6vR1m8gg661d94ZqDpZXtMEwPjGQ3Q0NwOQftZZQBSGPhg5+SoMEP0aUFVKTQK+D+QCf9NaPxLrzxBODLbVbWPm2pmU5ZRRttjQ4uMRdDXlmh1vvw7Aaf96YY+G3mqwf7JqU8DA5xyt4xefPk8J4K6oCP3mvpA/1fDoJZVSOIEIy7grpR4HLgHqtNanWcbnAfcDNuB3WuuVWutdwE1KqSTg0TisWTgBCKXFP7/necPQW4KuscqRN3X4+qp9getwmFyQFbj+p9vLddNu4JxxOVxfczcFn+yEa64FovTiL1rZacBfuQ0++qNfvhEtXhg4wpJllFLnAy3A703jrpSyAZ8CcwEHsAVYrLUuV0p9DbgNeEhrvba3+UWWGdxYC5JtPWz8d5xx8gyKts8I5MhHW5DMxMyuMfPwe/Pirax4cWcg6JrRUMsPtj3Lqc01pLUb5RfiItcc2AQpwyF/mnjxQsyJWpbRWr+jlCoJGj4b2KO13uv/kKeB+UC51voF4AWl1EtASOOulFoKLAUoLi4OZxnCCUqPQdegFn99CbpaCZZrPnzlhbCza6xB1xUv7uQvU0+lvKaJzCO1/Neu5xhfUUGHyxXxmrolVKGyj/5oGPrg58ToCzEm7ICq37hvsHjuVwDztNbf9t9fA5wD/Am4DEgFtmutH+5tbvHcE5Pegq4FE0cAfTf0plxjtv0DSElPByLz6M2UyWeWzWT/Ndd20ePTyjrlp6g8+uC8eDPrBmUYdzkFK/SBeAVUQwmKWmv9FvBWWBNI4bCEp8sBKEvQtWJTDQ2OZqLRpUPp8nVVe/G43RHp8mBk1Uy941VyRs7ltuwm7vOXG/7Zvo3k11dH79F355lLGqUQJ6Ix7g6gyHJfCByKZAIpHJbYlOWUUeGsoMJZQYunJXAAymroo60fbxJ86tXEGoyF0NKNNejK6CyemHQrOcA/9zk7A7D/dzfpR44xNiar7QY59SrEkGiM+xZgolJqHHAQuAq4OpIJxHNPbG49+9aAHm/V4oMPKFkzaqz0Va4BI6vmwSVXdpFrPG53yGe7O71qDcD+z8SL+Y/dL/dpLb1yYBPcVWSkUYJx6lVSKoUoCTcVch0wB8hVSjmA5Vrrx5RStwCvYqRCPq613hnJh4vnPnSwGnpTiwfDgFsxpBqIVUkD8/6C65d28ejDwWr0X7lwAfn1B6g862wAakcVkeUwip5F1QbQGnQ17y9aKSmVQtSEmy2zuJvxl4E+uzPiuQ9duhyA8ufFW4lGrukpkGp69BBZ0LV2VBHH2rwMTzX+yTQ1ujk6bCRKQcHh/X1v5t2dN27NnTdTKu8qkpRKIWykWYfQ7/R4ACqn09DHWq4JlUYZ7qlXa2EygMmjswIFyV65cAHFB3dTedbZpJWVxS5P3sTq3Vs1eUHoASkcJvQ7wXnx1gNQ1qqTuXljGJ3ZeQaiwdGMp83X58/tLrum3eXq1dD3VFXS6tXnb99BUyzKDVsJrk5p9eKhM63y9G+IRy8EGNDCYRZZ5sbdu3fH5TMkz33wYAZdARSK0hyj6qQV8zBUbqGh1UcTdDWxZtQ4yncAkeXLr3hxJ3/6wAHAz157gHSvG62SsGcMD2jx1mJmEEXOfHBGDXTWtAF/CWLE0A8Respzl6qQwgnJko1L2Fa3jWHJw7rIOGZJg2GNJ8XsMJSV4Hz5MWWTWbQ8fCO5/tv/jtrxMQATjxoGPykzM1CRMinTkJjSysoY+4ffR7XWLljbA4qhHzJImz1h0GHmyFupcFawLX8bZ+SdETj12lDdQoOjmfZWH4d2Hw2cgi2bObpPhj5Ul6hIArDB3aGm7ngPW5uX2sJSVp52Oc4Redzz3iMUb/0gthq91XgH94EVnX5IMqDGXbJlhO6wpk5asaZRWo231dB72nyBssPRYAZgQ+ny4dSYP3D1Tdz3wSWAEYB1+oOxO9NPJt9+gGRiXHrYJFijF4YkIssIgwqzp6tZFXLBhAXdplFGW4HSSvBJV6s2H2kzkUWrNrG1ykl6ajL3vPcI6Sk2/vXlP8dsrV0wG4n4f17kT5MAbAIhsoyQMJj6u1nS4KldTwXkG2saZYOjhUd/+LYx3keJxkqw4TZbAoKRO28dD6fcgZlS2dTqoanVw6JVm5j31lqm7/o7aXZb7OSa4PaAJiLXJDziuQuDFjONssJZQau3tVstHoy2fxAbQx+MtSWgtdyBQjGqZFyPAdm3L76cX46bR+2oYpb/7UEmNewjOWN4lwBsXHLne/LoxbsfNJywnrto7kI0WOUYU66ZuXYmAAtmL+jS9s809NvfcEQddA0mb+x46qoMb71w8mldyh0crCjnwSVXklfS+YxVxikZOZwH3rqfpPR0XO1eDoyZyEWvP98162bLFlxbttD43POx9+h7Qrz7QY2cUBUSguBTr0/teiqQM182pYyK0RWkHctk4cHvgj+NMlaG/oLrl4bU261G34pVxkmdVBYIqtaOKua/Jy3kJ3e8SnPuBTDnAjLTkrl685+ZfGQfSkFRrA5JheONW4Ox1gwcEI9+ECCau5AQhDr1GpxK+XlqHdvOXR9SuomHR9+d0TdTLM1CZnk3f5sLrl/K0y/upNl/GOqccTmB8gYrXizkZ/7x5X97kOHtfT+lGzG1nxxfsVI8+kGBGHch4QiVQgn9m0bZE6ZHX1e1t0v54+WXTglZ5sA6/sp7j4Sc0zwBa/4VkL1wQWyDsalZnd66qdff5W/nIF78CYlo7sKQx2rozfIGscy0Ccbq0UdahhjA29zMC+fOxZ4xnPQUm9EpyhKA7XC5upQ66DPdGWyr0Rcv/oRFNHdhSGENulpPwZr58mZ9+XjKNd1hTa/sLgDbXjIhEGg91uYNvDcpMzPgre+/5tq4rRE4/pCU1Yu3liQ2a9IHjwv9gsgywpDBmiNvpdXbGhjrTa6JxwEpM6MmuMm3iTUAay1vYG3s3R1xkWusBOfR73/P+Proj111eut4cNqlGP24IMZdGDKEo8UHB2PNlEpTrjHzwo17QwrJLcyMqsZ8qDRKK8EpldZnzMbeYJQ4KK9pIj9rNve89wgfnzuXpI4OTmk6FFu5xkqwUbZ662NnhfbirYikEzfkEJMw5LGWNGjxGMHUDHtGtwejwDDo5rX1oFQ0hr47rHKN1btvzcjnWLsXt6sVgI68EjZmnkvO0Tpu2/FnPC3H0BrKR45jYvMhUjxtjHU7SbMbB7pi7sX3BbM+fcpw8eL7wAl7iEkQTgSsck2GPSOgv3d3MCqYd5/9NKDLG959bLng+qWBkgZ5Y8cHDP3YXEO+qatqMMoTZ53M/yz/iv9d17Bo1Sb2HznG2JHDWVvTROaRWv5r13N0uFxon4+psfbi+0L+1NCSjhj6qBHjLgx5upNrrEbfqstD18YiZTllnJE9nyJL16hYYy1hEEq2CXVYKliLX7RqEz8Z+R0A8usP8Ov3/xe3v+F3WllZF13elG9iWnM+FNZesVbpRuSaqJFUSEHohuDyBlZMgz8seRiVzko4dz3/Nm9Nl8beVo8+HnKNyaLlKwMpleb34Ho2z6y4jTMbXHDaYsprmjiWlMKh3CLGNx7q8lxHczOf//4PgaYitXfe2X/STThNwYMzcJx7IWc8LHmpf9Y4iJBUSEEIE6tEo1DHdYkKpqG6BU+bD3uqjUO7jwaaiVj1+lga/fqqfYFSyGZ1yqO1NYzIH01d1V6GATelfsIFdyzt4sUDXHFmIcsvnRLIrtnxWe3ASjfdyTXBGTgA7S3GLwORcbogsowghEFwGmVpTmmgxHCwV1/z2VH/ISjF6FNGsPDH07t48VZipdGHaiySkp5Ou8tFi/NI4NpsOHKWp4Pik6eyMfNcXG1eyg8ZRnPV1PmUj7yA8lOayK8/wM/2bWSs5XPMHPoBk2u6y8Ax697UfiJevB8x7oIQBqZEYxry4MbdFc4Klmxcwg1FPw145a3ZTh7I+iX3rG2mLKeMssWd9eat8k0ssOrw1j6wKenpgfaA1vEkXzszslo5kN9ZWx6g/FBT4N7n06Qf2MsL584FIDsni/z6amAA5BpTg7ca7lAyTu128eL9SCqkIERJcDNvq0dvjisUpTmlx/1SMPPlTXmmPzR66CxeptG42nx8mlXG5vzzcbV5mVGSw2W162mo/IzxdR4jpRJIyRjO+MZDdLhcpE+fHn/vPRKsXvwQahAuqZCCEEesZQwqnZVdDkH1pssDxulXRzOHdh8FjHz5eKRUWrHKOMm+NiZ//jG5x4zg6siWTOpaaiFVkfbNi3mibSrlNU1MHp3FM8tmxr+8QV8IlnFCNQgfYmWLxbgLQpRYm3mb3nqFswKFoiynjDXz1hyny5vkFmUEZJyCiSNorHeRPSo95LOxxFq4zAy6HtlbBxj583Ut4HG7qdu/l8vYS1lNExWjr+kyxysXLgDgotefD4xZm4zYM4bTXjKhS8mEfsEq1Zg6/BAsWyzGXRBiiNWLN4OuJqYub5Vm/l7yHM97nw+8tyynjOv95Q5M4plSaU2ZXBT0mlW6SW/zUfzpX1m0Chqzz+eud3+LZ9hItIJHLruEDl8HAOneNkaiAMWow/ux1R1g/zXXDoyEs+Slrt76ECtbHBfjrpRaAHwVyAMe1lr/NR6fIwgnGlYvPhjzINSSjUsCuvxx+fIWzKwba3kDq1wTXBIh1lUrg6WbfMcWkuqqULqDzWNGM9rZjgbcNkjx9w85mj6MT3NySUlPx/7ZcIoP7sZdUcH+a66NfR/YcLB68db7cMoWD3IZJ2zjrpR6HLgEqNNan2YZnwfcD9iA32mtV2qtnweeV0qdBPwaEOMuDGnC1eW31W1j5tqZzPV9kzzbRMB2nFzT4GgOePamsY9HkxFrBs5dy+/CXVsNrlZQ0HjKKYw4J526qr0UlIzH+fEOAApOOw1dUY693cWnI5PJOZLCCMBdYVSmbNtVMXBevJVg6SYUtZ90Gv1BKOMkRfDsE8A864BSygY8DFwETAYWK6UmWx75mf91QRjS3Hr2rWy6ehObrt5EaU5pwIuvdFYGdPmynDKGJQ8D4PXCP9KS1UBuYSYLfzyd61fOCpQZNgOwDY4WcgszyC3MxJ5qi+v6f7rip6xY9VumTziZMcmtpLccpq5qLx63G4Dv/GUD3/nLBvLGjseelgaAO1nz8tkzKd2ymbSyMnYnZbLjs1r2X3MttXfeGZh70apNgfLF/c6Sl4yTrmAYemvfWDA8/PxpRmGzYEI9fwIRtueutX5HKVUSNHw2sEdrvRdAKfU0MF8ptQtYCbyitY5tQq8gDHK60+VNmcZk/ZQHKcsp49PNZYE6NlaPPrcwI6C/h8qbj0ft+UXLV3bJl7enpQXkG+jaZWr5su/y8vBz+Msdr/Ijbzat+Q0AFGzfQdInO2nbVcETV97K15/6lTE3twf6xvY7tZ9glnPuIsfkTzN+AfTULPyV245vYAIDfpgqWs19DFBtuXcA5wDfAy4EspVSE7TW/xv8RqXUUmApQHFx/AouCcKJhtWIB+e9m/dLNi4JePdbDxtnQDLsGTx38v/Cyca1GYCdTVeNP1iLf/fZT2OqxQe3CAzVBBxgeEoyX6x/i47PUygvKCCpzpCNfOMUxbVtqN01lK38CXZvO0rB15/6FQcL0njmwwnH1caxNiaJ+SlZq/7e1gT/fKQzo8ZKqKwb83lrvRvT6FslnwGochmtcVchxrTW+gHggZ7eqLVerZSqAS5NSUk5M8p1CMKgItioB2P17mecPIMDzQcoziymLKfTiw8OwJq9X60B2Hg2/A42wMGMzU3HebQJe4eHkY4t1NtHkmSz4U21oZVCacgaZqegoZY0u42PMtOptY/k8N46WHFboCnJihd3Bk7Nrln8Pabv2kma3cb+a66l/cABUoqLozP0Vv3dLERWu91fY95v+LtrFh7sxXfHAOj10Rp3B1BkuS8EDnXz7HFI4TBBCE1P3n1wm0CgS+/XlGE2ymaO7uK9DwR5Y8czxuwDO/k0MmprGJGfB+RxsG07SUlJfOcvzweef+OySyhsrgfAUV5H4wcf8Nnzf6Hj5PHYMmfhyxhJpmMfyW1usA/HtWUL/zilABpr+WIsDL1VRgnOruku6yZ43CrhBMs5ZmmEfpJrIio/4NfcN5jZMkqpZOBT4EvAQWALcLXWemeY85klf2/cvXt3hEsPDyk/ICQqoercrLx9LQC3/epq4PgaNqb+Hu80SpNQJYjNtoH2tLQubQNXXX4pXq8PBSR7k1BJbaCgJTWVPxcsYMzkKVz/f3fjaTmGPWM4vtJR1FRXAZDs62BqdR2ZqcNIKysbmLTLngjuOBWjUsUxKT+glFoHzAFylVIOYLnW+jGl1C3AqxipkI+Ha9hBPHdBiBWB3q9TDK9eba6mwllBQ3YLX9v5Pcxgoam/G4a9+zTKWAVjQ0k31r6x1ubf6dmZZO2qJ1kpktLTOZTWRpJSZLnb+J93H6bAOZVy4DdnfJ36k8dyWc16xgBJSTaah6fjs38OEGg6ckIRXMIY4l6qOJJsmcXdjL8MvByzFQmCEDFmWiVAi6eFp3Y9RYY9gzSdSWu2k2GNJx1nxHMLO6Uck1DBWPM9scq6sbYNtJIytpiCPQfIGzuen8z6Dtf/391MHp3Fy8ec7BgzkorGWqY3HMFWaoT6XO0+PssuJC19GJMLsqitduNMG8bk0UbBsH4rTxwO1sqW+VP7peOUdGIShEHOko1LqHBWBFIqzeBrhbOCz1Pr2HbuekrfnYvH5mM0I7q8t9JZgcfmI5cpgQqVZp5Ee6uP7W84SBlm5NDHMuvG9OjNFoGmfLP3S7M4a/lKWLWJn8z6DpNHZ/Evb9yLzduGF81HZUXoYSlMHp1Feo2Nl0+agzsrHw6txz2ugI7kFKg+TEFDdaARuNmABI439NYsnLhjlWD6IcAqnZgEYRBT6axEo2n1tgJd9XfT6Fc6K6mYUkF6Yw7Zh29k5e0VeNp8nDZ6CpWzX6PB0cJpjZ255aZHb56KbXA0xzXrpjtcbV7Ka5rIOKmUs91bSVKK5mGpzD/yEnmZu9ifkkyS6kzYU3SQ5G1n54gkatMLaFU+0JoLgtoGfn/kBUA/GfTuMA19HA9BiecuCIMUa3eo7koLp9vTA168T3vx1ifjTvOgtKLSXwIh3ZPDwf0NpNpS8bQZaZRWCabTo+9KrHR5j9tNXdVeFIpRJeMAmFzQ2USk5YxLoH47druNzJJxHKwop65qL+koho+2UTI6izklp/Pam/8AQNnacQ6DNDegFFsnnUrO4Va0z4ftjc0UF+0HjEJps18xDlCtKLi7y+EpayC4X737GCKeuyAMUoK7QwUXLAv24h2tdbSPaAI3aKVxZRsByLakVloyG/i8zQfpMLWosMs8C388Peado0yswdVRJeMCp12XXzol0PrvmWUzYdmLgL/LlOV5O0a5hguuX8pbmz4CoL3kPNy11dS5WlF00JaUyin6EEp30KE8lDj95y4/NUteacoPNXUpf1xXtZc2Twf/8eMVlGeeC8CKF3cOzOnZPiIlfwVhkNPbgajgZwLpkj+5meqNW6mgghemPMSFH98AGGWIradel2xcQkN2Czc0/hToPegaiUdvDa4GZ9aE8pSDn7eWKV6x6rddnl2+7Lu0tbaS7z2C0kZJ4vZURZrbyBzKd2wJjM9+40HcyoXN7abeXy8HTxs4D0EmXfrMDhZElhGEIUbl7Nf8V1ezZt6aQBrla194jFZvK2c4z2DJxiVdArPpnhyqmw8E9Pp8n9E2OzjoapVwnrv3w7Bqz/d20rWvTC7I4mjtMUbkT+TjvXXojg7O9Tbj1M340GSo4bRro4VgM02kutrQQLaykTK2mKrK3aSn2Pju9gfxdcC7JbfHZZ3xQnqoCoIAdAZgFQqNpsVjeOMZ9gxSj2ZxXtVl2JSNJK+dnMxsijKLA0HXHTXG8ZbTRk+x6POK3MKMmBYu6yvLl30XMLz7J69aAMB1Tz/Pk1ctoN3lwpucEmg4Upg+jPnr/sz9i64gxeMmzdtOR4cmKbOMjXOMw2HPLJsZlRYfSNP84hFjoI+HmaSHqiAIvWL14iucFWTYM1gwYQEVzgoONjWQ5xrL56mHUVrh8rh4YcqDgfdV3m6kGgbr8ztqdlJ5e0XgxGwkxLKqpVWyue7p57tcL1q1ifKaJpZ99CBJuoMRjcZrKR437UkdJKNBaZKOVXWZ8/r/u9u4WPZ8l5x6a/tBa2C2v/PuxbgLghAgVJB2ycYlZAwfTvG4PJpq6vHRwcG0vYEaN0s2LqHIe17g+ozm+RRlFlPdfACf7sDjbevSfSoc3n3204jlnb7+MphcYBx6yv8b2D0eXBkp7L/mWqbvO8iH48agkmx0dPg4lqQD2TWLuJ2vt3mxez28ffHl5NdX4/b4KL9wAZ6WY2gFD1/9dTpSjVTNZ1bcRpk/WFt7552BU7T7az2k5qWQH7rFblSI5i4IQo9Yg7GVt1fg83lpOeszcHY+89oXHgNAORWcu55/m7eGlbdXoLQiyWun6M1ZHBvpNjpABBHKKDdUt+Bp82FP7dpaMBjzl9ANTT+N+JeBiZkBs4jbcW7fwY8qX6K8pglPai4lTcnU5SbTfuwYtiTwdYDSHUaNG08bSR0d5O0t5++nFtHRoclu9FJ3sh0NtHtaSU41umcdrthFifMI7qONuLZsASApMxN3XXtYa+wLkXRiijla6xe11kuzs7MHchmCIASxZt6akFk4pTllfGHUFwKdo6xdpMpyyijNKQ30iXVlf45WGptKYuSxMYw8cErAkD9374e9plfaU21GQ/DCDB7PvitgyEO91/xlAEbp42gOXOXXH6DD5SLJn0mTNqkMV3oq7UkdgewaV0cDjpPt7B+dyl+/MAVXUjJum51PJhej/eeq0nwYhdFKxpOtFbUpOeyxjyD9rLP456QS/nFKAWl5KX1eZ2+ILCMIQth0J3lYm4yYVE/bStGb55GWnE5rqpOMI3mB/q9mIDZYfrH2iu0NMz4AUOqsIMOWS27hiD7v7ZllM1mzeC2fZRWQ4mlDqyTqRxWxZPlKNtx8I0eO1NPebmTXuEqKGe5y4W5tpSmpg6wQeSlp3uB2F0ZBtL1fmkXz268D8FZmLiN8Hsb2edXdI8ZdEIQ+0V1+vdlBSqEoTZ5LaU4Z23ybGNaYA9g5tPsoYFSjNK9ThpnyS6eVNPvHPnDH87jSXVQ4Hfz8nofJq55IanIqen0Rc9uWgs2Hi1aG+b3qaDhw9U2UH2oKtP47cPVNAFzy8KMAPHnVAjxuN43aR5rbjdIduLPycaYZfzVkXHIzuR/+AefHO8hvsnGRP81z1eWXooFjbV7+sekjMltbSR02jEabPeo1d8eAyjKCICQW1ibfpTmlqPnVLPzxdKqnbaU120luYSbTvlgYyIsvmDiCz7MOcST9ILmFGRxKOsCOmp1ddHaXx0WHNownR9LAY5itzCP52Dps2H2pjDw2htZsZ9SZNcsvncIzy2bSOP5KGsdfGfJEqkpKYlTJOFpPyqJt5EnMmXk66Sk20lNsxz3/yoULeOXCBXRoza/P+jorvvQ9XO0+6u25NKTkku3zRLXenpCAqiAIMaOnDlImZj15MGQeM40ytyiDpBrjmdzCDP6Qdw8vbBxGKXP5188Wk5Zmh2TwJXvJLcxhm28TSYczAEVrtjNQTiEWVOWF6iDaNY3S2kP2f9s2BcYXLV8ZSIe0oiBQzdLtjdlSu0VqywiC0C9Uzn6N2+YZ+e6V/l8Ad29+jfVTnjfGssooshkplS9MeZDG5nqyKe52vuppWyl915B9zJz7aDFLKaTozvtwsm5CHWQadXg/h4bnAmBP6/raG6OMUsU/qvufqNfcHaK5C4IQU7rz2M0smjXz1nSWQHAaGr0p5ZiYpYxD8XnqYVqdzuPGzfm/xvd6XJ+1FWFwGmagQ5UNOjR9zrppL5lAPUDLMQA8KanM+vzvpHz4EcMtpYq1BhX6j4SoEeMuCEK/Ys1yUahAueI189awBCPbppRSttVto8JZQZF3FnnHxpLaYcflaeW1KQ9SPC4vLmurbj6AK92Fx9tGktdOdfMBILSO31NNnPm/+zVAQJ7J+UIZ3qq95BXkAzC8zShVrD6O6fK7IAFVQRD6BTOL5qldTwXq1pTmlJJuPz710RqYZaQb7EYmTGu2k47kziBk5ezXAl63OX+ls8JvlLvy/x5Yy8rb1+J2e3C7PTxwx/M0OJppcDTz7rOfAkbw1uVvfAIal8cVq+33O+K5C4IQd8pyygLe+oyTZwQqTnYn4VgDs7+4+uaAfPL3Ka/xeV0dbmezkWqZU3rc/KZxDpZfkvblkKp9uNMaMA33MDp7yz5374dGuma2Ifm4vcYvEat0E06Jg+6esTYlWVYCi5Z9gzUbw/wB9gEx7oIgxJ3gLBrrYScrvdWmtxrx0pzSQPcp6/zpQfo9GAFcd6qHtDQ7adhxeV1Uzn67+96ys1/jwL465jq+EdE+g7no9eeB45uMmE1J4omkQgqCcEJiNfSdXvD0XlMtAVKPZtOY1gDAA3c8j6fNh9LdRy7NA1Q2b3Jg7pW3r2VYYw4Nrs4TtNYGJcFZNKGamJjPBDcZCaf8QrRIKqQgCP1OON2j+krqydBGo9FOEM1h12HsOg38rQXTG08CjIycIu95JJFMa7aTYY0n4Uv2BvLlze9N/po1uRgHlLprFh7ItOnmmUpnZXw23A0iywiC0C/E06B3mX+e8W3l7Wtx+9o4NOcfFL1p5M8Pn9PCrWffzN2b76bUWdrZfSrvDL6283tUOg9SPc1oHGR+L313LtCpuVtr4ZjjJrmFGQAhG4qbWOvptKaOwdbRFovtH4dkywiCMKjormJlKNJsqayZt4b05HTSk9MD9eRvPfvWQDXL4Bx7K5XOSlxeFy6vi7s33x3WZ1Y6K6i1dc3WuXvz3XjTvoo37au8//FW2vxHVH1JKfiSUsOaN1LEuAuCIITALGEM4NMdAa0/FFaPPhQVzgp8Zrlgbys+m4fcwkxsHfGr5y6yjCAIAobH7fJ25rWbXv7Kd9cGxiudFXhsPnCMxaxgaebIhyIQNJ0CNpVEenJ45YxjgRh3QRASEmvf1kC5A7rv5Vo5+zUqnBWUUdbteOXs12isb+Waup/Q4GjuEjht87ZR6TzI+ikPkt6YQ/bhGynKNGrjFG2fQZLXjsfnI8s9KrYb7QYx7oIgJDzdafQ95dx3R/aoYSy8pjO42uBooda2nw67xuc/+NShfV1Ot6Y3nkSb9oIyTtm629ppdTqJpx8fc+OulBoP3A5ka62viPX8giAIJwKVzgq89g6mnDyZ2hrQSsNIN2U5ZRxorAs8Y6KVxp6a3PmXQE4ZZ3wWv/WFFVBVSj2ulKpTSu0IGp+nlKpUSu1RSt0GoLXeq7X+VjwWKwiCEA8qnZVUOCtoDdSV6cTMqjGfqXBWBDJnku1JLPzxdOypNjqSPYH0SYBhjTl42nx42nwMa8zhpLaTKc0pO27+eBFutswTBLJHDZRSNuBh4CJgMrBYKTU5pqsTBEGIM9asGLNCZU/PmAXKANy+NqMZuNcVyIYB6Ej20JrdWZY4uOCZOUcHdFPYOHrCMu5a63eA4ALKZwN7/J56O/A0MD/cD1ZKLVVKbVVKba2vrw97wYIgCLHEmvNellMWyJLp7hkzL75y9mu8Om114OSpTSUFfjG4hzdTOfs17Kk27Kk2Kme/RttwI1Wya259d1XroycazX0MUG25dwDnKKVGAr8CzlBK/VRrfVeoN2utVwOrAWbMmBGv/QmCIMQcs5mIebrVTHG89exvA7Bk45JAeQPzeWbj70Q13ZIzH31T7+6IxriHqsKjtdZHgJvCmkAKhwmCMMhIt6dTnFlMhbMiIOMEe6fB0o61gmV/EY1xdwBFlvtC4FAkE0jhMEEQBhtmHXozhfLWs29lidNMp7w6MAbGASiIf12dUERTfmALMFEpNU4plQJcBbwQyQRKqUuVUqsbGxujWIYgCIIQTFieu1JqHTAHyFVKOYDlWuvHlFK3AK8CNuBxrfXOSD5cPHdBEE4UwvGuI/XAwzkZGy/CMu5a68XdjL8MvNzXDxfNXRAEIT5Isw5BEIQoidSjN5//zRPXxWM5gJT8FQRBSEikh6ogCEIfiIdGH0sG1HPXWr+otV6anZ09kMsQBEFIOESWEQRBSECU1gN38t+UZYBFwO4+TpMLNMRsUYMD2fPQQPY8NIhmz2O11iG7fwyocY8FSqmtWusZA72O/kT2PDSQPQ8N4rVnkWUEQRASEDHugiAICUgiGPfVA72AAUD2PDSQPQ8N4rLnQa+5C4IgCMeTCJ67IAiCEIQYd0EQhARkUBt3pdQ8pVSlUmqPUuq2gV5PrFBKPa6UqlNK7bCM5SilXlNK7fZ/P8ny2k/9P4NKpdRXBmbVfUcpVaSUelMptUsptVMp9X3/eCLvOU0ptVkp9bF/zyv84wm7ZxOllE0ptU0ptcF/n9B7VkpVKaU+UUp9pJTa6h+L/5611oPyC6OG/GfAeCAF+BiYPNDritHezgemAzssY/cAt/mvbwPu9l9P9u89FRjn/5nYBnoPEe53NDDdf50JfOrfVyLvWQEZ/ms78E/g3ETes2XvPwLWAhv89wm9Z6AKyA0ai/ueB7PnfjawR2u9V2vdDjwNzB/gNcUErfU7gDNoeD7wpP/6SWCBZfxprXWb1nofsAfjZzNo0FrXaK0/9F83A7swGrAn8p611rrFf2v3f2kSeM8ASqlC4KvA7yzDCb3nboj7ngezcR8DVFvuHf6xROVkrXUNGMYQyPOPJ9TPQSlVApyB4ckm9J798sRHQB3wmtY64fcM/Ab4CdBhGUv0PWvgr0qpD5RSS/1jcd/zgJb8jRIVYmwo5nUmzM9BKZUB/Bn4gda6SalQWzMeDTE26PastfYBpyulRgDPKaVO6+HxQb9npdQlQJ3W+gOl1Jxw3hJibFDt2c95WutDSqk84DWlVEUPz8Zsz4PZc3cARZb7QuDQAK2lPzislBoN4P9e5x9PiJ+DUsqOYdj/qLX+i384ofdsorU+CrwFzCOx93we8DWlVBWGjPpFpdRTJPae0Vof8n+vA57DkFnivufBbNy3ABOVUuOUUinAVcALA7ymePICYPbkug5Ybxm/SimVqpQaB0wENg/A+vqMMlz0x4BdWuv7LC8l8p5H+T12lFLDgAuBChJ4z1rrn2qtC7XWJRj/Xt/QWn+TBN6zUmq4UirTvAa+DOygP/Y80JHkKKPQF2NkVnwG3D7Q64nhvtYBNYAH4zf5t4CRwN8wSiP/DcixPH+7/2dQCVw00Ovvw35nYfzpuR34yP91cYLveRqwzb/nHcDP/eMJu+eg/c+hM1smYfeMkc33sf9rp2mn+mPPUn5AEAQhARnMsowgCILQDWLcBUEQEhAx7oIgCAmIGHdBEIQERIy7IAhCAiLGXRAEIQER4y4IgpCAiHEXhhRKqZZeXh+hlPpuf61HEOKFGHdB6MoIQIy7MOgR4y4MWZRS3/R3Q/pIKbVKKWUDVgKn+Mf+J8R7nlZKPaOU+qdSar9S6qv9v3JB6B0x7sKQRCk1CViEUY71dMAHfAOjK85nWuvTtdb/EeKtXwD2aq3P8T+/vJ+WLAgRMZjruQtCNHwJOBPY4q8bPwyj7Oo73b3BX70xF1jhHyoHTvK/tgQ4B/gK8CqwTWu9Kl6LF4TeEOMuDFUU8KTW+qddBo1OUN1xGrBba+3230/HqPaH1nqNUmo9kKy1vikO6xWEiBBZRhiq/A24wt8dx+xGPxZoxmjSHYovAMVKqTR/be4VwP+zvH4m8GEc1ywIYSPGXRgyKKWSgTYArXU58DOM3pbbgdeA0VrrI8D7SqkdIQKqXwD+iNE1aQvwiNb6fcvrZwIfxHcXghAeUs9dGDIopb4APKq17lM3eaXUO8CNWuvKbl5fB9ygtW6NYpmCEBPEuAtDAqXUTcC/YTTf/msf5zgIFGmtO2K6OEGIA2LcBUEQEhDR3AVBEBIQMe6CIAgJiBh3QRCEBESMuyAIQgIixl0QBCEBEeMuCIKQgIhxFwRBSED+P8F6SWz8Qu+mAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "h = (\n", - " hist.Hist.new\n", - " .IntCat(range(6), label=\"Sample\")\n", - " .Reg(100, 0, 500, label=\"Jet $p_T$\")\n", - " .Double()\n", - ")\n", - "for i, sample in enumerate(samples):\n", - " h.fill(i, ak.flatten(sample.Jet.pt))\n", - "\n", - "fig, ax = plt.subplots()\n", - "h.plot1d(ax=ax)\n", - "ax.set_yscale(\"log\")\n", - "ax.legend(title=\"Sample\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/05-scaleout.ipynb b/05-scaleout.ipynb new file mode 100644 index 0000000..59c6679 --- /dev/null +++ b/05-scaleout.ipynb @@ -0,0 +1,344 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "6ecec3ca", + "metadata": {}, + "outputs": [], + "source": [ + "import awkward as ak\n", + "import dask\n", + "from distributed import performance_report\n", + "import hist\n", + "from hist.dask import Hist\n", + "import json\n", + "from coffea import processor\n", + "from coffea.nanoevents import BaseSchema, NanoAODSchema \n", + "from coffea.dataset_tools import apply_to_dataset, apply_to_fileset, preprocess, rucio_utils\n", + "from coffea.dataset_tools import max_chunks, max_files, slice_chunks, slice_files\n", + "from coffea.analysis_tools import Weights, PackedSelection\n", + "import corrections\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0c5cb60-03c3-40a2-89b9-e4c9225ff2f5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "class MyZPeak(processor.ProcessorABC):\n", + " def process(self, events):\n", + " dataset = events.metadata['dataset']\n", + " isRealData = \"genWeight\" not in events.fields\n", + " #sumw = 0. if isRealData else ak.sum(events.genWeight, axis=0)\n", + " weights = Weights(None)\n", + " ps = PackedSelection()\n", + " \n", + " if isRealData:\n", + " weights.add(\"nominal\", ak.ones_like(events.event))\n", + " ps.add(\"lumimask\", corrections.lumimask(events.run, events.luminosityBlock))\n", + " else:\n", + " weights.add(\"genWeight\", events.genWeight)\n", + " # for symmetry, we can use a trivially-true array for \"lumimask\" in MC\n", + " ps.add(\"lumimask\", ak.ones_like(events.event, dtype=bool))\n", + " \n", + " events[\"goodmuons\"] = events.Muon[\n", + " (events.Muon.pt >= 20.)\n", + " & events.Muon.tightId\n", + " ]\n", + " ps.add(\"ossf\", (ak.num(events.goodmuons) == 2) & (ak.sum(events.goodmuons.charge, axis=1) == 0))\n", + " \n", + " # https://twiki.cern.ch/twiki/bin/view/CMS/MuonHLT2018\n", + " ps.add(\"trigger\", events.HLT.Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ_Mass3p8)\n", + " \n", + " # add first and second muon p4 in every event together\n", + " sel_events = events[ps.require(lumimask=True, ossf=True, trigger=True)]\n", + " sel_zcand = sel_events.goodmuons[:, 0] + sel_events.goodmuons[:, 1]\n", + " sel_weights = weights.weight()[ps.all(\"lumimask\", \"ossf\", \"trigger\")] \n", + "\n", + " cutflow = {\"lumimask\": ak.sum(ps.require(lumimask=True), axis=0),\n", + " \"ossf\": ak.sum(ps.require(lumimask=True, ossf=True), axis=0),\n", + " \"trigger\": ak.sum(ps.require(lumimask=True, ossf=True, trigger=True), axis=0),\n", + " } \n", + "\n", + " return {\n", + " \"sumw\": weights.weightStatistics,\n", + " \"cutflow\": cutflow,\n", + " \"mass\": (\n", + " Hist.new\n", + " .Reg(120, 0., 120., label=\"$m_{\\mu\\mu}$ [GeV]\")\n", + " .Weight()\n", + " .fill(sel_zcand.mass, weight=sel_weights)\n", + " )\n", + " }\n", + "\n", + " def postprocess(self, accumulator):\n", + " return accumulator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef8ed89c-606f-4d6b-9ee8-65fc51a39bbb", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from dask.distributed import Client\n", + "\n", + "client = Client(\"tls://localhost:8786\")\n", + "client" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e4fa5b5", + "metadata": {}, + "outputs": [], + "source": [ + "import shutil\n", + "shutil.make_archive(\"corrections\", \"zip\", base_dir=\"corrections\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5954b16e-1e8c-4280-af62-c487a2b49d69", + "metadata": {}, + "outputs": [], + "source": [ + "client.upload_file(\"corrections.zip\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1645956d-00ce-4fee-b521-8296097a5a08", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with open(\"fileset.json\", \"rt\") as file:\n", + " initial_fileset = json.load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fca39dc-246a-424a-8e43-4b0771d766ae", + "metadata": {}, + "outputs": [], + "source": [ + "preprocessed_available, preprocessed_total = preprocess(\n", + " initial_fileset,\n", + " step_size=50_000,\n", + " align_clusters=None,\n", + " skip_bad_files=True,\n", + " recalculate_steps=False,\n", + " files_per_batch=1,\n", + " file_exceptions=(OSError,),\n", + " save_form=True,\n", + " uproot_options={},\n", + " step_size_safety_factor=0.5,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81d2939e-a443-45d1-b010-f9cf90a38400", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import gzip, pickle, json\n", + "output_file = \"scaleout_fileset\"\n", + "with gzip.open(f\"{output_file}_available.json.gz\", \"wt\") as file:\n", + " json.dump(preprocessed_available, file, indent=2)\n", + " print(f\"Saved available fileset chunks to {output_file}_available.json.gz\")\n", + "with gzip.open(f\"{output_file}_all.json.gz\", \"wt\") as file:\n", + " json.dump(preprocessed_total, file, indent=2)\n", + " print(f\"Saved complete fileset chunks to {output_file}_all.json.gz\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d7762d7-e4d3-45ee-acda-eb816ef47e42", + "metadata": {}, + "outputs": [], + "source": [ + "test_preprocessed_files = max_files(preprocessed_available, 30)\n", + "test_preprocessed = max_chunks(test_preprocessed_files, 30)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad9fd74e-ee15-4d10-8822-6729325d7749", + "metadata": {}, + "outputs": [], + "source": [ + "#small_tg, small_rep = apply_to_fileset(data_manipulation=MyZPeak(),\n", + " #fileset=test_preprocessed,\n", + "tg, rep = apply_to_fileset(data_manipulation=MyZPeak(), \n", + " fileset=test_preprocessed,\n", + " schemaclass=NanoAODSchema,\n", + " uproot_options={\"allow_read_errors_with_report\": (OSError, KeyError)},\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "0174d912-befa-4de5-8263-ed4f703457b9", + "metadata": {}, + "source": [ + "## Distributed performance_report\n", + "The dask distributed performance_report will save an html page of our dask computations,\n", + "preserving a record of the tasks, performance profiling, and so on" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "acf49610-9b33-4b24-a72f-0c42cabe3141", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "performance_report_name = \"scaleout_report.html\"\n", + "with performance_report(performance_report_name, stacklevel=1, mode=None, storage_options=None):\n", + " result, report = dask.compute(tg, rep)" + ] + }, + { + "cell_type": "markdown", + "id": "ae858763-7cf8-45c8-8c5f-4214235b86ed", + "metadata": {}, + "source": [ + "### Computing the luminosity scaling\n", + "The coffea lumi_tools subpackage contains tools for calculating the lumi processed\n", + "We'll take a simpler approach, calculating the fraction of the dataset we computed\n", + "and scaling the known-luminosity of the 2018A run by this fraction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb1af3a6-1c44-4acf-b8c0-44441091332a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Compute h\n", + "def total_data(events):\n", + " isRealData = \"genWeight\" not in events.fields\n", + " if isRealData:\n", + " events = events[\n", + " corrections.lumimask(events.run, events.luminosityBlock)\n", + " ]\n", + " return ak.num(events, axis=0)\n", + " else:\n", + " return -1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd0c1e3f-4992-432c-955f-168dfe978f52", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# This number should be calculated on the preprocessed_total,\n", + "# but some of those files may be inaccessible. We rely upon most being readable\n", + "dfd, _ = apply_to_fileset(data_manipulation=total_data,\n", + " fileset=preprocessed_available,\n", + " schemaclass=NanoAODSchema,\n", + " uproot_options={\"allow_read_errors_with_report\": (OSError, KeyError)},\n", + " )\n", + "data_fraction_den = dfd[\"DoubleMuon2018A\"].compute()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3be3894b-0029-45d6-98da-ed727e761e55", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "\n", + "data_fraction_num = result[\"DoubleMuon2018A\"][\"cutflow\"][\"lumimask\"]\n", + "data_fraction = data_fraction_num / data_fraction_den\n", + "print(data_fraction)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c89aa2b9-ac03-4d63-82de-dd1506dfe18b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "data = result[\"DoubleMuon2018A\"][\"mass\"]\n", + "\n", + "lumi = 14.0\n", + "xsweight = lumi * 1e3 * 6225.42 * data_fraction / result[\"ZJets2018\"][\"sumw\"][\"genWeight\"][\"sumw\"]\n", + "sim = result[\"ZJets2018\"][\"mass\"] * xsweight" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7149f305-8505-4a9c-bb7a-cd9af31d5a34", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "sim.plot(ax=ax, histtype=\"fill\", label=\"Z+jets\")\n", + "data.plot(ax=ax, histtype=\"errorbar\", color=\"k\", label=\"Data\")\n", + "ax.set_xlim(60, 120)\n", + "ax.legend()" + ] + } + ], + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/06-samplegame.ipynb b/06-samplegame.ipynb new file mode 100644 index 0000000..8892806 --- /dev/null +++ b/06-samplegame.ipynb @@ -0,0 +1,117 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The sample guessing game\n", + "In this game, we analyze 6 files, `sample[0-6].root` that are each a small 500k event sample of a CMS NanoAOD dataset. All generator-level branches have been removed. Your task is to figure out which file came from which dataset. To make it a bit easier, here are the 6 possible datasets:\n", + "\n", + " * `DY2JetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8`, producing $Z(\\to \\ell\\ell)+2j$ events via QCD processes;\n", + " * `ST_t-channel_4f_leptonDecays_TuneCP5_PSweights_13TeV-amcatnlo-pythia8`, producing single-top events through W boson exchange between a light and $b$ quark, where the $W$ boson from the top decay itself decays leptonically;\n", + " * `GluGluHToWWTo2L2Nu_M125_13TeV_powheg2_JHUGenV714_pythia8`, producing Higgs boson events through gluon fusion, where the Higgs boson decays via $H\\to WW^{*}\\to 2\\ell2\\nu$;\n", + " * `GluGluHToZZTo2L2Q_M125_13TeV_powheg2_JHUGenV7011_pythia8`, producing Higgs boson events through gluon fusion, where the Higgs boson decays via $H\\to ZZ^{*}\\to 2\\ell2q$;\n", + " * `TTTo2L2Nu_TuneCP5_13TeV-powheg-pythia8`, producing di-top events, where both $W$ bosons from the top quark decays must decay leptonically; and\n", + " * `WWTo2L2Nu_NNPDF31_TuneCP5_13TeV-powheg-pythia8`, producing WW diboson events, where both W bosons decay leptonically $W\\to \\ell\\nu$.\n", + " \n", + "In all cases, the lepton can be any flavor, $\\ell\\in\\{e,\\mu,\\tau\\}$. All 6 datasets were produced with the `RunIIAutumn18NanoAODv7-Nano02Apr2020_102X_upgrade2018_realistic_v21` conditions tag." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "delayed=False\n", + "\n", + "import numpy as np\n", + "import awkward as ak\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import dask\n", + "import hist\n", + "if delayed:\n", + " from hist.dask import Hist\n", + "else:\n", + " from hist import Hist\n", + "from coffea.nanoevents import NanoEventsFactory" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "prefix = 'root://xcache//store/user/ncsmith/samplegame/'\n", + "samples = [\n", + " NanoEventsFactory.from_root({f\"{prefix}sample{i}.root\": \"Events\"},\n", + " delayed=delayed,\n", + " entry_start=None if delayed else 0,\n", + " entry_stop=None if delayed else 50_000,\n", + " ).events()\n", + " for i in range(6)\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's an example of plotting all 6 samples together for one variable (here `Jet.pt`)\n", + "Let your physics intuition guide you, and good luck!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "h = (\n", + " Hist.new\n", + " .IntCat(range(6), label=\"Sample\")\n", + " .Reg(100, 0, 500, label=\"Jet $p_T$\")\n", + " .Double()\n", + ")\n", + "for i, sample in enumerate(samples):\n", + " h.fill(i, ak.flatten(sample.Jet.pt))\n", + "\n", + "fig, ax = plt.subplots()\n", + "if delayed:\n", + " h, *_ = dask.compute(h)\n", + "h.plot1d(ax=ax)\n", + "ax.set_yscale(\"log\")\n", + "ax.legend(title=\"Sample\")" + ] + } + ], + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/06-scaleout.ipynb b/06-scaleout.ipynb deleted file mode 100644 index c9c2ee7..0000000 --- a/06-scaleout.ipynb +++ /dev/null @@ -1,187 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "6ecec3ca", - "metadata": {}, - "outputs": [], - "source": [ - "import awkward as ak\n", - "import hist\n", - "from coffea import processor\n", - "import corrections\n", - "\n", - "\n", - "class MyZPeak(processor.ProcessorABC):\n", - " def process(self, events):\n", - " dataset = events.metadata['dataset']\n", - " isRealData = \"genWeight\" not in events.fields\n", - " sumw = 0. if isRealData else ak.sum(events.genWeight)\n", - " cutflow = {\"start\": len(events)}\n", - " \n", - " if isRealData:\n", - " events = events[\n", - " corrections.lumimask(events.run, events.luminosityBlock)\n", - " ]\n", - " cutflow[\"lumimask\"] = len(events)\n", - " \n", - " events[\"goodmuons\"] = events.Muon[\n", - " (events.Muon.pt >= 20.)\n", - " & events.Muon.tightId\n", - " ]\n", - "\n", - " events = events[\n", - " (ak.num(events.goodmuons) == 2)\n", - " & (ak.sum(events.goodmuons.charge, axis=1) == 0)\n", - " ]\n", - " cutflow[\"ossf\"] = len(events)\n", - " \n", - " # add first and second muon p4 in every event together\n", - " events[\"zcand\"] = events.goodmuons[:, 0] + events.goodmuons[:, 1]\n", - "\n", - " # require trigger\n", - " events = events[\n", - " # https://twiki.cern.ch/twiki/bin/view/CMS/MuonHLT2018\n", - " events.HLT.Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ_Mass3p8\n", - " ]\n", - " cutflow[\"trigger\"] = len(events)\n", - "\n", - " return {\n", - " dataset: {\n", - " \"entries\": len(events),\n", - " \"sumw\": sumw,\n", - " \"cutflow\": cutflow,\n", - " \"mass\": (\n", - " hist.Hist.new\n", - " .Reg(120, 0., 120., label=\"$m_{\\mu\\mu}$ [GeV]\")\n", - " .Double()\n", - " .fill(events.zcand.mass)\n", - " )\n", - " }\n", - " }\n", - "\n", - " def postprocess(self, accumulator):\n", - " return accumulator" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5a9702a9", - "metadata": {}, - "outputs": [], - "source": [ - "from dask.distributed import Client\n", - "\n", - "client = Client(\"tls://localhost:8786\")\n", - "client" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e4fa5b5", - "metadata": {}, - "outputs": [], - "source": [ - "import shutil\n", - "shutil.make_archive(\"corrections\", \"zip\", base_dir=\"corrections\")\n", - "client.upload_file(\"corrections.zip\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7f2e7388", - "metadata": {}, - "outputs": [], - "source": [ - "from coffea.nanoevents import NanoAODSchema\n", - "\n", - "\n", - "runner = processor.Runner(\n", - " executor = processor.DaskExecutor(client=client),\n", - " schema=NanoAODSchema,\n", - " # maxchunks=10,\n", - ")\n", - "\n", - "result = runner(\n", - " \"fileset.json\",\n", - " \"Events\",\n", - " processor_instance=MyZPeak()\n", - ")\n", - "result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9e7a8b71", - "metadata": {}, - "outputs": [], - "source": [ - "data = result[\"DoubleMuon2018A\"][\"mass\"]\n", - "\n", - "lumi = 14.0\n", - "xsweight = lumi * 1e3 * 6225.42 / result[\"ZJets2018\"][\"cutflow\"][\"start\"]\n", - "sim = result[\"ZJets2018\"][\"mass\"] * xsweight" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9df6ee82", - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "fig, ax = plt.subplots()\n", - "sim.plot(ax=ax, histtype=\"fill\", label=\"Z+jets\")\n", - "data.plot(ax=ax, histtype=\"errorbar\", color=\"k\", label=\"Data\")\n", - "ax.set_xlim(60, 120)\n", - "ax.legend()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e69b81e0", - "metadata": {}, - "outputs": [], - "source": [ - "result[\"DoubleMuon2018A\"][\"cutflow\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d62acb50", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/advanced-01-numba.ipynb b/advanced-01-numba.ipynb new file mode 100644 index 0000000..217a00e --- /dev/null +++ b/advanced-01-numba.ipynb @@ -0,0 +1,425 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Coffea Processors\n", + "This is the numba portion of a rendered copy of [processor.ipynb](https://github.com/CoffeaTeam/coffea/blob/master/binder/processor.ipynb). " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import hist\n", + "import dask\n", + "import awkward as ak\n", + "import hist.dask as hda\n", + "import dask_awkward as dak\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from coffea import processor\n", + "from coffea.nanoevents import NanoEventsFactory, BaseSchema\n", + "from coffea.nanoevents.methods import candidate\n", + "from coffea.dataset_tools import (\n", + " apply_to_fileset,\n", + " max_chunks,\n", + " preprocess,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from dask.distributed import Client\n", + "\n", + "client = Client(\"tls://localhost:8786\")\n", + "client" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fileset = {\n", + " 'DoubleMuon': {\n", + " \"files\": {\n", + " 'root://xcache//store/user/ncsmith/opendata_mirror/Run2012B_DoubleMuParked.root': \"Events\",\n", + " #'root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/Run2012B_DoubleMuParked.root': \"Events\",\n", + " 'root://xcache//store/user/ncsmith/opendata_mirror/Run2012C_DoubleMuParked.root': \"Events\",\n", + " #'root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/Run2012C_DoubleMuParked.root': \"Events\"\n", + " },\n", + " \"metadata\": {\n", + " \"is_mc\": False,\n", + " },\n", + " },\n", + " 'ZZ to 4mu': {\n", + " \"files\": {\n", + " 'root://xcache//store/user/ncsmith/opendata_mirror/ZZTo4mu.root': \"Events\"\n", + " #'root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/ZZTo4mu.root': \"Events\"\n", + " },\n", + " \"metadata\": {\n", + " \"is_mc\": True,\n", + " },\n", + " }\n", + "}\n", + "\n", + "\n", + "dataset_runnable, dataset_updated = preprocess(\n", + " fileset,\n", + " align_clusters=False,\n", + " step_size=100_000,\n", + " files_per_batch=1,\n", + " skip_bad_files=True,\n", + " save_form=False,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Getting fancy\n", + "Let's flesh out the processor from the coffea-04-processing notebook into a 4-muon analysis, searching for diboson events:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from collections import defaultdict\n", + "import numba\n", + "\n", + "\n", + "@numba.njit\n", + "def find_4lep_kernel(events_leptons, builder):\n", + " \"\"\"Search for valid 4-lepton combinations from an array of events * leptons {charge, ...}\n", + " \n", + " A valid candidate has two pairs of leptons that each have balanced charge\n", + " Outputs an array of events * candidates {indices 0..3} corresponding to all valid\n", + " permutations of all valid combinations of unique leptons in each event\n", + " (omitting permutations of the pairs)\n", + " \"\"\"\n", + " for leptons in events_leptons:\n", + " builder.begin_list()\n", + " nlep = len(leptons)\n", + " for i0 in range(nlep):\n", + " for i1 in range(i0 + 1, nlep):\n", + " if leptons[i0].charge + leptons[i1].charge != 0:\n", + " continue\n", + " for i2 in range(nlep):\n", + " for i3 in range(i2 + 1, nlep):\n", + " if len({i0, i1, i2, i3}) < 4:\n", + " continue\n", + " if leptons[i2].charge + leptons[i3].charge != 0:\n", + " continue\n", + " builder.begin_tuple(4)\n", + " builder.index(0).integer(i0)\n", + " builder.index(1).integer(i1)\n", + " builder.index(2).integer(i2)\n", + " builder.index(3).integer(i3)\n", + " builder.end_tuple()\n", + " builder.end_list()\n", + "\n", + " return builder\n", + "\n", + "\n", + "def find_4lep(events_leptons):\n", + " if ak.backend(events_leptons) == \"typetracer\":\n", + " # here we fake the output of find_4lep_kernel since\n", + " # operating on length-zero data returns the wrong layout!\n", + " ak.typetracer.length_zero_if_typetracer(events_leptons.charge) # force touching of the necessary data\n", + " return ak.Array(ak.Array([[(0,0,0,0)]]).layout.to_typetracer(forget_length=True))\n", + " return find_4lep_kernel(events_leptons, ak.ArrayBuilder()).snapshot()\n", + "\n", + "\n", + "class FancyDimuonProcessor(processor.ProcessorABC):\n", + " def process(self, events):\n", + " dataset_axis = hist.axis.StrCategory([], growth=True, name=\"dataset\", label=\"Primary dataset\")\n", + " mass_axis = hist.axis.Regular(300, 0, 300, name=\"mass\", label=r\"$m_{\\mu\\mu}$ [GeV]\")\n", + " pt_axis = hist.axis.Regular(300, 0, 300, name=\"pt\", label=r\"$p_{T,\\mu}$ [GeV]\")\n", + " \n", + " h_nMuons = hda.Hist(\n", + " dataset_axis,\n", + " hda.hist.hist.axis.IntCategory(range(6), name=\"nMuons\", label=\"Number of good muons\"),\n", + " storage=\"weight\", label=\"Counts\",\n", + " )\n", + " h_m4mu = hda.hist.Hist(dataset_axis, mass_axis, storage=\"weight\", label=\"Counts\")\n", + " h_mZ1 = hda.hist.Hist(dataset_axis, mass_axis, storage=\"weight\", label=\"Counts\")\n", + " h_mZ2 = hda.hist.Hist(dataset_axis, mass_axis, storage=\"weight\", label=\"Counts\")\n", + " h_ptZ1mu1 = hda.hist.Hist(dataset_axis, pt_axis, storage=\"weight\", label=\"Counts\")\n", + " h_ptZ1mu2 = hda.hist.Hist(dataset_axis, pt_axis, storage=\"weight\", label=\"Counts\")\n", + " \n", + " cutflow = defaultdict(int)\n", + " \n", + " dataset = events.metadata['dataset']\n", + " muons = ak.zip({\n", + " \"pt\": events.Muon_pt,\n", + " \"eta\": events.Muon_eta,\n", + " \"phi\": events.Muon_phi,\n", + " \"mass\": events.Muon_mass,\n", + " \"charge\": events.Muon_charge,\n", + " \"isolation\": events.Muon_pfRelIso03_all,\n", + " }, with_name=\"PtEtaPhiMCandidate\", behavior=candidate.behavior)\n", + " \n", + " # make sure they are sorted by transverse momentum\n", + " muons = muons[ak.argsort(muons.pt, axis=1)]\n", + " \n", + " cutflow['all events'] = ak.num(muons, axis=0)\n", + " \n", + " # impose some quality and minimum pt cuts on the muons\n", + " muons = muons[\n", + " (muons.pt > 5)\n", + " & (muons.isolation < 0.2)\n", + " ]\n", + " cutflow['at least 4 good muons'] += ak.sum(ak.num(muons) >= 4)\n", + " h_nMuons.fill(dataset=dataset, nMuons=ak.num(muons))\n", + " \n", + " # reduce first axis: skip events without enough muons\n", + " muons = muons[ak.num(muons) >= 4]\n", + " \n", + " # find all candidates with helper function\n", + " fourmuon = dak.map_partitions(find_4lep, muons)\n", + " fourmuon = [muons[fourmuon[idx]] for idx in \"0123\"]\n", + "\n", + " fourmuon = ak.zip({\n", + " \"z1\": ak.zip({\n", + " \"lep1\": fourmuon[0],\n", + " \"lep2\": fourmuon[1],\n", + " \"p4\": fourmuon[0] + fourmuon[1],\n", + " }),\n", + " \"z2\": ak.zip({\n", + " \"lep1\": fourmuon[2],\n", + " \"lep2\": fourmuon[3],\n", + " \"p4\": fourmuon[2] + fourmuon[3],\n", + " }),\n", + " })\n", + "\n", + " cutflow['at least one candidate'] += ak.sum(ak.num(fourmuon) > 0)\n", + "\n", + " # require minimum dimuon mass\n", + " fourmuon = fourmuon[(fourmuon.z1.p4.mass > 60.) & (fourmuon.z2.p4.mass > 20.)]\n", + " cutflow['minimum dimuon mass'] += ak.sum(ak.num(fourmuon) > 0)\n", + "\n", + " # choose permutation with z1 mass closest to nominal Z boson mass\n", + " bestz1 = ak.singletons(ak.argmin(abs(fourmuon.z1.p4.mass - 91.1876), axis=1))\n", + " fourmuon = ak.flatten(fourmuon[bestz1])\n", + "\n", + " h_m4mu.fill(\n", + " dataset=dataset,\n", + " mass=(fourmuon.z1.p4 + fourmuon.z2.p4).mass,\n", + " )\n", + " h_mZ1.fill(\n", + " dataset=dataset, \n", + " mass=fourmuon.z1.p4.mass,\n", + " )\n", + " h_mZ2.fill(\n", + " dataset=dataset, \n", + " mass=fourmuon.z2.p4.mass,\n", + " )\n", + " h_ptZ1mu1.fill(\n", + " dataset=dataset,\n", + " pt=fourmuon.z1.lep1.pt,\n", + " )\n", + " h_ptZ1mu2.fill(\n", + " dataset=dataset,\n", + " pt=fourmuon.z1.lep2.pt,\n", + " )\n", + " return {\n", + " 'nMuons': h_nMuons,\n", + " 'mass': h_m4mu,\n", + " 'mass_z1': h_mZ1,\n", + " 'mass_z2': h_mZ2,\n", + " 'pt_z1_mu1': h_ptZ1mu1,\n", + " 'pt_z1_mu2': h_ptZ1mu2,\n", + " 'cutflow': {dataset: cutflow},\n", + " }\n", + "\n", + " def postprocess(self, accumulator):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import time\n", + "\n", + "tstart = time.time()\n", + "\n", + "to_compute = apply_to_fileset(\n", + " FancyDimuonProcessor(),\n", + " max_chunks(dataset_runnable, 300),\n", + " schemaclass=BaseSchema,\n", + " )\n", + "(out,) = dask.compute(to_compute)\n", + "print(out)\n", + "\n", + "elapsed = time.time() - tstart\n", + "print(elapsed)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "nevt = out['ZZ to 4mu']['cutflow']['ZZ to 4mu']['all events'] + out['DoubleMuon']['cutflow']['DoubleMuon']['all events']\n", + "print(\"Events/s:\", (nevt / elapsed).compute())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What follows is just us looking at the output, you can execute it if you wish" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# scale ZZ simulation to expected yield\n", + "lumi = 11.6 # 1/fb\n", + "zzxs = 7200 * 0.0336**2 # approximate 8 TeV ZZ(4mu)\n", + "nzz = out['ZZ to 4mu']['cutflow']['ZZ to 4mu']['all events']\n", + "\n", + "scaled = {}\n", + "for (name1, h1), (nam2, h2) in zip(out['ZZ to 4mu'].items(), out['DoubleMuon'].items()):\n", + " if isinstance(h1, hist.Hist) and isinstance(h2, hist.Hist):\n", + " scaled[name1] = h1.copy() + h2.copy()\n", + " scaled[name1].view()[0, :] *= lumi * zzxs / nzz.compute()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "scaled['nMuons'].plot1d(ax=ax, overlay='dataset')\n", + "ax.set_yscale('log')\n", + "ax.set_ylim(1, None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "\n", + "scaled['mass'][:, ::hist.rebin(4)].plot1d(ax=ax, overlay='dataset');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "\n", + "scaled['mass_z1'].plot1d(ax=ax, overlay='dataset');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "\n", + "scaled['mass_z2'].plot1d(ax=ax, overlay='dataset')\n", + "ax.set_xlim(2, 300)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "\n", + "scaled['pt_z1_mu1'].plot1d(ax=ax, overlay='dataset');" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "\n", + "scaled['pt_z1_mu2'].plot1d(ax=ax, overlay='dataset');" + ] + } + ], + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/fileset.json b/fileset.json index 8fd842f..fd6891b 100644 --- a/fileset.json +++ b/fileset.json @@ -1,148 +1,152 @@ { - "DoubleMuon2018A": [ - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/0555868D-6B32-D249-9ED1-6B9A6AABDAF7.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/07796DC0-9F65-F940-AAD1-FE82262B4B03.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/09BED5A5-E6CC-AC4E-9344-B60B3A186CFA.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/0BA8AE9C-DD73-5C4A-8CEE-D2583EED2987.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/0EE26CB3-281A-F044-928C-71C484801A88.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/10B55DFA-0821-2F4C-A167-4C32E9E9CB46.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/139A9CD3-523E-EB4A-88D0-C383A7965FCF.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/1D5F5E8C-ACED-6B4B-89BC-CB73AC1B0A0D.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2045B46A-1140-4748-876A-4D47867899E3.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2665B2E8-1135-AF40-82D1-5F142261B4EE.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/276A1513-927A-5D46-A5C3-8C26C76EB3FB.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2B1F690D-1EC2-CD40-8F73-C9587BC2A1FD.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2BB811DE-6C90-4D46-9BA7-F1FDAA7E4886.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/343CC4BB-33EA-7244-BD1A-7E4D75B167DB.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/346BDAA9-2646-7943-A07F-FD45AF6D4F0A.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/3A4CF01C-4DC4-9345-998C-2D875B329FBC.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/3DDD5A3F-D9CD-E14C-9D84-B4E64A1768DD.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/433C25FD-1E20-1A4A-9414-16E1D52F2CBE.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/46420107-37F1-DF41-B3B9-4E882D5C0C1B.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/46C9FECE-6771-0F40-A3AC-FCD297C227BA.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/495F2094-64A7-E74B-9072-480C8926C600.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/4B9A1B22-666D-7A4C-96AC-5F5D9D305E0C.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/4CB9A28F-BD33-4A4A-9AF3-C9D93C2C9CB5.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/53D11EEE-D3BE-6B41-A7C0-8056B7923ACF.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/54C285EB-2965-3F45-B6D0-4EAF80435FC3.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/57CDDE17-6579-294D-A42B-9C1FD01F9309.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/5AADA718-F7B6-B64B-BD12-B589FD69BBB6.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/5E146028-F9DA-DF4B-88A3-265E254D867D.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/609C12B9-B0F5-0A45-9D1C-B6DE2EE2C8C6.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/628748C1-F73D-CE4E-BF35-B4A653C02DB9.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/6331F65C-DFBF-7149-8743-3E0A24430492.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/635645AE-A795-D64C-A422-54E793B4258C.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/666B3844-A712-9547-9099-3DA8A027AF31.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/6E66CDDA-1D07-A649-91B7-234DE3849C24.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/71213F8D-F11C-5546-94B7-3CD4F3017CF3.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/712948FD-7CF8-B84E-A8DE-80CB4D7F2EE4.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/721784AD-5030-6146-B8B2-5D6C6EBF02E1.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/79C584F0-5E43-4144-8BA3-558B39A6CD2A.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/7C09B2FE-4DD0-2C41-BE19-A53FFCE7E12E.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/7C137374-E8E4-0646-93E5-0D0C85E73056.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/8C35337D-20A7-ED42-9858-63BCCFD2A461.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/8CBC98D1-B188-5148-9BC7-841EEC81B624.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/8E999177-B3F9-EE4E-8E89-95A2FB621C19.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/923AF931-4B5E-A04B-B1CA-A0893B729767.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/946474E3-8B93-AC4C-9DD8-56CD890B5532.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/9C9EACD1-5400-1D45-B2B9-B90BE1895D6A.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/9ECE7BB3-57F2-AE47-8EC7-A664E5F07EB0.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A3ED35CF-CC16-6C44-8BD2-CE09AA3CA843.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A8C82CB7-3094-9F4D-A8C3-36D4AA92D2C1.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A8D31937-AC8B-A542-B830-0384FA372B1D.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A9C84EEB-BE63-E548-9A0F-76E3D0256C5B.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AA391086-4A93-C646-98BD-28C7F2E34253.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AD63A27E-7342-5A4C-95F2-4FB6E1B8B6D4.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AD8A8927-5783-C243-8E59-C2281E510D0F.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AE9CEFEA-8069-6A4C-A2E4-7D4699E92299.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/B5E993D5-9533-7045-979C-9D724835C62E.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/B64FB825-9CA1-574B-8394-C671E6707D55.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/BA073491-215E-2241-B866-C2276FEDFA98.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/BF39D8A1-4603-7544-A930-593BB93CA2BE.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C51A4416-4D2B-AD47-B3D6-29EA9F5D8CE7.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C7E969E4-29A1-984A-8527-C8E44964450B.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C83EA9E0-AF1B-0F41-B1C1-4BAD869BA9E4.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C841E007-F4FF-D347-84C7-F6F0B3B98606.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C9D9A02C-C192-6547-9C9A-4CC85F006A26.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/CD25F914-CA18-2847-989C-91E6BF71E22F.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/CFB7EA86-E446-F442-B92F-A9429F3A29C3.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/D652898C-ACE8-1C4E-84DE-3E34432B7B82.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DA4806B9-DCFC-E344-AA87-D13F3C158E29.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DD6D5FC5-534B-A94D-8242-2002A0A764B2.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DEA073D8-82BA-F14C-A40D-D15C7246D5CF.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DF26F2C2-8761-2D4A-953B-75128F50DEDD.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/E11C4036-174D-214E-8D56-811BE213B429.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/E164452D-3810-6F4C-9FEA-EAD991901C98.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/EAC3C712-C1D8-6446-BE01-08C44EB55C08.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/EB58749F-202D-6942-A562-9585843A62FE.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/EEC20024-C194-DB46-BCB1-B3C149972AC7.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F16C5A5E-EF95-1D40-A0C3-BA441FF790EC.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F1AF68A7-0E43-704F-95ED-F021EA729E09.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F4BB10CD-C611-F444-B236-41A4DA3BCDC9.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F593578D-D6BA-AC4D-97BF-705403892148.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F60CC6BE-5AA3-1F4C-8563-6B51945C9441.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FA184AF9-7AA9-9D4E-A9F7-58CE06938995.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FA93A4BF-AF81-5B4B-BD4E-BEC08EE0C68D.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FBC838D5-BD98-E649-8682-72BAFA819D8F.root", - "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FF6E5147-5AA7-3640-9F30-FA49DD27073C.root" - ], - "ZJets2018": [ - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/3391856D-092B-624A-A3BB-F6112936F5D9.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/4113D85C-7A97-8349-A164-D0AF161EFD1B.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/43FC6DD5-C2F1-F847-8F6A-EE1480BAB9E1.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/441063D2-9CEE-8043-9CC8-9BA75D26463F.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/51C9FDF1-F122-4943-87BA-6EFE4459F867.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/5973143C-C4F0-2E46-894F-0165FA1BB01B.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/77F36D6F-1209-B242-BEEF-66CB4A785A78.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/7F4CDDD8-5808-D046-B0A5-48E261C0DD64.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/83C2832F-611A-E34C-AEC2-08E5007D5AD5.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/93195E83-70B4-5848-AD36-DD562E44EB43.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/970CFDF1-F82B-764A-B0C2-F72462DB031D.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/9EF938C0-3F08-8240-A9C7-AD3957E89FDD.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/DB735CFE-2E39-324E-A1B9-4B798235959E.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/DBD32736-2540-4145-BAF6-AE20BF1D4544.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/F1E5BBFE-9D45-9B4F-8C73-7F9EBA65DF3F.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/F94D44E5-7F22-5840-9FBC-D2867DDC50FE.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/08A4919E-3971-8141-8C26-C4E00B5DBADB.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/0E56A24D-0333-AB43-9554-DE11223D624A.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/10A4E7FB-AE45-954A-84AD-D69540D5C59A.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/124CBC8A-3D8E-DA48-A4EF-44B58400F13C.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/15F719CB-CB32-FD48-8DCA-8BB53496CCCA.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/1A376B9E-9A7E-8540-B9D5-E51DA8F89DBB.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2C88168C-6A07-3642-B166-C7BC262B6B73.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2CCBC68D-FB53-384B-A2BB-98F79215FC17.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2D494ABA-4415-6246-8136-C48D11A2F80B.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2D508ADD-D554-D24E-9E31-D0434BBB17A7.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/31971833-48FA-4242-B0F3-20DB7365C780.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/31A7B7AE-7141-3440-9F00-D15B50210894.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/433FB6B8-175B-854B-8ABD-E4E0ACD0DE96.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/468E68CF-22F1-B047-A91F-B1FEAB1123DF.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/47B65D32-735E-C94C-B352-8F4E1A18B3A6.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/480549D3-C835-5648-ADD8-4E90F771A463.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/4F18B610-B322-8247-BC42-0B08710A1387.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/4F43E8B6-0634-034E-931F-F5DD30DA3302.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/53B042AE-E840-5643-8913-F8E9083D74AC.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/5854D387-42A2-8E46-8392-559FF9450092.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/5DA1002C-6CFC-3843-8A69-68FDDFFB19A2.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/704D5BC1-F21B-7643-A9D9-D57A3D1B39E6.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/74CD4EFA-E839-4E43-B2C9-8D57312C382F.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/86AF6A1D-C03D-9043-B80C-843C099E1664.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/86C92CED-B42E-3C46-8F9C-9C195EF44655.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/91D58402-B691-654D-B64A-3DDC9632AD23.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/9B0D4902-152A-A84B-B2B0-84B6B7F0858F.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/9E3461B2-6CA4-F444-ABDF-3B890FEB32BB.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/A2245E1C-1CD8-8541-AC44-555D1EC0EAAC.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/A281D79D-1AB7-4D49-9EED-2AC609AF0202.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/A3ABC487-C762-444A-8585-F668023EC2B8.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/AF3F2ABA-9725-AA4D-A1F1-45510A1854E6.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/B12CC304-F521-E14B-B1F7-E54E5E5A6D4E.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/BAE6285D-B0C3-1C43-AF2F-119FB45B0EA9.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/C7A884FF-434B-E346-81C1-1BD94203BC2A.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/DA515A53-0D58-AA42-A917-CE4642746D8E.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/DEF2382F-FEDD-2B49-9498-97EE3AD7A0AA.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/E074AFA3-6B0E-A74B-8D47-04C9A3D4DF4E.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/E9E8E477-2B5A-314A-8E95-B538A6D70535.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/F024C872-6B4C-2A48-AEB6-389CF255BE48.root", - "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/FED96E0A-68D0-8D41-9BE4-510E75032588.root" - ] + "DoubleMuon2018A": { + "files": { + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/0555868D-6B32-D249-9ED1-6B9A6AABDAF7.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/07796DC0-9F65-F940-AAD1-FE82262B4B03.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/09BED5A5-E6CC-AC4E-9344-B60B3A186CFA.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/0BA8AE9C-DD73-5C4A-8CEE-D2583EED2987.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/0EE26CB3-281A-F044-928C-71C484801A88.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/10B55DFA-0821-2F4C-A167-4C32E9E9CB46.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/139A9CD3-523E-EB4A-88D0-C383A7965FCF.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/1D5F5E8C-ACED-6B4B-89BC-CB73AC1B0A0D.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2045B46A-1140-4748-876A-4D47867899E3.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2665B2E8-1135-AF40-82D1-5F142261B4EE.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/276A1513-927A-5D46-A5C3-8C26C76EB3FB.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2B1F690D-1EC2-CD40-8F73-C9587BC2A1FD.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/2BB811DE-6C90-4D46-9BA7-F1FDAA7E4886.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/343CC4BB-33EA-7244-BD1A-7E4D75B167DB.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/346BDAA9-2646-7943-A07F-FD45AF6D4F0A.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/3A4CF01C-4DC4-9345-998C-2D875B329FBC.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/3DDD5A3F-D9CD-E14C-9D84-B4E64A1768DD.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/433C25FD-1E20-1A4A-9414-16E1D52F2CBE.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/46420107-37F1-DF41-B3B9-4E882D5C0C1B.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/46C9FECE-6771-0F40-A3AC-FCD297C227BA.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/495F2094-64A7-E74B-9072-480C8926C600.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/4B9A1B22-666D-7A4C-96AC-5F5D9D305E0C.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/4CB9A28F-BD33-4A4A-9AF3-C9D93C2C9CB5.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/53D11EEE-D3BE-6B41-A7C0-8056B7923ACF.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/54C285EB-2965-3F45-B6D0-4EAF80435FC3.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/57CDDE17-6579-294D-A42B-9C1FD01F9309.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/5AADA718-F7B6-B64B-BD12-B589FD69BBB6.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/5E146028-F9DA-DF4B-88A3-265E254D867D.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/609C12B9-B0F5-0A45-9D1C-B6DE2EE2C8C6.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/628748C1-F73D-CE4E-BF35-B4A653C02DB9.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/6331F65C-DFBF-7149-8743-3E0A24430492.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/635645AE-A795-D64C-A422-54E793B4258C.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/666B3844-A712-9547-9099-3DA8A027AF31.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/6E66CDDA-1D07-A649-91B7-234DE3849C24.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/71213F8D-F11C-5546-94B7-3CD4F3017CF3.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/712948FD-7CF8-B84E-A8DE-80CB4D7F2EE4.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/721784AD-5030-6146-B8B2-5D6C6EBF02E1.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/79C584F0-5E43-4144-8BA3-558B39A6CD2A.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/7C09B2FE-4DD0-2C41-BE19-A53FFCE7E12E.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/7C137374-E8E4-0646-93E5-0D0C85E73056.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/8C35337D-20A7-ED42-9858-63BCCFD2A461.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/8CBC98D1-B188-5148-9BC7-841EEC81B624.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/8E999177-B3F9-EE4E-8E89-95A2FB621C19.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/923AF931-4B5E-A04B-B1CA-A0893B729767.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/946474E3-8B93-AC4C-9DD8-56CD890B5532.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/9C9EACD1-5400-1D45-B2B9-B90BE1895D6A.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/9ECE7BB3-57F2-AE47-8EC7-A664E5F07EB0.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A3ED35CF-CC16-6C44-8BD2-CE09AA3CA843.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A8C82CB7-3094-9F4D-A8C3-36D4AA92D2C1.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A8D31937-AC8B-A542-B830-0384FA372B1D.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/A9C84EEB-BE63-E548-9A0F-76E3D0256C5B.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AA391086-4A93-C646-98BD-28C7F2E34253.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AD63A27E-7342-5A4C-95F2-4FB6E1B8B6D4.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AD8A8927-5783-C243-8E59-C2281E510D0F.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/AE9CEFEA-8069-6A4C-A2E4-7D4699E92299.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/B5E993D5-9533-7045-979C-9D724835C62E.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/B64FB825-9CA1-574B-8394-C671E6707D55.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/BA073491-215E-2241-B866-C2276FEDFA98.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/BF39D8A1-4603-7544-A930-593BB93CA2BE.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C51A4416-4D2B-AD47-B3D6-29EA9F5D8CE7.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C7E969E4-29A1-984A-8527-C8E44964450B.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C83EA9E0-AF1B-0F41-B1C1-4BAD869BA9E4.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C841E007-F4FF-D347-84C7-F6F0B3B98606.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/C9D9A02C-C192-6547-9C9A-4CC85F006A26.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/CD25F914-CA18-2847-989C-91E6BF71E22F.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/CFB7EA86-E446-F442-B92F-A9429F3A29C3.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/D652898C-ACE8-1C4E-84DE-3E34432B7B82.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DA4806B9-DCFC-E344-AA87-D13F3C158E29.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DD6D5FC5-534B-A94D-8242-2002A0A764B2.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DEA073D8-82BA-F14C-A40D-D15C7246D5CF.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/DF26F2C2-8761-2D4A-953B-75128F50DEDD.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/E11C4036-174D-214E-8D56-811BE213B429.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/E164452D-3810-6F4C-9FEA-EAD991901C98.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/EAC3C712-C1D8-6446-BE01-08C44EB55C08.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/EB58749F-202D-6942-A562-9585843A62FE.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/EEC20024-C194-DB46-BCB1-B3C149972AC7.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F16C5A5E-EF95-1D40-A0C3-BA441FF790EC.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F1AF68A7-0E43-704F-95ED-F021EA729E09.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F4BB10CD-C611-F444-B236-41A4DA3BCDC9.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F593578D-D6BA-AC4D-97BF-705403892148.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/F60CC6BE-5AA3-1F4C-8563-6B51945C9441.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FA184AF9-7AA9-9D4E-A9F7-58CE06938995.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FA93A4BF-AF81-5B4B-BD4E-BEC08EE0C68D.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FBC838D5-BD98-E649-8682-72BAFA819D8F.root": "Events", + "root://xcache//store/data/Run2018A/DoubleMuon/NANOAOD/02Apr2020-v1/30000/FF6E5147-5AA7-3640-9F30-FA49DD27073C.root": "Events" + } + }, + "ZJets2018": { + "files": { + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/3391856D-092B-624A-A3BB-F6112936F5D9.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/4113D85C-7A97-8349-A164-D0AF161EFD1B.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/43FC6DD5-C2F1-F847-8F6A-EE1480BAB9E1.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/441063D2-9CEE-8043-9CC8-9BA75D26463F.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/51C9FDF1-F122-4943-87BA-6EFE4459F867.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/5973143C-C4F0-2E46-894F-0165FA1BB01B.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/77F36D6F-1209-B242-BEEF-66CB4A785A78.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/7F4CDDD8-5808-D046-B0A5-48E261C0DD64.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/83C2832F-611A-E34C-AEC2-08E5007D5AD5.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/93195E83-70B4-5848-AD36-DD562E44EB43.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/970CFDF1-F82B-764A-B0C2-F72462DB031D.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/9EF938C0-3F08-8240-A9C7-AD3957E89FDD.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/DB735CFE-2E39-324E-A1B9-4B798235959E.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/DBD32736-2540-4145-BAF6-AE20BF1D4544.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/F1E5BBFE-9D45-9B4F-8C73-7F9EBA65DF3F.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/100000/F94D44E5-7F22-5840-9FBC-D2867DDC50FE.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/08A4919E-3971-8141-8C26-C4E00B5DBADB.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/0E56A24D-0333-AB43-9554-DE11223D624A.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/10A4E7FB-AE45-954A-84AD-D69540D5C59A.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/124CBC8A-3D8E-DA48-A4EF-44B58400F13C.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/15F719CB-CB32-FD48-8DCA-8BB53496CCCA.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/1A376B9E-9A7E-8540-B9D5-E51DA8F89DBB.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2C88168C-6A07-3642-B166-C7BC262B6B73.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2CCBC68D-FB53-384B-A2BB-98F79215FC17.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2D494ABA-4415-6246-8136-C48D11A2F80B.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/2D508ADD-D554-D24E-9E31-D0434BBB17A7.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/31971833-48FA-4242-B0F3-20DB7365C780.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/31A7B7AE-7141-3440-9F00-D15B50210894.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/433FB6B8-175B-854B-8ABD-E4E0ACD0DE96.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/468E68CF-22F1-B047-A91F-B1FEAB1123DF.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/47B65D32-735E-C94C-B352-8F4E1A18B3A6.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/480549D3-C835-5648-ADD8-4E90F771A463.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/4F18B610-B322-8247-BC42-0B08710A1387.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/4F43E8B6-0634-034E-931F-F5DD30DA3302.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/53B042AE-E840-5643-8913-F8E9083D74AC.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/5854D387-42A2-8E46-8392-559FF9450092.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/5DA1002C-6CFC-3843-8A69-68FDDFFB19A2.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/704D5BC1-F21B-7643-A9D9-D57A3D1B39E6.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/74CD4EFA-E839-4E43-B2C9-8D57312C382F.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/86AF6A1D-C03D-9043-B80C-843C099E1664.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/86C92CED-B42E-3C46-8F9C-9C195EF44655.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/91D58402-B691-654D-B64A-3DDC9632AD23.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/9B0D4902-152A-A84B-B2B0-84B6B7F0858F.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/9E3461B2-6CA4-F444-ABDF-3B890FEB32BB.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/A2245E1C-1CD8-8541-AC44-555D1EC0EAAC.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/A281D79D-1AB7-4D49-9EED-2AC609AF0202.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/A3ABC487-C762-444A-8585-F668023EC2B8.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/AF3F2ABA-9725-AA4D-A1F1-45510A1854E6.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/B12CC304-F521-E14B-B1F7-E54E5E5A6D4E.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/BAE6285D-B0C3-1C43-AF2F-119FB45B0EA9.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/C7A884FF-434B-E346-81C1-1BD94203BC2A.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/DA515A53-0D58-AA42-A917-CE4642746D8E.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/DEF2382F-FEDD-2B49-9498-97EE3AD7A0AA.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/E074AFA3-6B0E-A74B-8D47-04C9A3D4DF4E.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/E9E8E477-2B5A-314A-8E95-B538A6D70535.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/F024C872-6B4C-2A48-AEB6-389CF255BE48.root": "Events", + "root://xcache//store/mc/RunIIAutumn18NanoAODv7/DYJetsToLL_M-50_TuneCP5_13TeV-madgraphMLM-pythia8/NANOAODSIM/Nano02Apr2020_102X_upgrade2018_realistic_v21-v1/70000/FED96E0A-68D0-8D41-9BE4-510E75032588.root": "Events" + } + } }