11import logging
2+ import xml .etree .ElementTree as ET
23from pathlib import Path
34from typing import Dict , Optional
45
1213)
1314from murfey .client .instance_environment import MurfeyInstanceEnvironment
1415from murfey .util .client import capture_post
16+ from murfey .util .models import FoilHoleParameters
1517from murfey .util .spa_metadata import (
16- FoilHoleInfo ,
1718 get_grid_square_atlas_positions ,
1819 grid_square_data ,
1920)
2021
2122logger = logging .getLogger ("murfey.client.contexts.spa_metadata" )
2223
2324
24- def _foil_hole_positions (xml_path : Path , grid_square : int ) -> Dict [str , FoilHoleInfo ]:
25- with open (xml_path , "r" ) as xml :
26- for_parsing = xml .read ()
27- data = xmltodict .parse (for_parsing )
28- data = data ["GridSquareXml" ]
29- if "TargetLocationsEfficient" in data ["TargetLocations" ].keys ():
30- # Grids with regular foil holes
31- serialization_array = data ["TargetLocations" ]["TargetLocationsEfficient" ][
32- "a:m_serializationArray"
33- ]
34- elif "TargetLocations" in data ["TargetLocations" ].keys ():
35- # Lacey grids
36- serialization_array = data ["TargetLocations" ]["TargetLocations" ][
37- "a:m_serializationArray"
38- ]
39- else :
25+ def _foil_hole_positions (
26+ xml_path : Path , tag : str , grid_square : int
27+ ) -> Dict [str , FoilHoleParameters ]:
28+ tree = ET .parse (xml_path )
29+ for elem in tree .iter ():
30+ if "}" in elem .tag :
31+ elem .tag = elem .tag .split ("}" )[1 ]
32+ tree_root = tree .getroot ()
33+ target_locations = tree_root .find ("TargetLocations" )
34+ serialization_array = None
35+ if target_locations :
36+ if eff_target_locations := target_locations .find ("TargetLocationsEfficient" ):
37+ # Grids with regular foil holes
38+ serialization_array = eff_target_locations .find ("m_serializationArray" )
39+ elif eff_target_locations := target_locations .find ("TargetLocations" ):
40+ # Lacey grids
41+ serialization_array = eff_target_locations .find ("m_serializationArray" )
42+ if not serialization_array :
4043 logger .warning (f"Target locations not found for { str (xml_path )} " )
4144 return {}
42- required_key = ""
43- for key in serialization_array .keys ():
44- if key .startswith ("b:KeyValuePairOfintTargetLocation" ):
45- required_key = key
46- break
47- if not required_key :
48- logger .info (f"Required key not found for { str (xml_path )} " )
49- return {}
45+
46+ fh_blocks = [
47+ i
48+ for i in serialization_array .iter ()
49+ if "KeyValuePairOfintTargetLocationXml" in i .tag
50+ ]
5051 foil_holes = {}
51- for fh_block in serialization_array [required_key ]:
52- if fh_block ["b:value" ]["IsNearGridBar" ] == "false" :
53- image_paths = list (
54- (xml_path .parent .parent ).glob (
55- f"Images-Disc*/GridSquare_{ grid_square } /FoilHoles/FoilHole_{ fh_block ['b:key' ]} _*.jpg"
52+ for fh_block in fh_blocks :
53+ fh_block_values = fh_block .find ("value" )
54+ fh_key = fh_block .find ("key" )
55+ if fh_key and fh_key .text and fh_block_values :
56+ near_grid_bar = fh_block_values .find ("IsNearGridBar" )
57+ if near_grid_bar and near_grid_bar .text == "false" :
58+ image_paths = list (
59+ (xml_path .parent .parent ).glob (
60+ f"Images-Disc*/GridSquare_{ grid_square } /FoilHoles/FoilHole_{ fh_key .text } _*.jpg"
61+ )
5662 )
57- )
58- image_paths .sort (key = lambda x : x .stat ().st_ctime )
59- image_path : str = str (image_paths [- 1 ]) if image_paths else ""
60- pix_loc = fh_block ["b:value" ]["PixelCenter" ]
61- stage = fh_block ["b:value" ]["StagePosition" ]
62- diameter = fh_block ["b:value" ]["PixelWidthHeight" ]["c:width" ]
63- foil_holes [fh_block ["b:key" ]] = FoilHoleInfo (
64- id = int (fh_block ["b:key" ]),
65- grid_square_id = grid_square ,
66- x_location = int (float (pix_loc ["c:x" ])),
67- y_location = int (float (pix_loc ["c:y" ])),
68- x_stage_position = float (stage ["c:X" ]),
69- y_stage_position = float (stage ["c:Y" ]),
70- image = str (image_path ),
71- diameter = int (float (diameter )),
72- )
63+ image_paths .sort (key = lambda x : x .stat ().st_ctime )
64+ image_path : str = str (image_paths [- 1 ]) if image_paths else ""
65+ pix_loc = fh_block_values .find ("PixelCenter" )
66+ stage = fh_block_values .find ("StagePosition" )
67+ width_height = fh_block_values .find ("PixelWidthHeight" )
68+ diameter = width_height .find ("width" ) if width_height else None
69+ if pix_loc and stage :
70+ x_pix = pix_loc .find ("x" )
71+ y_pix = pix_loc .find ("y" )
72+ x_stage = stage .find ("X" )
73+ y_stage = stage .find ("Y" )
74+ foil_holes [fh_key .text ] = FoilHoleParameters (
75+ name = int (fh_key .text ),
76+ tag = tag ,
77+ x_location = int (float (x_pix .text ))
78+ if (x_pix and x_pix .text )
79+ else None ,
80+ y_location = int (float (y_pix .text ))
81+ if (y_pix and y_pix .text )
82+ else None ,
83+ x_stage_position = int (float (x_stage .text ))
84+ if (x_stage and x_stage .text )
85+ else None ,
86+ y_stage_position = int (float (y_stage .text ))
87+ if (y_stage and y_stage .text )
88+ else None ,
89+ image = str (image_path ),
90+ diameter = int (float (diameter .text ))
91+ if (diameter and diameter .text )
92+ else None ,
93+ ).model_dump ()
7394 return foil_holes
7495
7596
@@ -193,7 +214,6 @@ def post_transfer(
193214 logger .info (
194215 f"Collecting foil hole positions for { str (transferred_file )} and grid square { gs_name } "
195216 )
196- fh_positions = _foil_hole_positions (transferred_file , gs_name )
197217 visitless_source_search_dir = "/" .join (
198218 [part for part in source .parts if part != environment .visit ]
199219 ).replace ("//" , "/" )
@@ -209,6 +229,11 @@ def post_transfer(
209229 Path (visitless_source_search_dir ) / "Images-Disc1"
210230 ]
211231 visitless_source = str (visitless_source_images_dirs [- 1 ])
232+ fh_positions = _foil_hole_positions (
233+ xml_path = transferred_file ,
234+ tag = visitless_source ,
235+ grid_square = gs_name ,
236+ )
212237
213238 if fh_positions :
214239 gs_info = grid_square_data (
@@ -244,44 +269,28 @@ def post_transfer(
244269 },
245270 )
246271
247- if gs_name not in self ._registered_squares :
248- for fh , fh_data in fh_positions .items ():
249- capture_post (
250- base_url = str (environment .url .geturl ()),
251- router_name = "session_control.spa_router" ,
252- function_name = "register_foil_hole" ,
253- token = self ._token ,
254- instrument_name = environment .instrument_name ,
255- session_id = environment .murfey_session ,
256- gs_name = gs_name ,
257- data = {
258- "name" : fh ,
259- "x_location" : fh_data .x_location ,
260- "y_location" : fh_data .y_location ,
261- "x_stage_position" : fh_data .x_stage_position ,
262- "y_stage_position" : fh_data .y_stage_position ,
263- "readout_area_x" : fh_data .readout_area_x ,
264- "readout_area_y" : fh_data .readout_area_y ,
265- "thumbnail_size_x" : fh_data .thumbnail_size_x ,
266- "thumbnail_size_y" : fh_data .thumbnail_size_y ,
267- "pixel_size" : fh_data .pixel_size ,
268- "diameter" : fh_data .diameter ,
269- "tag" : visitless_source ,
270- "image" : fh_data .image ,
271- },
272- )
273- if fh_positions :
274- capture_post (
275- base_url = str (environment .url .geturl ()),
276- router_name = "session_control.spa_router" ,
277- function_name = "register_square" ,
278- token = self ._token ,
279- instrument_name = environment .instrument_name ,
280- session_id = environment .murfey_session ,
281- gsid = gs_name ,
282- data = {
283- "tag" : visitless_source ,
284- "count" : len (self ._registered_squares ) + 1 ,
285- },
286- )
287- self ._registered_squares .add (gs_name )
272+ if fh_positions and gs_name not in self ._registered_squares :
273+ capture_post (
274+ base_url = str (environment .url .geturl ()),
275+ router_name = "session_control.spa_router" ,
276+ function_name = "register_foil_holes" ,
277+ token = self ._token ,
278+ instrument_name = environment .instrument_name ,
279+ session_id = environment .murfey_session ,
280+ gs_name = gs_name ,
281+ data = fh_positions ,
282+ )
283+ capture_post (
284+ base_url = str (environment .url .geturl ()),
285+ router_name = "session_control.spa_router" ,
286+ function_name = "register_square" ,
287+ token = self ._token ,
288+ instrument_name = environment .instrument_name ,
289+ session_id = environment .murfey_session ,
290+ gsid = gs_name ,
291+ data = {
292+ "tag" : visitless_source ,
293+ "count" : len (self ._registered_squares ) + 1 ,
294+ },
295+ )
296+ self ._registered_squares .add (gs_name )
0 commit comments