Beispiel #1
0
    def preprocess(self):
        self.target.mi.target = self.target

        # assemble hyper parameters
        self.length_scales, self.amp_variance, self.single_noise_variance, self.mean_noise_variance, self.precision_matrix = normscales.normscales(
            self.target.mi, self.devices, correlationsQ=self.correlationsQ)

        # build precision_matrix if not returned
        print('Precision before', self.precision_matrix)
        if self.precision_matrix is None:
            self.covarmat = np.diag(self.length_scales)**2
            print('Covariance', self.covarmat)
            self.precision_matrix = np.linalg.inv(self.covarmat)
        print('Precision', self.precision_matrix)
        print('Length Scales', self.length_scales)
        # create OnlineGP model
        dim = len(self.devices)
        hyperparams = (self.precision_matrix, np.log(self.amp_variance),
                       np.log(self.mean_noise_variance))
        #        self.model = OGP(dim, hyperparams, maxBV=self.numBV, weighted=False)
        self.model = OGP(dim,
                         hyperparams,
                         maxBV=self.numBV,
                         covar=['RBF_ARD', 'MATERN32_ARD', 'MATERN52_ARD'][0],
                         weighted=False)
        # initialize model on prior data if available
        if (self.prior_data is not None):
            p_X = self.prior_data.iloc[:, :-1]
            p_Y = self.prior_data.iloc[:, -1]
            num = p_X.shape[0]
            self.model.fit(p_X, p_Y, min(self.m, num))

        # create Bayesian optimizer
        dev_ids = [dev.eid for dev in self.devices]
        dev_vals = [dev.get_value() for dev in self.devices]
        self.scanner = BayesOpt(
            model=self.model,
            target_func=self.target,
            acq_func=self.acq_func,
            xi=self.xi,
            alt_param=self.alt_param,
            m=self.m,
            bounds=self.bounds,
            iter_bound=self.iter_bound,
            prior_data=self.prior_data,
            start_dev_vals=dev_vals,
            dev_ids=dev_ids,
            searchBoundScaleFactor=self.searchBoundScaleFactor)
        self.scanner.max_iter = self.max_iter
        self.scanner.opt_ctrl = self.opt_ctrl
Beispiel #2
0
    def __init__(self,
                 dim,
                 hidden_layers=[],
                 dim_z=None,
                 mask=None,
                 alpha=1.0,
                 noise=0.1,
                 activations='lrelu',
                 weight_dir=None):
        self.dim = dim
        self.dim_z = dim_z or dim

        # initialize the OGP object we use to actually make our predictions
        OGP_params = (np.zeros((self.dim_z, )), np.log(alpha), np.log(noise)
                      )  # lengthscales of one (logged)
        self.ogp = OGP(self.dim_z, OGP_params)

        # our embedding function, initially the identity
        # if unchanged, the DKLGP should match the functionality of OGP
        self.embed = lambda x: x

        # build the neural network structure of the DKL
        self.layers = []
        for l in hidden_layers:
            self.layers.append(Dense(l, activation=activations))

        # add the linear output layer and the GP (used for likelihood training)
        if len(self.layers) > 0:
            self.layers.append(Dense(dim_z))
        else:
            self.mask = mask
            self.layers.append(Dense(dim_z, mask=mask))
        self.layers.append(CovMat(
            kernel='rbf',
            alpha_fixed=False))  # kernel should match the one used in OGP

        # if weight_dir is specified, we immediately initialize the embedding based on the specified neural network
        if weight_dir is not None:
            self.load_embedding(weight_dir)
