Пример #1
0
    def plotQuantity(self, quantity_id, param_values):
        ''' Plot a simulated quantity vs its data points using Tellurium.'''
        from data import measured_quantity_ids, measured_quantity_id_to_name_map
        from data import t1, t2, time_end, n1, n2, n3
        quantity_name = measured_quantity_id_to_name_map.get(quantity_id,quantity_id)
        iq = measured_quantity_ids.index(quantity_id)
        reference_data = array(self.reference_values[:,iq])

        r = RoadRunner(self.sbml)
        r.reset()
        r.resetAll()
        r.resetToOrigin()
        self._setParameterVector(param_values, self.param_list, r)
        # r.oneStep(0., 10)
        # print('plotQuantity OAA\' = {}'.format(r["OAA'"]))
        s1 = r.simulate(0., t1, n1, ['time', quantity_id])
        s2 = r.simulate(t1, t2, n2, ['time', quantity_id])
        # print(quantity_id)
        # if quantity_id == 'GLC':
            # print('BM before {}'.format(r['[BM]']))
            # print(iq)
            # print(reference_data)
        s3 = r.simulate(t2, time_end, n3, ['time', quantity_id])
        sim = vstack((
            s1,
            s2,
            s3,
            ))
        assert sim.shape[0] == reference_data.shape[0]
        residuals = sim[:,1] - reference_data

        r.reset()
        r.resetAll()
        r.resetToOrigin()
        self._setParameterVector(param_values, self.param_list, r)
        # self._setParameterVector(param_values, self.param_list, r)
        s = r.simulate(0,time_end,1000,['time',quantity_id])

        import tellurium as te
        te.plot(sim[:,0], reference_data, scatter=True,
            name=quantity_name+' data', show=False,
            title=quantity_name,
            error_y_pos=maximum(residuals,0),
            error_y_neg=-minimum(residuals,0))
        te.plot(s[:,0], s[:,1], name=quantity_name+' sim')
Пример #2
0
class B3Problem(TimecourseSimBiopredyn):
    ''' Class that performs a timecourse simulation
    and evaluates the objective function for b1.'''

    def __init__(self, sbml):
        self.sbml = sbml
        self.r = RoadRunner(sbml)
        from data import measured_quantity_ids, exp_data
        self.measured_quantity_ids = measured_quantity_ids
        self.reference_values = exp_data
        self.reference_value_means_squared = mean(self.reference_values, axis=0)**2
        from params import new_param_ids as param_ids
        self.param_list = param_ids

        self.penalty_scale = 1.


    def evaluate(self, x):
        # type: (array) -> SupportsFloat
        """
        Evaluate and return the objective function.
        """
        from interruptingcow import timeout
        # from data import time_end, n_points
        from data import t1, t2, time_end, n1, n2, n3
        self.reset()
        self.r.resetAll()
        self.r.resetToOrigin()
        self.setParameterVector(x)
        self.r.reset()
        def worker():
            # sim = array(self.r.simulate(0., time_end, n_points, self.measured_quantity_ids))

            s1 = self.r.simulate(0., t1, n1, self.measured_quantity_ids)
            s2 = self.r.simulate(t1, t2, n2, self.measured_quantity_ids)
            s3 = self.r.simulate(t2, time_end, n3, self.measured_quantity_ids)
            sim = vstack((
                s1,
                s2,
                s3,
                ))
            residuals = sim-self.reference_values
            normalized_mse_per_quantity = mean(residuals**2,axis=0)/self.reference_value_means_squared
            # from pprint import pprint
            # print('residuals:')
            # pprint({id: value for id,value in zip(self.measured_quantity_ids, sqrt(normalized_mse_per_quantity))})
            return sqrt(mean(normalized_mse_per_quantity))
        try:
            with timeout(10, StalledSimulation):
                return worker()
        except (RuntimeError, StalledSimulation):
            # if convergence fails, use a penalty score
            return 1e9*self.penalty_scale


    def plotQuantity(self, quantity_id, param_values):
        ''' Plot a simulated quantity vs its data points using Tellurium.'''
        from data import measured_quantity_ids, measured_quantity_id_to_name_map
        from data import t1, t2, time_end, n1, n2, n3
        quantity_name = measured_quantity_id_to_name_map.get(quantity_id,quantity_id)
        iq = measured_quantity_ids.index(quantity_id)
        reference_data = array(self.reference_values[:,iq])

        r = RoadRunner(self.sbml)
        r.reset()
        r.resetAll()
        r.resetToOrigin()
        self._setParameterVector(param_values, self.param_list, r)
        # r.oneStep(0., 10)
        # print('plotQuantity OAA\' = {}'.format(r["OAA'"]))
        s1 = r.simulate(0., t1, n1, ['time', quantity_id])
        s2 = r.simulate(t1, t2, n2, ['time', quantity_id])
        # print(quantity_id)
        # if quantity_id == 'GLC':
            # print('BM before {}'.format(r['[BM]']))
            # print(iq)
            # print(reference_data)
        s3 = r.simulate(t2, time_end, n3, ['time', quantity_id])
        sim = vstack((
            s1,
            s2,
            s3,
            ))
        assert sim.shape[0] == reference_data.shape[0]
        residuals = sim[:,1] - reference_data

        r.reset()
        r.resetAll()
        r.resetToOrigin()
        self._setParameterVector(param_values, self.param_list, r)
        # self._setParameterVector(param_values, self.param_list, r)
        s = r.simulate(0,time_end,1000,['time',quantity_id])

        import tellurium as te
        te.plot(sim[:,0], reference_data, scatter=True,
            name=quantity_name+' data', show=False,
            title=quantity_name,
            error_y_pos=maximum(residuals,0),
            error_y_neg=-minimum(residuals,0))
        te.plot(s[:,0], s[:,1], name=quantity_name+' sim')
        # print('deviation for {}: {}/{} = {}'.format(quantity_id, sqrt(mean(residuals**2)), sqrt(self.reference_value_means_squared[iq]),  sqrt(mean(residuals**2)/self.reference_value_means_squared[iq])))


    def getParameterValue(self,param_index):
        from params import param_index_to_name_map
        try:
            return self.r[param_index_to_name_map[param_index]]
        except KeyError:
            raise KeyError('No such parameter for index {}, must be 0-1758 inclusive'.format(param_index))
