Exemplo n.º 1
0
    def __init__(self, birthdate=None, id=None, min_radius=0.001, latency=6, 
                 store_data=True):
        """**Constructor**

        :param datetime.datetime birthdate:
        :param int id:
        :param float min_radius: in meters
        :param int store_data:
        :param float latency: number of days of latency before stopping the gu.

        :attributes:
            * :attr:`length`: total length of the growth unit in meters
            * :attr:`radius`:  radius of at the base of the growth unit (see plants module)
            * those inherited by :class:`~openalea.plantik.biotik.component.ComponentInterface`:
                * :attr:`age`
                * :attr:`demand`
                * :attr:`birthdate`
                * :attr:`state` set to 'growing' by default in the constructor. Then, the :meth:`update`
                  may set to it to 'stopped' if no changement has been done for a duration> :attr:`latency`.
            * :attr:`internode_counter`: number of internodes in the growth unit
            * :attr:`variables` is a :class:`CollectionVariables` instance containing the :attr:`age`,
              :attr:`radius` and :attr:`length` at each time step



        .. note:: when creating a gu, :attr:`state` is by definition set 
            to 'growing'.
        """
        self.context = Context()
        # when creating a gu, it is by definition in a growing state.
        ComponentInterface.__init__(self, label='GrowthUnit', 
                                    birthdate=birthdate, id=id, state='growing')

        self.store_data = store_data

        self._length = 0.
        self._radius = min_radius
        self._latency = latency
        self._internode_counter = 0.

        self.variables = CollectionVariables()
        self.variables.add(SingleVariable(name='age', unit='days', 
                                          values=[self.age.days]))
        self.variables.add(SingleVariable(name='length', unit='meters', 
                                          values=[self.length]))
        self.variables.add(SingleVariable(name='radius', unit='meters', 
                                          values=[self.radius]))

        self.__step_without_growing = 0
