Exemple #1
0
def image_to_ndarray(filename, convert_grey=True, cmap=None, debug=False):
    """
    Convert an image to a numpy array using pillow (matplotlib only supports the PNG format).

    :param filename: absolute path of the image to open
    :param convert_grey: if True and the number of layers is 3, it will be converted to a single layer of grey
    :param cmap: colormap for the plots
    :param debug: True to see plots
    :return:
    """
    from PIL import Image
    if cmap is None:
        cmap = gu.Colormap(bad_color='1.0').cmap

    im = Image.open(filename)

    array = np.asarray(im)
    if array.ndim == 3 and convert_grey:
        print('converting image to gray')
        array = rgb2gray(array)

    print(f'Image shape after conversion to ndarray: {array.shape}')
    if debug:
        gu.imshow_plot(array,
                       sum_axis=2,
                       plot_colorbar=True,
                       cmap=cmap,
                       reciprocal_space=False)
    return array
Exemple #2
0
                      allow_none=True,
                      name=valid_name)

if ndim == 3:
    comment = f'_direction{direction[0]}_{direction[1]}_{direction[2]}_{comment}'
else:
    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 ndim == 2:
    gu.imshow_plot(array=obj,
                   plot_colorbar=True,
                   reciprocal_space=False,
                   is_orthogonal=True)
else:
    gu.multislices_plot(array=obj,
                        sum_frames=False,
                        plot_colorbar=True,
                        reciprocal_space=False,
                        is_orthogonal=True,
                        slice_position=(25, 37, 25))

#####################################
# create the linecut for each point #
#####################################
result = dict()
for point in points:
    # get the distances and the modulus values along the linecut
    max_included=1,
    name="angular_profile",
)

comment = f"_origin_{origin}_{comment}"

#########################
# normalize the modulus #
#########################
obj = abs(obj) / abs(obj).max()  # normalize the modulus to 1
obj[np.isnan(obj)] = 0  # remove nans
fig, axs, _ = gu.imshow_plot(
    array=obj,
    sum_frames=True,
    sum_axis=1,
    plot_colorbar=True,
    reciprocal_space=False,
    vmin=0,
    vmax=np.nan,
    is_orthogonal=True,
)

gu.savefig(
    savedir=savedir,
    figure=fig,
    axes=axs,
    tick_width=tick_width,
    tick_length=tick_length,
    tick_labelsize=14,
    xlabels=axs.get_xlabel(),
    ylabels=axs.get_ylabel(),
    titles=axs.get_title(),
Exemple #4
0
plt.ion() # interactive graphics
mask = np.zeros((nb_pixel_y, nb_pixel_x))

ccdfiletmp = os.path.join(datadir,'scan_' + str('{:04d}'.format(scan)) + '_' + detector + '0000.hdf5'
h5file = h5py.File(ccdfiletmp, 'r')
    
data = h5file['entry']['measurement']['Merlin']['data']
nbz, nby, nbx = data.shape

if not roi:
    data = np.array(data) # the whole array is loaded here
else
    data = np.array(data[roi[0]:roi[1],roi[2]:roi[3],roi[4]:roi[5]])

mask[np.log10(data) > high_threshold] = 1
data[mask == 1] = 0

print('')
if is_scan: 
    plot_title = 'masked data'
    filename = 'S' + str(scan) + '_scan.npz'

#sumdata, mask = pru.mask_merlin(data=sumdata, mask=mask) NOT IMPLEMENTED
if save_mask:
    fig, _, _ = gu.imshow_plot(mask, plot_colorbar=False, title='mask')
    np.savez_compressed(savedir+'hotpixels.npz', mask=mask)
    fig.savefig(savedir + 'mask.png')

np.savez_compressed(savedir + filename, data=data)

Exemple #5
0
def beamstop_correction(data, setup, debugging=False):
    """
    Correct absorption from the beamstops during P10 forward CDI experiment.

    :param data: the 3D stack of 2D CDI images, shape = (nbz, nby, nbx) or 2D image of
     shape (nby, nbx)
    :param setup: an instance of the class Setup
    :param debugging: set to True to see plots
    :return: the corrected data
    """
    valid.valid_ndarray(arrays=data, ndim=(2, 3))
    energy = setup.energy
    if not isinstance(energy, Real):
        raise TypeError(
            f"Energy should be a number in eV, not a {type(energy)}")

    print(f"Applying beamstop correction for the X-ray energy of {energy}eV")

    if energy not in [8200, 8700, 10000, 10235]:
        print("no beam stop information for the X-ray energy of {:d}eV,"
              " defaulting to the correction for 8700 eV".format(int(energy)))
        energy = 8700

    ndim = data.ndim
    if ndim == 3:
        pass
    elif ndim == 2:
        data = data[np.newaxis, :, :]
    else:
        raise ValueError("2D or 3D data expected")
    nbz, nby, nbx = data.shape

    directbeam_y = setup.direct_beam[0] - setup.detector.roi[0]  # vertical
    directbeam_x = setup.direct_beam[1] - setup.detector.roi[2]  # horizontal

    # at 8200eV, the transmission of 100um Si is 0.26273
    # at 8700eV, the transmission of 100um Si is 0.32478
    # at 10000eV, the transmission of 100um Si is 0.47337
    # at 10235eV, the transmission of 100um Si is 0.51431
    if energy == 8200:
        factor_large = 1 / 0.26273  # 5mm*5mm (100um thick) Si wafer
        factor_small = 1 / 0.26273  # 3mm*3mm (100um thick) Si wafer
        pixels_large = [-33, 35, -31, 36]
        # boundaries of the large wafer relative to the direct beam (V x H)
        pixels_small = [-14, 14, -11, 16]
        # boundaries of the small wafer relative to the direct beam (V x H)
    elif energy == 8700:
        factor_large = 1 / 0.32478  # 5mm*5mm (100um thick) Si wafer
        factor_small = 1 / 0.32478  # 3mm*3mm (100um thick) Si wafer
        pixels_large = [-33, 35, -31, 36]
        # boundaries of the large wafer relative to the direct beam (V x H)
        pixels_small = [-14, 14, -11, 16]
        # boundaries of the small wafer relative to the direct beam (V x H)
    elif energy == 10000:
        factor_large = 2.1 / 0.47337  # 5mm*5mm (200um thick) Si wafer
        factor_small = 4.5 / 0.47337  # 3mm*3mm (300um thick) Si wafer
        pixels_large = [-36, 34, -34, 35]
        # boundaries of the large wafer relative to the direct beam (V x H)
        pixels_small = [-21, 21, -21, 21]
        # boundaries of the small wafer relative to the direct beam (V x H)
    else:  # energy = 10235
        factor_large = 2.1 / 0.51431  # 5mm*5mm (200um thick) Si wafer
        factor_small = 4.5 / 0.51431  # 3mm*3mm (300um thick) Si wafer
        pixels_large = [-34, 35, -33, 36]
        # boundaries of the large wafer relative to the direct beam (V x H)
        pixels_small = [-20, 22, -20, 22]
        # boundaries of the small wafer relative to the direct beam (V x H)

    # define boolean arrays for the large and the small square beam stops
    large_square = np.zeros((nby, nbx))
    large_square[directbeam_y + pixels_large[0]:directbeam_y + pixels_large[1],
                 directbeam_x + pixels_large[2]:directbeam_x +
                 pixels_large[3], ] = 1
    small_square = np.zeros((nby, nbx))
    small_square[directbeam_y + pixels_small[0]:directbeam_y + pixels_small[1],
                 directbeam_x + pixels_small[2]:directbeam_x +
                 pixels_small[3], ] = 1

    # define the boolean array for the border of the large square wafer
    # (the border is 1 pixel wide)
    temp_array = np.zeros((nby, nbx))
    temp_array[directbeam_y + pixels_large[0] + 1:directbeam_y +
               pixels_large[1] - 1, directbeam_x + pixels_large[2] +
               1:directbeam_x + pixels_large[3] - 1, ] = 1
    large_border = large_square - temp_array

    # define the boolean array for the border of the small square wafer
    # (the border is 1 pixel wide)
    temp_array = np.zeros((nby, nbx))
    temp_array[directbeam_y + pixels_small[0] + 1:directbeam_y +
               pixels_small[1] - 1, directbeam_x + pixels_small[2] +
               1:directbeam_x + pixels_small[3] - 1, ] = 1
    small_border = small_square - temp_array

    if debugging:
        gu.imshow_plot(
            data,
            sum_frames=True,
            sum_axis=0,
            vmin=0,
            vmax=11,
            plot_colorbar=True,
            scale="log",
            title="data before absorption correction",
            is_orthogonal=False,
            reciprocal_space=True,
        )

        gu.combined_plots(
            tuple_array=(large_square, small_square, large_border,
                         small_border),
            tuple_sum_frames=(False, False, False, False),
            tuple_sum_axis=0,
            tuple_width_v=None,
            tuple_width_h=None,
            tuple_colorbar=False,
            tuple_vmin=0,
            tuple_vmax=11,
            is_orthogonal=False,
            reciprocal_space=True,
            tuple_title=(
                "large_square",
                "small_square",
                "larger border",
                "small border",
            ),
            tuple_scale=("linear", "linear", "linear", "linear"),
        )

    # absorption correction for the large and small square beam stops
    for idx in range(nbz):
        tempdata = data[idx, :, :]
        tempdata[np.nonzero(large_square)] = (
            tempdata[np.nonzero(large_square)] * factor_large)
        tempdata[np.nonzero(small_square)] = (
            tempdata[np.nonzero(small_square)] * factor_small)
        data[idx, :, :] = tempdata

    if debugging:
        width = 40
        _, (ax0, ax1) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6))
        ax0.plot(
            np.log10(data[:, directbeam_y, directbeam_x - width:directbeam_x +
                          width].sum(axis=0)))
        ax0.set_title("horizontal cut after absorption correction")
        ax0.vlines(
            x=[
                width + pixels_large[2],
                width + pixels_large[3],
                width + pixels_small[2],
                width + pixels_small[3],
            ],
            ymin=ax0.get_ylim()[0],
            ymax=ax0.get_ylim()[1],
            colors="b",
            linestyle="dashed",
        )
        ax1.plot(
            np.log10(data[:, directbeam_y - width:directbeam_y + width,
                          directbeam_x].sum(axis=0)))
        ax1.set_title("vertical cut after absorption correction")
        ax1.vlines(
            x=[
                width + pixels_large[0],
                width + pixels_large[1],
                width + pixels_small[0],
                width + pixels_small[1],
            ],
            ymin=ax1.get_ylim()[0],
            ymax=ax1.get_ylim()[1],
            colors="b",
            linestyle="dashed",
        )

        gu.imshow_plot(
            data,
            sum_frames=True,
            sum_axis=0,
            vmin=0,
            vmax=11,
            plot_colorbar=True,
            scale="log",
            title="data after absorption correction",
            is_orthogonal=False,
            reciprocal_space=True,
        )

    # interpolation for the border of the large square wafer
    indices = np.argwhere(large_border == 1)
    data[np.nonzero(np.repeat(large_border[np.newaxis, :, :], nbz,
                              axis=0))] = 0  # exclude border points
    for frame in range(nbz):  # loop over 2D images in the detector plane
        tempdata = data[frame, :, :]
        for idx in range(indices.shape[0]):
            pixrow = indices[idx, 0]
            pixcol = indices[idx, 1]
            counter = (9 - large_border[pixrow - 1:pixrow + 2,
                                        pixcol - 1:pixcol + 2].sum()
                       )  # number of pixels in a 3x3 window
            # which do not belong to the border
            tempdata[pixrow, pixcol] = (
                tempdata[pixrow - 1:pixrow + 2, pixcol - 1:pixcol + 2].sum() /
                counter)
        data[frame, :, :] = tempdata

    # interpolation for the border of the small square wafer
    indices = np.argwhere(small_border == 1)
    data[np.nonzero(np.repeat(small_border[np.newaxis, :, :], nbz,
                              axis=0))] = 0  # exclude border points
    for frame in range(nbz):  # loop over 2D images in the detector plane
        tempdata = data[frame, :, :]
        for idx in range(indices.shape[0]):
            pixrow = indices[idx, 0]
            pixcol = indices[idx, 1]
            counter = (9 - small_border[pixrow - 1:pixrow + 2,
                                        pixcol - 1:pixcol + 2].sum()
                       )  # number of pixels in a 3x3 window
            # which do not belong to the border
            tempdata[pixrow, pixcol] = (
                tempdata[pixrow - 1:pixrow + 2, pixcol - 1:pixcol + 2].sum() /
                counter)
        data[frame, :, :] = tempdata

    if debugging:
        width = 40
        _, (ax0, ax1) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6))
        ax0.plot(
            np.log10(data[:, directbeam_y, directbeam_x - width:directbeam_x +
                          width].sum(axis=0)))
        ax0.set_title("horizontal cut after interpolating border")
        ax0.vlines(
            x=[
                width + pixels_large[2],
                width + pixels_large[3],
                width + pixels_small[2],
                width + pixels_small[3],
            ],
            ymin=ax0.get_ylim()[0],
            ymax=ax0.get_ylim()[1],
            colors="b",
            linestyle="dashed",
        )
        ax1.plot(
            np.log10(data[:, directbeam_y - width:directbeam_y + width,
                          directbeam_x].sum(axis=0)))
        ax1.set_title("vertical cut after interpolating border")
        ax1.vlines(
            x=[
                width + pixels_large[0],
                width + pixels_large[1],
                width + pixels_small[0],
                width + pixels_small[1],
            ],
            ymin=ax1.get_ylim()[0],
            ymax=ax1.get_ylim()[1],
            colors="b",
            linestyle="dashed",
        )

        gu.imshow_plot(
            data,
            sum_frames=True,
            sum_axis=0,
            vmin=0,
            vmax=11,
            plot_colorbar=True,
            scale="log",
            title="data after interpolating the border of beam stops",
            is_orthogonal=False,
            reciprocal_space=True,
        )
    return data
