def stem_example_rtp(self): """ an example used in the tests below, a main stem with laterals """ self.plant = pb.Organism( ) # store organism (not owned by Organ, or OrganRandomParameter) p0 = pb.StemRandomParameter(self.plant) p0.name, p0.subType, p0.la, p0.lb, p0.lmax, p0.ln, p0.r, p0.dx = "main", 1, 1, 10, 100, ( 89. / 19.), 1, 0.5 p0.successor = [3] p0.successorP = [1.] p1 = pb.StemRandomParameter(self.plant) p1.name, p1.subType, p1.la, p1.ln, p1.r, p1.dx = "lateral", 3, 25, 0, 2, 0.1 self.p0, self.p1 = p0, p1 # needed at later point self.plant.setOrganRandomParameter( p0) # the organism manages the type parameters and takes ownership self.plant.setOrganRandomParameter(p1) # TODO (first node is not set, if seed is used) self.plant.setOrganRandomParameter(pb.SeedRandomParameter(self.plant)) self.seed = pb.Seed( self.plant) # store parent (not owned by child Organ) # param0 = p0.realize() # set up stem by hand (without a stem system) param0.la, param0.lb = 0, 0 # its important parent has zero length, otherwise creation times are messed up parentstem = pb.Stem(1, param0, True, True, 0., 0., pb.Vector3d(0, 0, -1), 0, 0, False, 0) # takes ownership of param0 parentstem.setOrganism(self.plant) parentstem.addNode(pb.Vector3d(0, 0, -3), 0) # there is no nullptr in Python self.parentstem = parentstem # store parent (not owned by child Organ) # self.stem = pb.Stem(self.plant, p0.subType, pb.Vector3d(0, 0, -1), 0, self.parentstem, 0, 0) self.stem.setOrganism(self.plant)
def test_initialize(self): """ test initialization (! most important) """ srp = self.get_srp() seed = pb.Seed(self.plant) # print(seed) tap_rp = pb.RootRandomParameter(self.plant) tap_rp.name = "taproot" tap_rp.subType = seed.tapType # 1 basal_rp = pb.RootRandomParameter(self.plant) basal_rp.name = "basalroot" basal_rp.subType = seed.basalType # 4 shootborne_rp = pb.RootRandomParameter(self.plant) shootborne_rp.name = "shootborneroot" shootborne_rp.subType = seed.shootborneType # 5 self.plant.setOrganRandomParameter(tap_rp) self.plant.setOrganRandomParameter(basal_rp) self.plant.setOrganRandomParameter(shootborne_rp) seed.initialize(False) # A CRootBox initializations (now StemRandomParameter set) # print("CRootBox initialization (including shootborne)") organs = seed.baseOrgans() st_ = [] ot_ = [] for o in organs: st_ .append(o.getParameter("subType")) ot_ .append(o.getParameter("organType")) norc = int(((365 - srp.firstSB) / srp.delayRC) + 0.5) self.assertEqual(norc, seed.getNumberOfRootCrowns(), "wrong number of root crowns") maxB = min(srp.maxB, int(((365 - srp.firstB) / srp.delayB) + 0.5)) self.assertEqual(len(st_), norc * srp.nC + 1 + maxB, "wrong number of roots created") seed = pb.Seed(self.plant) stem_rp = pb.StemRandomParameter(self.plant) stem_rp.name = "stem" stem_rp.subType = seed.mainStemType # 1 tiller_rp = pb.StemRandomParameter(self.plant) tiller_rp.name = "tiller" tiller_rp.subType = seed.tillerType # 4 self.plant.setOrganRandomParameter(stem_rp) self.plant.setOrganRandomParameter(tiller_rp) seed.initialize(False) # A CPlantBox initializations (now StemRandomParameter set) organs = seed.baseOrgans() # print("CPlantBox initialization (no shootborne, since they emerge from the stem)") st_ = [] ot_ = [] for o in organs: # print(o) st_ .append(o.getParameter("subType")) ot_ .append(o.getParameter("organType")) st = [1.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 1.0, 4.0, 4.0, 4.0] ot = [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0] for i in range(0, len(organs)): self.assertEqual(st_[i], st[i], "no tap root produced") self.assertEqual(ot_[i], ot[i], "tap root produced wrong organ type")
def test_xml(self): """ write the organ as xml, and rereads it """ self.stem_example() self.add_successors() otp = self.srp # rename otp.name = "lateral" otp.subType = 1 otp.lmax = 42 otp.writeXML("stem.xml") otp2 = pb.StemRandomParameter(self.plant) otp2.readXML("stem.xml") self.assertEqual(otp2.name, otp.name, "xml: value unexpected") self.assertEqual(otp2.organType, otp.organType, "xml: value unexpected") self.assertEqual(otp2.subType, otp.subType, "xml: value unexpected") self.assertEqual(otp2.lmax, otp.lmax, "xml: value unexpected") # value self.assertEqual(otp2.nob(), otp.nob(), "xml: value unexpected") # value self.assertEqual(otp2.lns, otp.lns, "xml: value unexpected") # dev for i in range(0, 3): self.assertEqual(otp2.successor[i], otp.successor[i], "xml: value unexpected") for i in range(0, 3): self.assertAlmostEqual(otp2.successorP[i], otp.successorP[i], 7, "xml: value unexpected")
def test_parameter(self): """ tests getParameter() """ self.plant = pb.Organism() srp = pb.StemRandomParameter(self.plant) srp.lns = 0.123 srp.la = 12 ot = srp.getParameter("organType") # test defaults st = srp.getParameter("subType") gf = srp.getParameter("gf") ln = srp.getParameter("ln") lns = srp.getParameter("ln_dev") la = srp.getParameter( "la_mean") # we can always add "_mean" to avoid naming conflicts self.assertEqual(ot, 3., "getParameter: value unexpected") self.assertEqual(st, -1., "getParameter: value unexpected") self.assertEqual(gf, 1., "getParameter: value unexpected") self.assertEqual(ln, 1., "getParameter: value unexpected") self.assertEqual(lns, 0.123, "getParameter: value unexpected") self.assertEqual(la, 12, "getParameter: value unexpected") srp.theta = 123 # change values srp.thetas = 456 theta = srp.getParameter("theta") thetas = srp.getParameter("theta_dev") self.assertEqual(theta, 123, "getParameter: value unexpected") self.assertEqual(thetas, 456, "getParameter: value unexpected")
def test_toString(self): self.srp = pb.StemRandomParameter(pb.Organism()) srp = self.srp # rename srp.name = "the stem" self.assertEqual(srp.__str__(False), "name: the stem, organType: 3, subType: -1.", "toString: value unexpected")
def stem_example(self): self.plant = pb.Organism() self.srp = pb.StemRandomParameter(self.plant) self.srp.la = 1.5 self.srp.lb = 5.5 self.srp.ln = 1.25 self.srp.lns = 0.12 self.srp.lmax = 7 * self.srp.ln + self.srp.la + self.srp.lb
def stem_example(self): self.plant = pb.Organism() self.srp = pb.StemRandomParameter(self.plant) self.srp.la = 1.5 self.srp.lb = 5.5 self.srp.ln = 1.25 self.srp.lns = 0.12 self.srp.lmax = 7 * self.srp.ln + self.srp.la + self.srp.lb # print(self.srp.las) self.srp.successor = [4, 5, 6] self.srp.successorP = [0.4, 0.1, 0.5]
def stem_example_rtp(self, phytomereGrowth = "sequential"): """ an example used in the tests below, a main stem with laterals """ self.plant = pb.Plant() # store organism (not owned by Organ, or OrganRandomParameter) p0 = pb.StemRandomParameter(self.plant) p0.name, p0.subType, p0.la, p0.lb, p0.lmax, p0.ln, p0.r, p0.dx, p0.dxMin = "main", 1, 10., 10., 100., 1., 1.5, 1, 0.5 p0.delayLat = 1. p0.delayNG = 2. p0.successor = [5] p0.successorP = [1.] if phytomereGrowth == "sequential": p0.nodalGrowth = 0 if phytomereGrowth == "equal": p0.nodalGrowth = 1 p1 = pb.StemRandomParameter(self.plant) p1.name, p1.subType, p1.lmax, p1.r, p1.dx, p1.dxMin = "lateral", 5, 5., 2., 1, 0.5 self.p0, self.p1 = p0, p1 # needed at later point self.plant.setOrganRandomParameter(p0) # the organism manages the type parameters and takes ownership self.plant.setOrganRandomParameter(p1) srp = pb.SeedRandomParameter(self.plant) self.plant.setOrganRandomParameter(srp) # creates seed organ (otherwise throws error in plant::simulate()) # test == True => no need to give root parameter self.plant.initialize(verbose = False, test = True) param0 = p0.realize() # set up stem by hand (without a stem system) param0.la, param0.lb = 0, 0 # its important parent has zero length, otherwise creation times are messed up self.ons = pb.Matrix3d(pb.Vector3d(0., 0., 1.), pb.Vector3d(0., 1., 0.), pb.Vector3d(1., 0., 0.)) parentstem = pb.Stem(1, param0, True, True, 0., 0., self.ons, 0, False, 0) # takes ownership of param0 parentstem.setOrganism(self.plant) parentstem.addNode(pb.Vector3d(0, 0, -3), 0) # there is no nullptr in Python self.parentstem = parentstem # store parent (not owned by child Organ) self.stem = pb.Stem(self.plant, p0.subType, self.ons, 0, self.parentstem , 0) self.stem.setOrganism(self.plant)
def test_constructors(self): """ tests constructor and copy """ plant = pb.Organism() otp = pb.StemRandomParameter(plant) otp.theta = 123 otp.thetas = 456 otp.gf = 789 otp2 = otp.copy(plant) self.assertIsNot(otp, otp2, "copy: organ type parameter set is not copied") self.assertEqual(otp2.name, otp.name, "copy: value unexpected") self.assertEqual(otp2.organType, otp.organType, "copy: value unexpected") self.assertEqual(otp2.subType, otp.subType, "copy: value unexpected") self.assertEqual(otp2.a, otp.a, "copy: value unexpected") self.assertEqual(otp2.theta, otp.theta, "copy: value unexpected") self.assertEqual(otp2.thetas, otp.thetas, "copy: value unexpected") self.assertEqual(otp2.gf, otp.gf, "copy: value unexpected")
def create_basil(): plant = pb.Plant() p0 = pb.RootRandomParameter(plant) # with default values, p1 = pb.RootRandomParameter(plant) # all standard deviations are 0 s2 = pb.StemRandomParameter(plant) s3 = pb.StemRandomParameter(plant) l1 = pb.LeafRandomParameter(plant) p0.name = "taproot" p0.a = 0.2 # [cm] radius p0.subType = 1 # [-] index starts at 1 p0.lb = 5 # [cm] basal zone p0.la = 10 # [cm] apical zone p0.lmax = 30 # [cm] maximal root length, number of lateral branching nodes = round((lmax-lb-la)/ln) + 1 p0.ln = 1. # [cm] inter-lateral distance (16 branching nodes) p0.theta = 0. # [rad] p0.r = 1 # [cm/day] initial growth rate p0.dx = 10 # [cm] axial resolution p0.successor = [2] # add successors p0.successorP = [1] # probability that successor emerges p0.tropismT = pb.TropismType.gravi # p0.tropismN = 1.8 # [-] strength of tropism p0.tropismS = 0.2 # [rad/cm] maximal bending p1.name = "lateral" p1.a = 0.1 # [cm] radius p1.subType = 2 # [1] index starts at 1 p1.lmax = 15 # # [cm] apical zone p1.lmaxs = 0.15 # [cm] standard deviation of the apical zone p1.theta = 90. / 180. * np.pi # [rad] p1.r = 2 # initial growth rate p1.dx = 1 # [cm] axial resolution p1.tropismT = pb.TropismType.gravi # exo p1.tropismN = 2 # [-] strength of tropism p1.tropismS = 0.1 # [rad/cm] maximal bending s2.name = "mainstem" s2.subType = 1 s2.lmax = 25 # s2.lmaxs = 1 s2.lb = 3 s2.la = 0 s2.ln = 3 # This value is normally the Inter-lateral distance [cm], but with decussate plant, this value is # multiplied by 2 s2.lnf = 5 # This value means "successors in a decussate position" s2.RotBeta = 1 s2.BetaDev = 0 s2.InitBeta = 0 s2.gf = 1 s2.successor = [2] s2.successorP = [1] s2.tropismT = 4 # s2.theta = 1/6 s2.theta = 0 s2.tropismN = 18 s2.tropismS = 0.01 s3.name = "invisible" # The invisible stem representing the bud of the leaf s3.subType = 2 s3.la = 0 s3.ln = 0 s3.lmax = 5 s3.RotBeta = 1 s3.BetaDev = 0 s3.InitBeta = 0.5 s3.tropismS = 0 s3.lnf = 5 l1.name = 'basil' l1.subType = 2 l1.lb = 2 l1.la = 0.2 l1.lmax = 5 l1.r = 0.5 l1.RotBeta = 0.5 l1.BetaDev = 0 l1.InitBeta = 0.5 l1.tropismT = 1 l1.tropismN = 5 l1.tropismS = 0.1 l1.theta = 0.35 l1.thetas = 0.05 l1.gf = 1 l1.lnf = 5 # If not precised, it will not be possible to do the opposite decussate arrangement plant.setOrganRandomParameter(p0) plant.setOrganRandomParameter(p1) plant.setOrganRandomParameter(s2) plant.setOrganRandomParameter(s3) plant.setOrganRandomParameter(l1) srp = pb.SeedRandomParameter(plant) # with default values # srp.seedPos = pb.Vector3d(10, 10, -3.) # [cm] seed position srp.seedPos = pb.Vector3d(0, 0, -3.) # [cm] seed position srp.maxB = 0 # [-] number of basal roots (neglecting basal roots and shoot borne) srp.firstB = 10. # [day] first emergence of a basal root srp.delayB = 3. # [day] delay between the emergence of basal roots plant.setOrganRandomParameter(srp) return plant
def create_arabidopsis(): plant = pb.Plant() p0 = pb.RootRandomParameter(plant) # with default values, p1 = pb.RootRandomParameter(plant) # all standard deviations are 0 s1 = pb.StemRandomParameter(plant) s2 = pb.StemRandomParameter(plant) s3 = pb.StemRandomParameter(plant) s4 = pb.StemRandomParameter(plant) l1 = pb.LeafRandomParameter(plant) p0.name = "taproot" p0.a = 0.2 # [cm] radius p0.subType = 1 # [-] index starts at 1 p0.lb = 5 # [cm] basal zone p0.la = 10 # [cm] apical zone p0.lmax = 30 # [cm] maximal root length, number of lateral branching nodes = round((lmax-lb-la)/ln) + 1 p0.ln = 1. # [cm] inter-lateral distance (16 branching nodes) p0.theta = 0. # [rad] p0.r = 1 # [cm/day] initial growth rate p0.dx = 10 # [cm] axial resolution p0.successor = [2] # add successors p0.successorP = [1] # probability that successor emerges p0.tropismT = pb.TropismType.gravi # p0.tropismN = 1.8 # [-] strength of tropism p0.tropismS = 0.2 # [rad/cm] maximal bending p1.name = "lateral" p1.a = 0.1 # [cm] radius p1.subType = 2 # [1] index starts at 1 p1.lmax = 15 # # [cm] apical zone p1.lmaxs = 0.15 # [cm] standard deviation of the apical zone p1.theta = 90. / 180. * np.pi # [rad] p1.r = 2 # initial growth rate p1.dx = 1 # [cm] axial resolution p1.tropismT = pb.TropismType.gravi # exo p1.tropismN = 2 # [-] strength of tropism p1.tropismS = 0.1 # [rad/cm] maximal bending s1.name = "mainstem" s1.subType = 1 s1.lmax = 25 s1.lmaxs = 1 s1.lb = 0 s1.lbs = 0.1 s1.la = 3 s1.las = 0.1 s1.ln = 3 s1.lns = 0.2 s1.lnf = 0 # 1 peut être cool s1.RotBeta = 0 s1.BetaDev = 0 s1.InitBeta = 0 s1.gf = 1 s1.successor = [3, 2] s1.successorP = [0.3, 0.7] # s1.successor = [3] # s1.successorP = [1] s1.tropismT = 1 s1.theta = 0. s1.thetas = 0.05 s1.tropismN = 2 s1.tropismS = 0.005 s1.r = 1 s1.rs = 0.05 s2.name = "secondary_stem" s2.subType = 3 s2.lmax = 7 s2.lmaxs = 0.2 s2.lb = 0 s2.la = 2 s2.ln = 2 s2.lns = 0.1 s2.lnf = 0 s2.RotBeta = 2 / 3 s2.BetaDev = 0.1 s2.InitBeta = 0 s2.gf = 1 s2.successor = [2] s2.successorP = [1] s2.tropismT = 4 s2.theta = 0.3 s2.thetas = 0.02 s2.tropismN = 18 s2.tropismS = 0.01 s2.r = 0.5 s2.rs = 0.02 s3.name = "invisible stem" s3.subType = 2 s3.lmax = 5 s3.la = 0 s3.ln = 0 s3.RotBeta = 2/3 s3.BetaDev = 0 s3.InitBeta = 0. s3.lb = 0 s3.la = 0 s3.ln = 0 s3.lnf = 0 s3.RotBeta = 2 / 3 s3.BetaDev = 0 s3.InitBeta = 0 s3.gf = 1 s3.tropismT = 1 s3.theta = 0.3 s3.tropismN = 18 s3.tropismS = 0.01 s3.r = 1 l1.name = 'leaf_under_second_stem' l1.subType = 2 l1.lb = 2 l1.la = 0.2 l1.lmax = 5 l1.lmaxs = 0.1 l1.r = 0.5 l1.rs = 0.02 l1.RotBeta = 0.5 l1.BetaDev = 0 l1.InitBeta = 0. l1.tropismT = 1 l1.tropismN = 5 l1.tropismS = 0.15 l1.theta = 0.35 l1.gf = 1 s4.name = "rosette" # Cannot be a leaf organ because we can only create 1 leaf organ subType s4.subType = 4 s4.lmax = 10 s4.lmaxs = 0.2 s4.lb = 1 s4.la = 0 s4.ln = 2 s4.lnf = 0 s4.RotBeta = 3 / 5 s4.BetaDev = 0.02 s4.InitBeta = 0 s4.gf = 1 s4.tropismT = 1 s4.theta = 0.3 s4.thetas = 0.02 s4.tropismN = 18 s4.tropismS = 0.01 s4.r = 0.5 s4.rs = 0.02 plant.setOrganRandomParameter(p0) plant.setOrganRandomParameter(p1) plant.setOrganRandomParameter(s1) plant.setOrganRandomParameter(s2) plant.setOrganRandomParameter(s3) plant.setOrganRandomParameter(s4) plant.setOrganRandomParameter(l1) srp = pb.SeedRandomParameter(plant) # with default values srp.seedPos = pb.Vector3d(0., 0., -3.) # [cm] seed position srp.maxB = 0 # [-] number of basal roots (neglecting basal roots and shoot borne) srp.firstB = 10. # [day] first emergence of a basal root srp.delayB = 3. # [day] delay between the emergence of basal roots srp.maxTil = 10 plant.setOrganRandomParameter(srp) return plant
import vtk_plot as vp plant = pb.Plant() seed_rp = pb.SeedRandomParameter(plant) seed_rp.subType = 0 plant.setOrganRandomParameter(seed_rp) root_rp = pb.RootRandomParameter(plant) root_rp.subType = 1 root_rp.lmax = 1 root_rp.r = 0.1 root_rp.theta = 0 plant.setOrganRandomParameter(root_rp) stem_rp = pb.StemRandomParameter(plant) stem_rp.subType = 1 stem_rp.la = 1. stem_rp.lb = 5 stem_rp.lmax = 7.5 stem_rp.ln = 1 stem_rp.theta = 0 stem_rp.successor = [2] stem_rp.successorP = [1] plant.setOrganRandomParameter(stem_rp) stem_rp = pb.StemRandomParameter(plant) stem_rp.subType = 2 # dummy stem_rp.la = 0 stem_rp.lb = 0 stem_rp.lmax = 0