Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b3464bb
Create additional fluorescent-only and bright field-only composite im…
tieneupin Oct 29, 2025
8641d38
Import Murfey database classes differently, to eventually differentia…
tieneupin Oct 29, 2025
f511242
'slot' should be optional
tieneupin Oct 31, 2025
c5aca0c
Updated Murfey database to integrate CLEM workflow with ISPyB
tieneupin Oct 31, 2025
c6fea87
Removed registration of composite image file path from 'register_alig…
tieneupin Oct 31, 2025
09190be
Stored tag/name of data collection group in CLEMImageSeries table as …
tieneupin Oct 31, 2025
edba7eb
Added logic to create data collection group and atlas table entries f…
tieneupin Oct 31, 2025
6fa10e3
Revert to using older annotated types
tieneupin Oct 31, 2025
1b007fa
Added more database columns to 'CLEMImageSeries' table to keep track …
tieneupin Nov 4, 2025
2387cdd
Broke 'register_preprocessing_results' workflow down into smaller fun…
tieneupin Nov 4, 2025
836e016
Added new optional fields into 'GridSquareParameters' table to stored…
tieneupin Nov 4, 2025
0d88293
Migrated logic for rescaling grid square values into the 'flush_spa_p…
tieneupin Nov 4, 2025
d7b33f3
Return failure result if unable to load Murfey session information
tieneupin Nov 4, 2025
41f533a
Added logic to register non-atlas CLEM image series as grid squares
tieneupin Nov 5, 2025
1cfb006
Included calculation of image dimensions (in pixels) as displayed on …
tieneupin Nov 5, 2025
7967068
Added placeholders for the unit tests to register CLEM preprocessing …
tieneupin Nov 5, 2025
4038cda
Added unit test for 'run' main function in 'register_preprocessing_re…
tieneupin Nov 5, 2025
72b2b1f
Test workflow with actual Murfey and ISPyB databases
tieneupin Nov 6, 2025
df1f732
Pass messages to test in reverse order as well
tieneupin Nov 6, 2025
406d510
More thorough test to verify that the database insertions on both Mur…
tieneupin Nov 6, 2025
3abe4f6
Fixed bug with grid square registration not running if the CLEM atlas…
tieneupin Nov 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 20 additions & 36 deletions src/murfey/server/ispyb.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ def do_insert_atlas(self, record: Atlas):
return {"success": False, "return_value": None}