Exemplo n.º 2
0
    def __init__(self,
                 time_step,
                 options=None,
                 revision=None,
                 pipe_fraction=1.,
                 filename=None,
                 tag=None):
        """**Constructor**

        :param float time_step: the time step of the simulation.
        :param options: a variable containing the simulation options from the config 
            file (see :class:`~vplants.plantik.tools.config.ConfigParams`)
        :param str revision: a SVN revision for book keeping.
        :param float pipe_fraction:
        :param str filename:  if None, populates attribute :attr:`filename` with 'plant'
        :param str tag:  append to the filename if not None

        :param pipe_fraction: cost of the pipe model is metamer_growth volume times the
          pipe_fraction parameter

            >>> from vplants.plantik import get_shared_data
            >>> from vplants.plantik.tools import  ConfigParams
            >>> from vplants.plantik.biotik import Plant
            >>> options = ConfigParams(get_shared_data('pruning.ini'))
            >>> plant = Plant(1, options, revision=1, tag='test')
            >>> plant.filename
            'plant_test'
            >>> plant.dt
            1


        :Attributes:

            * :attr:`revision` :
            * :attr:`options`  :
            * :attr:`time`  :
            * :attr:`filename`:
            * :attr:`mtg`:
            * :attr:`lstring`: used to store the lstring of an lsystem
            * :attr:`dt`:
            * :attr:`mtgtools`: an attribute of type :class:`~vplants.plantik.tools.mtgtools.MTGTools` that is used
              to store the mtg and retrieve many relevant information. It also has a DB facility.
            * :attr:`variables`: a :class:`~vplants.plantik.biotik.collection.CollectionVariables` instance containing the `pipe_ratio`
              variable. pipe_ratio contains is the ratio of resource attributed to the pipe model over time.
            * :attr:`counter`: a :class:`~vplants.plantik.biotik.collection.CollectionVariables` instance containing the count of 
              leaves/internodes/apices/growth units/branches over time. See also :meth:`plot_counter` and :meth:`update_counter`.
            * :attr:`DARC`: a :class:`~vplants.plantik.biotik.collection.CollectionVariables` instance containing the DARC values. 
              See also :meth:`plot_DARC` and :meth:`update_DARC`. DARC stands for Demand, Allocated, Resource, Cost


        .. todo:: clean up all other variables that could be extracted from the lstring ?
        .. todo:: difference pipe_ratio pipe_fraction
        .. todo::   duration,        apex,        all,        dv 
        """

        # RESERVE related
        try:
            self.reserve_duration = options.reserve.duration  # used for the reserve sigmoid
            self.reserve_starting_time = options.reserve.starting_time  # used for the reserve sigmoid
            assert options.reserve.alpha >= 0 and options.reserve.alpha <= 1, 'options reserve.alpha must be in [0,1] in ini file.'
            self.reserve_alpha = options.reserve.alpha
            self.verbose = options.general.verbose
        except:
            self.reserve_duration = 210
            self.reserve_starting_time = 105
            self.reserve_alpha = 1
            self.verbose = True
        self.Reserve = 0

        #FILENAME
        if filename != None: assert type(filename) == str
        if tag != None: assert type(tag) == str

        self._filename = self._set_filename(filename, tag)
        self._revision = revision
        self._options = options
        self._time = []
        self.age = 0
        self._mtg = None
        self._lstring = None
        self.label = 'Plant'
        # could be retrieved from options parameter but let us try to not depends on options !
        self._dt = time_step

        #!! when calling self.mtg, what you really do is self.mtgtools.mtg
        # !!when doing self.mtg = a, what you really do is self.mtgtools.mtg = a
        self.mtgtools = MTGTools(verbose=self.verbose)

        self.D = 0
        try:
            self.R = options.root.initial_resource
        except:
            self.R = 1
        self.C = 0
        self.A = 0
        self.allocated = []

        self.duration = 0  # used to store the duration of the simulation
        self.apex = {
            'demand': [],
            'allocated': [],
            'height': [],
            'age': []
        }  # keeps track of the main apex characteristics
        self.all = {'age': [], 'order': [], 'height': []}

        #: expected increase of volume related to the pipe model.
        self.dV = 0

        #PIPE FRACTION
        assert pipe_fraction <= 1 and pipe_fraction >= 0
        self.pipe_fraction = pipe_fraction

        self.radius = 0

        #: extract storeage for variables over time inluding :attr:`pipe_ratio` and :attr:`dV`.
        self.variables = CollectionVariables()
        self.variables.add(
            SingleVariable(name='pipe_ratio', unit='ratio', values=[]))
        self.variables.add(SingleVariable(name='dV', unit='ratio'))
        self.variables.add(SingleVariable(name='reserve', unit='UR'))

        self.year = 1

        self._reserve_function = GrowthFunction(
            0,
            1,
            maturation=(self.year) * self.reserve_duration -
            self.reserve_starting_time - (self.year - 1) * 365,
            growth_rate=0.1,
            growth_function='sigmoid',
            nu=1)

        #: a CollectionVariable instance that containes the count of
        # **apices**, **internodes**, **leaves**
        #: **branches** and growth units (denoted **gus**) at each time step.
        #For instance, to acces to apices counter::
        #:
        #: plant.counter.apices.values
        self.counter = CollectionVariables()
        self.counter.add(SingleVariable(name='apices', unit=r'#'))
        self.counter.add(SingleVariable(name='internodes', unit=r'#'))
        self.counter.add(SingleVariable(name='leaves', unit=r'#'))
        self.counter.add(SingleVariable(name='branches', unit=r'#'))
        self.counter.add(SingleVariable(name='gus', unit=r'#'))

        #: a CollectionVariable instance that contains the demand (D), allocated resources(R),
        #: resources (R) and cost (C) at each time step. To acces to demand over time::
        #:
        #: >>> plant.DARC.D.values
        self.DARC = CollectionVariables()
        self.DARC.add(SingleVariable(name='D', unit='biomass unit', values=[]))
        self.DARC.add(SingleVariable(name='A', unit='biomass unit', values=[]))
        self.DARC.add(SingleVariable(name='R', unit='biomass unit', values=[]))
        self.DARC.add(SingleVariable(name='C', unit='biomass unit', values=[]))
        self.DARC.add(SingleVariable(name='pipe_cost', unit='biomass unit'))
