def AdvancedBraggEdgeFitting(
    myspectrum, myrange, myTOF, est_pos, est_sigma, est_alpha, bool_print,
    bool_average, bool_linear, bool_transmission
):  ## my range should be now the index position of the spectra that I want to study, est_pos is also the index position where the expected peak is

    #get the part of the spectrum that I want to fit
    mybragg = myspectrum[myrange[0]:myrange[1]]

    if (bool_average):
        mybragg = running_mean(mybragg, 3)

    t = myTOF[myrange[0]:myrange[1]]
    est_pos = est_pos - myrange[
        0]  # I move the estimated position relative to the studied range, this is an index
    t0_f = myTOF[
        est_pos +
        myrange[0]]  # this is the actual estimated first position in TOF [s]

    plt.figure()
    plt.plot(t, mybragg)
    plt.plot(t0_f, mybragg[est_pos], 'x', markeredgewidth=3, c='orange')
    plt.title('Bragg edge')
    plt.xlabel('Wavelenght [Å]')
    plt.ylabel('Tranmission I/I$_{0}$')
    #     plt.savefig('step1_fitting.pdf')

    t_before = t[0:est_pos]
    bragg_before = mybragg[0:est_pos]
    #     t_after= t[est_pos+int(est_pos*0.2):-1]
    #     bragg_after=mybragg[est_pos+int(est_pos*0.2):-1]
    t_after = t[est_pos + int(est_pos * 0.2):-1]
    bragg_after = mybragg[est_pos + int(est_pos * 0.2):-1]

    #first step: estimate the linear or exponential function before and after the Bragg Edge

    if (bool_linear):
        [slope_before,
         interception_before] = np.polyfit(t_before, bragg_before, 1)
        [slope_after, interception_after] = np.polyfit(t_after, bragg_after, 1)
        #first guess of paramters
        a2_f = slope_after
        a5_f = interception_before
        a6_f = slope_before
        a1_f = interception_after
        plt.figure()
        plt.plot(t_before, bragg_before, '.g')
        plt.plot(t_after, bragg_after, '.r')
        plt.plot(t, mybragg)
        plt.plot(t, interception_before + slope_before * t, 'g')
        plt.plot(t, interception_after + slope_after * t, 'r')
        plt.title('linear fitting before and after the given edge position')
        gmodel = Model(BraggEdgeLinear)
    else:
        [slope_before,
         interception_before] = np.polyfit(t_before, bragg_before, 1)
        [slope_after, interception_after] = np.polyfit(t_after, bragg_after, 1)
        #first guess of paramters
        a2_f = slope_after
        a5_f = interception_before
        a6_f = slope_before
        a1_f = interception_after

        exp_model_after = Model(exp_after)
        params = exp_model_after.make_params(a1=a1_f, a2=a2_f)
        result_exp_model_after = exp_model_after.fit(bragg_after,
                                                     params,
                                                     t=t_after)
        a1_f = result_exp_model_after.best_values.get('a1')
        a2_f = result_exp_model_after.best_values.get('a2')

        exp_model_before = Model(exp_combined)
        params = exp_model_before.make_params(a1=a1_f,
                                              a2=a2_f,
                                              a5=a5_f,
                                              a6=a6_f)
        params['a1'].vary = False
        params['a2'].vary = False
        result_exp_model_before = exp_model_before.fit(bragg_before,
                                                       params,
                                                       t=t_before)
        a5_f = result_exp_model_before.best_values.get('a5')
        a6_f = result_exp_model_before.best_values.get('a6')
        gmodel = Model(BraggEdgeExponential)
        plt.figure()
        plt.plot(t_before, bragg_before, '.r', label='int point')
        plt.plot(t_after, bragg_after, '.g', label='int point')
        plt.plot(t, mybragg)

        plt.plot(t,
                 interception_before + slope_before * t,
                 '--r',
                 label='firred line before')
        plt.plot(t,
                 interception_after + slope_after * t,
                 '--g',
                 label='fitted line after')
        plt.plot(t, exp_after(t, a1_f, a2_f), 'g', label='fitted exp before')
        plt.plot(t,
                 exp_combined(t, a1_f, a2_f, a5_f, a6_f),
                 'r',
                 label='fitted exp after')
        plt.xlabel('Wavelenght [Å]')
        plt.ylabel('Transmission I/I$_{0}$')
        plt.title('fitting before and after the given edge position')
        plt.legend()
