diff --git a/README.md b/README.md index 604e0b0b..be66208c 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ gramineaous plant. ## Content The package hosts generic data structure and simulation tools for -gramineaous plants(Fournier & Pradal, unpublished), the Adel-Maize +gramineous plants(Fournier & Pradal, unpublished), the Adel-Maize (Fournier & Andrieu, 1998), Adel-Wheat (Fournier et al. 2003) models, together with the wheat parameterization model of Abichou et al. (2013) and the plastic leaf model of Fournier & Pradal (2012) @@ -48,6 +48,6 @@ mamba env create -n adel -c openalea3 -c conda-forge openalea.adel ```bash git clone 'https://github.com/openalea/adel.git' -cd caribu +cd adel mamba env create -n adel_dev -f ./conda/environment.yml ``` diff --git a/src/openalea/adel/Adel.R b/src/openalea/adel/Adel.R index ec7c4bf8..e0a8e366 100644 --- a/src/openalea/adel/Adel.R +++ b/src/openalea/adel/Adel.R @@ -393,6 +393,19 @@ kinLvis <- function(kinlist,pars=NULL) { # stem inclination is beared by visible sheaths (option 0) or by nodes (option 1) # leaf inclination indicates whether leaf base angle is dynamic or not # +#compute incT +getIncT <- function(axename, HS, incBase, start_incT=1, incT_rate=30) { + if (axename == "MS") { + incT <- incBase + } else { + if (HS > start_incT) { + incT <- max(3,min(incBase, incT_rate * (HS - start_incT))) + } else { + incT <- 3 + } + } + incT +} # #returns stack of visible elements of the stem of an axe stemElements <- function(desc) { @@ -416,29 +429,14 @@ stemElements <- function(desc) { # # Compute inclinations of stem elements # -axe_inclination <- function(dat, HS, ht, axename, incBase, dredT, start_incT=1, incT_rate=30,epsillon=1e-6) { +axe_inclination <- function(dat, incT, dredT, epsillon=1e-6) { nbphy <- nrow(dat)#inclus ear,ped et awn # Calcul des inclinaisons de tiges # 1er phyto = entrenoeud a incT Einc <- rep(0,nbphy) Ginc <- rep(0,nbphy) - if (axename == "MS") { - incT <- incBase - } else { - if (HS > start_incT) { - incT <- max(3,min(incBase, incT_rate * (HS - start_incT))) - } else { - incT <- 3 - } - } Einc[1] <- incT - if (axename != "MS" && incT <= 3) { #Do not represent basal part of first metamer for non inclining tillers - dat$Lv[1] = min(dat$Ll[1],max(0, dat$Ll[1] + dat$Gl[1] + dat$El[1] - ht)) - dat$Lr[1] = min(dat$Lv[1],dat$Lr[1]) - dat$Gv[1] = min(dat$Gl[1],max(0, dat$Gl[1] + dat$El[1] - ht)) - dat$Ev[1] = min(dat$El[1],max(0, dat$El[1] - ht)) - } - # redressement (if any) + # redressement (if any) if (dredT > 0 & sum(dat$Ev+dat$Gv) > epsillon) { #distance inserton talle -> extremite stemElements stem <- stemElements(dat) @@ -519,7 +517,8 @@ getdesc <- function(kinlist,plantlist,pars=list("senescence_leaf_shrink" = 0.5," axilrank <- ms_pos(axename) ht <- kin$MS[t,axilrank+1,"ht"] # length of the tube the axe emerge from } - dat <- axe_inclination(dat, HS_axe, ht, axename, dataxe$incT, dataxe$dredT, start_incT, incT_rate) + incT <- getIncT(axename, HS_axe, dataxe$incT, start_incT, incT_rate) + dat <- axe_inclination(dat, incT, dataxe$dredT) #azimuts : Attention new 21 fev 2011 : azimuts en relatif / phytomere precedent ! Laz <- datp$Azim @@ -639,4 +638,5 @@ getAxeT <- function(plants) do.call('rbind', mapply(function(idpl,pl) {df=pl$axe getPhenT <- function(plants, axe='MS') do.call('rbind', mapply(function(idpl,pl) {df=pl$pheno[[axe]];df$plant=idpl;df},seq(plants),plants,SIMPLIFY=FALSE)) # getPhytoT <- function(plants, axe='MS') do.call('rbind', mapply(function(idpl,pl) {df=data.frame(pl$phytoT[,,axe]);df$plant=idpl;df$axe=axe;df$n=seq(nrow(df));df},seq(plants),plants,SIMPLIFY=FALSE)) - +# +AxeDfList <- function(axeArray) setNames(lapply(seq_len(dim(axeArray)[3]), function(i) {as.data.frame(axeArray[, , i])}),dimnames(axeArray)[[3]]) diff --git a/src/openalea/adel/AdelR.py b/src/openalea/adel/AdelR.py index cc0129d4..b2316e48 100644 --- a/src/openalea/adel/AdelR.py +++ b/src/openalea/adel/AdelR.py @@ -58,6 +58,7 @@ def get_rcode(file_name): RgetAxeT = robj.globalEnv["getAxeT"] RgetPhenT = robj.globalEnv["getPhenT"] RgetPhytoT = robj.globalEnv["getPhytoT"] +RAxeDfList = robj.globalEnv["AxeDfList"] # RgetLeafT = robj.globalEnv['getLeafT'] @@ -116,6 +117,32 @@ def dataframeAsdict(df): ) # r delegator is replaced by rx/rx2 in new rpy2 return d +def axeDfdict(axe_array): + """convert a [,,axe] Rarray to python axe list of dict""" + if r["is.null"](axe_array)[0]: + return None + return RlistAsDict(RAxeDfList(axe_array)) + + +def setAdelpars(Rpars): + """convert output of setAdel R object to python readable object""" + Rplants = RlistAsDict(Rpars) + pyplants = {} + for p in Rplants: + rout = RlistAsDict(Rplants[p]) + pyout = {} + pyout['refp'] = rout['refp'][0] + pyout['axeT'] = pandas.DataFrame(dataframeAsdict(rout['axeT'])) + _phytoT = axeDfdict(rout['phytoT']) + pyout['phytoT'] = {axe: pandas.DataFrame(dataframeAsdict(df)) for axe, df in _phytoT.items()} + _pheno = RlistAsDict(rout['pheno']) + pyout['pheno'] = {axe: pandas.DataFrame(dataframeAsdict(df)) for axe, df in _pheno.items()} + _pedT = RlistAsDict(rout['pedT']) + pyout['pedT'] = {axe: pandas.DataFrame(dataframeAsdict(df)) for axe, df in _pedT.items()} + if 'ssisenT' in rout: + pyout['ssisenT'] = pandas.DataFrame(dataframeAsdict(rout['ssisenT'])) + pyplants[p] = pyout + return pyplants def _is_iterable(x): try: diff --git a/src/openalea/adel/adel.py b/src/openalea/adel/adel.py index c1485a5d..852ec4cb 100644 --- a/src/openalea/adel/adel.py +++ b/src/openalea/adel/adel.py @@ -22,7 +22,7 @@ plot_statistics, midrib_statistics, ) -from openalea.adel.newmtg import exposed_areas, exposed_areas2canS, duplicate, mtg_factory +from openalea.adel.newmtg import exposed_areas, exposed_areas2canS, stem_elements, stem_bases, duplicate, mtg_factory def flat_list(nested_list): @@ -342,6 +342,25 @@ def get_exposed_areas(self, g, convert=False, TT=None): areas["TT"] = TT return areas + def get_stem_bases(self, g): + return stem_bases(g) + + def get_stem_elements(self, g): + bases = self.get_stem_bases(g) + desc = self.get_exposed_areas(g) + desc = pandas.concat([desc, bases]).drop_duplicates().sort_values('vid') + + result = [] + + for (pid, plant, axe), axe_desc in desc.groupby(["refplant_id", "plant", "axe"]): + stem = stem_elements(axe_desc, axe=axe) + stem["axe"] = axe + stem["plant"] = plant + stem["refplant_id"] = str(int(pid)) + result.append(stem) + + return pandas.concat(result, ignore_index=True) + def axis_statistics(self, g): meta = self.meta_informations(g) df_lai = self.get_exposed_areas(g, convert=True) diff --git a/src/openalea/adel/adelwheat_dynamic.py b/src/openalea/adel/adelwheat_dynamic.py index c3eff558..55ad8767 100644 --- a/src/openalea/adel/adelwheat_dynamic.py +++ b/src/openalea/adel/adelwheat_dynamic.py @@ -106,13 +106,13 @@ def build_mtg(self, parameters, stand, **kwds): return g def update_geometry( - self, g, SI_units=False, properties_to_convert={"lengths": [], "areas": []} + self, g, SI_units=None, properties_to_convert={"lengths": [], "areas": []} ): """Update MTG geometry. :Parameters: - `g` (:class:`openalea.mtg.mtg.MTG`) - The MTG to update the geometry. - - `SI_units` (:class:`bool`) - A boolean indicating whether the MTG properties are expressed in SI units. + - `SI_units` (:class:`bool`) - deprecated : use scene _unit to specify unit for scene and properties. - `properties_to_convert` (:class:`dict` of :class:`pandas.DataFrame`) - A dictionnary with the list of length properties area properties to be converted. :Returns: MTG with updated geometry @@ -120,11 +120,15 @@ def update_geometry( :class:`openalea.mtg.mtg.MTG` """ - if SI_units: - self.convert_to_ADEL_units(g, properties_to_convert) + if SI_units is not None: + raise ValueError('SI_units is deprecated, use scene _unit to specify unit for both scene and mtg properties, use dev_T unit to provide adel inputs in another unit') + #self.convert_to_ADEL_units(g, properties_to_convert) # update elements g = update_organ_elements(g, self.leaves, self.split, self.phyllochron()) + inclinations = self.axe_inclination(g) + newinc = inclinations.set_index("vid")["inclination"].to_dict() + g.property('inclination').update(newinc) g = mtg_interpreter(g, self.leaves, min_length=self.min_length, face_up=self.face_up, classic=self.classic) pos = g.property("position") az = g.property("azimuth") diff --git a/src/openalea/adel/astk_interface.py b/src/openalea/adel/astk_interface.py index 5cf99890..56743af8 100644 --- a/src/openalea/adel/astk_interface.py +++ b/src/openalea/adel/astk_interface.py @@ -2,6 +2,7 @@ import os import numpy +import pandas from openalea.adel.AdelR import ( setAdel, RunAdel, @@ -12,6 +13,7 @@ getPhytoT, saveRData, readRData, + setAdelpars ) from openalea.adel.newmtg import move_properties import openalea.adel.data_samples as adel_data @@ -58,45 +60,48 @@ def __call__(self, time_sequence, weather_data): class AdelWheat(Adel): def __init__( - self, - devT=None, - sample="random", - thermal_time_model=None, - geoAxe=None, - incT=60, - dinT=5, - dep=7, - run_adel_pars=None, - aborting_tiller_reduction=1.0, - ssipars=None, - nplants=1, - duplicate=None, - species=None, - nsect=1, - leaves=None, - stand=None, - aspect="smart", - split=False, - face_up=False, - classic=False, - devT_unit="cm", - scene_unit="cm", - age=None, - seed=None, - leaf_db=None, - positions=None, - convUnit=None, - ): - self.canopy_age = None - if species is not None or isinstance(leaves, dict): - raise ValueError("multi_species canopies not yet implemented") + self, + devT=None, + devT_unit="cm", + sample="random", + thermal_time_model=None, + geoAxe=None, + incT=60, + dinT=5, + dep=7, + run_adel_pars=None, + aborting_tiller_reduction=1.0, + ssipars=None, + *args, **kwargs): + """ + Args: + devT: adel parameter, eg as generated by plantgen + devT_unit: lenght unit used in devT (eg 'cm') + sample: if 'random' (default) plants are sampled randomly in devT, otherwise devT is recycled keeping its original order + thermal_time_model: a callable computing thermal time + geoAxe: a R code to pass to adel for axe geometry. If none, built from incT, dinT and dep + incT: basal inclination of tillers (deg) + dinT: the random deviation around incT + dep: the distance (cm) at which a tiller ear is far from rank at maturity + run_adel_pars: a dict of inner parameter for adel + aborting_tiller_reduction: a reduction factor for dimension, applied gobally to devT + ssipars: a set of parameter for senescence + *args, **kwargs: parameters passed to parent class: Adel + """ if devT is None: devT = adel_data.devT() devT_unit = "cm" - if devT_unit != scene_unit: - convert = self.conv_units[devT_unit] / self.conv_units[scene_unit] + self.ref_plants = list(set(devT["axeT"]["id_plt"])) + kwargs.update({'nref_plants': len(self.ref_plants)}) + + super(AdelWheat, self).__init__(*args, **kwargs) + + self.canopy_age = None + + if devT_unit != self.scene_unit: + convert = self.conv_units[devT_unit] / self.conv_units[self.scene_unit] for x in ( "L_internode", "W_internode", @@ -109,27 +114,6 @@ def __init__( self.devT = devT - self.ref_plants = list(set(self.devT["axeT"]["id_plt"])) - super(AdelWheat, self).__init__( - nref_plants=len(self.ref_plants), - nplants=nplants, - duplicate=duplicate, - nsect=nsect, - species=species, - leaves=leaves, - stand=stand, - aspect=aspect, - split=split, - face_up=face_up, - classic=classic, - scene_unit=scene_unit, - age=age, - seed=seed, - leaf_db=leaf_db, - positions=positions, - convUnit=convUnit, - ) - if run_adel_pars is None: run_adel_pars = { "senescence_leaf_shrink": 0.5, @@ -138,7 +122,7 @@ def __init__( "stemDuration": 2.0 / 1.2, "dHS_col": 0.2, "dHS_en": 0, - "epsillon": 1e-6, + "epsillon": 1e-6 * self.conv_units["m"] / self.conv_units[self.scene_unit], "HSstart_inclination_tiller": 1, "rate_inclination_tiller": 30, "drop_empty": True, @@ -148,7 +132,10 @@ def __init__( thermal_time_model = DegreeDayModel(Tbase=0) if geoAxe is None: - geoAxe = genGeoAxe(incT=incT, dinT=dinT, dep=dep) + cm_to_scene_unit = self.conv_units['cm'] / self.conv_units[self.scene_unit] + dep *= cm_to_scene_unit + depMin = 1.5 * cm_to_scene_unit + geoAxe = genGeoAxe(incT=incT, dinT=dinT, dep=dep, depMin=depMin) assert len(list(self.leaves.keys())) == 1 k = list(self.leaves.keys())[0] @@ -207,32 +194,87 @@ def check(self, attname, defaultvalue): for i in range(steps) ) + def set_adel_pars(self): + return setAdelpars(self.pars) + + + def axe_inclination(self, g): + # Axe inclinitation slightly differs from adelR one as base angle is not dynamic + stems = self.get_stem_elements(g) + pars = self.set_adel_pars() + result = [] + for (pid, axe), stem in stems.groupby(["refplant_id", "axe"]): + incT = pars[pid]['axeT'].set_index('axe')['incT'][axe] + dredT = pars[pid]['axeT'].set_index('axe')['dredT'][axe] + if incT > 0: + result.append((stem.vid.iat[0], stem.plant.iat[0], stem.axe.iat[0], stem.metamer.iat[0], stem.elt.iat[0], incT)) + if dredT > 0 and sum(stem.dl) > 1e-6: + alpha = (90 - incT) * numpy.pi / 180 + hc = stem["dl"].cumsum().to_numpy() + dc = hc * numpy.cos(alpha) + # check first stem element going outside dredT cylynder + outside = numpy.flatnonzero(dc >= dredT) + if len(outside) > 0: + # inc first outside element to end at dredt + nd = outside[0] + beta = numpy.arccos((dredT - dc[nd - 1]) / (hc[nd] - hc[nd - 1])) + inc = -(beta - alpha) / numpy.pi * 180 + result.append((stem.vid.iat[nd], stem.plant.iat[nd], stem.axe.iat[nd], stem.metamer.iat[nd], + stem.elt.iat[nd], inc)) + # inc next stem element to vertical + if nd < len(stem) - 1: + nd += 1 + inc = -(numpy.pi / 2 - beta) / numpy.pi * 180 + result.append((stem.vid.iat[nd], stem.plant.iat[nd], stem.axe.iat[nd], stem.metamer.iat[nd], + stem.elt.iat[nd], inc)) + + return pandas.DataFrame(result, columns=['vid', 'plant', 'axe', 'metamer', 'elt', 'inclination']) + + def run_adel(self, age=10, as_df=False): + if self.duplicate is None: + df = RunAdel(age, self.pars, adelpars=self.run_adel_pars) + if as_df: + return pandas.DataFrame(df) + else: + return df + else: + canopy_quot, canopy_rem = None, None + if self.nrem > 0: + canopy_quot = RunAdel(age, self.pars_quot, adelpars=self.run_adel_pars) + if self.nrem > 0: + canopy_rem = RunAdel(age, self.pars_rem, adelpars=self.run_adel_pars) + if as_df: + return pandas.DataFrame(canopy_quot), pandas.DataFrame(canopy_rem) + else: + return canopy_quot, canopy_rem + def setup_canopy(self, age=10): + + self.canopy_age = age + if "stand" not in self.meta: self.new_stand(age=age) if self.duplicate is None: - self.canopy_age = age - canopy = RunAdel(age, self.pars, adelpars=self.run_adel_pars) + canopy = self.run_adel(age) stand = list(zip(self.positions, self.plant_azimuths)) g = self.build_mtg( canopy, stand, aborting_tiller_reduction=self.aborting_tiller_reduction ) else: + cquot, crem = self.run_adel(age) + gquot, grem = None, None # produce plants positioned at origin - grem = None if self.nrem > 0: - canopy = RunAdel(age, self.pars_rem, adelpars=self.run_adel_pars) grem = self.build_mtg( - canopy, + crem, stand=None, aborting_tiller_reduction=self.aborting_tiller_reduction, ) if self.nquot > 0: - canopy = RunAdel(age, self.pars_quot, adelpars=self.run_adel_pars) gquot = self.build_mtg( - canopy, + cquot, stand=None, aborting_tiller_reduction=self.aborting_tiller_reduction, ) diff --git a/src/openalea/adel/newmtg.py b/src/openalea/adel/newmtg.py index 655c53a1..5e6feb83 100644 --- a/src/openalea/adel/newmtg.py +++ b/src/openalea/adel/newmtg.py @@ -1052,7 +1052,7 @@ def exposed_areas(g): ) for vid in g.vertices_iter(scale=g.max_scale()): n = g.node(vid) - if n.length > 0 and not n.label.startswith("Hidden"): + if 'length' in n.properties() and n.length > 0 and not n.label.startswith("Hidden"): organ = n.complex() metamer = organ.complex() axe = metamer.complex() @@ -1130,6 +1130,63 @@ def _metamer(sub): d["d_basecol"] = 0 return d +def stem_bases(g): + """returns a Dataframe with all stem base elements in g, same format as exposed_areas""" + data = {} + what = ( + "length", + "area", + "green_length", + "green_area", + "senesced_length", + "senesced_area", + ) + for vid in g.vertices_iter(scale=g.max_scale()): + n = g.node(vid) + organ = n.complex() + metamer = organ.complex() + axe = metamer.complex() + plant = axe.complex() + numphy = int("".join(list(metamer.label)[7:])) + if numphy == 1 and organ.label.startswith("internode") and n.label.startswith('Stem'): + nf = axe.nff + node_data = { + "plant": plant.label, + "axe": axe.label, + "metamer": numphy, + "organ": organ.label, + "vid": vid, + "ntop": nf - numphy + 1, + "element": n.label, + "refplant_id": plant.refplant_id, + "nff": nf, + "HS_final": axe.HS_final, + "L_shape": metamer.L_shape, + } + properties = n.properties() + node_data.update({k: properties[k] for k in what}) + if "species" in plant.properties(): + node_data.update({"species": plant.species}) + else: + node_data.update({"species": 0}) + data[vid] = node_data + df = pandas.DataFrame(data).T + # hack + df["d_basecol"] = 0 + return df + + +def stem_elements(exposed_areas, axe='MS'): + """Equivalent of Adel.R stemElements query""" + rows = [] + desc = exposed_areas[exposed_areas.axe==axe] + + for i, row in desc.iterrows(): + if row["element"] == "StemElement": + if row["length"] > 0 or (row["organ"] == "internode" and row["metamer"] == 1): + rows.append((row["vid"], row["metamer"], row["organ"], row["length"])) + return pandas.DataFrame(rows, columns=["vid", "metamer", "elt", "dl"]) + def replicate(g, target=1): """replicate the plants in g up to obtain target new plants""" diff --git a/src/openalea/adel/plantgen/plantgen_interface.py b/src/openalea/adel/plantgen/plantgen_interface.py index 918ffb79..ff45af25 100644 --- a/src/openalea/adel/plantgen/plantgen_interface.py +++ b/src/openalea/adel/plantgen/plantgen_interface.py @@ -162,6 +162,13 @@ def gen_adel_input_data( # update values defined in openalea.adel.plantgen.params from values in inner_params attribute_names = set(dir(params)) attribute_names.intersection_update(list(inner_params.keys())) + + original_params = { + key: getattr(params, key) + for key in inner_params + if hasattr(params, key) + } + params.__dict__.update( dict( [ @@ -617,6 +624,10 @@ def gen_adel_input_data( TT_t1_user=TT_t1_user, ) + # restore original params + for key, value in original_params.items(): + setattr(params, key, value) + return ( axeT_, dimT_, diff --git a/src/openalea/adel/plantgen_extensions.py b/src/openalea/adel/plantgen_extensions.py index db4d8321..603d0ab0 100644 --- a/src/openalea/adel/plantgen_extensions.py +++ b/src/openalea/adel/plantgen_extensions.py @@ -194,7 +194,7 @@ def final_leaf_number(ms_nff=12, cohort=1, inner_parameters={}): params.SECONDARY_STEM_LEAVES_NUMBER_COEFFICIENTS, ) _nff = numpy.vectorize(tools.calculate_tiller_final_leaves_number) - return numpy.where(cohort == 1, ms_nff, _nff(ms_nff, cohort, a1_a2)) + return numpy.where(cohort == 1, ms_nff, _nff(ms_nff, cohort, a1_a2)).item() # define classes for structuring/handling the different botanical models found in pgen @@ -638,7 +638,7 @@ def fit_a(self, HS_since_flag, GL): return a, rmse def hs_t1(self, nff=None): - return float(self.hsfit.HSflag(nff)) - self.n_elongated_internode + return self.hsfit.HSflag(nff) - self.n_elongated_internode def dn_nff(self, nff=None): return 0.5 * (self.hs_t2(nff) - self.hs_t2()) @@ -647,7 +647,7 @@ def n1(self, nff=None): return self.GL_bolting + self.dn_nff(nff) def hs_t2(self, nff=None): - return float(self.hsfit.HSflag(nff)) + return self.hsfit.HSflag(nff) def n2(self, nff=None): return self.GL_flag + self.dn_nff(nff) @@ -1111,14 +1111,12 @@ def _dfc(x, y): for k, v in cohort_decimal_nff.items() } cohort_nff_cardinalities = {} - for nff in nff_MS_cardinalities: - d = {} - for c in cardnff.loc[int(nff)].index: - d[int(c)] = cardinalities( - cohort_nff_modalities[int(nff)][int(c)], - int(cardnff.loc[int(nff), c].values), - ) - cohort_nff_cardinalities[int(nff)] = d + for (nff, c), n in cardnff["axe"].items(): + cohort_nff_cardinalities.setdefault(int(nff), {})[int(c)] = cardinalities( + cohort_nff_modalities[int(nff)][int(c)], + int(n), + ) + cohort_nff = { k: {kk: card2list(vv) for kk, vv in v.items()} for k, v in cohort_nff_cardinalities.items() diff --git a/test/data/test_Adel_Maxwell_plante11/Adel.R b/test/data/test_Adel_Maxwell_plante11/Adel.R deleted file mode 100644 index ec7c4bf8..00000000 --- a/test/data/test_Adel_Maxwell_plante11/Adel.R +++ /dev/null @@ -1,642 +0,0 @@ -# -# Ce fichier : Core Code modele ADEL(cinetique, ssi...) sous R -# -# Doc input et exemples sont dans docAdel.R -# -# macros Parametrisation et visu parametres sont dans setAdel.R -# -# macros pour utilisation R,alea et python sont dans UseAdel.R -# -# -# disparition gaine a faire disp - ssi dd apres sa senescence -# -# accrocher la feuille axilante lors de l'inclinaison -# -# inclinaison talle : fonction a definir (debut a f1) par Mariem et a ajouter -# -# -# Linear interpolator/extrapolator -# -openapprox <- function(x,y,xout,extrapolate=TRUE) { - xy <- cbind(x,y) - xy <- xy[order(xy[,1]),] - res <- approx(xy[,1],xy[,2],xout = xout,rule=2)$y - last <- nrow(xy) - twolast <- c(last - 1,last) - if (extrapolate) { - lastrate <- diff(xy[twolast,2]) / diff(xy[twolast,1]) - firstrate <- diff(xy[1:2,2]) / diff(xy[1:2,1]) - } else { - lastrate <- 0 - firstrate <- 0 - } - extrax <- xout > xy[last,1] - res[extrax] <- xy[last,2] + lastrate * (xout[extrax] - xy[last,1]) - extrax <- xout < xy[1,1] - res[extrax] <- xy[1,2] + firstrate * (xout[extrax] - xy[1,1]) - res -} -# -#senescence pattern for leaf n on an axe bearing nf leaves -# -# 'old' adel model based on csv ssi2sen table -rssi_patternT <- function(n,nf,ssisenT,hasEar=TRUE) { - ndelsen <- max(ssisenT$ndel) - pattern <- list(t=c(-1, 0),p=c(0,1)) - if (hasEar & n > (nf - ndelsen)) { - idel <- n - (nf - ndelsen) - t0 <- -idel - t1 <- t0 + ssisenT$dssit1[idel] - t2 <- min(t0 + ssisenT$dssit2[idel],nf - n) - if (nf < ndelsen) { - t0 <- -nf - t1 <- min(nf - n, max(t1,t0))#nf - n is complete senescence of last leaf - t2 <- min(nf - n, max(t2,t1)) - } - p1 <- ssisenT$rate[idel] * (t1 - t0) - pattern <- list(t=c(t0,t1,t2),p=c(0,p1,1)) - } - pattern -} -# new model based on r1 and ndel only -# -#ssi table -ssi_table <- function(r1=.1, ndel=3) { - table <- matrix(0,ncol=ndel,nrow=ndel) - table[1,] <- c(rep(r1,ndel-1),1-(ndel-1)*r1) - for (i in 2:ndel) { - if ((ndel-i) >= 1) - table[i,1:(ndel-i)] <- r1 - table[i,ndel-i+2] <- 1 - sum(table[1:(i-1),(ndel-i+2)]) - table[i,ndel-i+1] <- 1 - sum(table[i,]) - } - table -} -# -rssi_pattern <- function(n,nf,hasEar=TRUE,pars=list(r1=0.07,ndelsen=3)) { - pattern <- list(t=c(-1, 0),p=c(0,1)) - ndel <- min(pars$ndelsen,nf) - if (ndel > 1 & hasEar & (nf - n) < pars$ndel) { - table <- ssi_table(r1=pars$r1,ndel=ndel) - t <- ((nf - ndel):nf) - n - p <- cumsum(c(0,table[nf - n + 1,])) - pattern <- list(t=t,p=p) - } - pattern -} -# -#proportion Senesced as a function of Relative ssi and number from top -#TO DO add nf pour gerer pattern special si nf <4 & hasEar -psen <- function(rssi, n, nf, hasEar=TRUE, pars = NULL) { - if ('ssisenT' %in% names(pars)) - pat <- rssi_patternT(n, nf, pars$ssisenT,hasEar) - else if ('ssipars' %in% names(pars)) - pat <- rssi_pattern(n,nf,hasEar,pars$ssipars) - else - pat <- rssi_pattern(n,nf,hasEar) - openapprox(pat$t, pat$p, rssi, extrapolate=FALSE) -} - -# -# kinL : Model for organ extension and leaf senescence -# -# -# TO DO : voir systeme avec HS "continu", et duree croissance leaf = 2 phyllos, et fin croissance = ligulation => Tip ne sera plus utilise -# -# -# Pb 2 : comme la gaine est sur l'arrondi de fin de croissance, dans le modele elle va trop vite (prolongement de la lineaire) : how to deal with that (concernerait surtout les 3 derniers ) ? -# -# -#plant are the parameters generated by setAdel -# -kinL <- function(x,plant,pars=list("leafDuration" = 2, "fracLeaf" = 0.2, "stemDuration" = 2 / 1.2, "dHS_col"=0.2, "dHS_en"=0.)) { - #Model parameter - apparentLeafDuration <- (1 - pars$fracLeaf) * pars$leafDuration - dhslin <- apparentLeafDuration - pars$dHS_col# delay tip-hslin - startLeaf <- apparentLeafDuration - pars$leafDuration - endLeaf <- apparentLeafDuration - endLeaf1 <- apparentLeafDuration - startE <- endLeaf + pars$dHS_en - endE <- startE + pars$stemDuration - #setting output - naxe <- nrow(plant$axeT) - nf <- plant$axeT$nf - hsf <- plant$axe$HS_final - nx <- length(x) - res <- vector("list",naxe) - names(res) <- plant$axeT$axe - #compute kinetic - for (a in seq(naxe)) { - xa <- x - xend <- plant$axeT$end[a] - if (!is.na(xend)) - xa[xa>=xend] <- xend - ph <- openapprox(plant$pheno[[a]]$tip,plant$pheno[[a]]$n,xa) - hs <- ph - dhslin - phcol <- openapprox(plant$pheno[[a]]$col,plant$pheno[[a]]$n,xa) - ssi <- openapprox(plant$pheno[[a]]$ssi,plant$pheno[[a]]$n,x) - disp <- openapprox(plant$pheno[[a]]$disp,plant$pheno[[a]]$n,x) - dim <- data.frame(plant$phytoT[,,a]) - ped <- plant$pedT[[a]] - kin <- array(NA,c(nx,nf[a]+3,24),list(1:nx,1:(nf[a]+3),c("Ll","Gl","El","Lhem","Lhcol","xh","Lh","ht","Llvis","Glvis","Elvis","Llrolled","Glopen","Llsen","Glsen","Elsen","ntop", "rph", "rssi", "rhs","exposition","lifetime", "age",'is_ligulated'))) - nfa <- nf[a] - for (i in 1:(nfa+3)) - kin[,i,c("Ll","Gl","El","Llsen","Glsen","Elsen","Llvis")] <- 0 - for (i in seq(nf[a])) { - #print(i) - rph <- ph - i - rssi <- ssi - i - kin[,i,"rph"] <- rph - kin[,i,"rssi"] <- rssi - kin[,i,"rhs"] <- hs - i - xtip <- openapprox(plant$pheno[[a]]$n,plant$pheno[[a]]$tip,i) - xssi <- openapprox(plant$pheno[[a]]$n,plant$pheno[[a]]$ssi,i) - kin[,i,"lifetime"] <- max(0,min(1, (x - xtip) / (xssi - xtip))) - kin[,i,"age"] <- x - xtip - kin[,i,"is_ligulated"] <- ifelse(rph > apparentLeafDuration, 1, 0) - #longueur blade+sheath - LGl <- approx(c(startLeaf,endLeaf),c(0,dim$Ll[i]+dim$Gl[i]),xout=rph,rule=2)$y - if (i ==1) - LGl <- approx(c(startLeaf,endLeaf1),c(0,dim$Ll[i]+dim$Gl[i]),xout=rph,rule=2)$y - El <- approx(c(startE,endE),c(0,dim$El[i]),xout=rph,rule=2)$y - kin[,i,"Ll"] <- sapply(LGl,function(x) min(x,dim$Ll[i])) - kin[,i,"Gl"] <- LGl - kin[,i,"Ll"] - kin[,i,"El"] <- El - # hidden length of metamer at leaf emergence (depends only on coordination rule) - Lhem <- approx(c(startLeaf,endLeaf),c(0,dim$Ll[i]+dim$Gl[i]),xout=0,rule=2)$y + approx(c(startE,endE),c(0,dim$El[i]),xout=0,rule=2)$y - # hidden length of metamer at collar appearance (hypothesis: collar app = time at which blade is first completly visible) - xcol <- openapprox(plant$pheno[[a]]$n,plant$pheno[[a]]$col,i) - rphcol <- openapprox(plant$pheno[[a]]$tip,plant$pheno[[a]]$n,xcol) - i - LGcol <- approx(c(startLeaf,endLeaf),c(0,dim$Ll[i]+dim$Gl[i]),xout=rphcol,rule=2)$y - Ecol <- approx(c(startE,endE),c(0,dim$El[i]),xout=rphcol,rule=2)$y - Lhcol <- LGcol + Ecol - dim$Ll[i] - xh <- max(0, rph / rphcol) - Lh <- ifelse(xh <= 0, sum(kin[,i,c("Ll","Gl","El")]),Lhem + (Lhcol - Lhem) * min(xh, 1)) - # makes first phyto replace enclosing sheath after emergence - if (i == 1 & xh > 0) { - Lh <- 0 - } else if (xh > 1) { - Lhmat <- dim$Gl[i - 1] - Lh <- Lhcol + (Lhcol - Lhmat) * (xh - 1) - Lh <- ifelse(Lhmat < Lhcol, min(Lhmat, Lh), max(Lhmat, Lh)) - } - # - kin[,i,"Lhem"] <- Lhem - kin[,i,"Lhcol"] <- Lhcol - kin[,i,"xh"] <- xh - kin[,i,"Lh"] <- Lh - # Llvis is forced to be compatible with tip-col rates, Hcol/Glvis will be adjusted - kin[,i,"Llvis"] <- max(0,min(dim$Ll[i],LGl + El - Lh)) - if (dim$Ll[i] > 0) - kin[,i,"exposition"] <- kin[,i,"Llvis"] / dim$Ll[i] - #senescence - kin[,i,"Llsen"] <- psen(rssi, i, nf[a], plant$axeT$hasEar[a], plant) * kin[,i,"Ll"] - kin[,i,"Glsen"] <- psen(rssi - 2, i, nf[a], plant$axeT$hasEar[a], plant) * kin[,i,"Gl"] - - ## disparition feuille - kin[i <= disp,i,c("Ll","Llsen","Llvis","Lh")] <- 0 - kin[i <= (disp-1),i,c("Gl","Glsen")] <- 0 - } - #ear + peduncle elongation - - if (plant$axeT$hasEar[a]) { - for (i in (nfa+2):(nfa+3)) - kin[,i,"El"] <- ifelse(ph < (nfa + 1.6),0,dim$El[i]) - if (dim$El[nfa+1] > 0) - kin[,nfa+1,"El"] <- approx(c(ped$startPed,ped$endPed),c(0,dim$El[nfa+1]),xout=xa,rule=2)$y - else - kin[,nfa+1,"El"] = 0 - #senescence of stem + ear + awn + peduncle - for (i in 1:(nfa+3)) - kin[,i,"Elsen"] <- tryCatch(ifelse(xa < ped$senPed | length(dim$El[i]) <= 0,0,dim$El[i]), error = function(e) {stop(paste('plant:', plant$refp, 'axe', a, 'i', i));e}) - } - ##TO DO disparition axe = longueurs nulles pour tout ce qui est sur des entrenoeuds allonges sauf pour entrenoeuds - if (!is.na(plant$axeT$disp[a])) - #kin[x > plant$axeT$disp[a],,c("Ll","Gl","Llsen","Glsen")] <- 0 - kin[x > plant$axeT$disp[a],,c("Ll","Gl","El","Llsen","Glsen","Elsen","Llvis","Lh")] <- 0 - #rang depuis flag leaf - for (d in seq(along=x)) - kin[d,,"ntop"] <- -(seq(nrow(kin[d,,])) - nfa) - res[[a]] <- kin - } - res -} -# -#compute rolling (to be done) + visibilty -# -#hauteur du tube forme par les gaines d'un axe, a prtir des cinetiques de longeur. -#ht0 est la cinetique du tube dans lequel emerge la premiere feuille -#hauteur du tube = depuis la base de l'entreneoud, pour chaque phyto -# -htube <- function(kin,ht0) { - nmax <- max(seq(nrow(kin))[kin$ntop >=0]) - # hauteur base phyto - stem <- cumsum(kin$El) - kin$El - hcol <- stem + kin$Gl + kin$El + kin$Llrolled - kin$Glopen - #ajout ht0,=>parcours hcol de 1 a n-1 - hins <- sapply(seq(along=hcol),function(i) max(c(ht0,hcol)[1:i])) - Gt <- sapply(seq(along=hcol),function(i) min(nmax,which.max(c(ht0,hcol)[1:i]) - 1)) - ht <- pmax(0,hins - stem) - data.frame(hins=hins,ht=ht,Gt=Gt) -} -# -basetube <- function(kin,ht0=0) { - # for first phytomer, try to accomodate for ht0 if first sheath is too short - if (ht0 > kin$Gl[1] & kin$xh[1] > 0) { - delta = ht0 - kin$Gl[1] - kin$Llrolled[1] = min(delta,kin$Ll[1]) - } - # makes first phyto replace enclosing sheath after emergence - if (kin$xh[1] > 0) { - kin$ht[1] <- 0 - kin$ht <- htube(kin,0) - } - kin -} -# -checktube <- function(kin,ht0=0) { - n <- max(seq(nrow(kin))[kin$ntop >=0]) - #try to accomodate tube length to emergence constrainst using rolling/opening - if (n >=2) - for (i in 2:n) { - # for emerged collar, ht must be less than Lh - if (kin$xh[i] >= 1) - if (kin$ht[i] > kin$Lh[i]) { - delta <- kin$ht[i] - kin$Lh[i] - if (kin$Llrolled[i-1] > 0) { - dl = min(kin$Llrolled[i-1], delta) - kin$Llrolled[i-1] = kin$Llrolled[i-1] - dl - delta = delta - dl - } - if (delta > 0) { - dl = min(delta,kin$Gl[i-1]) - kin$Glopen[i-1] <- dl - } - #update tube - kin$ht <- htube(kin,0) - } - #for emegrning leaves ht must be as close to Lh as possible - if (kin$xh[i] > 0 & kin$xh[i] < 1) - if (abs(kin$ht[i] - kin$Lh[i]) > 0) { - delta <- kin$Lh[i] - kin$ht[i] - if (delta > 0) #tube is too short - kin$Llrolled[i-1] = min(delta,kin$Ll[i-1]) - else - kin$Glopen[i-1] = min(abs(delta),kin$Gl[i-1]+kin$Llrolled[i-1]) - #update tube - kin$ht <- htube(kin,0) - } - #for non-emerged leaves, Lh must be less than ht - if (kin$xh[i] <=0) - if (kin$Lh[i] > kin$ht[i]) { - delta <- kin$Lh[i] - kin$ht[i] - kin$Llrolled[i-1] = min(delta,kin$Ll[i-1]) - kin$ht <- htube(kin,0) - } - } - kin -} -# -# compute whorl adjustements needed to make Lh match ht. -# -whorl <- function(kin) { - do.call('rbind',lapply(split(kin,kin$Gt),function(mat) { - res <- NULL - if (mat$Gt[1] > 0) { - delta <- mean((mat$Lh - mat$ht)[mat$xh > 0],na.rm=TRUE) - if (!is.na(delta)) - if (abs(delta) > 1e-6) - res <- data.frame(Gt=mat$Gt[1],delta=delta) - } - res - })) -} -# -#Hmax : hauteur max axe si feuille verticale (pour calcul visibilite talles) -# -Hmax <- function(kin) { - kin <- data.frame(kin) - max(cumsum(kin$El)+kin$Gl+kin$Ll) -} -# -# ms_pos : position of axis on main stem from axis_id.returns 0 for ms itself -ms_pos <- function(axeid) { - idpos <- strsplit(axeid,split=".",fixed=TRUE)[[1]][1] - if (idpos=="MS") - pos <- 0 - else - pos <- as.numeric(strsplit(idpos,split="T")[[1]][2]) - pos -} -# -# Construct whorl, compute rolling and visibility -# -visibility <- function(kin,ht0=0) { - #initialisation of rolling/opening - kin[,c("Llrolled","Glopen")] <- 0 - kin[,c('hins','ht','Gt')] <- htube(kin,ht0) - if (all(c("xh","Lh") %in% colnames(kin))) { - w <- whorl(kin) - if (length(w) > 0) - for (i in seq(nrow(w))) { - if (w$delta[i] < 0) { - kin$Glopen[w$Gt[i]] <- min(kin$Gl[i],-w$delta[i]) - } else { - kin$Llrolled[w$Gt[i]] <- min(w$delta[i],kin$Llvis[i]) - } - } - kin[,c('hins','ht','Gt')] <- htube(kin,ht0) - } - #kin$Llvis <- pmin(pmax(0,kin$Ll + kin$Gl + kin$El - kin$ht),kin$Ll) - kin$Glvis <- pmin(pmax(0,kin$Gl - kin$Glopen + kin$El - kin$ht),kin$Gl) - kin$Elvis <- pmin(pmax(0,kin$El - kin$ht),kin$El) - kin -} -# -#model: kinlist is the output of kinL : all axes computed as ramification emerging from stem (no enclosing sheath). Length of the enclosing sheath is accomodated by rolling first blade if needed. -# -kinLvis <- function(kinlist,pars=NULL) { - res <- kinlist - axes <- names(kinlist) - for (d in seq(dim(kinlist[[1]])[1])) { - #Haxe <- sapply(kinlist,function(kinaxe) Hmax(kinaxe[d,,])) - for (a in seq(kinlist)) { - kin <- data.frame(kinlist[[a]][d,,c("ntop","Ll","Gl","El","Llvis","Lhem","Lhcol","xh","Lh","rph","rssi", "rhs")]) - # calcul visibilite : talles doivent emerger du tube de la gaine axilante - if (axes[a] == "MS") { - ht0 = kin$Lh[1] - kin <- visibility(kin,ht0) - htbm <- kin$ht - } else { - # numero de la gaine axillante sur le bm - axilrank <- ms_pos(axes[a]) - axil <- htbm[axilrank + 1]# tiller a emerges from same tube as leaf a+1 on the bearing axe - kin <- visibility(kin,axil) - } - res[[a]][d,,"ht"] <- kin$ht - res[[a]][d,,"Llrolled"] <- kin$Llrolled - res[[a]][d,,"Glopen"] <- kin$Glopen - res[[a]][d,,"Llvis"] <- kin$Llvis - res[[a]][d,,"Glvis"] <- kin$Glvis - res[[a]][d,,"Elvis"] <- kin$Elvis - } - } - res -} -# -# Converting kinetics -> Canopy desc table -# -#TO DO : include rolled blade as stem elements -#take into account Llrolled and Glopen -# -#generate desc table(s) for one plant at time t -# stem inclination is beared by visible sheaths (option 0) or by nodes (option 1) -# leaf inclination indicates whether leaf base angle is dynamic or not -# -# -#returns stack of visible elements of the stem of an axe -stemElements <- function(desc) { - metamer <- NULL - elt <- NULL - dl <- NULL - for (i in seq(nrow(desc))) { - if (desc$Ev[i] > 0) { - metamer <- c(metamer,i) - elt <- c(elt,"en") - dl <- c(dl,desc$Ev[i]) - } - if (desc$Gv[i] > 0) { - metamer <- c(metamer,i) - elt <- c(elt,"ga") - dl <- c(dl,desc$Gv[i]) - } - } - data.frame(metamer=metamer,elt=elt,dl=dl) -} -# -# Compute inclinations of stem elements -# -axe_inclination <- function(dat, HS, ht, axename, incBase, dredT, start_incT=1, incT_rate=30,epsillon=1e-6) { - nbphy <- nrow(dat)#inclus ear,ped et awn - # Calcul des inclinaisons de tiges - # 1er phyto = entrenoeud a incT - Einc <- rep(0,nbphy) - Ginc <- rep(0,nbphy) - if (axename == "MS") { - incT <- incBase - } else { - if (HS > start_incT) { - incT <- max(3,min(incBase, incT_rate * (HS - start_incT))) - } else { - incT <- 3 - } - } - Einc[1] <- incT - if (axename != "MS" && incT <= 3) { #Do not represent basal part of first metamer for non inclining tillers - dat$Lv[1] = min(dat$Ll[1],max(0, dat$Ll[1] + dat$Gl[1] + dat$El[1] - ht)) - dat$Lr[1] = min(dat$Lv[1],dat$Lr[1]) - dat$Gv[1] = min(dat$Gl[1],max(0, dat$Gl[1] + dat$El[1] - ht)) - dat$Ev[1] = min(dat$El[1],max(0, dat$El[1] - ht)) - } - # redressement (if any) - if (dredT > 0 & sum(dat$Ev+dat$Gv) > epsillon) { - #distance inserton talle -> extremite stemElements - stem <- stemElements(dat) - alpha <- (90 - incT) * pi / 180 - hc <- cumsum(stem$dl) - dc <- hc * cos(alpha) - #phytomer a redresser - if (any(dc >= dredT)) { - nd <- min(which(dc >= dredT)) - #beta : angle entre l'horizontale et l'element nd pour que son extremite tombe a dredT - if (nd > 1) { - beta <- acos( (dredT - dc[nd - 1]) / (hc[nd] - hc[nd - 1]) ) - inc <- -(beta - alpha) / pi * 180 - if (stem$elt[nd] == "en") { - Einc[stem$metamer[nd]] <- inc - } else { - Ginc[stem$metamer[nd]] <- inc - } - if (nd < nrow(stem)) { - inc <- - (pi / 2 - beta) / pi * 180 - if (stem$elt[nd+1] == "en") { - Einc[stem$metamer[nd+1]] <- inc - } else { - Ginc[stem$metamer[nd+1]] <- inc - } - } - } else {#incT too large - beta <- acos(dredT / hc[1]) - Einc[1] <- (pi / 2 - beta) / pi * 180 - if (nrow(stem) > 1) { - inc <- -Einc[1] - if (stem$elt[2] == "en") { - Einc[stem$metamer[2]] <- inc - } else { - Ginc[stem$metamer[2]] <- inc - } - } - } - } - } - dat$Einc <- Einc - dat$Ginc <- Ginc - dat -} -# -getdesc <- function(kinlist,plantlist,pars=list("senescence_leaf_shrink" = 0.5,"epsillon" = 1e-6, "dynamic_leaf_angle" = TRUE, 'HSstart_inclination_tiller' = 1, 'rate_inclination_tiller' = 30, 'drop_empty'=TRUE),t=1) { - epsillon = pars$epsillon - fshrink = pars$senescence_leaf_shrink - start_incT = pars$HSstart_inclination_tiller - incT_rate = pars$rate_inclination_tiller - drop_empty = pars$drop_empty - res <- NULL - for (p in seq(kinlist)) { - #print(p) - refp <- as.numeric(names(kinlist)[p]) - kin <- kinlist[[p]] - plant <- plantlist[[p]] - pldesc <- NULL - - for (a in seq(kin)) { - #print(paste("axe",a)) - axename <- names(kin)[a] - #numaxe <- as.numeric(axename) - dat <- data.frame(kin[[a]][t,,c("Ll","Gl","El","Llvis","Glvis","Elvis","Llsen","Glsen","Elsen","Llrolled")]) - if (sum(dat) > epsillon | a == 1) {#do not represent empty tillers (BUT main stems are needed even if empty! ) - colnames(dat) <- c("Ll","Gl","El","Lv","Gv","Ev","Lsen","Gsen","Esen","Lr") - # infos brutes de plant parameters - datp <- data.frame(plant$phytoT[,,a]) - dataxe <- plant$axeT[a,] - nbleaf <- dataxe$nf - nbphy <- nrow(dat)#inclus ear,ped et awn - datp <- datp[1:nbphy,] - # Calcul des inclinaisons de tiges - HS_axe <- kin[[a]][t,1,"rhs"] + 1 - if (axename =="MS") { - ht <- 0 - } else { - axilrank <- ms_pos(axename) - ht <- kin$MS[t,axilrank+1,"ht"] # length of the tube the axe emerge from - } - dat <- axe_inclination(dat, HS_axe, ht, axename, dataxe$incT, dataxe$dredT, start_incT, incT_rate) - - #azimuts : Attention new 21 fev 2011 : azimuts en relatif / phytomere precedent ! - Laz <- datp$Azim - Laz[1] <- dataxe$azT - - # control of blade basal inclination (to be moved in kinL?) - Linc <- ifelse(datp$Ll > 0,dat$Lv / datp$Ll,1) - # setup of Lindex (for Tino, no more needed) as a function of leaf stage - #LcType <- plant$geoLeaf$Lindex(as.numeric(axename),seq(nbphy),nbleaf - seq(nbphy),dat$Lv/datp$Ll) - #LcType <- plant$geoLeaf$Lindex(as.numeric(axename),seq(nbphy),nbleaf - seq(nbphy)) - #Epo - Epo <- c(rep(1,nbleaf),3,3,3) - Epos <- c(rep(2,nbleaf),4,4,4) - pogreen <- rep(1,nbphy) - posen <- rep(2,nbphy) - rph <- kin[[a]][t,,"rph"] - rssi <- kin[[a]][t,,"rssi"] - rhs <- kin[[a]][t,,"rhs"] - exposition <- kin[[a]][t,,"exposition"] - lifetime <- kin[[a]][t,,"lifetime"] - age <- kin[[a]][t,,"age"] - is_ligulated <- kin[[a]][t,,"is_ligulated"] - mtype <- c(rep('vegetative',nbleaf),'peduncle','ear','awn') - # - pldesc <- rbind(pldesc, - cbind(data.frame(refplant_id = rep(refp,nbphy), - axe_id = rep(axename,nbphy), - ms_insertion=rep(ms_pos(axename),nbphy), - az_insertion = rep(dataxe$azTb,nbphy), - nff = dataxe$nf, - nff_end = dataxe$nf_end, - HS_final= dataxe$HS_final, - hasEar = dataxe$hasEar, - numphy=1:nbphy, - ntop= dataxe$nf + 1 - (1:nbphy), - L_shape=datp$Ll, - Lw_shape=datp$Lw, - LsenShrink = rep(fshrink,nbphy), - LcType=datp$Lindex, - LcIndex=datp$Lseed, - Linc=Linc, - Laz=Laz, - Lpo=pogreen, - Lpos=posen, - Gd=datp$Gd, - Gpo=pogreen, - Gpos=posen, - Ed=datp$Ed, - Epo=Epo, - Epos=Epos, - rph=rph, - rssi=rssi, - rhs=rhs, - exposition=exposition, - lifetime=lifetime, - m_type=mtype, - age=age, - is_ligulated = is_ligulated -), - dat)) - } - } - if (!is.null(pldesc)) { - if (drop_empty) { - # option allows filtering non growing metamers, - ms <- pldesc[pldesc$axe_id =='MS',] - tillers <- pldesc[pldesc$axe_id !='MS',] - #keep at least two row of MS to avoid degenerated one-line dataframe in python - lmetamer <- apply(na.omit(ms[,c('Ll','El','Gl')]),1,sum) - last <- 1 - if (sum(lmetamer) > 0) - last <- max(which(lmetamer > 0)) - pldesc <- ms[1:max(2,last),] - if (nrow(tillers) > 0) { - tillers <- do.call('rbind',lapply(split(tillers,tillers$axe_id, drop=TRUE), function(axdesc) { - lmetamer <- apply(na.omit(axdesc[,c('Ll','El','Gl')]),1,sum) - last <- 1 - if (sum(lmetamer) > 0) - last <- max(which(lmetamer > 0)) - axdesc[1:last,] - })) - pldesc <- rbind(pldesc,tillers) - } - } - res <- rbind(res,cbind(plant=p,pldesc)) - } - } - res -} -# -# Checker for axe dynamics of the plants sampled at dates -# -checkAxeDyn <- function(dates,plants, density=1) { - em <- unlist(sapply(plants,function(p) p$axeT$emf1)) - end <- unlist(sapply(plants,function(p) p$axeT$end)) - disp <- unlist(sapply(plants,function(p) p$axeT$disp)) - em_p <- unlist(sapply(plants,function(p) p$axeT$emf1[p$axeT$axe=='MS'])) - disp_p <- unlist(sapply(plants,function(p) p$axeT$disp[p$axeT$axe=='MS'])) - disp[is.na(disp)] <- max(dates) + 1 - end[is.na(end)] <- max(dates) + 1 - disp_p[is.na(disp_p)] <- max(dates) + 1 - emited <- sapply(dates,function(d) length(em[em <=d])) - stoped <- sapply(dates,function(d) length(end[end <=d])) - disped <- sapply(dates,function(d) length(disp[disp <=d])) - emited_p <- sapply(dates,function(d) length(em_p[em_p<=d])) - disped_p <- sapply(dates,function(d) length(disp_p[disp_p<=d])) - nbaxes <- emited - nbaxes_growing <- emited - stoped - nbaxes_present <- emited - disped - nbpl <- emited_p - disped_p - nbpld <- length(plants) - data.frame(TT=dates, nbplants=nbpl/nbpld*density, nbaxes_emited=nbaxes/nbpld*density, nbaxes_growing=nbaxes_growing/nbpld*density, nbaxes_present=nbaxes_present/nbpld*density) -} -# -getAxeT <- function(plants) do.call('rbind', mapply(function(idpl,pl) {df=pl$axeT;df$plant=idpl;df},seq(plants),plants,SIMPLIFY=FALSE)) -# -getPhenT <- function(plants, axe='MS') do.call('rbind', mapply(function(idpl,pl) {df=pl$pheno[[axe]];df$plant=idpl;df},seq(plants),plants,SIMPLIFY=FALSE)) -# -getPhytoT <- function(plants, axe='MS') do.call('rbind', mapply(function(idpl,pl) {df=data.frame(pl$phytoT[,,axe]);df$plant=idpl;df$axe=axe;df$n=seq(nrow(df));df},seq(plants),plants,SIMPLIFY=FALSE)) - diff --git a/test/data/test_Adel_Maxwell_plante11/Maxwell_reference_simulation.csv b/test/data/test_Adel_Maxwell_plante11/Maxwell_reference_simulation.csv index cd3ee83b..aea45bbd 100644 --- a/test/data/test_Adel_Maxwell_plante11/Maxwell_reference_simulation.csv +++ b/test/data/test_Adel_Maxwell_plante11/Maxwell_reference_simulation.csv @@ -13,9 +13,9 @@ 300,1,11,"MS",0,0,11,11,11,TRUE,3,9,7.0333333347,0.452776836758985,0.5,9,91,1,179.806239211466,1,2,0.4,1,2,0,1,2,1.73079663786325,-6.83636364054876,0.33079663786325,1,0.295960585126987,"vegetative",162.264758751254,1,7.0333333347,2.85479999897252,0,7.0333333347,0.342493332127054,0,0,0,0,0.0797842702445717,0,0 300,1,11,"MS",0,0,11,11,11,TRUE,4,8,8.99999999213333,0.540027999650995,0.5,8,62,0.456747900122318,170.586528042331,1,2,0.4,1,2,0,1,2,0.73079663786325,-7.83636364054876,-0.66920336213675,0.456747900122318,0.134468080576822,"vegetative",68.5132716450059,0,7.04531536672487,0,0,4.11073109750777,0,0,0,0,0,0,0,0 300,1,11,"MS",0,0,11,11,11,TRUE,5,7,10.34999999325,0.603818699681047,0.5,7,77,0,189.82119955821,1,2,0.4,1,2,0,1,2,-0.26920336213675,-8.83636364054876,-1.66920336213675,0,0,"vegetative",-25.2382155612426,0,0.913642636258305,0,0,0,0,0,0,0,0,0,0,0 -300,1,11,"T1",1,26.6805161163211,9,9,9,TRUE,1,9,6.2000000023,0.328690000207228,0.5,9,56,0.564042985854208,75.3642668167595,1,2,0.4,1,2,0,1,2,0.986759515804753,-10.6888888802765,-0.413240484195247,0.956791372805285,0.163363609232735,"vegetative",93.9212027048186,0,5.93210651359339,0,0,3.49706651359339,0,0,0,0,0,0,3,0 +300,1,11,"T1",1,26.6805161163211,9,9,9,TRUE,1,9,6.2000000023,0.328690000207228,0.5,9,56,0.956791372805285,75.3642668167595,1,2,0.4,1,2,0,1,2,0.986759515804753,-10.6888888802765,-0.413240484195247,0.956791372805285,0.163363609232735,"vegetative",93.9212027048186,0,5.93210651359339,0,0,5.93210651359339,0,0,0,0,0,0,3,0 300,1,11,"T1",1,26.6805161163211,9,9,9,TRUE,2,8,8.5000000002,0.535918000332276,0.5,8,98,0,178.771971787792,1,2,0.4,1,2,0,1,2,-0.0132404841952471,-11.6888888802765,-1.41324048419525,0,0,"vegetative",-1.26024850036288,0,2.16293712224692,0,0,0,0,0,0,0,0,0,0,0 -300,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,1,8,8.05,0.38724965,0.5,8,93,0.143777766044973,77.0410389499739,1,2,0.4,1,2,0,1,2,0.294258998110506,-16.8666666666667,-1.10574100188949,0.455865550746273,0.053313500196282,"vegetative",28.4958443,0,3.6697176835075,0,0,1.15741101666204,0,0,0,0,0,0,3,0 +300,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,1,8,8.05,0.38724965,0.5,8,93,0.455865550746273,77.0410389499739,1,2,0.4,1,2,0,1,2,0.294258998110506,-16.8666666666667,-1.10574100188949,0.455865550746273,0.053313500196282,"vegetative",28.4958443,0,3.6697176835075,0,0,3.6697176835075,0,0,0,0,0,0,3,0 400,1,11,"MS",0,0,11,11,11,TRUE,1,11,8.7,0.381001176,0.5,11,74,1,133.964603869244,1,2,0.4,1,2,0,1,2,4.79744637492423,-3.01818182038347,3.39744637492423,1,0.730417832868111,"vegetative",449.767733163751,1,8.7,2.43504,0,8.7,2.43504,0,0,0,0,0,1.4119491497986,0 400,1,11,"MS",0,0,11,11,11,TRUE,2,10,7.6000000022,0.372438537017125,0.5,10,94,1,182.986974762753,1,2,0.4,1,2,0,1,2,3.79744637492423,-4.01818182038347,2.39744637492423,1,0.611694688097534,"vegetative",356.016245977503,1,7.6000000022,2.51230666684547,0,7.6000000022,0.0772666668454658,0,0,0,0,0,0,0 400,1,11,"MS",0,0,11,11,11,TRUE,3,9,7.0333333347,0.452776836758985,0.5,9,91,1,179.806239211466,1,2,0.4,1,2,0,1,2,2.79744637492423,-5.01818182038347,1.39744637492423,1,0.478354216008158,"vegetative",262.264758751254,1,7.0333333347,2.85479999897252,0,7.0333333347,0.342493332127054,0,0,0,0,0,0,0 @@ -25,9 +25,9 @@ 400,1,11,"T1",1,26.6805161163211,9,9,9,TRUE,1,9,6.2000000023,0.328690000207228,0.5,9,56,1,75.3642668167595,1,2,0.4,1,2,0,1,2,2.03738438813208,-8.46666666002962,0.637384388132084,1,0.337300488795664,"vegetative",193.921202704819,1,6.2000000023,2.35535000032957,0,6.2000000023,0,0,0,0,0,0,19.1215316439625,0 400,1,11,"T1",1,26.6805161163211,9,9,9,TRUE,2,8,8.5000000002,0.535918000332276,0.5,8,98,0.648365243018046,178.771971787792,1,2,0.4,1,2,0,1,2,1.03738438813208,-9.46666666002962,-0.362615611867916,0.648365243018046,0.188168994591735,"vegetative",98.7397514996371,0,8.03851469707228,0,0,5.51110456578307,0,0,0,0,0,0,0,0 400,1,11,"T1",1,26.6805161163211,9,9,9,TRUE,3,7,8.6000000048,0.702056176476847,0.5,7,34,0.0233652425923015,174.971840225626,1,2,0.4,1,2,0,1,2,0.0373843881320841,-10.4666666600296,-1.36261561186792,0.0233652425923015,0.00547803069941559,"vegetative",3.55830031445566,0,2.72282716403856,0,0,0.200941086405946,0,0,0,0,0,0,0,0 -400,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,1,8,8.05,0.38724965,0.5,8,93,0.821830513219522,77.0410389499739,1,2,0.4,1,2,0,1,2,1.3268972840017,-13.5333333333333,-0.0731027159982973,1,0.24040569383338,"vegetative",128.4958443,0,8.05,1.07804229826262,0,6.61573563141715,0,0,0,0,0,0,3,0 +400,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,1,8,8.05,0.38724965,0.5,8,93,1,77.0410389499739,1,2,0.4,1,2,0,1,2,1.3268972840017,-13.5333333333333,-0.0731027159982973,1,0.24040569383338,"vegetative",128.4958443,0,8.05,1.07804229826262,0,8.05,0,0,0,0,0,0,3,0 400,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,2,7,9.1,0.486133,0.5,7,44,0.204310802527437,172.364655418787,1,2,0.4,1,2,0,1,2,0.326897284001703,-14.5333333333333,-1.0731027159983,0.204310802527437,0.0488785542239522,"vegetative",31.65651404,0,4.4931302022491,0,0,1.85922830299967,0,0,0,0,0,0,0,0 -400,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,1,5,7.5,0.413765,0.5,5,62,0.174993387053634,73.5084096551873,1,2,0.4,1,2,0,1,2,0.429359678440885,-9.10909090909091,-0.970640321559115,0.555633386916637,0.0839418618864543,"vegetative",45.9085194,0,4.16725040187478,0,0,1.31245040290226,0,0,0,0,0,0,3,0 +400,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,1,5,7.5,0.413765,0.5,5,62,0.555633386916637,73.5084096551873,1,2,0.4,1,2,0,1,2,0.429359678440885,-9.10909090909091,-0.970640321559115,0.555633386916637,0.0839418618864543,"vegetative",45.9085194,0,4.16725040187478,0,0,4.16725040187478,0,0,0,0,0,0,3,0 500,1,11,"MS",0,0,11,11,11,TRUE,1,11,8.7,0.381001176,0.5,11,74,1,133.964603869244,1,2,0.4,1,2,0,1,2,5.86409611852902,-1.20000000021818,4.46409611852902,1,0.892816728789393,"vegetative",549.767733163751,1,8.7,2.43504,0,8.7,2.43504,0,0,0,0,0,1.4119491497986,0 500,1,11,"MS",0,0,11,11,11,TRUE,2,10,7.6000000022,0.372438537017125,0.5,10,94,1,182.986974762753,1,2,0.4,1,2,0,1,2,4.86409611852902,-2.20000000021818,3.46409611852902,1,0.783511197880121,"vegetative",456.016245977503,1,7.6000000022,2.51230666684547,0,7.6000000022,0.0772666668454658,0,0,0,0,0,0,0 500,1,11,"MS",0,0,11,11,11,TRUE,3,9,7.0333333347,0.452776836758985,0.5,9,91,1,179.806239211466,1,2,0.4,1,2,0,1,2,3.86409611852902,-3.20000000021818,2.46409611852902,1,0.66074784688933,"vegetative",362.264758751254,1,7.0333333347,2.85479999897252,0,7.0333333347,0.342493332127054,0,0,0,0,0,0,0 @@ -42,7 +42,7 @@ 500,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,1,8,8.05,0.38724965,0.5,8,93,1,77.0410389499739,1,2,0.4,1,2,0,1,2,2.35953556981589,-10.2,0.959535569815893,1,0.427497887470479,"vegetative",228.4958443,1,8.05,2.52161,0,8.05,0.00930333315453247,0,0,0,0,0.79947259397612,28.7860670944768,0 500,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,2,7,9.1,0.486133,0.5,7,44,0.849709731244614,172.364655418787,1,2,0.4,1,2,0,1,2,1.35953556981589,-11.2,-0.0404644301841068,0.849709731244614,0.203281386330453,"vegetative",131.65651404,0,9.1,1.77612044324664,0,7.73235855432598,0,0,0,0,0,0,0,0 500,1,11,"T2",2,9.64786754921079,8,8,8,TRUE,3,6,10.45,0.616371,0.5,6,47,0.224709731250955,169.299131382722,1,2,0.4,1,2,0,1,2,0.359535569815893,-12.2,-1.04046443018411,0.224709731250955,0.042160885584614,"vegetative",34.8171838,0,5.84661999060407,0,0,2.34821669157248,0,0,0,0,0,0,0,0 -500,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,1,5,7.5,0.413765,0.5,5,62,0.801568855211406,73.5084096551873,1,2,0.4,1,2,0,1,2,1.364610224982,-7.29090909090909,-0.0353897750179988,1,0.266787797637661,"vegetative",145.9085194,0,7.5,1.36656641305806,0,6.01176641408554,0,0,0,0,0,0,3,0 +500,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,1,5,7.5,0.413765,0.5,5,62,1,73.5084096551873,1,2,0.4,1,2,0,1,2,1.364610224982,-7.29090909090909,-0.0353897750179988,1,0.266787797637661,"vegetative",145.9085194,0,7.5,1.36656641305806,0,7.5,0,0,0,0,0,0,3,0 500,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,2,4,9.2,0.550396,0.5,4,26,0.227881390619584,185.925658028573,1,2,0.4,1,2,0,1,2,0.364610224982001,-8.29090909090909,-1.035389775018,0.227881390619584,0.0696184334637586,"vegetative",38.9852993,0,4.87786151468168,0,0,2.09650879370018,0,0,0,0,0,0,0,0 500,1,11,"T4",4,-26.2928237719461,2,2,NA,FALSE,1,2,7.15,0.3979345,0.5,2,58,0,76.9919484248385,1,2,0.4,1,2,0,1,2,-0.32283007955238,-2.65,-1.72283007955238,0,0,"vegetative",-28.6520017,0,0.389216525867227,0,0,0,0,0,0,0,0,0,3,0 600,1,11,"MS",0,0,11,11,11,TRUE,1,11,8.7,0.381001176,0.5,11,74,1,133.964603869244,1,2,0.4,1,2,0,1,2,6.93074586436191,0.566666668233334,5.53074586436191,1,1,"vegetative",649.767733163751,1,8.7,2.43504,0,8.7,2.43504,0,8.7,0,0,0,1.4119491497986,0 @@ -65,7 +65,7 @@ 600,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,1,5,7.5,0.413765,0.5,5,62,1,73.5084096551873,1,2,0.4,1,2,0,1,2,2.29986077177636,-5.47272727272727,0.899860771776364,1,0.449633733388868,"vegetative",245.9085194,1,7.5,2.54932,0,7.5,0,0,0,0,0,0,26.9958231532909,0 600,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,2,4,9.2,0.550396,0.5,4,26,0.812412982381025,185.925658028573,1,2,0.4,1,2,0,1,2,1.29986077177636,-6.47272727272727,-0.100139228223636,0.812412982381025,0.248194549881463,"vegetative",138.9852993,0,9.2,1.64432978797819,0,7.47419943790543,0,0,0,0,0,0,0,0 600,1,11,"T3",3,7.74684263393283,5,5,NA,FALSE,3,3,11.4,0.833454083,0.5,3,2,0.204628000152748,208.57024169527,1,2,0.4,1,2,0.0325,1,2,0.299860771776364,-7.47272727272727,-1.10013922822364,0.204628000152748,0.0472848729914221,"vegetative",32.0620793000001,0,5.87821810474616,0,0,2.33275920174133,0,0,0,0,0,0,0,0 -600,1,11,"T4",4,-26.2928237719461,2,2,NA,FALSE,1,2,7.15,0.3979345,0.5,2,58,0.365204875292125,76.9919484248385,1,2,0.4,1,2,0,1,2,0.803897759334981,-2.23333333333333,-0.596102240665019,0.849232846981076,0.117474657856298,"vegetative",71.3479983,0,6.07201485591469,0,0,2.61121485833869,0,0,0,0,0,0,3,0 +600,1,11,"T4",4,-26.2928237719461,2,2,NA,FALSE,1,2,7.15,0.3979345,0.5,2,58,0.849232846981076,76.9919484248385,1,2,0.4,1,2,0,1,2,0.803897759334981,-2.23333333333333,-0.596102240665019,0.849232846981076,0.117474657856298,"vegetative",71.3479983,0,6.07201485591469,0,0,6.07201485591469,0,0,0,0,0,0,3,0 600,1,11,"T4",4,-26.2928237719461,2,2,NA,FALSE,2,1,10.6,0.624288,0.5,1,20,0,179.735614671372,1,2,0.4,1,2,0,1,2,-0.196102240665019,-3.23333333333333,-1.59610224066502,0,0,"vegetative",-17.4045793400001,0,1.36711408656512,0,0,0,0,0,0,0,0,0,0,0 700,1,11,"MS",0,0,11,11,11,TRUE,1,11,8.7,0.381001176,0.5,11,74,1,133.964603869244,1,2,0.4,1,2,0,1,2,7.99739561019479,2.25454545772562,6.59739561019479,1,1,"vegetative",749.767733163751,1,8.7,2.43504,0,8.7,2.43504,0,8.7,2.43504,0,0,1.4119491497986,0 700,1,11,"MS",0,0,11,11,11,TRUE,2,10,7.6000000022,0.372438537017125,0.5,10,94,1,182.986974762753,1,2,0.4,1,2,0,1,2,6.99739561019479,1.25454545772562,5.59739561019479,1,1,"vegetative",656.016245977503,1,7.6000000022,2.51230666684547,0,7.6000000022,0.0772666668454658,0,7.6000000022,0.639496250459307,0,0,0,0 diff --git a/test/data/test_Adel_Maxwell_plante11/UseAdel.R b/test/data/test_Adel_Maxwell_plante11/UseAdel.R deleted file mode 100644 index 91d99b45..00000000 --- a/test/data/test_Adel_Maxwell_plante11/UseAdel.R +++ /dev/null @@ -1,221 +0,0 @@ -# -# User front End and utilities for using adel -# -# -# -#Run adel for several dates and a list of plants. Returns a list of string -# -runAdel <- function(dates,plants,pars = list('senescence_leaf_shrink' = 0.5, 'leafDuration' = 2, 'fracLeaf' = 0.2, 'stemDuration' = 2 / 1.2, 'dHS_col'=0.2, 'dHS_en'=0.,'epsillon' = 1e-6, 'HSstart_inclination_tiller' = 1, 'rate_inclination_tiller' = 30,'drop_empty'=TRUE)) { - out <- vector("list",length(dates)) - #deals with python-flatten lists - if ("axeT" %in% names(plants)) { - plants <- list(plants) - names(plants) <- plants[[1]]$refp - } - for (i in seq(out)) { - kinlist <- lapply(plants,function(plant) kinLvis(kinL(dates[i],plant,pars),pars)) - desc <- getdesc(kinlist,plants,pars) - #chn <- genString(desc,pars) - if (!is.null(desc)) - out[[i]] <- cbind(TT=dates[i],desc) - } - out -} -# -#set Adel from parameters -# -setAdeluser <- function(devT,geoLeaf,geoAxe,nplants,sample='random',seed=NULL,xy_db=NULL,sr_db=NULL, ssipars=NULL) { - setAdel(devT$axeT,devT$dimT,devT$phenT,devT$earT,devT$ssisenT,geoLeaf,geoAxe,nplants,sample,seed,xy_db,sr_db) -} -# -#build devT from csv parameter files -# -readCsv <- function(file,type=1) { - reader <- get(ifelse(type==1,"read.csv","read.csv2")) - #type 1 : "." for decimal, "," for separator - #type 2: "," for decimal, ";" for separator - data <- reader(file) - #filter empty columns - Filter(function(x)!all(is.na(x)), data) -} -# -devTcsv <- function(axeTfile,dimTfile,phenTfile,earTfile=NULL,ssisenTfile=NULL,type=1) { - - #conversion nouvelle nomencalture - #axeT - axeT <- readCsv(axeTfile) - # nouvelle convention (kirby) id_axe - if ("axe" %in% colnames(axeT)) - axeT$axe <- ifelse(axeT$axe==0,"MS",paste("T",axeT$axe,sep="")) - # - #conversions nouveaux noms - - conv <- c("plant","axe","nf","end","disp","dimIndex","phenIndex","earIndex","emf1","ligf1","senf1","dispf1") - names(conv) <- c("id_plt","id_axis","N_phytomer","TT_stop_axis","TT_del_axis","id_dim","id_phen","id_ear","TT_em_phytomer1","TT_col_phytomer1","TT_sen_phytomer1","TT_del_phytomer1") - if (all(conv %in% colnames(axeT))) - colnames(axeT)[colnames(axeT) %in% conv] <- names(conv)[na.omit(match(colnames(axeT),conv))] - else if (!all(names(conv) %in% colnames(axeT))) - stop(paste("axeT : missing data: ",paste(names(conv)[!names(conv) %in% colnames(axeT)],collapse=" "))) - # force numeric conversion - numcols <- names(conv)[-grep('id_axis',names(conv))] - for (w in numcols) - axeT[,w] <- as.numeric(as.character(axeT[,w])) - #dimT - dimT <- readCsv(dimTfile, type) - conv <- c("index","nrel","Ll","Lw","Gl","Gd","El","Ed") - names(conv) <- c("id_dim","index_rel_phytomer","L_blade","W_blade","L_sheath","W_sheath","L_internode","W_internode") - if (all(conv %in% colnames(dimT))) - colnames(dimT)[colnames(dimT) %in% conv] <- names(conv)[na.omit(match(colnames(dimT),conv))] - else if (!all(names(conv[-grep('nrel',conv)]) %in% colnames(dimT))) - stop(paste("dimT : missing data: ",paste(names(conv)[!names(conv) %in% colnames(dimT)],collapse=" "))) - # phenT - phenT = readCsv(phenTfile, type) - conv <- c("index","nrel","tip","col","ssi","disp") - names(conv) <- c("id_phen","index_rel_phytomer","dTT_em_phytomer","dTT_col_phytomer","dTT_sen_phytomer","dTT_del_phytomer") - if (all(conv %in% colnames(phenT))) - colnames(phenT)[colnames(phenT) %in% conv] <- names(conv)[na.omit(match(colnames(phenT),conv))] - else if (!all(names(conv[-grep('nrel',conv)]) %in% colnames(phenT))) - stop(paste("phenT : missing data: ",paste(names(conv)[!names(conv) %in% colnames(phenT)],collapse=" "))) - phenT <- phenT[!is.na(phenT$id_phen),] - # earT - if (!is.null(earTfile)) { - earT <- readCsv(earTfile, type) - conv <- c("index","em_ear","em_ped","end_gf","l_ped","d_ped","l_ear","Sp_ear","l_ear_awn") - names(conv) <- c("id_ear","dTT_em_ear","dTT_em_peduncle","TT_z92","L_peduncle","W_peduncle","L_ear","A_ear","L_spike") - if (all(conv %in% colnames(earT))) - colnames(earT)[colnames(earT) %in% conv] <- names(conv)[na.omit(match(colnames(earT),conv))] - else if (!all(names(conv) %in% colnames(earT))) - stop(paste("earT : missing data: ",paste(names(conv)[!names(conv) %in% colnames(earT)],collapse=" "))) - } - else - earT <- NULL - - if (!is.null(ssisenTfile)) - ssisenT <- readCsv(ssisenTfile, type) - else - ssisenT <- NULL - list(axeT = axeT, - dimT = dimT, - phenT = phenT, - earT = earT, - ssisenT = ssisenT) -} -# -# -#geoAxe from parameter -# -genGeoAxe <- function(azTM = 75,dazT = 5,incBmM = 2,dincBm = 2,incT = 60,dincT = 5,depMax = 7,depMin = 1.5,dazTb=60) { - list( - azT = function(a) { - ifelse(a == 'MS', - runif(1) * 360,#plant azimuth - azTM + (runif(1) - .5) * dazT) - }, - azTb = function(a) { - ifelse(a == 'MS', - 0, - (runif(1) - .5) * dazTb) - }, - incT = function(a) { - ifelse(a == 'MS', - incBmM + (runif(1) - .5) * dincBm, - incT + (runif(1) - .5) * dincT) - }, - dredT = function(a) { - #1.5 is an offset to avoid tiller superposed to mainstem - ifelse(a == 'MS', - 0, - depMin + runif(1) * (depMax-depMin)) - } - ) -} -# -#geoLeaf from parameter (prevoir aussi une boite freeGeomAxe et freegeoLeaf) -# -genGeoLeaf <- function(ntoplim = 4,dazTop = 60,dazBase = 30,topIndex=TRUE) { - list( - Azim = function(a,n,nf) { - ntop = nf - n - ifelse(ntop <= ntoplim, - 180 + dazTop * (runif(1) - .5), - 180 + dazBase * (runif(1) - .5)) - }, - Lindex = function(a,n,nf) { - ifelse(topIndex, - nf - n + 1, - n)} - ) - } -# -# Compute surfaces from lengths in canopy table -# -leafSurface <- function(shape_db, shape_index, scL,scW,from=0,to=1) { - shape <- shape_db[[shape_index]] - if (is.na(scL) | is.na(scW) | is.null(shape)) - res <- NA - else if (to <= from | scL == 0 | scW == 0) - res <- 0 - else { - shape[,1] <- shape[,1] / max(shape[,1]) * scL - shape[,2] <- shape[,2] / max(shape[,2]) * scW - ws <- approxfun(shape[,1],shape[,2],rule=2) - res <- integrate(ws,from * scL,to *scL)$value - } - res -} -# -canL2canS <- function(canL,sr_db,leaf_shrink=NULL) { - canS <- canL - canS$ntop <- canL$nff - canL$numphy + 1 - if (all(canS$LcIndex <= 1)) {#leaf shape has not been set by setAdel - print("canL2canS : can't compute Blade surfaces : SR data not connected to setAdel!!!") - } - else { - rg <- ifelse(is.na(canS$LcType) | canS$LcType <= 0, 1,canS$LcType)#handle phytomers above nff (peduncle, ear, awn) for which Lindex = zero - shapes <- sr_db - Lref <- canS$L_shape - Lwref <- canS$Lw_shape - Lwsen <- canS$Lw_shape * canS$LsenShrink - # add some info on visibility - canS$Lvsen <- pmin(canS$Lv,canS$Lsen) - canS$Lvgreen <- canS$Lv - canS$Lvsen - canS$Gvsen <- pmin(canS$Gv,canS$Gsen) - canS$Gvgreen <- canS$Gv - canS$Gvsen - canS$Evsen <- pmin(canS$Ev,canS$Esen) - canS$Evgreen <- canS$Ev - canS$Evsen - # - #add info on distances base of axes -> col - g <- list(canS$plant,canS$axe_id) - canS <- unsplit(lapply(split(canS,g), function(dat) {dat$d_basecol <- cumsum(dat$El) + dat$Gl;dat}),g) - # - canS$S_shape <- sapply(seq(nrow(canS)),function(x) leafSurface(shapes, rg[x], Lref[x], Lwref[x])) - # - base <- 1 - (canS$Lvsen + canS$Lvgreen) / Lref - top <- 1 - canS$Lvsen / Lref - canS$Slvgreen <- sapply(seq(nrow(canS)),function(x) leafSurface(shapes, rg[x], Lref[x], Lwref[x], base[x], top[x])) - # - base <- 1 - canS$Lvsen / Lref - canS$Slvsen <- sapply(seq(nrow(canS)),function(x) leafSurface(shapes, rg[x], Lref[x], Lwsen[x], base[x], 1)) - # - canS$Slv <- canS$Slvgreen + canS$Slvsen - # - top <- 1 - canS$Lsen / Lref - Shgreen <- sapply(seq(nrow(canS)),function(x) leafSurface(shapes, rg[x], Lref[x], Lwref[x], 0, top[x])) - # - base <- 1 - canS$Lsen / Lref - canS$Slsen <- sapply(seq(nrow(canS)),function(x) leafSurface(shapes, rg[x], Lref[x], Lwsen[x], base[x], 1)) - # - canS$SLl <- Shgreen + canS$Slsen - } - #names(res)[match(c("Ll","Lsen","Lv"),names(res))] <- c("SLl","SLsen","SLv") - # - for (w in c("Gl","Gv","Gsen","Gvsen","Gvgreen")) - canS[[paste("S",w,sep="")]] <- canS[[w]] * pi * canS$Gd - for (w in c("El","Ev","Esen","Evsen","Evgreen")) - canS[[paste("S",w,sep="")]] <- canS[[w]] * pi * canS$Ed - canS -} - - - - diff --git a/test/data/test_Adel_Maxwell_plante11/setAdel.R b/test/data/test_Adel_Maxwell_plante11/setAdel.R deleted file mode 100644 index 9374d667..00000000 --- a/test/data/test_Adel_Maxwell_plante11/setAdel.R +++ /dev/null @@ -1,288 +0,0 @@ -# -# Setting and dressing of adel plants -# -# -#Utilities foor reconstructing a plant from parameters -# -openapprox <- function(x,y,xout,extrapolate=TRUE) { - xy <- cbind(x,y) - xy <- xy[order(xy[,1]),] - res <- approx(xy[,1],xy[,2],xout = xout,rule=2)$y - last <- nrow(xy) - twolast <- c(last - 1,last) - if (extrapolate) { - lastrate <- diff(xy[twolast,2]) / diff(xy[twolast,1]) - firstrate <- diff(xy[1:2,2]) / diff(xy[1:2,1]) - } else { - lastrate <- 0 - firstrate <- 0 - } - if (!is.finite(lastrate)) # last two x identical - lastrate <- diff(xy[twolast,2]) - if (!is.finite(firstrate)) # last two x identical - firstrate <- diff(xy[1:2,2]) - extrax <- xout > xy[last,1] - res[extrax] <- xy[last,2] + lastrate * (xout[extrax] - xy[last,1]) - extrax <- xout < xy[1,1] - res[extrax] <- xy[1,2] + firstrate * (xout[extrax] - xy[1,1]) - res -} -# -#extract or replicate a desired number of plant from a canopy table -# -setCanopy <- function(canT, nplants=1, randomize = TRUE, seed = NULL) { - if (!is.null(seed)) - set.seed(seed) - out <- vector("list",nplants) - plantdb <- by(canT,list(canT$plant),function(x) x) - if (randomize) - plnb <- ceiling(runif(nplants) * length(plantdb)) - else - plnb <- rep(seq(length(plantdb)),len=nplants) - for (p in seq(out)) { - pT <- plantdb[[plnb[p]]] - pT$plant <- p - if (randomize) - pT$Laz <- (pT$Laz + 360 * runif(1)) %% 360 - out[[p]] <- pT - } - do.call("rbind",out) -} - -# -predictDim <- function(dimT,index,nf,nf_end) { - res <- NULL - if (!index %in% dimT$index) - stop(paste("setAdel : dimIndex", index, "not found in dimTable")) - else { - dim <- dimT[dimT$index == index,] - if ('index_phytomer' %in% colnames(dimT)) {# index is absolute - headers <- c('index_phytomer', 'index', 'nrel') - headers <- headers[headers %in% colnames(dim)] - out <- vector("list",ncol(dimT) - length(headers)) - names(out) <- colnames(dim)[-match(headers,colnames(dim))] - for (w in names(out)) - out[[w]] <- c(dim[seq(nf_end),w], rep(0, nf - nf_end)) - res <- data.frame(do.call("cbind",out)) - } else {#index is relative to n phytomer potentiel - nout <- seq(nf)/nf - out <- vector("list",ncol(dimT)-2) - names(out) <- colnames(dim)[-match(c('index','nrel'),colnames(dim))] - for (w in names(out)) - out[[w]] <- approx(dim$nrel,dim[,w],nout,rule=2)$y - res <- data.frame(do.call("cbind",out)) - } - } - res -} -# -predictPhen <- function(phenT,index,nf,datesf1,nf_end) { - if (!"disp"%in%colnames(phenT)) - stop("setAdel: Missing input for leaf desapearance in phenT (see docAdel.txt") - res <- NULL - if (!index %in% phenT$index) - stop(paste("setAdel : phenIndex/id_phen", index, "not found in phenTable")) - else { - phen <- phenT[phenT$index == index,] - headers <- c('index_phytomer', 'index', 'nrel') - headers <- headers[headers %in% colnames(phen)] - out <- vector("list",ncol(phen) - length(headers)) - names(out) <- colnames(phen)[-match(headers,colnames(phen))] - names(datesf1) <- c("tip","col","ssi","disp") - # - if ('index_phytomer' %in% colnames(phen)) {# index is absolute - nin <- phen$index_phytomer - nout <- c(0,seq(nf)) - if (length(na.omit(phen$index_phytomer)) < 2) - stop(paste("setAdel : not enough data in phenTable for id_phen:",index)) - } else {#index is relative to n phytomer potentielnout <- c(0,seq(nf))/nf - nin <- phen$nrel - nout <- c(0,seq(nf))/nf - if (length(na.omit(phen$nrel)) < 2) - stop(paste("setAdel : not enough data in phenTable for id_phen:",index)) - } - for (i in 1:4) { - w <- names(out)[i] - if (length(na.omit(phen[,w])) < 2) - stop(paste("setAdel : not enough data in phenTable for id_phen:",index, 'column:', w)) - out[[w]] <- openapprox(nin,phen[,w],nout,extrapolate=FALSE) + datesf1[[w]] - } - res <- data.frame(cbind(n=c(0,seq(nf)),do.call("cbind",out))) - } - res -} -# -#peduncle elongation -# -predictPed <- function(pheno,phyto,index,nf,earT) { - par <- earT[index,] - rate <- 0 - if (par$em_ped - par$em_ear > 0) - rate <- par$l_ear / (par$em_ped - par$em_ear) - start <- pheno[pheno$n==nf,"col"] + par$em_ped - phyto[nf,"Gl"] / ifelse(rate == 0,1,rate) - end <- start + par$l_ped / ifelse(rate == 0,1,rate) - data.frame(startPed=start,endPed=end,senPed=pheno[pheno$n==nf,"col"] + par$end_gf) -} - - -#setAdel performs the dressing (geometry, tiller number ...) of plants from parameters and duplicate them for a given number of outputed plants -# -#debug load defaults -#axeT=devT$axeT;dimT=devT$dimT;phenT=devT$phenT;earT=devT$earT;ssisenT=devT$ssisenT;nplants=1;sample='random';seed=NULL;xy_db=xydb;sr_db=srdb;ssipars=NULL -# -setAdel <- function(axeT,dimT,phenT,earT,ssisenT,geoLeaf,geoAxe,nplants=1,sample='random',seed=NULL,xy_db=NULL,sr_db=NULL,ssipars=NULL) { - - # Handle semantic of nf, N_phytomer and N_phytomer_potentiel, that depend on the history of adel. - # - if ("nf"%in%colnames(axeT)) {#first version of adel: N_phytomer_potentiel = nf & N_phytomer = nf - colnames(axeT)[match("nf",colnames(axeT))] <- "N_phytomer_potentiel" - axeT <- cbind(axeT,N_phytomer = axeT$N_phytomer_potentiel) - } else if (!"N_phytomer_potentiel"%in%colnames(axeT)) {# old plantgen (before may 2015) - axeT <- cbind(axeT,N_phytomer_potentiel = axeT$N_phytomer) - } - #prise en chage nouveaux noms - conv <- c("id_plt","id_axis","N_phytomer","N_phytomer_potentiel","TT_stop_axis","TT_del_axis","id_dim","id_phen","id_ear","TT_em_phytomer1","TT_col_phytomer1","TT_sen_phytomer1","TT_del_phytomer1") - names(conv) <- c("plant","axe","nf_end","nf","end","disp","dimIndex","phenIndex","earIndex","emf1","ligf1","senf1","dispf1") - colnames(axeT)[colnames(axeT) %in% conv] <- names(conv)[na.omit(match(colnames(axeT),conv))] - # - conv <- c("id_dim","index_rel_phytomer","L_blade","W_blade","L_sheath","W_sheath","L_internode","W_internode") - names(conv) <- c("index","nrel","Ll","Lw","Gl","Gd","El","Ed") - colnames(dimT)[colnames(dimT) %in% conv] <- names(conv)[na.omit(match(colnames(dimT),conv))] - # - conv <- c("id_phen","index_rel_phytomer","dTT_em_phytomer","dTT_col_phytomer","dTT_sen_phytomer","dTT_del_phytomer") - names(conv) <- c("index","nrel","tip","col","ssi","disp") - colnames(phenT)[colnames(phenT) %in% conv] <- names(conv)[na.omit(match(colnames(phenT),conv))] - # - conv <- c("id_ear","dTT_em_ear","dTT_em_peduncle","TT_z92","L_peduncle","W_peduncle","L_ear","A_ear","L_spike") - names(conv) <- c("index","em_ear","em_ped","end_gf","l_ped","d_ped","l_ear","Sp_ear","l_ear_awn") - colnames(earT)[colnames(earT) %in% conv] <- names(conv)[na.omit(match(colnames(earT),conv))] - - #verif inputs et completion default values - if (!is.null(seed)) - set.seed(seed) - - if (is.null(earT)) { - iear <- grep("earIndex",colnames(axeT),fixed=TRUE) - if (length(iear) > 0) { - earindex <- axeT[,iear] - axeT <- axeT[,-iear] - } - axeT <- cbind(axeT,earIndex = 1) - #protect no-ear axes from default ear restoration - axeT$earIndex <- ifelse(is.na(earindex),NA,axeT$earIndex) - earT <- data.frame(index = 1,em_ear = 100, em_ped = 200, end_gf = 1000, l_ped = 0, d_ped = 0, l_ear = 0, Sp_ear = 0, l_ear_awn = 0) - } - - if (is.null(ssisenT)) - if (is.null(ssipars))#otherwise, use ssipars - ssisenT <- data.frame(ndel=1:4,rate1=0.07,dssit1=c(0,1.2,2.5,3),dssit2=c(1.2,2.5,3.7,4)) - - if (!"incB"%in%colnames(dimT)) - dimT <- cbind(dimT,incB = -999,dincB = 0) - useAzim <- FALSE - if (!"pAngle"%in%colnames(dimT)) { - useAzim <- TRUE - dimT <- cbind(dimT,pAngle = -999,dpAngle = 0) - } - - if (!"HS_final"%in%colnames(axeT)) - axeT <- cbind(axeT, HS_final = ifelse(is.na(axeT$end), 1, NA) * pmin(axeT$nf_end,axeT$nf)) - - - - - plantdb <- by(axeT,list(axeT$plant),function(x) { - if (! "MS" %in% x$axe) - stop(paste("No main stem found for plant",x$plant[1],", Check axeT table")) - x}) - #sampling nplants in the database - if (sample == 'random') - plnb <- ceiling(runif(nplants) * length(unique(axeT$plant))) - else - plnb <- rep(seq(plantdb),length.out=nplants) - # - out <- vector("list",nplants) - names(out) <- names(plantdb)[plnb] - for (p in seq(out)) { - #print(p) - #axeTable from axeT and geoAxe or dimT if azim/azdev in colums - pT <- plantdb[[plnb[p]]] - axeTable <- data.frame(axe = pT$axe, - nf = pT$nf, - nf_end = pT$nf_end, - emf1 = pT$emf1, - end = pT$end, - disp = pT$disp, - azT = sapply(pT$axe,geoAxe$azT), - azTb = sapply(pT$axe,geoAxe$azTb), - incT = sapply(pT$axe,geoAxe$incT), - dredT = sapply(pT$axe,geoAxe$dredT), - hasEar = is.na(pT$end), - HS_final = pT$HS_final - ) - #phytoT and leafT from dimT and geoleaf - nomsdim <- c("Ll","Lw","Gl","Gd","El","Ed","pAngle","dpAngle","incB","dincB") - #row = phytomer number + 3 (peduncle, ear, awns) - nfM <- max(pT$nf) + 3 - if (! all(is.finite(c(nfM,nrow(pT))))) - stop("setAdel: Can't create phytoT array") - phytoT <- array(NA,dim=c(nfM,length(nomsdim)+3,nrow(pT)),dimnames=list(seq(nfM),c(nomsdim,"Azim","Lindex","Lseed"),pT$axe)) - for (a in seq(nrow(pT))) { - nf <- pT$nf[a] - nf_end <- pT$nf_end[a] - idaxe <- pT$axe[a] - pred <- predictDim(dimT,pT$dimIndex[a],nf, nf_end)[,nomsdim] - if (!is.null(pred)) - phytoT[seq(nf),nomsdim,a] <- unlist(pred) - phytoT[seq(nf),"incB",a] <- phytoT[seq(nf),"incB",a] + (runif(nf) - .5) * phytoT[seq(nf),"dincB",a] - if (useAzim) - phytoT[seq(nf),"Azim",a] <- sapply(seq(nf),function(n) geoLeaf$Azim(idaxe,n,nf)) - else - phytoT[seq(nf),"Azim",a] <- phytoT[seq(nf),"pAngle",a] + (runif(nf) - .5) * phytoT[seq(nf),"dpAngle",a] - # - lindex <- sapply(seq(nf),function(n) geoLeaf$Lindex(idaxe,n,nf)) - lseed <- runif(nf) - if (is.null(xy_db)) { - phytoT[seq(nf),"Lindex",a] <- lindex - phytoT[seq(nf),"Lseed",a] <- lseed - } - else { - lindex <- sapply(lindex,function(x) ifelse(x %in% seq(xy_db),x,seq(xy_db)[which.min(abs(x - seq(xy_db)))])) - lindex <- sapply(lindex,function(x) ifelse(x %in% seq(sr_db),x,seq(sr_db)[which.min(abs(x - seq(sr_db)))])) - # uses R-style indexing convention for lindex and lseed : they vary from 1 to length(object_list) - phytoT[seq(nf),"Lindex",a] <- lindex - phytoT[seq(nf),"Lseed",a] <- sapply(seq(lseed),function(x) {index = round(lseed[x] * length(xy_db[[lindex[x]]])); ifelse(index==0,1,index)}) - } - # - phytoT[(nf+1):(nf+3),,a] <- 0 - phytoT[(nf+1):(nf+3),c('Lindex', 'Lseed'),a] <- -999 - if (!is.na(pT$earIndex[a])) { - phytoT[(nf+1):(nf+2),"El",a] <- unlist(earT[pT$earIndex[a],c("l_ped","l_ear")]) - if (earT[pT$earIndex[a],"l_ear_awn"] > earT[pT$earIndex[a],"l_ear"]) - phytoT[nf+3,"El",a] <- unlist(earT[pT$earIndex[a],"l_ear_awn"] - earT[pT$earIndex[a],"l_ear"]) - phytoT[nf+1,"Ed",a] <- unlist(earT[pT$earIndex[a],"d_ped"]) - if (earT[pT$earIndex[a],"l_ear"] > 0) - phytoT[(nf+2):(nf+3),"Ed",a] <- unlist(earT[pT$earIndex[a],"Sp_ear"]/earT[pT$earIndex[a],"l_ear"]) - } - } - #tip, collar and ssi : table input for oppenapprox - phenoT <- vector("list",nrow(pT)) - names(phenoT) <- pT$axe - if (!"dispf1"%in%colnames(pT)) - print("Missing input for leaf desapearance in axeT (see docAdel.txt") - for (a in seq(nrow(pT))) - phenoT[[a]] <- predictPhen(phenT,pT$phenIndex[a],pT$nf[a],pT[a,c("emf1","ligf1","senf1","dispf1")], pT$nf_end[a]) - # date of start and end of peduncle elongation - pedT <- vector("list",nrow(pT)) - names(pedT) <- pT$axe - for (a in seq(nrow(pT))) - if (!is.na(pT$earIndex[a])) - pedT[[a]] <- predictPed(phenoT[[a]],phytoT[,,a],pT$earIndex[a],pT$nf[a],earT) - if (!is.null(ssisenT)) - out[[p]] <- list(refp=names(out)[p],axeT = axeTable,phytoT=phytoT,pheno=phenoT,pedT = pedT,ssisenT=ssisenT) - else - out[[p]] <- list(refp=names(out)[p],axeT = axeTable,phytoT=phytoT,pheno=phenoT,pedT = pedT,ssipars=ssipars) - } - out -} - diff --git a/test/data/test_Adel_Maxwell_plante11/testMaxwell.R b/test/data/test_Adel_Maxwell_plante11/testMaxwell.R index 4c1fd4fd..e4b1101c 100644 --- a/test/data/test_Adel_Maxwell_plante11/testMaxwell.R +++ b/test/data/test_Adel_Maxwell_plante11/testMaxwell.R @@ -8,7 +8,13 @@ #Load R files for Adel.R # AdelRfiles <- c("Adel.R","setAdel.R","UseAdel.R") -sapply(AdelRfiles,source) +Adel_source_path <- file.path( + "..", "..", "..", "src", "openalea", "adel" +) +sapply( + file.path(Adel_source_path, AdelRfiles), + source +) # #run the model with csv files # @@ -32,13 +38,11 @@ detach() # #generate a list of plant to simulate from parameters pl <- setAdel(pars$axeT, pars$dimT, pars$phenT, pars$earT, pars$ssisenT, geoLeaf, geoAxe, nplants=1, xy_db=xydb, sr_db=srdb, seed=1) -#run the model as a whole from plant list to AleaChn -canopy <- runAdel(-61,pl)[[1]] -# ref <- sapply(seq(0,2200,100),function(x) runAdel(x,pl)[[1]],simplify=FALSE) -# write.csv(do.call('rbind',ref),'Maxwell_reference_simulation.csv',row.names=FALSE) -# + +#run the model as a whole from plant list to AleaChn +canopy <- runAdel(-61,pl)[[1]]# Scanopy <- canL2canS(canopy,srdb) # chn <- genString(canopy) diff --git a/test/test_Adel_Maxwell_plante11.py b/test/test_Adel_Maxwell_plante11.py index 21cae2f9..f6d3e22c 100644 --- a/test/test_Adel_Maxwell_plante11.py +++ b/test/test_Adel_Maxwell_plante11.py @@ -3,8 +3,8 @@ from functools import reduce import numpy as np -from openalea.adel.AdelR import devCsv, setAdel, RunAdel, genGeoLeaf, genGeoAxe, \ - csvAsDict +from openalea.adel.AdelR import devCsv, csvAsDict +from openalea.adel.astk_interface import AdelWheat from .conftest import pytest_r_skip @@ -20,10 +20,8 @@ def test_organ_length(): earTpath = dir + "earT.csv" ssi2senpath = dir + "ssi2sen.csv" devT = devCsv(axeTpath, dimTpath, phenTpath, earTpath, ssi2senpath) - geoLeaf = genGeoLeaf() - geoAxe = genGeoAxe() - pars = setAdel(devT, geoLeaf, geoAxe, 1, seed=1) - cantables = [RunAdel(x, pars) for x in range(0, 2300, 100)] + adel = AdelWheat(devT=devT, seed=1) + cantables = [adel.run_adel(x) for x in range(0, 2300, 100)] expected = csvAsDict(dir + "reference_simulation.csv") for k in ( "TT", diff --git a/test/test_init_cnw_wheat.py b/test/test_init_cnw_wheat.py new file mode 100644 index 00000000..9fd8b51a --- /dev/null +++ b/test/test_init_cnw_wheat.py @@ -0,0 +1,42 @@ +from openalea.adel.Stand import AgronomicStand +from openalea.adel.adelwheat_dynamic import AdelWheatDyn +from openalea.adel.AdelR import devCsv +from openalea.adel.plantgen_extensions import TillerEmission, TillerRegression, \ + AxePop, PlantGen, HaunStage +from openalea.adel.echap_leaf import echap_leaves +from openalea.mtg.mtg import MTG +from .conftest import pytest_r_skip + + +@pytest_r_skip +def test_init_MTG_with_tillers(): + + nplants=1 + sowing_density=250. + plant_density=250. + inter_row=0.15 + nff=12 + nsect=1 + seed=1 + leaves=echap_leaves(xy_model='Soissons_byleafclass') + + stand = AgronomicStand(sowing_density=sowing_density, + plant_density=plant_density, inter_row=inter_row, + noise=0.04, density_curve_data=None) + em = TillerEmission( + primary_tiller_probabilities={'T1': 1., 'T2': 1, 'T3': 1, + 'T4': 1, 'T5': 1, 'T6': 1, 'T7': 1}) + reg = TillerRegression(ears_per_plant=3) + axp = AxePop(MS_leaves_number_probabilities={str(nff): 1}, Emission=em, Regression=reg) + plants = axp.plant_list(nplants=nplants) + hs = HaunStage(mean_nff=nff) + pgen = PlantGen(HSfit=hs) + axeT, dimT, phenT = pgen.adelT(plants) + axeT = axeT.sort_values(['id_plt', 'id_cohort', 'N_phytomer']) + devT = devCsv(axeT, dimT, phenT) + adel = AdelWheatDyn(nplants=nplants, nsect=nsect, devT=devT, stand=stand, + seed=seed, sample='sequence', leaves=leaves, scene_unit='m', devT_unit='cm') + age = hs.TT(reg.hs_debreg(nff=nff)) + g = adel.setup_canopy(age) + assert isinstance(adel, AdelWheatDyn) + assert isinstance(g, MTG)