Replies: 2 comments
-
This is not so much about making it a cut string in Uproot as finding a one-liner in Awkward Array. Since operations are columnar, For instance, if you start with >>> import awkward as ak
>>> array = ak.Array([[1, 2, 3], [], [4, 5]])
>>> array
<Array [[1, 2, 3], [], [4, 5]] type='3 * var * int64'> you can't do >>> (ak.num(array) > 0) & (array[:, 0])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jpivarski/irishep/awkward-1.0/awkward/highlevel.py", line 996, in __getitem__
tmp = ak._util.wrap(self.layout[where], self._behavior)
ValueError: in ListOffsetArray64 attempting to get 0, index out of range but you can do >>> array[ak.num(array) > 0, 0]
<Array [1, 4] type='2 * int64'> or even >>> array[ak.num(array) > 0][:, 0]
<Array [1, 4] type='2 * int64'> The thing is that the selection of events (first dimension) that makes the selection of particles (second dimension) valid has to be applied to the same array. When Following this logic, I was about to say that your cut string could be MuonsPt.mask[nMuons == 2][:, 0] > 20 By analogy (going back to my example), >>> array.mask[ak.num(array) > 0]
<Array [[1, 2, 3], None, [4, 5]] type='3 * option[var * int64]'> puts a "None" in the event that fails the multiplicity cut, and then >>> array.mask[ak.num(array) > 0][:, 0]
<Array [1, None, 4] type='3 * ?int64'> passes that "None" through, and >>> array.mask[ak.num(array) > 0][:, 0] > 1
<Array [False, None, True] type='3 * ?bool'> creates a boolean-or-None array, which at least has the right length; it applies to "all events," not just "events with two muons" (going back to your example, by analogy). This would drop values of >>> ak.fill_none(array.mask[ak.num(array) > 0][:, 0] > 1, False)
<Array [False, False, True] type='3 * bool'> which, in your case, is
This replaces all "None" values with "False" values, giving you a purely boolean array with "False" for both the case of not having two muons and the case of the first muon having a pT less than 20. As usual, turning things into one-liners doesn't always make them more clear. If you're doing this for pedagogy, will your students/audience be able to read that one-liner? They'd need to know about ak.mask and ak.fill_none. (I'm not sure it was a great idea to introduce the |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot for this detailed and interesting explanation! Thanks again! |
Beta Was this translation helpful? Give feedback.
-
Hi,
I have a pretty standard tree (showing only part of it):
nMuons can be 0, in which cas MuonsPt is empty. I want to filter on the MuonsPt, so I naively do:
but it fails because the cut on MuonsPt is evaluated even for events with nMuons==0, and fails with an index out of range error.
I managed to do what I want in two steps (first filtering on nMuons, later on MuonsPt) with the array filter synthax, but I would prefer the cut string approach for pedagogical reasons.
What would you suggest in such a case?
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions