コード例 #1
0
    def linearity_func(self, value):
        def poly4(array_1d, coeffs):
            """
            Define a 4th order polynomial and apply it on a 1D array.

            :param array_1d: a numpy 1D array
            :param coeffs: sequence of 5 Real numbers, the coefficients [a, b, c, d, e]
             of the polynomial ax^4 + bx^3 + cx^2 + dx + e
            :return: the updated 1D array
            """
            return (coeffs[0] * array_1d**4 + coeffs[1] * array_1d**3 +
                    coeffs[2] * array_1d**2 + coeffs[3] * array_1d + coeffs[4])

        if value is None:
            self._linearity_func = None
            return

        valid.valid_container(
            value,
            container_types=(tuple, list, np.ndarray),
            length=5,
            item_types=Real,
            name="linearity_func",
        )
        self._linearity_func = partial(poly4, coeffs=value)
コード例 #2
0
ファイル: diffractometer.py プロジェクト: LonglonWu/bcdi
    def rotation_matrix(self, stage_name, angles):
        """
        Calculate a 3D rotation matrix given rotation axes and angles.

        :param stage_name: supported stage name, 'sample' or 'detector'
        :param angles: list of angular values in degrees for the stage circles
         during the measurement
        :return: the rotation matrix as a numpy ndarray of shape (3, 3)
        """
        self.valid_name(stage_name)
        nb_circles = len(self.__getattribute__(self.valid_names[stage_name]))
        if isinstance(angles, Number):
            angles = (angles, )
        valid.valid_container(
            angles,
            container_types=(list, tuple, np.ndarray),
            length=nb_circles,
            item_types=Real,
            name="angles",
        )

        # create a list of rotation matrices corresponding to the circles,
        # index 0 corresponds to the most outer circle
        rotation_matrices = [
            RotationMatrix(circle, angles[idx]).get_matrix()
            for idx, circle in enumerate(
                self.__getattribute__(self.valid_names[stage_name]))
        ]

        # calculate the total tranformation matrix by rotating back
        # from outer circles to inner circles
        return np.array(reduce(np.matmul, rotation_matrices))
コード例 #3
0
def in_range(point, extent):
    """
    Return a boolean depending on whether point is in the indices range defined by extent or not.

    :param point: tuple of two real numbers (2D case) (y, x) or three real numbers (3D case) (z, y, x) representing
     the voxel indices to be tested
    :param extent: tuple of four integers (2D case) (y_start, y_stop, x_tart, x_stop) or six integers (3D case)
     (z_start, z_stop, y_start, y_stop, x_tart, x_stop) representing the range of valid indices
    :return: True if point belongs to extent, False otherwise
    """
    # check parameters
    valid.valid_container(point,
                          container_types=(list, tuple, np.ndarray),
                          item_types=Real,
                          name='utilities.in_range')
    ndim = len(point)
    if ndim not in {2, 3}:
        raise ValueError('point should be 2D or 3D')
    valid.valid_container(extent,
                          container_types=(list, tuple, np.ndarray),
                          length=2 * ndim,
                          item_types=int,
                          name='utilities.in_range')

    # check the appartenance to the defined extent
    if ndim == 2:
        if (extent[0] <= point[0] <= extent[1]) and\
           (extent[2] <= point[1] <= extent[3]):
            return True
    else:
        if (extent[0] <= point[0] <= extent[1]) and\
           (extent[2] <= point[1] <= extent[3]) and\
           (extent[4] <= point[2] <= extent[5]):
            return True
    return False
コード例 #4
0
def rotation_matrix_3d(axis_to_align, reference_axis):
    """
    Calculate the rotation matrix which aligns axis_to_align onto reference_axis in 3D.

    :param axis_to_align: the 3D vector to be aligned (e.g. vector q), expressed in an orthonormal frame x y z
    :param reference_axis: will align axis_to_align onto this 3D vector, expressed in an orthonormal frame  x y z
    :return: the rotation matrix as a np.array of shape (3, 3)
    """
    # check parameters
    valid_name = 'utilities.rotation_matrix_3d'
    valid.valid_container(axis_to_align,
                          container_types=(list, tuple, np.ndarray),
                          length=3,
                          item_types=Real,
                          name=valid_name)
    valid.valid_container(reference_axis,
                          container_types=(list, tuple, np.ndarray),
                          length=3,
                          item_types=Real,
                          name=valid_name)

    # normalize the vectors
    axis_to_align = axis_to_align / np.linalg.norm(axis_to_align)
    reference_axis = reference_axis / np.linalg.norm(reference_axis)

    # calculate the skew-symmetric matrix
    v = np.cross(axis_to_align, reference_axis)
    skew_sym_matrix = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]],
                                [-v[1], v[0], 0]])
    rotation_matrix = np.identity(3) + skew_sym_matrix +\
        np.dot(skew_sym_matrix, skew_sym_matrix) / (1+np.dot(axis_to_align, reference_axis))

    return rotation_matrix.transpose()
