random offset control added to gui, and json file writing
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import builtins
|
||||
import datetime
|
||||
import fcntl
|
||||
import json
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
@@ -28,9 +29,12 @@ if builtins.__dict__.get("bec") is not None:
|
||||
|
||||
def umv(*args):
|
||||
return scans.umv(*args, relative=False)
|
||||
|
||||
|
||||
def umvr(*args):
|
||||
return scans.umv(*args, relative=True)
|
||||
|
||||
|
||||
class OMNYToolsError(Exception):
|
||||
pass
|
||||
|
||||
@@ -157,8 +161,10 @@ class OMNYTools:
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_term)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags)
|
||||
|
||||
|
||||
import socket
|
||||
|
||||
|
||||
class PtychoReconstructor:
|
||||
"""Writes ptychography reconstruction queue files after each scan projection.
|
||||
|
||||
@@ -195,6 +201,8 @@ class PtychoReconstructor:
|
||||
next_scan_number: int,
|
||||
base_path: str = "~/data/raw/analysis/",
|
||||
probe_file_propagation: float | None = None,
|
||||
random_offset_x: float | None = None,
|
||||
random_offset_y: float | None = None,
|
||||
):
|
||||
"""Write a reconstruction queue file for the given scan list.
|
||||
|
||||
@@ -211,19 +219,25 @@ class PtychoReconstructor:
|
||||
omitted entirely otherwise, matching the old reconstruction.mac
|
||||
behavior of only writing this parameter when
|
||||
progagateprobeinsteadofsample==1.
|
||||
random_offset_x (float, optional): Random x shift [um] applied for
|
||||
this single-point acquisition. Written to the JSON sidecar as
|
||||
``random_offset_x`` when given; omitted otherwise.
|
||||
random_offset_y (float, optional): Random y shift [um] applied for
|
||||
this single-point acquisition. Written to the JSON sidecar as
|
||||
``random_offset_y`` when given; omitted otherwise.
|
||||
"""
|
||||
if not self._accounts_match():
|
||||
logger.warning("Active BEC account does not match system user — skipping queue file write.")
|
||||
logger.warning(
|
||||
"Active BEC account does not match system user — skipping queue file write."
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
base_path = os.path.expanduser(base_path)
|
||||
queue_path = Path(os.path.join(base_path, self.folder_name))
|
||||
queue_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
last_scan_number = next_scan_number - 1
|
||||
queue_file = os.path.abspath(
|
||||
os.path.join(queue_path, f"scan_{last_scan_number:05d}.dat")
|
||||
)
|
||||
queue_file = os.path.abspath(os.path.join(queue_path, f"scan_{last_scan_number:05d}.dat"))
|
||||
with open(queue_file, "w") as f:
|
||||
scans = " ".join(str(s) for s in scan_list)
|
||||
f.write(f"p.scan_number {scans}\n")
|
||||
@@ -231,6 +245,17 @@ class PtychoReconstructor:
|
||||
f.write(f"p.probe_file_propagation {probe_file_propagation:.6f}\n")
|
||||
f.write("p.check_nextscan_started 1\n")
|
||||
|
||||
json_file = os.path.abspath(os.path.join(queue_path, f"{last_scan_number:06d}.json"))
|
||||
json_content = {"scan_id": last_scan_number}
|
||||
if probe_file_propagation is not None:
|
||||
json_content["probe_file_propagation"] = round(probe_file_propagation, 6)
|
||||
if random_offset_x is not None:
|
||||
json_content["random_offset_x"] = round(random_offset_x, 6)
|
||||
if random_offset_y is not None:
|
||||
json_content["random_offset_y"] = round(random_offset_y, 6)
|
||||
with open(json_file, "w") as f:
|
||||
json.dump(json_content, f, indent=4)
|
||||
|
||||
|
||||
class TomoIDManager:
|
||||
"""Registers a tomography measurement in the OMNY sample database
|
||||
@@ -249,7 +274,7 @@ class TomoIDManager:
|
||||
)
|
||||
"""
|
||||
|
||||
#OMNY_URL = "https://omny.web.psi.ch/samples/newmeasurement.php"
|
||||
# OMNY_URL = "https://omny.web.psi.ch/samples/newmeasurement.php"
|
||||
OMNY_URL = "https://v1p0zyg2w9n2k9c1.myfritz.net/samples/newmeasurement.php"
|
||||
OMNY_USER = ""
|
||||
OMNY_PASSWORD = ""
|
||||
@@ -294,12 +319,9 @@ class TomoIDManager:
|
||||
# f" -q -O {self.TMP_FILE} '{url}'",
|
||||
# shell=True,
|
||||
# )
|
||||
#print(url)
|
||||
# print(url)
|
||||
tmp_file = os.path.expanduser(self.TMP_FILE)
|
||||
result = subprocess.run(
|
||||
f"wget -q -O {tmp_file} '{url}'",
|
||||
shell=True,
|
||||
)
|
||||
result = subprocess.run(f"wget -q -O {tmp_file} '{url}'", shell=True)
|
||||
if result.returncode != 0:
|
||||
raise OMNYToolsError(
|
||||
f"wget failed (exit code {result.returncode}) fetching tomo ID from {self.OMNY_URL}"
|
||||
@@ -313,4 +335,4 @@ class TomoIDManager:
|
||||
except ValueError as exc:
|
||||
raise OMNYToolsError(
|
||||
f"Unexpected response from tomo ID server, got: {content!r}"
|
||||
) from exc
|
||||
) from exc
|
||||
@@ -104,6 +104,7 @@ QUEUE_PARAM_NAMES = (
|
||||
"manual_shift_y",
|
||||
"frames_per_trigger",
|
||||
"single_point_instead_of_fermat_scan",
|
||||
"single_point_random_shift_max",
|
||||
"tomo_type",
|
||||
"tomo_angle_range",
|
||||
"tomo_angle_stepsize",
|
||||
@@ -126,6 +127,7 @@ DEFAULTS: dict[str, Any] = {
|
||||
"manual_shift_y": 0.0,
|
||||
"frames_per_trigger": 1,
|
||||
"single_point_instead_of_fermat_scan": False,
|
||||
"single_point_random_shift_max": 0.0,
|
||||
"tomo_type": 1,
|
||||
"corridor_size": -1.0,
|
||||
"tomo_angle_range": 180,
|
||||
@@ -364,6 +366,14 @@ class TomoParamsWidget(BECWidget, QWidget):
|
||||
self._add_int(common_form, "frames_per_trigger", "Frames / trigger", min_=1, max_=100)
|
||||
sp = self._add_bool(common_form, "single_point_instead_of_fermat_scan", "Single-point scan")
|
||||
sp.stateChanged.connect(self._on_single_point_changed)
|
||||
self._add_double(
|
||||
common_form,
|
||||
"single_point_random_shift_max",
|
||||
"Random shift max (µm)",
|
||||
min_=0.0,
|
||||
max_=10.0,
|
||||
decimals=3,
|
||||
)
|
||||
vbox.addLayout(common_form)
|
||||
|
||||
# type-1 section
|
||||
@@ -590,6 +600,9 @@ class TomoParamsWidget(BECWidget, QWidget):
|
||||
return "tomo_type must be 1, 2, or 3"
|
||||
if params.get("tomo_angle_range") not in (180, 360):
|
||||
return "tomo_angle_range must be 180 or 360"
|
||||
rshift = params.get("single_point_random_shift_max", 0.0)
|
||||
if not 0 <= rshift <= 10:
|
||||
return "single_point_random_shift_max must be between 0 and 10 µm"
|
||||
return None
|
||||
|
||||
# ── type visibility ───────────────────────────────────────────────────────
|
||||
@@ -659,6 +672,8 @@ class TomoParamsWidget(BECWidget, QWidget):
|
||||
self._pw["stitch_y"].setValue(0)
|
||||
self._pw["stitch_x"].setEnabled(self._edit_mode and not checked)
|
||||
self._pw["stitch_y"].setEnabled(self._edit_mode and not checked)
|
||||
# random shift only applies to single-point acquisitions
|
||||
self._pw["single_point_random_shift_max"].setEnabled(self._edit_mode and checked)
|
||||
|
||||
def _on_poll(self) -> None:
|
||||
"""Periodic refresh: params (guarded against edit mode) + sample name."""
|
||||
@@ -882,10 +897,13 @@ class TomoParamsWidget(BECWidget, QWidget):
|
||||
if key in skip:
|
||||
continue
|
||||
widget.setEnabled(enabled)
|
||||
# stitch locked when single_point is active
|
||||
if enabled and self._pw["single_point_instead_of_fermat_scan"].isChecked():
|
||||
# stitch locked when single_point is active; random shift is the
|
||||
# inverse -- only editable while single_point is active
|
||||
single_point = self._pw["single_point_instead_of_fermat_scan"].isChecked()
|
||||
if enabled and single_point:
|
||||
self._pw["stitch_x"].setEnabled(False)
|
||||
self._pw["stitch_y"].setEnabled(False)
|
||||
self._pw["single_point_random_shift_max"].setEnabled(enabled and single_point)
|
||||
# projection requested total only meaningful in edit mode
|
||||
self._pw["_requested_total"].setEnabled(enabled)
|
||||
|
||||
@@ -981,16 +999,7 @@ class TomoQueueDialog(QDialog):
|
||||
|
||||
self._table = QTableWidget(0, 8)
|
||||
self._table.setHorizontalHeaderLabels(
|
||||
[
|
||||
"#",
|
||||
"Label",
|
||||
"Status",
|
||||
"Type",
|
||||
"Projections",
|
||||
"Exp (s)",
|
||||
"Step (µm)",
|
||||
"Added at",
|
||||
]
|
||||
["#", "Label", "Status", "Type", "Projections", "Exp (s)", "Step (µm)", "Added at"]
|
||||
)
|
||||
self._table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
|
||||
self._table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
|
||||
|
||||
Reference in New Issue
Block a user