def leaf_example_rtp(self): """ an example used in the tests below, a main leaf with laterals """ self.plant = pb.Organism( ) # store organism (not owned by Organ, or OrganRandomParameter) p0 = pb.LeafRandomParameter(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.LeafRandomParameter(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 leaf by hand (without a leaf syleaf) param0.la, param0.lb = 0, 0 # its important parent has zero length, otherwise creation times are messed up parentleaf = pb.Leaf(1, param0, True, True, 0., 0., pb.Vector3d(0, 0, -1), 0, 0, False, 0) # takes ownership of param0 parentleaf.setOrganism(self.plant) parentleaf.addNode(pb.Vector3d(0, 0, -3), 0) # there is no nullptr in Python self.parentleaf = parentleaf # store parent (not owned by child Organ) # self.leaf = pb.Leaf(self.plant, p0.subType, pb.Vector3d(0, 0, -1), 0, self.parentleaf, 0, 0) self.leaf.setOrganism(self.plant)
def test_toString(self): """ tests toString() """ self.lrp = pb.LeafRandomParameter(pb.Organism()) self.add_successors() lrp = self.lrp # rename lrp.name = "the leaf" self.assertEqual(lrp.__str__(False), "name: the leaf, organType: 4, subType: -1.", "toString: value unexpected")
def test_leaf_geometry(self): """ tests if a leaf geometry can be set""" self.plant = pb.Organism() lrp = pb.LeafRandomParameter(self.plant) lrp.la = 3.5 lrp.lb = 1. lrp.ln = 3. lrp.lmax = lrp.la + lrp.lb + lrp.ln lrp.areaMax = 10 """ radial geometry """ y = np.array([-3, -3 * 0.7, 0., 3.5 * 0.7, 3.5]) l = np.array([0., 2.2 * 0.7, 1.7, 1.8 * 0.7, 0.]) N = 105 # N is rather high for testing lrp.createLeafGeometry(y, l, N) self.assertEqual(lrp.leafMid(), 3., "unexpected leaf mid") self.assertEqual(lrp.leafLength(), 6.5, "unexpected leaf length") y_ = np.linspace(0, lrp.leafLength(), N) geom = lrp.leafGeometry x_ = np.array([ x[-1] for x in geom]) self.assertEqual(x_.shape[0], y_.shape[0], "leaf geometry has wrong size"); a = lrp.areaMax / lrp.leafLength() self.assertAlmostEqual(2 * np.sum(x_) / N * a * lrp.leafLength(), lrp.areaMax , 2, "xml: value unexpected") plt.plot(x_ * a, y_, "g-*") plt.plot(-x_ * a, y_, "g-*") plt.ylim([0, 7]) plt.xlim([-2, 2]) plt.show()
def test_leaf(self): """ leaf without lateral leafs """ ons = pb.Matrix3d(pb.Vector3d(0., 0., 1.), pb.Vector3d(0., 1., 0.), pb.Vector3d(1., 0., 0.)) plant = pb.Plant() # store organism (not owned by Organ, or OrganRandomParameter) p0 = pb.LeafRandomParameter(plant) p0.name, p0.subType, p0.la, p0.lb, p0.lmax, p0.ln, p0.r, p0.dx = "leaf", 1, 3.5, 1., 7.5, 3, 1, 0.1 phi = np.array([-90, -45, 0., 45, 90]) / 180. * np.pi l = np.array([3, 2.2, 1.7, 2, 3.5]) N = 100 # N is rather high for testing p0.createLeafRadialGeometry(phi, l, N) # y = np.array([-3, -3 * 0.7, 0., 3.5 * 0.7, 3.5]) # l = np.array([0., 2.2 * 0.7, 1.7, 1.8 * 0.7, 0.]) # N = 105 # N is rather high for testing # p0.createLeafGeometry(y, l, N) plant.setOrganRandomParameter(p0) # the organism manages the type parameters and takes ownership plant.setOrganRandomParameter(pb.SeedRandomParameter(plant)) # because we cannot pass a nullptr to pb.Leaf(...) L48 param0 = p0.realize() # set up leaf by hand (without a leaf syleaf) param0.la, param0.lb = 0, 0 # its important parent has zero length, otherwise creation times are messed up parentleaf = pb.Leaf(1, param0, True, True, 0., 0., ons, 0, False, 0) # takes ownership of param0 parentleaf.setOrganism(plant) parentleaf.addNode(pb.Vector3d(0, 0, -3), 0) # there is no nullptr in Python leaf = pb.Leaf(plant, p0.subType, ons, 0, parentleaf , 0) leaf.setOrganism(plant) leaf.simulate(7) vp.plot_leaf(leaf)
def leaf_example(self): self.plant = pb.Organism() self.lrp = pb.LeafRandomParameter(self.plant) self.lrp.la = 1.5 self.lrp.lb = 5.5 self.lrp.ln = 1.25 self.lrp.lns = 0.12 self.lrp.lmax = 7 * self.lrp.ln + self.lrp.la + self.lrp.lb self.lrp.subType = 1
def test_constructors(self): """ tests constructor and copy """ plant = pb.Organism() otp = pb.LeafRandomParameter(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 test_radial_leaf_geometry(self): """ tests if a radial leaf geometry can be set""" self.plant = pb.Organism() lrp = pb.LeafRandomParameter(self.plant) lrp.la = 3.5 lrp.lb = 1. lrp.ln = 3. lrp.lmax = lrp.la + lrp.lb + lrp.ln lrp.areaMax = 50 # """ radial geometry """ # phi = np.array([-90, -45, 0., 45, 90]) / 180. * np.pi # l = np.array([3, 2.2, 1.7, 2, 3.5]) # N = 105 # N is rather high for testing # lrp.createLeafRadialGeometry(phi, l, N) lrp.la, lrp.lb, lrp.lmax, lrp.ln, lrp.r, lrp.dx = 5, 1, 11, 5, 1, 0.5 phi = np.array([-90., -67.5, -45, -22.5, 0, 22.5, 45, 67.5, 90]) / 180. * np.pi l = np.array([5., 1, 5, 1, 5, 1, 5, 1, 5]) assert(l.shape == phi.shape) N = 500 # N is rather high for testing lrp.createLeafRadialGeometry(phi, l, N) # self.assertEqual(lrp.leafMid(), 3., "unexpected leaf mid") # self.assertEqual(lrp.leafLength(), 6.5, "unexpected leaf length") yy = np.linspace(0, lrp.leafLength(), N) geom = lrp.leafGeometry x_, y_ = [], [] for i, x in enumerate(geom): # if len(x) > 1: # print(len(x), x, [yy[i]] * len(x)) # if len(x) == 1: # print(len(x), x, [yy[i]] * len(x)) x_.extend(x) y_.extend([yy[i]] * len(x)) x_ = np.array(x_) y_ = np.array(y_) # self.assertEqual(x_.shape[0], y_.shape[0], "leaf geometry has wrong size"); a = lrp.areaMax / lrp.leafLength() # self.assertAlmostEqual(2 * np.sum(x_) / N * a * lrp.leafLength(), lrp.areaMax , 2, "xml: value unexpected") plt.plot(x_ * a, y_, "g*") plt.plot(-x_ * a, y_, "g*") plt.ylim([0, 10]) plt.xlim([-7.5, 7.5]) plt.show()
def test_xml(self): """ write the organ as xml, and rereads it """ self.leaf_example() self.add_successors() otp = self.lrp # rename otp.name = "lateral" otp.subType = 1 otp.lmax = 17; otp.writeXML("leaf.xml") otp2 = pb.LeafRandomParameter(self.plant) otp2.readXML("leaf.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.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() """ lrp = pb.LeafRandomParameter(pb.Organism()) lrp.lns = 0.123 lrp.la = 12 ot = lrp.getParameter("organType") # test defaults st = lrp.getParameter("subType") gf = lrp.getParameter("gf") ln = lrp.getParameter("ln") lns = lrp.getParameter("ln_dev") la = lrp.getParameter("la_mean") # we can always add "_mean" to avoid naming conflicts self.assertEqual(ot, 4., "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") lrp.theta = 123 # change values lrp.thetas = 456 theta = lrp.getParameter("theta") thetas = lrp.getParameter("theta_dev") self.assertEqual(theta, 123, "getParameter: value unexpected") self.assertEqual(thetas, 456, "getParameter: 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
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 stem_rp.ln = 0 plant.setOrganRandomParameter(stem_rp) leaf_rp = pb.LeafRandomParameter(plant) leaf_rp.subType = 2 leaf_rp.lmax = 10 leaf_rp.tropismS = 0. leaf_rp.theta = 20. / np.pi # Mint # leaf_rp.la, leaf_rp.lb, leaf_rp.lmax, leaf_rp.ln, leaf_rp.r, leaf_rp.dx = 3.5, 1., 7.5, 3, 1, 0.5 # phi = np.array([-90, -45, 0., 45, 90]) / 180. * np.pi # l = np.array([3, 2.2, 1.7, 2, 3.5]) # N = 30 # N is rather high for testing # leaf_rp.createLeafRadialGeometry(phi, l, N) # Pasley (non convex - TODO)