Skip to content

Commit af1c88e

Browse files
Merge pull request #958 from TheDeanLab/pr956-update-from-develop
Pr956 update from develop
2 parents 2637689 + d02d3a1 commit af1c88e

File tree

8 files changed

+77
-38
lines changed

8 files changed

+77
-38
lines changed

src/navigate/config/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ def verify_experiment_config(manager, configuration):
341341
"celltype": "MV3",
342342
"label": "GFP",
343343
"file_type": "TIFF",
344+
"prefix": "Cell_",
344345
"date": time.strftime("%Y-%m-%d"),
345346
"solvent": "BABB",
346347
}

src/navigate/model/devices/APIs/asi/asi_MS2000_controller.py

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def __init__(self, com_port: str, baud_rate: int, verbose: bool = False):
9494
#: float: Last time a command was sent to the MS2000 Controller
9595
self._last_cmd_send_time = time.perf_counter()
9696

97+
9798
@staticmethod
9899
def scan_ports() -> list[str]:
99100
"""Scans for available COM ports
@@ -109,6 +110,7 @@ def scan_ports() -> list[str]:
109110
com_ports.sort(key=lambda value: int(value[3:]))
110111
return com_ports
111112

113+
112114
def connect_to_serial(
113115
self,
114116
rx_size: int = 12800,
@@ -143,8 +145,6 @@ def connect_to_serial(
143145

144146
# set the size of the rx and tx buffers before calling open
145147
self.serial_port.set_buffer_size(rx_size, tx_size)
146-
147-
# try to open the serial port
148148
try:
149149
self.serial_port.open()
150150
except SerialException:
@@ -164,7 +164,8 @@ def connect_to_serial(
164164
)
165165

166166
#: list[str]: Default axes sequence of the MS2000 Controller
167-
self.default_axes_sequence = self.get_default_motor_axis_sequence()
167+
self.default_axes_sequence = ["X", "Y", "Z"] # self.get_default_motor_axis_sequence()
168+
168169

169170
def get_default_motor_axis_sequence(self) -> None:
170171
"""Get the default motor axis sequence from the ASI device
@@ -187,6 +188,7 @@ def get_default_motor_axis_sequence(self) -> None:
187188

188189
return default_axes_sequence
189190

191+
190192
def set_feedback_alignment(self, axis, aa):
191193
"""Set the stage feedback alignment.
192194
@@ -200,6 +202,7 @@ def set_feedback_alignment(self, axis, aa):
200202
self.send_command(f"AZ {axis}\r")
201203
self.read_response()
202204

205+
203206
def set_backlash(self, axis, val):
204207
"""Enable/disable stage backlash correction.
205208
@@ -210,10 +213,10 @@ def set_backlash(self, axis, val):
210213
val : float
211214
Distance of anti-backlash motion [mm]
212215
"""
213-
cmd_str = f"B {axis}={val:.7f}\r"
214216
self.send_command(f"B {axis}={val:.7f}\r")
215217
self.read_response()
216218

219+
217220
def set_finishing_accuracy(self, axis, ac):
218221
"""Set the stage finishing accuracy.
219222
@@ -227,6 +230,7 @@ def set_finishing_accuracy(self, axis, ac):
227230
self.send_command(f"PC {axis}={ac:.7f}\r")
228231
self.read_response()
229232

233+
230234
def set_error(self, axis, ac):
231235
"""
232236
Set the stage drift error
@@ -240,14 +244,15 @@ def set_error(self, axis, ac):
240244
"""
241245
self.send_command(f"E {axis}={ac:.7f}\r")
242246
self.read_response()
243-
247+
244248

245249
def disconnect_from_serial(self) -> None:
246250
"""Disconnect from the serial port if it's open."""
247251
if self.is_open():
248252
self.serial_port.close()
249253
self.report_to_console("Disconnected from the serial port.")
250254

255+
251256
def is_open(self) -> bool:
252257
"""Returns True if the serial port exists and is open.
253258
@@ -259,6 +264,7 @@ def is_open(self) -> bool:
259264
# short circuits if serial port is None
260265
return self.serial_port and self.serial_port.is_open
261266

267+
262268
def report_to_console(self, message: str) -> None:
263269
"""Print message to the output device, usually the console.
264270
@@ -268,10 +274,10 @@ def report_to_console(self, message: str) -> None:
268274
Message to print to the output device
269275
"""
270276
# useful if we want to output data to something other than the console
271-
# (ui element etc)
272277
if self.verbose:
273278
print(message)
274279

280+
275281
def wait_for_device(self, report: bool = False) :
276282
"""Waits for the all motors to stop moving."""
277283
if not report:
@@ -283,6 +289,7 @@ def wait_for_device(self, report: bool = False) :
283289
busy = self.is_device_busy()
284290
self.report = temp
285291

292+
286293
def send_command(self, cmd: bytes) -> None:
287294
"""Send a serial command to the device.
288295
@@ -309,6 +316,7 @@ def send_command(self, cmd: bytes) -> None:
309316

