Example #1
0
def tags_to_quarks(eventWise, tag_idxs, quark_pdgids=[-5, 5]):
    """
    Find the quark that is most strongly assocated with each tag particle.

    Parameters
    ----------
    eventWise : EventWise
        dataset containing locations of particles and jets
    tag_idx : iterable of ints
        the idx of the tag particles as found in the EventWise
    quark_pdgids : iterable of ints
        list of mcpids considred to be quarks
         (Default value = [-5, 5])

    Returns
    -------
    quark_parents : numpy array of ints
        the idx of the quark parents as found in the EventWise

    """
    assert eventWise.selected_event is not None
    if np.all([pid in quark_pdgids for pid in eventWise.MCPID[tag_idxs]]):
        # check if the tags are already quarks
        return tag_idxs
    # fetch the angular variables for speed
    rapidity = eventWise.Rapidity
    phi = eventWise.Phi
    pids = eventWise.MCPID
    parents = eventWise.Parents
    children = eventWise.Children
    # fetch any quarks in the tag's parents
    quark_parents = []
    quark_distances = []
    for tag_idx in tag_idxs:
        this_qparents = []
        parent_stack = [tag_idx]
        while parent_stack:
            idx = parent_stack.pop()
            if pids[idx] in quark_pdgids:
                this_qparents.append(idx)
            else:
                parent_stack += parents[idx].tolist()
        this_qparents = list(set(this_qparents))
        # if there are multiple parents, abandon any that have b-quark decendants
        if len(this_qparents) > 1:
            last_b = [
                5 not in np.abs(pids[children[idx]]) for idx in this_qparents
            ]
            if sum(last_b):  # there must be at least 1 remaining
                this_qparents = [
                    this_qparents[i] for i, l in enumerate(last_b) if l
                ]
        quark_parents.append(this_qparents)
        # if there is more than one quark on a tag calculate the deltaR to that quark
        # if these is just one parent, call the deltaR 0
        if len(this_qparents) == 1:
            quark_distances.append(np.zeros(1))
        elif len(this_qparents) > 1:
            distances = np.sqrt((rapidity[this_qparents] -
                                 rapidity[tag_idx])**2 +
                                Components.angular_distance(
                                    phi[this_qparents], phi[tag_idx])**2)
            quark_distances.append(distances.tolist())
        else:
            raise RuntimeError(
                f"Why does this tag have no quark parents? event_n = {eventWise.selected_event}, tag_idx = {tag_idx}."
            )
    # go through the quark distances, assigning each quark to its closest tag
    remaining = list(range(len(quark_parents)))
    while remaining:
        tag_num = np.argmin([np.min(quarks) for quarks in quark_distances])
        remaining.remove(tag_num)  # we found this one
        quark_distances[tag_num] = [np.inf]
        quark_num = np.argmin(quark_distances[tag_num])
        quark_idx = quark_parents[tag_num].pop(quark_num)
        quark_parents[tag_num] = quark_idx
        # chekc if this quark_idx is found elsewhere
        for num in remaining:
            try:
                quark_num2 = quark_parents[num].index(quark_idx)
            except ValueError:
                # it wasn't in this list, that's fine
                pass
            else:
                quark_parents[num].pop(quark_num2)
                quark_distances[num].pop(quark_num2)
                # check if there is now only one parent left at num
                if len(quark_distances[num]) == 1:
                    quark_distances[num][0] = 0.  # set this distance to 0
    assert np.all([isinstance(q, int) for q in quark_parents])
    return quark_parents
Example #2
0
"""Processing events in version 1 of the paper"""
#hepmc_dir = "/scratch/hadh1g17/MG5_aMC_v2_6_7/ttsemileptonic/Events/run_02/tag_1_pythia8_events.hepmc"
#hepmc_dir = "../megaIgnore/ttsemileptonic_pt4.hepmc"
hepmc_dir = "/home/henry/Programs/MG5_aMC_v2_9_2/ttsemileptonic3/Events/run_03/tag_1_pythia8_events.hepmc"
from jet_tools import ReadHepmc, Components, FormJets, TrueTag, MassPeaks, FormJetInputs
import numpy as np

hepmc = ReadHepmc.Hepmc(hepmc_dir, 0, np.inf)
hepmc.file_name = "ttsemileptonic_pt7.awkd"
#hepmc.dir_name = "/home/hadh1g17/jets/megaIgnore"
hepmc.dir_name = "../megaIgnore"
hepmc.write()
print()
print("Adding components")
print()
Components.add_all(hepmc)
print()
print("Creating jet inputs")
print()
FormJetInputs.create_jetInputs(hepmc)
jet_names = []
jet_name = "AntiKTp8Jet"
jet_names.append(jet_name)
jet_class = FormJets.Traditional
jet_params = {
    'DeltaR': 0.8,
    'ExpofPTFormat': 'min',
    'ExpofPTMultiplier': 0,
    'PhyDistance': 'angular'
}
print()
def test_remove_particles_from_jets():
    contents = {}
    # check it does the right thing with a non-empty event
    contents["Event_n"] = [0]
    contents["DogJet_Parent"] = [[[], [-1], [3, -1, 3]]]
    contents["DogJet_Child1"] = [[[], [-1], [-1, 2, -1]]]
    contents["DogJet_Child2"] = [[[], [-1], [-1, 4, -1]]]
    contents["DogJet_Rapidity"] = [[[], [0.5], [0.1, 0.3, 0.4]]]
    contents["DogJet_Label"] = [[[], [1], [2, 3, 4]]]
    contents["DogJet_Tag"] = [[[], [10, 20], [34, 50]]]
    # check it manages an empty event
    contents["Event_n"] += [1]
    contents["DogJet_Parent"] += [[]]
    contents["DogJet_Child1"] += [[]]
    contents["DogJet_Child2"] += [[]]
    contents["DogJet_Rapidity"] += [[]]
    contents["DogJet_Label"] += [[]]
    contents["DogJet_Tag"] += [[]]
    # what we want to remove
    remove = [1, 2]
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**contents)
        GhostParticles.remove_particles_from_jets(eventWise, remove)
        eventWise.selected_event = 1
        assert "GhostDogJet_Rapidity" in eventWise.columns
        # the first event shoudl still be empty
        for name in eventWise.columns:
            value = getattr(eventWise, name)
            if name == "Event_n":
                assert value == 1
            else:
                assert len(value) == 0
        # the second event has a predictable structure
        eventWise.selected_event = 0
        assert eventWise.Event_n == 0
        # all relations will have the same format
        relations = [
            eventWise.DogJet_Parent, eventWise.DogJet_Child1,
            eventWise.DogJet_Child2
        ]
        for values in relations:
            assert len(values[0]) == 0
            assert len(values[1]) == 0
            tst.assert_allclose(values[2], [-1])
        # only one value of rapidity/Label should be left
        rapidity = eventWise.DogJet_Rapidity
        assert len(rapidity[0]) == 0
        assert len(rapidity[1]) == 0
        tst.assert_allclose(rapidity[2], [0.4])
        inputidx = eventWise.DogJet_Label
        assert len(inputidx[0]) == 0
        assert len(inputidx[1]) == 0
        tst.assert_allclose(inputidx[2], [4])
        # the tags should be unchanged
        tags = eventWise.DogJet_Tag
        assert len(tags[0]) == 0
        tst.assert_allclose(tags[1], [10, 20])
        tst.assert_allclose(tags[2], [34, 50])
        # test the right ghosts have been added
        ghost_inputs = eventWise.GhostDogJet_Label
        assert len(ghost_inputs[0]) == 0
        tst.assert_allclose(ghost_inputs[1], [1])
        tst.assert_allclose(ghost_inputs[2], [2])
        ghost_rapidity = eventWise.GhostDogJet_Rapidity
        assert len(ghost_rapidity[0]) == 0
        tst.assert_allclose(ghost_rapidity[1], [0.5])
        tst.assert_allclose(ghost_rapidity[2], [0.1])
Example #4
0
def tree_motion(start, root, steps_between):
    """
    

    Parameters
    ----------
    start :
        param root:
    steps_between :
        
    root :
        

    Returns
    -------

    
    """
    if root.is_leaf:
        location = [[[start[0]], [start[1]]]] * (steps_between + 1)
        size = [[root.size]] * (steps_between + 1)
        colour = [[root.colour]] * (steps_between + 1)
        return location, size, colour
    else:
        # find out what is beflow this point
        next_left = [root.left.rap, root.left.phi]
        below_left, below_left_size, below_left_colour = tree_motion(
            next_left, root.left, steps_between)
        next_right = [root.right.rap, root.right.phi]
        below_right, below_right_size, below_right_colour = tree_motion(
            next_right, root.right, steps_between)
        # if either were leaves pad to the right depth
        if len(below_left) < len(below_right):
            pad_height = int(len(below_right) - len(below_left))
            pad = pad_height * [below_left[-1]]
            below_left += pad
            pad_colour = pad_height * [below_left_colour[-1]]
            below_left_colour += pad_colour
            pad_size = pad_height * [below_left_size[-1]]
            below_left_size += pad_size
        elif len(below_right) < len(below_left):
            pad_height = int(len(below_left) - len(below_right))
            pad = pad_height * [below_right[-1]]
            below_right += pad
            pad_colour = pad_height * [below_right_colour[-1]]
            below_right_colour += pad_colour
            pad_size = pad_height * [below_right_size[-1]]
            below_right_size += pad_size
        assert len(below_left) == len(below_right)
        levels = [[r_rap + l_rap, r_phi + l_phi]
                  for (r_rap, r_phi), (l_rap,
                                       l_phi) in zip(below_left, below_right)]
        sizes = [
            l_size + r_size
            for l_size, r_size in zip(below_left_size, below_right_size)
        ]
        colours = [
            l_col + r_col
            for l_col, r_col in zip(below_left_colour, below_right_colour)
        ]
        # now make the this level
        rap_left = np.linspace(next_left[0], start[0], steps_between)
        rap_right = np.linspace(next_right[0], start[0], steps_between)
        # this coordinate is cyclic
        # so this next bit is a shuffle to get it to link by the shortest route
        distance = next_left[1] - start[1]
        if distance > np.pi:
            adjusted_next_left = -next_left[1]
        elif distance < -np.pi:
            adjusted_next_left = next_left[1] + 2 * np.pi
        else:
            adjusted_next_left = next_left[1]
        phi_left = np.linspace(adjusted_next_left, start[1], steps_between)
        phi_left = Components.confine_angle(phi_left)
        distance = next_right[1] - start[1]
        if distance > np.pi:
            adjusted_next_right = -next_right[1]
        elif distance < -np.pi:
            adjusted_next_right = next_right[1] + 2 * np.pi
        else:
            adjusted_next_right = next_right[1]
        phi_right = np.linspace(adjusted_next_right, start[1], steps_between)
        phi_right = Components.confine_angle(phi_right)
        this_level = [[[eleft, eright], [pleft, pright]]
                      for eleft, eright, pleft, pright in zip(
                          rap_left, rap_right, phi_left, phi_right)]
        this_level += [[[root.rap], [root.phi]]]
        # add all the motion together
        levels += this_level
        # pick size
        l_size = root.left.size
        r_size = root.right.size
        this_size = [[l_size, r_size]] * steps_between + [[root.size]]
        sizes += this_size
        l_colour = root.left.colour
        r_colour = root.right.colour
        this_colour = [[l_colour, r_colour]] * steps_between + [[
            (*root.colour[:3], 0.5)
        ]]
        colours += this_colour
        return levels, sizes, colours