Пример #3
0
class B5Problem(TimecourseSimBiopredyn):
    ''' Class that performs a timecourse simulation
    and evaluates the objective function for b1.'''
    def __init__(self, sbml):
        self.sbml = sbml
        self.r = RoadRunner(sbml)
        self.r.integrator.absolute_tolerance = 1e-15
        self.r.integrator.relative_tolerance = 1e-9
        self.r.integrator.stiff = True
        from observables import observables
        self.measured_quantity_ids = observables
        from json import load
        with open(join(dirname(realpath(__file__)), 'exp_data.json')) as f:
            self.reference_value_collection = [array(a) for a in load(f)]
            self.reference_value_means_squared_collection = []
            for a in self.reference_value_collection:
                self.reference_value_means_squared_collection.append(
                    mean(a, axis=0)**2)
        with open(join(dirname(realpath(__file__)), 'exp_y0.json')) as f:
            self.exp_y0_collection = [array(a) for a in load(f)]
        with open(join(dirname(realpath(__file__)), 'stimuli.json')) as f:
            self.stimuli_collection = [d for d in load(f)]
        from parameters import param_ids
        self.param_list = param_ids

        self.penalty_scale = 1.

    def setExperimentNumber(self, n):
        '''
        Villaverde et al. use a set of 10 different experiments with respective
        different stimuli combinations and expected results.
        This method initialized appropriate variables for the given experiment.
        '''
        self.reference_values = self.reference_value_collection[n]
        self.reference_value_means_squared = self.reference_value_means_squared_collection[
            n]
        self.exp_y0 = self.exp_y0_collection[n]
        from species import species
        for k, s in enumerate(species):
            self.r.setValue('init({})'.format(s), float(self.exp_y0[k]))
        self.stimuli = self.stimuli_collection[n]
        for s, b in self.stimuli.items():
            print('{} = {}'.format(s, b * 1.))
            self.r[s] = b * 1.

    def evaluate(self, x):
        # type: (array) -> SupportsFloat
        """
        Evaluate and return the objective function.
        """
        from interruptingcow import timeout
        for n in range(10):
            self.setExperimentNumber(n)
            self.reset()

            def worker():
                self.r.reset()
                self.r.resetAll()
                self.setParameterVector(x, exponential=False)
                sim = self.r.simulate(0., 30., 16, self.measured_quantity_ids)
                residuals = sim - self.reference_values
                normalized_mse_per_quantity = mean(
                    residuals**2, axis=0) / self.reference_value_means_squared
                return sqrt(mean(normalized_mse_per_quantity))

            try:
                with timeout(10, StalledSimulation):
                    return worker()
            except (RuntimeError, StalledSimulation):
                # if convergence fails, use a penalty score
                return 1e9 * self.penalty_scale

    def plotQuantity(self, quantity_id, param_values, exp_number):
        ''' Plot a simulated quantity vs its data points using Tellurium.'''
        self.setExperimentNumber(exp_number)
        iq = self.measured_quantity_ids.index(quantity_id)
        reference_data = array(self.reference_values[:, iq])

        # self.r.reset()
        # self.r.resetAll()
        # # r.resetToOrigin()
        # self.setParameterVector(param_values, exponential=False)
        # sim = self.r.simulate(0., 30., 16, ['time', quantity_id])
        # # print(self.r.getReactionRates())
        # assert sim.shape[0] == reference_data.shape[0]
        # residuals = sim[:,1] - reference_data

        self.r.reset()
        self.r.resetAll()
        # r.resetToOrigin()
        self.setParameterVector(param_values, exponential=False)
        s = self.r.simulate(0, 25., 100, ['time', quantity_id])

        import tellurium as te
        # te.plot(sim[:,0], reference_data, scatter=True,
        #     name=quantity_id+' data', show=False,
        #     title=quantity_id,
        #     error_y_pos=maximum(residuals,0),
        #     error_y_neg=-minimum(residuals,0))
        print(quantity_id + ' sim')
        te.plot(s[:, 0], s[:, 1], name=quantity_id + ' sim')

    def getParameterValue(self, param_index):
        from params import param_index_to_name_map
        try:
            return self.r[param_index_to_name_map[param_index]]
        except KeyError:
            raise KeyError(
                'No such parameter for index {}, must be 0-1758 inclusive'.
                format(param_index))