310317
# sleep to avoid error, emperically found this made it work
311318
time.sleep(0.1)
319+
312320

313321
def read_response(self) -> str:
314322
"""Read a line from the serial response.
@@ -320,16 +328,15 @@ def read_response(self) -> str:
320328
"""
321329
response = self.serial_port.readline()
322330
self.safe_to_write.set()
323-
324331
response = response.decode(encoding="ascii")
325332
# Remove leading and trailing empty spaces
326333
self.report_to_console(f"Received Response: {response.strip()}")
327-
328334
if response.startswith(":N"):
329335
raise MS2000Exception(response)
330336

331337
return response # in case we want to read the response
332338

339+
333340
def moverel(self, x: int = 0, y: int = 0, z: int = 0) -> None:
334341
"""Move the stage with a relative move on multiple axes.
335342
@@ -345,6 +352,7 @@ def moverel(self, x: int = 0, y: int = 0, z: int = 0) -> None:
345352
self.send_command(f"MOVREL X={x} Y={y} Z={z}\r")
346353
self.read_response()
347354

355+
348356
def moverel_axis(self, axis: str, distance: float) -> None:
349357
"""Move the stage with a relative move on one axis
350358
@@ -358,6 +366,7 @@ def moverel_axis(self, axis: str, distance: float) -> None:
358366
self.send_command(f"MOVREL {axis}={round(distance, 6)}\r")
359367
self.read_response()
360368

369+
361370
def move(self, pos_dict) -> None:
362371
"""Move the stage with an absolute move on multiple axes
363372
@@ -372,6 +381,7 @@ def move(self, pos_dict) -> None:
372381
self.send_command(f"MOVE {pos_str}\r")
373382
self.read_response()
374383

384+
375385
def move_axis(self, axis: str, distance: float) -> None:
376386
"""Move the stage with an absolute move on one axis
377387
@@ -385,6 +395,7 @@ def move_axis(self, axis: str, distance: float) -> None:
385395
self.send_command(f"MOVE {axis}={round(distance, 6)}\r")
386396
self.read_response()
387397

398+
388399
def set_max_speed(self, axis: str, speed: float) -> None:
389400
"""Set the speed on a specific axis. Speed is in mm/s.
390401
@@ -401,6 +412,7 @@ def set_max_speed(self, axis: str, speed: float) -> None:
401412
self.send_command(f"SPEED {axis}={speed}\r")
402413
self.read_response()
403414

415+
404416
def get_axis_position(self, axis: str) -> int:
405417
"""Return the position of the stage in ASI units (tenths of microns).
406418
@@ -415,12 +427,10 @@ def get_axis_position(self, axis: str) -> int:
415427
"""
416428
self.send_command(f"WHERE {axis}\r")
417429
response = self.read_response()
418-
# try:
419430
pos = float(response.split(" ")[1])
420-
# except:
421-
# pos = float('Inf')
422431
return pos
423432

433+
424434
def get_axis_position_um(self, axis: str) -> float:
425435
"""Return the position of the stage in microns.
426436
@@ -437,6 +447,7 @@ def get_axis_position_um(self, axis: str) -> float:
437447
response = self.read_response()
438448
return float(response.split(" ")[1]) / 10.0
439449

450+
440451
def get_position(self, axes) -> dict:
441452
"""Return current stage position in ASI units.
442453
@@ -465,8 +476,7 @@ def get_position(self, axes) -> dict:
465476
cmd = f"WHERE {' '.join(axes)}\r"
466477
self.send_command(cmd)
467478
response = self.read_response()
468-
469-
# return response.split(" ")[1:-1]
479+
470480
pos = response.split(" ")
471481
axes_seq = list(
472482
filter(
@@ -483,14 +493,17 @@ def get_position(self, axes) -> dict:
483493
# Report position failed. Don't crash, we can try again.
484494
pass
485495
return axis_dict
496+
486497
else:
487498
result = {}
488499
for axis in axes:
489500
result[axis] = self.get_axis_position(axis)
490501
return result
491502

503+
492504
# Utility Functions
493505

506+
494507
def is_axis_busy(self, axis: str) -> bool:
495508
"""Returns True if the axis is busy.
496509
@@ -507,6 +520,7 @@ def is_axis_busy(self, axis: str) -> bool:
507520
res = self.read_response()
508521
return "B" in res
509522