Beispiel #3
0
def testFunc():
    """ Function to try and find a bug in the model load function """

    numBV = 50
    xi = .01
    bnds = None

    thing = GpScanner()
    pvs = [
        "SIOC:SYS0:ML00:CALCOUT000", "SIOC:SYS0:ML00:CALCOUT999",
        "SIOC:SYS0:ML00:CALCOUT998", "SIOC:SYS0:ML00:CALCOUT997"
    ]

    #thing.setup(pvs, 'GDET:FEE1:241:ENRCHSTBR')
    thing.pvs = pvs
    thing.objective_func_pv = 'GDET:FEE1:241:ENRCHSTBR'
    total_delay = .2
    mi = LCLSMachineInterface()
    mi.setUpDetector(pvs, detector=thing.objective_func_pv)
    mi.setup_data_record(pvs)
    dp = LCLSDeviceProperties()
    dp.get_start_values(pvs)
    interface = GpInterfaceWrapper(pvs, mi, dp, total_delay)
    s_data = thing.loadSeedData(thing.seed_file)

    hyps = thing.loadHyperParams(thing.hyp_file)
    thing.model = OGP(len(pvs), hyps, maxBV=50)

    filename = '/u1/lcls/matlab/data/2016/2016-04/2016-04-25/OcelotScan-2016-04-25-181811.mat'
    model_file = scipy.io.loadmat(filename)['data']
    thing.model.alpha = model_file['alpha'].flatten(0)[0]
    thing.model.C = model_file['C'].flatten(0)[0]
    thing.model.BV = model_file['BV'].flatten(0)[0]
    thing.model.covar_params = model_file['covar_params'].flatten(0)[0]
    thing.model.KB = model_file['KB'].flatten(0)[0]
    thing.model.KBinv = model_file['KBinv'].flatten(0)[0]
    thing.model.weighted = model_file['weighted'].flatten(0)[0]

    thing.model.covar_params = (thing.model.covar_params[0][0],
                                thing.model.covar_params[1][0])
    print type(thing.model.covar_params)
    print thing.model.covar_params
    thing.model.predict(np.array(s_data[0, :-1], ndmin=2))

    thing.opt = BOpt.BayesOpt(thing.model,
                              interface,
                              prior_data=pd.DataFrame(s_data))
Beispiel #4
0
 def preprocess(self):
     hyp_params = HyperParams(pvs=self.devices, filename=self.hyper_file)
     self.energy = str(round(self.target.get_energy()))
     dev_ids = [dev.eid for dev in self.devices]
     hyps1 = hyp_params.loadHyperParams(self.hyper_file, self.energy,
                                        self.target, dev_ids,
                                        self.multiplier)
     dim = len(self.devices)
     self.model = OGP(dim, hyps1, maxBV=self.numBV, weighted=False)
     self.scanner = BayesOpt(model=self.model,
                             target_func=self.target,
                             acq_func=self.acq_func,
                             xi=self.xi,
                             alt_param=self.alt_param,
                             m=self.m,
                             bounds=self.bounds,
                             iter_bound=self.iter_bound,
                             prior_data=self.prior_data)
     self.scanner.max_iter = self.max_iter
