Beispiel #1
0
def make_eval_b_candidate_kwargs(data, model, plate_lvl):
    """Make evalaluation kwargs for multiprocessing b_candidate evaluation.

    Corresponds to the function genetic.eval_b_candidate.

    data : A dictionary

    model : A pickleable CANS Model instance.

    plate_lvl : An array of plate level parameters.

    The returned dictionary should be supplied in the call to evolve
    when using the eval_b_candidate evaluator for
    multiprocessing. Due to the overhead of loading SBML models, a
    large number of cores (>20) may be needed before any performance
    benefit is seen.

    """
    plate = Plate(**_get_plate_kwargs(data))
    plate.data_shape = np.array(
        [len(plate.times), plate.no_cultures * model.no_species])
    plate.rr = PickleableRoadRunner()
    eval_kwargs = {
        "plate": plate,
        "fitter": Fitter(model),
        "sbml": create_sbml(plate, model, data["sim_params"]),
        "plate_lvl": plate_lvl,
    }
    return eval_kwargs
Beispiel #2
0
def make_eval_b_candidates_kwargs(data, model, plate_lvl):
    """Make evalaluation kwargs for in serial b_candidate evaluation.

    Corresponds to the function genetic.eval_b_candidates. The
    returned values in the dict eval_kwargs need not be pickleable.

    data : A dictionary

    model : A CANS Model instance.

    plate_lvl : An array of plate level parameters.

    The returned dictionary should be supplied in the call to evolve
    when using the eval_b_candidates evaluator for serial
    processing.

    """
    plate = Plate(**_get_plate_kwargs(data))
    no_params = len(plate_lvl) + plate.no_cultures
    plate.set_rr_model(model, np.ones(no_params))  # Dummy params
    eval_kwargs = {
        "plate": plate,
        "fitter": Fitter(model),
        "plate_lvl": plate_lvl,
    }
    return eval_kwargs
Beispiel #3
0
def get_plate_zone(plate, coords, rows, cols):
    """Return a plate from a zone of a larger plate.

    Coords are a tuple for the top left culture of a rectangular
    zone. rows and cols are the size of the new zone.

    """
    no_cultures = plate.no_cultures
    c_collected = [plate.c_meas[i::no_cultures] for i in range(no_cultures)]
    c_collected = np.array(c_collected)
    c_collected.shape = (plate.rows, plate.cols, len(plate.times))
    zone = _get_zone(c_collected, coords, rows, cols)
    c_meas = [zone[:, :, i] for i in range(len(plate.times))]
    c_meas = np.array(c_meas).flatten()
    assert len(c_meas) == rows * cols * len(plate.times)
    zone_indices = list(_get_zone_indices(plate, coords, rows, cols))
    zone_data = {
        "c_meas":
        c_meas,
        "times":
        plate.times,
        "empties":
        np.array([
            z_i for z_i, p_i in enumerate(zone_indices) if p_i in plate.empties
        ]),
        # "genes": np.array(plate.genes)[zone_indices],
    }
    zone_plate = Plate(rows, cols, data=zone_data)
    return zone_plate
Beispiel #4
0
    def guess_kn(self, start, stop, num, params):
        """Guess kn from final cell measurement variance.

        params should have a dummy value, e.g. nan, in place of
        kn. Returns this array with the guess of kn inserted.

        """
        C_f_var_true = np.var(self.plate.c_meas[-self.plate.no_cultures:])
        kns = np.linspace(start, stop, num)
        kn_index = self.model.params.index("kn")
        # Make a new Plate so that we do not alter the original
        # containing true data.
        sim_plate = Plate(self.plate.rows, self.plate.cols)
        sim_plate.times = self.plate.times
        C_f_vars = []
        for kn in kns:
            params[kn_index] = kn
            sim_plate.sim_params = params
            sim_plate.set_sim_data(self.model)
            C_fs = sim_plate.c_meas[-sim_plate.no_cultures:]
            C_f_vars.append(np.var(C_fs))
        # Fit a line by least squares.
        A = np.vstack([kns, np.ones(len(kns))]).T
        m, c = np.linalg.lstsq(A, C_f_vars)[0]
        kn_guess = (C_f_var_true - c) / float(m)
        params[kn_index] = kn_guess
        return params.clip(min=0.0)
