示例#1
0
# load q values #
#################
file_path = filedialog.askopenfilename(initialdir=datadir,
                                       title="Select q values",
                                       filetypes=[("NPZ", "*.npz")])
npzfile = np.load(file_path)
qx = npzfile["qx"]  # downstream
qz = npzfile["qz"]  # vertical up
qy = npzfile["qy"]  # outboard

###################################
# bin data and q values if needed #
###################################
if any(bin_factor != 1 for bin_factor in binning):
    diff_pattern = util.bin_data(array=diff_pattern,
                                 binning=binning,
                                 debugging=False)
    mask = util.bin_data(array=mask, binning=binning, debugging=False)
    mask[np.nonzero(mask)] = 1
    qx = qx[::binning[0]]
    qy = qy[::binning[1]]
    qz = qz[::binning[2]]

############################
# plot diffraction pattern #
############################
nz, ny, nx = diff_pattern.shape
print(
    "Data shape after binning=",
    nz,
    ny,
示例#2
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
示例#3
0
##############################
# load reciprocal space data #
##############################
plt.ion()
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename(
    initialdir=root_folder,
    title="Select the diffraction pattern",
    filetypes=[("NPZ", "*.npz")],
)
npzfile = np.load(file_path)
diff_pattern = util.bin_data(
    npzfile[list(npzfile.files)[0]],
    (bin_factor, bin_factor, bin_factor),
    debugging=False,
)
diff_pattern[diff_pattern < threshold] = 0
nz, ny, nx = diff_pattern.shape
print("Data shape after binning:", nz, ny, nx)
print("Data type:", diff_pattern.dtype)

gu.multislices_plot(
    diff_pattern,
    sum_frames=True,
    plot_colorbar=True,
    cmap=my_cmap,
    title="diffraction pattern",
    scale="log",
    vmin=np.nan,
示例#4
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
示例#5
0
                "skip"  # we assume that normalization was already performed
            )
            monitor = []  # we assume that normalization was already performed
            min_range = (nx / 2) * np.sqrt(
                2
            )  # used when fit_datarange is True, keep the full array because
            # we do not know the position of the origin of reciprocal space
            frames_logical = np.ones(nz)

            # bin data and mask if needed
            if ((detector.binning[0] != 1) or (detector.binning[1] != 1)
                    or (detector.binning[2] != 1)):
                print("Binning the reloaded orthogonal data by",
                      detector.binning)
                data = util.bin_data(data,
                                     binning=detector.binning,
                                     debugging=False)
                mask = util.bin_data(mask,
                                     binning=detector.binning,
                                     debugging=False)
                mask[np.nonzero(mask)] = 1
                if len(q_values) != 0:
                    qx = q_values[0]
                    qz = q_values[1]
                    qy = q_values[2]
                    numz, numy, numx = len(qx), len(qz), len(qy)
                    qx = qx[:numz -
                            (numz % detector.binning[2]):detector.binning[2]]
                    # along z downstream, same binning as along x
                    qz = qz[:numy -
                            (numy % detector.binning[1]):detector.binning[1]]
示例#6
0
if not np.all(np.asarray(crop_center) - np.asarray(roi_size) // 2 >= 0):
    raise ValueError("crop_center incompatible with roi_size")
if not (
    crop_center[0] + roi_size[0] // 2 <= nbz
    and crop_center[1] + roi_size[1] // 2 <= nby
    and crop_center[2] + roi_size[2] // 2 <= nbx
):
    raise ValueError("crop_center incompatible with roi_size")

#######################################################
# crop the data, and optionally the mask and q values #
#######################################################
data = util.crop_pad(
    data, output_shape=roi_size, crop_center=crop_center, debugging=debug
)
data = util.bin_data(data, binning=binning, debugging=debug)
comment = (
    f"{data.shape[0]}_{data.shape[1]}_{data.shape[2]}_"
    f"{binning[0]}_{binning[1]}_{binning[2]}" + comment
)
np.savez_compressed(datadir + "S" + str(scan) + "_pynx" + comment + ".npz", data=data)

fig, _, _ = gu.multislices_plot(
    data,
    sum_frames=True,
    scale="log",
    plot_colorbar=True,
    vmin=0,
    title="Cropped data",
    is_orthogonal=is_orthogonal,
    reciprocal_space=reciprocal_space,
示例#7
0
        hxrd=hxrd,
        debugging=debug,
    )

    nz, ny, nx = data.shape  # CXI convention: z downstream, y vertical up, x outboard
    print("Diffraction data shape", data.shape)
    qx = q_values[0]  # axis=0, z downstream, qx in reciprocal space
    qz = q_values[1]  # axis=1, y vertical, qz in reciprocal space
    qy = q_values[2]  # axis=2, x outboard, qy in reciprocal space
    ############
    # bin data #
    ############
    qx = qx[:nz - (nz % binning[0]):binning[0]]
    qz = qz[:ny - (ny % binning[1]):binning[1]]
    qy = qy[:nx - (nx % binning[2]):binning[2]]
    data = util.bin_data(data, (binning[0], binning[1], binning[2]),
                         debugging=False)
    nz, ny, nx = data.shape
    print("Diffraction data shape after binning", data.shape)

    # apply photon threshold
    data[data < photon_threshold] = 0
else:  # load a reconstructed real space object
    comment = comment + "_CDI"
    file_path = filedialog.askopenfilename(initialdir=homedir,
                                           title="Select 3D data",
                                           filetypes=[("NPZ", "*.npz")])
    amp = np.load(file_path)["amp"]
    amp = amp / abs(amp).max()  # normalize amp
    nz, ny, nx = amp.shape  # CXI convention: z downstream, y vertical up, x outboard
    print("CDI data shape", amp.shape)
    # nz1, ny1, nx1 = [value * pad_size for value in amp.shape]
示例#8
0
    sys.exit()

###############################################
# 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
setup.detector.binning = phasing_binning
print(
    "Pixel sizes after phasing_binning (vertical, horizontal): ",
    setup.detector.pixelsize_y,
    setup.detector.pixelsize_x,
    "(m)",
)
slice_2D = util.bin_data(array=slice_2D,
                         binning=(phasing_binning[1], phasing_binning[2]),
                         debugging=False)
mask_2D = util.bin_data(array=mask_2D,
                        binning=(phasing_binning[1], phasing_binning[2]),
                        debugging=False)

slice_2D[np.nonzero(mask_2D)] = 0

plt.figure()
plt.imshow(np.log10(np.sqrt(slice_2D)), cmap=my_cmap, vmin=0, vmax=3.5)
plt.title("2D diffraction amplitude")
plt.colorbar()
plt.pause(0.1)

##########################################################
# load the 3D dataset in order to calculate the q values #