Beispiel #5
0
class GaussProcess(Minimizer):
    def __init__(self, correlationsQ=False, searchBoundScaleFactor=None):
        super(GaussProcess, self).__init__()
        self.seed_timeout = 1
        self.target = None
        self.devices = []
        self.energy = 4
        self.seed_iter = 0
        self.numBV = 30
        self.xi = 0.01
        self.bounds = None
        self.acq_func = ['PI', 'EI', 'UCB'][-1]
        self.alt_param = -1
        self.m = 200
        self.iter_bound = False
        # filepath = os.path.join(os.getcwd(), "parameters", "hyperparameters.npy")
        # print('MINT-->Grabbing hyps from...: ', filepath)
        # self.hyper_file = filepath
        self.max_iter = 50
        self.norm_coef = 0.1
        self.multiplier = 1
        self.simQ = False
        self.seedScanBool = True
        self.prior_data = None
        self.correlationsQ = correlationsQ
        self.searchBoundScaleFactor = searchBoundScaleFactor

    def seed_simplex(self):
        opt_smx = Optimizer()
        opt_smx.normalization = True
        opt_smx.norm_coef = self.norm_coef
        opt_smx.timeout = self.seed_timeout
        minimizer = Simplex()
        minimizer.max_iter = self.seed_iter
        opt_smx.minimizer = minimizer
        # opt.debug = True
        seq = [
            Action(func=opt_smx.max_target_func,
                   args=[self.target, self.devices])
        ]
        opt_smx.eval(seq)

        seed_data = np.append(
            np.vstack(opt_smx.opt_ctrl.dev_sets),
            np.transpose(-np.array([opt_smx.opt_ctrl.penalty])),
            axis=1)
        import pandas as pd
        self.prior_data = pd.DataFrame(seed_data)
        self.seed_y_data = opt_smx.opt_ctrl.penalty

    def preprocess(self):
        self.target.mi.target = self.target

        # assemble hyper parameters
        self.length_scales, self.amp_variance, self.single_noise_variance, self.mean_noise_variance, self.precision_matrix = normscales.normscales(
            self.target.mi, self.devices, correlationsQ=self.correlationsQ)

        # build precision_matrix if not returned
        print('Precision before', self.precision_matrix)
        if self.precision_matrix is None:
            self.covarmat = np.diag(self.length_scales)**2
            print('Covariance', self.covarmat)
            self.precision_matrix = np.linalg.inv(self.covarmat)
        print('Precision', self.precision_matrix)
        print('Length Scales', self.length_scales)
        # create OnlineGP model
        dim = len(self.devices)
        hyperparams = (self.precision_matrix, np.log(self.amp_variance),
                       np.log(self.mean_noise_variance))
        #        self.model = OGP(dim, hyperparams, maxBV=self.numBV, weighted=False)
        self.model = OGP(dim,
                         hyperparams,
                         maxBV=self.numBV,
                         covar=['RBF_ARD', 'MATERN32_ARD', 'MATERN52_ARD'][0],
                         weighted=False)
        # initialize model on prior data if available
        if (self.prior_data is not None):
            p_X = self.prior_data.iloc[:, :-1]
            p_Y = self.prior_data.iloc[:, -1]
            num = p_X.shape[0]
            self.model.fit(p_X, p_Y, min(self.m, num))

        # create Bayesian optimizer
        dev_ids = [dev.eid for dev in self.devices]
        dev_vals = [dev.get_value() for dev in self.devices]
        self.scanner = BayesOpt(
            model=self.model,
            target_func=self.target,
            acq_func=self.acq_func,
            xi=self.xi,
            alt_param=self.alt_param,
            m=self.m,
            bounds=self.bounds,
            iter_bound=self.iter_bound,
            prior_data=self.prior_data,
            start_dev_vals=dev_vals,
            dev_ids=dev_ids,
            searchBoundScaleFactor=self.searchBoundScaleFactor)
        self.scanner.max_iter = self.max_iter
        self.scanner.opt_ctrl = self.opt_ctrl

    def minimize(self, error_func, x):
        self.energy = self.mi.get_energy()
        if self.seedScanBool: self.seed_simplex()
        self.preprocess()
        # x = [dev.get_value() for dev in self.devices] # is this needed?
        self.scanner.minimize(error_func, x)
        self.saveModel()
        return

    def saveModel(self):
        """
        Add GP model parameters to the save file.
        """
        # add in extra GP model data to save
        try:
            self.mi.data
        except:
            self.mi.data = {}
        self.mi.data["acq_fcn"] = self.acq_func
        # OnlineGP stuff
        try:
            self.mi.data["alpha"] = self.model.alpha
        except:
            pass
        try:
            self.mi.data["C"] = self.model.C
        except:
            pass
        try:
            self.mi.data["BV"] = self.model.BV
        except:
            pass
        try:
            self.mi.data["covar_params"] = self.model.covar_params
        except:
            pass
        try:
            self.mi.data["KB"] = self.model.KB
        except:
            pass
        try:
            self.mi.data["KBinv"] = self.model.KBinv
        except:
            pass
        try:
            self.mi.data["weighted"] = self.model.weighted
        except:
            pass
        try:
            self.mi.data["noise_var"] = self.model.noise_var
        except:
            pass
        try:
            self.mi.data["corrmat"] = self.corrmat
        except:
            pass
        try:
            self.mi.data["covarmat"] = self.covarmat
        except:
            pass
        try:
            self.mi.data["length_scales"] = self.length_scales
        except:
            pass
        try:
            self.mi.data["amp_variance"] = self.amp_variance
        except:
            pass
        try:
            self.mi.data["single_noise_variance"] = self.single_noise_variance
        except:
            pass
        try:
            self.mi.data["mean_noise_variance"] = self.mean_noise_variance
        except:
            pass
        try:
            self.mi.data["precision_matrix"] = self.precision_matrix
        except:
            pass
        self.mi.data["seedScanBool"] = self.seedScanBool
        if self.seedScanBool:
            self.mi.data["nseed"] = self.prior_data.shape[0]
        else:
            self.mi.data["nseed"] = 0
        if type(self.model.prmeanp) is type(None):
            self.mi.data["prmean_params_amp"] = "None"
            self.mi.data["prmean_params_centroid"] = "None"
            self.mi.data["prmean_params_invcovarmat"] = "None"
        else:
            self.mi.data["prmean_params_amp"] = self.model.prmeanp[0]
            self.mi.data["prmean_params_centroid"] = self.model.prmeanp[1]
            self.mi.data["prmean_params_invcovarmat"] = self.model.prmeanp[2]
        if type(self.model.prvarp) is type(None):
            self.mi.data["prvar_params"] = "None"
        else:
            self.mi.data["prvar_params"] = self.model.prvarp
        try:
            self.mi.data["prmean_name"] = self.model.prmean_name
        except:
            pass
        try:
            self.mi.data["prior_pv_info"] = self.model.prior_pv_info
        except:
            pass