Пример #4
0
class TimecourseModel(Evaluator):
    ''' Class that performs a timecourse simulation
    and calculates the residuals for b4.'''
    def __init__(self, sbml, data_quantities, measurement_map):
        '''
        Constructor.

        :param measurement_map: A dictionary that maps the names of quantities to measurements to their respective (numpy) arrays.
        '''
        self.sbml = sbml
        self.r = RoadRunner(sbml)
        self.residuals = []
        #print(self.r.getFloatingSpeciesIds())

        self.timepoints = unique(hstack(a[:, 0] for a in data_quantities))
        self.reset()

        self.measurement_map = measurement_map

        # keep track of the number of times a measurement is used
        # (check correct number of residuals)
        self.measurement_count = OrderedDict(
            (quantity, 0) for quantity in self.measurement_map)
        self.quantity_residuals = dict(
            (quantity, list()) for quantity in self.measurement_map)

    def calcResiduals(self, t):
        ''' Try to calculate residuals at the current time t
        and add them to self.residuals.
        If they do not exist for certain datasets at time t,
        just pass over the dataset.'''
        self.usage_map = dict((q, False) for q in self.measurement_map)
        for quantity in self.measurement_map.keys():
            self.tryAddResidual(t, self.r[quantity], quantity)

    def tryAddResidual(self, t, predicted_value, identifier):
        ''' Append a residual to the list of residuals.
            Call with a single value from a simulation and pass
            array of measurements for that quantity.
            If there is no measurement at this time point (t), do nothing.'''
        a = self.measurement_map[identifier]
        try:
            # if there is a measurement a this timepoint, append to list
            r = predicted_value - valueAtTime(a, t)
            self.residuals.append(r)
            self.quantity_residuals[identifier].append(r)
            # increment the residual use count (check all measurements are used exactly once)
            self.measurement_count[identifier] += 1
            self.usage_map[identifier] = True
        except MissingValue:
            # no measurement at this timepoint, do nothing
            return

    def plotQuantity(self, identifier, bars=True):
        ''' Plot a simulated quantity vs its data points using Tellurium.
        The residuals should already be calculated.'''
        data = self.measurement_map[identifier]
        # data contains one column of time and one column of values
        import tellurium as te
        te.plot(data[:, 0],
                data[:, 1],
                scatter=True,
                name=identifier + ' data',
                show=False,
                error_y_pos=maximum(array(self.quantity_residuals[identifier]),
                                    0),
                error_y_neg=-minimum(
                    array(self.quantity_residuals[identifier]), 0))
        # simulate and plot the model
        r = RoadRunner(self.sbml)
        s = r.simulate(0, self.timepoints[-1], 1000, ['time', identifier])
        te.plot(s[:, 0], s[:, 1], name=identifier + ' sim')

    def MSE(self):
        ''' Calc the MSE for all residuals.
        Call this after calculating all residuals.'''
        r = array(self.residuals)
        return (r**2).mean()

    def simulateToNextTime(self):
        t_begin = self.t
        t_end = self.timepoints[self.next_ti]
        delta = t_end - t_begin
        stepsize = 0.1
        steps = int(max(100, delta / stepsize))
        self.r.simulate(t_begin, t_end, steps)
        return t_end

    def reset(self):
        self.r.resetAll()
        self.t = self.timepoints[0]
        # next time index
        self.next_ti = 0

    def buildResidualList(self):
        # simulate to the first timepoint (not necessarily zero)
        delta = self.timepoints[0]
        stepsize = 0.1
        steps = int(max(100, delta / stepsize))
        self.r.simulate(0, delta, steps)
        self.next_ti = 1
        if len(self.timepoints) < 2:
            raise RuntimeError('Expected at least two timepoints')
        # calculate the residuals
        self.calcResiduals(self.t)
        # simulate to the rest of the timepoints
        while self.next_ti < self.timepoints.shape[0]:
            self.t = self.simulateToNextTime()
            self.calcResiduals(self.t)
            self.next_ti += 1

    def setParameterVector(self, x, param_list):
        # type: (array, List) -> None
        # TODO: sample in log space
        expect(
            len(x) == len(param_list),
            'Wrong length for parameter vector - expected {} but got {}'.
            format(len(param_list), len(x)))
        for i, v in enumerate(x):
            self.r[param_list[i]] = v

    def evaluate(self, x):
        # type: (array) -> SupportsFloat
        """
        Evaluate and return the objective function.
        """
        self.reset()
        self.setParameterVector(x)
        try:
            self.buildResidualList()
        except RuntimeError:
            # if convergence fails, use a penalty score
            return 1e9
        return self.MSE()

    def getUsageByQuantity(self):
        '''
        Calculates the number of times a given quantity is used.
        Should be equal to the number of datap oints for that quantity
        if all goes well.
        '''
        total = 0
        total_used = 0
        usage_for_quantity = OrderedDict()

        for q in self.measurement_count:
            a = self.measurement_map[q]
            used = self.measurement_count[q]
            usage_for_quantity[q] = used
            n = a.shape[0]
            total += n
            total_used += used

        return (total, total_used, usage_for_quantity)

    def printDatapointUsage(self):
        ''' For debugging. Make sure every data point is
        used.'''
        total, total_used, usage_for_quantity = self.getUsageByQuantity()
        for q, used in usage_for_quantity.keys():
            a = self.measurement_map[q]
            n = a.shape[0]
            print('Usage for {}: {}/{}'.format(q, used, n))
        print('*** Total usage: {}/{} ({:.1f}%)'.format(
            total_used, total, 100. * total_used / total))