Exemple #6
0
def main(parameters):
    """
    Protection for multiprocessing.

    :param parameters: dictionnary containing input parameters
    """

    def collect_result(result):
        """
        Callback processing the result after asynchronous multiprocessing. Update the global arrays.

        :param result: the output of load_p10_file, containing the 2d data, 2d mask, counter for each frame, and the
         file index
        """
        nonlocal sumdata, mask, counter, nb_files, current_point
        # result is a tuple: data, mask, counter, file_index
        current_point += 1
        sumdata = sumdata + result[0]
        mask[np.nonzero(result[1])] = 1
        counter.append(result[2])

        sys.stdout.write('\rFile {:d} / {:d}'.format(current_point, nb_files))
        sys.stdout.flush()

    ######################################
    # load the dictionnary of parameters #
    ######################################
    scan = parameters['scan']
    samplename = parameters['sample_name']
    rootdir = parameters['rootdir']
    image_nb = parameters['file_list']
    counterroi = parameters['counter_roi']
    savedir = parameters['savedir']
    load_scan = parameters['is_scan']
    compare_end = parameters['compare_ends']
    savemask = parameters['save_mask']
    multiproc = parameters['multiprocessing']
    threshold = parameters['threshold']
    cb_min = parameters['cb_min']
    cb_max = parameters['cb_max']
    grey_bckg = parameters['grey_bckg']
    ###################
    # define colormap #
    ###################
    if grey_bckg:
        bad_color = '0.7'
    else:
        bad_color = '1.0'  # white background
    colormap = gu.Colormap(bad_color=bad_color)
    my_cmap = colormap.cmap

    #######################
    # Initialize detector #
    #######################
    detector = exp.Detector(name=parameters['detector'])
    nb_pixel_y, nb_pixel_x = detector.nb_pixel_y, detector.nb_pixel_x
    sumdata = np.zeros((nb_pixel_y, nb_pixel_x))
    mask = np.zeros((nb_pixel_y, nb_pixel_x))
    counter = []

    ####################
    # Initialize paths #
    ####################
    if type(image_nb) == int:
        image_nb = [image_nb]
    if len(counterroi) == 0:
        counterroi = [0, nb_pixel_y, 0, nb_pixel_x]

    assert (counterroi[0] >= 0
            and counterroi[1] <= nb_pixel_y
            and counterroi[2] >= 0
            and counterroi[3] <= nb_pixel_x), 'counter_roi setting does not match the detector size'
    nb_files = len(image_nb)
    if nb_files == 1:
        multiproc = False

    if load_scan:  # scan or time series
        detector.datadir = rootdir + samplename + '_' + str('{:05d}'.format(scan)) + '/e4m/'
        template_file = detector.datadir + samplename + '_' + str('{:05d}'.format(scan)) + "_data_"
    else:  # single image
        detector.datadir = rootdir + samplename + '/e4m/'
        template_file = detector.datadir + samplename + '_take_' + str('{:05d}'.format(scan)) + "_data_"
        compare_end = False

    detector.savedir = savedir or os.path.abspath(os.path.join(detector.datadir, os.pardir)) + '/'
    print(f'datadir: {detector.datadir}')
    print(f'savedir: {detector.savedir}')

    #############
    # Load data #
    #############
    plt.ion()
    filenames = [template_file + '{:06d}.h5'.format(image_nb[idx]) for idx in range(nb_files)]
    roi_counter = None
    current_point = 0
    start = time.time()

    if multiproc:
        print("\nNumber of processors used: ", min(mp.cpu_count(), len(filenames)))
        mp.freeze_support()
        pool = mp.Pool(processes=min(mp.cpu_count(), len(filenames)))  # use this number of processes

        for file in range(nb_files):
            pool.apply_async(load_p10_file, args=(detector, filenames[file], file, counterroi, threshold),
                             callback=collect_result, error_callback=util.catch_error)

        pool.close()
        pool.join()  # postpones the execution of next line of code until all processes in the queue are done.

        # sort out counter values (we are using asynchronous multiprocessing, order is not preserved)
        roi_counter = sorted(counter, key=lambda x: x[1])

    else:
        for idx in range(nb_files):
            sys.stdout.write('\rLoading file {:d}'.format(idx + 1) + ' / {:d}'.format(nb_files))
            sys.stdout.flush()
            h5file = h5py.File(filenames[idx], 'r')
            data = h5file['entry']['data']['data'][:]
            data[data <= threshold] = 0
            nbz, nby, nbx = data.shape
            [counter.append(data[index, counterroi[0]:counterroi[1], counterroi[2]:counterroi[3]].sum())
                for index in range(nbz)]
            if compare_end and nb_files == 1:
                data_start, _ = detector.mask_detector(data=data[0, :, :], mask=mask)
                data_start = data_start.astype(float)
                data_stop, _ = detector.mask_detector(data=data[-1, :, :], mask=mask)
                data_stop = data_stop.astype(float)

                fig, _, _ = gu.imshow_plot(data_stop - data_start, plot_colorbar=True, scale='log',
                                           title='difference between the last frame and the first frame of the series')
            nb_frames = data.shape[0]  # collect the number of frames in the eventual series
            data, mask = detector.mask_detector(data=data.sum(axis=0), mask=mask, nb_img=nb_frames)
            sumdata = sumdata + data
            roi_counter = [[counter, idx]]

    end = time.time()
    print('\nTime ellapsed for loading data:', str(datetime.timedelta(seconds=int(end - start))))

    frame_per_series = int(len(counter) / nb_files)

    print('')
    if load_scan:
        if nb_files > 1:
            plot_title = 'masked data - sum of ' + str(nb_files)\
                         + ' points with {:d} frames each'.format(frame_per_series)
        else:
            plot_title = 'masked data - sum of ' + str(frame_per_series) + ' frames'
        filename = 'S' + str(scan) + '_scan.png'
    else:  # single image
        plot_title = 'masked data'
        filename = 'S' + str(scan) + '_image_' + str(image_nb[0]) + '.png'

    if savemask:
        fig, _, _ = gu.imshow_plot(mask, plot_colorbar=False, title='mask')
        np.savez_compressed(detector.savedir+'hotpixels.npz', mask=mask)
        fig.savefig(detector.savedir + 'mask.png')

    y0, x0 = np.unravel_index(abs(sumdata).argmax(), sumdata.shape)
    print("Max at (y, x): ", y0, x0, ' Max = ', int(sumdata[y0, x0]))

    np.savez_compressed(detector.savedir + f'{sample_name}_{scan_nb:05d}_sumdata.npz', data=sumdata)
    if save_to_mat:
        savemat(detector.savedir + f'{sample_name}_{scan_nb:05d}_sumdata.mat', {'data': sumdata})

    if len(roi_counter[0][0]) > 1:  # roi_counter[0][0] is the list of counter intensities in a series
        int_roi = []
        [int_roi.append(val[0][idx]) for val in roi_counter for idx in range(frame_per_series)]
        plt.figure()
        plt.plot(np.asarray(int_roi))
        plt.title('Integrated intensity in counter_roi')
        plt.pause(0.1)

    cb_min = cb_min or sumdata.min()
    cb_max = cb_max or sumdata.max()

    fig, _, _ = gu.imshow_plot(sumdata, plot_colorbar=True, title=plot_title, vmin=cb_min, vmax=cb_max, scale='log',
                               cmap=my_cmap)
    np.savez_compressed(detector.savedir + 'hotpixels.npz', mask=mask)
    fig.savefig(detector.savedir + filename)
    plt.show()
