Beispiel #1
0
    def exception(self, timeout=None):
        """Return the exception raised by the call that the future represents.

        Args:
            timeout: The number of seconds to wait for the exception if the
                future isn't done. If None, then there is no limit on the wait
                time.

        Returns:
            The exception raised by the call that the future represents or None
            if the call completed without raising.

        Raises:
            CancelledError: If the future was cancelled.
            TimeoutError: If the future didn't finish executing before the
                given timeout.
        """

        with self._condition:
            if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
                raise CancelledError()
            elif self._state == FINISHED:
                return self._exception

            self._condition.wait(timeout)

            if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
                raise CancelledError()
            elif self._state == FINISHED:
                return self._exception
            else:
                raise TimeoutError()
Beispiel #2
0
    def result(self, timeout=None):
        """Return the result of the call that the future represents.

        Args:
            timeout: The number of seconds to wait for the result if the future
                isn't done. If None, then there is no limit on the wait time.

        Returns:
            The result of the call that the future represents.

        Raises:
            CancelledError: If the future was cancelled.
            TimeoutError: If the future didn't finish executing before the
                given timeout.
            Exception: If the call raised then that exception will be raised.
        """
        with self._condition:
            if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
                raise CancelledError()
            elif self._state == FINISHED:
                return self.__get_result()

            self._condition.wait(timeout)

            if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:
                raise CancelledError()
            elif self._state == FINISHED:
                return self.__get_result()
            else:
                raise TimeoutError()
Beispiel #3
0
 async def _run_with_tg(self, *, evt: anyio.abc.Event=None):
     try:
         await super()._run_with_tg(evt=evt)
     except anyio.get_cancelled_exc_class():
         if self._done.is_set():
             await self._handle_prev(_ResultEvent(self._result))
         else:
             await self._handle_prev(_ErrorEvent(CancelledError()))
         raise
     except Exception as exc:
         await self._handle_prev(_ErrorEvent(exc))
     except BaseException:
         await self._handle_prev(_ErrorEvent(CancelledError()))
         raise
     else:
         await self._handle_prev(_ResultEvent(self._result))
Beispiel #4
0
    def _acquireStreamTile(self, i, ix, iy, stream):
        """
        Calls acquire function and blocks until the data is returned.
        :return DataArray: Acquired da for the current tile stream
        """
        # Update the progress bar
        self._future.set_progress(
            end=self.estimateTime((self._nx * self._ny) - i) + time.time())
        # Acquire data array for passed stream
        self._future.running_subf = acqmng.acquire([stream],
                                                   self._settings_obs)
        das, e = self._future.running_subf.result(
        )  # blocks until all the acquisitions are finished
        if e:
            logging.warning(
                f"Acquisition for tile {ix}x{iy}, stream {stream.name} partially failed: {e}"
            )

        if self._future._task_state == CANCELLED:
            raise CancelledError()
        try:
            return das[0]  # return first da
        except IndexError:
            raise IndexError(
                f"Failure in acquiring tile {ix}x{iy}, stream {stream.name}.")
Beispiel #5
0
    def _doMoveAbs(self, f, pos):
        self._check_hw_error()
        self._updatePosition()
        current_pos = self._applyInversion(self.position.value)

        shifts = {}
        if f._must_stop.is_set():
            raise CancelledError()
        for axname, val in pos.items():
            if self._closed_loop[axname]:
                shifts[axname] = val - current_pos[axname]
                encoder_cnts = round(val * self._counts_per_meter[axname])
                self.runAbsTargetMove(self._axis_map[axname], encoder_cnts,
                                      self._speed_steps[axname])
            else:
                # No absolute move for open-loop => convert to relative move
                shifts[axname] = val - current_pos[axname]
                steps_float = shifts[axname] * self._steps_per_meter[axname]
                steps = int(steps_float)
                usteps = int((steps_float - steps) * USTEPS_PER_STEP)
                self.runMotorJog(self._axis_map[axname], steps, usteps,
                                 self._speed_steps[axname])

        try:
            self._waitEndMotion(f, shifts)
        finally:
            # Leave target mode in case of closed-loop move
            for ax in pos:
                self.stopAxis(self._axis_map[ax])
            self._updatePosition()
Beispiel #6
0
    def _doMoveRel(self, f, shift):
        self._check_hw_error()

        shifts = {}
        if f._must_stop.is_set():
            raise CancelledError()

        for axname, val in shift.items():
            if self._closed_loop[axname]:
                shifts[axname] = val
                encoder_cnts = val * self._counts_per_meter[axname]
                self.runRelTargetMove(self._axis_map[axname], encoder_cnts,
                                      self._speed_steps[axname])
            else:
                shifts[axname] = val
                steps_float = val * self._steps_per_meter[axname]
                steps = int(steps_float)
                usteps = int((steps_float - steps) * USTEPS_PER_STEP)
                self.runMotorJog(self._axis_map[axname], steps, usteps,
                                 self._speed_steps[axname])

        try:
            self._waitEndMotion(f, shifts)
        finally:
            # Leave target mode in case of closed-loop move
            for ax in shift:
                self.stopAxis(self._axis_map[ax])
            self._updatePosition()
Beispiel #7
0
    def _waitEndMotion(self, f, shifts):
        """
        Wait until move is done.
        :param f: (CancellableFuture) move future
        :param shifts: (dict: str --> floats) relative move (in m) between current position and previous position
        """
        dur = 0
        for ax, shift in shifts.items():
            dur = max(abs(shift / self._speed[ax]), dur)

        max_dur = dur * 2 + 1
        logging.debug("Expecting a move of %g s, will wait up to %g s", dur, max_dur)

        end_time = time.time() + max_dur
        moving_axes = set(shifts.keys())  # All axes (still) moving
        while moving_axes:
            if f._must_stop.is_set():
                for axname in moving_axes:
                    self.stopAxis(self._axis_map[axname])
                    raise CancelledError()

            if time.time() > end_time:
                raise TimeoutError("Timeout after while waiting for end of motion on axes %s for %g s" % (moving_axes, max_dur))

            for axname in moving_axes.copy():  # Copy as the set can change during the iteration
                axis = self._axis_map[axname]
                if self._closed_loop[axname]:
                    moving = self.isMovingClosedLoop(axis)
                else:
                    moving = self.isMovingOpenLoop(axis)
                if not moving:
                    moving_axes.discard(axname)

            self._check_hw_error()
            time.sleep(0.05)
Beispiel #8
0
Datei: job.py Projekt: towr/bndl
 def set_executing(self, worker):
     '''Utility for sub-classes to register the task as executing on a worker.'''
     if self.cancelled:
         raise CancelledError()
     assert not self.pending, '%r pending' % self
     self.executed_on.append(worker.name)
     self.attempts += 1
     self.signal_start()
Beispiel #9
0
    def cancel(self):
        """Send a cancelation to the recipient.

        TODO: Trio can't do that cleanly.
        """
        if self.scope is not None:
            self.scope.cancel()
        self.set_error(CancelledError())