#         plt.savefig('step2_fitting_legend.pdf')
#         plt.plot(t, BraggEdgeExponential(t,t0_f,est_alpha,est_sigma,a1_f,a2_f,a5_f,a6_f))

    sigma_f = est_sigma
    alpha_f = est_alpha
    # method='trust_exact'
    # method='nelder' #not bad
    # method='differential_evolution' # needs bounds
    # method='basinhopping' # not bad
    # method='lmsquare' # this should implement the Levemberq-Marquardt but it says Nelder-Mead method (which should be Amoeba)
    method = 'least_squares'  # default and it implements the Levenberg-Marquardt

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f,
                                bool_trasmission=bool_transmission)
    print(bool_transmission)

    first_guess = gmodel.eval(params, t=t)
    plt.figure()
    plt.plot(t, mybragg, label='data')
    plt.plot(t, first_guess, '--b', label='initial model')
    plt.title('initial BE with given parameters')
    plt.xlabel('Wavelenght [Å]')
    plt.ylabel('Transmission I/I$_{0}$')
    plt.legend()
    #     plt.savefig('step3_fitting_legend.pdf')

    params['alpha'].vary = False
    params['sigma'].vary = False
    params['t0'].vary = False
    params['a2'].vary = False
    params['a5'].vary = False
    params['bool_transmission'].vary = False

    result1 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         method=method,
                         nan_policy='propagate')
    #    print(result1.fit_report())

    a1_f = result1.best_values.get('a1')
    a6_f = result1.best_values.get('a6')

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f,
                                bool_trasmission=bool_transmission)
    params['alpha'].vary = False
    params['sigma'].vary = False
    params['t0'].vary = False
    params['a1'].vary = False
    params['a6'].vary = False
    params['bool_transmission'].vary = False

    result2 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         method=method,
                         nan_policy='propagate')

    a2_f = result2.best_values.get('a2')
    a5_f = result2.best_values.get('a5')

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f,
                                bool_trasmission=bool_transmission)
    params['a2'].vary = False
    params['a5'].vary = False
    params['a1'].vary = False
    params['a6'].vary = False
    params['sigma'].vary = False
    params['alpha'].vary = False
    params['bool_transmission'].vary = False
    params['t0'].min = myTOF[myrange[0]]
    params['t0'].max = myTOF[myrange[1]]

    result3 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         method=method,
                         nan_policy='propagate')

    t0_f = result3.best_values.get('t0')

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f,
                                bool_trasmission=bool_transmission)
    params['a2'].vary = False
    params['a5'].vary = False
    params['a1'].vary = False
    params['a6'].vary = False
    params['bool_transmission'].vary = False
    params['t0'].min = myTOF[myrange[0]]
    params['t0'].max = myTOF[myrange[1]]
    params['alpha'].min = 0.0
    params['alpha'].max = 1.5
    params['sigma'].min = 0.0
    params['sigma'].max = 1.5

    result4 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         nan_policy='propagate',
                         method=method)

    sigma_f = result4.best_values.get('sigma')
    alpha_f = result4.best_values.get('alpha')
    t0_f = result4.best_values.get('t0')

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f,
                                bool_trasmission=bool_transmission)
    params['t0'].vary = False
    params['sigma'].vary = False
    params['alpha'].vary = False
    params['bool_transmission'].vary = False

    result5 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         nan_policy='propagate',
                         method=method)

    a1_f = result5.best_values.get('a1')
    a2_f = result5.best_values.get('a2')
    a5_f = result5.best_values.get('a5')
    a6_f = result5.best_values.get('a6')

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f,
                                bool_trasmission=bool_transmission)
    params['a2'].vary = False
    params['a5'].vary = False
    params['a1'].vary = False
    params['a6'].vary = False
    params['bool_transmission'].vary = False
    params['t0'].min = myTOF[myrange[0]]
    params['t0'].max = myTOF[myrange[1]]
    params['alpha'].min = 0.0
    params['alpha'].max = 1.5
    params['sigma'].min = 0.0
    params['sigma'].max = 1.5

    result6 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         nan_policy='propagate',
                         method=method)

    t0_f = result6.best_values.get('t0')
    sigma_f = result6.best_values.get('sigma')
    alpha_f = result6.best_values.get('alpha')

    params = gmodel.make_params(t0=t0_f,
                                sigma=sigma_f,
                                alpha=alpha_f,
                                a1=a1_f,
                                a2=a2_f,
                                a5=a5_f,
                                a6=a6_f)
    params['bool_transmission'].vary = False
    params['t0'].min = myTOF[myrange[0]]
    params['t0'].max = myTOF[myrange[1]]
    params['alpha'].min = 0.0
    params['alpha'].max = 1.5
    params['sigma'].min = 0.0
    params['sigma'].max = 1.5

    result7 = gmodel.fit(mybragg,
                         params,
                         t=t,
                         nan_policy='propagate',
                         method=method)

    #     print(params)
    print(result7.fit_report())
    print(result7.covar)
    print('bool value, Boolean for whether error bars were estimated by fit.',
          result7.errorbars)
    print(result7.ci_out)  # print out the interval confidence
    #     print(result7.conf_interval())
    #     print(result7.ci_report()) # this crashes sometimes when the MinimizerException: Cannot determine Confidence Intervals without sensible uncertainty estimates

    t0_f = result7.best_values.get('t0')
    sigma_f = result7.best_values.get('sigma')
    alpha_f = result7.best_values.get('alpha')
    a1_f = result7.best_values.get('a1')
    a2_f = result7.best_values.get('a2')
    a5_f = result7.best_values.get('a5')
    a6_f = result7.best_values.get('a6')

    #    Get the extrema for edge height fitting
    fitted_data = result7.best_fit
    pos_extrema = []

    ## Attempt n.1 -------- Here I was searching the last 0 value and the first value with 1.0 in the step function, however is it not a robust solution
    #     step_function = B(t,t0_f,alpha_f,sigma_f)
    #     min_pos = find_last(step_function,0.0)
    #     pos_extrema.append(min_pos)
    #     max_pos = find_first(step_function,0.99)
    #     pos_extrema.append(max_pos)

    if (bool_linear):
        fit_before = line_before(t, a5_f, a6_f)
        fit_after = line_after(t, a1_f, a2_f)
    else:
        fit_before = exp_combined(t, a1_f, a2_f, a5_f, a6_f)
        fit_after = exp_after(t, a1_f, a2_f)

    fit_edge = B(t, t0_f, alpha_f, sigma_f, bool_transmission)

    plt.figure()
    plt.plot(t, fit_before, 'o-')
    plt.plot(t, fit_after, 'o-')
    plt.plot(t, fitted_data, '.-')

    index_t0 = find_nearest(t, t0_f)

    # Attempt n.2 ------This is Florencia's approach: this gives an overestimation in most cases of the edge height
    #     pos_extrema.append(fit_before[index_t0])
    #     pos_extrema.append(fit_after[index_t0])

    # Attempt n.3 ------ This approach is based on the difference between the fit before and after the edge and the fitted data itself. so far, it gives the nicest results on the calibration sample, however the value used as threshold is not general and should probably be adjusted from case to case. So again it is not yet the final solution

    for i in range(0, len(fitted_data)):
        #         print(i,(fitted_data[i]-fit_before[i]))
        if (np.abs(fitted_data[i] - fit_before[i]) > 1e-4):
            pos_extrema.append(i - 1)
            break

    for i in range(len(fitted_data) - 1, 0, -1):  # here I am moving backwards
        #         print(i,(fitted_data[i]-fit_after[i]))
        if (np.abs(fitted_data[i] - fit_after[i]) > 1e-3):
            pos_extrema.append(i)
            break

