11import re
2- from typing import Dict , List , Set , Any
2+ from typing import Any , Dict , List
3+
34
45class DashboardLatticeParser :
56 """
@@ -15,7 +16,7 @@ def __init__(self, content: str):
1516 def parse (self ) -> Dict [str , Any ]:
1617 """
1718 Extracts the lattice configuration from provided ImpactX simulation file.
18-
19+
1920 Example return:
2021 {
2122 "lattice_elements": [
@@ -44,21 +45,21 @@ def parse(self) -> Dict[str, Any]:
4445 print (f"Warning: Unsupported operation type: { operation_type } " )
4546
4647 clean_lattice_list = self .replace_variables (expanded_elements )
47- clean_lattice_list_str = ' \n ' .join (clean_lattice_list )
48+ clean_lattice_list_str = " \n " .join (clean_lattice_list )
4849 result = self .parse_cleaned_lattice (clean_lattice_list_str )
4950
5051 return result
5152
5253 def parse_cleaned_lattice (self , content : str ) -> Dict [str , List [Dict [str , Any ]]]:
5354 """
5455 Parses the lattice elements from the ImpactX simulation file content.
55-
56+
5657 Extracts element names and their parameters from constructor calls in the format:
5758 elements.ElementName(param1=value1, param2=value2, ...)
58-
59+
5960 EX:
6061 elements.Drift(ds=1.0)
61-
62+
6263 Results in:
6364 {
6465 "lattice_elements": [
@@ -68,7 +69,7 @@ def parse_cleaned_lattice(self, content: str) -> Dict[str, List[Dict[str, Any]]]
6869 }
6970 ]
7071 }
71-
72+
7273 :param content: The content of the ImpactX simulation file.
7374 :return: A dictionary containing the parsed lattice elements.
7475 """
@@ -79,10 +80,7 @@ def parse_cleaned_lattice(self, content: str) -> Dict[str, List[Dict[str, Any]]]
7980 lattice_elements = re .findall (element_pattern , content , re .DOTALL )
8081
8182 for element_name , parameter in lattice_elements :
82- element = {
83- "name" : element_name ,
84- "parameters" : {}
85- }
83+ element = {"name" : element_name , "parameters" : {}}
8684
8785 # CHANGE: Updated parameter pattern to handle multiline and whitespace around =
8886 # OLD: r"(\w+)=([^,\)]+)"
@@ -97,11 +95,10 @@ def parse_cleaned_lattice(self, content: str) -> Dict[str, List[Dict[str, Any]]]
9795
9896 return dictionary
9997
100-
10198 def collect_lattice_operations (self , debug : bool = False ) -> List [Dict [str , str ]]:
10299 """
103100 Collects lattice operations (sim.lattice.append(), sim.lattice.extend(), and variable.reverse() calls)
104- in the order they appear in the content.
101+ in the order they appear in the content.
105102
106103 EX:
107104 sim.lattice.append(monitor) ; sim.lattice.extend([drift1, quad1]) ; lattice_half.reverse()
@@ -125,12 +122,16 @@ def collect_lattice_operations(self, debug: bool = False) -> List[Dict[str, str]
125122 # Store sim.lattice.append and sim.lattice.extend calls
126123 for match in re .finditer (lattice_call_pattern , self ._content ):
127124 operation , arg = match .groups ()
128- operations .append ((match .start (), {"type" : operation , "argument" : arg .strip ()}))
125+ operations .append (
126+ (match .start (), {"type" : operation , "argument" : arg .strip ()})
127+ )
129128
130129 # Store .reverse() calls
131130 reverse_pattern = r"(\w+)\.reverse\(\)"
132131 for match in re .finditer (reverse_pattern , self ._content ):
133- operations .append ((match .start (), {"type" : "reverse" , "argument" : match .group (1 )}))
132+ operations .append (
133+ (match .start (), {"type" : "reverse" , "argument" : match .group (1 )})
134+ )
134135
135136 # important: sort operations by their position in the content
136137 # since the for loops can be executed in any order
@@ -145,33 +146,33 @@ def _get_variable_assignments(self) -> Dict[str, str]:
145146 """
146147 Helper function to extract all variable list assignments from content.
147148 Caches the result to avoid re-parsing the same content.
148-
149+
149150 EX:
150151 content = '''
151152 drift1 = elements.Drift(ds=1.0)
152153 cell = [drift1, quad1]
153154 line = [cell, monitor]
154155 '''
155156 _get_variable_assignments()
156-
157+
157158 Results in:
158159 {
159160 "cell": "drift1, quad1",
160161 "line": "cell, monitor"
161162 }
162-
163+
163164 """
164165 if self ._content_hash in self ._variable_assignments_cache :
165166 return self ._variable_assignments_cache [self ._content_hash ]
166-
167+
167168 variable_assignments = {}
168169 var_assignment_pattern = r"(\w+)\s*=\s*\[(.*?)\]"
169-
170+
170171 for match in re .finditer (var_assignment_pattern , self ._content , re .DOTALL ):
171172 var_name = match .group (1 )
172173 list_content = match .group (2 )
173174 variable_assignments [var_name ] = list_content
174-
175+
175176 self ._variable_assignments_cache [self ._content_hash ] = variable_assignments
176177 return variable_assignments
177178
@@ -187,7 +188,7 @@ def _flatten(self, variable_name: str, debug: bool = False) -> List[str]:
187188 sim.lattice.extend(line)
188189 '''
189190 _flatten(content, "line")
190-
191+
191192 Results in:
192193 ["drift1", "quad1", "drift1", "quad1"]
193194
@@ -199,22 +200,28 @@ def _flatten(self, variable_name: str, debug: bool = False) -> List[str]:
199200 cache_key = f"{ self ._content_hash } :{ variable_name } "
200201 if cache_key in self ._flatten_cache :
201202 return self ._flatten_cache [cache_key ]
202-
203+
203204 # Get variable assignments (cached)
204205 variable_assignments = self ._get_variable_assignments ()
205-
206+
206207 # Check if the input is an inline list like "[monitor, elements.Drift(...)]"
207208 if variable_name .startswith ("[" ) and variable_name .endswith ("]" ):
208209 list_contents = variable_name [1 :- 1 ]
209210 # split on commas that are NOT inside parentheses
210- list_to_flatten = [element .strip () for element in re .split (r",\s*(?![^()]*\))" , list_contents ) if element .strip ()]
211+ list_to_flatten = [
212+ element .strip ()
213+ for element in re .split (r",\s*(?![^()]*\))" , list_contents )
214+ if element .strip ()
215+ ]
211216 else :
212217 if variable_name not in variable_assignments :
213218 self ._flatten_cache [cache_key ] = [variable_name ]
214219 return [variable_name ] # It's not a list, it's a single element
215220
216221 list_content = variable_assignments [variable_name ]
217- list_to_flatten = [item .strip () for item in list_content .split ("," ) if item .strip ()]
222+ list_to_flatten = [
223+ item .strip () for item in list_content .split ("," ) if item .strip ()
224+ ]
218225
219226 expanded = []
220227 for item in list_to_flatten :
@@ -224,9 +231,8 @@ def _flatten(self, variable_name: str, debug: bool = False) -> List[str]:
224231
225232 # Cache the result
226233 self ._flatten_cache [cache_key ] = expanded
227-
228- return expanded
229234
235+ return expanded
230236
231237 def replace_variables (self , raw_lattice : List [str ]) -> List [str ]:
232238 """
@@ -237,7 +243,7 @@ def replace_variables(self, raw_lattice: List[str]) -> List[str]:
237243 drift1 = elements.Drift(ds=1.0)
238244 quad1 = elements.Quad(k=0.5)
239245 raw_lattice = ["drift1", "quad1"]
240- (output)
246+ (output)
241247 raw_lattice = ["elements.Drift(ds=1.0)", "elements.Quad(k=0.5)"]
242248
243249 :param raw_lattice: List of lattice element variable names or constructor calls, e.g. ["drift1", "quad1"].
@@ -259,7 +265,7 @@ def replace_variables(self, raw_lattice: List[str]) -> List[str]:
259265 # Replace each item in the list
260266 # later can be optimized by not iterating over the whole raw_lattice list
261267 return [element_mapping .get (item , item ) for item in raw_lattice ]
262-
268+
263269 def extract_lattice_inputs (self , parsed_lattice : Dict [str , Any ]) -> List [str ]:
264270 """
265271 Extracts all parameter values from parsed lattice data.
@@ -303,8 +309,7 @@ def _apply_reverse(self, var_name: str) -> None:
303309 # Clear the flatten cache so future lookups rebuild the list using the new reversed order.
304310 self ._flatten_cache .clear ()
305311
306-
307- #-----------------------------------------------------------------------------
312+ # -----------------------------------------------------------------------------
308313 # Debug methods
309314 # -----------------------------------------------------------------------------
310315
0 commit comments