Skip to content
45 changes: 40 additions & 5 deletions src/murfey/client/contexts/spa.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
thumbnail_size_y: Optional[int] = None
pixel_size: Optional[float] = None
image: str = ""
diameter: Optional[float] = None


class GridSquare(NamedTuple):
Expand All @@ -59,9 +60,18 @@
tag: str = ""


def _get_grid_square_atlas_positions(
xml_path: Path, grid_square: str = ""
) -> Dict[str, Tuple[Optional[int], Optional[int], Optional[float], Optional[float]]]:
def _get_grid_square_atlas_positions(xml_path: Path, grid_square: str = "") -> Dict[
str,
Tuple[
Optional[int],
Optional[int],
Optional[float],
Optional[float],
Optional[int],
Optional[int],
Optional[float],
],
]:
with open(
xml_path,
"r",
Expand All @@ -71,7 +81,16 @@
"TileXml"
]
gs_pix_positions: Dict[
str, Tuple[Optional[int], Optional[int], Optional[float], Optional[float]]
str,
Tuple[
Optional[int],
Optional[int],
Optional[float],
Optional[float],
Optional[int],
Optional[int],
Optional[float],
],
] = {}
for ti in tile_info:
try:
Expand All @@ -96,6 +115,13 @@
* 1e9,
float(gs["value"]["b:PositionOnTheAtlas"]["c:Physical"]["d:y"])
* 1e9,
int(
float(gs["value"]["b:PositionOnTheAtlas"]["c:Size"]["d:width"])
),
int(
float(gs["value"]["b:PositionOnTheAtlas"]["c:Size"]["d:height"])
),
float(gs["value"]["b:PositionOnTheAtlas"]["c:Rotation"]),
)
if grid_square:
break
Expand Down Expand Up @@ -221,6 +247,7 @@
for fh_block in serialization_array[required_key]:
pix = fh_block["b:value"]["PixelCenter"]
stage = fh_block["b:value"]["StagePosition"]
diameter = fh_block["b:value"]["PixelWidthHeight"]["c:width"]

Check warning on line 250 in src/murfey/client/contexts/spa.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/client/contexts/spa.py#L250

Added line #L250 was not covered by tests
if int(fh_block["b:key"]) == foil_hole:
return FoilHole(
id=foil_hole,
Expand All @@ -236,6 +263,7 @@
thumbnail_size_y=None,
pixel_size=float(pixel_size) if image_path else None,
image=str(image_path),
diameter=diameter,
)
logger.warning(
f"Foil hole positions could not be determined from metadata file {xml_path} for foil hole {foil_hole}"
Expand Down Expand Up @@ -557,7 +585,10 @@
Optional[int],
Optional[float],
Optional[float],
] = (None, None, None, None)
Optional[int],
Optional[int],
Optional[float],
] = (None, None, None, None, None, None, None)
data_collection_group = (
requests.get(
f"{str(environment.url.geturl())}/sessions/{environment.murfey_session}/data_collection_groups"
Expand Down Expand Up @@ -611,6 +642,9 @@
"y_location": gs_pix_position[1],
"x_stage_position": gs_pix_position[2],
"y_stage_position": gs_pix_position[3],
"width": gs_pix_position[4],
"height": gs_pix_position[5],
"angle": gs_pix_position[6],
},
)
foil_hole = _foil_hole_from_file(transferred_file)
Expand Down Expand Up @@ -651,6 +685,7 @@
"thumbnail_size_x": fh.thumbnail_size_x,
"thumbnail_size_y": fh.thumbnail_size_y,
"pixel_size": fh.pixel_size,
"diameter": fh.diameter,
"tag": str(source),
"image": str(image_path),
},
Expand Down
37 changes: 37 additions & 0 deletions src/murfey/client/contexts/spa_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import requests
import xmltodict
from PIL import Image

