Beispiel #1
0
def EMG2DFit(x, y, data, x01h, samplewd, nSample, **kwargs):

    #data is 2-D distribution of columns (e.g. AOD, SO2 mol/m2)
    # initial guess of each parameter
    #x,y always in the grid resolution (dxy==1)
    #7 parameters to fit, similar in two different parameterizations
    #samplewd: resolution, i.e. how many km represented by 1 grid

    npar = 7  #(a,x0,ux,uy,sigma,eta,b)

    GauDecay = False
    if 'GauDecay' in kwargs:
        if kwargs['GauDecay'] == True:
            GauDecay = True

    if 'fixparam' in kwargs:
        fixpars = kwargs['fixparam']
        fixvals = kwargs['fixvalue']

    # if GauDecay == False:
    #     eta=kwargs['eta']

    if 'solver' in kwargs:
        solver = kwargs['solver']
    else:
        solver = 'trust-constr'

    #total emission (kg)
    ini_a = np.sum(data)  #dxy==1
    #location of maxima
    maxxW = x[np.nanargmax(data)]
    maxyW = y[np.nanargmax(data)]

    if np.array(maxxW).size > 1:
        maxxW = maxxW[0]
        maxyW = maxyW[0]
    #take the across-wind data at maxima to estimate sigma

    ydata = data[x == maxxW]
    peaky = y[x == maxxW]
    HM = (np.max(ydata) - np.min(ydata)) / 2. + np.min(ydata)
    FWHM = np.absolute(peaky[np.nanargmin(np.absolute(ydata - HM))] -
                       maxyW) * 2. / 2.355

    minchisquare = -1

    #latin hypercube construction of initials
    design = lhs(3, samples=nSample)
    if GauDecay == False:
        means = np.array([ini_a, x01h, FWHM])
    else:
        means = np.array([ini_a / x01h, x01h, FWHM])

    stds = nSample * means

    for i in np.arange(3):
        design[:, i] = norm(loc=means[i], scale=stds[i]).ppf(design[:, i])

    for jfit in np.arange(nSample + 1):

        if jfit < nSample:
            fitpars = design[jfit, :]
        else:
            fitpars = means

        if np.min(fitpars) < 0:
            continue
        try:
            if solver == 'trust-constr':  # Do the scipy.optimize fit using "trust_constr" method

                # initials and bounds
                x0 = np.zeros(npar)  # (a,x0,ux,uy,sigma,eta,b)
                x0[0:2] = fitpars[0:2]
                x0[2] = maxxW
                x0[3] = maxyW
                x0[4] = fitpars[2]
                x0[5] = np.min(data)
                x0[6] = 1.5 * samplewd

                bounds = Bounds([0., 1. / 3, np.min(x), np.min(y), 0.5, 0.,0.], \
                                [np.inf, np.inf, np.max(x), np.max(y), np.inf, np.max(data),np.inf])

                if 'fixparam' in kwargs:
                    for ipar in np.arange(len(fixvals)):
                        bounds.lb[fixpars[ipar]] = fixvals[ipar]
                        bounds.ub[fixpars[ipar]] = fixvals[ipar]
                        x0[fixpars[ipar]] = fixvals[ipar]

                if GauDecay == False:
                    # EMG Fitting

                    nlconstr = NonlinearConstraint(EMG2DConstr, -np.inf, 20.)
                    res = scipyminimize(EMG2Dchisqr, x0, args=(x, y, data), method='trust-constr', \
                                        constraints=[nlconstr], options={'verbose': 0,'maxiter':10000}, \
                                        bounds=bounds)  # constraints=[lconstr, nlconstr],
                    pars = res.x
                    Hess = nd.Hessian(EMG2Dchisqr)(pars, x, y, data)

                    chisqr = EMG2Dchisqr(pars, x, y, data)

                elif GauDecay == True:
                    # 2-D gaussian decay fitting
                    res = scipyminimize(GauDecay2Dchisqr, x0, args=(x, y, data), method='trust-constr', \
                                        options={'verbose': 0,'maxiter':10000}, bounds=bounds)  # constraints=[lconstr, nlconstr],
                    pars = res.x
                    Hess = nd.Hessian(GauDecay2Dchisqr)(pars, x, y, data)

                    chisqr = GauDecay2Dchisqr(pars, x, y, data)
                else:
                    print(
                        "Something went wrong, the type of fitting is not determined!"
                    )
                    return [False, False]

                sigmas = np.sqrt(
                    np.linalg.inv(Hess) * chisqr / (data.size - pars.size))

                params = Parameters()
                params.add('x0', value=pars[1], brute_step=sigmas[1, 1])
                params.add('ux', value=pars[2], brute_step=sigmas[2, 2])
                params.add('uy', value=pars[3], brute_step=sigmas[3, 3])
                params.add('sigma', value=pars[4], brute_step=sigmas[4, 4])
                if GauDecay == True:
                    params.add('Qu', value=pars[0], brute_step=sigmas[
                        0, 0])  # x-direction integration of total burden
                else:
                    params.add('a', value=pars[0], brute_step=sigmas[
                        0, 0])  # x-direction integration of total burden
                    params.add('eta', value=pars[6], brute_step=sigmas[
                        6, 6])  # x-direction integration of total burden
                params.add('b', value=pars[5], brute_step=sigmas[5, 5])

                if (minchisquare < 0) | (chisqr < minchisquare):
                    EMGout = params
                    minchisquare = chisqr

                if np.sqrt(minchisquare) / np.mean(data) < 0.01:
                    break

            else:

                print(
                    "solver wrong! specify one of these: pyipm, trust-constr, lmfit !"
                )
                return [False, False]

        except:
            print("Unsuccessful Fitting!")
            continue

    if minchisquare < 0:
        return [False, False]
    else:

        return [EMGout, True]