#     # Attempt n.4 -- max and min before and after the estimated edge position, for the calibration sample works fine
#     range_min = t[0:index_t0]
#     range_max= t[index_t0:-1]
#     min_fit = np.min(fitted_data[0:index_t0])
#     max_fit = np.max(fitted_data[index_t0:-1])
#     pos_min = find_nearest(fitted_data[0:index_t0], min_fit)
#     pos_max = index_t0+find_nearest(fitted_data[index_t0:-1], max_fit)

## For other attempts have a look in the SENJU branch

    height = np.abs(mybragg[pos_extrema[0]] - mybragg[pos_extrema[1]])

    plt.figure()
    plt.plot(t, mybragg)
    #     plt.plot(t, result7.init_fit, 'k--')

    plt.plot(t,
             result1.best_fit,
             '--',
             color='gray',
             label='intermediate steps')
    plt.plot(t, result1.init_fit, '--', color='gray')
    plt.plot(t, result2.best_fit, '--', color='gray')
    plt.plot(t, result3.best_fit, '--', color='gray')
    plt.plot(t, result4.best_fit, '--', color='gray')
    plt.plot(t, result5.best_fit, '--', color='gray')
    plt.plot(t, result6.best_fit, '--', color='gray')
    plt.plot(t, result7.best_fit, 'r', linewidth='1.5', label='final fit')
    plt.legend()
    plt.xlabel('Wavelenght [Å]')
    plt.ylabel('Transmission I/I$_{0}$')

    plt.plot(t0_f, result7.best_fit[index_t0], 'ok')
    plt.plot(t[pos_extrema[0]], result7.best_fit[pos_extrema[0]], 'ok')
    plt.plot(t[pos_extrema[1]], result7.best_fit[pos_extrema[1]], 'ok')
    plt.title('edge fitting and estimated edge position')
    plt.show()

    if (bool_print):
        print('first iteration: ', result1.fit_report())
        print('second iteration: ', result2.fit_report())
        print('third iteration: ', result3.fit_report())
        print('fourth iteration: ', result4.fit_report())
        print('fifth iteration: ', result5.fit_report())
        print('sixth iteration: ', result6.fit_report())

    return {
        't0': t0_f,
        'sigma': sigma_f,
        'alpha': alpha_f,
        'a1': a1_f,
        'a2': a2_f,
        'a5': a5_f,
        'a6': a6_f,
        'final_result': result7,
        'fitted_data': fitted_data,
        'pos_extrema': pos_extrema,
        'height': height
    }