Example #5
0
def test_add_detectable_fourvector():
    # will need the TagIndex, Px, Py, Pz, Energy, JetInputs_SourceIdx, Child, Parent
    # empty event should do nothing
    params = {}
    params["Children"] = [ak.from_iter([])]
    params["Parents"] = [ak.from_iter([])]
    params["Energy"] = [ak.from_iter([])]
    params["Px"] = [ak.from_iter([])]
    params["Py"] = [ak.from_iter([])]
    params["Pz"] = [ak.from_iter([])]
    params["TagIndex"] = [ak.from_iter([])]
    params["JetInputs_SourceIdx"] = [ak.from_iter([])]
    # idx       0   1       2    3       4   5       6          7   8   9   10
    # dtectable                          x   v                  v   v   v
    children = [[], [2, 3], [5], [6, 5], [], [], [7, 8, 9], [], [], [], []]
    parents = [[], [], [1], [1], [], [2, 3], [3], [6], [6], [6], []]
    energy = [0, 11, 9, 11, 10, 23, 1, 2, 0, 5, 0]
    px = [4, 2, 30, 0, 1, 0, 1, 0, 0, -4, 0]
    py = [0, 0, 2, 6, 0, 4, 1, 0, 0, 0, 0]
    pz = [0, 1, 0, 0, 0, 2, 0, 1, 0, 1, 0]
    bquark = [2, 3, 4, 10]
    source = [0, 4, 5, 8, 9]
    expected_roots = [{2, 3}, {4}]
    expected_leaves = [{5, 8, 9}, {4}]
    expected_px = [-4, 1]
    expected_py = [4, 0]
    expected_pz = [3, 0]
    expected_energy = [28, 10]
    params["Children"] += [ak.from_iter(children)]
    params["Parents"] += [ak.from_iter(parents)]
    params["Energy"] += [ak.from_iter(energy)]
    params["Px"] += [ak.from_iter(px)]
    params["Py"] += [ak.from_iter(py)]
    params["Pz"] += [ak.from_iter(pz)]
    params["TagIndex"] += [ak.from_iter(bquark)]
    params["JetInputs_SourceIdx"] += [ak.from_iter(source)]
    params = {k: ak.from_iter(v) for k, v in params.items()}
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**params)
        columns_before = [x for x in eventWise.columns]
        TrueTag.add_detectable_fourvector(eventWise)
        columns_after = [x for x in eventWise.columns]
        # the first event should contain nothing
        eventWise.selected_event = 0
        try:
            roots = eventWise.DetectableTag_Roots
        except Exception as e:
            message = f"Error; {e}\ncolumns_before={columns_before}\ncolumns_after={columns_after}"
            raise Exception(message)

        assert len(roots) == 0
        energy = eventWise.DetectableTag_Energy
        assert len(energy) == 0
        # the second event should contain the predicted values
        eventWise.selected_event = 1
        roots = [set(r) for r in eventWise.DetectableTag_Roots]
        assert len(roots) == len(expected_roots)
        # this will thro an error if anythign is missing
        order = [roots.index(r) for r in expected_roots]
        for e, f in enumerate(order):
            assert expected_leaves[e] == set(eventWise.DetectableTag_Leaves[f])
        tst.assert_allclose(expected_energy,
                            eventWise.DetectableTag_Energy[order])
        tst.assert_allclose(expected_px, eventWise.DetectableTag_Px[order])
        tst.assert_allclose(expected_py, eventWise.DetectableTag_Py[order])
        tst.assert_allclose(expected_pz, eventWise.DetectableTag_Pz[order])
Example #6
0
def test_make_n_working_fragments():
    with TempTestDir("tst") as dir_name:
        # calling this one a directory that dosn't contain any eventWise objects
        # should raise a file not found erroj
        with pytest.raises(FileNotFoundError):
            ParallelFormJets.make_n_working_fragments(dir_name, 3, "squibble")
        # trying to split something that isn't an eventwise shoudl raise a NotADirectoryError
        wrong_path = os.path.join(dir_name, "wrong.ods")
        open(wrong_path, 'w').close()  # equivalent of touch
        with pytest.raises(NotADirectoryError):
            ParallelFormJets.make_n_working_fragments(wrong_path, 3, "flob")
        os.remove(wrong_path)
        # now make a real eventWise to play with
        file_name = "test.parquet"
        ew = Components.EventWise(os.path.join(dir_name, file_name))
        ew_path = os.path.join(dir_name, file_name)
        # try with 12 events
        n_events = 12
        params = {}
        params['Event_n'] = ak.from_iter(np.arange(n_events))
        params['JetInputs_Energy'] = ak.from_iter(np.arange(n_events))
        unfinished_jet = 'DogJet'
        n_unfinished = 6
        params[unfinished_jet + '_Energy'] = ak.from_iter(
            np.random.rand(n_events - n_unfinished))
        params[unfinished_jet + '_Food'] = ak.from_iter([
            np.random.rand(np.random.randint(5))
            for _ in range(n_events - n_unfinished)
        ])
        finished_jet = 'CatJet'
        params[finished_jet + '_Energy'] = ak.from_iter([[
            ak.from_iter(np.random.rand(np.random.randint(5)))
            for _ in range(np.random.randint(5))
        ] for _ in range(n_events)])
        ew.append(**params)
        # making fragments of the finished jet should result in no change
        paths = ParallelFormJets.make_n_working_fragments(
            ew_path, 3, finished_jet)
        assert isinstance(paths, bool)
        assert paths
        # check nothing else has been made in the dir
        assert len(os.listdir(dir_name)) == 1
        # now split the unfinished jet
        paths = ParallelFormJets.make_n_working_fragments(
            ew_path, 3, unfinished_jet)
        assert len(paths) == 3
        ew.selected_event = None
        # there is no garentee that the split events will hold the same order
        expected_indices = list(range(n_events - n_unfinished, n_events))
        for path in paths:
            ew_part = Components.EventWise.from_file(path)
            indices_here = ew_part.JetInputs_Energy.tolist()
            for i in indices_here:
                expected_indices.remove(i)
            flat_here = ak.flatten(ew.CatJet_Energy[indices_here])
            flat_part = ak.flatten(ew_part.CatJet_Energy)
            try:
                flat_here = ak.flatten(flat_here)
                flat_part = ak.flatten(flat_part)
            except ValueError:  # already flat
                pass
            tst.assert_allclose(flat_here.tolist(), flat_part.tolist())
        assert not expected_indices, "Didn't find all the expected indices"
        # if we ask for the same split again it would not do anything
        paths2 = ParallelFormJets.make_n_working_fragments(
            ew_path, 3, unfinished_jet)
        assert set(paths2) == set(paths)
        paths2 = ParallelFormJets.make_n_working_fragments(
            os.path.split(paths[0])[0], 3, unfinished_jet)
        assert set(paths2) == set(paths)
        # if we ask for a diferent number of paths it should recluster and then split
        paths3 = ParallelFormJets.make_n_working_fragments(
            ew_path, 2, unfinished_jet)
        assert len(paths3) == 2
        # there is no garentee that the split events will hold the same order
        expected_indices = list(range(n_events - n_unfinished, n_events))
        for path in paths3:
            ew_part = Components.EventWise.from_file(path)
            indices_here = ew_part.JetInputs_Energy.tolist()
            for i in indices_here:
                expected_indices.remove(i)
            flat_here = ak.flatten(ew.CatJet_Energy[indices_here])
            flat_part = ak.flatten(ew_part.CatJet_Energy)
            try:
                flat_here = ak.flatten(flat_here)
                flat_part = ak.flatten(flat_part)
            except ValueError:  # already flat
                pass
            tst.assert_allclose(flat_here.tolist(), flat_part.tolist())
        assert not expected_indices, "Didn't find all the expected indices"
        # remove any existing directories
        [
            shutil.rmtree(os.path.join(dir_name, name))
            for name in os.listdir(dir_name) if '.' not in name
        ]
        # try fragmenting and then joining
        ew.fragment("JetInputs_Energy", n_fragments=3)
        fragment_dir = next(
            os.path.join(dir_name, name) for name in os.listdir(dir_name)
            if "fragment" in name)
        Components.EventWise.combine(fragment_dir,
                                     ew.file_name.split('.', 1)[0])
        ParallelFormJets.make_n_working_fragments(ew_path, 4, finished_jet)
        # check it has reconstructed the original eventWise
        found = os.listdir(fragment_dir)
        assert len(found) == 1
        new_ew = Components.EventWise.from_file(
            os.path.join(fragment_dir, found[0]))
        order = np.argsort(new_ew.JetInputs_Energy)
        dog_order = order[order < n_events - n_unfinished]
        tst.assert_allclose(ew.JetInputs_Energy,
                            new_ew.JetInputs_Energy[order])
        tst.assert_allclose(ew.DogJet_Energy, new_ew.DogJet_Energy[dog_order])
        for i, j in enumerate(dog_order):
            tst.assert_allclose(ew.DogJet_Food[i], new_ew.DogJet_Food[j])
        for i, j in enumerate(order):
            for evt, new_evt in zip(ew.CatJet_Energy[i],
                                    new_ew.CatJet_Energy[j]):
                tst.assert_allclose(evt, new_evt)
Example #7
0
else:
    root_present = False

print(
    "It is often useful to calculate some values from the momentum and energy."
)
print("In the Components module there are a number of methods for this; ")
print("  > Components.add_thetas(eventwise)")
print("  > Components.add_pt(eventwise)")
print("  > Components.add_phi(eventwise)")
print("  > Components.add_rapidity(eventwise)")
print("  > Components.add_pseudorapidity(eventwise)")
print("  > Components.add_mass(eventwise)")
print("These have been combined in Components.add_all(eventWise)")
print("  > Components.add_all(eventWise, inc_mass=True)")
Components.add_all(eventWise, inc_mass=True)
print(
    "All these variables now exist as attributes of the eventWise, have a look; "
)
interactive()

if InputTools.yesNo_question("Do you want to cluster the jets with Anti-kt? "):
    print("~~ Example of adding JetInputs ~~")
    if root_present:
        print(
            "As the root file has been added we can form jets based on the particles"
        )
        print(
            "based on the particles that actually have been picked up by the detector."
        )
        print(" > filter1 = FormJets.filter_obs")
Example #8
0
def test_link_tags_to_hard():
    # need TagCreators, TagIndex, Parents, Children, MCPID
    contents = {}
    # empty event
    for name in ["TagCreators", "TagIndex", "Parents", "Children", "MCPID"]:
        contents[name] = [[]]
    hard = [[]]
    expected_hard = [[]]
    expected_created = [[]]
    # one particle, not tagged
    contents["TagIndex"] += [[]]
    contents["TagCreators"] += [[]]
    contents["Parents"] += [[[]]]
    contents["Children"] += [[[]]]
    contents["MCPID"] += [[5]]
    hard += [[]]
    expected_hard += [[]]
    expected_created += [[]]
    # one particle, tagged
    contents["TagIndex"] += [[0]]
    contents["TagCreators"] += [[[]]]
    contents["Parents"] += [[[]]]
    contents["Children"] += [[[]]]
    contents["MCPID"] += [[5]]
    hard += [[5]]
    expected_hard += [[[0]]]
    expected_created += [[[[]]]]
    # two particles, one tagged
    contents["TagIndex"] += [[1]]
    contents["TagCreators"] += [[[0]]]
    contents["Parents"] += [[[], [0]]]
    contents["Children"] += [[[1], []]]
    contents["MCPID"] += [[10, 5]]
    hard += [[10, 1]]
    expected_hard += [[[0], []]]
    expected_created += [[[[1]], []]]
    # two particles, related but not hard
    contents["TagIndex"] += [[1]]
    contents["TagCreators"] += [[[0]]]
    contents["Parents"] += [[[], [0]]]
    contents["Children"] += [[[1], []]]
    contents["MCPID"] += [[1, 6]]
    hard += [[10, 5]]
    expected_hard += [[[], []]]
    expected_created += [[[], []]]
    # three particles, one hard creates two
    contents["TagIndex"] += [[1, 2]]
    contents["TagCreators"] += [[[0], [0]]]
    contents["Parents"] += [[[], [0], [0]]]
    contents["Children"] += [[[1, 2], [], []]]
    contents["MCPID"] += [[10, -5, -5]]
    hard += [[10, 6]]
    expected_hard += [[[0], []]]
    expected_created += [[[[1, 2]], []]]
    # three particles, two hard creates one
    contents["TagIndex"] += [[2]]
    contents["TagCreators"] += [[[0, 1]]]
    contents["Parents"] += [[[], [], [0, 1]]]
    contents["Children"] += [[[2], [2], []]]
    contents["MCPID"] += [[10, 5, -4]]
    hard += [[10, 5]]
    expected_hard += [[[0], [1]]]
    expected_created += [[[[2]], [[2]]]]
    # three particles, hard particle is up a chain
    contents["TagIndex"] += [[2]]
    contents["TagCreators"] += [[[1]]]
    contents["Parents"] += [[[], [0], [1], [2]]]
    contents["Children"] += [[[1], [2], [3], []]]
    contents["MCPID"] += [[10, 10, 5, -5]]
    hard += [[10]]
    expected_hard += [[[0]]]
    expected_created += [[[[2]]]]
    contents = {k: ak.from_iter(v) for k, v in contents.items()}
    n_events = len(hard)
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**contents)
        for i in range(n_events):
            eventWise.selected_event = i
            found_hard, found_created = MassPeaks.link_tags_to_hard(
                eventWise, hard[i])
            for p, pid in enumerate(hard[i]):
                for h, c in zip(found_hard[p], found_created[p]):
                    assert h in expected_hard[i][p],\
                            f"{i}; Expected {expected_hard[i][p]}, found {h}"
                    position = expected_hard[i][p].index(h)
                    assert set(c) == set(expected_created[i][p][position]),\
                            f"{i}; Expected {expected_created[i][p][position]}, found {c}"
