Exemplo n.º 1
0
    def add_circle(self, stage_name, index, circle):
        """
        Add a circle to the list of circles.

        The most outer circle should be at index 0.

        :param stage_name: supported stage name, 'sample' or 'detector'
        :param index: index where to put the circle in the list
        :param circle: valid circle in {'x+', 'x-', 'y+', 'y-', 'z+', 'z-'}.
         + for a counter-clockwise rotation, - for a clockwise rotation.
        """
        self.valid_name(stage_name)
        nb_circles = len(self.__getattribute__(self.valid_names[stage_name]))
        valid.valid_item(
            index,
            allowed_types=int,
            min_included=0,
            max_included=nb_circles,
            name="index",
        )
        if circle not in self.valid_circles:
            raise ValueError(f"{circle} is not in the list of valid circles:"
                             f" {list(self.valid_circles)}")
        self.__getattribute__(self.valid_names[stage_name]).insert(
            index, circle)
Exemplo n.º 2
0
    def _saturation_correction(self, data, mask, nb_frames):
        """
        Mask pixels above a certain threshold.

        This is detector dependent. If a 2D frames was obtained by summing a series of
        frames (e.g. series measurement at P10), the threshold is multiplied
        accordingly.

        :param data: a 2D numpy array
        :param mask: a 2D numpy array of the same shape as data
        :param nb_frames: int, number of frames concatenated to obtain the 2D data array
        :return:

         - the masked data
         - the updated mask

        """
        if self.saturation_threshold is not None:
            valid.valid_ndarray((data, mask), ndim=2)

            valid.valid_item(nb_frames,
                             allowed_types=int,
                             min_excluded=0,
                             name="nb_frames")
            mask[data > self.saturation_threshold * nb_frames] = 1
            data[data > self.saturation_threshold * nb_frames] = 0
        return data, mask
Exemplo n.º 3
0
 def scan_number(self, value):
     valid.valid_item(
         value,
         allowed_types=int,
         min_included=1,
         allow_none=True,
         name="scan_number",
     )
     self._scan_number = value
Exemplo n.º 4
0
def create_roi(dic: Dict[str, Any]) -> Any:
    """
    Load "roi_detector" from the dictionary of parameters and update it.

    If the keys "center_roi_x" or "center_roi_y" are defined, it will consider that the
    current values in roi_detector define a window around the Bragg peak position and
    the final output will be:
    [center_roi_y - roi_detector[0], center_roi_y + roi_detector[1],
    center_roi_x - roi_detector[2], center_roi_x + roi_detector[3]].

    If a key is not defined, it will consider that the values of roi_detector are
    absolute pixels positions, e.g. if only "center_roi_y" is defined, the output will
    be:
    [center_roi_y - roi_detector[0], center_roi_y + roi_detector[1],
    roi_detector[2], roi_detector[3]].

    Accordingly, if none of the keys are defined, the output will be:
    [roi_detector[0], roi_detector[1], roi_detector[2], roi_detector[3]].

    :param dic: a dictionary of parameters
    :return: the calculated region of interest [Vstart, Vstop, Hstart, Hstop] or None
    """
    valid.valid_container(dic, container_types=dict, name="dic")
    roi = dic.get("roi_detector")
    valid.valid_container(
        roi,
        container_types=(tuple, list, np.ndarray),
        length=4,
        item_types=int,
        allow_none=True,
        name="roi_detector",
    )

    # update the ROI
    if roi is not None:
        center_roi_y = dic.get("center_roi_y")
        if center_roi_y is not None:
            valid.valid_item(center_roi_y,
                             allowed_types=int,
                             name="center_roi_y")
            roi[0] = center_roi_y - roi[0]
            roi[1] = center_roi_y + roi[1]

        center_roi_x = dic.get("center_roi_x")
        if center_roi_x is not None:
            valid.valid_item(center_roi_x,
                             allowed_types=int,
                             name="center_roi_x")
            roi[2] = center_roi_x - roi[2]
            roi[3] = center_roi_x + roi[3]
    return roi
Exemplo n.º 5
0
    def remove_circle(self, stage_name, index):
        """
        Remove the circle at index from the list of sample circles.

        :param stage_name: supported stage name, 'sample' or 'detector'
        :param index: index of the circle to be removed from the list
        """
        if stage_name not in self.valid_names:
            raise NotImplementedError(
                f"'{stage_name}' is not implemented,"
                f" available are {list(self.valid_names.keys())}")
        nb_circles = len(self.__getattribute__(self.valid_names[stage_name]))
        if nb_circles > 0:
            valid.valid_item(
                index,
                allowed_types=int,
                min_included=0,
                max_included=nb_circles - 1,
                name="index",
            )
            del self.__getattribute__(self.valid_names[stage_name])[index]
Exemplo n.º 6
0
    def __init__(self, name, **kwargs):

        self.custom_pixelsize = kwargs.get("custom_pixelsize")
        valid.valid_item(
            self.custom_pixelsize,
            allowed_types=Real,
            min_excluded=0,
            allow_none=True,
            name="custom_pixelsize",
        )
        self.custom_pixelnumber = kwargs.get("custom_pixelnumber")
        if isinstance(self.custom_pixelnumber, np.ndarray):
            self.custom_pixelnumber = list(self.custom_pixelnumber)
        valid.valid_container(
            self.custom_pixelnumber,
            container_types=(list, tuple),
            length=2,
            item_types=Integral,
            min_excluded=0,
            allow_none=True,
            name="custom_pixelnumber",
        )
        super().__init__(name=name, **kwargs)