Beispiel #5
0
def resim_zone(plate, model, coords, rows, cols, noise=True):
    """Resimulate a zone from the underlying parameters."""
    zone = Plate(rows, cols)
    zone.times = plate.times
    b_index = len(plate.sim_params) - plate.no_cultures
    plate_lvl = plate.sim_params[:b_index]
    bs = plate.sim_params[b_index:]
    zone_bs = get_zone_bs(bs, plate.rows, plate.cols, coords, rows, cols)
    zone_params = np.append(plate_lvl, zone_bs)
    zone.sim_params = zone_params
    zone.set_sim_data(model, noise=noise)
    return zone
Beispiel #6
0
def sim_zone(plate_file, model, coords, rows, cols):
    """Resimulate and return a zone of a saved plate."""
    params = get_zone_params(plate_file, coords, rows, cols)
    with open(plate_file, 'b') as f:
        plate_data = json.load(f)
    times = plate_data['times']

    try:
        assert model.name == plate_data['model']
    except AssertionError:
        print("Plate model is not the same as zone model.")

    zone = Plate(rows, cols)
    zone.sim_params = params
    zone.times = times
    zone.set_sim_data(model)
    return zone
Beispiel #7
0
def make_eval_plate_lvl_im_neigh_grad_kwargs(data, model, b_bound):
    """Make eval kwargs for plate level parallel parameter candidate evaluaton.

    Corresponds to the function genetic.eval_plate_lvl_im_neigh_grad.

    data : dictionary

    model : A Pickleable CANS model.

    b_bound : bound for gradient fitting of b parameters. e.g. [0.0, 100.0].

    """
    pickleable(model)  # Model must be pickleable for multiprocessing.
    plate = Plate(**_get_plate_kwargs(data))
    eval_kwargs = {
        "plate": plate,
        "model": model,
        # Not including amounts. Last two are place holders for
        # b_guess*1.5 and b_guess.
        "imag_neigh_params": np.array([1.0, 1.0, 0.0, 0.0, 0.0]),
        "b_bounds": np.array([b_bound for c in range(plate.no_cultures)]),
    }
    return eval_kwargs
Beispiel #8
0
    return writeSBMLToString(document)


if __name__ == "__main__":
    import numpy as np


    from cans.plate import Plate
    from cans.model import CompModelBC, CompModel
    from cans.plotter import Plotter


    # Simulate a plate with data and parameters.
    rows = 3
    cols = 3
    plate1 = Plate(rows, cols)
    plate1.times = np.linspace(0, 5, 11)
    comp_model_bc = CompModelBC()
    params = {
        "C_0": 1e-6,
        "N_0": 0.1,
        "kn": 1.5
    }
    plate1.set_sim_data(comp_model_bc, b_mean=40.0, b_var=15.0,
                        custom_params=params)

    # Convert comp model to SBML.
    sbml = create_sbml(plate1, comp_model_bc, plate1.sim_params,
                        outfile="sbml_models/simulated_{0}x{1}_test_plate_bc.xml".format(rows, cols))

    comp_model_ir = CompModel(rev_diff=False)
