예제 #1
0
def printTable(table, first_index=0, stable_decays=True):
    """Print MC truth from 'table' starting from particle at 'first_index'.

    Prints MC truth for the specified particle and its descendents in
    tabular format."""

    print "  row  ID                      parent  children"
    print "-----------------------------------------------"

    # First collect the indices of rows that need to be included.  These
    # rows include that given by 'first_index', and its direct and
    # indirect descendents.  Build the result here.  
    indices = [first_index]
    # 'indices' doubles as our worklist, and 'position' is the start of
    # the worklist.
    position = 0
    # Loop until we've considered all the rows we need to.
    while position < len(indices):
        i = indices[position]
        # Get the row.
        row = table[i]
        child_begin = i + row["child_offset"]
        child_end = child_begin + row["num_children"]
        # Append all children of this row.
        if stable_decays or not pdt.findId(row["id"]).is_stable:
            for j in range(child_begin, child_end):
                indices.append(j)
        # Done with this row.
        position += 1
    # Put the rows into numerical order.
    indices.sort()

    # Print the rows.
    for i in indices:
        row = table[i]
        if row["parent_offset"] == 0:
            parent = "   "
        else:
            parent = "%5d" % (i + row["parent_offset"])
        child_begin = i + row["child_offset"]
        child_end = child_begin + row["num_children"]
        print "%5d  %-20s   %5s %5d-%5d" \
              % (i, pdt.findId(row["id"]).name, parent,
                 child_begin, child_end)
    print
예제 #2
0
def printStdhep(table, first_index):
    """Print an MC truth table for a particle decay tree.

    'table' -- A STDHEP table.

    'first_index' -- The index of the parent particle whose tree to print.

    Prints MC truth for the specified particle and its descendents in
    tabular format."""

    print "  row  species                    parents     children"
    print "------------------------------------------------------"

    # First collect the indices of rows that need to be included.  These
    # rows include that given by 'first_index', and its direct and
    # indirect descendents.  Build the result here.  
    indices = [first_index]
    # 'indices' doubles as our worklist, and 'position' is the start of
    # the worklist.
    position = 0
    # Loop until we've considered all the rows we need to.
    while position < len(indices):
        i = indices[position]
        # Get the row.
        row = table[i]
        child_begin = i + row["child_begin_offset"]
        child_end = i + row["child_end_offset"]
        # Append all children of this row.
        for j in range(child_begin, child_end):
            indices.append(j)
        # Done with this row.
        position += 1
    # Put the rows into numerical order.
    indices.sort()

    # Print the rows.
    for i in indices:
        row = table[i]
        if row["parent_offset"] == 0:
            parent = "   "
        else:
            parent = "%5d" % (i + row["parent_offset"])
        if row["parent2_offset"] == 0:
            parent2 = "   "
        else:
            parent2 = "%5d" % (i + row["parent2_offset"])
        child_begin = i + row["child_begin_offset"]
        child_end = i + row["child_end_offset"]
        if child_begin == child_end:
            children = "      -     "
        else:
            children = "%5d -%5d" % (child_begin, child_end)
        print "%5d  %-20s   %5s %5s %s" \
              % (i, pdt.findId(row["id"]).name, parent, parent2,
                 children)
    print
예제 #3
0
def _printTree(table, index, indent, stable_decays, labels):
    row = table[index]
    pdt_info = pdt.findId(row["id"])
    name = (indent * " ") + pdt_info.name
    child_begin = row["child_offset"] + index
    child_end = child_begin + row["num_children"]
    print "%5d  %-20s   %7.3f %7.3f %7.3f %7.3f   %s" \
          % (index, name, row["en"], row["px"], row["py"],
             row["pz"], str(labels.get(index, "")))
    # Recursively print children too.
    if stable_decays or not pdt_info.is_stable:
        for child_index in range(child_begin, child_end):
            _printTree(table, child_index, indent + 1, stable_decays, labels)
예제 #4
0
def buildTable(decay, table, labels):
    """Construct an MC truth table from a 'Decay'.

    'decay' -- A 'Decay' instance.

    'table' -- A list to append to.  This will contain the constructed
    table. 

    'labels' -- A dictionary in which to store label information.  For
    each decay and subdecay, an entry is added whose key is the decay's
    label and whose value is the decay's index."""

    # Keep a work list of subdecays to process, along with the parent
    # index for each.
    work_list = [(decay, -1, )]
    while len(work_list) > 0:
        # Get the next decay to work on.
        decay, parent = work_list.pop(0)
        # Construct the entry.
        index = len(table)
        entry = {}
        entry["id"] = decay.id
        entry["cc_id"] = pdt.findId(decay.id).charge_conjugate.id
        if parent == -1:
            entry["parent_offset"] = 0
        else:
            entry["parent_offset"] = parent - index
        entry["child_begin_offset"] = len(work_list) + 1
        entry["child_end_offset"] = len(work_list) + 1 + len(decay.products)
        # Add it to the result.
        table.append(entry)
        # Update labels.
        labels[decay.label] = index
        # Add child decays to the work list.
        for product in decay.products:
            work_list.append((product, index))