コード例 #5
0
ファイル: diffractometer.py プロジェクト: LonglonWu/bcdi
    def get_rocking_circle(self, rocking_angle, stage_name, angles):
        """
        Find the index of the circle which corresponds to the rocking angle.

        :param rocking_angle: angle which is tilted during the rocking curve in
         {'outofplane', 'inplane'}
        :param stage_name: supported stage name, 'sample' or 'detector'
        :param angles: tuple of angular values in degrees, one for each circle
         of the sample stage
        :return: the index of the rocking circles in the list of angles
        """
        # check parameters
        if rocking_angle not in {"outofplane", "inplane"}:
            raise ValueError(
                f"Invalid value {rocking_angle} for rocking_angle,"
                f' should be either "inplane" or "outofplane"')
        self.valid_name(stage_name)
        valid.valid_container(angles,
                              container_types=(tuple, list),
                              name="angles")
        nb_circles = len(angles)

        # find which angles were scanned
        candidate_circles = set()
        for idx in range(nb_circles):
            if not isinstance(angles[idx], Real) and len(angles[idx]) > 1:
                # not a number, hence a tuple/list/ndarray (cannot be None)
                candidate_circles.add(idx)

        # exclude arrays with identical values
        wrong_motors = []
        for idx in candidate_circles:
            if (angles[idx][1:] - angles[idx][:-1]).mean(
            ) < 0.0001:  # motor not scanned, noise in the position readings
                wrong_motors.append(idx)
        candidate_circles.difference_update(wrong_motors)

        # check that there is only one candidate remaining
        if len(candidate_circles) > 1:
            raise ValueError(
                "Several circles were identified as scanned motors")
        if len(candidate_circles) == 0:
            raise ValueError("No circle was identified as scanned motor")
        index_circle = next(iter(candidate_circles))

        # check that the rotation axis corresponds to the one definec by rocking_angle
        circles = self.__getattribute__(self.valid_names[stage_name])
        if rocking_angle == "inplane":
            if circles[index_circle][0] != "y":
                raise ValueError(
                    f"The identified circle '{circles[index_circle]}' is incompatible "
                    f"with the parameter '{rocking_angle}'")
        else:  # 'outofplane'
            if circles[index_circle][0] != "x":
                raise ValueError(
                    f"The identified circle '{circles[index_circle]}' is incompatible "
                    f"with the parameter '{rocking_angle}'")
        return index_circle
コード例 #6
0
 def sample_name(self, value):
     valid.valid_container(
         value,
         container_types=str,
         min_length=1,
         allow_none=True,
         name="Detector.sample_name",
     )
     self._sample_name = value
コード例 #7
0
 def template_imagefile(self, value):
     valid.valid_container(
         value,
         container_types=str,
         min_length=0,
         allow_none=True,
         name="template_imagefile",
     )
     self._template_imagefile = value
コード例 #8
0
ファイル: parser.py プロジェクト: LonglonWu/bcdi
 def file_path(self, value):
     valid.valid_container(value,
                           container_types=str,
                           min_length=1,
                           name="file_path")
     if pathlib.Path(value).suffix != ".yml":
         raise ValueError("Expecting a YAML config file")
     if not os.path.isfile(value):
         raise ValueError(f"The file {value} does not exist")
     self._file_path = value
コード例 #9
0
 def preprocessing_binning(self, value):
     valid.valid_container(
         value,
         container_types=(tuple, list),
         length=3,
         item_types=int,
         min_excluded=0,
         name="Detector.preprocessing_binning",
     )
     self._preprocessing_binning = value
コード例 #10
0
 def savedir(self, value):
     valid.valid_container(
         value,
         container_types=str,
         min_length=1,
         allow_none=True,
         name="Detector.savedir",
     )
     if value is not None:
         pathlib.Path(value).mkdir(parents=True, exist_ok=True)
     self._savedir = value
コード例 #11
0
 def rootdir(self, value):
     valid.valid_container(
         value,
         container_types=str,
         min_length=1,
         allow_none=True,
         name="Detector.rootdir",
     )
     if value is not None and not os.path.isdir(value):
         raise ValueError(f"The directory {value} does not exist")
     self._rootdir = value