Beispiel #6
0
def test_GP():
    """
    test GP method
    :return:
    """
    def get_limits():
        return [-100, 100]

    d1 = TestDevice(eid="d1")
    d1.get_limits = get_limits
    d2 = TestDevice(eid="d2")
    d2.get_limits = get_limits
    d3 = TestDevice(eid="d3")
    d3.get_limits = get_limits

    devices = [d1, d2]
    target = TestTarget()

    opt = Optimizer()
    opt.timeout = 0

    opt_smx = Optimizer()
    opt_smx.timeout = 0
    minimizer = Simplex()
    minimizer.max_iter = 3
    opt_smx.minimizer = minimizer
    #opt.debug = True

    seq = [Action(func=opt_smx.max_target_func, args=[target, devices])]
    opt_smx.eval(seq)
    s_data = np.append(np.vstack(opt_smx.opt_ctrl.dev_sets),
                       np.transpose(-np.array([opt_smx.opt_ctrl.penalty])),
                       axis=1)
    print(s_data)

    # -------------- GP config setup -------------- #
    #GP parameters
    numBV = 30
    xi = 0.01
    #no input bounds on GP selection for now

    pvs = [dev.eid for dev in devices]
    hyp_params = HyperParams(pvs=pvs,
                             filename="../parameters/hyperparameters.npy")
    ave = np.mean(-np.array(opt_smx.opt_ctrl.penalty))
    std = np.std(-np.array(opt_smx.opt_ctrl.penalty))
    noise = hyp_params.calcNoiseHP(ave, std=0.)
    coeff = hyp_params.calcAmpCoeffHP(ave, std=0.)
    len_sc_hyps = []
    for dev in devices:
        ave = 10
        std = 3
        len_sc_hyps.append(hyp_params.calcLengthScaleHP(ave, std))
    print("y_data", opt_smx.opt_ctrl.penalty)
    print("pd.DataFrame(s_data)", pd.DataFrame(s_data))
    print("len_sc_hyps", len_sc_hyps)

    bnds = None
    #hyps = hyp_params.loadHyperParams(energy=3, detector_stat_params=target.get_stat_params())
    hyps1 = (np.array([len_sc_hyps]), coeff, noise
             )  #(np.array([hyps]), coeff, noise)
    print("hyps1", hyps1)
    #exit(0)
    #init model
    dim = len(pvs)

    model = OGP(dim, hyps1, maxBV=numBV, weighted=False)

    minimizer = BayesOpt(model,
                         target_func=target,
                         xi=0.01,
                         acq_func='EI',
                         bounds=bnds,
                         prior_data=pd.DataFrame(s_data))
    minimizer.devices = devices
    minimizer.max_iter = 300
    opt.minimizer = minimizer

    seq = [Action(func=opt.max_target_func, args=[target, devices])]
    opt.eval(seq)