Beispiel #9
0
    def plot_zone_est(self,
                      plates,
                      plate_names,
                      est_params,
                      models,
                      coords,
                      rows,
                      cols,
                      title="Zone Estimates",
                      legend=False,
                      filename=None,
                      plot_types=None,
                      vis_ticks=True,
                      log_plate=None,
                      log_params=None):
        """Plot estimates for a zone.

        Plotting a zone from a full plate estimate requires simulating
        for the full plate and then taking the amounts from the zone
        rather than just simulating from the zone params.

        plates : list of Plates with different c_meas data. If both
        estimates are from the same Plate you need only provide one
        Plate in the list.

        plate_neams : list of strings. Names of plates to use in
        figure legend.

        est_params : list of parameter estimate from fits of different
        models.

        models : list of models corresponding to est_params.

        coords : tuple of coordinates of top left culture in zone
        (indices start from zero).

        row, cols : rows and columns for zone.

        plot_types : list of strings for plot labels. If the first
        plate is to plot the estimate and the second a simulation use
        e.g. ["Est", "Sim"]

        log_plate : A plate from a QFA R logistic fit.

        """
        smooth_times = np.linspace(plates[0].times[0], plates[0].times[-1],
                                   100)

        if log_plate is not None:
            log_zone = get_qfa_R_zone(log_plate, log_params, coords, rows,
                                      cols, smooth_times)

        smooth_plate = Plate(plates[0].rows, plates[0].cols)
        smooth_plate.times = smooth_times
        smooth_plate.smooth_amounts = []
        for params, model in zip(est_params, models):
            smooth_plate.set_rr_model(model, params)
            smooth_amounts = smooth_plate.rr_solve()
            # print("1")
            # print(smooth_amounts)
            # smooth_amounts = np.split(smooth_amounts, self.model.no_species,
            #                           axis=1)
            smooth_plate.smooth_amounts.append(smooth_amounts)

        plates[0].amounts = []
        # Simulate comp model at observed timepoints and get the amounts for the zone
        plates[0].set_rr_model(models[0], est_params[0])
        plates[0].amounts = plates[0].rr_solve()
        zone_amounts = get_zone_amounts(plates[0].amounts, plates[0],
                                        models[0], coords, rows, cols)

        zones = []
        for plate in plates:
            zone = get_plate_zone(plate, coords, rows, cols)
            zone.times = plate.times
            zones.append(zone)

        # Caclulate objective function for comp model
        comp_obj_funs = []
        for i, culture in enumerate(zone.cultures):
            comp_obj_funs.append(least_sq(culture.c_meas, zone_amounts[:, i]))
        print(np.sum(comp_obj_funs))

        zone_smooth_amounts = []
        for model, smooth_amounts in zip(models, smooth_plate.smooth_amounts):
            sim_amounts = get_zone_amounts(smooth_amounts, plate, model,
                                           coords, rows, cols)
            sim_amounts = np.split(sim_amounts, self.model.no_species, axis=1)
            zone_smooth_amounts.append(sim_amounts)

        fig, grid = self._make_grid(zone,
                                    np.array(zone_smooth_amounts).flatten(),
                                    False, title, vis_ticks)

        if plot_types is None:
            plot_types = ["Est." for plate in plates]

        species_labels = {
            "C": "Cells",
            "N": "Nutrients",
        }

        # Check if c_meas are equal for the plates so don't plot
        # twice. Currently only checks for two.
        if len(plates) == 2 and len(plates[0].c_meas) == len(plates[1].c_meas):
            same_c_meas = np.array_equal(plates[0].c_meas, plates[1].c_meas)
        else:
            same_c_meas = False

        colors = {
            "C": ["b", "b", "b"],
            "N": ["y", "y", "g"],
        }
        lines = ["-", "--", "--"]

        # for i, ax in enumerate(grid):
        #     # Plot c_meas.
        #     for plate_name, c, zone in zip(plate_names, self.c_meas_colors, zones):
        #     # for plate_name, c, zone in zip(plate_names, colors["C"][:-1], zones):
        #         if same_c_meas:
        #             ax.plot(zone.times, zone.c_meas[i::zone.no_cultures],
        #                     'x', color=c, label='Observed Cells',
        #                     ms=self.ms, mew=self.mew)
        #             break
        #         else:
        #             ax.plot(zone.times, zone.c_meas[i::zone.no_cultures],
        #                     'x', color=c,
        #                     label='Observed Cells {0}'.format(plate_name),
        #                     ms=self.ms, mew=self.mew)
        #     # continue    # Remove this line
        #     # Plot smooth amounts for each estimate.
        #     plot_zip = zip(plate_names, plot_types, zone_smooth_amounts, models)
        #     for k, (plate_name, plot_type, smooth_amounts, model) in enumerate(plot_zip):
        #         for j, (amounts, species) in enumerate(zip(smooth_amounts, model.species)):
        #             # if j==1: break
        #             ax.plot(smooth_times, amounts[:, i], colors[species][k],
        #                     label="{0} ".format(plot_type) + species_labels[species] + " {0}".format(plate_name),
        #                     # lw=self.lw, ls=self.linestyles[plate_names.index(plate_name)])
        #                     lw=self.lw, ls=lines[k])
        # if log_zone is not None:
        #     # for ax, culture in zip(grid, log_zone.cultures):
        #     #     ax.plot(smooth_times, culture.c_smooth, '-',
        #     #             label='Logistic Cells', color="r", lw=self.lw)
        #     for ax, culture in zip(grid, log_zone.cultures):
        #         ax.plot(smooth_times, culture.c_smooth, '-',
        #                 label="Log. obj. {0:.3f}".format(culture.least_sq*1000),
        #                 color="r", lw=self.lw)
        #         ax.legend(loc='best', fontsize=self.legend_font_size)

        # Add text to plots with objective fuction values

        # Alternative labels objective function.
        for i, ax in enumerate(grid):
            # Plot c_meas.
            for plate_name, c, zone in zip(plate_names, self.c_meas_colors,
                                           zones):
                # for plate_name, c, zone in zip(plate_names, colors["C"][:-1], zones):
                if same_c_meas:
                    ax.plot(zone.times,
                            zone.c_meas[i::zone.no_cultures],
                            'x',
                            color=c,
                            ms=self.ms,
                            mew=self.mew)
                    break
                else:
                    ax.plot(zone.times,
                            zone.c_meas[i::zone.no_cultures],
                            'x',
                            color=c,
                            ms=self.ms,
                            mew=self.mew)
            # continue    # Remove this line
            # Plot smooth amounts for each estimate.
            plot_zip = zip(plate_names, plot_types, zone_smooth_amounts,
                           models)
            for k, (plate_name, plot_type, smooth_amounts,
                    model) in enumerate(plot_zip):
                for j, (amounts, species) in enumerate(
                        zip(smooth_amounts, model.species)):
                    if j == 0 and k == 0:
                        ax.plot(
                            smooth_times,
                            amounts[:, i],
                            colors[species][k],
                            label="Obj. {0:.2f}".format(comp_obj_funs[i] *
                                                        10000),
                            # lw=self.lw, ls=self.linestyles[plate_names.index(plate_name)])
                            lw=self.lw,
                            ls=lines[k])
                    else:
                        ax.plot(
                            smooth_times,
                            amounts[:, i],
                            colors[species][k],
                            # lw=self.lw, ls=self.linestyles[plate_names.index(plate_name)])
                            lw=self.lw,
                            ls=lines[k])
        if log_zone is not None:
            for ax, culture in zip(grid, log_zone.cultures):
                ax.plot(smooth_times,
                        culture.c_smooth,
                        '-',
                        label="Obj. {0:.2f}".format(culture.least_sq * 10000),
                        color="r",
                        lw=self.lw)
                ax.legend(loc=2, fontsize=self.legend_font_size)

        self._hide_last_ticks(grid, zone.rows, zone.cols)

        # plt.tight_layout()

        # # Change order of labels.
        # ax = grid[-1]
        # handles, labels = ax.get_legend_handles_labels()
        # new_order = [0, 2, 3, 1, 4, 5, 6, 7]
        # handles2 = [handles[i] for i in new_order]
        # labels2 = [labels[i] for i in new_order]

        # # Change order of labels.
        # ax = grid[-1]
        # handles, labels = ax.get_legend_handles_labels()
        # new_order = [0, 2, 1, 3, 4]
        # handles2 = [handles[i] for i in new_order]
        # labels2 = [labels[i] for i in new_order]

        # For multiple columns reorder the axis labels by row
        def flip(items, ncol):
            """http://stackoverflow.com/a/10101532"""
            return itertools.chain(*[items[i::ncol] for i in range(ncol)])

        ax = grid[-1]
        handles, labels = ax.get_legend_handles_labels()
        handles = flip(handles, self.legend_cols)
        labels = flip(labels, self.legend_cols)

        if legend:
            # grid[1].legend(handles2, labels2, loc='best', fontsize=self.legend_font_size)
            grid[-1].legend(handles,
                            labels,
                            loc='best',
                            fontsize=self.legend_font_size,
                            ncol=self.legend_cols,
                            bbox_to_anchor=self.bbox)

        if filename is None:
            plt.show()
        else:
            plt.savefig(filename)
        plt.close()