Example #2
0
def image_edge_fitting_Ttof_gauss(pathdata,
                                  pathspectrum,
                                  lambda_range,
                                  filemask=0,
                                  t0_cal=-0.0002618673892937752,
                                  L_cal=18.961609065251505,
                                  est_pos=0,
                                  bool_save=0,
                                  bool_print=1):
    """ Run edge_fitting on provided 3D image, the third dimension is supposed to be lambda(A) or TOF     
    ##INPUTS:
    #pathdata: path to sample transmission images
    #filemask: path to the .tif mask of the region to fit. if not specified runs over the whole area
    #pathspectrum: path to the .txt spectrum (in tof)
    #t0_cal: t0 for conversion from tof to lambda
    #L_cal: L for conversion from tof to lambda
    #lambda_range: lambda range for single edge fitting (in Angstrom): 2 values array
    #est_pos: expected bragg edge position (in A), if unset is found automatically
    #bool_save: flag for data saving
    #bool_print: flag for image printing
    
    ##OUTPUTS:
    #dictionary with the following fit in the dimension of the mask
    #'edge_position' : edge position
    #'edge_height': edge height
    #'edge_width': edge width
    """

    debug_flag = 1

    files_sample = (sorted(fnmatch.filter(listdir(pathdata), '*.tif')))

    #load the spectrum
    spectrum = np.loadtxt(pathspectrum, usecols=0)

    mylambda_bin = tof2l(spectrum, t0_cal, L_cal)

    ob = io.imread(pathdata + '/' + files_sample[0])

    sample_image = np.zeros(
        [np.shape(ob)[0], np.shape(ob)[1],
         len(files_sample)])

    if (filemask):
        mymask = io.imread(filemask)
        if ([np.shape(sample_image)[0],
             np.shape(sample_image)[1]] !=
            [np.shape(mymask)[0], np.shape(mymask)[1]]):
            print('WARNING: Mask size does not match frames size')
    else:
        mymask = np.ones(
            [np.shape(sample_image)[0],
             np.shape(sample_image)[1]])

    #read the images, in this example they are already selected in a neighborhood of the studied edge
    for i in range(0, len(files_sample)):
        sample_image[:, :,
                     i] = io.imread(pathdata + '/' + files_sample[i]) / 256

    #here define the lambda range to be used for single edge fitting
    myrange = []
    myrange.append(find_nearest(mylambda_bin, lambda_range[0]))  # 3.7
    myrange.append(find_nearest(mylambda_bin, lambda_range[1]))  # 4.2
    if (debug_flag):  #testing on a single pixel
        plt.imshow(sample_image.sum(axis=2))
        plt.show()
        plt.close()
        sp = np.zeros(len(files_sample))
        for i in range(0, len(files_sample)):
            sp[i] = np.median(
                sample_image[256, 256,
                             i])  # This is for the first Bragg edge fitting
        #run once the fitting to check if everything works
        AdvancedBraggEdgeFitting.GaussianBraggEdgeFitting(myspectrum=sp,
                                                          myTOF=mylambda_bin,
                                                          myrange=myrange,
                                                          est_pos=est_pos,
                                                          bool_smooth=1,
                                                          smooth_w=3,
                                                          smooth_n=0,
                                                          bool_print=1)

    edge_position = np.zeros(np.shape(mymask))
    edge_width = np.zeros(np.shape(mymask))
    edge_height = np.zeros(np.shape(mymask))
    #loop for all pixel position, where the mask is equal to one
    start_time = time.time()
    for i in range(0, np.shape(mymask)[0]):
        #print('processing row n. ', i, 'of', np.shape(mymask)[0])
        for j in range(0, np.shape(mymask)[1]):
            if (mymask[i, j]):
                print(i, j)
                mysignal = np.zeros(len(files_sample))
                for ind in range(0, len(files_sample)):
                    mysignal[ind] = np.median(sample_image[i, j, ind])
                try:
                    edge_fit = AdvancedBraggEdgeFitting.GaussianBraggEdgeFitting(
                        myspectrum=mysignal,
                        myTOF=mylambda_bin,
                        myrange=myrange,
                        est_pos=est_pos,
                        bool_smooth=1,
                        smooth_w=3,
                        smooth_n=0,
                        bool_print=debug_flag)
                    edge_position[i, j] = edge_fit['t0']
                    edge_height[i, j] = edge_fit['edge_height']
                    edge_width[i, j] = edge_fit['edge_width']
                except:
                    print("Unexpected error at :", i, j)
                    edge_position[i, j] = -2.0
                    edge_width[i, j] = -2.0
                    edge_height[i, j] = -2.0
                print("--- %s seconds ---" % (time.time() - start_time))

    if (bool_print):
        plt.figure()
        plt.imshow(edge_position)
        plt.figure()
        plt.imshow(edge_width)
        plt.figure()
        plt.imshow(edge_height)
    if (bool_save):
        np.save('edge_position.npy', edge_position)
        np.save('edge_height.npy', edge_height)
        np.save('edge_width.npy', edge_width)

    return {
        'edge_position': edge_position,
        'edge_height': edge_height,
        'edge_width': edge_width
    }