Beispiel #10
0
    def _acquireStreamCompressedZStack(self, i, ix, iy, stream):
        """
        Acquire a compressed zstack image for the given stream.
        The method does the following:
            - Move focus over the list of zlevels
            - For each focus level acquire image of the stream
            - Construct xyz cube for the acquired zstack
            - Compress the cube into a single image using 'maximum intensity projection'
        :return DataArray: Acquired da for the current tile stream
        """
        zstack = []
        for z in self._zlevels:
            logging.debug(f"Moving focus for tile {ix}x{iy} to {z}.")
            stream.focuser.moveAbsSync({'z': z})
            da = self._acquireStreamTile(i, ix, iy, stream)
            zstack.append(da)

        if self._future._task_state == CANCELLED:
            raise CancelledError()
        logging.debug(
            f"Zstack acquisition for tile {ix}x{iy}, stream {stream.name} finished, compressing data into a single image."
        )
        # Convert zstack into a cube
        fm_cube = assembleZCube(zstack, self._zlevels)
        # Save the cube on disk if a log path exists
        if self._log_path:
            self._save_tiles(ix,
                             iy,
                             fm_cube,
                             stream_cube_id=self._streams.index(stream))

        if self._focusing_method == FocusingMethod.MAX_INTENSITY_PROJECTION:
            # Compress the cube into a single image (using maximum intensity projection)
            mip_image = numpy.amax(fm_cube, axis=0)
            if self._future._task_state == CANCELLED:
                raise CancelledError()
            logging.debug(
                f"Zstack compression for tile {ix}x{iy}, stream {stream.name} finished."
            )
            return DataArray(mip_image, copy.copy(zstack[0].metadata))
        else:
            # TODO: support stitched Z-stacks
            # For now, the init will raise NotImplementedError in such case
            logging.warning("Zstack returned as-is, while it is not supported")
            return fm_cube
Beispiel #11
0
    def _moveTo(self, future, x, y, z, timeout=60):
        with future._moving_lock:
            try:
                if future._must_stop.is_set():
                    raise CancelledError()
                logging.debug("Moving to position (%s, %s, %s)", x, y, z)
                self.parent.MoveStage(x, y, z)
                # documentation suggests to wait 1s before calling
                # GetStagePosition() after MoveStage()
                time.sleep(1)

                # Wait until the move is over
                # Don't check for future._must_stop because anyway the stage will
                # stop moving, and so it's nice to wait until we know the stage is
                # not moving.
                moving = True
                tstart = time.time()
                while moving:
                    x, y, z, moving = self.parent.GetStagePosition()
                    # Take the opportunity to update .position
                    self._updatePosition({"x": x, "y": y, "z": z})

                    if time.time() > tstart + timeout:
                        self.parent.Abort()
                        logging.error(
                            "Timeout after submitting stage move. Aborting move."
                        )
                        break

                    # 50 ms is about the time it takes to read the stage status
                    time.sleep(50e-3)

                # If it was cancelled, Abort() has stopped the stage before, and
                # we still have waited until the stage stopped moving. Now let
                # know the user that the move is not complete.
                if future._must_stop.is_set():
                    raise CancelledError()
            except RemconError:
                if future._must_stop.is_set():
                    raise CancelledError()
                raise
            finally:
                future._was_stopped = True
                # Update the position, even if the move didn't entirely succeed
                self._updatePosition()
Beispiel #12
0
def task(spec, cancel):
    if cancel.get():
        raise CancelledError("Cancelled by request")
    cov = np.array(spec.inputs['cov'])
    mean = np.array(spec.inputs['mean'])
    w = np.array(spec.inputs['c.w'], dtype=float)
    z = max(0.5, sum(w))
    w /= z
    return {'c.norm': z, 'c.er': mean @ w, 'c.var': w @ cov @ w}
Beispiel #13
0
 def result(self, timeout=None):
     self._recv(timeout)
     if self.state == self.STATE_FINISHED:
         return self._result
     elif self.state == self.STATE_EXCEPTION:
         raise self._exception
     else:
         assert self.state == self.STATE_CANCELLED
         raise CancelledError()