Beispiel #10
0
    def plot_est_rr(self,
                    plate,
                    est_params,
                    title='Estimated Growth',
                    sim=False,
                    filename=None,
                    legend=False,
                    vis_ticks=True):
        # Smooth times for sims.
        sim_times = np.linspace(plate.times[0], plate.times[-1], 100)
        # Cannot deepcopy swig objects belonging to plate so define
        # new plate and simulate smooth curves from the estimates.
        est_plate = Plate(plate.rows, plate.cols)
        est_plate.times = sim_times
        est_plate.set_rr_model(self.model, est_params)
        est_amounts = self.model.rr_solve(est_plate, est_params)
        est_amounts = np.split(est_amounts, self.model.no_species, axis=1)

        if sim:
            # "True" data
            sim_amounts = np.split(plate.sim_amounts,
                                   self.model.no_species,
                                   axis=1)

        fig, grid = self._make_grid(plate, est_amounts, sim, title, vis_ticks)

        for i, ax in enumerate(grid):
            if not sim:  # and i not in plate.empties:
                # Plot c_meas.
                ax.plot(plate.times,
                        plate.c_meas[i::plate.no_cultures],
                        'x',
                        color="black",
                        label='Observed Cells',
                        ms=self.ms,
                        mew=self.mew)
            for j, species in enumerate(self.model.species):
                ax.plot(sim_times,
                        est_amounts[j][:, i],
                        self.colours[j],
                        label="Est " + self.species[species],
                        lw=self.lw)
                if j == 0:  # and i in plate.empties:
                    # Do not plot c_meas for empty cultures.
                    continue
                elif sim:
                    # Plot all "true" amounts (e.g. including C and
                    # unobservable, but known, N.)
                    ax.plot(plate.times,
                            sim_amounts[j][:, i],
                            'x' + self.colours[j],
                            label="True" + self.species[species],
                            ms=self.ms,
                            mew=self.mew)
                else:
                    continue

        self._hide_last_ticks(grid, plate.rows, plate.cols)

        if legend:
            grid[-1].legend(loc='best', fontsize=self.legend_font_size)
        if filename is None:
            plt.show()
        else:
            plt.savefig(filename)
        plt.close()