Exemple #7
0
        labels = (
            (
                "detector X",
                "detector Y",
                "stacking axis",
            ),  # labels for x axis, y axis, title
            ("detector X", "stacking axis", "detector Y"),
            ("detector Y", "stacking axis", "detector X"),
        )

    fig, ax, _ = gu.imshow_plot(
        dataset[cen_z, :, :],
        sum_frames=False,
        width_v=2 * width[1],
        width_h=2 * width[2],
        scale=plot_scale,
        vmin=vmin,
        vmax=vmax,
        reciprocal_space=False,
        is_orthogonal=is_orthogonal,
        plot_colorbar=True,
    )

    gu.savefig(
        savedir=savedir,
        figure=fig,
        axes=ax,
        tick_width=tick_width,
        tick_length=tick_length,
        tick_labelsize=16,
        xlabels=labels[0][0],
        ylabels=labels[0][1],
Exemple #8
0
        counter.append(data[index, counter_roi[0]:counter_roi[1],
                            counter_roi[2]:counter_roi[3]].sum())
        for index in range(nbz)
    ]
    if compare_ends and nb_files == 1:
        data_start, _ = pru.mask_eiger4m(data=data[0, :, :], mask=mask)
        data_start[np.log10(data_start) > high_threshold] = 0
        data_start = data_start.astype(float)
        data_stop, _ = pru.mask_eiger4m(data=data[-1, :, :], mask=mask)
        data_stop[np.log10(data_stop) > high_threshold] = 0
        data_stop = data_stop.astype(float)

        fig, _, _ = gu.imshow_plot(
            data_stop - data_start,
            plot_colorbar=True,
            scale='log',
            title=
            'difference between the last frame and the first frame of the series'
        )

    data = data.sum(axis=0)  # data becomes 2D
    mask[np.log10(data) > high_threshold] = 1
    data[mask == 1] = 0
    sumdata = sumdata + data
    sys.stdout.write('\rLoading file {:d}'.format(idx + 1) +
                     ' / {:d}'.format(nb_files))
    sys.stdout.flush()