Example #9
0
def test_descendants_masses():
    # need TagCreators, TagIndex, Parents, Children, MCPID,
    # Px, Py, Px, Energy
    # JetInput_SourceIdx
    # also, Additional3
    contents = {}
    # empty event
    hard = [10, 6]
    # with jet inputs
    expected_tags_ji = {pid: [] for pid in hard}
    expected_mass_ji = {pid: [] for pid in hard}
    # with additional particles
    expected_tags_ad = {pid: [] for pid in hard}
    expected_mass_ad = {pid: [] for pid in hard}
    # with jet inputs and additional particles
    expected_tags_jiad = {pid: [] for pid in hard}
    expected_mass_jiad = {pid: [] for pid in hard}
    for name in [
            "TagCreators", "TagIndex", "Parents", "Children", "MCPID", "Px",
            "Py", "Pz", "Energy", "Additional3", "JetInputs_SourceIdx"
    ]:
        contents[name] = [[]]
    for pid in hard:
        expected_tags_ji[pid] += [[]]
        expected_mass_ji[pid] += [[]]
        expected_tags_ad[pid] += [[]]
        expected_mass_ad[pid] += [[]]
        expected_tags_jiad[pid] += [[]]
        expected_mass_jiad[pid] += [[]]
    # four particles, one hard creates two tags, one additional
    contents["TagIndex"] += [[1, 2]]
    contents["TagCreators"] += [[[0], [0]]]
    contents["Parents"] += [[[], [0], [0], [0]]]
    contents["Children"] += [[[1, 2, 3], [], [], []]]
    contents["MCPID"] += [[10, -5, -5, 3]]
    contents["Additional3"] += [[[3], [3]]]
    # One tag is not in the jet inputs
    contents["JetInputs_SourceIdx"] += [[1]]
    # kinematics
    contents["Px"] += [[0., 1., 1., 1.]]
    contents["Py"] += [[0., 1., 1., 1.]]
    contents["Pz"] += [[0., 1., 1., 1.]]
    contents["Energy"] += [[0., 10., 10., 10.]]
    # one hard undetected
    expected_tags_ji[6] += [[]]
    expected_mass_ji[6] += [[]]
    expected_tags_ad[6] += [[]]
    expected_mass_ad[6] += [[]]
    expected_tags_jiad[6] += [[]]
    expected_mass_jiad[6] += [[]]
    # the tag will still be assocated with that hard pid, even if it is unseen
    expected_tags_ji[10] += [[{1, 2}]]
    expected_mass_ji[10] += [[np.sqrt(100 - 3)]]
    expected_tags_ad[10] += [[{1, 2}]]
    expected_mass_ad[10] += [[np.sqrt(30**2 - 3 * 3**2)]]
    expected_tags_jiad[10] += [[{1, 2}]]
    expected_mass_jiad[10] += [[np.sqrt(20**2 - 3 * 2**2)]]
    # same again, but nothing is in the jet inputs
    contents["TagIndex"] += [[1, 2]]
    contents["TagCreators"] += [[[0], [0]]]
    contents["Parents"] += [[[], [0], [0], [0]]]
    contents["Children"] += [[[1, 2, 3], [], [], []]]
    contents["MCPID"] += [[10, -5, -5, 3]]
    contents["Additional3"] += [[[3], [3]]]
    # nothing in the jet inputs
    contents["JetInputs_SourceIdx"] += [[]]
    # kinematics
    contents["Px"] += [[0., 1., 1., 1.]]
    contents["Py"] += [[0., 1., 1., 1.]]
    contents["Pz"] += [[0., 1., 1., 1.]]
    contents["Energy"] += [[0., 10., 10., 10.]]
    # one hard undetected
    expected_tags_ji[6] += [[]]
    expected_mass_ji[6] += [[]]
    expected_tags_ad[6] += [[]]
    expected_mass_ad[6] += [[]]
    expected_tags_jiad[6] += [[]]
    expected_mass_jiad[6] += [[]]
    # the tag will still be assocated with that hard pid, even if it is unseen
    expected_tags_ji[10] += [[{1, 2}]]
    expected_mass_ji[10] += [[0.]]
    expected_tags_ad[10] += [[{1, 2}]]
    # still get mass from add
    expected_mass_ad[10] += [[np.sqrt(100 - 3)]]
    expected_tags_jiad[10] += [[{1, 2}]]
    expected_mass_jiad[10] += [[np.sqrt(100 - 3)]]
    contents = {k: ak.from_iter(v) for k, v in contents.items()}
    n_events = len(hard)
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**contents)
        found_tags_ji, found_mass_ji = MassPeaks.descendants_masses(
            eventWise, hard, additional_decay_pid=None, use_jetInputs=True)
        for i in range(n_events):
            for pid in hard:
                for tags, mass in zip(found_tags_ji[pid][i],
                                      found_mass_ji[pid][i]):
                    tags = set(tags)
                    assert tags in expected_tags_ji[pid][i]
                    pos = expected_tags_ji[pid][i].index(tags)
                    err_message = f"Jet inputs, no additionals\n" + \
                            f"event = {i}, pid = {pid}, tags = {tags}\n" + \
                            f"expected_mass = {expected_mass_ji[pid][i][pos]}\n" + \
                            f"found mass = {mass}\n"
                    tst.assert_allclose(expected_mass_ji[pid][i][pos],
                                        mass,
                                        err_msg=err_message)
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**contents)
        found_tags_ad, found_mass_ad = MassPeaks.descendants_masses(
            eventWise, hard, additional_decay_pid=3, use_jetInputs=False)
        for i in range(n_events):
            for pid in hard:
                for tags, mass in zip(found_tags_ad[pid][i],
                                      found_mass_ad[pid][i]):
                    tags = set(tags)
                    assert tags in expected_tags_ad[pid][i]
                    pos = expected_tags_ad[pid][i].index(tags)
                    err_message = f"no Jet inputs, with additionals\n" + \
                            f"event = {i}, pid = {pid}, tags = {tags}\n" + \
                            f"expected_mass = {expected_mass_ad[pid][i][pos]}\n" + \
                            f"found mass = {mass}\n"
                    tst.assert_allclose(expected_mass_ad[pid][i][pos],
                                        mass,
                                        err_msg=err_message)
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**contents)
        found_tags_jiad, found_mass_jiad = MassPeaks.descendants_masses(
            eventWise, hard, additional_decay_pid=3, use_jetInputs=True)
        for i in range(n_events):
            for pid in hard:
                for tags, mass in zip(found_tags_jiad[pid][i],
                                      found_mass_jiad[pid][i]):
                    tags = set(tags)
                    assert tags in expected_tags_jiad[pid][i]
                    pos = expected_tags_jiad[pid][i].index(tags)
                    err_message = f"Jet inputs, with additionals\n" + \
                            f"event = {i}, pid = {pid}, tags = {tags}\n" + \
                            f"expected_mass = {expected_mass_jiad[pid][i][pos]}\n" + \
                            f"found mass = {mass}\n"
                    tst.assert_allclose(expected_mass_jiad[pid][i][pos],
                                        mass,
                                        err_msg=err_message)
Example #10
0
def test_all_jet_masses():
    params = {}
    jet_name = "Jet"
    # event 0 is empty - should be 0
    params['Jet_Label'] = [[]]
    params['Jet_Px'] = [[]]
    params['Jet_Py'] = [[]]
    params['Jet_Pz'] = [[]]
    params['Jet_Energy'] = [[]]
    params['Jet_Phi'] = [[]]
    params['Jet_PT'] = [[]]
    params['Jet_Rapidity'] = [[]]
    params['Jet_Tags'] = [[]]
    params['Jet_Child1'] = [[]]
    params['Jet_Parent'] = [[]]
    expected_masses = [0.]
    # event 1 has just 1 jet
    params['Jet_Label'] += [[[0, 1, 2]]]
    params['Jet_Px'] += [[[1, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1]]]
    params['Jet_Tags'] += [[[1]]]
    params['Jet_Child1'] += [[[1, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0]]]
    expected_masses += [np.sqrt(97)]
    # event 2 has just 1 jet but it is untagged - should be 0
    params['Jet_Label'] += [[[0, 1, 2]]]
    params['Jet_Px'] += [[[1, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1]]]
    params['Jet_Tags'] += [[[]]]
    params['Jet_Child1'] += [[[1, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0]]]
    expected_masses += [0.]
    # event 3 has one untagged and one tagged jet
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Tags'] += [[[1], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3]]]
    expected_masses += [np.sqrt(10**2 - 3)]
    # event 4 has one untagged and two tagged jets
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10], [5, 5, 5]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3]]]
    params['Jet_PT'] += [[[1, 1, 1], [1, 1, 1], [1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Tags'] += [[[1], [], [4]]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7]]]
    prep_params = {
        key: ak.from_iter([ak.from_iter(e) for e in v])
        for key, v in params.items()
    }
    expected_masses += [15.]
    # check this results in the predicted masses
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**prep_params)
        found = MassPeaks.all_jet_masses(eventWise, jet_name, 0)
        tst.assert_allclose(found, expected_masses)
Example #11
0
def test_all_PT_pairs():
    params = {}
    jet_name = "Jet"
    # event 0 is empty - no pairs
    params['Jet_Label'] = [[]]
    params['Jet_Px'] = [[]]
    params['Jet_Py'] = [[]]
    params['Jet_Pz'] = [[]]
    params['Jet_Energy'] = [[]]
    params['Jet_Phi'] = [[]]
    params['Jet_PT'] = [[]]
    params['Jet_Rapidity'] = [[]]
    params['Jet_Tags'] = [[]]
    params['Jet_Child1'] = [[]]
    params['Jet_Parent'] = [[]]
    # 0 1, 0 2, 0 3, 1 2, 1 3, 2 3
    expected_order = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
    expected = [[] for _ in expected_order]
    # event 1 has one untagged and one tagged jet - no pairs
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5]]]
    params['Jet_Px'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [11, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Tags'] += [[[1], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3]]]
    # event 2 has one untagged and two tagged jets - only the 0 1 pair
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]]
    params['Jet_Px'] += [[[1, 1, 1], [3, 1, 1], [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [3, 1, 1], [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [3, 1, 1], [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [12, 12, 12], [5, 5, 5],
                              [10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3], [1, 3, 3]]]
    params['Jet_PT'] += [[[4, 5, 4], [10, 10, 10], [1, 1, 1], [7, 7, 7]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1],
                                [10, 10, 10]]]
    params['Jet_Tags'] += [[[1], [], [4], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1],
                              [11, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7], [-1, 9, 9]]]
    expected[expected_order.index((0, 1))].append(15)
    # event 3 has five tagged jet - the 4 with highest PT will contribute to every combination
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11],
                             [12, 13, 14]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [1, 1, 1],
                          [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [2, 2, 2], [-1, -1, -1], [1, 1, 1],
                          [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [1, 1, 1],
                          [3, 3, 3]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10], [5, 5, 5],
                              [10, 10, 10], [6, 6, 6]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3], [0, 0, 0],
                           [3, 3, 3]]]
    params['Jet_PT'] += [[[2.5, 2, 2], [2, 2, 2], [3, 3, 3], [1, 1, 4],
                          [2, 1.5, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [1, 1, 1],
                                [-1, -1, -1]]]
    params['Jet_Tags'] += [[[1], [2], [4], [5, 6], [10]]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1],
                              [-1, 11, -1], [-1, 14, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7], [-1, 9, 9],
                              [12, -1, 12]]]
    # PT order is 2, 0, 1, 4
    expected[expected_order.index((0, 1))].append(15)
    mass = np.sqrt(15**2 - 1)
    expected[expected_order.index((0, 2))].append(mass)
    mass = np.sqrt(11**2 - 4 * 3)
    expected[expected_order.index((0, 3))].append(mass)
    mass = np.sqrt(20**2 - 4 * 2 - 3**2)
    expected[expected_order.index((1, 2))].append(mass)
    mass = np.sqrt(16**2 - 4**2)
    expected[expected_order.index((1, 3))].append(mass)
    mass = np.sqrt(16**2 - 4**2 - 1)
    expected[expected_order.index((2, 3))].append(mass)
    prep_params = {
        key: ak.from_iter([ak.from_iter(e) for e in v])
        for key, v in params.items()
    }
    # check this results in the predicted masses
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**prep_params)
        _, pairs, pair_masses = MassPeaks.all_PT_pairs(eventWise,
                                                       jet_name,
                                                       jet_pt_cut=0)
        err_start = f"All expected = {list(zip(expected_order, expected))}\n"
        err_start += f"All found = {list(zip(pairs, pair_masses))}\n"
        for found_pair, found_masses in zip(pairs, pair_masses):
            expected_mass = expected[expected_order.index(
                tuple(sorted(found_pair)))]
            err_msg = err_start + f"found pair = {found_pair}, found_masses = {found_masses}\n"
            err_msg = err_start + f"expected masses = {expected_mass}\n"
            tst.assert_allclose(found_masses, expected_mass, err_msg=err_msg)