Exemplo n.º 7
0
 def test_validitem_min_included_valid(self):
     self.assertTrue(
         valid.valid_item(value=1, allowed_types=Real, min_included=0))
Exemplo n.º 8
0
    item_types=Real,
    min_excluded=0,
    name=valid_name,
)

valid.valid_container(
    padding_shape,
    container_types=(tuple, list, np.ndarray),
    item_types=int,
    min_excluded=0,
    length=3,
    name=valid_name,
)

valid.valid_item(
    peak_value, allowed_types=Real, min_excluded=0, allow_none=True, name=valid_name
)

valid.valid_container(
    (
        load_qvalues,
        flip_phase,
        save_qyqz,
        save_qyqx,
        save_qzqx,
        save_sum,
        debug,
        grey_background,
    ),
    container_types=tuple,
    item_types=bool,
Exemplo n.º 9
0
markers = ('.', 'v', '^', '<', '>', 'x', '+', 'o')  # for plots
mpl.rcParams['axes.linewidth'] = tick_width  # set the linewidth globally
validation_name = 'bcdi_blurring_function'

#########################
# check some parameters #
#########################
if not datadir.endswith('/'):
    datadir += '/'
savedir = savedir or datadir
if not savedir.endswith('/'):
    savedir += '/'
pathlib.Path(savedir).mkdir(parents=True, exist_ok=True)
valid.valid_item(isosurface_threshold,
                 allowed_types=Real,
                 min_included=0,
                 max_excluded=1,
                 name=validation_name)
valid.valid_container(phasing_shape,
                      container_types=(tuple, list, np.ndarray),
                      allow_none=True,
                      item_types=int,
                      min_excluded=0,
                      name=validation_name)
valid.valid_item(value=upsampling_factor,
                 allowed_types=int,
                 min_included=1,
                 name=validation_name)
valid.valid_container(comment, container_types=str, name=validation_name)
if len(comment) != 0 and not comment.startswith('_'):
    comment = '_' + comment
Exemplo n.º 10
0
def reload_cdi_data(
    data,
    mask,
    scan_number,
    setup,
    normalize_method="skip",
    debugging=False,
    **kwargs,
):
    """
    Reload forward CDI data, apply optional threshold, normalization and binning.

    :param data: the 3D data array
    :param mask: the 3D mask array
    :param scan_number: the scan number to load
    :param setup: an instance of the class Setup
    :param normalize_method: 'skip' to skip, 'monitor'  to normalize by the default
     monitor, 'sum_roi' to normalize by the integrated intensity in a defined region
     of interest
    :param debugging:  set to True to see plots
    :parama kwargs:
     - 'photon_threshold' = float, photon threshold to apply before binning

    :return:
     - the updated 3D data and mask arrays
     - the monitor values used for the intensity normalization

    """
    valid.valid_ndarray(arrays=(data, mask), ndim=3)
    # check and load kwargs
    valid.valid_kwargs(
        kwargs=kwargs,
        allowed_kwargs={"photon_threshold"},
        name="kwargs",
    )
    photon_threshold = kwargs.get("photon_threshold", 0)
    valid.valid_item(
        photon_threshold,
        allowed_types=Real,
        min_included=0,
        name="photon_threshold",
    )

    nbz, nby, nbx = data.shape
    frames_logical = np.ones(nbz)

    print((data < 0).sum(), " negative data points masked"
          )  # can happen when subtracting a background
    mask[data < 0] = 1
    data[data < 0] = 0

    # normalize by the incident X-ray beam intensity
    if normalize_method == "skip":
        print("Skip intensity normalization")
        monitor = []
    else:
        if normalize_method == "sum_roi":
            monitor = data[:,
                           setup.detector.sum_roi[0]:setup.detector.sum_roi[1],
                           setup.detector.sum_roi[2]:setup.detector.
                           sum_roi[3], ].sum(axis=(1, 2))
        else:  # use the default monitor of the beamline
            monitor = setup.loader.read_monitor(
                scan_number=scan_number,
                setup=setup,
            )

        print("Intensity normalization using " + normalize_method)
        data, monitor = loader.normalize_dataset(
            array=data,
            monitor=monitor,
            norm_to_min=True,
            savedir=setup.detector.savedir,
            debugging=True,
        )

    # pad the data to the shape defined by the ROI
    if (setup.detector.roi[1] - setup.detector.roi[0] > nby
            or setup.detector.roi[3] - setup.detector.roi[2] > nbx):
        start = (
            0,
            max(0, abs(setup.detector.roi[0])),
            max(0, abs(setup.detector.roi[2])),
        )
        print("Paddind the data to the shape defined by the ROI")
        data = util.crop_pad(
            array=data,
            pad_start=start,
            output_shape=(
                data.shape[0],
                setup.detector.roi[1] - setup.detector.roi[0],
                setup.detector.roi[3] - setup.detector.roi[2],
            ),
        )
        mask = util.crop_pad(
            array=mask,
            pad_value=1,
            pad_start=start,
            output_shape=(
                mask.shape[0],
                setup.detector.roi[1] - setup.detector.roi[0],
                setup.detector.roi[3] - setup.detector.roi[2],
            ),
        )

    # apply optional photon threshold before binning
    if photon_threshold != 0:
        mask[data < photon_threshold] = 1
        data[data < photon_threshold] = 0
        print("Applying photon threshold before binning: < ", photon_threshold)

    # bin data and mask in the detector plane if needed
    # binning in the stacking dimension is done at the very end of the data processing
    if (setup.detector.binning[1] != 1) or (setup.detector.binning[2] != 1):
        print(
            "Binning the data: detector vertical axis by",
            setup.detector.binning[1],
            ", detector horizontal axis by",
            setup.detector.binning[2],
        )
        data = util.bin_data(
            data,
            (1, setup.detector.binning[1], setup.detector.binning[2]),
            debugging=debugging,
        )
        mask = util.bin_data(
            mask,
            (1, setup.detector.binning[1], setup.detector.binning[2]),
            debugging=debugging,
        )
        mask[np.nonzero(mask)] = 1

    return data, mask, frames_logical, monitor
Exemplo n.º 11
0
def partial_coherence_rl(measured_intensity,
                         coherent_intensity,
                         iterations=20,
                         debugging=False,
                         **kwargs):
    """
    Partial coherence deconvolution using Richardson-Lucy algorithm. See J.N. Clark et al., Nat. Comm. 3, 993 (2012).

    :param measured_intensity: measured object with partial coherent illumination
    :param coherent_intensity: estimate of the object measured by a fully coherent illumination
    :param iterations: number of iterations for the Richardson-Lucy algorithm
    :param debugging: True to see plots
    :param kwargs:
     - 'scale': scale for the plot, 'linear' or 'log'
     - 'reciprocal_space': True if the data is in reciprocal space, False otherwise.
     - 'is_orthogonal': set to True is the frame is orthogonal, False otherwise (detector frame) Used for plot labels.
     - 'vmin' = lower boundary for the colorbar. Float or tuple of 3 floats
     - 'vmax' = [higher boundary for the colorbar. Float or tuple of 3 floats
     - 'guess': ndarray, initial guess for the psf, of the same shape as measured_intensity
    :return: the retrieved psf (ndarray), the error metric (1D ndarray of len=iterations)
    """
    validation_name = 'algorithms_utils.psf_rl'
    # check and load kwargs
    valid.valid_kwargs(kwargs=kwargs,
                       allowed_kwargs={
                           'scale', 'reciprocal_space', 'is_orthogonal',
                           'vmin', 'vmax', 'guess'
                       },
                       name=validation_name)
    scale = kwargs.get('scale', 'log')
    if scale not in {'log', 'linear'}:
        raise ValueError('"scale" should be either "log" or "linear"')
    reciprocal_space = kwargs.get('reciprocal_space', True)
    if not isinstance(reciprocal_space, bool):
        raise TypeError('"reciprocal_space" should be a boolean')
    is_orthogonal = kwargs.get('is_orthogonal', True)
    if not isinstance(is_orthogonal, bool):
        raise TypeError('"is_orthogonal" should be a boolean')
    vmin = kwargs.get('vmin', np.nan)
    valid.valid_item(vmin, allowed_types=Real, name=validation_name)
    vmax = kwargs.get('vmax', np.nan)
    valid.valid_item(vmax, allowed_types=Real, name=validation_name)
    guess = kwargs.get('guess', None)
    if guess is not None:
        if not isinstance(guess, np.ndarray):
            raise TypeError(f"guess should be a ndarray, got {type(guess)}")
        if guess.shape != measured_intensity.shape:
            raise ValueError(
                'the guess array should have the same shape as measured_intensity'
            )

    # calculate the psf
    psf, error = richardson_lucy(image=measured_intensity,
                                 psf=coherent_intensity,
                                 iterations=iterations,
                                 clip=False,
                                 guess=guess)

    # optional plot
    if debugging:
        gu.multislices_plot(psf,
                            scale=scale,
                            sum_frames=False,
                            title='psf',
                            vmin=vmin,
                            vmax=vmax,
                            reciprocal_space=reciprocal_space,
                            is_orthogonal=is_orthogonal,
                            plot_colorbar=True)
        _, ax = plt.subplots(figsize=(12, 9))
        ax.plot(error, 'r.')
        ax.set_yscale('log')
        ax.set_xlabel('iteration number')
        ax.set_ylabel('difference between consecutive iterates')
    return psf, error
Exemplo n.º 12
0
            f"Incorrect setting {strain_range} " 'for the parameter "strain_range"'
        )
    strain_min, strain_max = -np.inf, np.inf