Beispiel #14
0
    def _moveTo(self, future, pos, timeout=60):
        with future._moving_lock:
            try:
                if future._must_stop.is_set():
                    raise CancelledError()
                logging.debug("Moving to position {}".format(pos))
                self.parent.move_stage(pos, rel=False)
                time.sleep(0.5)

                # Wait until the move is over.
                # Don't check for future._must_stop because anyway the stage will
                # stop moving, and so it's nice to wait until we know the stage is
                # not moving.
                moving = True
                tstart = time.time()
                while moving:
                    pos = self.parent.get_stage_position()
                    moving = self.parent.stage_is_moving()
                    # Take the opportunity to update .position
                    self._updatePosition(pos)

                    if time.time() > tstart + timeout:
                        self.parent.stop_stage_movement()
                        logging.error(
                            "Timeout after submitting stage move. Aborting move."
                        )
                        break

                    # Wait for 50ms so that we do not keep using the CPU all the time.
                    time.sleep(50e-3)

                # If it was cancelled, Abort() has stopped the stage before, and
                # we still have waited until the stage stopped moving. Now let
                # know the user that the move is not complete.
                if future._must_stop.is_set():
                    raise CancelledError()
            except Exception:
                if future._must_stop.is_set():
                    raise CancelledError()
                raise
            finally:
                future._was_stopped = True
                # Update the position, even if the move didn't entirely succeed
                self._updatePosition()
Beispiel #15
0
    def download_installer(self, remote_version):
        """
        Download the installer for the given version to a temporary directory
        remote_version (str): version number as "1.20.3"
        return (str): path to the local file
        """
        installer_file = INSTALLER_FILE % remote_version
        web_file = self._open_remote_file(installer_file)
        file_size = int(web_file.headers["Content-Length"])

        dest_dir = tempfile.gettempdir()
        local_path = os.path.join(dest_dir, installer_file)

        logging.info("Downloading from %s (%d bytes) to %s...", web_file.url,
                     file_size, local_path)

        try:
            pdlg = wx.ProgressDialog(
                "Downloading update...",
                "The new %s installer %s is being downloaded." %
                (VIEWER_NAME, remote_version),
                maximum=file_size,
                parent=wx.GetApp().main_frame,
                style=wx.PD_CAN_ABORT | wx.PD_AUTO_HIDE | wx.PD_APP_MODAL
                | wx.PD_REMAINING_TIME)

            with open(local_path, 'wb') as local_file:
                count = 0
                chunk_size = 100 * 1024  # Too small chunks slows down the download
                while count < file_size:
                    grabbed = web_file.read(chunk_size)
                    local_file.write(grabbed)
                    if grabbed:
                        count += len(grabbed)
                    else:
                        logging.warning(
                            "Received no more data, will assume the file is only %d bytes",
                            count)
                        break
                    if count > file_size:
                        logging.warning(
                            "Received too much data (%d bytes), will stop",
                            count)
                        break
                    keep_going, skip = pdlg.Update(count)
                    if not keep_going:
                        raise CancelledError("Download cancelled by user")

            logging.info("Download done.")
            return local_path
        finally:
            try:
                pdlg.Destroy()
            except (RuntimeError, AttributeError):
                pass
            web_file.close()
Beispiel #16
0
    def update_tasks(self):
        """Handles timing out Tasks."""
        for task in self.task_manager.timeout_tasks():
            self.task_manager.task_done(
                task.id, TimeoutError("Task timeout", task.timeout))
            self.worker_manager.stop_worker(task.worker_id)

        for task in self.task_manager.cancelled_tasks():
            self.task_manager.task_done(task.id, CancelledError())
            self.worker_manager.stop_worker(task.worker_id)
Beispiel #17
0
 def result(self, timeout=None):
     if self._exception is not None:
         raise self._exception
     elif self._cancelled:
         raise CancelledError()
     else:
         if self._result_ready.wait(timeout):
             return self._result
         else:
             raise TimeoutError(f"Timeout of {timeout} seconds exceeded.")
Beispiel #18
0
 def cancel(self):
     """Try to cancel a coroutine. Will return True if successfully raised otherwise False"""
     if self.cancelled:
         return True
     if self.complete:
         return False
     if self.running():
         return False
     self.cancelled = True
     self.set_exception(
         CancelledError("Execution of this coro has been cancelled!"))
     return True