Example #3
0
def image_edge_fitting_Tlambda_gauss(Ttof,
                                     spectrum_l,
                                     lambda_range,
                                     filemask=0,
                                     auto_mask=True,
                                     mask_thresh=[0.05, 0.95],
                                     est_pos=0,
                                     est_wid=0,
                                     est_h=0,
                                     bool_smooth=False,
                                     smooth_w=3,
                                     smooth_n=0,
                                     bool_save=True,
                                     bool_print=True,
                                     debug_flag=False,
                                     debug_idx=[160, 200]):
    if (filemask):
        mymask = io.imread(filemask)
        if ([np.shape(Ttof)[0], np.shape(Ttof)[1]] !=
            [np.shape(mymask)[0], np.shape(mymask)[1]]):
            print('WARNING: Mask size does not match frames size')
    elif (auto_mask):
        import skimage.filters
        mymask = TOF_routines.medianimage(Ttof)
        plt.figure()
        plt.subplot(1, 3,
                    1), plt.imshow(mymask), plt.title('Full-spectrum Image')
        mymask[mymask > mask_thresh[1]] = 0.0
        mymask[mymask < mask_thresh[0]] = 0.0
        mymask[mymask > 0] = 1.0
        mymask[np.isinf(mymask)] = 0.0
        mymask[np.isnan(mymask)] = 0.0
        plt.subplot(1, 3, 2), plt.imshow(mymask), plt.title('Mask')
        mymask = skimage.filters.gaussian(mymask, sigma=2)
        mymask[mymask > 0] = 1.0
        plt.subplot(1, 3, 3), plt.imshow(mymask), plt.title('Mask - gauss')
        plt.show(), plt.close()
    else:
        mymask = np.ones([np.shape(Ttof)[0], np.shape(Ttof)[1]])

    myrange = []
    myrange.append(find_nearest(spectrum_l, lambda_range[0]))  # 3.7
    myrange.append(find_nearest(spectrum_l, lambda_range[1]))  # 4.4
    if (debug_flag):  #testing on a single pixel
        plt.imshow(Ttof.sum(axis=2))
        plt.show()
        plt.close()
        sp = np.zeros(len(spectrum_l))
        for i in range(0, len(spectrum_l)):
            sp[i] = np.median(
                Ttof[debug_idx[0], debug_idx[1],
                     i])  # This is for the first Bragg edge fitting
        #run once the fitting to check if everything works
        AdvancedBraggEdgeFitting.GaussianBraggEdgeFitting(
            myspectrum=sp,
            myTOF=spectrum_l,
            myrange=myrange,
            est_pos=est_pos,
            est_wid=est_wid,
            est_h=est_h,
            bool_smooth=bool_smooth,
            smooth_w=smooth_w,
            smooth_n=smooth_n,
            bool_print=debug_flag)

    median_image = TOF_routines.medianimage(Ttof)
    edge_position = np.zeros(np.shape(mymask))
    edge_width = np.zeros(np.shape(mymask))
    edge_height = np.zeros(np.shape(mymask))
    edge_slope = np.zeros(np.shape(mymask))
    #loop for all pixel position, where the mask is equal to one
    start_time = time.time()
    for i in range(0, np.shape(mymask)[0]):
        if (debug_flag):
            print('processing row n. ', i, 'of', np.shape(mymask)[0])
        for j in range(0, np.shape(mymask)[1]):
            if (mymask[i, j]):
                #print(i,j)
                mysignal = np.zeros(len(spectrum_l))
                for ind in range(0, len(spectrum_l)):
                    mysignal[ind] = np.median(Ttof[i, j, ind])
                try:
                    edge_fit = AdvancedBraggEdgeFitting.GaussianBraggEdgeFitting(
                        myspectrum=mysignal,
                        myTOF=spectrum_l,
                        myrange=myrange,
                        est_pos=est_pos,
                        est_wid=est_wid,
                        est_h=est_h,
                        bool_smooth=bool_smooth,
                        smooth_w=smooth_w,
                        smooth_n=smooth_n,
                        bool_print=False)
                    edge_position[i, j] = edge_fit['t0']
                    edge_height[i, j] = edge_fit['edge_height']
                    edge_width[i, j] = edge_fit['edge_width']
                    edge_slope[i, j] = edge_fit['edge_slope']
                except:
                    print("Unexpected error at :", i, j)
                    edge_position[i, j] = -2.0
                    edge_width[i, j] = -2.0
                    edge_height[i, j] = -2.0
                    edge_slope[i, j] = -2.0
    print("--- %s seconds ---" % (time.time() - start_time))

    if (bool_print):
        plt.figure(), plt.imshow(edge_position)
        plt.figure(), plt.imshow(edge_width)
        plt.figure(), plt.imshow(edge_height)
        plt.figure(), plt.imshow(edge_slope)
    if (bool_save):
        np.save('edge_position.npy', edge_position)
        np.save('edge_height.npy', edge_height)
        np.save('edge_width.npy', edge_width)
        np.save('edge_slope.npy', edge_slope)

    return {
        'edge_position': edge_position,
        'edge_height': edge_height,
        'edge_width': edge_width,
        'edge_slope': edge_slope,
        'median_image': median_image
    }
