1- from typing import List , Tuple , Dict
1+ from typing import List , Dict
22from pathlib import Path
33import json
4- import warnings
5-
6- from .validate import validate
7- from .parse import parse_elegant
8-
9-
10- LATTICEJSON_ELEGANT_MAP : Tuple [Tuple [str , Tuple [str , ...]], ...] = (
11- ("Drift" , ("DRIF" , "DRIFT" )),
12- ("Dipole" , ("CSBEND" , "SBEND" , "BEND" )),
13- ("Quadrupole" , ("KQUAD" , "QUAD" , "QUADRUPOLE" )),
14- ("Sextupole" , ("KSEXT" , "SEXT" , "SEXTUPOLE" )),
15- ("Lattice" , ("LINE" ,)),
16- ("length" , ("L" ,)),
17- ("angle" , ("ANGLE" ,)),
18- ("e1" , ("E1" ,)),
19- ("e2" , ("E2" ,)),
20- ("k1" , ("K1" ,)),
21- ("k2" , ("K2" ,)),
22- )
23- JSON_TO_ELE : Dict [str , str ] = {x : y [0 ] for x , y in LATTICEJSON_ELEGANT_MAP }
24- ELE_TO_JSON : Dict [str , str ] = {y : x for x , tup in LATTICEJSON_ELEGANT_MAP for y in tup }
25-
26-
27- def latticejson_to_elegant (lattice_dict ) -> str :
28- """Convert LatticeJSON dict to elegant lattice file format.
29- :param dict: dict in LatticeJSON format
30- :return: string with in elegant lattice file format
31- """
32- elements = lattice_dict ["elements" ]
33- sub_lattices = lattice_dict ["sub_lattices" ]
4+ from warnings import warn
5+ from .parse import parse_elegant , parse_madx
6+ from .exceptions import UnknownElementWarning , UnknownAttributeWarning
347
35- strings = []
36- element_template = "{}: {}, {}" .format
37- for name , (type_ , attributes ) in elements .items ():
38- attrs = ", " .join (f"{ JSON_TO_ELE [k ]} ={ v } " for k , v in attributes .items ())
39- elegant_type = JSON_TO_ELE [type_ ]
40- strings .append (element_template (name , elegant_type , attrs ))
8+ NAME_MAP = json .loads ((Path (__file__ ).parent / "map.json" ).read_text ())["map" ]
9+ JSON_TO_ELE = {x : y [0 ][0 ] for x , * y in NAME_MAP }
10+ ELE_TO_JSON = {y : x for x , * tup in NAME_MAP for y in tup [0 ]}
11+ JSON_TO_MADX = {x : y [1 ][0 ] for x , * y in NAME_MAP }
12+ MADX_TO_JSON = {y : x for x , * tup in NAME_MAP for y in tup [1 ]}
4113
42- lattice_template = "{}: LINE=({})" .format
43- for name in sort_lattices (sub_lattices ):
44- strings .append (lattice_template (name , ", " .join (sub_lattices [name ])))
4514
46- name = lattice_dict ["name" ]
47- strings .append (lattice_template (name , ", " .join (lattice_dict ["lattice" ])))
48- strings .append ("\n " )
49- return "\n " .join (strings )
15+ def from_elegant (string ):
16+ """Convert an elegant lattice file to a LatticeJSON dict.
5017
18+ :param str string: input lattice file as string
19+ :param lattice_name: name of the lattice
20+ :type str, optional
21+ :param description: description of the lattice
22+ :type str, optional
23+ :return: dict in LatticeJSON format
24+ """
25+ return _map_names_from_elegant (parse_elegant (string ))
5126
52- def elegant_to_latticejson (string ):
53- """Convert an elegant lattice file to a LatticeJSON dict.
27+
28+ def from_madx (string ):
29+ """Convert a MADX lattice file to a LatticeJSON dict.
5430
5531 :param str string: input lattice file as string
5632 :param lattice_name: name of the lattice
@@ -59,30 +35,36 @@ def elegant_to_latticejson(string):
5935 :type str, optional
6036 :return: dict in LatticeJSON format
6137 """
62- elegant_dict = parse_elegant ( string )
38+ return _map_names_from_madx ( parse_madx ( string ) )
6339
40+
41+ def _map_names_from_madx (madx_dict : dict ):
42+ return _map_names (madx_dict , MADX_TO_JSON )
43+
44+
45+ def _map_names_from_elegant (elegant_dict : dict ):
46+ return _map_names (elegant_dict , ELE_TO_JSON )
47+
48+
49+ def _map_names (lattice_data : dict , name_map : dict ):
6450 elements = {}
65- for name , (elegant_type , elegant_attributes ) in elegant_dict ["elements" ].items ():
66- latticejson_type = ELE_TO_JSON .get (elegant_type )
51+ for name , (other_type , other_attributes ) in lattice_data ["elements" ].items ():
52+ latticejson_type = name_map .get (other_type )
6753 if latticejson_type is None :
68- elements [name ] = ["Drift" , {"length" : elegant_attributes .get ("L" , 0 )}]
69- warnings .warn (
70- f"Replacing element { name } ({ elegant_type } ) with Drift." , stacklevel = 2
71- )
54+ elements [name ] = ["Drift" , {"length" : other_attributes .get ("L" , 0 )}]
55+ warn (UnknownElementWarning (name , other_type ), stacklevel = 2 )
7256 continue
7357
7458 attributes = {}
7559 elements [name ] = [latticejson_type , attributes ]
76- for elegant_key , value in elegant_attributes .items ():
77- latticejson_key = ELE_TO_JSON .get (elegant_key )
60+ for other_key , value in other_attributes .items ():
61+ latticejson_key = name_map .get (other_key )
7862 if latticejson_key is not None :
7963 attributes [latticejson_key ] = value
8064 else :
81- warnings .warn (
82- f"Ignoring attribute { elegant_key } of { name } ." , stacklevel = 2
83- )
65+ warn (UnknownAttributeWarning (other_key , name ), stacklevel = 2 )
8466
85- lattices = elegant_dict ["lattices" ]
67+ lattices = lattice_data ["lattices" ]
8668 lattice_name , main_lattice = lattices .popitem () # use last lattice as main_lattice
8769 return dict (
8870 name = lattice_name ,
@@ -92,24 +74,54 @@ def elegant_to_latticejson(string):
9274 )
9375
9476
95- def sort_lattices_old ( lattices : Dict [ str , List [ str ]] ) -> List [ str ] :
96- """Returns a sorted list of lattice names for a given dict of lattices."""
77+ def to_elegant ( latticejson : dict ) -> str :
78+ """Convert a LatticeJSON dict to the elegant lattice file format.
9779
98- lattices_copy = lattices .copy ()
99- lattice_names = []
80+ :param lattice_dict dict: dict in LatticeJSON format
81+ :return: string with in elegant lattice file format
82+ """
83+ elements = latticejson ["elements" ]
84+ sub_lattices = latticejson ["sub_lattices" ]
10085
101- def _sort_lattices (name , arrangement : List [str ]):
102- for child_name in arrangement :
103- if child_name in lattices_copy :
104- _sort_lattices (child_name , lattices_copy [child_name ])
86+ strings = [f"! TITLE: { latticejson ['name' ]} " ]
87+ element_template = "{}: {}, {}" .format
88+ for name , (type_ , attributes ) in elements .items ():
89+ attrs = ", " .join (f"{ JSON_TO_ELE [k ]} ={ v } " for k , v in attributes .items ())
90+ elegant_type = JSON_TO_ELE [type_ ]
91+ strings .append (element_template (name , elegant_type , attrs ))
10592
106- lattice_names .append (name )
107- lattices_copy .pop (name )
93+ lattice_template = "{}: LINE=({})" .format
94+ for name in sort_lattices (sub_lattices ):
95+ strings .append (lattice_template (name , ", " .join (sub_lattices [name ])))
96+
97+ strings .append (lattice_template ("__MAIN__" , ", " .join (latticejson ["lattice" ])))
98+ strings .append ("USE, __MAIN__\n " )
99+ return "\n " .join (strings )
108100
109- for name , arrangement in lattices .items ():
110- _sort_lattices (name , arrangement )
111101
112- return lattice_names
102+ def to_madx (latticejson : dict ) -> str :
103+ """Convert a LatticeJSON dict to the MADX lattice file format.
104+
105+ :param lattice_dict dict: dict in LatticeJSON format
106+ :return: string with in elegant lattice file format
107+ """
108+ elements = latticejson ["elements" ]
109+ sub_lattices = latticejson ["sub_lattices" ]
110+
111+ strings = [f"TITLE, \" { latticejson ['name' ]} \" " ]
112+ element_template = "{}: {}, {};" .format
113+ for name , (type_ , attributes ) in elements .items ():
114+ attrs = ", " .join (f"{ JSON_TO_MADX [k ]} ={ v } " for k , v in attributes .items ())
115+ elegant_type = JSON_TO_MADX [type_ ]
116+ strings .append (element_template (name , elegant_type , attrs ))
117+
118+ lattice_template = "{}: LINE=({});" .format
119+ for name in sort_lattices (sub_lattices ):
120+ strings .append (lattice_template (name , ", " .join (sub_lattices [name ])))
121+
122+ strings .append (lattice_template ("__MAIN__" , ", " .join (latticejson ["lattice" ])))
123+ strings .append ("USE, __MAIN__;\n " )
124+ return "\n " .join (strings )
113125
114126
115127def sort_lattices (lattices : Dict [str , List [str ]]) -> List [str ]:
0 commit comments