Beispiel #19
0
    def _waitEndMove(self, future, axes, end=0):
        """
        Wait until all the given axes are finished moving, or a request to
        stop has been received.
        future (Future): the future it handles
        axes (set of int): the axes IDs to check
        end (float): expected end time
        raise:
            CancelledError: if cancelled before the end of the move
        """
        moving_axes = set(axes)

        last_upd = time.time()
        last_axes = moving_axes.copy()
        try:
            while not future._must_stop.is_set():
                for aid in moving_axes.copy(
                ):  # need copy to remove during iteration
                    if self.IsMotionDone(aid):
                        moving_axes.discard(aid)
                if not moving_axes:
                    # no more axes to wait for
                    break

                # Update the position from time to time (10 Hz)
                if time.time() - last_upd > 0.1 or last_axes != moving_axes:
                    last_names = set(n for n, i in self._name_to_axis.items()
                                     if i in last_axes)
                    self._updatePosition(last_names)
                    last_upd = time.time()
                    last_axes = moving_axes.copy()

                # Wait half of the time left (maximum 0.1 s)
                left = end - time.time()
                sleept = max(0.001, min(left / 2, 0.1))
                future._must_stop.wait(sleept)

                # TODO: timeout if really too long
            else:
                logging.debug("Move of axes %s cancelled before the end", axes)
                # stop all axes still moving them
                for i in moving_axes:
                    self.StopMotion(i)
                future._was_stopped = True
                raise CancelledError()
        except Exception:
            raise
        else:
            # Did everything really finished fine?
            self._checkError()
        finally:
            self._updatePosition()  # update (all axes) with final position
Beispiel #20
0
    def _gather_result(_):
        result_list = []
        for fut in futs:
            if fut.cancelled():
                if return_exceptions:
                    result_list.append(CancelledError())
                    continue

                result.set_exception(CancelledError())
                break

            if fut.exception() is None:
                result_list.append(fut.result())
                continue

            if return_exceptions:
                result_list.append(fut.exception())
                continue

            result.set_exception(fut.exception())
            break
        result.set_result(result_list)
Beispiel #21
0
    def _doMoveAbs(self, future, pos):
        """
        Blocking and cancellable absolute move
        future (Future): the future it handles
        _pos (dict str -> float): axis name -> absolute target position
        raise:
            SmarPodError: if the controller reported an error
            CancelledError: if cancelled before the end of the move
        """
        last_upd = time.time()
        dur = 30  # TODO: Calculate an estimated move duration
        end = time.time() + dur
        max_dur = dur * 2 + 1
        logging.debug("Expecting a move of %g s, will wait up to %g s", dur,
                      max_dur)
        timeout = last_upd + max_dur

        with future._moving_lock:
            self.Move(pos)
            while not future._must_stop.is_set():
                status = self.GetMoveStatus()
                # check if move is done
                if status.value == SmarPodDLL.SMARPOD_STOPPED.value:
                    break

                now = time.time()
                if now > timeout:
                    logging.warning("Stopping move due to timeout after %g s.",
                                    max_dur)
                    self.stop()
                    raise TimeoutError("Move is not over after %g s, while "
                                       "expected it takes only %g s" %
                                       (max_dur, dur))

                # Update the position from time to time (10 Hz)
                if now - last_upd > 0.1:
                    self._updatePosition()
                    last_upd = time.time()

                # Wait half of the time left (maximum 0.1 s)
                left = end - time.time()
                sleept = max(0.001, min(left / 2, 0.1))
                future._must_stop.wait(sleept)
            else:
                self.stop()
                future._was_stopped = True
                raise CancelledError()

        self._updatePosition()

        logging.debug("move successfully completed")