from murfey.client.context import Context
from murfey.client.contexts.spa import _get_grid_square_atlas_positions, _get_source
Expand Down Expand Up @@ -64,6 +65,38 @@
visitless_path = Path(
str(transferred_file).replace(f"/{environment.visit}", "")
)
visit_index_of_transferred_file = transferred_file.parts.index(

Check warning on line 68 in src/murfey/client/contexts/spa_metadata.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/client/contexts/spa_metadata.py#L68

Added line #L68 was not covered by tests
environment.visit
)
atlas_xml_path = list(

Check warning on line 71 in src/murfey/client/contexts/spa_metadata.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/client/contexts/spa_metadata.py#L71

Added line #L71 was not covered by tests
(
Path(
"/".join(
transferred_file.parts[
: visit_index_of_transferred_file + 1
]
)
)
/ partial_path
).parent.glob("Atlas_*.xml")
)[0]
with open(atlas_xml_path, "rb") as atlas_xml:
atlas_xml_data = xmltodict.parse(atlas_xml)
atlas_original_pixel_size = atlas_xml_data["MicroscopeImage"][

Check warning on line 85 in src/murfey/client/contexts/spa_metadata.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/client/contexts/spa_metadata.py#L83-L85

Added lines #L83 - L85 were not covered by tests
"SpatialScale"
]["pixelSize"]["x"]["numericValue"]
readout_width = float(

Check warning on line 88 in src/murfey/client/contexts/spa_metadata.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/client/contexts/spa_metadata.py#L88

Added line #L88 was not covered by tests
atlas_xml_data["MicroscopeImage"]["SpatialScale"]["pixelSize"]["x"][
"numericValue"
]
)

# need to calculate the pixel size of the downscaled image
atlas_im = Image.open(atlas_xml_path.with_suffix(".jpg"))
atlas_pixel_size = atlas_original_pixel_size * (

Check warning on line 96 in src/murfey/client/contexts/spa_metadata.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/client/contexts/spa_metadata.py#L95-L96

Added lines #L95 - L96 were not covered by tests
readout_width / atlas_im.width
)