Example #12
0
def test_all_smallest_angles():
    params = {}
    jet_name = "Jet"
    # event 0 is empty - no contribution
    params['Jet_Label'] = [[]]
    params['Jet_Px'] = [[]]
    params['Jet_Py'] = [[]]
    params['Jet_Pz'] = [[]]
    params['Jet_Energy'] = [[]]
    params['Jet_Phi'] = [[]]
    params['Jet_PT'] = [[]]
    params['Jet_Rapidity'] = [[]]
    params['Jet_Tags'] = [[]]
    params['Jet_Child1'] = [[]]
    params['Jet_Parent'] = [[]]
    # event 1 has just 1 jet - no contribution
    params['Jet_Label'] += [[[0, 1, 2]]]
    params['Jet_Px'] += [[[1, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1]]]
    params['Jet_Tags'] += [[[1]]]
    params['Jet_Child1'] += [[[1, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0]]]
    # event 2 has one untagged and one tagged jet - no contribution
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Tags'] += [[[1], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3]]]
    prep_params = {
        key: ak.from_iter([ak.from_iter(e) for e in v])
        for key, v in params.items()
    }
    # check this results in no masses
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**prep_params)
        found = MassPeaks.all_smallest_angles(eventWise, jet_name, 0)
        assert len(found) == 0
    # now start adding things that will contribute
    # event 3 has one untagged and two tagged jets - two tagged jets should combine
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10], [5, 5, 5]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3]]]
    params['Jet_PT'] += [[[1, 1, 1], [1, 1, 1], [1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1]]]
    params['Jet_Tags'] += [[[1], [], [4]]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7]]]
    expected_masses = [15.]
    # event 4 has two untagged and three tagged jets - two closest tagged jets should combine
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11],
                             [12, 13, 14]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [-1, -1, -1],
                          [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [-1, -1, -1],
                          [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [-1, -1, -1],
                          [-1, -1, -1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10], [5, 5, 5], [6, 6, 6],
                              [7, 7, 7]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3], [3, 3, 3],
                           [3, 3, 3]]]
    params['Jet_PT'] += [[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
                          [1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1],
                                [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Tags'] += [[[1], [], [4], [10, 11], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1],
                              [10, -1, -1], [13, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7], [-1, 9, 9],
                              [12, -1, 12]]]
    expected_masses += [np.sqrt(11**2 - 3 * 4)]
    # event 5 has one untagged and four tagged jets - all tagged jets will combine
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11],
                             [12, 13, 14]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [-1, -1, -1],
                          [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [-1, -1, -1],
                          [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [-1, -1, -1],
                          [-1, -1, -1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10], [5, 5, 5], [6, 6, 6],
                              [7, 7, 7]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3], [3, 3, 3],
                           [3, 3, 3]]]
    params['Jet_PT'] += [[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
                          [1, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1],
                                [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Tags'] += [[[1], [3], [4], [10, 11], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1],
                              [10, -1, -1], [13, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7], [-1, 9, 9],
                              [12, -1, 12]]]
    expected_masses += [np.sqrt(20**2 - 3 * 4), np.sqrt(11**2 - 3 * 4)]
    prep_params = {
        key: ak.from_iter([ak.from_iter(e) for e in v])
        for key, v in params.items()
    }
    # check this results in the predicted masses
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**prep_params)
        found = MassPeaks.all_smallest_angles(eventWise, jet_name, 0)
        tst.assert_allclose(sorted(found), sorted(expected_masses))
Example #13
0
def create_jet_internals(energy, px, py, pz,
                         rapidity=None, phi=None, labels=None):
    """ For a requested set of particle 4 momentum, rapidity, and phi
    create the list structure that would be needed to place those particles
    into FormJets.Clustering object

    Parameters
    ----------
    energy : array of floats
        List of energy values of the the desired particles
    px : array of floats
        List of px values of the the desired particles
    py : array of floats
        List of py values of the the desired particles
    pz : array of floats
        List of pz values of the the desired particles
    rapidity : array of floats (optional)
        List of rapidity values of the the desired particles
    phi : array of floats (optional)
        List of phi values of the the desired particles
    labels : array of ints (optional)
        List of labels to give the new particles,
        if not given negative numbers below -2 will be assigned

    Returns
    -------
    labels : numpy array of ints
        the Label given to the new particles
    new_ints : list of list of ints
        the list of list of ints for the new particles,
        in the same format as in the input to FormJets.Agglomerative
    new_floats : list of list of floats
        the list of list of floats for the new particles,
        in the same format as in the input to FormJets.Agglomerative
    
    """
    # jets.int_columns = 
    #["Pseudojet_Label",
    # "Pseudojet_Parent", "Pseudojet_Child1", "Pseudojet_Child2",
    # "Pseudojet_Rank"]
    # jets.float_columns = 
    #["Pseudojet_PT",
    # "Pseudojet_Rapidity",
    # "Pseudojet_Phi",
    # "Pseudojet_Energy",
    # "Pseudojet_Px",
    # "Pseudojet_Py",
    # "Pseudojet_Pz",
    # "Pseudojet_JoinDistance",
    # "Pseudojet_Size"]
    # check the jet interals have the shape you expected
    num_ints = 5
    # give the particles a set of labels that are negative
    num_additions = px.shape[0]
    if labels is None:
        labels = np.arange(-2, -num_additions - 2, -1)
    new_ints = [[i] + [-1]*(num_ints-1) for i in labels]
    if phi is None:
        phi, pt = Components.pxpy_to_phipt(px, py)
    else:
        _, pt = Components.pxpy_to_phipt(px, py)
    if rapidity is None:
        rapidity = Components.ptpze_to_rapidity(pt, pz, energy)
    # work out the float values
    new_floats = [pt, rapidity, phi, energy, px, py, pz,
                  np.zeros(num_additions),  # Join distance
                  np.ones(num_additions)]  # Size
    new_floats = list(map(list, zip(*new_floats)))
    return labels, new_ints, new_floats
Example #14
0
def fix_phis(eventWise, jet_name):
    eventWise.selected_event = None
    px = getattr(eventWise, jet_name + "_Px")
    py = getattr(eventWise, jet_name + "_Py")
    phis, _ = Components.pxpy_to_phipt(px, py)
    return {jet_name + "_Phi": phis}
Example #15
0
def test_combine():
    with TempTestDir("tst") as dir_name:
        empty_path = os.path.join(dir_name, "empty.parquet")
        # an empty eventWise
        empty = Components.EventWise(empty_path)
        # putting in an empty eventwise should have no effect
        returns = AddPileup.combine(empty, empty, [])
        assert len(returns.columns) == 0
        assert len(returns.hyperparameter_columns) == 0

        # if the base ew has hyper params they should be held
        hypers = {"Dog": "woof"}
        hypers_path = os.path.join(dir_name, "hypers.parquet")
        # an hypers eventWise
        hyper_ew = Components.EventWise(hypers_path)
        hyper_ew.append_hyperparameters(**hypers)
        returns = AddPileup.combine(hyper_ew, empty, [])
        assert len(returns.columns) == 0
        assert len(returns.hyperparameter_columns) == 1
        assert returns.Dog == "woof"

        # alternativly, hyperparameters in the pileup don't get kept
        returns = AddPileup.combine(empty, hyper_ew, [])
        assert len(returns.columns) == 0
        assert len(returns.hyperparameter_columns) == 0

        # make a simple base with just one event
        content = {}
        content["Parents"] = [[[], [0]]]
        content["Children"] = [[[1], []]]
        content["Particle_barcode"] = [[1, 2]]
        content["Start_vertex_barcode"] = [[0, -1]]
        content["End_vertex_barcode"] = [[-1, 0]]
        content["Vertex_barcode"] = [[-1]]
        content["Px"] = [[0., 3.]]
        content["Z"] = [[0.]]
        content["MCPID"] = [[1, 2]]
        content["Event_n"] = [0]
        ak_content = {name: ak.from_iter(val) for name, val in content.items()}
        simple_path = os.path.join(dir_name, "simple.parquet")
        simple = Components.EventWise(simple_path)
        simple.append(**ak_content)
        # putting it in with an empty pileup shoudl result in no change
        returns = AddPileup.combine(simple, empty, [[]])
        assert len(returns.Px) == 1
        for col in returns.columns:
            if col == "Is_pileup":
                continue
            found = getattr(returns, col)
            assert np.all(found == ak.from_iter(content[col]))
        assert np.all(~returns.Is_pileup[0])

        # simplist addition
        returns = AddPileup.combine(simple, simple, [[0]])
        returns.selected_event = 0
        parents = ak.from_iter([[], [0], [], [2]])
        assert np.all(returns.Parents == parents)
        children = ak.from_iter([[1], [], [3], []])
        assert np.all(returns.Children == children)
        particle_barcode = ak.from_iter([1, 2, 3, 4])
        assert np.all(returns.Particle_barcode == particle_barcode)
        start_vertex_barcode = ak.from_iter([0, -1, 0, -2])
        assert np.all(returns.Start_vertex_barcode == start_vertex_barcode)
        end_vertex_barcode = ak.from_iter([-1, 0, -2, 0])
        assert np.all(returns.End_vertex_barcode == end_vertex_barcode)
        vertex_barcode = ak.from_iter([-1, -2])
        assert np.all(returns.Vertex_barcode == vertex_barcode)
        px = ak.from_iter([0., 3., 0., 3.])
        assert np.all(returns.Px == px)
        MCPID = ak.from_iter([1, 2, 1, 2])
        assert np.all(returns.MCPID == MCPID)
        assert returns.Event_n == 0
        assert np.all(
            returns.Is_pileup == np.array([False, False, True, True]))

        # now make a more complex, 2 event pileup data
        content["Parents"] += [[[], [0], [1]]]
        content["Children"] += [[[1], [2], []]]
        content["Particle_barcode"] += [[2, 1, 3]]
        content["Start_vertex_barcode"] += [[0, -1, -2]]
        content["End_vertex_barcode"] += [[-1, -2, 0]]
        content["Vertex_barcode"] += [[-1, -2]]
        content["Px"] += [[2., 5., 6.]]
        content["Z"] += [[2., 5.]]
        content["MCPID"] += [[9, 8, 10]]
        content["Event_n"] += [1]
        ak_content = {name: ak.from_iter(val) for name, val in content.items()}
        complex_path = os.path.join(dir_name, "complex.parquet")
        comple = Components.EventWise(complex_path)
        comple.append(**ak_content)

        # check we can add it in a non trivial pattern
        returns = AddPileup.combine(comple, comple, [[], [1, 0]])
        # the first event should be unchanged
        returns.selected_event = 0
        for col in returns.columns:
            found = getattr(returns, col)
            if col == "Is_pileup":
                continue
            if col == "Event_n":
                assert found == content[col][0]
            else:
                assert np.all(found == ak.from_iter(content[col][0]))
        assert np.all(~returns.Is_pileup)
        # the second event shoudl have additions
        returns.selected_event = 1
        parents = ak.from_iter([[], [0], [1], [], [3], [4], [], [6]])
        assert np.all(returns.Parents == parents)
        children = ak.from_iter([[1], [2], [], [4], [5], [], [7], []])
        assert np.all(returns.Children == children)
        particle_barcode = ak.from_iter([2, 1, 3, 5, 4, 6, 7, 8])
        assert np.all(returns.Particle_barcode == particle_barcode)
        start_vertex_barcode = ak.from_iter([0, -1, -2, 0, -3, -4, 0, -5])
        assert np.all(returns.Start_vertex_barcode == start_vertex_barcode)
        end_vertex_barcode = ak.from_iter([-1, -2, 0, -3, -4, 0, -5, 0])
        assert np.all(returns.End_vertex_barcode == end_vertex_barcode)
        vertex_barcode = ak.from_iter([-1, -2, -3, -4, -5])
        assert np.all(returns.Vertex_barcode == vertex_barcode)
        px = ak.from_iter([2., 5., 6., 2., 5., 6., 0., 3])
        assert np.all(returns.Px == px)
        MCPID = ak.from_iter([9, 8, 10, 9, 8, 10, 1, 2])
        assert np.all(returns.MCPID == MCPID)
        assert returns.Event_n == 1
        assert np.all(returns.Is_pileup == np.array(
            [False, False, False, True, True, True, True, True]))