Beispiel #22
0
    def _search_index(self, f, axname, direction):
        """
        :param f (Future)
        :param axname (str): axis name (as seen by the user)
        :param direction (-1 or 1): -1 for negative direction (beginning of the rod), 1 for positive direction
        returns (bool): True if index was found, false if limit was reached
        raises PMDError for all other errors except limit exceeded error
        IOError in case of timeout
        """
        axis = self._axis_map[axname]
        maxdist = self._axes[axname].range[1] - self._axes[axname].range[
            0]  # complete rodlength
        steps = int(maxdist * self._steps_per_meter[axname])
        maxdur = maxdist / self._speed[axname] + 1
        end_time = time.time() + 2 * maxdur

        logging.debug("Searching for index in direction %s.", direction)
        self.startIndexMode(axis)
        self.moveToIndex(axis, steps * direction)

        index_found = False
        while not index_found:
            if f._must_stop.is_set():
                self.stopAxis(axis)
                raise CancelledError()
            # Check for timeout
            if time.time() > end_time:
                self.stopAxis(axis)  # exit index mode
                raise IOError(
                    "Timeout while waiting for end of motion on axis %s" %
                    axis)

            # Check if limit is reached
            try:
                self._check_hw_error()
            except PMDError as ex:
                if ex.errno == 6:  # external limit reached
                    logging.debug("Axis %d limit reached during referencing",
                                  axis)
                    self.stopAxis(
                        axis
                    )  # that seems to be necessary after reaching the limit
                    break
                else:
                    raise

            # Get index status
            index_found = self.getIndexStatus(self._axis_map[axname])[-1]
            time.sleep(0.05)

        return index_found
Beispiel #23
0
def _get_result(future, pipe, timeout):
    """Waits for result and handles communication errors."""
    counter = count(step=SLEEP_UNIT)

    try:
        while not pipe.poll(SLEEP_UNIT):
            if timeout is not None and next(counter) >= timeout:
                return TimeoutError('Task Timeout', timeout)
            elif future.cancelled():
                return CancelledError()

        return pipe.recv()
    except (EOFError, OSError):
        return ProcessExpired('Abnormal termination')
    except Exception as error:
        return error
Beispiel #24
0
def main(spec, cancel):
    out = err = None
    with run_it(spec) as proc:
        while True:
            if cancel.get():
                raise CancelledError("Cancelled by request")
            try:
                out, err = proc.communicate(timeout=5)
            except sp.TimeoutExpired:
                continue
            if proc.returncode:
                raise RuntimeError(
                    ("Subprocess exited with status %s. stdout:\n%s\n"
                     + "stderr:\n%s") % (proc.returncode, out, err))
            else:
                return {"sum": int(out), "warnings": err}
Beispiel #25
0
 def _doReference(self, future, axes):
     """
     Actually runs the referencing code
     axes (set of str)
     raise:
         IOError: if referencing failed due to hardware
         CancelledError if was cancelled
     """
     # Reset reference so that if it fails, it states the axes are not
     # referenced (anymore)
     with future._moving_lock:
         try:
             # do the referencing for each axis sequentially
             # (because each referencing is synchronous)
             for a in axes:
                 if future._must_stop.is_set():
                     raise CancelledError()
                 aid = self._axis_map[a]
                 self.referenced._value[a] = False
                 self.HomeSearch(
                     aid, REF_NEGATIVE_LIMIT
                 )  # search for the negative limit signal to set an origin
                 self._waitEndMove(future, (aid, ),
                                   time.time() +
                                   100)  # block until it's over
                 self.SetHome(aid, 0.0)  # set negative limit as origin
                 self.referenced._value[a] = True
         except CancelledError:
             # FIXME: if the referencing is stopped, the device refuses to
             # move until referencing is run (and successful).
             # => Need to put back the device into a mode where at least
             # relative moves work.
             logging.warning(
                 "Referencing cancelled, device will not move until another referencing"
             )
             future._was_stopped = True
             raise
         except Exception:
             logging.exception("Referencing failure")
             raise
         finally:
             # We only notify after updating the position so that when a listener
             # receives updates both values are already updated.
             self._updatePosition(
                 axes)  # all the referenced axes should be back to 0
             # read-only so manually notify
             self.referenced.notify(self.referenced.value)
