Skip to content

Commit ce1728f

Browse files
committed
merge in main
2 parents 72533df + b7114c6 commit ce1728f

36 files changed

+1091
-638
lines changed

.bumpclient.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tool.bumpversion]
2-
current_version = "0.14.0"
2+
current_version = "0.15.3"
33
commit = true
44
tag = false
55

.bumpversion.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tool.bumpversion]
2-
current_version = "0.14.0"
2+
current_version = "0.15.3"
33
commit = true
44
tag = true
55

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A transporter for data from Diamond eBIC microscope and detector machines onto the Diamond network.
44

5-
### Who is Murfey?
5+
## Who is Murfey?
66

77
Murfey, the package, is named after [Eliza Murfey, the inventor](https://nationalrrmuseum.org/blog/mother-of-invention-women-railroad-innovators/):
88

@@ -11,38 +11,38 @@ Murfey, the package, is named after [Eliza Murfey, the inventor](https://nationa
1111
> it was Murfey who designed the packings that would lubricate the axles with oil, aiding
1212
> in the reduction of derailments caused by seized axles and bearings.
1313
14-
### How do I set up a development environment?
14+
## How do I set up a development environment?
1515

1616
We suggest you start with your favourite virtual environment (mamba/conda/python virtualenv/...),
1717
then install using the following command.
1818

19-
#### From Git
20-
21-
```bash
19+
```text
2220
$ git clone [email protected]:DiamondLightSource/python-murfey.git
2321
$ cd python-murfey
2422
$ pip install -e .[client,server,developer]
2523
```
2624

2725
The packages included under the `[developer]` installation key contain some helpful tools to aid you with developing Murfey further:
2826

27+
- `bump-my-version` - Simplifies version control.
2928
- `ipykernel` - Enables interactive code development via Jupyter Notebooks.
3029
- `pre-commit` - Allows for the installation and running of hooks to help with linting, formatting, and type checking your code.
3130
- `pytest` - Used in conjunction with test functions to evaluate the reliability of your code.
32-
- `bump2version` - A nice little script to simplify version control.
31+
32+
Instructions for setting up the database for Murfey to register files to can be found [here](src/murfey/server/MURFEY_DB.md).
3333

3434
Finally, you may want to set up an ISPyB mock database server and a Zocalo
3535
development environment. The instructions for this are out of scope here.
3636

3737
You can then start the Murfey server with
3838

39-
```bash
39+
```text
4040
$ murfey.server
4141
```
4242

4343
and connect the client with
4444

45-
```bash
45+
```text
4646
$ murfey --server http://127.0.0.1:8000
4747
```
4848

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ requires = [
77

88
[project]
99
name = "murfey"
10-
version = "0.14.0"
10+
version = "0.15.3"
1111
description = "Client-Server architecture hauling Cryo-EM data"
1212
readme = "README.md"
1313
keywords = [
@@ -82,6 +82,7 @@ murfey = "murfey.client:run"
8282
"murfey.create_db" = "murfey.cli.create_db:run"
8383
"murfey.db_sql" = "murfey.cli.murfey_db_sql:run"
8484
"murfey.decrypt_password" = "murfey.cli.decrypt_db_password:run"
85+
"murfey.dlq_murfey" = "murfey.cli.dlq_resubmit:run"
8586
"murfey.generate_key" = "murfey.cli.generate_crypto_key:run"
8687
"murfey.generate_password" = "murfey.cli.generate_db_password:run"
8788
"murfey.instrument_server" = "murfey.instrument_server:run"
@@ -93,6 +94,8 @@ murfey = "murfey.client:run"
9394
"murfey.transfer" = "murfey.cli.transfer:run"
9495
[project.entry-points."murfey.auth.token_validation"]
9596
"password" = "murfey.server.api.auth:password_token_validation"
97+
[project.entry-points."murfey.config.extraction"]
98+
"murfey_machine" = "murfey.util.config:get_extended_machine_config"
9699
[project.entry-points."murfey.workflows"]
97100
"lif_to_stack" = "murfey.workflows.lif_to_stack:zocalo_cluster_request"
98101
"tiff_to_stack" = "murfey.workflows.tiff_to_stack:zocalo_cluster_request"

src/murfey/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from __future__ import annotations
22

3-
__version__ = "0.14.0"
4-
__supported_client_version__ = "0.14.0"
3+
__version__ = "0.15.3"
4+
__supported_client_version__ = "0.15.3"

src/murfey/cli/dlq_resubmit.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import argparse
2+
import json
3+
import subprocess
4+
from pathlib import Path
5+
6+
import requests
7+
8+
9+
def handle_failed_posts(json_folder: Path, token: str):
10+
"""Deal with any messages that have been sent as failed client posts"""
11+
for json_file in json_folder.glob("*"):
12+
with open(json_file, "r") as json_data:
13+
message = json.load(json_data)
14+
15+
if not message.get("message") or not message["message"].get("url"):
16+
print(f"{json_file} is not a failed client post")
17+
continue
18+
dest = message["message"]["url"]
19+
message_json = message["message"]["json"]
20+
21+
response = requests.post(
22+
dest, json=message_json, headers={"Authorization": f"Bearer {token}"}
23+
)
24+
if response.status_code != 200:
25+
print(f"Failed to repost {json_file}")
26+
else:
27+
print(f"Reposted {json_file}")
28+
json_file.unlink()
29+
30+
31+
def handle_dlq_messages(json_folder: Path):
32+
"""Reinjected to the queue"""
33+
for json_file in json_folder.glob("*"):
34+
reinject_result = subprocess.run(
35+
["zocalo.dlq_reinject", "-e", "devrmq", str(json_file)],
36+
capture_output=True,
37+
)
38+
if reinject_result.returncode == 0:
39+
print(f"Reinjected {json_file}")
40+
json_file.unlink()
41+
else:
42+
print(f"Failed to reinject {json_file}")
43+
44+
45+
def run():
46+
"""
47+
Method of checking and purging murfey queues on rabbitmq
48+
Two types of messages are possible:
49+
- failed client posts which need reposting to the murfey server API
50+
- feedback messages that can be sent back to rabbitmq
51+
"""
52+
parser = argparse.ArgumentParser(
53+
description="Purge and reinject failed murfey messages"
54+
)
55+
parser.add_argument(
56+
"--queue",
57+
help="Queue to check and purge",
58+
required=True,
59+
)
60+
parser.add_argument(
61+
"--token",
62+
help="Murfey token",
63+
required=True,
64+
)
65+
args = parser.parse_args()
66+
67+
purge_result = subprocess.run(
68+
["zocalo.dlq_purge", "-e", "devrmq", args.queue],
69+
capture_output=True,
70+
)
71+
if purge_result.returncode != 0:
72+
print(f"Failed to purge {args.queue}")
73+
return
74+
purge_stdout = purge_result.stdout.decode("utf8")
75+
export_directories = []
76+
if "exported" in purge_stdout:
77+
for line in purge_stdout.split("\n"):
78+
if line.strip().startswith("DLQ/"):
79+
dlq_dir = "DLQ/" + line.split("/")[1]
80+
if dlq_dir not in export_directories:
81+
print(f"Found messages in {dlq_dir}")
82+
export_directories.append(dlq_dir)
83+
84+
if not export_directories:
85+
print("No exported messages found")
86+
return
87+
88+
for json_dir in export_directories:
89+
handle_failed_posts(Path(json_dir), args.token)
90+
handle_dlq_messages(Path(json_dir))
91+
print("Done")
92+
93+
94+
if __name__ == "__main__":
95+
run()

src/murfey/cli/inject_spa_processing.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from murfey.server.ispyb import TransportManager
1212
from murfey.server.murfey_db import url
13-
from murfey.util.config import get_machine_config, get_microscope
13+
from murfey.util.config import get_machine_config, get_microscope, get_security_config
1414
from murfey.util.db import (
1515
AutoProcProgram,
1616
ClientEnvironment,
@@ -97,12 +97,13 @@ def run():
9797
os.environ["BEAMLINE"] = args.microscope
9898

9999
machine_config = get_machine_config()
100+
security_config = get_security_config()
100101
_url = url(machine_config)
101102
engine = create_engine(_url)
102103
murfey_db = Session(engine)
103104

104105
_transport_object = TransportManager(args.transport)
105-
_transport_object.feedback_queue = machine_config.feedback_queue
106+
_transport_object.feedback_queue = security_config.feedback_queue
106107

107108
query = (
108109
select(Movie)
@@ -182,7 +183,7 @@ def run():
182183
zocalo_message = {
183184
"recipes": ["em-spa-preprocess"],
184185
"parameters": {
185-
"feedback_queue": machine_config.feedback_queue,
186+
"feedback_queue": _transport_object.feedback_queue,
186187
"node_creator_queue": machine_config.node_creator_queue,
187188
"dcid": detached_ids[1],
188189
"kv": proc_params["voltage"],

src/murfey/cli/spa_ispyb_messages.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from murfey.server.ispyb import Session, TransportManager, get_session_id
2323
from murfey.server.murfey_db import url
2424
from murfey.util import db
25-
from murfey.util.config import get_machine_config, get_microscope
25+
from murfey.util.config import get_machine_config, get_microscope, get_security_config
2626

2727

2828
def run():
@@ -341,6 +341,7 @@ def run():
341341
.where(db.ProcessingJob.recipe == "em-spa-preprocess")
342342
).one()
343343
machine_config = get_machine_config()
344+
security_config = get_security_config()
344345
params = db.SPARelionParameters(
345346
pj_id=collected_ids[2].id,
346347
angpix=float(metadata["pixel_size_on_image"]) * 1e10,
@@ -377,7 +378,7 @@ def run():
377378

378379
if args.flush_preprocess:
379380
_transport_object = TransportManager(args.transport)
380-
_transport_object.feedback_queue = machine_config.feedback_queue
381+
_transport_object.feedback_queue = security_config.feedback_queue
381382
stashed_files = murfey_db.exec(
382383
select(db.PreprocessStash)
383384
.where(db.PreprocessStash.session_id == args.session_id)
@@ -407,7 +408,7 @@ def run():
407408
zocalo_message = {
408409
"recipes": ["em-spa-preprocess"],
409410
"parameters": {
410-
"feedback_queue": machine_config.feedback_queue,
411+
"feedback_queue": _transport_object.feedback_queue,
411412
"dcid": collected_ids[1].id,
412413
"kv": metadata["voltage"],
413414
"autoproc_program_id": collected_ids[3].id,

src/murfey/client/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,9 @@ def run():
288288

289289
status_bar = StatusBar()
290290

291-
machine_data = requests.get(f"{murfey_url.geturl()}/machine").json()
291+
machine_data = requests.get(
292+
f"{murfey_url.geturl()}/instruments/{instrument_name}/machine"
293+
).json()
292294
gain_ref: Path | None = None
293295

294296
instance_environment = MurfeyInstanceEnvironment(

src/murfey/client/analyser.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from murfey.client.instance_environment import MurfeyInstanceEnvironment
2323
from murfey.client.rsync import RSyncerUpdate, TransferResult
2424
from murfey.client.tui.forms import FormDependency
25-
from murfey.util import Observer, get_machine_config
25+
from murfey.util import Observer, get_machine_config_client
2626
from murfey.util.models import PreprocessingParametersTomo, ProcessingParametersSPA
2727

2828
logger = logging.getLogger("murfey.client.analyser")
@@ -73,7 +73,7 @@ def __init__(
7373
self._stopping = False
7474
self._halt_thread = False
7575
self._murfey_config = (
76-
get_machine_config(
76+
get_machine_config_client(
7777
str(environment.url.geturl()),
7878
instrument_name=environment.instrument_name,
7979
demo=environment.demo,
@@ -86,6 +86,10 @@ def _find_extension(self, file_path: Path):
8686
"""
8787
Identifies the file extension and stores that information in the class.
8888
"""
89+
if "atlas" in file_path.parts:
90+
self._extension = file_path.suffix
91+
return True
92+
8993
if (
9094
required_substrings := self._murfey_config.get(
9195
"data_required_substrings", {}
@@ -121,6 +125,10 @@ def _find_context(self, file_path: Path) -> bool:
121125
stages of processing. Actions to take for individual files will be determined
122126
in the Context classes themselves.
123127
"""
128+
if "atlas" in file_path.parts:
129+
self._role = "detector"
130+
self._context = SPAMetadataContext("epu", self._basepath)
131+
return True
124132

125133
# CLEM workflow checks
126134
# Look for LIF and XLIF files
@@ -137,7 +145,7 @@ def _find_context(self, file_path: Path) -> bool:
137145
and self._environment
138146
):
139147
created_directories = set(
140-
get_machine_config(
148+
get_machine_config_client(
141149
str(self._environment.url.geturl()),
142150
instrument_name=self._environment.instrument_name,
143151
demo=self._environment.demo,
@@ -157,7 +165,7 @@ def _find_context(self, file_path: Path) -> bool:
157165
logger.info("Acquisition software: EPU")
158166
if self._environment:
159167
try:
160-
cfg = get_machine_config(
168+
cfg = get_machine_config_client(
161169
str(self._environment.url.geturl()),
162170
instrument_name=self._environment.instrument_name,
163171
demo=self._environment.demo,
@@ -310,7 +318,10 @@ def _analyse(self):
310318
)
311319
except Exception as e:
312320
logger.error(f"Exception encountered: {e}")
313-
if self._role == "detector":
321+
if (
322+
self._role == "detector"
323+
and "atlas" not in transferred_file.parts
324+
):
314325
if not dc_metadata:
315326
try:
316327
dc_metadata = self._context.gather_metadata(
@@ -376,7 +387,10 @@ def _analyse(self):
376387
)
377388
except Exception as e:
378389
logger.error(f"Exception encountered: {e}")
379-
if self._role == "detector":
390+
if (
391+
self._role == "detector"
392+
and "atlas" not in transferred_file.parts
393+
):
380394
if not dc_metadata:
381395
try:
382396
dc_metadata = self._context.gather_metadata(

0 commit comments

Comments
 (0)