def do_update_atlas(
self, atlas_id: int, atlas_image: str, pixel_size: float, slot: int
self,
atlas_id: int,
atlas_image: str,
pixel_size: float,
slot: int | None,
):
try:
with ISPyBSession() as db:
Expand Down Expand Up @@ -190,34 +194,14 @@ def do_insert_grid_square(
grid_square_parameters.readout_area_x
/ grid_square_parameters.thumbnail_size_x
)
grid_square_parameters.height = (
int(grid_square_parameters.height / 7.8)
if grid_square_parameters.height
else None
)
grid_square_parameters.width = (
int(grid_square_parameters.width / 7.8)
if grid_square_parameters.width
else None
)
grid_square_parameters.x_location = (
int(grid_square_parameters.x_location / 7.8)
if grid_square_parameters.x_location
else None
)
grid_square_parameters.y_location = (
int(grid_square_parameters.y_location / 7.8)
if grid_square_parameters.y_location
else None
)
record = GridSquare(
atlasId=atlas_id,
gridSquareLabel=grid_square_id,
gridSquareImage=grid_square_parameters.image,
pixelLocationX=grid_square_parameters.x_location,
pixelLocationY=grid_square_parameters.y_location,
height=grid_square_parameters.height,
width=grid_square_parameters.width,
pixelLocationX=grid_square_parameters.x_location_scaled,
pixelLocationY=grid_square_parameters.y_location_scaled,
height=grid_square_parameters.height_scaled,
width=grid_square_parameters.width_scaled,
angle=grid_square_parameters.angle,
stageLocationX=grid_square_parameters.x_stage_position,
stageLocationY=grid_square_parameters.y_stage_position,
Expand All @@ -242,7 +226,7 @@ def do_update_grid_square(
):
try:
with ISPyBSession() as db:
grid_square = (
grid_square: GridSquare = (
db.query(GridSquare)
.filter(GridSquare.gridSquareId == grid_square_id)
.one()
Expand All @@ -258,18 +242,18 @@ def do_update_grid_square(
)
if grid_square_parameters.image:
grid_square.gridSquareImage = grid_square_parameters.image
if grid_square_parameters.x_location:
grid_square.pixelLocationX = int(
grid_square_parameters.x_location / 7.8
if grid_square_parameters.x_location_scaled:
grid_square.pixelLocationX = (
grid_square_parameters.x_location_scaled
)
if grid_square_parameters.y_location:
grid_square.pixelLocationY = int(
grid_square_parameters.y_location / 7.8
if grid_square_parameters.y_location_scaled:
grid_square.pixelLocationY = (
grid_square_parameters.y_location_scaled
)
if grid_square_parameters.height is not None:
grid_square.height = int(grid_square_parameters.height / 7.8)
if grid_square_parameters.width is not None:
grid_square.width = int(grid_square_parameters.width / 7.8)
if grid_square_parameters.height_scaled is not None:
grid_square.height = grid_square_parameters.height_scaled
if grid_square_parameters.width_scaled is not None:
grid_square.width = grid_square_parameters.width_scaled
if grid_square_parameters.angle:
grid_square.angle = grid_square_parameters.angle
if grid_square_parameters.x_stage_position:
Expand Down
47 changes: 40 additions & 7 deletions src/murfey/util/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class CLEMImageMetadata(SQLModel, table=True): # type: ignore

class CLEMImageSeries(SQLModel, table=True): # type: ignore
"""
Database recording the individual files associated with a series, which are to be
Database recording the files and metadata associated with a series, which are to be
processed together as a group. These files could stem from a parent LIF file, or
have been compiled together from individual TIFF files.
"""
Expand All @@ -239,6 +239,7 @@ class CLEMImageSeries(SQLModel, table=True): # type: ignore
series_name: str = Field(
index=True
) # Name of the series, as determined from the metadata
search_string: Optional[str] = Field(default=None) # Path for globbing with

session: Optional["Session"] = Relationship(
back_populates="image_series"
Expand All @@ -247,6 +248,22 @@ class CLEMImageSeries(SQLModel, table=True): # type: ignore
foreign_key="session.id", default=None, unique=False
)

# Type of data (atlas/overview or grid square)
data_type: Optional[str] = Field(default=None) # "atlas" or "grid_square"

# Link to data collection group
data_collection_group: Optional["DataCollectionGroup"] = Relationship(
back_populates="clem_image_series"
)
dcg_id: Optional[int] = Field(foreign_key="datacollectiongroup.id", default=None)
dcg_name: Optional[str] = Field(default=None)

# Link to grid squares
grid_square: Optional["GridSquare"] = Relationship(
back_populates="clem_image_series"
)
grid_square_id: Optional[int] = Field(foreign_key="gridsquare.id", default=None)

# The parent LIF file this series originates from, if any
parent_lif: Optional["CLEMLIFFile"] = Relationship(
back_populates="child_series",
Expand All @@ -270,18 +287,27 @@ class CLEMImageSeries(SQLModel, table=True): # type: ignore
default=None,
)

# Databases of the image stacks that comprise this series
# Image stack entries that are part of this series
child_stacks: List["CLEMImageStack"] = Relationship(
back_populates="parent_series",
sa_relationship_kwargs={"cascade": "delete"},
) # One to many
number_of_members: Optional[int] = Field(default=None)

# Process checklist for series
number_of_members: int = (
0 # Expected number of image stacks belonging to this series
)
# Shape and resolution information
pixels_x: Optional[int] = Field(default=None)
pixels_y: Optional[int] = Field(default=None)
pixel_size: Optional[float] = Field(default=None)
units: Optional[str] = Field(default=None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the units in the database? I can't see they are used anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a valid point. I included it as a just-in-case, so I'll revisit this in the future if no new workflows end up using this column.


# Extent of the imaged area in real space
x0: Optional[float] = Field(default=None)
x1: Optional[float] = Field(default=None)
y0: Optional[float] = Field(default=None)
y1: Optional[float] = Field(default=None)

# Composite images
composite_created: bool = False # Has a composite image been created?
composite_image: Optional[str] = None # Full path to composite image


class CLEMImageStack(SQLModel, table=True): # type: ignore
Expand Down Expand Up @@ -389,6 +415,10 @@ class DataCollectionGroup(SQLModel, table=True): # type: ignore
back_populates="data_collection_group",
sa_relationship_kwargs={"cascade": "delete"},
)
clem_image_series: List["CLEMImageSeries"] = Relationship(
back_populates="data_collection_group",
sa_relationship_kwargs={"cascade": "delete"},
)
notification_parameters: List["NotificationParameter"] = Relationship(
back_populates="data_collection_group",
sa_relationship_kwargs={"cascade": "delete"},
Expand Down Expand Up @@ -591,6 +621,9 @@ class GridSquare(SQLModel, table=True): # type: ignore
pixel_size: Optional[float] = None
image: str = ""
session: Optional[Session] = Relationship(back_populates="grid_squares")
clem_image_series: List["CLEMImageSeries"] = Relationship(
back_populates="grid_square", sa_relationship_kwargs={"cascade": "delete"}
)
foil_holes: List["FoilHole"] = Relationship(
back_populates="grid_square", sa_relationship_kwargs={"cascade": "delete"}
)
Expand Down
4 changes: 4 additions & 0 deletions src/murfey/util/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,19 @@ class Base(BaseModel):
class GridSquareParameters(BaseModel):
tag: str
x_location: Optional[float] = None
x_location_scaled: Optional[int] = None
y_location: Optional[float] = None
y_location_scaled: Optional[int] = None
x_stage_position: Optional[float] = None
y_stage_position: Optional[float] = None
readout_area_x: Optional[int] = None
readout_area_y: Optional[int] = None
thumbnail_size_x: Optional[int] = None
thumbnail_size_y: Optional[int] = None
height: Optional[int] = None
height_scaled: Optional[int] = None
width: Optional[int] = None
width_scaled: Optional[int] = None
pixel_size: Optional[float] = None
image: str = ""
angle: Optional[float] = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ def register_align_and_merge_result(
session_id=session_id,
series_name=result.series_name,
)
clem_img_series.composite_image = str(result.composite_image)
clem_img_series.composite_created = True
murfey_db.add(clem_img_series)
murfey_db.commit()
Expand Down
Loading