Example #16
0
def test_filter_jets():
    # will need
    # Jet_Parent, Jet_Child1, Jet_PT
    min_pt = 0.1
    min_ntracks = 2
    params = {}
    # an empty event should return nothing
    params['Jet_Parent'] = [ak.from_iter([])]
    params['Jet_Child1'] = [ak.from_iter([])]
    params['Jet_PT'] = [ak.from_iter([])]
    params['MCPID'] = [ak.from_iter([])]
    params['Generated_mass'] = [ak.from_iter([])]
    # an event with nothing that passes cuts
    params['Jet_Parent'] += [ak.from_iter([[-1], [-1, 1, 1, 2, 2]])]
    params['Jet_Child1'] += [ak.from_iter([[-1], [1, 2, -1, -1, -1]])]
    params['Jet_PT'] += [ak.from_iter([[
        50.,
    ], [0.2, 0.1, 0., 0., .1]])]
    params['MCPID'] += [ak.from_iter([25])]
    params['Generated_mass'] += [ak.from_iter([40.])]
    # an event with somthing that passes cuts
    params['Jet_Parent'] += [ak.from_iter([[-1], [-1, 1, 1]])]
    params['Jet_Child1'] += [ak.from_iter([[-1], [1, -1, -1]])]
    params['Jet_PT'] += [ak.from_iter([[
        50.,
    ], [21., 0.1, 0.]])]
    params['MCPID'] += [ak.from_iter([25])]
    params['Generated_mass'] += [ak.from_iter([40.])]
    # an event to make use of variable cuts
    params['Jet_Parent'] += [ak.from_iter([[-1, 0], [-1, 1, 1]])]
    params['Jet_Child1'] += [ak.from_iter([[-1, -1], [1, -1, -1]])]
    params['Jet_PT'] += [ak.from_iter([[50., 20.], [16., 0.1, 0.]])]
    params['MCPID'] += [ak.from_iter([25])]
    params['Generated_mass'] += [ak.from_iter([40.])]
    # an event to make use of variable cuts
    params['Jet_Parent'] += [ak.from_iter([[-1, 0], [-1, 1, 1]])]
    params['Jet_Child1'] += [ak.from_iter([[-1, -1], [1, -1, -1]])]
    params['Jet_PT'] += [ak.from_iter([[50., 20.], [14., 0.1, 0.]])]
    params['MCPID'] += [ak.from_iter([25])]
    params['Generated_mass'] += [ak.from_iter([40.])]
    # an event to make use of variable cuts
    params['Jet_Parent'] += [ak.from_iter([[-1, 0], [-1, 1, 1]])]
    params['Jet_Child1'] += [ak.from_iter([[-1, -1], [1, -1, -1]])]
    params['Jet_PT'] += [ak.from_iter([[17., 20.], [16., 0.1, 0.]])]
    params['MCPID'] += [ak.from_iter([25])]
    params['Generated_mass'] += [ak.from_iter([40.])]
    params = {key: ak.from_iter(val) for key, val in params.items()}
    with TempTestDir("tst") as dir_name:
        # this will raise a value error if given an empty eventWise
        file_name = "test.parquet"
        ew = Components.EventWise(os.path.join(dir_name, file_name))
        ew.append(**params)
        # using defaults
        jet_idxs = FormJets.filter_jets(ew, "Jet")
        assert len(jet_idxs[0]) == 0
        assert len(jet_idxs[1]) == 0
        assert len(jet_idxs[2]) == 1
        assert len(jet_idxs[3]) == 2
        assert len(jet_idxs[4]) == 1
        assert len(jet_idxs[5]) == 0
        assert 1 in jet_idxs[2]
        assert 0 in jet_idxs[3]
        assert 1 in jet_idxs[3]
        assert 0 in jet_idxs[4]
        # using selected values
        jet_idxs = FormJets.filter_jets(ew, "Jet", min_pt, min_ntracks)
        assert len(jet_idxs[0]) == 0
        assert len(jet_idxs[1]) == 1
        assert 1 in jet_idxs[1]
        assert len(jet_idxs[2]) == 1
        assert 1 in jet_idxs[2]
Example #17
0
def test_generate_pool():
    # mock _worker, this is tested above
    with unittest.mock.patch('jet_tools.ParallelFormJets._worker',
                             new=fake_worker):
        with TempTestDir("tst") as temp_dir:
            ew = Components.EventWise(os.path.join(temp_dir, "file.parquet"))
            ew.append(JetInputs_Energy=np.arange(100))
            eventWise_path = os.path.join(temp_dir, ew.file_name)
            # get rid of a continue file if there is one or we will get stuck
            try:
                os.remove('continue')
            except FileNotFoundError:
                pass
            end_time = time.time() + 100
            jet_class = FormJets.Spectral
            jet_params = {"Bark": 3}
            n_cores = psutil.cpu_count()
            function = lambda x: x
            found = ParallelFormJets.generate_pool(
                eventWise_path,
                function,
                function_args=[jet_class, "Bali", jet_params],
                function_kwargs=dict(batch_size=500),
                leave_one_free=True,
                end_time=end_time)
            assert found, "One of the processes crashed"
            # now we expect to find a subdirectory containing n_cores - 1 eventWise
            subdir = next(
                os.path.join(temp_dir, name) for name in os.listdir(temp_dir)
                if ".parquet" not in name)
            paths = [
                os.path.join(subdir, name) for name in os.listdir(subdir)
                if Components.EventWise.pottential_file(name)
            ]
            assert len(paths) == n_cores - 1
            # check the ake worker has been run on all of them
            for path in paths:
                ew = Components.EventWise.from_file(path)
                tst.assert_allclose(ew.Catto, [2, 3])
                assert ew.Run_condition == end_time
                assert ew.Jet_class == jet_class.__name__
                assert ew.Cluster_parameters["Bark"] == 3
                assert ew.Batch_size == 500
            # tidy up
            shutil.rmtree(os.path.split(path)[0])
            # it should work fine with a continue file too
            open('continue', 'w').close()
            found = ParallelFormJets.generate_pool(
                eventWise_path,
                function,
                function_args=[jet_class, "Bali", jet_params],
                function_kwargs=dict(batch_size=500),
                leave_one_free=False,
                end_time=None)
            assert found, "One of the processes crashed"
            # now we expect to find a subdirectory containing n_cores eventWise
            subdir = next(
                os.path.join(temp_dir, name) for name in os.listdir(temp_dir)
                if ".parquet" not in name)
            paths = [
                os.path.join(subdir, name) for name in os.listdir(subdir)
                if Components.EventWise.pottential_file(name)
            ]
            assert len(paths) == n_cores, \
                f"paths = {len(paths)}, cores = {n_cores}"
            # check the ake worker has been run on all of them
            for path in paths:
                ew = Components.EventWise.from_file(path)
                tst.assert_allclose(ew.Catto, [2, 3])
                assert ew.Run_condition == 'continue'
                assert ew.Jet_class == jet_class.__name__
                assert ew.Cluster_parameters["Bark"] == 3
                assert ew.Batch_size == 500
def test_create_JetInputs():
    with TempTestDir("create_JetInputs") as dir_name:
        name = "test.parquet"
        columns = [
            name for name in FormJets.Clustering.float_columns
            if "Distance" not in name and "Size" not in name
        ]
        columns_unchanged = [c for c in columns
                             ]  # because the ew will change the columns list
        floats = SimpleClusterSamples.two_oposite['floats']
        contents = {
            name: ak.from_iter([x])
            for name, x in zip(columns, floats.T)
        }

        def return_all(_, current_idx):
            return current_idx

        def return_second(_, current_idx):
            return current_idx[1:2]

        ew = Components.EventWise(os.path.join(dir_name, name),
                                  columns=columns,
                                  contents=contents)
        FormJetInputs.create_jetInputs(ew, filter_functions=[return_all])
        for name in columns_unchanged:
            ji_name = "JetInputs_" + name
            idx = columns.index(name)
            assert hasattr(ew, ji_name)
            tst.assert_allclose(getattr(ew, ji_name).tolist(), [floats.T[idx]],
                                err_msg=f"In two_oposite {name} not matching")
        ew.remove_prefix("JetInputs")
        FormJetInputs.create_jetInputs(ew, filter_functions=[return_second])
        for name in columns_unchanged:
            ji_name = "JetInputs_" + name
            idx = columns.index(name)
            assert hasattr(ew, ji_name)
            tst.assert_allclose(
                getattr(ew, ji_name).tolist(), [floats.T[idx][1:2]])
        # test batching
        columns = [
            name for name in FormJets.Clustering.float_columns
            if "Distance" not in name
        ]
        contents = {
            name: ak.from_iter([x, x, x])
            for name, x in zip(columns, floats.T)
        }
        ew = Components.EventWise(os.path.join(dir_name, name),
                                  columns=columns,
                                  contents=contents)
        FormJetInputs.create_jetInputs(ew,
                                       filter_functions=[return_all],
                                       batch_length=0)
        for name in columns_unchanged:
            ji_name = "JetInputs_" + name
            assert len(getattr(ew, ji_name)) == 0
        FormJetInputs.create_jetInputs(ew,
                                       filter_functions=[return_all],
                                       batch_length=1)
        for name in columns_unchanged:
            ji_name = "JetInputs_" + name
            assert hasattr(ew, ji_name)
            idx = columns.index(name)
            tst.assert_allclose(getattr(ew, ji_name).tolist(), [floats.T[idx]])
        FormJetInputs.create_jetInputs(ew,
                                       filter_functions=[return_all],
                                       batch_length=1)
        for name in columns_unchanged:
            ji_name = "JetInputs_" + name
            assert hasattr(ew, ji_name)
            idx = columns.index(name)
            tst.assert_allclose(
                getattr(ew, ji_name).tolist(), [floats.T[idx], floats.T[idx]])
Example #19
0
hepmc_save_dir = os.path.join(os.path.split(pileup_name)[0], higgs_weight)
print(f"Will be saving in {hepmc_save_dir}")

print("Reading hepmc")
ew = ReadHepmc.Hepmc(hepmc_name)
ew.selected_event = None
num_events = len(ew.X)
print(f"Contains {num_events} events")
ew.dir_name = hepmc_save_dir
i = 0
while True:
    ew.file_name = f"{i:02}_{file_num:02}_signal.parquet"
    try:
        # will throw an error if the fiel exists
        open(ew.path_name, 'x').close()
        # otherwise, works like touch
        break
    except FileExistsError:
        i += 1
ew.write()
print("Adding components")
Components.add_all(ew)

#print(f"Taking pileup from {pileup_name}")
#pileup = Components.EventWise.from_file(pileup_name)
#average_count = 50
#print(f"Adding an average of {average_count} pileup events")
#noised = AddPileup.add_pileup(ew, pileup, average_count)
#noised.write()
#print("done")
Example #20
0
def create_jetInputs(eventWise,
                     filter_functions=None,
                     batch_length=np.inf,
                     silent=False):
    """
    Add to the eventWise a set of particles prefixed by JetInputs
    which pass all criteria required to be used in jet clustering.

    Parameters
    ----------
    eventWise : EventWise
        data structure
    filter_functions : list of callabels
        callabels with the same signature as filter_pt_eta
        that should reduce down the list of list of particle indices
        to those that are sutable as jet inputs
        (Default value = [filter_obs, filter_neutrinos, filter_pt_eta, filter_pileup])
    batch_length : int
        how many particles to checks
        (Default value = np.inf)
    silent : bool (optional)
        don't print progress?
        (Default; False)

    """
    if filter_functions is None or filter_functions == "remove pileup":
        filter_functions = [
            filter_ends, filter_neutrinos, filter_pt_eta,
            RemovePileup.filter_pileup
        ]
    elif filter_functions == "ignore pileup":
        filter_functions = [filter_ends, filter_neutrinos, filter_pt_eta]
        #filter_functions = [filter_ends, filter_pt_eta]
    # decide on run range
    eventWise.selected_event = None
    n_events = len(eventWise.Energy)
    start_point = len(getattr(eventWise, "JetInputs_Energy", []))
    if start_point >= n_events:
        print("Finished")
        return True
    end_point = min(n_events, start_point + batch_length)
    if not silent:
        print(f" Will stop at {end_point/n_events:.1%}")
    # sort out olumn names
    sources = ["PT", "Rapidity", "Phi", "Energy", "Px", "Py", "Pz"]
    for s in sources:
        if not hasattr(eventWise, s):
            Components.add_all(eventWise)
            break
    columns = ["JetInputs_" + c for c in sources]
    columns.append("JetInputs_SourceIdx")
    # the source column gives indices in the origin
    # construct the observable filter in advance
    contents = {
        "JetInputs_SourceIdx":
        list(getattr(eventWise, "JetInputs_SourceIdx", []))
    }
    for name in columns:
        contents[name] = list(getattr(eventWise, name, []))
    mask = []
    for event_n in range(start_point, end_point):
        if not silent and event_n % 100 == 0:
            print(f"{event_n/n_events:.1%}", end='\r', flush=True)
        eventWise.selected_event = event_n
        idx_selection = np.arange(len(eventWise.PT))
        for filter_func in filter_functions:
            idx_selection = filter_func(eventWise, idx_selection)
        contents["JetInputs_SourceIdx"].append(idx_selection)
        mask_here = np.full_like(ak.to_numpy(eventWise.PT), False, dtype=bool)
        mask_here[idx_selection] = True
        mask.append(mask_here)
    mask = ak.from_iter(mask)
    eventWise.selected_event = None
    for name, source_name in zip(columns, sources):
        contents[name] += list(
            getattr(eventWise, source_name)[start_point:end_point][mask])
    contents = {k: ak.from_iter(v) for k, v in contents.items()}
    eventWise.append(**contents)
    if not silent:
        print("Completed batch")
    return end_point == n_events
