--- name: coffea description: >- Use when building a columnar HEP analysis with coffea: loading ROOT data as NanoEvents, choosing a schema, writing a ProcessorABC processor, accumulating histograms or cutflows, and scaling execution from local iteration to Dask. --- # coffea Use coffea to organize columnar analysis over uproot, Awkward Array, and hist. Keep the physics selection independent of the executor so the same processor can run locally or on distributed infrastructure. ## Choose the data model first - Inspect tree and branch names with uproot before selecting a schema. - Use `BaseSchema` for an unfamiliar or flat custom NTuple; branches remain directly accessible by name. - Use a named schema only when the input format actually conforms to it. - Build a small custom schema when stable branch naming justifies structured collections. Do not silently apply NanoAOD assumptions to other formats. ## Minimal processor ```python import awkward as ak from coffea import processor from hist import Hist class Analysis(processor.ProcessorABC): def process(self, events): selected = events[events.mass > 5.2] h_mass = Hist.new.Reg(60, 5.0, 5.6, name="mass").Double() h_mass.fill(selected.mass) return { "events": len(events), "selected": len(selected), "sumw": ak.sum(events.weight), "mass": h_mass, } def postprocess(self, accumulator): return accumulator ``` Run a representative file and a small `maxchunks` value before scaling out: ```python from coffea import processor from coffea.nanoevents import BaseSchema fileset = {"signal": ["signal.root"]} runner = processor.Runner( executor=processor.IterativeExecutor(status=True), schema=BaseSchema, chunksize=100_000, maxchunks=2, ) result = runner(fileset, treename="Events", processor_instance=Analysis()) ``` ## Analysis invariants - Preserve jagged structure; use Awkward operations instead of Python loops. - Confirm branch units and missing-value conventions from the producing format. - Apply event weights and systematic variations explicitly, and return mergeable accumulators from every chunk. - Treat `skipbadfiles=True` as a diagnostic choice, not a default: record every skipped input and investigate before producing final results. - Validate local and distributed results on the same fixed subset before a large run. Use the current [coffea documentation](https://coffea-hep.readthedocs.io/) for executor and schema APIs, which evolve between releases.