コード例 #12
0
ファイル: diffractometer.py プロジェクト: LonglonWu/bcdi
 def sample_offsets(self, value):
     nb_circles = len(self.__getattribute__(self.valid_names["sample"]))
     if value is None:
         value = (0, ) * nb_circles
     valid.valid_container(
         value,
         container_types=(tuple, list, np.ndarray),
         length=nb_circles,
         item_types=Real,
         name="Diffractometer.sample_offsets",
     )
     self._sample_offsets = value
コード例 #13
0
 def roi(self, value):
     if not value:  # None or empty list/tuple
         value = [0, self.nb_pixel_y, 0, self.nb_pixel_x]
     valid.valid_container(
         value,
         container_types=(tuple, list, np.ndarray),
         length=4,
         item_types=int,
         name="Detector.roi",
     )
     if value[1] <= value[0] or value[3] <= value[2]:
         raise ValueError("roi coordinates should be increasing in x and y")
     self._roi = value
コード例 #14
0
ファイル: diffractometer.py プロジェクト: LonglonWu/bcdi
 def sample_circles(self, value):
     valid.valid_container(
         value,
         container_types=(tuple, list),
         min_length=0,
         item_types=str,
         name="Diffractometer.sample_circles",
     )
     if any(val not in self.valid_circles for val in value):
         raise ValueError(
             "Invalid circle value encountered in sample_circles,"
             f" valid are {self.valid_circles}")
     self._sample_circles = list(value)
コード例 #15
0
 def sum_roi(self, value):
     if not value:  # None or empty list/tuple
         value = self.roi
     valid.valid_container(
         value,
         container_types=(tuple, list),
         length=4,
         item_types=int,
         name="Detector.sum_roi",
     )
     if value[1] <= value[0] or value[3] <= value[2]:
         raise ValueError("roi coordinates should be increasing in x and y")
     self._sum_roi = value
コード例 #16
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
コード例 #17
0
ファイル: test_validation.py プロジェクト: LonglonWu/bcdi
 def test_validcontainer_container_itemtype_ndarray(self):
     self.assertTrue(
         valid.valid_container(
             obj=(np.ones(3), np.zeros(4)),
             container_types=(tuple, list),
             item_types=np.ndarray,
         ))
コード例 #18
0
ファイル: test_validation.py プロジェクト: LonglonWu/bcdi
 def test_validcontainer_container_dict_itemtype_int(self):
     self.assertTrue(
         valid.valid_container(obj={0: {
             "x": 1
         }},
                               container_types=dict,
                               item_types=int))
コード例 #19
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)
コード例 #20
0
                                cmap='gray',
                                debug=False)
else:
    obj, _ = util.load_file(file_path)
ndim = obj.ndim

#########################
# check some parameters #
#########################
valid_name = 'bcdi_line_profile'
if ndim not in {2, 3}:
    raise ValueError(f'Number of dimensions = {ndim}, expected 2 or 3')

valid.valid_container(direction,
                      container_types=(list, tuple, np.ndarray),
                      length=ndim,
                      item_types=Real,
                      name=valid_name)

valid.valid_container(points,
                      container_types=(list, tuple, set),
                      min_length=1,
                      name=valid_name)
for point in points:
    valid.valid_container(point,
                          container_types=(list, tuple, np.ndarray),
                          length=ndim,
                          item_types=Real,
                          min_included=0,
                          name=valid_name)
コード例 #21
0
#############################
# 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)))

#################
# load the data #
コード例 #22
0
# end of user-defined parameters #
##################################

#########################
# check some parameters #
#########################
valid_name = "diffpattern_from_reconstruction"
savedir = savedir or datadir
pathlib.Path(savedir).mkdir(parents=True, exist_ok=True)

if isinstance(voxel_sizes, Real):
    voxel_sizes = (voxel_sizes,) * 3
valid.valid_container(
    voxel_sizes,
    container_types=(list, tuple, np.ndarray),
    length=3,
    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
コード例 #23
0
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),
    allow_none=True,
    item_types=Real,
    min_excluded=0,
    name=valid_name,
)
valid.valid_item(num_ticks, allowed_types=int, min_excluded=0, name=valid_name)
コード例 #24
0
    except AttributeError:  # mouse pointer out of axes
        pass


#########################
# check some parameters #
#########################
if (vmin and vmax) and (vmax <= vmin):
    raise ValueError("vmax should be larger than vmin")

savedir = savedir or datadir

valid.valid_container(
    obj=starting_point,
    container_types=list,
    allow_none=True,
    item_types=int,
    name="linecut_diffpattern.py",
)
valid.valid_container(
    obj=endpoint,
    container_types=list,
    allow_none=True,
    item_types=int,
    name="linecut_diffpattern.py",
)