523+
510524
def is_device_busy(self) -> bool:
511525
"""Returns True if any axis is busy.
512526
@@ -519,17 +533,20 @@ def is_device_busy(self) -> bool:
519533
res = self.read_response()
520534
return "B" in res
521535

536+
522537
def wait_for_device(self, timeout: float = 1.75) -> None:
523538
"""Waits for the all motors to stop moving.
524539
525540
timeout : float
526541
Timeout in seconds. Default is 1.75 seconds.
527542
"""
543+
528544
if self.verbose:
529545
print("Waiting for device...")
530546
busy = self.is_device_busy()
531547
waiting_time = 0.0
532-
548+
549+
# t_start = time.time()
533550
while busy:
534551
waiting_time += 0.001
535552
if waiting_time >= timeout:
@@ -540,6 +557,7 @@ def wait_for_device(self, timeout: float = 1.75) -> None:
540557
if self.verbose:
541558
print(f"Waited {waiting_time:.2f} s")
542559

560+
543561
def stop(self):
544562
"""Stop all stage movement immediately"""
545563

@@ -548,6 +566,7 @@ def stop(self):
548566
if self.verbose:
549567
print("ASI Stages stopped successfully")
550568

569+
551570
def set_speed(self, speed_dict):
552571
"""Set speed
553572
@@ -560,6 +579,7 @@ def set_speed(self, speed_dict):
560579
self.send_command(f"S {axes}")
561580
self.read_response()
562581

582+
563583
def set_speed_as_percent_max(self, pct):
564584
"""Set speed as a percentage of the maximum speed
565585
@@ -601,6 +621,7 @@ def get_speed(self, axis: str):
601621
response = self.read_response()
602622
return float(response.split("=")[1])
603623

624+
604625
def get_encoder_counts_per_mm(self, axis: str):
605626
"""Get encoder counts pre mm of axis
606627
@@ -619,6 +640,7 @@ def get_encoder_counts_per_mm(self, axis: str):
619640
response = self.read_response()
620641
return float(response.split("=")[1].split()[0])
621642

643+
622644
def scanr(
623645
self,
624646
start_position_mm: float,
@@ -655,6 +677,7 @@ def scanr(
655677
self.send_command(command)
656678
self.read_response()
657679

680+
658681
def scanv(
659682
self,
660683
start_position_mm: float,
@@ -689,6 +712,7 @@ def scanv(
689712
self.send_command(command)
690713
self.read_response()
691714

715+
692716
def start_scan(self, axis: str, is_single_axis_scan: bool = True):
693717
"""
694718
Start scan
@@ -703,11 +727,13 @@ def start_scan(self, axis: str, is_single_axis_scan: bool = True):
703727
self.send_command("SCAN")
704728
self.read_response()
705729

730+
706731
def stop_scan(self):
707732
"""Stop scan."""
708733
self.send_command("SCAN P")
709734
self.read_response()
710735

736+
711737
def is_moving(self):
712738
"""Check to see if the stage is moving.
713739
@@ -744,6 +770,7 @@ def is_moving(self):
744770
print("WARNING: WAIT UNTIL DONE RECEIVED NO RESPONSE")
745771
return False
746772

773+
747774
def set_triggered_move(self, axis):
748775
'''
749776
Set ASI to repeat the latest relative movement

src/navigate/model/devices/camera/photometrics.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,6 @@ def set_readout_direction(self, mode):
214214
Scan direction options: {'Down': 0, 'Up': 1, 'Down/Up Alternate': 2}
215215
216216
"""
217-
# print("available scan directions on camera are:")
218-
# print(str(self.camera_controller.prog_scan_dirs))
219-
220217
if mode == "Top-to-Bottom":
221218
# 'Down' readout direction
222219
self.camera_controller.prog_scan_dir = 0
@@ -359,7 +356,6 @@ def set_binning(self, binning_string):
359356
}
360357
if binning_string not in binning_dict.keys():
361358
logger.debug(f"can't set binning to {binning_string}")
362-
print(f"Can't set binning to {binning_string}")
363359
return False
364360
self.camera_controller.binning = binning_dict[binning_string]
365361
idx = binning_string.index("x")
@@ -442,15 +438,11 @@ def initialize_image_series(self, data_buffer=None, number_of_frames=100):
442438
self.camera_controller.exp_mode = "Edge Trigger"
443439
self.camera_controller.prog_scan_line_delay = self._scandelay
444440
self.camera_controller.exp_out_mode = 4
445-
print(
446-
"camera ready to acquire programmable scan mode "
447-
"with scandelay {}".format(self._scandelay)
448-
)
441+
449442
else:
450443
# Normal mode
451444
self.camera_controller.exp_out_mode = "Any Row"
452445
self.camera_controller.exp_mode = "Edge Trigger"
453-
print("camera ready to acquire static light sheet mode")
454446

455447
# Prepare for buffered acquisition
456448
#: int: Number of frames
@@ -496,10 +488,14 @@ def _receive_images(self):
496488
# Delete copied frame for memory management
497489
frame = None
498490
del frame
491+
492+
frame_to_return = [self._frames_received]
499493
self._frames_received += 1
494+
# check to make sure the next frame exist in buffer
500495
if self._frames_received >= self._numberofframes:
501496
self._frames_received = 0
502-
return [self._frames_received - 1]
497+
return frame_to_return
498+
503499
except Exception as e:
504500
print(str(e))
505501

0 commit comments

Comments
 (0)