Example #4
0
def image_edge_fitting(pathdata,
                       pathob,
                       pathspectrum,
                       lambda_range,
                       filemask=0,
                       t0_cal=-0.0002618673892937752,
                       L_cal=18.961609065251505,
                       binning=1,
                       est_pos=0,
                       est_sigma=1,
                       est_alpha=1,
                       bool_dose=0,
                       bool_save=0,
                       bool_print=1):
    """ Run edge_fitting on provided 3D image, the third dimension is supposed to be lambda(A) or TOF 
    #INPUTS:
    #pathdata: path to sample transmission images
    #filemask: path to the .tif mask of the region to fit. if not specified runs over the whole area
    #pathspectrum: path to the .txt spectrum (in tof)
    #t0_cal: t0 for conversion from tof to lambda
    #L_cal: L for conversion from tof to lambda
    #lambda_range: lambda range for single edge fitting (in Angstrom): 2 values array
    #est_pos: expected bragg edge position (in A), if unset is found automatically
    #est_sigma: expected Gaussian broadening
    #est_alpha: expected decay constant (moderator property))
    #bool_save: flag for data saving
    #bool_print: flag for image printing
    
    ##OUTPUTS:
    #dictionary with the following fit in the dimension of the mask
    #'edge_position' : edge position
    #'edge_height': edge height
    #'edge_width': edge width
    """

    debug_flag = 1

    files_sample = (sorted(fnmatch.filter(listdir(pathdata), '*.tif')))
    files_ob = (sorted(fnmatch.filter(listdir(pathob), '*.tif')))
    #files_sample = (sorted(fnmatch.filter(listdir(pathdata),'*.fits')))
    #files_ob = (sorted(fnmatch.filter(listdir(pathob),'*.fits')))

    #load the spectrum
    spectrum = np.loadtxt(pathspectrum, usecols=0)
    spectrum_binned = spectrum[0::binning]

    mylambda_bin = tof2l(spectrum_binned, t0_cal, L_cal)

    ob = io.imread(pathob + '/' + files_ob[0])
    #ob = fits.getdata(pathob+'/'+files_ob[0])

    ob_image = np.zeros([np.shape(ob)[0], np.shape(ob)[1], len(files_ob)])
    sample_image = np.zeros([np.shape(ob)[0], np.shape(ob)[1], len(files_ob)])

    if (filemask):
        mymask = io.imread(filemask)
    else:
        mymask = np.ones([np.shape(ob)[0], np.shape(ob)[1], len(files_ob)])

    #read the images, in this example they are already selected in a neighborhood of the studied edge
    for i in range(0, len(files_ob)):
        #ob_image[:,:,i] = io.imread(pathob+'/'+files_ob[i])
        #sample_image[:,:,i] = io.imread(pathdata+'/'+files_sample[i])
        ob_image[:, :, i] = fits.getdata(pathob + '/' + files_ob[i])
        sample_image[:, :, i] = fits.getdata(pathdata + '/' + files_sample[i])

    #compute transmission image
    trans_image = np.zeros([np.shape(ob)[0], np.shape(ob)[1], len(files_ob)])
    dose = 1
    for i in range(0, len(files_ob)):
        if (bool_dose):
            dose = np.median(ob_image[10:20, 10:20, i]) / np.median(
                sample_image[10:20, 10:20, i])  # update the doseROI
        trans_image[:, :, i] = sample_image[:, :, i] / ob_image[:, :, i] * dose

    #here define the lambda range to be used for single edge fitting
    myrange = []
    myrange.append(find_nearest(mylambda_bin, lambda_range[0]))  # 3.7
    myrange.append(find_nearest(mylambda_bin, lambda_range[1]))  # 4.4
    if (est_pos):
        est_pos = find_nearest(mylambda_bin[myrange[0]:myrange[1]],
                               est_pos)  # 4.05

    if (debug_flag):  #testing on a single pixel
        plt.imshow(trans_image.sum(axis=2))
        plt.show()
        plt.close()
        small_range = np.array([0, myrange[1] - myrange[0] - 1])
        small_lambda = mylambda_bin[myrange[0]:myrange[1]]
        sp = np.zeros(len(files_ob))
        for i in range(0, len(files_ob)):
            sp[i] = np.median(
                trans_image[50, 50,
                            i])  # This is for the first Bragg edge fitting
        #run once the fitting to check if everything works
        AdvancedBraggEdgeFitting.AdvancedBraggEdgeFitting(
            myspectrum=sp[myrange[0]:myrange[1]],
            myrange=small_range,
            myTOF=small_lambda,
            est_pos=est_pos,
            est_sigma=est_sigma,
            est_alpha=est_alpha,
            bool_print=1,
            bool_average=0,
            bool_linear=0)

    edge_position = np.zeros(np.shape(mymask))
    edge_width = np.zeros(np.shape(mymask))
    edge_height = np.zeros(np.shape(mymask))
    #loop for all pixel position, where the mask is equal to one
    start_time = time.time()
    for i in range(0, np.shape(mymask)[0]):
        #print('processing row n. ', i, 'of', np.shape(mymask)[0])
        for j in range(0, np.shape(mymask)[1]):
            if (mymask[i, j]):
                #             print(i,j,' ciao')
                # extract the signal
                #mysignal = np.zeros(myrange[1]-myrange[0])
                mysignal = np.zeros(np.int(np.shape(ob)[2]))
                #for ind in range(myrange[0],myrange[1]):
                #mysignal[ind-myrange[0]] = np.median(trans_image[i,j,ind])
                for ind in range(0, np.int(np.shape(mysignal)[0])):
                    mysignal[ind] = np.median(trans_image[i, j, ind])
                try:
                    edge_fit = AdvancedBraggEdgeFitting.AdvancedBraggEdgeFitting(
                        myspectrum=mysignal,
                        myrange=myrange,
                        myTOF=mylambda_bin,
                        est_pos=est_pos,
                        est_sigma=est_sigma,
                        est_alpha=est_alpha,
                        bool_print=0,
                        bool_average=0,
                        bool_linear=0)
                    edge_position[i, j] = edge_fit['t0']
                    edge_height[i, j] = edge_fit['height']
                    if (len(edge_fit['pos_extrema']) == 2):
                        edge_width[i, j] = small_lambda[
                            edge_fit['pos_extrema'][1]] - small_lambda[
                                edge_fit['pos_extrema'][0]]
                    else:
                        edge_width[i, j] = -2.0
                except:
                    print("Unexpected error at :", i, j)
                    edge_position[i, j] = -2.0
                    edge_width[i, j] = -2.0
                    edge_height[i, j] = -2.0

    if (bool_print):
        plt.figure()
        plt.imshow(edge_position)
        plt.figure()
        plt.imshow(edge_width)
        plt.figure()
        plt.imshow(edge_height)
    if (bool_save):
        np.save('edge_position.npy', edge_position)
        np.save('edge_height.npy', edge_height)
        np.save('edge_width.npy', edge_width)

    print("--- %s seconds ---" % (time.time() - start_time))

    return {
        'edge_position': edge_position,
        'edge_height': edge_height,
        'edge_width': edge_width
    }