Exemplo n.º 3
0
    def __init__(self,
                 final_length=0.03,
                 length_max=0.03,
                 length_min=0.001,
                 cambial_fraction=0.,
                 birthdate=None,
                 id=None,
                 maturation=10,
                 radius_min=0.001,
                 growth_rate=1,
                 growth_function='logistic',
                 store_data=False,
                 nu=1):
        r"""**Constructor**


        :param float final_length: final length :math:`l^{(i)_{\rm{final}}}`
        :param float length_max: maximum internode length, :math:`l^{(i)}_{max}` (default is 3cm)
        :param float length_min: maximum internode length, :math:`l^{(i)}_{min}` (default is 0.1cm)
        :param float cambial_fraction: :math:`p_c` (default is 0.) 
        :param datetime.datetime birthdate:
        :param int id:
        :param float maturation: :math:`T^{(i)}_m` (default is 10) 
        :param float radius_min: starting radius of an internode, :math:`r^{(i)}_{min}` (in meters) (default is 0.001)        
        :param str growth_function: linear or logistic (default is logistic) 
        :param float growth_rate: :math:`\lambda` (default is 1)
        :param float nu: :math:`\nu^{(i)}` parameter of the logistic function (default is 1)
        :param int store_data: store length, radius, demand at each time step (default is False)

        .. note:: the growth function is logistic by default, which is identical 
            to a sigmoid function isnce :math:`\nu=1` and :math:`\lambda=1`.
            
        
        :attributes:
            * :attr:`length`: internode length
            * :attr:`radius`:  internode radius (supposed the same from base to top)
            * :attr:`target_radius`:  at each time step, a pipe model may be computed indicating what the new radius should be.
            *  those inherited by :class:`~vplants.plantik.biotik.component.ComponentInterface`: 
                * :attr:`age`
                * :attr:`demand`
                * :attr:`birthdate`, ...
            * :attr:`mass`
            * :attr:`volume`
    
        """
        self.radius_min = radius_min
        self.length_max = length_max
        self.length_min = length_min
        self.final_length = final_length
        assert final_length >= length_min, 'final length must be greater or equal to min length'
        assert length_max >= length_min, 'max length must be greater or equal to min length'

        self.volume_standard = 3.14159 * self.radius_min**2 * self.length_max
        self.cost_per_metamer = 1. / (self.radius_min * self.radius_min *
                                      self.length_max * pi)

        self.context = Context()
        ComponentInterface.__init__(self,
                                    label='Internode',
                                    birthdate=birthdate,
                                    id=id)

        self._radius = self.radius_min
        self._target_radius = self.radius_min
        self._length = GrowthFunction(self.length_min,
                                      self.final_length,
                                      maturation=maturation,
                                      growth_rate=growth_rate,
                                      nu=nu,
                                      growth_function=growth_function)

        self.store_data = store_data

        self.variables = CollectionVariables()
        self.variables.add(
            SingleVariable(name='age', unit='days', values=[self.age.days]))
        self.variables.add(
            SingleVariable(name='length', unit='meters', values=[self.length]))
        self.variables.add(
            SingleVariable(name='radius', unit='meters', values=[self.radius]))
        #self.variables.add(SingleVariable(name='demand',
        #    unit='biomass unit', values=[self.demand]))
        self.variables.add(
            SingleVariable(name='living_cost',
                           unit='biomass unit',
                           values=[self.livingcost]))

        self.demand_coeff = 0.
        self.density = 1.

        assert cambial_fraction <= 1 and cambial_fraction >= 0
        self._mu = cambial_fraction  # % of cambial layer alive
Exemplo n.º 4
0
    def __init__(self,
                 resource_per_day,
                 birthdate=None,
                 id=None,
                 maturation=21,
                 internode_vigor=1.,
                 livingcost=0.,
                 growth_rate=1,
                 area_optimal=30 * 0.01 * 0.01,
                 growth_function='sigmoid',
                 efficiency_method='unity',
                 store_data=False,
                 nu=1,
                 t1=15,
                 t2=150,
                 angle=0.):
        """**Constructor**

        

        :param float resource_per_day: stricly positive , notation :math:`r_0`. 

        :param datetime.datetime birthdate:
        :param int id:
        :param float maturation: leaf maturation in days
        :param float internode_vigor: a leaf area is proportional to the internode length. 
            intenode_vigor of 1 means the internode had full length and therefore leaf has
            a potential for maximum area as well.
        :param float livingcost: zero by default
        :param float growth_rate: the :math:`lambda` parameter of the growth function
        :param str growth_function: a GrowthFunction method in ['linear', 'sigmoid', 'logistic']
        :param nu: shape of the logistic function is :attr:`growth_function` is logisitic
        :param efficiency_method: 'unity' or 'sigmoid' (default is unity)
        :param int store_data:
        :param float t1: parameter of the leaf_efficiency method
        :param float t2: parameter of the leaf_efficiency method
        
        
        :attributes:

            * :attr:`area`: the leaf area, a :meth:`~vplants.plantik.biotik.growth.GrowthFunction` 
              instance (read-only). The input parameters **growth_function**, **growth_rate**, **nu**,
              and **maturation** are used by this function.
            * Those inherited by :class:`~vplants.plantik.biotik.component.ComponentInterface`: 
              :attr:`age`,
              :attr:`allocated`,
              :attr:`demand`,
              :attr:`livingcost`,
              :attr:`~vplants.plantik.biotik.component.ComponentInterface.resource`.
            * :attr:`variables` is a :class:`CollectionVariables` instance containing the :attr:`age`, 
              :attr:`demand`, :attr:`resource`, :attr:`area`.
        """
        assert internode_vigor >= 0 and internode_vigor <= 1, \
            "internode vifor must be in [0,1]"
        assert resource_per_day > 0, \
            'resource_per_day must be positive otherwise noting will happen...'

        self.context = Context()
        ComponentInterface.__init__(self,
                                    label='Leaf',
                                    birthdate=birthdate,
                                    id=id,
                                    state='growing')

        # leaf min must correspond to internode length min so that
        # leafmaxarea>-leafminarea
        self._radius = Leaf.petiole_radius  # for geometry purpose only

        # set the area growth function
        self.area_max = Leaf.area_max * internode_vigor
        self._area = GrowthFunction(Leaf.area_min,
                                    self.area_max,
                                    maturation=maturation,
                                    growth_rate=growth_rate,
                                    growth_function=growth_function,
                                    nu=nu)
        self._r0 = resource_per_day
        self.angle = angle

        # used for bookeeping only
        self.internode_vigor = internode_vigor  # in %
        self.maturation = maturation  # in days

        # used by update()
        self.store_data = store_data

        # some variables to store.
        self.variables = CollectionVariables()
        self.variables.add(
            SingleVariable(name='age', unit='days', values=[self.age.days]))
        self.variables.add(
            SingleVariable(name='resource',
                           unit='biomass unit',
                           values=[self.resource]))
        self.variables.add(
            SingleVariable(name='demand',
                           unit='biomass unit',
                           values=[self.demand]))
        self.variables.add(
            SingleVariable(name='area',
                           unit='square meters',
                           values=[self.area]))

        # parameters
        self.livingcost = livingcost  # cost to maintain leaf alive !!
        self.efficiency_method = efficiency_method

        # other attributes.
        # radius used by the interpretation of the lsystem.
        #todo: move it elsewhere outsitde this class.
        self.father_radius = 0

        #others
        self.lg = 0.  # light interception

        # related to leaf efficiency
        self._leaf_efficiency = 1.
        self.t1 = t1
        self.t2 = t2
        self.growth_rate = growth_rate