Beispiel #11
0
def remove_edges(array, rows, cols):
    """Remove values at edge indices from a flat array."""
    empty_plate = Plate(rows, cols)
    return np.array(array)[list(empty_plate.internals)]
Beispiel #12
0
if __name__ == "__main__":
    from cans.plate import Plate
    from cans.model import CompModel
    from cans.plotter import Plotter

    outdir = "sbml_models/sim_3x3/"
    c_meas_path = outdir + "c_meas.csv"
    sbml_path = outdir + "sim_3x3.xml"

    rows = 3
    cols = 3

    comp_model = CompModel()
    comp_plotter = Plotter(comp_model)

    plate1 = Plate(rows, cols)
    plate1.times = np.linspace(0, 5, 11)

    true_params = {'N_0': 0.1, 'kn': 0.5}
    true_params['C_0'] = true_params['N_0'] / 100000.0
    plate1.set_sim_data(comp_model,
                        b_mean=100.0,
                        b_var=50.0,
                        custom_params=true_params)

    # comp_plotter.plot_est(plate1, plate1.sim_params, sim=True)

    plate1.set_rr_model(comp_model, plate1.sim_params, outfile=sbml_path)
    print(plate1.rr.model.getFloatingSpeciesInitConcentrations())

    write_c_meas(plate1, c_meas_path)