Skip to content

Commit c221083

Browse files
Add soft x-ray tomography (#759)
Adds a context file for SXT data collection, triggered if txrm or xrm files are seen. This will register data collection groups, data collections, processing jobs and autoprocprograms for txrm files. When a txrm file is seen the metadata is read from the header and processing is launched with a newly defined recipe "sxt-tomo-align" Requires a new experiment type in ispyb to be made (currently assumed to be 47)
1 parent 5781360 commit c221083

17 files changed

Lines changed: 693 additions & 49 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
- name: Install Murfey
7878
run: |
7979
set -eux
80-
pip install --disable-pip-version-check -e "."[cicd,server,developer]
80+
pip install --disable-pip-version-check -e "."[cicd,server,developer,sxt]
8181
8282
- uses: shogo82148/actions-setup-mysql@v1
8383
with:

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ server = [
7171
smartem = [
7272
"smartem-decisions[backend]",
7373
]
74+
sxt = [
75+
"txrm2tiff",
76+
]
7477
[project.urls]
7578
Bug-Tracker = "https://github.com/DiamondLightSource/python-murfey/issues"
7679
Documentation = "https://github.com/DiamondLightSource/python-murfey"

src/murfey/client/analyser.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from murfey.client.contexts.fib import FIBContext
2121
from murfey.client.contexts.spa import SPAModularContext
2222
from murfey.client.contexts.spa_metadata import SPAMetadataContext
23+
from murfey.client.contexts.sxt import SXTContext
2324
from murfey.client.contexts.tomo import TomographyContext
2425
from murfey.client.contexts.tomo_metadata import TomographyMetadataContext
2526
from murfey.client.destinations import find_longest_data_directory
@@ -111,8 +112,12 @@ def _find_extension(self, file_path: Path) -> bool:
111112
if subframe_path := mdoc_data_block.get("SubFramePath"):
112113
self._extension = Path(subframe_path).suffix
113114
return True
114-
# Check for LIF files separately
115-
elif file_path.suffix == ".lif":
115+
# Check for LIF files and TXRM files separately
116+
elif (
117+
file_path.suffix == ".lif"
118+
or file_path.suffix == ".txrm"
119+
or file_path.suffix == ".xrm"
120+
):
116121
self._extension = file_path.suffix
117122
return True
118123
return False
@@ -179,6 +184,13 @@ def _find_context(self, file_path: Path) -> bool:
179184
self._context = FIBContext("meteor", self._basepath, self._token)
180185
return True
181186

187+
# -----------------------------------------------------------------------------
188+
# SXT workflow checks
189+
# -----------------------------------------------------------------------------
190+
if file_path.suffix in (".txrm", ".xrm"):
191+
self._context = SXTContext("zeiss", self._basepath, self._token)
192+
return True
193+
182194
# -----------------------------------------------------------------------------
183195
# Tomography and SPA workflow checks
184196
# -----------------------------------------------------------------------------
@@ -370,6 +382,10 @@ def _analyse(self):
370382
)
371383
self.post_transfer(transferred_file)
372384

385+
elif isinstance(self._context, SXTContext):
386+
logger.debug(f"File {transferred_file.name!r} is an SXT file")
387+
self.post_transfer(transferred_file)
388+
373389
elif isinstance(self._context, AtlasContext):
374390
logger.debug(f"File {transferred_file.name!r} is part of the atlas")
375391
self.post_transfer(transferred_file)

src/murfey/client/context.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,44 @@
1313
logger = logging.getLogger("murfey.client.context")
1414

1515

16+
def _file_transferred_to(
17+
environment: MurfeyInstanceEnvironment, source: Path, file_path: Path, token: str
18+
):
19+
machine_config = get_machine_config_client(
20+
str(environment.url.geturl()),
21+
token,
22+
instrument_name=environment.instrument_name,
23+
)
24+
if environment.visit in environment.default_destinations[source]:
25+
return (
26+
Path(machine_config.get("rsync_basepath", ""))
27+
/ Path(environment.default_destinations[source])
28+
/ file_path.relative_to(source) # need to strip out the rsync_module name
29+
)
30+
return (
31+
Path(machine_config.get("rsync_basepath", ""))
32+
/ Path(environment.default_destinations[source])
33+
/ environment.visit
34+
/ file_path.relative_to(source)
35+
)
36+
37+
38+
def _get_source(file_path: Path, environment: MurfeyInstanceEnvironment) -> Path | None:
39+
possible_sources = []
40+
for s in environment.sources:
41+
if file_path.is_relative_to(s):
42+
possible_sources.append(s)
43+
if not possible_sources:
44+
return None
45+
elif len(possible_sources) == 1:
46+
return possible_sources[0]
47+
source = possible_sources[0]
48+
for extra_source in possible_sources[1:]:
49+
if extra_source.is_relative_to(source):
50+
source = extra_source
51+
return source
52+
53+
1654
def _atlas_destination(
1755
environment: MurfeyInstanceEnvironment, source: Path, token: str
1856
) -> Path:
@@ -61,6 +99,10 @@ def ensure_dcg_exists(
6199
)
62100
except Exception as e:
63101
logger.warning(f"Get EPU session hook failed: {e}")
102+
elif collection_type == "sxt":
103+
experiment_type_id = 47
104+
session_file = metadata_source / "Session.dm"
105+
source_visit_dir = metadata_source.parent
64106
else:
65107
logger.error(f"Unknown collection type {collection_type}")
66108
return None

src/murfey/client/contexts/atlas.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
import xmltodict
66

7-
from murfey.client.context import Context, _atlas_destination
8-
from murfey.client.contexts.spa import _get_source
7+
from murfey.client.context import Context, _atlas_destination, _get_source
98
from murfey.client.instance_environment import MurfeyInstanceEnvironment
109
from murfey.util.client import capture_post
1110

src/murfey/client/contexts/spa.py

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77

88
import xmltodict
99

10-
from murfey.client.context import Context, ProcessingParameter
10+
from murfey.client.context import (
11+
Context,
12+
ProcessingParameter,
13+
_file_transferred_to,
14+
_get_source,
15+
)
1116
from murfey.client.destinations import find_longest_data_directory
1217
from murfey.client.instance_environment import (
1318
MovieTracker,
@@ -26,28 +31,6 @@
2631
logger = logging.getLogger("murfey.client.contexts.spa")
2732

2833

29-
def _file_transferred_to(
30-
environment: MurfeyInstanceEnvironment, source: Path, file_path: Path, token: str
31-
):
32-
machine_config = get_machine_config_client(
33-
str(environment.url.geturl()),
34-
token,
35-
instrument_name=environment.instrument_name,
36-
)
37-
if environment.visit in environment.default_destinations[source]:
38-
return (
39-
Path(machine_config.get("rsync_basepath", ""))
40-
/ Path(environment.default_destinations[source])
41-
/ file_path.relative_to(source) # need to strip out the rsync_module name
42-
)
43-
return (
44-
Path(machine_config.get("rsync_basepath", ""))
45-
/ Path(environment.default_destinations[source])
46-
/ environment.visit
47-
/ file_path.relative_to(source)
48-
)
49-
50-
5134
def _grid_square_metadata_file(
5235
f: Path, data_directories: list[Path], visit: str, grid_square: int
5336
) -> Path:
@@ -66,22 +49,6 @@ def _grid_square_metadata_file(
6649
return metadata_file
6750

6851

69-
def _get_source(file_path: Path, environment: MurfeyInstanceEnvironment) -> Path | None:
70-
possible_sources = []
71-
for s in environment.sources:
72-
if file_path.is_relative_to(s):
73-
possible_sources.append(s)
74-
if not possible_sources:
75-
return None
76-
elif len(possible_sources) == 1:
77-
return possible_sources[0]
78-
source = possible_sources[0]
79-
for extra_source in possible_sources[1:]:
80-
if extra_source.is_relative_to(source):
81-
source = extra_source
82-
return source
83-
84-
8552
def _get_xml_list_index(key: str, xml_list: list) -> int:
8653
for i, elem in enumerate(xml_list):
8754
if elem["a:Key"] == key:

src/murfey/client/contexts/spa_metadata.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44

55
import xmltodict
66

7-
from murfey.client.context import Context, ensure_dcg_exists
8-
from murfey.client.contexts.spa import _file_transferred_to, _get_source
7+
from murfey.client.context import (
8+
Context,
9+
_file_transferred_to,
10+
_get_source,
11+
ensure_dcg_exists,
12+
)
913
from murfey.client.instance_environment import MurfeyInstanceEnvironment
1014
from murfey.util.client import capture_post
1115
from murfey.util.spa_metadata import (

0 commit comments

Comments
 (0)