Beispiel #26
0
    def acquire_roa(self, dataflow):
        """
        Acquire the single field images that resemble the region of acquisition (ROA, megafield image).
        :param dataflow: (model.DataFlow) The dataflow on the detector.
        :return: (list of DataArrays): A list of the raw image data. Each data array (entire field, thumbnail,
                                       or zero array) represents one single field image within the ROA (megafield).
        """

        total_field_time = self._detector.frameDuration.value
        timeout = total_field_time + 5  # TODO what margin should be used?

        # Acquire all single field images, which are automatically offloaded to the external storage.
        for field_idx in self._roa.field_indices:
            # Reset the event that waits for the image being received (puts flag to false).
            self._data_received.clear()
            self.field_idx = field_idx
            logging.debug("Acquiring field with index: %s", field_idx)

            self.move_stage_to_next_tile(
            )  # move stage to next field image position

            if field_idx != (0, 0):
                self.correct_beam_shift(
                )  # correct the shift of the beams caused by the parasitic magnetic field.

            dataflow.next(field_idx)  # acquire the next field image.

            # Wait until single field image data has been received (image_received sets flag to True).
            if not self._data_received.wait(timeout):
                # TODO here we often timeout when actually just the offload queue is full
                #  need to handle offload queue error differently to just wait a bit instead of timing out
                #   -> check if finish megafield is called in finally when hitting here
                raise TimeoutError("Timeout while waiting for field image.")

            self._fields_remaining.discard(field_idx)

            # In case the acquisition was cancelled by a client, before the future returned, raise cancellation error.
            # Note: The acquisition of the current single field image (tile) is still finished though.
            if self._cancelled:
                raise CancelledError()

            # Update the time left for the acquisition.
            expected_time = len(self._fields_remaining) * total_field_time
            self._future.set_progress(end=time.time() + expected_time)

        return self.megafield
Beispiel #27
0
    def _doReference(self, f, axes):
        self._check_hw_error()
        # Request referencing on all axes
        # Referencing procedure: index signal is in the middle of the rod (when using encoder)
        #   * move to the limit switch in the negative direction (fixed end of the rod)
        #   * once we reach the limit switch, PMD error 6 will be raised
        #   * move back in the opposite direction until indexing signal is registered

        # In case there is no encoder, it is still possible to reference. The motor has an internal indexing
        # signal 8.9 µm from fixed end of the rod (the end of the rod should be the most negative position if
        # the axis is not inverted). By referencing, this position can be set to 0 and absolute moves are possible
        # (although with less accuracy). However, we do not currently support this type of referencing without
        # encoder. With our hardware attached to the motor, it is impossible to reach the 8.9 µm indexing position.

        for axname in axes:
            if f._must_stop.is_set():
                self.stopAxis(self._axis_map[axname])
                raise CancelledError()
            axis = self._axis_map[axname]
            self.referenced._value[axname] = False

            # First, search for the index in negative direction.
            idx_found = self._search_index(f, axname, direction=-1)

            # If it wasn't found, try again in positive direction.
            if not idx_found:
                logging.debug("Referencing axis %s in the positive direction",
                              axis)
                idx_found = self._search_index(f, axname, direction=1)

            # If it's still not found, something went wrong.
            if not idx_found:
                raise ValueError(
                    "Couldn't find index on axis %s (%s), referencing failed."
                    % (axis, axname))

            # Referencing complete
            logging.debug("Finished referencing axis %s." % axname)
            self.stopAxis(
                axis
            )  # the axis should already be stopped, make sure for safety
            self.referenced._value[axname] = True

        # read-only so manually notify
        self.referenced.notify(self.referenced.value)
        self._updatePosition()
