예제 #1
0
    def save_result(self, name, value, group=None, overwrite=True):
        """Save a result to h5 file. Defaults are to save to the active group 
        in the 'results' group and overwrite an existing result.
        Note that the result is saved as an attribute of 'results/group' and
        overwriting attributes causes h5 file size bloat."""
        if self.no_write:
            raise Exception('This run is read-only. '
                            'You can\'t save results to runs through a '
                            'Sequence object. Per-run analysis should be done '
                            'in single-shot analysis routines, in which a '
                            'single Run object is used')
        with h5py.File(self.h5_path, 'a') as h5_file:
            if not group:
                # Save to analysis results group by default
                group = 'results/' + self.group
            elif not group in h5_file:
                # Create the group if it doesn't exist
                h5_file.create_group(group)
            if name in h5_file[group].attrs and not overwrite:
                raise Exception('Attribute %s exists in group %s. ' \
                                'Use overwrite=True to overwrite.' % (name, group))
            set_attributes(h5_file[group], {name: value})

        if spinning_top:
            if self.h5_path not in _updated_data:
                _updated_data[self.h5_path] = {}
            if group.startswith('results'):
                toplevel = group.replace('results/', '', 1)
                _updated_data[self.h5_path][toplevel, name] = value
예제 #2
0
    def transition_to_manual(self):
        if self.h5_filepath is None:
            print('No camera exposures in this shot.\n')
            return True
        assert self.acquisition_thread is not None
        self.acquisition_thread.join(timeout=self.stop_acquisition_timeout)
        if self.acquisition_thread.is_alive():
            msg = """Acquisition thread did not finish. Likely did not acquire expected
                number of images. Check triggering is connected/configured correctly"""
            if self.exception_on_failed_shot:
                self.abort()
                raise RuntimeError(dedent(msg))
            else:
                self.camera.abort_acquisition()
                self.acquisition_thread.join()
                print(dedent(msg), file=sys.stderr)
        self.acquisition_thread = None

        print("Stopping acquisition.")
        self.camera.stop_acquisition()

        print(f"Saving {len(self.images)}/{len(self.exposures)} images.")

        with h5py.File(self.h5_filepath, 'r+') as f:
            # Use orientation for image path, device_name if orientation unspecified
            if self.orientation is not None:
                image_path = 'images/' + self.orientation
            else:
                image_path = 'images/' + self.device_name
            image_group = f.require_group(image_path)
            image_group.attrs['camera'] = self.device_name

            # Save camera attributes to the HDF5 file:
            if self.attributes_to_save is not None:
                set_attributes(image_group, self.attributes_to_save)

            # Whether we failed to get all the expected exposures:
            image_group.attrs['failed_shot'] = len(self.images) != len(
                self.exposures)

            # key the images by name and frametype. Allow for the case of there being
            # multiple images with the same name and frametype. In this case we will
            # save an array of images in a single dataset.
            images = {(exposure['name'], exposure['frametype']): []
                      for exposure in self.exposures}

            # Iterate over expected exposures, sorted by acquisition time, to match them
            # up with the acquired images:
            self.exposures.sort(order='t')
            for image, exposure in zip(self.images, self.exposures):
                images[(exposure['name'], exposure['frametype'])].append(image)

            # Save images to the HDF5 file:
            for (name, frametype), imagelist in images.items():
                data = imagelist[0] if len(imagelist) == 1 else np.array(
                    imagelist)
                print(f"Saving frame(s) {name}/{frametype}.")
                group = image_group.require_group(name)
                dset = group.create_dataset(frametype,
                                            data=data,
                                            dtype='uint16',
                                            compression='gzip')
                # Specify this dataset should be viewed as an image
                dset.attrs['CLASS'] = np.string_('IMAGE')
                dset.attrs['IMAGE_VERSION'] = np.string_('1.2')
                dset.attrs['IMAGE_SUBCLASS'] = np.string_('IMAGE_GRAYSCALE')
                dset.attrs['IMAGE_WHITE_IS_ZERO'] = np.uint8(0)

        # If the images are all the same shape, send them to the GUI for display:
        try:
            image_block = np.stack(self.images)
        except ValueError:
            print(
                "Cannot display images in the GUI, they are not all the same shape"
            )
        else:
            self._send_image_to_parent(image_block)

        self.images = None
        self.n_images = None
        self.attributes_to_save = None
        self.exposures = None
        self.h5_filepath = None
        self.stop_acquisition_timeout = None
        self.exception_on_failed_shot = None
        print("Setting manual mode camera attributes.\n")
        self.set_attributes_smart(self.manual_mode_camera_attributes)
        if self.continuous_dt is not None:
            # If continuous manual mode acquisition was in progress before the bufferd
            # run, resume it:
            self.start_continuous(self.continuous_dt)
        return True
예제 #3
0
    def save_result(self, name, value, group=None, overwrite=True):
        """Save a result to the hdf5 file.

        With the default argument values this method saves to `self.group` in
        the `'/results'` group and overwrites any existing value. Note that the
        result is saved as an attribute and overwriting attributes causes hdf5
        file size bloat.

        Args:
            name (str): The name of the result. This will be the name of the
                attribute added to the hdf5 file's group.
            value (any): The value of the result, which will be saved as the
                value of the hdf5 group's attribute set by `name`. However note
                that when saving large arrays, it is better to use the
                `self.save_result_array()` method which will store the results
                as a dataset in the hdf5 file.
            group (str, optional): The group in the hdf5 file to which the
                result will be saved as an attribute. If set to `None`, then the
                result will be saved to `self.group` in `'/results'`. Note that
                if a value is passed for `group` here then it will NOT have
                `'/result'` prepended to it which allows the caller to save
                results anywhere in the hdf5 file. This is in contrast to using
                the default group set with `self.set_group()`; when the default
                group is set with that method it WILL have `'/results'`
                prepended to it when saving results. Defaults to `None`.
            overwrite (bool, optional): Sets whether or not to overwrite the
                previous value if the attribute already exists. If set to
                `False` and the attribute already exists, a `PermissionError` is
                raised. Defaults to `True`.

        Raises:
            PermissionError: A `PermissionError` is raised if `self.no_write` is
                `True` because saving the result would edit the file.
            ValueError: A `ValueError` is raised if `self.group` is `None` and
                no value is provided for `group` because the method then doesn't
                know where to save the result.
            PermissionError: A `PermissionError` is raised if an attribute with
                name `name` already exists but `overwrite` is set to `False`.
        """
        if self.no_write:
            msg = "Cannot save result; this instance is read-only."
            raise PermissionError(msg)
        with h5py.File(self.h5_path, 'a') as h5_file:
            if not group:
                if self.group is None:
                    msg = """Cannot save result; no default group set. Either
                        specify a value for this method's optional group
                        argument, or set a default value using the set_group()
                        method."""
                    raise ValueError(dedent(msg))
                # Save to analysis results group by default
                group = 'results/' + self.group
            elif not group in h5_file:
                # Create the group if it doesn't exist
                h5_file.create_group(group)
            if name in h5_file[group].attrs and not overwrite:
                msg = """Cannot save result; group '{group}' already has
                    attribute '{name}' and overwrite is set to False. Set
                    overwrite=True to overwrite the existing value.""".format(
                    group=group,
                    name=name,
                )
                raise PermissionError(dedent(msg))
            set_attributes(h5_file[group], {name: value})

        if spinning_top:
            if self.h5_path not in _updated_data:
                _updated_data[self.h5_path] = {}
            if group.startswith('results'):
                toplevel = group.replace('results/', '', 1)
                _updated_data[self.h5_path][toplevel, name] = value