###################
# define colormap #
###################
my_cmap = ColormapFactory().generate_cmap()
コード例 #25
0
ファイル: bcdi_rocking_curves.py プロジェクト: LonglonWu/bcdi
# check and initialize some parameters #
########################################
print(f"\n{len(scans)} scans: {scans}")
print(f"\n {len(x_axis)} x_axis values provided:")
if len(x_axis) == 0:
    x_axis = np.arange(len(scans))
if len(x_axis) != len(scans):
    raise ValueError(
        "the length of x_axis should be equal to the number of scans")

if isinstance(sample_name, str):
    sample_name = [sample_name for idx in range(len(scans))]
valid.valid_container(
    sample_name,
    container_types=(tuple, list),
    length=len(scans),
    item_types=str,
    name="preprocess_bcdi",
)
if peak_method not in [
        "max",
        "com",
        "max_com",
]:
    raise ValueError('invalid value for "peak_method" parameter')

int_sum = []  # integrated intensity in the detector ROI
int_max = []  # maximum intensity in the detector ROI
zcom = []  # center of mass for the first data axis
ycom = []  # center of mass for the second data axis
xcom = []  # center of mass for the third data axis
コード例 #26
0
ファイル: parser.py プロジェクト: LonglonWu/bcdi
 def command_line_args(self, value):
     valid.valid_container(value,
                           container_types=dict,
                           allow_none=True,
                           name="command_line_args")
     self._command_line_args = value
コード例 #27
0
# 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
valid.valid_item(tick_length,
                 allowed_types=int,
                 min_excluded=0,
                 name=validation_name)
valid.valid_item(tick_width,
                 allowed_types=int,
コード例 #28
0
    filetypes=[("NPZ", "*.npz"), ("NPY", "*.npy")],
)
try:
    mask, _ = util.load_file(file_path)
except ValueError:
    mask = np.zeros(diff_pattern.shape, dtype=int)

###########################################################
# crop the diffraction pattern and the mask to compensate #
# the "auto_center_resize" option used in PyNX            #
###########################################################
# The shape will be equal to 'roi_final' parameter of the .cxi file
valid.valid_container(
    obj=crop_roi,
    container_types=(list, tuple),
    length=6,
    item_types=int,
    allow_none=True,
    name="prtf_bcdi.py",
)
if crop_roi is not None:
    diff_pattern = diff_pattern[crop_roi[0]:crop_roi[1],
                                crop_roi[2]:crop_roi[3],
                                crop_roi[4]:crop_roi[5]]
    mask = mask[crop_roi[0]:crop_roi[1], crop_roi[2]:crop_roi[3],
                crop_roi[4]:crop_roi[5]]

###############################################
# bin the diffraction pattern and the mask to #
# compensate the "rebin" option used in PyNX  #
###############################################
# update also the detector pixel sizes to take into account the binning
コード例 #29
0
if ext in {".png", ".jpg", ".tif"}:
    obj = util.image_to_ndarray(filename=file_path, convert_grey=True)
else:
    obj, _ = util.load_file(file_path)
ndim = obj.ndim

#########################
# check some parameters #
#########################
if ndim != 2:
    raise ValueError(f"Number of dimensions = {ndim}, expected 2")

valid.valid_container(
    direction,
    container_types=(list, tuple, np.ndarray),
    length=ndim,
    item_types=Real,
    name=validation_name,
)

valid.valid_container(points,
                      container_types=(list, tuple),
                      min_length=1,
                      name=validation_name)
for point in points:
    valid.valid_container(
        point,
        container_types=(list, tuple, np.ndarray),
        length=ndim,
        item_types=Real,
        min_included=0,
コード例 #30
0
elif data_frame == 'detector':
    is_orthogonal = False
else:
    is_orthogonal = True

if ref_axis_q not in {'x', 'y', 'z'}:
    raise ValueError("ref_axis_q should be either 'x', 'y', 'z'")

if ref_axis not in {'x', 'y', 'z'}:
    raise ValueError("ref_axis should be either 'x', 'y', 'z'")

if isinstance(output_size, Real):
    output_size = (output_size, ) * 3
valid.valid_container(output_size,
                      container_types=(tuple, list, np.ndarray),
                      length=3,
                      allow_none=True,
                      item_types=int,
                      name=valid_name)
axis_to_array_xyz = {
    'x': np.array([1, 0, 0]),
    'y': np.array([0, 1, 0]),
    'z': np.array([0, 0, 1])
}  # in xyz order

comment = comment + '_' + str(isosurface_strain)

###################
# define colormap #
###################
if grey_background:
    bad_color = '0.7'