Example #21
0
def test_sorted_masses():
    params = {}
    jet_name = "Jet"
    # event 0 is empty - no pairs
    params['Jet_Label'] = [[]]
    params['Jet_Px'] = [[]]
    params['Jet_Py'] = [[]]
    params['Jet_Pz'] = [[]]
    params['Jet_Energy'] = [[]]
    params['Jet_Phi'] = [[]]
    params['Jet_PT'] = [[]]
    params['Jet_Rapidity'] = [[]]
    params['Jet_Tags'] = [[]]
    params['Jet_Child1'] = [[]]
    params['Jet_Parent'] = [[]]
    # 0 1, 0 2, 0 3, 1 2, 1 3, 2 3
    # only intrested in 0 1
    expected = []
    # event 1 has one untagged and one tagged jet - no pairs
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5]]]
    params['Jet_Px'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Py'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Energy'] += [[[10, 10, 10], [11, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0]]]
    params['Jet_PT'] += [[[1, 1, 1], [2, 1, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1]]]
    params['Jet_Tags'] += [[[1], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3]]]
    # event 2 has one untagged and two tagged jets - only the 0 1 pair
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]]
    params['Jet_Px'] += [[[1, 1, 1], [3, 1, 1], [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [3, 1, 1], [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [3, 1, 1], [-1, -1, -1], [-1, -1, -1]]]
    params['Jet_Energy'] += [[[8, 10, 10], [12, 12, 12], [5, 5, 5],
                              [10, 10, 10]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3], [1, 3, 3]]]
    params['Jet_PT'] += [[[2, 5, 4], [10, 10, 10], [1, 1, 1], [7, 7, 7]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1],
                                [10, 10, 10]]]
    params['Jet_Tags'] += [[[1], [], [4], []]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1],
                              [11, -1, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7], [-1, 9, 9]]]
    expected.append(13)
    # event 3 has five tagged jet - the 4 with highest PT will contribute to every combination
    params['Jet_Label'] += [[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11],
                             [12, 13, 14]]]
    params['Jet_Px'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [1, 1, 1],
                          [-1, -1, -1]]]
    params['Jet_Py'] += [[[1, 1, 1], [2, 2, 2], [-1, -1, -1], [1, 1, 1],
                          [-1, -1, -1]]]
    params['Jet_Pz'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [1, 1, 1],
                          [3, 3, 3]]]
    params['Jet_Energy'] += [[[10, 10, 10], [10, 10, 10], [5, 5, 5],
                              [10, 10, 10], [6, 6, 6]]]
    params['Jet_Phi'] += [[[0, 0, 0], [0, 0, 0], [3, 3, 3], [0, 0, 0],
                           [3, 3, 3]]]
    params['Jet_PT'] += [[[2.5, 2, 2], [2, 2, 2], [3, 3, 3], [1, 1, 4],
                          [2, 1.5, 1]]]
    params['Jet_Rapidity'] += [[[1, 1, 1], [1, 1, 1], [-1, -1, -1], [1, 1, 1],
                                [-1, -1, -1]]]
    params['Jet_Tags'] += [[[1], [2], [4], [5, 6], [10]]]
    params['Jet_Child1'] += [[[1, -1, -1], [4, -1, -1], [-1, 8, -1],
                              [-1, 11, -1], [-1, 14, -1]]]
    params['Jet_Parent'] += [[[-1, 0, 0], [-1, 3, 3], [7, -1, 7], [-1, 10, 10],
                              [13, -1, 13]]]
    # PT order is 2, 0, 1, 4
    expected.append(15)
    prep_params = {
        key: ak.from_iter([ak.from_iter(e) for e in v])
        for key, v in params.items()
    }
    # check this results in the predicted masses
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**prep_params)
        masses = JetQuality.sorted_masses(eventWise,
                                          jet_name,
                                          mass_function='highest pt pair',
                                          jet_pt_cut=0)
        tst.assert_allclose(masses, sorted(expected))
        masses = JetQuality.sorted_masses(eventWise,
                                          jet_name,
                                          mass_function='highest pt pair',
                                          jet_pt_cut=2.1)
        tst.assert_allclose(masses, sorted(expected[1:]))
Example #22
0
def python_shape(energies, pxs, pys, pzs, thrust_axis=None):
    """
    

    Parameters
    ----------
    energies :
        
    pxs :
        
    pys :
        
    pzs :
        

    Returns
    -------

    """
    shapes = {}
    # https://home.fnal.gov/~mrenna/lutp0613man2/node234.html
    # precalculate some quantities
    momentums = np.vstack((pxs, pys, pzs)).T
    birrs2 = np.sum(momentums**2, axis=1)
    # This way round gets Fortran like results
    #sum_birr = np.sqrt(np.sum(birrs2))
    #sum_Tbirr = np.sqrt(np.sum(momentums[:, :2]**2))
    sum_birr = np.sum(np.sqrt(birrs2))
    sum_Tbirr = np.sum(np.sqrt(np.sum(momentums[:, :2]**2, axis=1)))
    # Thrust
    if thrust_axis is None:
        def to_minimise(theta_phi):
            """
            

            Parameters
            ----------
            theta_phi :
                

            Returns
            -------

            """
            sin_theta = np.sin(theta_phi[0])
            thrust_axis = [sin_theta*np.cos(theta_phi[1]),
                           sin_theta*np.sin(theta_phi[1]),
                           np.cos(theta_phi[0])]
            return -np.sum(np.abs(np.dot(momentums, thrust_axis)))
        theta_phi_bounds = ((0, np.pi), (-np.pi, np.pi))
        best_theta_phi = minimzer(to_minimise, bounds=theta_phi_bounds,
                                  objective_name="Thrust")
        sin_theta = np.sin(best_theta_phi[0])
        thrust_axis = [sin_theta*np.cos(best_theta_phi[1]),
                       sin_theta*np.sin(best_theta_phi[1]),
                       np.cos(best_theta_phi[0])]
    else:
        phi, pt = Components.pxpy_to_phipt(thrust_axis[0], thrust_axis[1])
        theta = Components.ptpz_to_theta(pt, thrust_axis[2])
        best_theta_phi = (theta, phi)
    shapes['thrustVector[1]'] = thrust_axis[0]
    shapes['thrustVector[2]'] = thrust_axis[1]
    shapes['thrustVector[3]'] = thrust_axis[2]
    momentum_dot_thrust = np.dot(momentums, thrust_axis)
    shapes['Thrust'] = np.sum(np.abs(momentum_dot_thrust))/sum_birr
    # transverse Thrust
    def to_minimise_transverse(phi):
        """
        

        Parameters
        ----------
        phi :
            

        Returns
        -------

        """
        transverse_thrust_axis = [np.cos(phi), np.sin(phi)]
        return -np.sum(np.abs(np.dot(momentums[:, :2], transverse_thrust_axis)))
    phi_bounds = (-np.pi, np.pi)
    best_phi = minimzer(to_minimise_transverse, bounds=phi_bounds,
                        objective_name="TransThrust")
    transverse_thrust_axis = [np.cos(best_phi), np.sin(best_phi)]
    momentum_dot_Tthrust = np.dot(momentums[:, :2], transverse_thrust_axis)
    shapes['Transversethrust'] = np.sum(np.abs(momentum_dot_Tthrust))/sum_Tbirr
    # the major thrust has an exist in the plane perpendicular to the thrust
    if best_theta_phi[0] in (np.pi, 0):
        # along the z axis
        perp1 = np.array([1, 0, 0])
        perp2 = np.array([0, 1, 0])
    else:
        perp1 = np.cross(np.array([0, 0, 1]), thrust_axis)
        perp1 /= np.sqrt(np.sum(perp1**2))
        perp2 = np.cross(perp1, thrust_axis)
        perp2 /= np.sqrt(np.sum(perp2**2))
    if not (np.isclose(np.dot(perp1, thrust_axis), 0) and \
           np.isclose(np.dot(perp2, thrust_axis), 0) and \
           np.isclose(np.dot(perp1, perp2), 0)):
        print("?")
        #st()
    def to_minimise_major(alpha):
        """
        

        Parameters
        ----------
        alpha :
            

        Returns
        -------

        """
        major_thrust_axis = np.cos(alpha)*perp1 + np.sin(alpha)*perp2
        return -np.sum(np.abs(momentums*major_thrust_axis))
    best_alpha = minimzer(to_minimise_major, bounds=(-np.pi, np.pi),
                          objective_name="Major")
    major_thrust_axis = np.cos(best_alpha)*perp1 + np.sin(best_alpha)*perp2
    shapes['Major[1]'] = major_thrust_axis[0]
    shapes['Major[2]'] = major_thrust_axis[1]
    shapes['Major[3]'] = major_thrust_axis[2]
    momentum_dot_major = np.dot(momentums, major_thrust_axis)
    shapes['Major'] = np.sum(np.abs(momentum_dot_major))/sum_birr
    minor_direction = np.cross(major_thrust_axis, thrust_axis)
    minor_direction /= np.sqrt(np.sum(minor_direction**2))
    shapes['Minor[1]'] = minor_direction[0]
    shapes['Minor[2]'] = minor_direction[1]
    shapes['Minor[3]'] = minor_direction[2]
    sum_momentum_dot_minor = max(np.sum(np.abs(np.dot(momentums, minor_direction))),
                                 np.sum(np.abs(np.dot(momentums, -minor_direction))))
    shapes['Minor'] = sum_momentum_dot_minor/sum_birr
    shapes['Oblateness'] = shapes['Major'] - shapes['Minor']

    # sphericity
    dimension = 3
    per_mom_tensor = np.ones((dimension, dimension, len(momentums)))
    for i in range(dimension):
        per_mom_tensor[:, i, :] *= momentums.T
        per_mom_tensor[i, :, :] *= momentums.T
    mom_tensor = np.sum(per_mom_tensor, axis=2)
    eigenvalues, _ = scipy.linalg.eig(mom_tensor/sum_birr**2)
    eigenvalues = np.real(np.sort(eigenvalues)/np.sum(eigenvalues))
    shapes['Sphericity'] = 1.5*(eigenvalues[0] + eigenvalues[1])
    shapes['Alpanarity'] = 1.5*eigenvalues[0]
    shapes['Planarity'] = eigenvalues[1] - eigenvalues[0]
    lin_mom_tensor = np.sum(per_mom_tensor/np.sqrt(birrs2), axis=2)
    eigenvalues, _ = scipy.linalg.eig(lin_mom_tensor/sum_birr)
    eigenvalues = np.real(np.sort(eigenvalues)/np.sum(eigenvalues))
    shapes['Cparameter'] = 3*(eigenvalues[2]*eigenvalues[1] +
                              eigenvalues[2]*eigenvalues[0] +
                              eigenvalues[1]*eigenvalues[0])
    shapes['Dparameter'] = 27*np.product(eigenvalues)
    # spherocity
    def to_minimise_spherocity(phi):
        """
        

        Parameters
        ----------
        phi :
            

        Returns
        -------

        """
        spherocity_axis = [np.cos(phi), np.sin(phi)]
        return -np.abs(np.sum(np.cross(momentums[:, :2], spherocity_axis)))
    phi_bounds = (-np.pi, np.pi)
    best_phi = minimzer(to_minimise_spherocity, bounds=phi_bounds, objective_name="Spherocity")
    spherocity_axis = [np.cos(best_phi), np.sin(best_phi)]
    momentum_cross_sphro = np.cross(momentums[:, :2], spherocity_axis)
    shapes['Spherocity'] = 0.25*np.pi**2*(np.sum(momentum_cross_sphro)/sum_Tbirr)**2
    # Acoplanarity
    def to_minimise_aco(theta_phi):
        """
        

        Parameters
        ----------
        theta_phi :
            

        Returns
        -------

        """
        sin_theta = np.sin(theta_phi[0])
        acoplanarity_axis = [sin_theta*np.cos(theta_phi[1]),
                             sin_theta*np.sin(theta_phi[1]),
                             np.cos(theta_phi[0])]
        return np.sum(np.abs(momentums*acoplanarity_axis))
    theta_phi_bounds = ((0, np.pi), (-np.pi, np.pi))
    best_theta_phi = minimzer(to_minimise_aco, bounds=theta_phi_bounds, objective_name="Acoplanarity")
    sin_theta = np.sin(best_theta_phi[0])
    acoplanarity_axis = [sin_theta*np.cos(best_theta_phi[1]),
                         sin_theta*np.sin(best_theta_phi[1]),
                         np.cos(best_theta_phi[0])]
    momentum_dot_aco = np.dot(momentums, acoplanarity_axis)
    shapes['Acoplanarity'] = 4*np.sum(np.abs(momentum_dot_aco))/sum_birr
    # jet masses
    upper = np.dot(momentums[:, :2], transverse_thrust_axis) > 0
    upper_mass2 = np.sum(energies[upper]**2) - np.sum(momentums[upper]**2)
    lower_mass2 = np.sum(energies[~upper]**2) - np.sum(momentums[~upper]**2)
    shapes['Lightjetmass2'], shapes['Heavyjetmass2'] = sorted((upper_mass2, lower_mass2))
    shapes['Differencejetmass2'] = abs(upper_mass2 - lower_mass2)
    return shapes
