<jupyter_start><jupyter_text>Example of parsing a .dec decay file with Lark<jupyter_code>from lark import Lark, Tree

from decaylanguage import data<jupyter_output><empty_output><jupyter_text>Read in the Lark grammar definition file and the input .dec decay file<jupyter_code>with data.basepath.joinpath("decfile.lark").open() as f:
    grammar = f.read()

with open("../tests/data/test_example_Dst.dec") as f:
    dec_file = f.read()<jupyter_output><empty_output><jupyter_text>For illustration - the grammar Lark file:<jupyter_code>print(grammar)<jupyter_output>// Copyright (c) 2018-2021, <NAME> and <NAME>.
//
// Distributed under the 3-clause BSD license, see accompanying file LICENSE
// or https://github.com/scikit-hep/decaylanguage for details.

start : _NEWLINE* (line _NEWLINE+)+ ("End" _NEWLINE+)?
?line : define | pythia_def | jetset_def | alias | chargeconj | commands | decay | cdecay | copydecay | setlspw

pythia_def : "PythiaBothParam" LABEL ":" LABEL "=" (LABEL | SIGNED_NUMBER)

jetset_def : "JetSetPar" LABEL "=" SIGNED_NUMBER

setlspw : "SetLineshapePW" label label label value

cdecay : "CDecay" label

define : "Define" label value

alias : "Alias" label label

chargeconj : "ChargeConj" label label

?commands : global_photos

global_photos : boolean_photos

boolean_photos : "yesPhotos" -> yes
                | "noPhotos"  -> no

decay : "Decay" particle _NEWLINE+ decayline+ "Enddecay"
decayline : value particle* photos? model (_NEWLINE | _SEMICOLON)+ // There is always a ; here
value : SIGNED_NUMBER
photos : "PHO[...]<jupyter_text>For illustration - the .dec decay file:<jupyter_code>print(dec_file)<jupyter_output># Example decay chain for testing purposes
# Considered by itself, this file in in fact incomplete,
# as there are no instructions on how to decay the anti-D0 and the D-!

Decay D*+
0.6770    D0  pi+                    VSS;
0.3070    D+  pi0                    VSS;
0.0160    D+  gamma                  VSP_PWAVE;
Enddecay

Decay D*-
0.6770    anti-D0  pi-                VSS;
0.3070    D-       pi0                VSS;
0.0160    D-       gamma              VSP_PWAVE;
Enddecay

Decay D0
1.0   K-      pi+                  PHSP;
Enddecay

Decay D+
1.0   K-   pi+   pi+   pi0    PHSP;
Enddecay

Decay pi0
0.988228297   gamma   gamma                   PHSP;
0.011738247   e+      e-      gamma           PI0_DALITZ;
0.000033392   e+      e+      e-      e-      PHSP;
0.000000065   e+      e-                      PHSP;
Enddecay<jupyter_text>Parse the .dec decay file.<jupyter_code>l = Lark(grammar, parser="lalr", lexer="standard")
parsed_dec_file = l.parse(dec_file)
def number_of_decays(parsed_file):
    """Returns the number of particle decays defined in the parsed .dec file."""
    return len(list(parsed_file.find_data("decay")))


print("# of decays in file =", number_of_decays(parsed_dec_file))
def list_of_decay_trees(parsed_file):
    """Return a list of the actual decays defined in the .dec file."""
    list_of_decays = list(parsed_file.find_data("decay"))
    return list_of_decays


list_of_decay_trees(parsed_dec_file)
def get_decay_mode_details(decay_mode_Tree):
    """Parse a decay mode tree and return the relevant bits of information in it."""
    bf = (
        [x for x in decay_mode_Tree.find_data("value")][0].children[0].value
        if len([x for x in decay_mode_Tree.find_data("value")]) == 1
        else None
    )
    bf = float(bf)
    products = tuple(
        [
            p.children[0].value
            for p in decay_mode_Tree.children
            if isinstance(p, Tree) and p.data == "particle"
        ]
    )
    model = (
        [x for x in decay_mode_Tree.find_data("model")][0].children[0].value
        if len([x for x in decay_mode_Tree.find_data("model")]) == 1
        else None
    )
    return (bf, products, model)<jupyter_output><empty_output><jupyter_text>Finally, digest all Lark's Tree objects parsed and collect the information of all defined decays.<jupyter_code>decays = {}

for tree in list_of_decay_trees(parsed_dec_file):
    if tree.data == "decay":
        if tree.children[0].children[0].value in decays:
            print(
                "Decays of particle %s are redefined! Please check your .dec file."
                % tree.children[0].children[0].value
            )
        decays[tree.children[0].children[0].value] = []
        for decay_mode in tree.find_data("decayline"):
            decays[tree.children[0].children[0].value].append(
                get_decay_mode_details(decay_mode)
            )<jupyter_output><empty_output><jupyter_text>For illustration - print out the decay modes:<jupyter_code>def print_decay(dec, final_state):
    """Pretty print of the decay modes of a given particle."""
    print(dec)
    for fs in final_state:
        print("%12g : %50s %15s" % (fs[0], "  ".join(p for p in fs[1]), fs[2]))
print_decay("pi0", decays["pi0"])
for particle, decay_info in decays.items():
    print_decay(particle, decay_info)<jupyter_output>D*+
       0.677 :                                            D0  pi+             VSS
       0.307 :                                            D+  pi0             VSS
       0.016 :                                          D+  gamma       VSP_PWAVE
D*-
       0.677 :                                       anti-D0  pi-             VSS
       0.307 :                                            D-  pi0             VSS
       0.016 :                                          D-  gamma       VSP_PWAVE
D0
           1 :                                            K-  pi+            PHSP
D+
           1 :                                  K-  pi+  pi+  pi0            PHSP
pi0
    0.988228 :                                       gamma  gamma            PHSP
   0.0117382 :                                      e+  e-  gamma      PI0_DALITZ
  3.3392e-05 :                                     e+  e+  e-  e-            PHSP
     6.5e-08 :                                             e+  e-            PHS[...]<jupyter_text>For illustration - produce a dot plot of a decay Tree:<jupyter_code>from lark.tree import pydot__tree_to_png  # requires pydot

pydot__tree_to_png(
    list_of_decay_trees(parsed_dec_file)[0], filename="decay.png", rankdir="LR"
)

from IPython.display import Image

Image(filename="decay.png")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10186649794368871, 'fraction_numerical': 0.028313824739006642, 'mean_word_length': 2.0442946557534905, 'pattern_counts': {'":': 2, '<': 32, '<?xml version=': 0, '>': 34, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 27, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '236263', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2191, 'n_tokens_neox': 2036, 'n_words': 529, 'path': 'notebooks/ExampleDecFileParsingWithLark.ipynb', 'repo_name': 'scikit-hep/decaylanguage', 'size': '6342'}