예제 #5
0
 def __get_species(self):
     species = pdt.findId(self.id).name
     self.__dict__["species"] = species
     return species
예제 #6
0
def _matchTree(pattern, decay, cc_mode, matches):
    """Recursively match 'pattern' to 'decay', filling in 'matches'.

    returns -- 'is_match, match_cc_mode', where 'is_match' is true if
    the match succeeds, and if so, 'match_cc_mode' contains the actual
    CC mode of the match (which may be different from 'cc_mode', if
    'cc_mode' is zero)."""

    # Get the ID of the pattern particle and its CC.
    pattern_id = pattern.id
    pattern_cc_id = pdt.findId(pattern_id).charge_conjugate.id
    # Get the ID of the decay particle.
    decay_id = decay.id

    if False:
        print "_matchTree(%s, %s, %d)" \
              % (pdt.findId(pattern_id).name,
                 pdt.findId(decay_id).name, cc_mode)

    if cc_mode == 1:
        # The MC truth must match the decay's ID.
        if decay_id != pattern_id:
            return False, None
    elif cc_mode == -1:
        # The MC truth must match the decay's CC ID.
        if decay_id != pattern_cc_id:
            return False, None
    elif cc_mode == 0:
        # We may match either the ID or its CC.
        if decay_id == pattern_id and decay_id == pattern_cc_id:
            pass
        elif decay_id == pattern_id:
            # Matched the ID.  Disallow CC matches for the parent.
            cc_mode = 1
        elif decay_id == pattern_cc_id:
            # Matched the CC ID.  Disallow non-CC matches for the
            # parent.
            cc_mode = -1
        else:
            return False, None

    try:
        label = pattern.label
    except AttributeError:
        pass
    else:
        matches[label] = decay

    pattern_products = pattern.decay_products
    # If the pattern is missing decay information, assume the match is
    # OK.
    if pattern_products is None:
        return True, cc_mode
    num_products = len(pattern_products)

    decay_products = decay.decay_products
    # It must have the same number of children as in the decay pattern.
    if len(decay_products) != num_products:
        return False, None

    # Loop over all permutations of match-ups between children in the
    # decay pattern and children in MC truth.
    for permutations in hep.fn.permute(tuple(range(num_products))):
        success = True
        # In each permutation, match each of the children.
        for i in xrange(num_products):
            # FIXME: If cc_mode is zero, don't we need to require that
            # all children match in the same cc_mode (or zero), i.e.
            # that there aren't both children that match for cc_mode = 1
            # and children that match for cc_mode = -1 ?
            is_match, match_cc_mode = \
                _matchTree(pattern_products[permutations[i]],
                           decay_products[i], cc_mode, matches)
            if not is_match:
                # Match failed.  Bail on this permutation.
                success = False
                break
            elif cc_mode == -match_cc_mode:
                # It matched, but with the wrong CC mode.
                success = False
                break
        # If we went all the way through all the children and matched
        # each without a failure, we're golden.
        if success:
            return True, match_cc_mode
    # None of the permutations worked out.  The match fails.
    return False, None
예제 #7
0
def parse(input):
    """Parse a decay in indented textual notation.

    returns -- A MC truth table containing the decay."""

    if isinstance(input, str):
        input = input.splitlines()
    # Keep a stack of parent decays and their indentation.
    stack = []

    for line in input:
        # Strip comments from the line.
        if "#" in line:
            line = line[:line.index("#")]
        # Ignore blank lines.
        if line.strip() == "":
            continue

        # Count indentation for this line.
        indentation = 0
        while line[indentation] == " ":
            indentation += 1
        # If we are indented more than the previous line, we'll be
        # adding to the decay at the top of the stack.
        if len(stack) == 0 or indentation > stack[-1][0]:
            pass
        # If we are indentated the same as the previous line, this decay
        # will be a sibling of the decay at the top of the stack, so pop
        # it off so that we add to its parent.
        elif indentation == stack[-1][0]:
            stack.pop()
        # If this line is unindented, pop decays off the stack until we
        # reach the right indentation level.  Then pop one more so that
        # the parent is at the top of the stack.
        else:
            while indentation < stack[-1][0]:
                stack.pop()
            if indentation != stack[-1][0]:
                raise ValueError, "invalid indentation"
            stack.pop()

        # Grab the ID name, and the label if provided.
        if "=" in line:
            name, label = line.split("=")
            label = label.strip()
        else:
            name = line
            label = None
        # Look up the ID.
        id = pdt[name.strip()].id
        # Make up a label if none was given.
        if label is None:
            label = pdt.findId(id).symbol_name

        # Build the decay object.
        decay = Particle(label, id)
        # Add it as a decay product of the particle at the top of the
        # stack. 
        if len(stack) > 0:
            stack[-1][1].decay_products.append(decay)
        # Push it on to the stack.
        stack.append((indentation, decay))

    return stack[0][1]