Beispiel #2
0
def EMAFit(x, data, nSample, **kwargs):

    maxtry = 100
    if "maxtry" in kwargs:
        maxtry = kwargs["maxtry"]
    # initial guess of each parameter
    nW = len(x)
    ini_a = np.sum(
        (data[1:] + data[0:nW - 1]) / 2. * np.absolute(x[1:] - x[0:nW - 1]))
    maxxW = x[np.nanargmax(data)]

    # if maxxW <= x[0]:
    #     return [False,False]

    # Weights of each point
    DtWeights = data - data + 1
    # DtWeights[data > np.nanpercentile(data, 75.)] = 4.
    # DtWeights[data < np.nanpercentile(data, 25.)] = 4.

    HM = (np.max(data) - np.min(data)) / 2. + np.min(data)
    FWHM = np.absolute(x[np.nanargmin(np.absolute(data - HM))] -
                       maxxW) * 2. / 2.355
    minchisquare = -1
    #resx = np.absolute(x[1] - x[0])

    means = np.array(
        [ini_a / 2. / 50., ini_a / 2. / 10., 50., 10., FWHM, FWHM / 5.])

    parnames = ['a', 'c', 'xa', 'xc', 'xsca', 'xscc', 'sigmaa', 'sigmac', 'b']

    if 'fixparam' in kwargs:
        fixpars = kwargs['fixparam']
        fixvals = kwargs['fixvalue']

    if 'consparam' in kwargs:
        conspars = kwargs['consparam']
        consvalsl = kwargs['consvaluel']
        consvalsu = kwargs['consvalueu']

    # DoSameSource = False
    # if 'sameSource' in kwargs:
    #     if kwargs['sameSource'] == True:
    #         DoSameSource = True

    PDom = False  #no precursor source
    SDom = False  #no primary source
    SameSource = False  #source location is the same for aerosols and precursors
    SameSigma = False

    if 'sameSource' in kwargs:
        if kwargs['sameSource'] == True:
            SameSource = True

    if 'sameSigma' in kwargs:
        if kwargs['sameSigma'] == True:
            SameSigma = True

    if 'pDom' in kwargs:
        if kwargs['pDom'] == True:
            PDom = True

    if 'sDom' in kwargs:
        if kwargs['sDom'] == True:
            SDom = True

    if 'solver' in kwargs:
        solver = kwargs['solver']
    else:
        solver = 'trust-constr'

    FoundSolution = False
    ntry = 0
    SampleDoubled = False

    while (FoundSolution == False) & (ntry < maxtry):

        ntry = ntry + 1
        SolutionUpdated = False

        design = lhs(6, samples=nSample)

        stds = 0.99 * means

        for i in np.arange(6):
            design[:, i] = norm(loc=means[i], scale=stds[i]).ppf(design[:, i])

        #solution for one sets of initial guess
        for jfit in np.arange(nSample + 1):
            if jfit < nSample:
                fitpars = design[jfit, :]
            else:
                fitpars = means
            if np.min(fitpars) < 0:
                continue

            if solver == 'lmfit':

                params = Parameters()
                params.add('a', value=fitpars[0],
                           min=0.)  # x-direction integration of total burden
                params.add('xa', value=fitpars[2], min=1. / 3)
                params.add('xc', value=fitpars[3], min=1. / 3)
                # params.add('fc', value=inifc, min=0., max=1.)
                params.add('c', value=fitpars[1], min=0.)

                params.add('xsca', value=maxxW, min=np.min(x), max=np.max(x))
                params.add('xscc', value=maxxW, min=np.min(x), max=np.max(x))

                params.add('sigmaa',
                           value=fitpars[4],
                           min=0.5 / samplewd,
                           max=np.max([maxxW - np.min(x),
                                       np.max(x) - maxxW
                                       ]))  # standard deviation
                params.add('sigmac',
                           value=fitpars[5],
                           min=0.5 / samplewd,
                           max=np.max([maxxW - np.min(x),
                                       np.max(x) - maxxW
                                       ]))  # standard deviation
                params.add('b', value=np.min(data), min=0.,
                           max=np.max(data))  # background concentration

                out = minimize(residualEMA,
                               params,
                               args=(x, data),
                               iter_cb=EMACall)
                chisqr = np.sum(residualEMA(out.params, x, data, DtWeights)**2)

                if (minchisquare < 0) | (chisqr < minchisquare):
                    EMAout = out.params
                    minchisquare = chisqr

                if np.sqrt(minchisquare) / np.mean(data) < 0.01:
                    break

            elif solver == 'trust-constr':  # Do the scipy.optimize fit using "trust_constr" method

                global ukninds, kninds, knvals

                ukninds = np.arange(9).astype(int)
                kninds = np.array([]).astype(int)
                knvals = []

                x0 = np.zeros(9)
                x0[0:4] = fitpars[0:4]
                x0[6:8] = fitpars[4:6]
                x0[8] = np.min(data)
                x0[4] = maxxW  # , min = x[0], max = x[-1])
                x0[5] = maxxW  # , min = x[0], max = x[-1])

                lowbs = np.array(
                    [0., 0., 0., 0.,
                     np.min(x),
                     np.min(x), 0., 0., 0.])
                highbs = np.array([
                    np.inf, np.inf, np.inf, np.inf,
                    np.max(x),
                    np.max(x), np.inf, np.inf,
                    np.max(data)
                ])  #np.max([maxxW - np.min(x), np.max(x) - maxxW])

                if 'consparam' in kwargs:
                    for ipar in np.arange(len(consvalsl)):
                        lowbs[conspars[ipar]] = consvalsl[ipar]
                        highbs[conspars[ipar]] = consvalsu[ipar]
                        x0[conspars[ipar]] = np.mean(
                            [consvalsl[ipar], consvalsu[ipar]])

                # test if solutions are similar for different "fixsource" handling
                if PDom == True:
                    kninds = np.append(kninds,
                                       np.array([1, 3, 5, 7]).astype(int))
                    knvals = np.append(knvals, [0., 0., 0., 0.])

                    delinds = ~np.isin(ukninds, [1, 3, 5, 7])
                    ukninds = ukninds[delinds]
                    x0 = x0[delinds]

                if SDom == True:
                    kninds = np.append(kninds, np.array([0, 4, 6]).astype(int))
                    knvals = np.append(knvals, [0., 0., 0.])

                    delinds = ~np.isin(ukninds, [0, 4, 6])
                    ukninds = ukninds[delinds]
                    x0 = x0[delinds]

                if 'fixparam' in kwargs:
                    for ipar in np.arange(len(fixvals)):
                        if ~np.isin(fixpars[ipar], ukninds):
                            continue
                        kninds = np.append(kninds, np.int(fixpars[ipar]))
                        knvals = np.append(knvals, fixvals[ipar])
                        delinds = ~np.isin(ukninds, fixpars[ipar])
                        ukninds = ukninds[delinds]
                        x0 = x0[delinds]

                # process bounds to be consistent with x0 and ukninds...
                bounds = Bounds(lowbs[ukninds],
                                highbs[ukninds],
                                keep_feasible=True)
                lconstmat = [[]]
                lconstmin = []
                lconstmax = []

                if SameSource == True:

                    if ~np.isin(4, ukninds) & ~np.isin(5, ukninds):
                        lconstmat = np.append(lconstmat,
                                              [np.zeros(len(ukninds))],
                                              axis=0)

                        lconstmat[:, ukninds == 4] = 1
                        lconstmat[:, ukninds == 5] = 1
                        lconstmin = np.append(lconstmin, 0.)
                        lconstmax = np.append(lconstmax, 0.)

                if SameSigma == True:
                    if ~np.isin(6, ukninds) & ~np.isin(7, ukninds):
                        lconstmat = np.append(lconstmat,
                                              [np.zeros(len(ukninds))],
                                              axis=0)
                        lconstmat[:, ukninds == 6] = 1
                        lconstmat[:, ukninds == 7] = 1
                        lconstmin = np.append(lconstmin, 0.)
                        lconstmax = np.append(lconstmax, 0.)

                nlconstr = NonlinearConstraint(EMANLConstr1, -np.inf, 0.)

                if (SameSource == True) | (SameSigma == True):
                    lconstr = LinearConstraint(lconstmat, lconstmin, lconstmax)
                    constraints = [lconstr, nlconstr]
                else:
                    constraints = nlconstr

                try:
                    res = scipyminimize(EMAchisqr1, x0, args=(x, data, DtWeights), method='trust-constr', \
                                        constraints=constraints,options={'verbose': 0,'maxiter':50000}, bounds=bounds)  #constraints=constraints,
                except:
                    continue

                pars = res.x
                Hess = nd.Hessian(EMAchisqr1)(pars, x, data, DtWeights)
                # args = {'x0': x[0]}

                # uncertanties from fitting, following Laughner et al. (2016)
                chisqr = EMAchisqr1(pars, x, data, DtWeights)

                try:
                    invHess = np.linalg.inv(Hess)
                except:
                    invHess = np.linalg.pinv(Hess)
                if np.any(np.isnan(invHess) == True):
                    invHess = np.linalg.pinv(Hess)
                    if np.any(np.isnan(invHess) == True):
                        continue
                sigmas = np.sqrt(invHess * chisqr / (data.size - pars.size))

                params = Parameters()

                for ikn in np.arange(len(kninds)):
                    params.add(parnames[kninds[ikn]],
                               value=knvals[ikn],
                               brute_step=0.)
                for iukn in np.arange(len(ukninds)):
                    params.add(parnames[ukninds[iukn]],
                               value=pars[iukn],
                               brute_step=sigmas[iukn, iukn])

                if (minchisquare < 0) | (chisqr < minchisquare):
                    SolutionUpdated = True

                    EMAout = params
                    minchisquare = chisqr
                    # update initial guess
                    means = np.array([EMAout['a'].value, EMAout['c'].value, EMAout['xa'].value, EMAout['xc'].value,\
                                      EMAout['sigmaa'].value, EMAout['sigmac'].value])

                if minchisquare < 0:
                    continue

                if np.sqrt(minchisquare) / np.mean(data) < 0.01:
                    FoundSolution = True
                    ntry = maxtry
                    break
            else:
                print(
                    "solver wrong! specify one of these: pyipm, trust-constr, lmfit !"
                )
                return [False, False]

        if (SolutionUpdated == False) & (SampleDoubled == False):
            nSample = np.int(nSample * 2)
            SampleDoubled = True
            continue

        if (SolutionUpdated == True) & (SampleDoubled == True):
            nSample = np.int(nSample / 2)
            SampleDoubled = False
            continue

        if (SolutionUpdated == False) & (SampleDoubled == True):
            nSample = np.int(nSample / 2)
            ntry = maxtry
            SampleDoubled = False
            continue
    if minchisquare < 0:
        return [False, False]
    else:
        return [EMAout, True]