else:
    strain_min, strain_max = -1 * strain_range, strain_range

if not isinstance(phase_range, Real):
    if phase_range != "minmax":
        raise ValueError(
            f"Incorrect setting {phase_range} " 'for the parameter "phase_range"'
        )
    phase_min, phase_max = -np.inf, np.inf
else:
    phase_min, phase_max = -1 * phase_range, phase_range

valid.valid_item(xmin_histo, allowed_types=Real, min_included=0, name="xmin_histo")
valid.valid_container(
    obj=vline_hist,
    container_types=(list, tuple, np.ndarray, set),
    min_excluded=0,
    allow_none=True,
    item_types=Real,
    name="vline_hist",
)

if amp_histogram_Yaxis == "linear":
    valid.valid_container(
        ylim_histo,
        container_types=(tuple, list, np.ndarray),
        item_types=Real,
        length=2,
Exemplo n.º 13
0
ideally the first mode should be as high as possible. Adapted from PyNX.
"""

datadir = "D:/data/P10_August2020_CDI/data/mag_3_macro1/centrosym/"
user_comment = ''  # string, should start with "_"
nb_mode = 1  # number of modes to return in the mode array
alignment_method = 'support'  # 'modulus' or 'support'
# if 'modulus', use the center of mass of the modulus. If 'support', use the center of mass of a support object defined
# by support_threshold
support_threshold = 0.2  # threshold on the normalized modulus to define the support if alignement_method is 'support'
debug = True  # True to see debugging plots
#########################
# check some parameters #
#########################
valid.valid_container(user_comment, container_types=str, name='modes_decomposition')
valid.valid_item(value=nb_mode, allowed_types=int, min_excluded=0, name='modes_decomposition')
valid.valid_item(value=support_threshold, allowed_types=Real, min_included=0, name='modes_decomposition')
if alignment_method not in {'modulus', 'support'}:
    raise ValueError(f'wrong value for alignment_method {alignment_method}, allowed are "support" and "modulus"')
valid.valid_item(value=debug, allowed_types=bool, name='modes_decomposition')

################
# Load objects #
################
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilenames(initialdir=datadir,
                                        filetypes=[("CXI", "*.cxi"), ("NPZ", "*.npz"),
                                                   ("NPY", "*.npy"), ("HDF5", "*.h5")])
nbfiles = len(file_path)
print('Loading ', nbfiles, 'objects')
Exemplo n.º 14
0
##################################

#############################
# define default parameters #
#############################
colors = ('b', 'g', 'r', 'c', 'm', 'y', 'k')  # for plots
markers = ('.', 'v', '^', '<', '>', 'x', '+', 'o')  # for plots
mpl.rcParams['axes.linewidth'] = tick_width  # set the linewidth globally
validation_name = 'compare_CDI_SEM'

#########################
# check some parameters #
#########################
valid.valid_item(value=index_sem,
                 allowed_types=int,
                 min_included=0,
                 allow_none=True,
                 name=validation_name)
valid.valid_container(plot_sem, container_types=str, name=validation_name)
if plot_sem not in {'single', 'fill'}:
    raise ValueError("allowed values for plot_sem are 'single' and 'all'")
valid.valid_container(comment, container_types=str, name=validation_name)
if len(comment) != 0 and not comment.startswith('_'):
    comment = '_' + comment

savedir = savedir or datadir
pathlib.Path(savedir).mkdir(parents=True, exist_ok=True)

########################
# load the SEM profile #
########################
Exemplo n.º 15
0
 def test_validitem_max_included_equal(self):
     self.assertTrue(
         valid.valid_item(value=0, allowed_types=Real, max_included=0))
Exemplo n.º 16
0
 def test_validitem_max_excluded_valid(self):
     self.assertTrue(
         valid.valid_item(value=1, allowed_types=Real, max_excluded=2))
Exemplo n.º 17
0
 def angle(self, value):
     valid.valid_item(value, allowed_types=Real, name="value")
     if np.isnan(value):
         raise ValueError("value is a nan")
     self._angle = value
Exemplo n.º 18
0
#########################
valid_name = "bcdi_view_psf"
savedir = savedir or datadir
pathlib.Path(savedir).mkdir(parents=True, exist_ok=True)
if width is not None and isinstance(width, Real):
    width = (width,) * 3
valid.valid_container(
    width,
    container_types=(tuple, list, np.ndarray),
    length=3,
    item_types=int,
    min_excluded=0,
    allow_none=True,
    name=valid_name,
)
valid.valid_item(vmin, allowed_types=Real, name=valid_name)
valid.valid_item(vmax, allowed_types=Real, name=valid_name)
valid.valid_item(tick_length, allowed_types=int, min_excluded=0, name=valid_name)
valid.valid_item(tick_width, allowed_types=int, min_excluded=0, name=valid_name)
valid.valid_item(linewidth, allowed_types=int, min_excluded=0, name=valid_name)
valid.valid_item(plot_mcf, allowed_types=bool, name=valid_name)
valid.valid_item(save_slices, allowed_types=bool, name=valid_name)
valid.valid_item(is_orthogonal, allowed_types=bool, name=valid_name)
if tick_direction not in {"out", "in", "inout"}:
    raise ValueError("allowed values for tick_direction: 'out', 'in', 'inout'")

if is_orthogonal:
    title = "log(psf) in laboratory frame"
else:
    title = "log(psf) in detector frame"
Exemplo n.º 19
0
def valid_param(key: str, value: Any) -> Tuple[Any, bool]:
    """
    Validate a key value pair corresponding to an input parameter.

    It will raise an exception if the check fails.

    :param key: name of the parameter
    :param value: the value of the parameter
    :return: a tuple (formatted_value, is_valid). is_valid is True if the key
     is valid, False otherwise.
    """
    is_valid = True
    allowed: Any = None

    # convert 'None' to None
    if value == "None":
        value = None

    # convert 'True' to True
    if isinstance(value, str) and value.lower() == "true":
        value = True

    # convert 'False' to False
    if isinstance(value, str) and value.lower() == "false":
        value = False

    # test the booleans first
    if key in {
            "align_axis",
            "align_q",
            "apodize",
            "bin_during_loading",
            "correct_refraction",
            "custom_scan",
            "debug",
            "flag_interact",
            "flip_reconstruction",
            "get_temperature",
            "grey_background",
            "invert_phase",
            "is_series",
            "keep_size",
            "mask_zero_event",
            "reload_orthogonal",
            "reload_previous",
            "save",
            "save_as_int",
            "save_rawdata",
            "save_support",
            "save_to_mat",
            "save_to_npz",
            "save_to_vti",
            "simulation",
            "use_rawdata",
    }:
        valid.valid_item(value, allowed_types=bool, name=key)
    elif key == "absorption":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "actuators":
        valid.valid_container(value,
                              container_types=dict,
                              allow_none=True,
                              name=key)
    elif key == "apodization_alpha":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=Real,
            min_included=0,
            name=key,
        )
        value = np.asarray(value)
    elif key == "apodization_mu":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=Real,
            min_included=0,
            name=key,
        )
        value = np.asarray(value)
    elif key == "apodization_sigma":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=Real,
            min_included=0,
            name=key,
        )
        value = np.asarray(value)
    elif key == "apodization_window":
        allowed = {"blackman", "tukey", "normal"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "averaging_space":
        allowed = {"reciprocal_space", "direct_space"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "axis_to_align":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=Real,
            name=key,
        )
        value = np.asarray(value)
    elif key == "backend":
        allowed = {
            "Agg", "Qt5Agg", "module://matplotlib_inline.backend_inline"
        }
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "background_file":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              allow_none=True,
                              name=key)
    elif key == "background_plot":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              name=key)
    elif key == "beam_direction":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=Real,
            name=key,
        )
        value = np.asarray(value)
    elif key == "beamline":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              name=key)
    elif key == "bragg_peak":
        valid.valid_container(
            value,
            container_types=(tuple, list),
            item_types=Real,
            min_included=0,
            length=3,
            allow_none=True,
            name=key,
        )
    elif key == "cch1":
        valid.valid_item(value, allowed_types=Real, name=key)
    elif key == "cch2":
        valid.valid_item(value, allowed_types=Real, name=key)
    elif key == "center_fft":
        allowed = {
            "crop_sym_ZYX",
            "crop_asym_ZYX",
            "pad_asym_Z_crop_sym_YX",
            "pad_sym_Z_crop_asym_YX",
            "pad_sym_Z",
            "pad_asym_Z",
            "pad_sym_ZYX",
            "pad_asym_ZYX",
            "skip",
        }
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "centering_method":
        allowed = {"com", "max", "max_com", "do_nothing"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "center_roi_x":
        valid.valid_item(value, allowed_types=int, allow_none=True, name=key)
    elif key == "center_roi_y":
        valid.valid_item(value, allowed_types=int, allow_none=True, name=key)
    elif key == "colormap":
        if value not in ["turbo", "custom"] and value not in cc.cm:
            raise ValueError(f"unknow colormap '{value}'")
    elif key == "comment":
        valid.valid_container(value, container_types=str, name=key)
        if value and not value.startswith("_"):
            value += "_"
    elif key == "config_file":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              name=key)
        if not os.path.isfile(value):
            raise ValueError(f"The file {value} does not exist")
    elif key == "correlation_threshold":
        valid.valid_item(value,
                         allowed_types=Real,
                         min_included=0,
                         max_included=1,
                         name=key)
    elif key == "custom_images":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            item_types=int,
            min_included=0,
            allow_none=True,
            name=key,
        )
    elif key == "custom_monitor":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            item_types=Real,
            min_included=0,
            allow_none=True,
            name=key,
        )
    elif key == "custom_motors":
        valid.valid_container(value,
                              container_types=dict,
                              allow_none=True,
                              name=key)
    elif key == "custom_pixelsize":
        valid.valid_item(value,
                         allowed_types=Real,
                         min_excluded=0,
                         allow_none=True,
                         name=key)
    elif key == "data_dir":
        if value is not None:
            valid.valid_container(value,
                                  container_types=str,
                                  min_length=1,
                                  name=key)
            if not os.path.isdir(value):
                raise ValueError(f"The directory {value} does not exist")
    elif key == "data_frame":
        allowed = {"detector", "crystal", "laboratory"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "dirbeam_detector_angles":
        valid.valid_container(
            value,
            container_types=(list, tuple),
            item_types=Real,
            length=2,
            allow_none=True,
            name=key,
        )
    elif key == "direct_beam":
        valid.valid_container(
            value,
            container_types=(list, tuple),
            item_types=Real,
            length=2,
            allow_none=True,
            name=key,
        )
    elif key == "detector":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              name=key)
    elif key == "detrot":
        valid.valid_item(value, allowed_types=Real, name=key)
    elif key == "dispersion":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "energy":
        if value is None or isinstance(value, Number):
            valid.valid_item(value,
                             allowed_types=Real,
                             min_excluded=0,
                             allow_none=True,
                             name=key)
        else:
            valid.valid_container(
                value,
                container_types=(tuple, list, np.ndarray),
                min_length=1,
                item_types=Real,
                min_excluded=0,
                name=key,
            )
    elif key == "fill_value_mask":
        allowed = (0, 1)
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "fix_size":
        valid.valid_container(
            value,
            container_types=(tuple, list),
            length=6,
            item_types=int,
            allow_none=True,
            name=key,
        )
    elif key == "fix_voxel":
        valid.valid_item(value,
                         allowed_types=Real,
                         min_excluded=0,
                         allow_none=True,
                         name=key)
    elif key == "flatfield_file":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              allow_none=True,
                              name=key)
    elif key == "frames_pattern":
        if value is not None:
            value = np.asarray(value)
            valid.valid_1d_array(value,
                                 allow_none=False,
                                 allowed_values={0, 1},
                                 name=key)
    elif key == "half_width_avg_phase":
        valid.valid_item(value, allowed_types=int, min_included=0, name=key)
    elif key == "hotpixels_file":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              allow_none=True,
                              name=key)
    elif key == "inplane_angle":
        valid.valid_item(value, allowed_types=Real, allow_none=True, name=key)
    elif key == "interpolation_method":
        allowed = {"xrayutilities", "linearization"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "isosurface_strain":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "linearity_func":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=5,
            item_types=Real,
            allow_none=True,
            name=key,
        )
    elif key == "median_filter":
        allowed = {"median", "interp_isolated", "mask_isolated", "skip"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "median_filter_order":
        valid.valid_item(value, allowed_types=int, min_included=0, name=key)
    elif key == "normalize_flux":
        allowed = {"monitor", "skip"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "offset_inplane":
        valid.valid_item(value, allowed_types=Real, name=key)
    elif key == "offset_method":
        allowed = {"com", "mean"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "optical_path_method":
        allowed = {"threshold", "defect"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "original_size":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=int,
            min_excluded=0,
            allow_none=True,
            name=key,
        )
    elif key == "outofplane_angle":
        valid.valid_item(value, allowed_types=Real, allow_none=True, name=key)
    elif key == "output_size":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=int,
            min_excluded=0,
            allow_none=True,
            name=key,
        )
    elif key == "pad_size":
        valid.valid_container(
            value,
            container_types=(tuple, list),
            length=3,
            item_types=int,
            allow_none=True,
            name=key,
        )
    elif key == "phase_offset":
        valid.valid_item(value, allowed_types=Real, allow_none=True, name=key)
    elif key == "phase_offset_origin":
        valid.valid_item(value, allowed_types=Real, allow_none=True, name=key)
    elif key == "phase_ramp_removal":
        allowed = {"gradient", "upsampling"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "phase_range":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "phasing_binning":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=int,
            min_excluded=0,
            name=key,
        )
    elif key == "photon_filter":
        allowed = {"loading", "postprocessing"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "photon_threshold":
        valid.valid_item(value, allowed_types=Real, min_included=0, name=key)
    elif key == "preprocessing_binning":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=int,
            min_excluded=0,
            name=key,
        )
    elif key == "reconstruction_file":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              allow_none=True,
                              name=key)
        if value is not None and not os.path.isfile(value):
            raise ValueError(f"The file {value} does not exist")
    elif key in {"ref_axis_q", "ref_axis"}:
        allowed = {"x", "y", "z"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "reference_spacing":
        valid.valid_item(value,
                         allowed_types=Real,
                         min_included=0,
                         allow_none=True,
                         name=key)
    elif key == "reference_temperature":
        valid.valid_item(value,
                         allowed_types=Real,
                         min_included=0,
                         allow_none=True,
                         name=key)
    elif key == "reflection":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=Real,
            name=key,
        )
        value = np.asarray(value)
    elif key == "rocking_angle":
        allowed = {"outofplane", "inplane", "energy"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "roi_detector":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=4,
            item_types=int,
            allow_none=True,
            name=key,
        )
    elif key == "roll_modes":
        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=3,
            item_types=int,
            name=key,
        )
    elif key == "root_folder":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              name=key)
        if not os.path.isdir(value):
            raise ValueError(f"The directory {value} does not exist")
    elif key == "sample_inplane":
        valid.valid_container(
            value,
            container_types=(tuple, list),
            length=3,
            item_types=Real,
            name=key,
        )
    elif key == "sample_name":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              name=key)
    elif key == "sample_offsets":
        valid.valid_container(value,
                              container_types=(tuple, list, np.ndarray),
                              allow_none=True,
                              name=key)
    elif key == "sample_outofplane":
        valid.valid_container(
            value,
            container_types=(tuple, list),
            length=3,
            item_types=Real,
            name=key,
        )
    elif key == "save_dir":
        valid.valid_container(value,
                              container_types=str,
                              min_length=1,
                              allow_none=True,
                              name=key)
        if isinstance(value, str) and not value.endswith("/"):
            value += "/"
    elif key == "save_frame":
        allowed = {"laboratory", "crystal", "lab_flat_sample"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "scan":
        valid.valid_item(value, allowed_types=int, min_included=0, name=key)
    elif key == "scans":
        if isinstance(value, Real):
            value = (value, )
        valid.valid_container(value,
                              container_types=(tuple, list, np.ndarray),
                              min_length=1,
                              name=key)

    elif key == "sdd":
        valid.valid_item(value,
                         allowed_types=Real,
                         min_excluded=0,
                         allow_none=True,
                         name=key)
    elif key == "sort_method":
        allowed = {"mean_amplitude", "variance", "variance/mean", "volume"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "specfile_name":
        valid.valid_container(value,
                              container_types=str,
                              allow_none=True,
                              name=key)
    elif key == "strain_method":
        allowed = {"default", "defect"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "strain_range":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "template_imagefile":
        valid.valid_container(value,
                              container_types=str,
                              min_length=0,
                              allow_none=True,
                              name=key)
    elif key == "threshold_gradient":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "threshold_unwrap_refraction":
        valid.valid_item(value, allowed_types=Real, min_included=0, name=key)
    elif key == "tick_direction":
        allowed = {"out", "in", "inout"}
        if value not in allowed:
            raise ParameterError(key, value, allowed)
    elif key == "tick_length":
        valid.valid_item(value, allowed_types=int, min_included=1, name=key)
    elif key == "tick_spacing":
        valid.valid_item(value, allowed_types=Real, min_excluded=0, name=key)
    elif key == "tick_width":
        valid.valid_item(value, allowed_types=int, min_included=1, name=key)
    elif key == "tilt_angle":
        valid.valid_item(value, allowed_types=Real, allow_none=True, name=key)
    elif key == "tiltazimuth":
        valid.valid_item(value, allowed_types=Real, name=key)
    elif key == "tilt_detector":
        valid.valid_item(value, allowed_types=Real, name=key)
    else:
        # this key is not in the known parameters
        is_valid = False

    return value, is_valid
Exemplo n.º 20
0
def load_cdi_data(
    scan_number,
    setup,
    bin_during_loading=False,
    flatfield=None,
    hotpixels=None,
    background=None,
    normalize="skip",
    debugging=False,
    **kwargs,
):
    """
    Load forward CDI data and preprocess it.

    It applies beam stop correction and an optional photon threshold, normalization
    and binning.

    :param scan_number: the scan number to load
    :param setup: an instance of the class Setup
    :param bin_during_loading: True to bin the data during loading (faster)
    :param flatfield: the 2D flatfield array
    :param hotpixels: the 2D hotpixels array. 1 for a hotpixel, 0 for normal pixels.
    :param background: the 2D background array to subtract to the data
    :param normalize: 'skip' to skip, 'monitor'  to normalize by the default monitor,
     'sum_roi' to normalize by the integrated intensity in the region of interest
     defined by detector.sum_roi
    :param debugging:  set to True to see plots
    :param kwargs:
     - 'photon_threshold': float, photon threshold to apply before binning
     - 'frames_pattern': 1D array of int, of length data.shape[0]. If
       frames_pattern is 0 at index, the frame at data[index] will be skipped,
       if 1 the frame will added to the stack.

    :return:
     - the 3D data and mask arrays
     - frames_logical: array of initial length the number of measured frames.
       In case of padding the length changes. A frame whose index is set to 1 means
       that it is used, 0 means not used, -1 means padded (added) frame.
     - the monitor values used for the intensity normalization

    """
    valid.valid_item(bin_during_loading,
                     allowed_types=bool,
                     name="bin_during_loading")
    # check and load kwargs
    valid.valid_kwargs(
        kwargs=kwargs,
        allowed_kwargs={"photon_threshold", "frames_pattern"},
        name="kwargs",
    )
    photon_threshold = kwargs.get("photon_threshold", 0)
    valid.valid_item(
        photon_threshold,
        allowed_types=Real,
        min_included=0,
        name="photon_threshold",
    )
    frames_pattern = kwargs.get("frames_pattern")
    valid.valid_1d_array(frames_pattern,
                         allow_none=True,
                         allowed_values={0, 1},
                         name="frames_pattern")

    rawdata, rawmask, monitor, frames_logical = setup.loader.load_check_dataset(
        scan_number=scan_number,
        setup=setup,
        frames_pattern=frames_pattern,
        bin_during_loading=bin_during_loading,
        flatfield=flatfield,
        hotpixels=hotpixels,
        background=background,
        normalize=normalize,
        debugging=debugging,
    )

    #################################
    # apply the beamstop correction #
    #################################
    rawdata = beamstop_correction(data=rawdata,
                                  setup=setup,
                                  debugging=debugging)

    #####################################################
    # apply an optional photon threshold before binning #
    #####################################################
    if photon_threshold != 0:
        rawmask[rawdata < photon_threshold] = 1
        rawdata[rawdata < photon_threshold] = 0
        print("Applying photon threshold before binning: < ", photon_threshold)

    ####################################################################################
    # bin data and mask in the detector plane if not already done during loading       #
    # binning in the stacking dimension is done at the very end of the data processing #
    ####################################################################################
    if not bin_during_loading and ((setup.detector.binning[1] != 1) or
                                   (setup.detector.binning[2] != 1)):
        print(
            "Binning the data: detector vertical axis by",
            setup.detector.binning[1],
            ", detector horizontal axis by",
            setup.detector.binning[2],
        )
        rawdata = util.bin_data(
            rawdata,
            (1, setup.detector.binning[1], setup.detector.binning[2]),
            debugging=False,
        )
        rawmask = util.bin_data(
            rawmask,
            (1, setup.detector.binning[1], setup.detector.binning[2]),
            debugging=False,
        )
        rawmask[np.nonzero(rawmask)] = 1

    ################################################
    # pad the data to the shape defined by the ROI #
    ################################################
    rawdata, rawmask = util.pad_from_roi(
        arrays=(rawdata, rawmask),
        roi=setup.detector.roi,
        binning=setup.detector.binning[1:],
        pad_value=(0, 1),
    )

    return rawdata, rawmask, frames_logical, monitor
Exemplo n.º 21
0
 def test_validitem_allowedtypes_bool(self):
     self.assertTrue(valid.valid_item(value=True, allowed_types=bool))
Exemplo n.º 22
0
                    min_included=0,
                    name=validation_name,
                )
valid.valid_container(
    background_roi,
    container_types=(list, tuple),
    allow_none=True,
    item_types=int,
    min_included=0,
    name=validation_name,
)

valid.valid_item(
    value=expected_width,
    allowed_types=Real,
    min_excluded=0,
    allow_none=True,
    name=validation_name,
)

valid.valid_container(comment, container_types=str, name=validation_name)
if comment.startswith("_"):
    comment = comment[1:]
comment = f"_direction{direction[0]}_{direction[1]}_{comment}"

#########################
# normalize the modulus #
#########################
obj = abs(obj) / abs(obj).max()  # normalize the modulus to 1
obj[np.isnan(obj)] = 0  # remove nans
if background_roi is not None:
Exemplo n.º 23
0
 def test_validitem_allowedtypes_ndarray(self):
     self.assertTrue(
         valid.valid_item(value=np.zeros(4), allowed_types=np.ndarray))
Exemplo n.º 24
0
tick_width = 2  # in plots
tick_spacing = (
    0.025,
    0.025,
    0.025,
)  # tuple of three numbers, in 1/A. Leave None for default.
num_ticks = 5  # number of ticks to use in axes when tick_spacing is not defined
##################################
# end of user-defined parameters #
##################################

####################
# Check parameters #
####################
valid_name = "bcdi_plot_diffpattern_2D"
valid.valid_item(save_sum, allowed_types=bool, name=valid_name)
if save_sum:
    comment = comment + "_sum"
valid.valid_container(
    colorbar_range,
    container_types=(tuple, list, np.ndarray),
    item_types=Real,
    length=2,
    allow_none=True,
    name=valid_name,
)
if isinstance(tick_spacing, Real) or tick_spacing is None:
    tick_spacing = (tick_spacing,) * 3
valid.valid_container(
    tick_spacing,
    container_types=(tuple, list, np.ndarray),
Exemplo n.º 25
0
 def test_validitem_allownone_true(self):
     self.assertTrue(
         valid.valid_item(value=None, allowed_types=Real, allow_none=True))
Exemplo n.º 26
0
# end of user-defined parameters #
##################################

#############################
# define default parameters #
#############################
colors = ("b", "g", "r", "c", "m", "y", "k")  # for plots
markers = (".", "v", "^", "<", ">")  # for plots
validation_name = "angular_profile"
mpl.rcParams["axes.linewidth"] = tick_width  # set the linewidth globally

#########################
# check some parameters #
#########################
valid.valid_item(value=upsampling_factor,
                 allowed_types=int,
                 min_included=1,
                 name=validation_name)
valid.valid_container(comment, container_types=str, name=validation_name)
if comment.startswith("_"):
    comment = comment[1:]

##################################################
# create the list of directions for the linecuts #
##################################################
angles = np.arange(0, 180, angular_step)
nb_dir = len(angles)
directions = []
for idx in range(nb_dir):
    directions.append(
        (np.sin(angles[idx] * np.pi / 180), np.cos(angles[idx] * np.pi / 180)))
Exemplo n.º 27
0
    if not strain_range == 'minmax':
        raise ValueError(
            f'Incorrect setting {strain_range} for the parameter "strain_range"'
        )
else:
    strain_min, strain_max = -strain_range, strain_range

if not isinstance(phase_range, Real):
    if not phase_range == 'minmax':
        raise ValueError(
            f'Incorrect setting {phase_range} for the parameter "phase_range"')
else:
    phase_min, phase_max = -phase_range, phase_range

valid.valid_item(min_histo,
                 allowed_types=Real,
                 min_included=0,
                 name=valid_name)
valid.valid_container(obj=vline_hist,
                      container_types=(list, tuple, np.ndarray, set),
                      min_excluded=0,
                      allow_none=True,
                      item_types=Real,
                      name=valid_name)

pathlib.Path(savedir).mkdir(parents=True, exist_ok=True)

#############
# load data #
#############
plt.ion()
root = tk.Tk()