source = _get_source(
visitless_path.parent / "Images-Disc1" / visitless_path.name,
environment,
Expand All @@ -90,6 +123,7 @@
/ environment.samples[source].atlas
),
"sample": environment.samples[source].sample,
"atlas_pixel_size": atlas_pixel_size,
}
capture_post(url, json=dcg_data)
registered_grid_squares = (
Expand Down Expand Up @@ -121,5 +155,8 @@
"y_location": pos_data[1],
"x_stage_position": pos_data[2],
"y_stage_position": pos_data[3],
"width": pos_data[4],
"height": pos_data[5],
"angle": pos_data[6],
},
)
19 changes: 19 additions & 0 deletions src/murfey/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from fastapi.templating import Jinja2Templates
from importlib_metadata import EntryPoint # For type hinting only
from ispyb.sqlalchemy._auto_db_schema import (
Atlas,
AutoProcProgram,
Base,
DataCollection,
Expand All @@ -43,6 +44,7 @@
from werkzeug.utils import secure_filename

import murfey
import murfey.server.ispyb
import murfey.server.prometheus as prom
import murfey.server.websocket
import murfey.util.db as db
Expand Down Expand Up @@ -2628,8 +2630,17 @@
experimentTypeId=message["experiment_type_id"],
)
dcgid = _register(record, header)
atlas_record = Atlas(
dataCollectionGroupId=dcgid,

Check warning on line 2634 in src/murfey/server/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/__init__.py#L2633-L2634

Added lines #L2633 - L2634 were not covered by tests
atlasImage=message.get("atlas", ""),
pixelSize=message.get("atlas_pixel_size", 0),
cassetteSlot=message.get("sample"),
)
if _transport_object:
atlas_id = _transport_object.do_insert_atlas(atlas_record)
murfey_dcg = db.DataCollectionGroup(
id=dcgid,
atlas_id=atlas_id,
session_id=message["session_id"],
tag=message.get("tag"),
)
Expand All @@ -2654,6 +2665,14 @@
}
_transport_object.transport.ack(header)
return None
elif message["register"] == "atlas_update":
if _transport_object:
_transport_object.do_update_atlas(
message["atlas_id"],

Check warning on line 2671 in src/murfey/server/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/__init__.py#L2671

Added line #L2671 was not covered by tests
message["atlas"],
message["atlas_pixel_size"],
message["sample"],
)
elif message["register"] == "data_collection":
murfey_session_id = message["session_id"]
ispyb_session_id = murfey.server.ispyb.get_session_id(
Expand Down
114 changes: 89 additions & 25 deletions src/murfey/server/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,21 @@
grid_square.y_location = grid_square_params.y_location
grid_square.x_stage_position = grid_square_params.x_stage_position
grid_square.y_stage_position = grid_square_params.y_stage_position
if _transport_object:
_transport_object.do_update_grid_square(grid_square.id, grid_square_params)

Check warning on line 506 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L506

Added line #L506 was not covered by tests
except Exception:
if _transport_object:
dcg = db.exec(

Check warning on line 509 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L509

Added line #L509 was not covered by tests
select(DataCollectionGroup)
.where(DataCollectionGroup.session_id == session_id)
.where(DataCollectionGroup.tag == grid_square_params.tag)
).one()
gs_ispyb_response = _transport_object.do_insert_grid_square(

Check warning on line 514 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L514

Added line #L514 was not covered by tests
dcg.atlas_id, gsid, grid_square_params
)
else:
# mock up response so that below still works
gs_ispyb_response = {"success": False, "return_value": None}

Check warning on line 519 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L519

Added line #L519 was not covered by tests
secured_grid_square_image_path = secure_filename(grid_square_params.image)
if (
secured_grid_square_image_path
Expand All @@ -512,6 +526,11 @@
else:
jpeg_size = (0, 0)
grid_square = GridSquare(
id=(
gs_ispyb_response["return_value"]
if gs_ispyb_response["success"]
else None
),
name=gsid,
session_id=session_id,
tag=grid_square_params.tag,
Expand Down Expand Up @@ -552,16 +571,13 @@
db=murfey_db,
):
try:
gsid = (
db.exec(
select(GridSquare)
.where(GridSquare.tag == foil_hole_params.tag)
.where(GridSquare.session_id == session_id)
.where(GridSquare.name == gs_name)
)
.one()
.id
)
gs = db.exec(

Check warning on line 574 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L574

Added line #L574 was not covered by tests
select(GridSquare)
.where(GridSquare.tag == foil_hole_params.tag)
.where(GridSquare.session_id == session_id)
.where(GridSquare.name == gs_name)
).one()
gsid = gs.id

Check warning on line 580 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L580

Added line #L580 was not covered by tests
except NoResultFound:
log.debug(
f"Foil hole {sanitise(str(foil_hole_params.name))} could not be registered as grid square {sanitise(str(gs_name))} was not found"
Expand All @@ -572,21 +588,53 @@
jpeg_size = Image.open(secured_foil_hole_image_path).size
else:
jpeg_size = (0, 0)
foil_hole = FoilHole(
name=foil_hole_params.name,
session_id=session_id,
grid_square_id=gsid,
x_location=foil_hole_params.x_location,
y_location=foil_hole_params.y_location,
x_stage_position=foil_hole_params.x_stage_position,
y_stage_position=foil_hole_params.y_stage_position,
readout_area_x=foil_hole_params.readout_area_x,
readout_area_y=foil_hole_params.readout_area_y,
thumbnail_size_x=foil_hole_params.thumbnail_size_x or jpeg_size[0],
thumbnail_size_y=foil_hole_params.thumbnail_size_y or jpeg_size[1],
pixel_size=foil_hole_params.pixel_size,
image=secured_foil_hole_image_path,
)
try:
foil_hole = db.exec(

Check warning on line 592 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L591-L592

Added lines #L591 - L592 were not covered by tests
select(FoilHole)
.where(FoilHole.name == foil_hole_params.name)
.where(FoilHole.grid_square_id == gsid)
.where(FoilHole.session_id == session_id)
).one()
foil_hole.x_location = foil_hole_params.x_location
foil_hole.y_location = foil_hole_params.y_location
foil_hole.x_stage_position = foil_hole_params.x_stage_position
foil_hole.y_stage_position = foil_hole_params.y_stage_position
foil_hole.readout_area_x = foil_hole_params.readout_area_x
foil_hole.readout_area_y = foil_hole_params.readout_area_y
foil_hole.thumbnail_size_x = foil_hole_params.thumbnail_size_x or jpeg_size[0]
foil_hole.thumbnail_size_y = foil_hole_params.thumbnail_size_y or jpeg_size[1]
foil_hole.pixel_size = foil_hole_params.pixel_size

Check warning on line 606 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L598-L606

Added lines #L598 - L606 were not covered by tests
if _transport_object:
_transport_object.do_update_foil_hole(

Check warning on line 608 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L608

Added line #L608 was not covered by tests
foil_hole.id, gs.thumbnail_size_x / gs.readout_area_x, foil_hole_params
)
except Exception:

Check warning on line 611 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L611

Added line #L611 was not covered by tests
if _transport_object:
fh_ispyb_response = _transport_object.do_insert_foil_hole(

Check warning on line 613 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L613

Added line #L613 was not covered by tests
gsid.id, gs.thumbnail_size_x / gs.readout_area_x, foil_hole_params
)
else:
fh_ispyb_response = {"success": False, "return_value": None}
foil_hole = FoilHole(

Check warning on line 618 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L617-L618

Added lines #L617 - L618 were not covered by tests
id=(
fh_ispyb_response["return_value"]
if fh_ispyb_response["success"]
else None
),
name=foil_hole_params.name,
session_id=session_id,
grid_square_id=gsid,
x_location=foil_hole_params.x_location,
y_location=foil_hole_params.y_location,
x_stage_position=foil_hole_params.x_stage_position,
y_stage_position=foil_hole_params.y_stage_position,
readout_area_x=foil_hole_params.readout_area_x,
readout_area_y=foil_hole_params.readout_area_y,
thumbnail_size_x=foil_hole_params.thumbnail_size_x or jpeg_size[0],
thumbnail_size_y=foil_hole_params.thumbnail_size_y or jpeg_size[1],
pixel_size=foil_hole_params.pixel_size,
image=secured_foil_hole_image_path,
)
db.add(foil_hole)
db.commit()
db.close()
Expand Down Expand Up @@ -1128,6 +1176,7 @@
"image_number": proc_file.image_number,
"microscope": get_microscope(),
"mc_uuid": murfey_ids[0],
"foil_hole_id": foil_hole_id,
"ft_bin": proc_params["motion_corr_binning"],
"fm_dose": proc_params["dose_per_frame"],
"gain_ref": proc_params["gain_ref"],
Expand Down Expand Up @@ -1335,15 +1384,30 @@
).all():
dcg_murfey[0].atlas = dcg_params.atlas
dcg_murfey[0].sample = dcg_params.sample
dcg_murfey[0].atlas_pixel_size = dcg_params.atlas_pixel_size

Check warning on line 1387 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L1387

Added line #L1387 was not covered by tests
db.add(dcg_murfey[0])
db.commit()
if _transport_object:
_transport_object.send(
_transport_object.feedback_queue,
{
"register": "atlas_update",
"atlas_id": dcg_murfey.atlas_id,

Check warning on line 1395 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L1395

Added line #L1395 was not covered by tests
"atlas": dcg_params.atlas,
"sample": dcg_params.sample,
"atlas_pixel_size": dcg_params.atlas_pixel_size,

Check warning on line 1398 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L1398

Added line #L1398 was not covered by tests
},
)
else:
dcg_parameters = {
"start_time": str(datetime.datetime.now()),
"experiment_type": dcg_params.experiment_type,
"experiment_type_id": dcg_params.experiment_type_id,
"tag": dcg_params.tag,
"session_id": session_id,
"atlas": dcg_params.atlas,

Check warning on line 1408 in src/murfey/server/api/__init__.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/__init__.py#L1408

Added line #L1408 was not covered by tests
"sample": dcg_params.sample,
"atlas_pixel_size": dcg_params.atlas_pixel_size,
}

if _transport_object:
Expand Down
Loading
Loading