Beispiel #7
0
class DKLGP(object):
    def __init__(self,
                 dim,
                 hidden_layers=[],
                 dim_z=None,
                 mask=None,
                 alpha=1.0,
                 noise=0.1,
                 activations='lrelu',
                 weight_dir=None):
        self.dim = dim
        self.dim_z = dim_z or dim

        # initialize the OGP object we use to actually make our predictions
        OGP_params = (np.zeros((self.dim_z, )), np.log(alpha), np.log(noise)
                      )  # lengthscales of one (logged)
        self.ogp = OGP(self.dim_z, OGP_params)

        # our embedding function, initially the identity
        # if unchanged, the DKLGP should match the functionality of OGP
        self.embed = lambda x: x

        # build the neural network structure of the DKL
        self.layers = []
        for l in hidden_layers:
            self.layers.append(Dense(l, activation=activations))

        # add the linear output layer and the GP (used for likelihood training)
        if len(self.layers) > 0:
            self.layers.append(Dense(dim_z))
        else:
            self.mask = mask
            self.layers.append(Dense(dim_z, mask=mask))
        self.layers.append(CovMat(
            kernel='rbf',
            alpha_fixed=False))  # kernel should match the one used in OGP

        # if weight_dir is specified, we immediately initialize the embedding based on the specified neural network
        if weight_dir is not None:
            self.load_embedding(weight_dir)

    # sets up the DKL and trains the embedding. nullifies the effect of load_embedding if it was called previously
    # lr is the learning rate: reasonable deafult is 2e-4
    # maxiter is the number of iterations of the solver; scales the training time linearly
    # batch_size is the size of a mini batch; scales the training time ~quadratically
    # gp = True in NNRegressor() sets gp likelihood as optimization target
    def train_embedding(self, x, y, lr=2.e-4, batch_size=50, maxiter=4000):
        opt = Adam(lr)
        self.DKLmodel = NNRegressor(self.layers,
                                    opt=opt,
                                    batch_size=batch_size,
                                    maxiter=maxiter,
                                    gp=True,
                                    verbose=False)
        self.DKLmodel.fit(x, y)

        self.embed = self.DKLmodel.fast_forward  # fast_forward gives mapping up to (but not including) gp (x -> z)
        # (something like) full_forward maps through the whole dkl + gp

    # loads the DKL and embedding from the specified directory. forgets any previous embedding
    # note that network structure and activations, etc. still need to be specified in __init__
    def load_embedding(self, dname):
        self.DKLmodel = NNRegressor(self.layers)
        self.DKLmodel.first_run(np.zeros((1, self.dim)), None, load_path=dname)

        self.embed = self.DKLmodel.fast_forward

    # saves the neural network parameters to specified directory, allowing the saved embedding to be replicated without re-training it
    def save_embedding(self, dname):
        if not os.path.isdir(dname):
            os.makedirs(dname)
        self.DKLmodel.save_weights(dname)

    # allows manually setting a linear transform. Make sure you get your tranpose stuff right (x_rows.shape is [npoints,ndim])
    def set_linear(self, matrix):
        self.linear_transform = matrix
        self.embed = lambda x_rows: np.dot(x_rows, self.linear_transform)

    # sets a linear transformation based on a given correlation matrix which is assumed to fit the data
    # NOTE: this isn't necessarily log-likelihood-optimal
    def linear_from_correlation(self, matrix):  # multinormal covariance matrix
        center = np.linalg.inv(matrix)
        chol = np.linalg.cholesky(center)

        self.set_linear(chol)

    # computes the log-likelihood of the given data set using the current embedding
    # ASSUMES YOU'RE USING RBF KERNEL
    def eval_LL(self, X, Y):
        N = X.shape[0]
        Z = self.embed(X)
        diffs = euclidean_distances(Z, squared=True)

        alpha = np.exp(self.ogp.covar_params[1])  # kind of a hack
        rbf_K = alpha * np.exp(-diffs / 2.)
        K_full = rbf_K + (self.ogp.noise_var) * np.eye(N)

        L = np.linalg.cholesky(K_full)  # K = L * L.T
        Ly = np.linalg.solve(L, Y)  # finds inverse(L) * y
        log_lik = -0.5 * np.sum(Ly**2)  # -1/2 * y.T * inverse(L * L.T) * y
        log_lik -= np.sum(np.log(
            np.diag(L)))  # equivalent to -1/2 * log(det(K))
        log_lik -= 0.5 * N * np.log(2 * np.pi)

        return float(log_lik)

    # allows passing custom alpha/noise
    # if compute_deriv is true, assumes that embedding is linear and returns derivative w.r.t. transform
    def custom_LL(self, X, Y, alpha, noise_variance, compute_deriv=False):
        N, dim = X.shape
        Z = self.embed(X)
        if not compute_deriv:
            diffs = euclidean_distances(Z, squared=True)

            rbf_K = alpha * np.exp(-diffs / 2.)
            K_full = rbf_K + noise_variance * np.eye(N)

            L = np.linalg.cholesky(K_full)  # K = L * L.T
            Ly = np.linalg.solve(L, Y)  # finds inverse(L) * y
            log_lik = -0.5 * np.sum(Ly**2)  # -1/2 * y.T * inverse(L * L.T) * y
            log_lik -= np.sum(np.log(
                np.diag(L)))  # equivalent to -1/2 * log(det(K))
            log_lik -= 0.5 * N * np.log(2 * np.pi)

            return float(log_lik)

        lengths = [0. for d in range(dim)]
        params = lengths + [np.log(alpha)] + [np.log(noise_variance)]
        neglik, deriv = SPGP_likelihood_4scipy(params, Y, Z)

        deriv_noise = deriv[-1]
        deriv_coeff = deriv[-2]
        deriv_z = deriv[:self.dim_z * N].reshape((N, self.dim_z))

        deriv_transform = np.dot(X.T, deriv_z)
        mask = self.mask or np.ones((dim, dim_z))
        return -neglik, deriv_transform * mask, deriv_coeff, deriv_noise

    # takes an n x dim_z matrix Z and translates it to x, assuming the embedding is linear
    # currently requires that the model embedding was set via set_linear
    def inverse_embed(self, Z):
        assert ('linear_transform' in dir(self))
        transform = self.linear_transform

        # assumption is that z = x * transform
        column_x = np.linalg.solve(transform.T, Z.T)
        return column_x.T

    ##########
    # remaining functions mimic Online GP functionality, just embedding x -> z first
    ##########

    def fit(self, X, y):
        Z = self.embed(X)
        self.ogp.fit(Z, y)

    def update(self, x_new, y_new):
        z_new = self.embed(x_new)
        self.ogp.update(z_new, y_new)

    def predict(self, x):
        z = np.array(self.embed(x), ndmin=2)
        return self.ogp.predict(z)
    def setup(self, devices, objective_func, iters=45):
        """
        Basic setup procedure for the GP scan objects, input args that are common to optimizer classes.

        Similar setup funtion with the same args as the ocelot scanner.
        Does not contain option to load in MachineInterface and DeviceProperties

        Could probably just write all this into the init function if you have motivation.

        Args:
                devices (List[str]): List of the PVs to be used in scan
                objective_func (str): String for the PV for the value to maximize
                iters (int): Number of iterations for the scanner to run
        """

        #load in the pvs to scan
        self.devices = devices
        self.objective_func = objective_func
        # for testing
        self.objective_func.devices = self.devices

        #number of iterations to scan (hardcode for now)
        self.iters = iters

        #set new timing variables
        #self.mi.secs_to_ave = self.parent.data_delay
        self.total_delay = self.parent.trim_delay + self.parent.data_delay

        # -------------- GP config setup -------------- #

        #GP parameters
        self.numBV = 30
        self.xi = 0.01

        #no input bounds on GP selection for now
        bnds = None

        pvs = [dev.eid for dev in devices]

        hyp_params = BOpt.HyperParams(pvs=pvs, filename=self.hyp_file)
        hyps = hyp_params.loadHyperParams(
            objective_func.get_energy(),
            detector_stat_params=objective_func.get_stat_params())

        #init model
        dim = len(devices)

        self.model = OGP(dim, hyps, maxBV=self.numBV, weighted=False)

        #load model stuff
        filename = '/u1/lcls/matlab/data/2016/2016-04/2016-04-25/OcelotScan-2016-04-25-181811.mat'

        #if you would lake to load a model from file, use this function
        #self.model = self.loadModelParams(self.model,filename)

        #if this is not a simplex seeded scan, setup the seed data from mat file and build optimizer object\
        if not self.seedScanBool:
            #load seed data file
            s_data = self.loadSeedData(self.seed_file)
            #optimzer object
            self.opt = Optimizer()
            self.opt.timeout = self.total_delay
            minimizer = BOpt.BayesOpt(self.model,
                                      self.objective_func,
                                      acq_func='EI',
                                      xi=self.xi,
                                      bounds=bnds,
                                      prior_data=pd.DataFrame(s_data))
            #self.opt = BOpt.BayesOpt(self.model, self.interface, xi=self.xi, acq_func='EI', bounds=bnds, prior_data=pd.DataFrame(s_data))
            #bool to kill scanner thread from GUI
            minimizer.devices = devices
            minimizer.max_iter = iter
            self.opt.minimizer = minimizer
            self.seq = [
                Action(func=self.opt.max_target_func,
                       args=[objective_func, self.devices])
            ]
            self.opt.kill = False