Beispiel #28
0
    def acquire_roa(self, dataflow):
        """
        Acquire the single field images that resemble the region of acquisition (ROA, megafield image).
        :param dataflow: (model.DataFlow) The dataflow on the detector.
        """

        total_field_time = self._detector.frameDuration.value + 1.5  # there is about 1.5 seconds overhead per field
        # The first field is acquired twice, so the timeout must be at least twice the total field time.
        # Use 5 times the total field time to have a wide margin.
        timeout = 5 * total_field_time + 2

        # Acquire all single field images, which are automatically offloaded to the external storage.
        for field_idx in self._roa.field_indices:
            # Reset the event that waits for the image being received (puts flag to false).
            self._data_received.clear()
            self.field_idx = field_idx
            logging.debug("Acquiring field with index: %s", field_idx)

            self.move_stage_to_next_tile(
            )  # move stage to next field image position

            self.correct_beam_shift(
            )  # correct the shift of the beams caused by the parasitic magnetic field.

            dataflow.next(field_idx)  # acquire the next field image.

            # Wait until single field image data has been received (image_received sets flag to True).
            if not self._data_received.wait(timeout):
                # TODO here we often timeout when actually just the offload queue is full
                #  need to handle offload queue error differently to just wait a bit instead of timing out
                #   -> check if finish megafield is called in finally when hitting here
                raise TimeoutError("Timeout while waiting for field image.")

            self._fields_remaining.discard(field_idx)

            # In case the acquisition was cancelled by a client, before the future returned, raise cancellation error.
            # Note: The acquisition of the current single field image (tile) is still finished though.
            if self._cancelled:
                raise CancelledError()

            # Update the time left for the acquisition.
            expected_time = len(self._fields_remaining) * total_field_time
            self._future.set_progress(start=time.time(),
                                      end=time.time() + expected_time)

        logging.debug("Successfully acquired all fields of ROA.")
Beispiel #29
0
    def exception(self, timeout: int = None):
        start = time.time()
        state, error = self._get_state_and_error()
        while state.is_executing():
            if timeout is not None and (time.time() - start) > timeout:
                raise TimeoutError(
                    f"{self.job_id} did not finish running before timeout of {timeout}s"
                )

            time.sleep(10)
            state, error = self._get_state_and_error()
            logging.info(f"Future for {self.job_id} has state {state}")

        if state.is_cancelled():
            raise CancelledError(f"{self.job_id}: " + error)
        if state is State.FAILED:
            return AipError(f"{self.job_id}: " + error)
Beispiel #30
0
    def _adjustFocus(self, das, i, ix, iy):
        if i % SKIP_TILES != 0:
            logging.debug("Skipping focus adjustment..")
            return das
        try:
            current_focus_level = MeasureOpticalFocus(das[self._streams.index(
                self._focus_stream)])
        except IndexError:
            logging.warning("Failed to get image to measure focus on.")
            return das
        if i == 0:
            # Use initial optical focus level to be compared to next tiles
            # TODO: instead of using the first image, use the best 10% images (excluding outliers)
            self._good_focus_level = current_focus_level

        # TODO: handle the case of _good_focus_level == 0
        logging.debug("Current focus level: %s (good = %s)",
                      current_focus_level, self._good_focus_level)
        # Run autofocus if current focus got worse than permitted deviation
        if abs(current_focus_level - self._good_focus_level
               ) / self._good_focus_level > FOCUS_FIDELITY:
            try:
                self._future.running_subf = AutoFocus(
                    self._focus_stream.detector,
                    self._focus_stream.emitter,
                    self._focus_stream.focuser,
                    good_focus=self._good_focus,
                    rng_focus=self._focus_rng,
                    method=MTD_EXHAUSTIVE)
                self._future.running_subf.result(
                )  # blocks until autofocus is finished
                if self._future._task_state == CANCELLED:
                    raise CancelledError()
            except CancelledError:
                raise
            except Exception as ex:
                logging.exception("Running autofocus failed on image i= %s." %
                                  i)
            else:
                # Reacquire the out of focus tile (which should be corrected now)
                das = self._getTileDAs(i, ix, iy)
        return das