Пример #5
0
class TimecourseSimIrreg(TimecourseSimBase):
    ''' Performs a timecourse simulation on an irregular grid.'''
    def __init__(self, sbml, data_quantities, measurement_map):
        '''
        Constructor.

        :param measurement_map: A dictionary that maps the names of quantities to measurements to their respective (numpy) arrays.
        '''
        self.sbml = sbml
        self.r = RoadRunner(sbml)
        # self.r.integrator.stiff = False
        # self.r.integrator.minimum_time_step = 0.0001
        # self.r.integrator.maximum_time_step = 1.
        # self.residuals = []
        #print(self.r.getFloatingSpeciesIds())

        self.timepoints = unique(hstack(a[:, 0] for a in data_quantities))
        self.reset()

        self.measurement_map = measurement_map
        # map a quantity to its mean measured value
        self.mean_measurement_map = {
            quantity: mean(values[:, 1])
            for quantity, values in self.measurement_map.items()
        }

        # keep track of the number of times a measurement is used
        # (check correct number of residuals)
        self.measurement_count = OrderedDict(
            (quantity, 0) for quantity in self.measurement_map)
        self.penalty_scale = 1.

    def plotQuantity(self, identifier, param_values, bars=True):
        ''' Plot a simulated quantity vs its data points using Tellurium.
        The residuals should already be calculated.'''
        data = self.measurement_map[identifier]
        # data contains one column of time and one column of values
        import tellurium as te
        te.plot(data[:, 0],
                data[:, 1],
                scatter=True,
                name=identifier + ' data',
                show=False,
                error_y_pos=maximum(array(self.quantity_residuals[identifier]),
                                    0),
                error_y_neg=-minimum(
                    array(self.quantity_residuals[identifier]), 0))
        # simulate and plot the model
        r = RoadRunner(self.sbml)
        if param_values is not None:
            self._setParameterVector(param_values, self.param_list, r)
        s = r.simulate(0, self.timepoints[-1], 1000, ['time', identifier])
        te.plot(s[:, 0], s[:, 1], name=identifier + ' sim')

    def calcResiduals(self, t):
        ''' Try to calculate residuals at the current time t
        and add them to self.residuals.
        If they do not exist for certain datasets at time t,
        just pass over the dataset.'''
        self.usage_map = dict((q, False) for q in self.measurement_map)
        for quantity in self.measurement_map.keys():
            self.tryAddResidual(t, self.r[quantity], quantity)

    def tryAddResidual(self, t, predicted_value, identifier):
        ''' Append a residual to the list of residuals.
            Call with a single value from a simulation and pass
            array of measurements for that quantity.
            If there is no measurement at this time point (t), do nothing.'''
        a = self.measurement_map[identifier]
        try:
            # if there is a measurement a this timepoint, append to list
            r = predicted_value - valueAtTime(a, t)
            # self.residuals.append(r)
            self.quantity_residuals[identifier].append(r)
            # increment the residual use count (check all measurements are used exactly once)
            self.measurement_count[identifier] += 1
            self.usage_map[identifier] = True
        except MissingValue:
            # no measurement at this timepoint, do nothing
            return

    def simulateToNextTime(self):
        t_begin = self.t
        t_end = self.timepoints[self.next_ti]
        delta = t_end - t_begin
        stepsize = 0.1
        steps = int(max(100, delta / stepsize))
        self.r.simulate(t_begin, t_end, steps)
        return t_end

    def reset(self):
        self.r.resetAll()
        self.t = self.timepoints[0]
        # next time index
        self.next_ti = 0

    def buildResidualList(self):
        # simulate to the first timepoint (not necessarily zero)
        delta = self.timepoints[0]
        stepsize = 0.1
        steps = int(max(100, delta / stepsize))
        self.r.simulate(0, delta, steps)
        if self.divergent():
            raise RuntimeError('Diverged at first time step')
        self.next_ti = 1
        if len(self.timepoints) < 2:
            raise RuntimeError('Expected at least two timepoints')
        # calculate the residuals
        self.calcResiduals(self.t)
        # simulate to the rest of the timepoints
        while self.next_ti < self.timepoints.shape[0]:
            self.t = self.simulateToNextTime()
            if self.divergent():
                raise RuntimeError('Diverged at time step {}'.format(
                    self.next_ti))
            self.calcResiduals(self.t)
            self.next_ti += 1

    def evaluate(self, x):
        # type: (array) -> SupportsFloat
        """
        Evaluate and return the objective function.
        """
        from interruptingcow import timeout
        self.reset()
        self.setParameterVector(x)
        self.quantity_residuals = dict(
            (quantity, list()) for quantity in self.measurement_map)

        def worker():
            self.buildResidualList()

        if self.divergent():
            return 1e9 * self.penalty_scale
        try:
            with timeout(10, StalledSimulation):
                worker()
        except (RuntimeError, StalledSimulation):
            # if convergence fails, use a penalty score
            return 1e9 * self.penalty_scale
        print('evaluate')
        # for quantity,residuals in self.quantity_residuals.items():
        # print(quantity,mean(array(residuals)**2.),self.mean_measurement_map[quantity])
        return sqrt(mean(array([
            mean(array(residuals)**2.)/self.mean_measurement_map[quantity]**2. \
            for quantity,residuals in self.quantity_residuals.items() \
            ])))

    def getUsageByQuantity(self):
        '''
        Calculates the number of times a given quantity is used.
        Should be equal to the number of datap oints for that quantity
        if all goes well.
        '''
        total = 0
        total_used = 0
        usage_for_quantity = OrderedDict()

        for q in self.measurement_count:
            a = self.measurement_map[q]
            used = self.measurement_count[q]
            usage_for_quantity[q] = used
            n = a.shape[0]
            total += n
            total_used += used

        return (total, total_used, usage_for_quantity)

    def printDatapointUsage(self):
        ''' For debugging. Make sure every data point is
        used.'''
        total, total_used, usage_for_quantity = self.getUsageByQuantity()
        for q, used in usage_for_quantity.keys():
            a = self.measurement_map[q]
            n = a.shape[0]
            print('Usage for {}: {}/{}'.format(q, used, n))
        print('*** Total usage: {}/{} ({:.1f}%)'.format(
            total_used, total, 100. * total_used / total))

    def RMSE_quantity(self, identifier):
        ''' Calc the RMSE of a quantity.'''
        from math import sqrt
        return sqrt(
            float((array(self.quantity_residuals[identifier])**
                   2).mean())) / self.mean_measurement_map[identifier]