Exemplo n.º 5
0
    def __init__(self, birthdate=None, 
                 demand=2, metamer_cost=2, livingcost=0.,
                 height=0., id=0, plastochron=3., growth_threshold = 0.2,
                 vigor=0.1, store_data=False):
        """**Constructor**

        :param datetime.datetime birthdate: (default is None)
        :param float demand:  (default is 2)
        :param float metamer_cost:    (default is 2)
        :param float livingcost: (default is 0)
        :param float height:   (default is 0)
        :param int id: (default is 0)
        :param plastochron: (default is 3)
        :param float growth_threshold: a value between  0 and 1 allowing a 
            production once allocation is larger than this value
        :param vigor: (default is 0.1)
        :param store_data: used by :meth:`save_data_product` to save data at each 
           time step (default is False).

        Additional attributes 

        :attributes:
            * :attr:`current_plastochron`:
            * :attr:`radius`:  (default is 0)
            * :attr:`growth_potential`:  (default is 1)
            * :attr:`interruption`: time step during which an apex is not growing (default is 0.)
            * :attr:`growing` (default is False)
            * :attr:`father_radius`  (default is 0.)
            * :attr:`lg`: used to store light interception
            * :attr:`internodes_created`  keep track of the number of internodes created by this
                apex (default is 0.).

        """
        self.context = Context()
        ComponentInterface.__init__(self, label='Apex', birthdate=birthdate, 
                                    id=id)


        # read-only attribute
        self.plastochron = plastochron      # time interval at which production of new biological object is possible
        self.metamer_cost = metamer_cost    # cost to produce new object (internode + new bud)
        self.demand = demand                # demand of the metamer in biomass unit/per time  unit


        self.store_data = store_data

        self._height = height
        self._vigor = vigor
        self._growth_threshold = growth_threshold

        self.lg = 0.14
        self.variables = CollectionVariables()
        self.variables.add(SingleVariable(name='age', unit='days', 
                                          values=[self.age.days]))
        self.variables.add(SingleVariable(name='height', unit='meters', 
                                          values=[self.height]))
        self.variables.add(SingleVariable(name='demand', unit='biomass unit', 
                                          values=[self.demand]))
        self.variables.add(SingleVariable(name='allocated', unit='biomass unit', 
                                          values=[self.allocated]))
        self.variables.add(SingleVariable(name='vigor', unit='biomass unit', 
                                          values=[self.vigor]))
        self.variables.add(SingleVariable(name='lg', unit='arbitrary', 
                                          values=[self.lg]))


        #read-write attributes
        self.livingcost = livingcost      # cost to maintain the apex alive
        self.initial_demand = demand

        # additional attributes
        self.current_plastochron = 0.   # keep track of the plastochron
        self.radius = 0.00 # for the pipe model
        self.growth_potential = 1   #?



        self.father_radius = 0.
        self.interruption = 0.   # time step during which an apex is not growing
        self.growing = False
        self.internodes_created = 0.        # count number of internodes created by this apex

        self.lg = 0.14

        self.type = 'Apex' #apex or meristem