Skip to content

Commit 8acd7f3

Browse files
committed
Initial code to insert searchmaps into murfey and ispyb databases
1 parent 10b61ca commit 8acd7f3

File tree

7 files changed

+347
-18
lines changed

7 files changed

+347
-18
lines changed

src/murfey/client/contexts/tomo_metadata.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,6 @@ def post_transfer(
152152
"Binning"
153153
]["a:x"]
154154
)
155-
readout_area = sm_data["MicroscopeImage"]["microscopeData"]["acquisition"][
156-
"camera"
157-
]["ReadoutArea"]
158155

159156
# Get the stage transformation
160157
sm_transformations = sm_data["MicroscopeImage"]["CustomData"][
@@ -222,14 +219,6 @@ def post_transfer(
222219
"tag": visitless_source,
223220
"x_stage_position": float(stage_position["X"]),
224221
"y_stage_position": float(stage_position["Y"]),
225-
"readout_area_x": readout_area[0],
226-
"readout_area_y": readout_area[1],
227-
"thumbnail_size_x": int(
228-
(512 / max(readout_area)) * readout_area[0]
229-
),
230-
"thumbnail_size_y": int(
231-
(512 / max(readout_area)) * readout_area[1]
232-
),
233222
"pixel_size": sm_pixel_size,
234223
"image": str(image_path),
235224
"binning": sm_binning,
@@ -248,7 +237,7 @@ def post_transfer(
248237
if not visitless_source:
249238
return
250239

251-
# This bit gets SearchMap location on Atlas
240+
# This bit gets SearchMap size
252241
sm_width = int(sm_data["TileSetXml"]["ImageSize"]["a:width"])
253242
sm_height = int(sm_data["TileSetXml"]["ImageSize"]["a:height"])
254243

@@ -286,8 +275,8 @@ def post_transfer(
286275
bp_url,
287276
json={
288277
"tag": visitless_source,
289-
"stage_position_x": batch_stage_location_x,
290-
"stage_position_y": batch_stage_location_y,
278+
"x_stage_position": batch_stage_location_x,
279+
"y_stage_position": batch_stage_location_y,
291280
"search_map": search_map_name,
292281
},
293282
)
@@ -309,8 +298,8 @@ def post_transfer(
309298
bp_url,
310299
json={
311300
"tag": visitless_source,
312-
"stage_position_x": beamshift_position_x,
313-
"stage_position_y": beamshift_position_y,
301+
"x_stage_position": beamshift_position_x,
302+
"y_stage_position": beamshift_position_y,
314303
"search_map": search_map_name,
315304
},
316305
)

src/murfey/server/api/session_control.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,18 @@
4646
Session,
4747
)
4848
from murfey.util.models import (
49+
BatchPositionParameters,
4950
ClientInfo,
5051
FoilHoleParameters,
5152
GridSquareParameters,
5253
RsyncerInfo,
54+
SearchMapParameters,
5355
Visit,
5456
)
57+
from murfey.util.tomo_metadata import (
58+
register_batch_position_in_database,
59+
register_search_map_in_database,
60+
)
5561
from murfey.workflows.spa.flush_spa_preprocess import (
5662
register_foil_hole as _register_foil_hole,
5763
)
@@ -364,6 +370,33 @@ def register_foil_hole(
364370
return _register_foil_hole(session_id, gs_name, foil_hole_params, db)
365371

366372

373+
tomography_router = APIRouter(
374+
prefix="/session_control/tomography",
375+
dependencies=[Depends(validate_instrument_token)],
376+
tags=["Session Control: Tomography"],
377+
)
378+
379+
380+
@tomography_router.post("/sessions/{session_id}/search_map/{sm_name}")
381+
def register_search_map(
382+
session_id: MurfeySessionID,
383+
sm_name: str,
384+
search_map_params: SearchMapParameters,
385+
db=murfey_db,
386+
):
387+
return register_search_map_in_database(session_id, sm_name, search_map_params, db)
388+
389+
390+
@tomography_router.post("/sessions/{session_id}/batch_position/{batch_name}")
391+
def register_batch_position(
392+
session_id: MurfeySessionID,
393+
batch_name: str,
394+
batch_params: BatchPositionParameters,
395+
db=murfey_db,
396+
):
397+
return register_batch_position_in_database(session_id, batch_name, batch_params, db)
398+
399+
367400
correlative_router = APIRouter(
368401
prefix="/session_control/correlative",
369402
dependencies=[Depends(validate_instrument_token)],

src/murfey/server/api/workflow.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ class DCGroupParameters(BaseModel):
8181
tag: str
8282
atlas: str = ""
8383
sample: Optional[int] = None
84-
atlas_pixel_size: int = 0
84+
atlas_pixel_size: float = 0
85+
atlas_size_x: int = 0
86+
atlas_size_y: int = 0
87+
atlas_binning: int = 1
8588

8689

8790
@router.post("/visits/{visit_name}/{session_id}/register_data_collection_group")
@@ -116,6 +119,9 @@ def register_dc_group(
116119
"atlas": dcg_params.atlas,
117120
"sample": dcg_params.sample,
118121
"atlas_pixel_size": dcg_params.atlas_pixel_size,
122+
"atlas_size_x": dcg_params.atlas_size_x,
123+
"atlas_size_y": dcg_params.atlas_size_y,
124+
"atlas_binning": dcg_params.atlas_binning,
119125
"dcgid": dcg_murfey[0].id,
120126
"session_id": session_id,
121127
},

src/murfey/server/ispyb.py

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232

3333
from murfey.util import sanitise
3434
from murfey.util.config import get_security_config
35-
from murfey.util.models import FoilHoleParameters, GridSquareParameters
35+
from murfey.util.models import (
36+
FoilHoleParameters,
37+
GridSquareParameters,
38+
SearchMapParameters,
39+
)
3640

3741
log = logging.getLogger("murfey.server.ispyb")
3842
security_config = get_security_config()
@@ -388,6 +392,90 @@ def do_update_foil_hole(
388392
)
389393
return {"success": False, "return_value": None}
390394

395+
def do_insert_search_map(
396+
self,
397+
atlas_id: int,
398+
search_map_parameters: SearchMapParameters,
399+
):
400+
if (
401+
search_map_parameters.pixel_size
402+
and search_map_parameters.height
403+
and search_map_parameters.height_on_atlas
404+
):
405+
search_map_parameters.pixel_size *= (
406+
search_map_parameters.height / search_map_parameters.height_on_atlas
407+
)
408+
record = GridSquare(
409+
atlasId=atlas_id,
410+
gridSquareImage=search_map_parameters.image,
411+
pixelLocationX=search_map_parameters.x_location,
412+
pixelLocationY=search_map_parameters.y_location,
413+
height=search_map_parameters.height_on_atlas,
414+
width=search_map_parameters.width_on_atlas,
415+
stageLocationX=search_map_parameters.x_stage_position,
416+
stageLocationY=search_map_parameters.y_stage_position,
417+
pixelSize=search_map_parameters.pixel_size,
418+
)
419+
try:
420+
with ISPyBSession() as db:
421+
db.add(record)
422+
db.commit()
423+
log.info(f"Created SearchMap (GridSquare) {record.gridSquareId}")
424+
return {"success": True, "return_value": record.gridSquareId}
425+
except ispyb.ISPyBException as e:
426+
log.error(
427+
"Inserting SearchMap (GridSquare) entry caused exception '%s'.",
428+
e,
429+
exc_info=True,
430+
)
431+
return {"success": False, "return_value": None}
432+
433+
def do_update_search_map(
434+
self, search_map_id, search_map_parameters: SearchMapParameters
435+
):
436+
try:
437+
with ISPyBSession() as db:
438+
grid_square = (
439+
db.query(GridSquare)
440+
.filter(GridSquare.gridSquareId == search_map_id)
441+
.one()
442+
)
443+
if (
444+
search_map_parameters.pixel_size
445+
and search_map_parameters.height
446+
and search_map_parameters.height_on_atlas
447+
):
448+
search_map_parameters.pixel_size *= (
449+
search_map_parameters.height
450+
/ search_map_parameters.height_on_atlas
451+
)
452+
if search_map_parameters.image:
453+
grid_square.gridSquareImage = search_map_parameters.image
454+
if search_map_parameters.x_location:
455+
grid_square.pixelLocationX = search_map_parameters.x_location
456+
if search_map_parameters.y_location:
457+
grid_square.pixelLocationY = search_map_parameters.y_location
458+
if search_map_parameters.height_on_atlas:
459+
grid_square.height = search_map_parameters.height_on_atlas
460+
if search_map_parameters.width_on_atlas:
461+
grid_square.width = search_map_parameters.width_on_atlas
462+
if search_map_parameters.x_stage_position:
463+
grid_square.stageLocationX = search_map_parameters.x_stage_position
464+
if search_map_parameters.y_stage_position:
465+
grid_square.stageLocationY = search_map_parameters.y_stage_position
466+
if search_map_parameters.pixel_size:
467+
grid_square.pixelSize = search_map_parameters.pixel_size
468+
db.add(grid_square)
469+
db.commit()
470+
return {"success": True, "return_value": grid_square.gridSquareId}
471+
except ispyb.ISPyBException as e:
472+
log.error(
473+
"Updating SearchMap (GridSquare) entry caused exception '%s'.",
474+
e,
475+
exc_info=True,
476+
)
477+
return {"success": False, "return_value": None}
478+
391479
def send(self, queue: str, message: dict, new_connection: bool = False):
392480
if self.transport:
393481
if not self.transport.is_connected():

src/murfey/util/db.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ class DataCollectionGroup(SQLModel, table=True): # type: ignore
372372
atlas_id: Optional[int] = None
373373
atlas_pixel_size: Optional[float] = None
374374
atlas: str = ""
375+
atlas_binning: Optional[int] = None
375376
sample: Optional[int] = None
376377
session: Optional[Session] = Relationship(back_populates="data_collection_groups")
377378
data_collections: List["DataCollection"] = Relationship(
@@ -601,6 +602,24 @@ class FoilHole(SQLModel, table=True): # type: ignore
601602
)
602603

603604

605+
class SearchMap(SQLModel, table=True): # type: ignore
606+
id: Optional[int] = Field(primary_key=True, default=None)
607+
session_id: int = Field(foreign_key="session.id")
608+
name: str
609+
tag: str
610+
x_location: Optional[float] = None
611+
y_location: Optional[float] = None
612+
x_stage_position: Optional[float] = None
613+
y_stage_position: Optional[float] = None
614+
pixel_size: Optional[float] = None
615+
image: str = ""
616+
binning: Optional[float] = None
617+
reference_matrix: Optional[dict[str, float]] = None
618+
stage_correction: Optional[dict[str, float]] = None
619+
image_shift_correction: Optional[dict[str, float]] = None
620+
session: Optional[Session] = Relationship(back_populates="grid_squares")
621+
622+
604623
class Movie(SQLModel, table=True): # type: ignore
605624
murfey_id: int = Field(primary_key=True, foreign_key="murfeyledger.id")
606625
foil_hole_id: int = Field(foreign_key="foilhole.id", nullable=True, default=None)

src/murfey/util/models.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,31 @@ class FoilHoleParameters(BaseModel):
136136
diameter: Optional[float] = None
137137

138138

139+
class SearchMapParameters:
140+
tag: str
141+
x_location: Optional[float] = None
142+
y_location: Optional[float] = None
143+
x_stage_position: Optional[float] = None
144+
y_stage_position: Optional[float] = None
145+
pixel_size: Optional[float] = None
146+
image: Optional[str] = None
147+
binning: Optional[float] = None
148+
reference_matrix: Optional[dict[str, float]] = None
149+
stage_correction: Optional[dict[str, float]] = None
150+
image_shift_correction: Optional[dict[str, float]] = None
151+
height: Optional[int] = None
152+
width: Optional[int] = None
153+
height_on_atlas: Optional[int] = None
154+
width_on_atlas: Optional[int] = None
155+
156+
157+
class BatchPositionParameters:
158+
tag: str
159+
x_stage_position: float
160+
Y_stage_position: float
161+
search_map: str
162+
163+
139164
class MultigridWatcherSetup(BaseModel):
140165
source: Path
141166
skip_existing_processing: bool = False

0 commit comments

Comments
 (0)