Example #23
0
def plot_rapidity_phi_offset(jet_name,
                             eventWise,
                             rapidity_in,
                             phi_in,
                             tag_rapidity_in,
                             tag_phi_in,
                             ax_arr=None):
    if ax_arr is None:
        fig, ax_arr = plt.subplots(1, 3)
        fig.suptitle(jet_name)
    colour = ak.flatten(eventWise.DetectableTag_Mass)
    alpha = 0.2
    x_range = (-3.5, 3.5)
    y_range = (0, np.pi + 0.1)
    # zeroth axis has the full jet kinematics
    ax = ax_arr[0]
    ax.set_title("Entire jets")
    rapidity_distance = ak.flatten(
        (ak.from_iter(rapidity_in) - eventWise.DetectableTag_Rapidity))
    phi_distance = ak.flatten(
        ak.from_iter(phi_in) - eventWise.DetectableTag_Phi)
    phi_distance = Components.raw_to_angular_distance(phi_distance)
    # print the mean distance
    ax.scatter([0], [0], s=5, c='k', marker='o')
    mean_distance = np.nanmean(np.sqrt(rapidity_distance**2 + phi_distance**2))
    # put a dot at the origin
    ax.text(0,
            y_range[1] * 0.75,
            f"mean distance={mean_distance:.2f}",
            horizontalalignment='center')
    points = ax.scatter(rapidity_distance, phi_distance, c=colour, alpha=alpha)
    ax.set_xlabel("Jet rapidity offset")
    ax.set_ylabel("Jet $|\\phi|$ offset")
    ax.set_ylim(y_range)
    ax.set_xlim(x_range)
    # add a colourbar
    cbar = plt.colorbar(points, ax=ax)
    cbar.set_label("True mass of detectable signal")
    # the first axis has only the signal content of the jet
    ax = ax_arr[1]
    ax.set_title("Signal content of jets")
    tag_rapidity_distance = ak.flatten(
        ak.from_iter(tag_rapidity_in) - eventWise.DetectableTag_Rapidity)
    tag_phi_distance = ak.flatten(
        (ak.from_iter(tag_phi_in) - eventWise.DetectableTag_Phi))
    tag_phi_distance = Components.raw_to_angular_distance(tag_phi_distance)
    # print the mean distance
    tag_mean_distance = np.nanmean(
        np.sqrt(tag_rapidity_distance**2 + tag_phi_distance**2))
    ax.text(0,
            y_range[1] * 0.75,
            f"mean distance={tag_mean_distance:.2f}",
            horizontalalignment='center')
    # put a dot at the origin
    ax.scatter([0], [0], s=5, c='k', marker='o')
    points = ax.scatter(tag_rapidity_distance,
                        tag_phi_distance,
                        c=colour,
                        alpha=alpha)
    ax.set_xlabel("Jet rapidity offset")
    ax.set_ylabel("Jet $|\\phi|$ offset")
    ax.set_ylim(y_range)
    ax.set_xlim(x_range)
    # add a colourbar
    cbar = plt.colorbar(points, ax=ax)
    cbar.set_label("True mass of detectable signal")
    if len(ax_arr) > 2:
        # then in the last axis discribe the jet
        PlottingTools.discribe_jet(eventWise, jet_name, ax=ax_arr[2])
        fig.subplots_adjust(top=0.88,
                            bottom=0.11,
                            left=0.05,
                            right=1.0,
                            hspace=0.2,
                            wspace=0.255)
        fig.set_size_inches(12, 4.)
    return mean_distance, tag_mean_distance
Example #24
0
def allocate(jet_phis,
             jet_rapidities,
             tag_phis,
             tag_rapidities,
             max_angle2,
             valid_jets=None):
    """
    In a given event each tag is allocated to a jet. 
    Each tag may only be allocated up to once, jets may recive multiple tags.
    If no valid jet is found inside the max_angle the tag will not be allocated.
    Unallocated tags are returned as -1.

    Parameters
    ----------
    jet_phis : array of floats
        the center of mass phi of each jet
    jet_rapidities : array of floats
        the center of mass rapidity of each jet
    tag_phis : array of floats
        the phi of each tag
    tag_rapidities : array of floats
        the rapidity of each tag
    valid_jets : array like of ints
        The idx of the jets that can be tagged, as found in the eventWise
        If None then all jets are valid
        (Default value = None)
    jet_name : str
        The prefix of the jet vairables in the eventWise
    max_angle2 : float
        the maximium angle that a tag may be alloated to squared
        (a deltaR mesurment)
        

    Returns
    -------
    closest : numpy array of ints
        The indices of the closest jet to each tag,
        -1 if no sutable jet found
    
    """
    if valid_jets is not None:
        # check that a list of indices not a bool mask has been passed
        if len(valid_jets) == len(jet_rapidities):
            # should they be the same length every index must appear
            # just check for the last one
            assert len(jet_rapidities) - 1 in valid_jets
        # select only valid jets for comparison
        jet_phis = jet_phis[valid_jets]
        jet_rapidities = jet_rapidities[valid_jets]
    tag_phis = ak.to_numpy(tag_phis).reshape((-1, 1))
    phi_distance = tag_phis - jet_phis
    phi_distance = Components.raw_to_angular_distance(phi_distance)
    tag_rapidities = ak.to_numpy(tag_rapidities).reshape((-1, 1))
    rap_distance = tag_rapidities - jet_rapidities
    dist2 = np.square(phi_distance) + np.square(rap_distance)
    try:
        closest = np.argmin(dist2, axis=1)
    except (np.AxisError, ValueError):
        assert len(dist2) == 0
        return dist2.reshape((0, 0))
    if valid_jets is not None:
        # revert to true indices
        closest = ak.to_numpy(valid_jets)[closest]
    # remove anything with too large an angle
    dist2_closest = np.min(dist2, axis=1)
    closest[dist2_closest > max_angle2] = -1
    return closest
Example #25
0
def test_add_tags_particles():
    params = {}
    jet_name = "Jet"
    # event 0
    params['Jet_Label'] = [ak.from_iter([])]
    params['Jet_Parent'] = [ak.from_iter([])]
    params['Jet_Phi'] = [ak.from_iter([])]
    params['Jet_Rapidity'] = [ak.from_iter([])]
    params['Jet_Energy'] = [ak.from_iter([])]
    params['Jet_PT'] = [ak.from_iter([])]
    params['Phi'] = [ak.from_iter([])]
    params['Rapidity'] = [ak.from_iter([])]
    params['Children'] = [ak.from_iter([])]
    params['Parents'] = [ak.from_iter([])]
    params['MCPID'] = [ak.from_iter([])]
    params['DetectableTag_Roots'] = [ak.from_iter([])]
    # event 1
    params['Jet_Label'] += [ak.from_iter([[0, 1, 2], [3, 4, 5]])]
    params['Jet_Parent'] += [ak.from_iter([[1, -1, 1], [1, -1, 1]])]
    params['Jet_Phi'] += [ak.from_iter([[0., 1., 1.], [1., np.pi, 1.]])]
    params['Jet_Rapidity'] += [ak.from_iter([[0., 1., 1.], [1., 2., 1.]])]
    params['Jet_Energy'] += [ak.from_iter([[1., 1., 1.], [1., 1., 1.]])]
    params['Jet_PT'] += [ak.from_iter([[1., 5., 1.], [1., 5., 1.]])]
    params['Phi'] += [ak.from_iter([4., 0., -np.pi, -1., np.pi, 2.])]
    params['Rapidity'] += [ak.from_iter([0., 0., -2., 10., 2., 0.])]
    params['Children'] += [
        ak.from_iter([[], [2, 3], [5], [6, 5], [], [], [7, 8, 9], [], [], [],
                      []])
    ]
    #                                   0   1   2     3   4   5        6   7
    params['Parents'] += [
        ak.from_iter([[], [], [1], [1], [], [2, 3], [3], [6], [6], [6], []])
    ]
    #                                 0   1  2  3   4  5   6   7  8
    params['MCPID'] += [ak.from_iter([4, -5, 5, 44, 2, 1, -5, -1, 7, 11, 12])]
    params['DetectableTag_Roots'] += [ak.from_iter([[2]])]
    params['X'] = [[], []]
    expected = [[], [1]]
    expected_creators = [np.array([]), np.array([[]])]
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**params)
        # try with append falst
        tag_angle = 8.
        hyperparameter_content, content =\
                TrueTag.add_tags(eventWise, jet_name, tag_angle,
                                 overwrite=True, append=False)
        assert hyperparameter_content[jet_name + "_TagAngle"] == tag_angle
        # as we didn't append the eventWise content should have stayed the same
        assert jet_name + "_Tags" not in eventWise.columns
        # the add tags method will call the add_tag_particles
        tag_angle = 10.
        TrueTag.add_tags(eventWise, jet_name, tag_angle, append=True)
        hyperparameter_content, content =\
                TrueTag.add_tags(eventWise, jet_name, tag_angle, overwrite=False, append=False)
        assert hyperparameter_content[jet_name + "_TagAngle"] == tag_angle
        # check the tagged jets
        eventWise.selected_event = 0
        tst.assert_allclose(eventWise.Jet_Tags.tolist(), [])
        # in event2 the only tag is particle 2
        # particle 2 has phi=-pi rap=-2
        # this is closest to the first jet at 0. 0.
        eventWise.selected_event = 1
        assert len(ak.flatten(eventWise.Jet_Tags)) == 1
        assert eventWise.Jet_Tags[0][0] == 2
        assert content[jet_name + "_Tags"][1][0][0] == 2
        # add tag particles  ~ colud be a sperate test really....
        TrueTag.add_tag_particles(eventWise)
        # check the tag particles
        eventWise.selected_event = 0
        tst.assert_allclose(eventWise.TagIndex, expected[0])
        tst.assert_allclose(ak.flatten(eventWise.TagCreators),
                            expected_creators[0].flatten())
        eventWise.selected_event = 1
        tst.assert_allclose(eventWise.TagIndex, expected[1])
        tst.assert_allclose(ak.flatten(eventWise.TagCreators),
                            ak.flatten(expected_creators[1]))