Beispiel #3
0
def EMGFit(x, data, nSample, **kwargs):

    maxtry = 100
    if "maxtry" in kwargs:
        maxtry = kwargs["maxtry"]
    parnames = ['a', 'x0', 'xsc', 'sigma', 'b']
    # initial guess of each parameter
    nW = len(x)
    ini_a = np.sum(
        (data[1:] + data[0:nW - 1]) / 2. * np.absolute(x[1:] - x[0:nW - 1]))

    #Weights of each point
    DtWeights = data - data + 1
    # DtWeights[data>np.nanpercentile(data,75.)]=4.
    # DtWeights[data < np.nanpercentile(data, 25.)] = 4.

    maxxW = x[np.nanargmax(data)]
    # print maxxW,x[0]
    # if maxxW <= x[0]:
    #     return [False,False]
    #resx=np.absolute(x[1]-x[0])

    HM = (np.max(data) - np.min(data)) / 2. + np.min(data)
    FWHM = np.absolute(x[np.nanargmin(np.absolute(data - HM))] -
                       maxxW) * 2. / 2.355

    minchisquare = -1
    means = np.array([ini_a, 50., FWHM])

    Gaussian = False

    GauDecay = False

    if 'GauDecay' in kwargs:
        if kwargs['GauDecay'] == True:
            GauDecay = True
            avgw10 = kwargs['minx0'] / 3600.

    if 'fixparam' in kwargs:
        fixpars = kwargs['fixparam']
        fixvals = kwargs['fixvalue']

    if 'solver' in kwargs:
        solver = kwargs['solver']
    else:
        solver = 'trust-constr'

    FoundSolution = False
    SampleDoubled = False
    ntry = 0

    while (FoundSolution == False) & (ntry < maxtry):

        ntry = ntry + 1
        SolutionUpdated = False
        design = lhs(3, samples=nSample)
        stds = 0.99 * means
        for i in np.arange(3):
            design[:, i] = norm(loc=means[i], scale=stds[i]).ppf(design[:, i])

        for jfit in np.arange(nSample + 1):

            if jfit < nSample:
                fitpars = design[jfit, :]
            else:
                fitpars = means

            if np.min(fitpars) < 0:
                continue

            if solver == 'lmfit':
                params = Parameters()
                params.add('a', value=fitpars[0],
                           min=0.)  # x-direction integration of total burden
                params.add('x0', value=fitpars[1], min=resx /
                           3)  # x-direction distance in one-lifetime

                params.add('xsc', value=maxxW, min=np.min(x), max=np.max(x))

                params.add('sigma',
                           value=fitpars[2],
                           min=0.5,
                           max=np.max([maxxW - np.min(x),
                                       np.max(x) - maxxW
                                       ]))  # # standard deviation
                params.add('b', value=np.min(data), min=0.,
                           max=np.max(data))  # background concentration

                out = minimize(residualEMG,
                               params,
                               args=(x, data),
                               iter_cb=EMGCall)

                chisqr = np.sum(residualEMG(out.params, x, data)**2)

                if (minchisquare < 0) | (chisqr < minchisquare):
                    EMGout = out.params
                    minchisquare = chisqr

                if np.sqrt(minchisquare) / np.mean(data) < 0.01:
                    break

            elif solver == 'trust-constr':  # Do the scipy.optimize fit using "trust_constr" method

                global uknindsg, knindsg, knvalsg

                uknindsg = np.arange(5).astype(int)
                knindsg = np.array([]).astype(int)
                knvalsg = []

                x0 = np.zeros(5)
                x0[0:2] = fitpars[0:2]
                x0[3] = fitpars[2]
                x0[2] = maxxW  # , min = x[0], max = x[-1])
                x0[4] = np.min(data)

                lbds = np.array([0., 0., np.min(x), 0., 0.])
                hbds = np.array([
                    np.inf, np.inf,
                    np.max(x), np.inf,
                    np.max(data)
                ])  #np.max([maxxW - np.min(x), np.max(x) - maxxW])

                # test if solutions are similar for different "fixsource" handling

                if 'fixparam' in kwargs:
                    for ipar in np.arange(len(fixvals)):

                        if (fixpars[ipar]
                                == 1) & (np.absolute(fixvals[ipar]) <= 1.e-20):
                            Gaussian = True

                        if ~np.isin(fixpars[ipar], uknindsg):
                            continue
                        knindsg = np.append(knindsg, np.int(fixpars[ipar]))
                        knvalsg = np.append(knvalsg, fixvals[ipar])
                        delinds = ~np.isin(uknindsg, fixpars[ipar])
                        uknindsg = uknindsg[delinds]
                        x0 = x0[delinds]

                        # process bounds to be consistent with x0 and ukninds...

                bounds = Bounds(lbds[uknindsg],
                                hbds[uknindsg],
                                keep_feasible=True)

                nlconstr = NonlinearConstraint(EMGNLConstr1, -np.inf, 100.)

                try:

                    if Gaussian == True:
                        res = scipyminimize(EMGchisqr2, x0, args=(x, data, DtWeights), method='trust-constr', \
                                            options={'verbose': 0 ,'maxiter':50000}, \
                                            bounds=bounds)  # constraints=[lconstr, nlconstr],
                        Hess = nd.Hessian(EMGchisqr2)(res.x, x, data)

                        pars = res.x

                        chisqr = EMGchisqr2(pars, x, data)
                    else:

                        res = scipyminimize(EMGchisqr1, x0, args=(x, data, DtWeights), method='trust-constr', \
                                            constraints=[nlconstr],options={'verbose': 0,'maxiter':50000}, \
                                            bounds=bounds)  # constraints=[nlconstr],
                        Hess = nd.Hessian(EMGchisqr1)(res.x, x, data,
                                                      DtWeights)

                        pars = res.x

                        chisqr = EMGchisqr1(pars, x, data, DtWeights)

                except:
                    continue

                try:
                    invHess = np.linalg.inv(Hess)
                except:
                    invHess = np.linalg.pinv(Hess)
                if np.any(np.isnan(invHess) == True):
                    invHess = np.linalg.pinv(Hess)
                    if np.any(np.isnan(invHess) == True):
                        continue
                sigmas = np.sqrt(invHess * chisqr / (data.size - pars.size))

                params = Parameters()
                for ikn in np.arange(len(knindsg)):
                    params.add(parnames[knindsg[ikn]],
                               value=knvalsg[ikn],
                               brute_step=0.)
                for iukn in np.arange(len(uknindsg)):
                    params.add(parnames[uknindsg[iukn]],
                               value=pars[iukn],
                               brute_step=sigmas[iukn, iukn])

                if (minchisquare < 0) | (chisqr < minchisquare):
                    SolutionUpdated = True

                    EMGout = params
                    minchisquare = chisqr
                    # update initial guess
                    means = np.array([
                        EMGout['a'].value, EMGout['x0'].value,
                        EMGout['sigma'].value
                    ])

                if np.sqrt(minchisquare) / np.mean(data) < 0.01:
                    FoundSolution = True
                    ntry = maxtry
                    break

            else:

                print(
                    "solver wrong! specify one of these: pyipm, trust-constr, lmfit !"
                )
                return [False, False]

        if (SolutionUpdated == False) & (SampleDoubled == False):

            nSample = np.int(nSample * 2)
            SampleDoubled = True
            continue

        if (SolutionUpdated == True) & (SampleDoubled == True):
            nSample = np.int(nSample / 2)
            SampleDoubled = False
            continue

        if (SolutionUpdated == False) & (SampleDoubled == True):
            nSample = np.int(nSample / 2)
            ntry = maxtry
            SampleDoubled = False
            continue

    if minchisquare < 0:
        return [False, False]
    else:

        return [EMGout, True]