print('')
if is_scan:
    if nb_files > 1:
Exemple #9
0
def main(parameters):
    """
    Protection for multiprocessing.

    :param parameters: dictionnary containing input parameters
    """
    def collect_result(result):
        """
        Callback processing the result after asynchronous multiprocessing.

        Update the global arrays.

        :param result: the output of load_p10_file, containing the 2d data, 2d mask,
         counter for each frame, and the file index
        """
        nonlocal sumdata, mask, counter, nb_files, current_point
        # result is a tuple: data, mask, counter, file_index
        current_point += 1
        sumdata = sumdata + result[0]
        mask[np.nonzero(result[1])] = 1
        counter.append(result[2])

        sys.stdout.write("\rFile {:d} / {:d}".format(current_point, nb_files))
        sys.stdout.flush()

    ######################################
    # load the dictionnary of parameters #
    ######################################
    scan = parameters["scan"]
    samplename = parameters["sample_name"]
    rootdir = parameters["rootdir"]
    image_nb = parameters["file_list"]
    counterroi = parameters["counter_roi"]
    savedir = parameters["savedir"]
    load_scan = parameters["is_scan"]
    compare_end = parameters["compare_ends"]
    savemask = parameters["save_mask"]
    multiproc = parameters["multiprocessing"]
    threshold = parameters["threshold"]
    cb_min = parameters["cb_min"]
    cb_max = parameters["cb_max"]
    grey_bckg = parameters["grey_bckg"]
    ###################
    # define colormap #
    ###################
    if grey_bckg:
        bad_color = "0.7"
    else:
        bad_color = "1.0"  # white background
    my_cmap = ColormapFactory(bad_color=bad_color).generate_cmap()

    #######################
    # Initialize detector #
    #######################
    detector = create_detector(name=parameters["detector"])
    nb_pixel_y, nb_pixel_x = detector.nb_pixel_y, detector.nb_pixel_x
    sumdata = np.zeros((nb_pixel_y, nb_pixel_x))
    mask = np.zeros((nb_pixel_y, nb_pixel_x))
    counter = []

    ####################
    # Initialize paths #
    ####################
    if isinstance(image_nb, int):
        image_nb = [image_nb]
    if len(counterroi) == 0:
        counterroi = [0, nb_pixel_y, 0, nb_pixel_x]

    if not (counterroi[0] >= 0 and counterroi[1] <= nb_pixel_y
            and counterroi[2] >= 0 and counterroi[3] <= nb_pixel_x):
        raise ValueError(
            "counter_roi setting does not match the detector size")

    nb_files = len(image_nb)
    if nb_files == 1:
        multiproc = False

    if load_scan:  # scan or time series
        detector.datadir = (rootdir + samplename + "_" +
                            str("{:05d}".format(scan)) + "/e4m/")
        template_file = (detector.datadir + samplename + "_" +
                         str("{:05d}".format(scan)) + "_data_")
    else:  # single image
        detector.datadir = rootdir + samplename + "/e4m/"
        template_file = (detector.datadir + samplename + "_take_" +
                         str("{:05d}".format(scan)) + "_data_")
        compare_end = False

    detector.savedir = (
        savedir
        or os.path.abspath(os.path.join(detector.datadir, os.pardir)) + "/")
    print(f"datadir: {detector.datadir}")
    print(f"savedir: {detector.savedir}")

    #############
    # Load data #
    #############
    plt.ion()
    filenames = [
        template_file + "{:06d}.h5".format(image_nb[idx])
        for idx in range(nb_files)
    ]
    roi_counter = None
    current_point = 0
    start = time.time()

    if multiproc:
        print("\nNumber of processors used: ",
              min(mp.cpu_count(), len(filenames)))
        mp.freeze_support()
        pool = mp.Pool(processes=min(
            mp.cpu_count(), len(filenames)))  # use this number of processes

        for file in range(nb_files):
            pool.apply_async(
                load_p10_file,
                args=(detector, filenames[file], file, counterroi, threshold),
                callback=collect_result,
                error_callback=util.catch_error,
            )

        pool.close()
        pool.join()  # postpones the execution of next line of code
        # until all processes in the queue are done.

        # sort out counter values
        # (we are using asynchronous multiprocessing, order is not preserved)
        roi_counter = sorted(counter, key=lambda x: x[1])

    else:
        for idx in range(nb_files):
            sys.stdout.write("\rLoading file {:d}".format(idx + 1) +
                             " / {:d}".format(nb_files))
            sys.stdout.flush()
            h5file = h5py.File(filenames[idx], "r")
            data = h5file["entry"]["data"]["data"][:]
            data[data <= threshold] = 0
            nbz, _, _ = data.shape
            for index in range(nbz):
                counter.append(data[index, counterroi[0]:counterroi[1],
                                    counterroi[2]:counterroi[3], ].sum())

            if compare_end and nb_files == 1:
                data_start, _ = detector.mask_detector(data=data[0, :, :],
                                                       mask=mask)
                data_start = data_start.astype(float)
                data_stop, _ = detector.mask_detector(data=data[-1, :, :],
                                                      mask=mask)
                data_stop = data_stop.astype(float)

                fig, _, _ = gu.imshow_plot(
                    data_stop - data_start,
                    plot_colorbar=True,
                    scale="log",
                    title="""difference between the last frame and
                    the first frame of the series""",
                )
            nb_frames = data.shape[
                0]  # collect the number of frames in the eventual series
            data, mask = detector.mask_detector(data=data.sum(axis=0),
                                                mask=mask,
                                                nb_frames=nb_frames)
            sumdata = sumdata + data
            roi_counter = [[counter, idx]]

    end = time.time()
    print(
        "\nTime ellapsed for loading data:",
        str(datetime.timedelta(seconds=int(end - start))),
    )

    frame_per_series = int(len(counter) / nb_files)

    print("")
    if load_scan:
        if nb_files > 1:
            plot_title = (
                "masked data - sum of " + str(nb_files) +
                " points with {:d} frames each".format(frame_per_series))
        else:
            plot_title = "masked data - sum of " + str(
                frame_per_series) + " frames"
        filename = "S" + str(scan) + "_scan.png"
    else:  # single image
        plot_title = "masked data"
        filename = "S" + str(scan) + "_image_" + str(image_nb[0]) + ".png"

    if savemask:
        fig, _, _ = gu.imshow_plot(mask, plot_colorbar=False, title="mask")
        np.savez_compressed(detector.savedir + "hotpixels.npz", mask=mask)
        fig.savefig(detector.savedir + "mask.png")

    y0, x0 = np.unravel_index(abs(sumdata).argmax(), sumdata.shape)
    print("Max at (y, x): ", y0, x0, " Max = ", int(sumdata[y0, x0]))

    np.savez_compressed(detector.savedir +
                        f"{sample_name}_{scan_nb:05d}_sumdata.npz",
                        data=sumdata)
    if save_to_mat:
        savemat(
            detector.savedir + f"{sample_name}_{scan_nb:05d}_sumdata.mat",
            {"data": sumdata},
        )

    if len(roi_counter[0][0]) > 1:
        # roi_counter[0][0] is the list of counter intensities in a series
        int_roi = [
            val[0][idx] for val in roi_counter
            for idx in range(frame_per_series)
        ]
        plt.figure()
        plt.plot(np.asarray(int_roi))
        plt.title("Integrated intensity in counter_roi")
        plt.pause(0.1)

    cb_min = cb_min or sumdata.min()
    cb_max = cb_max or sumdata.max()

    fig, _, _ = gu.imshow_plot(
        sumdata,
        plot_colorbar=True,
        title=plot_title,
        vmin=cb_min,
        vmax=cb_max,
        scale="log",
        cmap=my_cmap,
    )
    np.savez_compressed(detector.savedir + "hotpixels.npz", mask=mask)
    fig.savefig(detector.savedir + filename)
    plt.show()