Example #26
0
def add_tags(eventWise,
             jet_name,
             max_angle,
             batch_length=100,
             min_tracks=None,
             silent=False,
             append=True,
             overwrite=False):
    """
    Calculate and allocate the tags in the traditional way, using add_detectable_fourvector
    as we only wish to tag with particles that are in principle detectable. 

    Parameters
    ----------
    eventWise : EventWise
        dataset containing locations of particles and jets
    jet_name : str
        The prefix of the jet vairables in the eventWise
    max_angle : float
        the maximium angle that a tag may be alloated to a jet
        (a deltaR mesurment)
        If None then max_angle is drawn from Constants.py
        (Default value = None)
    batch_length: int
        max number of events to process
        (Default value = 100)
    min_tracks : int
        the minimum number of track for a jet to eb considered for tagging.
        If None then min_tracks is drawn from Constants.py
        (Default value = None)
    silent : bool
        Should the progress be printed?
        (Default value = False)
    append : bool
        Should the results be appended to the eventWise?
        (Default value = True)
    overwrite : bool
        Should existing results be abandoned?
        (Default value = True)
        

    Returns
    -------
    (if not appending)
    hyperparameter_content : dict
        hyperparameter values for eventWise
    content: dict of awkward arrays
        content for eventWise
    
    """
    if min_tracks is None:
        min_tracks = Constants.min_ntracks
    if max_angle is None:
        max_angle = Constants.max_tagangle
    eventWise.selected_event = None
    name = jet_name + "_Tags"
    namePID = jet_name + "_TagPIDs"
    n_events = len(getattr(eventWise, jet_name + "_Energy", []))
    if "DetectableTag_Roots" not in eventWise.columns:
        add_detectable_fourvector(eventWise, silent=silent)
    if overwrite:
        jet_tags = []
        jet_tagpids = []
    else:
        jet_tags = list(getattr(eventWise, name, []))
        jet_tagpids = list(getattr(eventWise, namePID, []))
    start_point = len(jet_tags)
    name_tagangle = jet_name + "_TagAngle"
    hyperparameter_content = {name_tagangle: max_angle}
    if start_point >= n_events:
        print("Finished")
        content = {}
        content[name] = ak.from_iter(jet_tags)
        content[namePID] = ak.from_iter(jet_tagpids)
        if append:
            return
        else:
            return hyperparameter_content, content
    end_point = min(n_events, start_point + batch_length)
    if not silent:
        print(f" Will stop at {end_point/n_events:.1%}")
    # name the vaiables to be cut on
    # will actually compare the square of the angle for speed
    max_angle2 = max_angle**2
    for event_n in range(start_point, end_point):
        if event_n % 10 == 0 and not silent:
            print(f"{event_n/n_events:.1%}", end='\r', flush=True)
        if os.path.exists("stop"):
            print(f"Completed event {event_n-1}")
            break
        eventWise.selected_event = event_n
        # get the tags
        tags = ak.flatten(eventWise.DetectableTag_Roots).tolist()
        #  Jacan need this to not be a BQuark!!!
        tag_phis = eventWise.Phi[tags]
        tag_raps = eventWise.Rapidity[tags]
        # get the valiables to cut on
        jet_roots = getattr(eventWise, jet_name + "_Parent") == -1
        jet_pt = ak.flatten(getattr(eventWise, jet_name + "_PT")[jet_roots])
        if len(jet_pt) == 0:
            num_tracks = []
            valid_jets = []
        else:
            # note this actually counts num pesudojets,
            # but for more than 2 that is sufficient
            num_tracks = \
                Components.apply_array_func(len, getattr(eventWise,
                                                         jet_name+"_PT"))
            valid_jets = np.where(num_tracks > min_tracks - 0.1)[0]
        jets_tags = [[] for _ in jet_pt]
        if len(tags) > 0 and len(valid_jets) > 0:
            # there may not be any of the particles we wish to tag in the event
            # or there may not be any jets
            jet_phis = ak.flatten(
                getattr(eventWise, jet_name + "_Phi")[jet_roots])
            jet_raps = ak.flatten(
                getattr(eventWise, jet_name + "_Rapidity")[jet_roots])
            closest_matches = allocate(jet_phis, jet_raps, tag_phis, tag_raps,
                                       max_angle2, valid_jets)
        else:
            closest_matches = []
        # keep only the indices for space reasons
        for match, particle in zip(closest_matches, tags):
            if match != -1:
                jets_tags[match].append(particle)
        jet_tags.append(ak.from_iter(jets_tags))
        tagpids = [eventWise.MCPID[jet] for jet in tags]
        jet_tagpids.append(ak.from_iter(tagpids))
    content = {}
    content[name] = ak.from_iter(jet_tags)
    content[namePID] = ak.from_iter(jet_tagpids)
    hyperparameter_content = {name_tagangle: max_angle}
    if append:
        eventWise.append(**content)
        eventWise.append_hyperparameters(**hyperparameter_content)
    else:
        return hyperparameter_content, content
def test_create_eigenvectors():
    params = {}
    # event 0  # no particles, should not have issues
    params['X'] = [ak.from_iter([])]
    params['JetInputs_SourceIdx'] = [ak.from_iter([])]
    params['JetInputs_Energy'] = [ak.from_iter([])]
    params['JetInputs_Px'] = [ak.from_iter([])]
    params['JetInputs_Py'] = [ak.from_iter([])]
    params['JetInputs_Pz'] = [ak.from_iter([])]
    # event 1  # just one particle should still work
    params['X'] += [ak.from_iter(np.arange(1))]
    params['JetInputs_SourceIdx'] += [ak.from_iter(np.arange(1))]
    params['JetInputs_Energy'] += [ak.from_iter([30.])]
    params['JetInputs_Px'] += [ak.from_iter([3.])]
    params['JetInputs_Py'] += [ak.from_iter([3.])]
    params['JetInputs_Pz'] += [ak.from_iter([3.])]
    # event 2  # two totally seperated particles shoudl produce totaly sperated results
    params['X'] += [ak.from_iter(np.arange(1))]
    params['JetInputs_SourceIdx'] += [ak.from_iter(np.arange(1))]
    params['JetInputs_Energy'] += [ak.from_iter([30., 40.])]
    params['JetInputs_Px'] += [ak.from_iter([3., 3.])]
    params['JetInputs_Py'] += [ak.from_iter([3., -3.])]
    params['JetInputs_Pz'] += [ak.from_iter([3., -3.])]
    # event 3  # standard event
    params['X'] += [ak.from_iter(np.arange(6))]
    params['JetInputs_SourceIdx'] += [ak.from_iter(np.arange(6))]
    params['JetInputs_Energy'] += [
        ak.from_iter([30., 10., 20., 70., 20., 10.])
    ]
    params['JetInputs_Px'] += [ak.from_iter([3., 1., 2., 1., 2., -1.])]
    params['JetInputs_Py'] += [ak.from_iter([3., 1., 2., 2., 2., 1.])]
    params['JetInputs_Pz'] += [ak.from_iter([3., 0., 2., 0., 2., 2.])]
    # invarient_mass                      873 sqrt99 388   4859, 388, 94
    # shifted energy                       30   10   20   70 sqrt(393) sqrt(103)
    with TempTestDir("tst") as dir_name:
        eventWise = Components.EventWise(os.path.join(dir_name, "tmp.parquet"))
        eventWise.append(**params)
        Components.add_phi(eventWise, "JetInputs")
        Components.add_PT(eventWise, "JetInputs")
        Components.add_rapidity(eventWise, "JetInputs")
        #TODO renitroduce this
        #jet_params = dict(CutoffDistance=1.)
        jet_params = {"EigenvalueLimit": np.inf}
        values, vectors = ParameterInvestigation.create_eigenvectors(
            eventWise, jet_params)
        # first event was empty
        assert len(values[0]) == 0
        assert len(vectors[0]) == 0
        # second event only had one object
        assert len(values[1]) == 0
        tst.assert_allclose(vectors[1].shape, [1, 0])
        # third event should be totaly seperated
        assert len(values[2]) == 1
        tst.assert_allclose(vectors[2].shape, [2, 1])
        # TODO need the CutoffDistance for this
        #tst.assert_allclose(vectors[2][0, 1], 0)
        #tst.assert_allclose(vectors[2][1, 0], 0)
        # forth event is regular
        assert len(values[3]) == 5
        assert len(vectors[3]) == 6
        assert len(vectors[3][0]) == 5
Example #28
0
def marry(hepmc, root_particles):
    """
    Combine the information in a hepmc file and a root file
    in one eventWise, to have richer information about the particles

    Parameters
    ----------
    hepmc : str or EventWise
        if a str should be the path to the hepmc file on disk
        if an EventWise should be a dataset with the
        hepmc event data
    root_particles : str or EventWise
        if a str should be the path to the root file on disk
        if an EventWise should be a dataset with the
        root event data

    Returns
    -------
    new_eventWise : EventWise
        dataset containing matched data from teh root file and
        the hepmc file.
    
    """
    if isinstance(root_particles, str):
        root_particles = Components.RootReadout(root_particles,
                                                ['Particle', 'Track', 'Tower'])
    if isinstance(hepmc, str):
        if Components.EventWise.pottential_file(hepmc):
            hepmc = ReadHepmc.Hepmc.from_file(hepmc)
        else:
            hepmc = ReadHepmc.Hepmc(hepmc)
    # first we assert that they both contain the same number of events
    n_events = len(root_particles.PID)
    assert n_events == len(
        hepmc.MCPID), "Files cotain doferent number of events"
    # this being extablished we compare them eventwise
    #  (hepmc name, root name)
    precicely_equivalent = [('MCPID', 'PID'), ('Status_code', 'Status')]
    close_equivalent = [('Px', 'Px'), ('Py', 'Py'), ('Pz', 'Pz'),
                        ('Energy', 'Energy'), ('Generated_mass', 'Mass')]
    for event_n in range(n_events):
        hepmc.selected_event = event_n
        root_particles.selected_event = event_n
        # the particles are expected to have the same order in both files
        for hepmc_name, root_name in precicely_equivalent:
            assert np.all(root_particles.__getattr__(root_name)
                          == hepmc.__getattr__(hepmc_name)), \
                                  f"{root_name} in root file not equal to {hepmc_name}"+\
                                  " in hepmc file"
        for hepmc_name, root_name in close_equivalent:
            np.testing.assert_allclose(
                root_particles.__getattr__(root_name),
                hepmc.__getattr__(hepmc_name),
                err_msg=f"{root_name} in root file not close" +
                "to {hepmc_name} in hepmc file")
    # remove all selected indices
    hepmc.selected_event = None
    root_particles.selected_event = None
    # we will keep all of the root columns, but only a selection of the hepmc columns
    # ensure a copy is made
    columns = [name for name in root_particles.columns]
    # forcefully read in here
    contents = {key: getattr(root_particles, key) for key in columns}
    per_event_hepmc_cols = hepmc.event_information_cols + hepmc.weight_cols + \
                           hepmc.units_cols + hepmc.cross_section_cols
    columns += sorted(per_event_hepmc_cols)
    for name in per_event_hepmc_cols:
        contents[name] = getattr(hepmc, name)
    # some get renamed
    per_vertex_hepmc_cols = {
        'Vertex_barcode': 'Vertex_barcode',
        'X': 'Vertex_X',
        'Y': 'Vertex_Y',
        'Z': 'Vertex_Z',
        'Ctau': 'Vertex_Ctau'
    }
    columns += sorted(per_vertex_hepmc_cols.values())
    for name, new_name in per_vertex_hepmc_cols.items():
        contents[new_name] = getattr(hepmc, name)
    per_particle_hepmc_cols = [
        'End_vertex_barcode', 'Start_vertex_barcode', 'Parents', 'Children',
        'Is_root', 'Is_leaf'
    ]
    columns += sorted(per_particle_hepmc_cols)
    for name in per_particle_hepmc_cols:
        contents[name] = hepmc.__getattr__(name)
    # firgure out which of the root columns are per particle and which are per event
    per_particle_root_cols = []
    per_event_root_cols = []
    for name in root_particles.columns:
        values = getattr(root_particles, name)
        _, depth = Components.detect_depth(values[:])
        if depth == 0:
            per_event_root_cols.append(name)
        else:
            per_particle_root_cols.append(name)
    # record what has what level of granularity
    contents['per_event'] = ak.from_iter(per_event_root_cols +
                                         per_event_hepmc_cols)
    contents['per_vertex'] = ak.from_iter(per_vertex_hepmc_cols.values())
    contents['per_particle'] = ak.from_iter(per_particle_root_cols +
                                            per_particle_hepmc_cols)
    # make the new object and save it
    file_name = (root_particles.file_name.split('.', 1)[0] + '_particles' +
                 Components.EventWise.FILE_EXTENTION)
    dir_name = root_particles.dir_name
    path_name = os.path.join(dir_name, file_name)
    new_eventWise = Components.EventWise(path_name, columns, contents)
    new_eventWise.write()
    return new_eventWise