Beispiel #4
0
        return (multi_obj_acq_total / sample_number)


    # l-bfgs-b acquisation optimization
    x_tries = np.random.uniform(bound[0], bound[1], size=(1000, d))
    y_tries = [mesmo_acq(x) for x in x_tries]
    sorted_indecies = np.argsort(y_tries)
    i = 0
    x_best = x_tries[sorted_indecies[i]]
    while (any((x_best == x).all() for x in GPs[0].xValues)):
        i = i + 1
        x_best = x_tries[sorted_indecies[i]]
    y_best = y_tries[sorted_indecies[i]]
    x_seed = list(np.random.uniform(low=bound[0], high=bound[1], size=(1000, d)))
    for x_try in x_seed:
        result = scipyminimize(mesmo_acq, x0=np.asarray(x_try).reshape(1, -1), method='L-BFGS-B', bounds=Fun_bounds)
        if not result.success:
            continue
        if ((result.fun <= y_best) and (not (result.x in np.asarray(GPs[0].xValues)))):
            x_best = result.x
            y_best = result.fun

    # ---------------Updating and fitting the GPs-----------------
    for i in range(len(functions)):
        GPs[i].addSample(x_best, functions[i](list(x_best), d))
        GPs[i].fitModel()

    ############################ write Input output into file ##################
    input_output = open(os.path.join(paths, 'input_output.txt'), "a")
    input_output.write(
        str(GPs[0].xValues[-1]) + '---' + str([GPs[i].yValues[-1] for i in range(len(functions))]) + '\n')