def timer_callback_(obj, ev): """ animation call back function (called every 0.1 second) """ global rootActor global c c += 1 print("hello", c) rs.simulate(1) ana = pb.SegmentAnalyser(rs) pd = vp.segs_to_polydata(ana, 1., ["radius", "subType", "creationTime"]) newRootActor, rootCBar = vp.plot_roots(pd, "creationTime", False) renWin = iren.GetRenderWindow() ren = renWin.GetRenderers().GetFirstRenderer() ren.RemoveActor(rootActor) newRootActor.RotateX(-90) ren.AddActor(newRootActor) ren.ResetCamera() rootActor = newRootActor iren.Render() if c >= max_age: c = 0 rs.initialize()
soil_index = lambda x, y, z: int(-10 * z ) # maps to p_s (hydrostatic equilibirum) rs.setSoilGrid(soil_index) path = "../../../modelparameter/rootsystem/" name = "Anagallis_femina_Leitner_2010" # Zea_mays_1_Leitner_2010 rs.setSeed(1) rs.readParameters(path + name + ".xml") rs.initialize() rs.simulate(simtime, False) p_s = np.linspace(-200, -400, 2001) # 2 meter down, resolution in mm """ set up xylem parameters """ r = XylemFluxPython(rs) r.setKr([kr]) # or use setKrTables, see XylemFlux.h r.setKx([kz]) """ numerical solution of transpiration -1 cm3/day""" rx = r.solve_neumann( simtime, -1, p_s, True) # True: matric potential given per cell (not per segment) print("solved") fluxes = r.segFluxes(simtime, rx, p_s, False, True) # cm3/day (double simTime, rx, sx, approx, cells print("Transpiration", r.collar_flux(simtime, rx, p_s), np.sum(fluxes), "cm3/day") suf = np.array(fluxes) / -1. # [1] """ Additional vtk plot """ ana = pb.SegmentAnalyser(r.rs) ana.addData("SUF", np.minimum(suf, 1.e-2)) # cut off for vizualisation vp.plot_roots(ana, "SUF", "Soil uptake fraction (cm3 day)") # "fluxes"
print("\n2. Simulate") rs.simulate(simtime, True) print("\n3. SegmentAnalyser and artificial shoot") ana = pb.SegmentAnalyser(rs) aseg = rs.getShootSegments( ) # if there are no shoot borne roots, it is only one segment for s in aseg: print("Shoot segment", s) ana.addSegment(s, 0., 0.1, True) ana.write("results/Moraes2018_{:s}days.dgf".format(str(simtime))) # r = XylemFluxPython(rs) # just for test # r.test() nodes = ana.nodes segs = ana.segments print("Number of nodes", len(nodes)) print("Number of segments", len(segs)) minx = np.min([n.x for n in nodes]) maxx = np.max([n.x for n in nodes]) miny = np.min([n.y for n in nodes]) maxy = np.max([n.y for n in nodes]) minz = np.min([n.z for n in nodes]) maxz = np.max([n.z for n in nodes]) print("Bounding box", minx, maxx, miny, maxy, minz, maxz) # Plot, using vtk print("\n4. Plot") vp.plot_roots(rs, "subType") # vp.plot_roots(ana, "subType") # DOES NOT WORK (TODO)
N = 3 # number of columns and rows dist = 40 # distance between the root systems [cm] # Initializes N*N root systems allRS = [] for i in range(0, N): for j in range(0, N): rs = pb.RootSystem() rs.readParameters(path + name + ".xml") rs.getRootSystemParameter().seedPos = pb.Vector3d( dist * i, dist * j, -3.) # cm rs.initialize(False) # verbose = False allRS.append(rs) # Simulate for rs in allRS: rs.simulate(simtime, False) # verbose = False # Export results as single vtp files (as polylines) ana = pb.SegmentAnalyser() # see example 3b for i, rs in enumerate(allRS): vtpname = "results/example_1d_" + str(i) + ".vtp" rs.write(vtpname) ana.addSegments(rs) # collect all # Write all into single file (segments) ana.write("results/example_1d_all.vtp") # Plot, using vtk vp.plot_roots(ana, "radius")
else: return self.gravi.tropismObjective(pos, old, a, b, dx, root) # set up the root system rs = pb.RootSystem() path = "../../../modelparameter/rootsystem/" name = "Zea_mays_1_Leitner_2010" rs.readParameters(path + name + ".xml") rs.initialize() # Set useer defined after initialize mytropism1 = My_Info_Tropism(rs) mytropism1.setTropismParameter(2., 0.2) mytropism2 = My_Age_Tropism( rs, 1.5, 0.5, 5) # after 5 days switch from plagio- to gravitropism rs.setTropism(mytropism2, 4) # 4 for base roots, -1 for all root types # Simulate simtime = 100 # e.g. 30 or 60 days dt = 1 N = round(simtime / dt) for _ in range(0, N): rs.simulate(dt) # Export results (as vtp) rs.write("results/example_4b.vtp") # Plot, using vtk vp.plot_roots(rs, "age", True, 'oblique')
if p.subType > 2: p.dx = 0.25 # adjust resolution p.f_sa = soilprop # Scale insertion angle p.lmax = 2 * p.lmax # make second order laterals longer # simulation rs.initialize() simtime = 60. dt = 1. for i in range(0, round(simtime / dt)): rs.simulate(dt, False) # analysis al = pb.SegmentAnalyser(rs) al.crop(left) lm_theta = np.mean(al.getParameter("theta")) ar = pb.SegmentAnalyser(rs) ar.crop(right) rm_theta = np.mean(ar.getParameter("theta")) print('\nLeft compartment mean insertion angle is {:g} degrees'.format( lm_theta)) print('\nRight compartment mean insertion angle is {:g} degrees\n'.format( rm_theta)) # write results rs.write("results/example_5c.py") # compartment geometry rs.write("results/example_5c.vtp") # root system # plot, using vtk vp.plot_roots(rs, "theta") # press 'y'
def view_vtk_plot(self, name): """ vtk plot coloring name """ if self.data.exists(): vp.plot_roots(self.data.analyser, name) else: tkinter.messagebox.showwarning("Warning", "Open RSML file first")
# try: # x[c] = rs.seg2cell[s.y - 1] # except: # x[c] = -1 y = np.zeros(x.shape[0]) for i in range(0, x.shape[0]): y[i] = i % 2 if x[i] >= 0 else i % 2 - 2 # for i in range(0, x.shape[0]): x[i] = x[i] if x[i] >= 0 else -1 ana = pb.SegmentAnalyser(r.rs) ana.addData("linear_index", x) # node data are converted to segment data ana.addData("zebra", y) pd = vp.segs_to_polydata(ana, 1., ["radius", "subType", "creationTime", "linear_index", "zebra"]) rootActor, rootCBar = vp.plot_roots(pd, "zebra", False) """ Mesh """ width_ = max_ - min_ ind_ = res_ / width_ print("min ", min_) print("max ", max_) print("width ", width_) print("cuboids", 1 / ind_) grid = vp.uniform_grid(min_, max_, res_) meshActor, meshCBar = vp.plot_mesh(grid, "", "", False) vp.render_window([meshActor, rootActor], "Test mapping", rootCBar).Start()
"""small example""" import sys sys.path.append("../../..") import plantbox as pb import vtk_plot as vp rs = pb.RootSystem() # Open plant and root parameter from a file path = "../../../modelparameter/rootsystem/" name = "Anagallis_femina_Leitner_2010" rs.readParameters(path + name + ".xml") # Initialize rs.initializeDB(1, 4) # numbers indicate basal and shoot borne root types # Simulate rs.simulate(30, True) # Export final result (as vtp) rs.write("results/example_1a.vtp") # Plot, using vtk vp.plot_roots(rs, "creationTime")
for i in range(0, x.shape[0]): x[i] = x[i] if x[i] >= 0 else -1 print("RS number of segments (mapped)", len(rs.segments), "(rs)", rs.getNumberOfSegments()) # shoot segments are mapped ana = pb.SegmentAnalyser( rs.mappedSegments() ) # rs is MappedSegments and RootSystem. So passing rs it is not unique which constructor is called. print("Number of segments", len(ana.segments), "x", len(x), "and", len(y)) ana.addData("linear_index", x) # node data are converted to segment data ana.addData("zebra", y) ana.mapPeriodic(max_[0] - min_[0], max_[1] - min_[1]) # data are also split pd = vp.segs_to_polydata( ana, 1., ["radius", "subType", "creationTime", "linear_index", "zebra"]) rootActor, rootCBar = vp.plot_roots(pd, "linear_index", False) """ Mesh """ width_ = max_ - min_ ind_ = res_ / width_ print("min ", min_) print("max ", max_) print("width ", width_) print("cuboids", 1 / ind_) grid = vp.uniform_grid(min_, max_, res_) meshActor, meshCBar = vp.plot_mesh(grid, "", "", False) # vp.render_window([meshActor, rootActor], "Test mapping", rootCBar).Start() grid = vp.uniform_grid(min_, max_, res_) actors = vp.plot_mesh_cuts(pd, "linear_index") print(actors) print(len(actors))
True) # cut and map segments """ add segment indices """ segs = rs.segments x = np.zeros(len(segs)) for i, s in enumerate(segs): try: x[i] = rs.seg2cell[i] except: # in case the segment is not within the domain x[i] = -1 """ infos on a specific cell""" ci = rs.soil_index(0, 0, -7) print("Cell at [0,0,-7] has index", ci) try: print(len(rs.cell2seg[ci]), "segments in this cell:") print(rs.cell2seg[ci]) except: print("There are no segments in this cell") """ vizualise roots """ # ana = pb.SegmentAnalyser(rs) # <---- wrong! ana = pb.SegmentAnalyser(rs.mappedSegments()) ana.addData("linear_index", x) pd = vp.segs_to_polydata(ana, 1., ["radius", "subType", "creationTime", "linear_index"]) rootActor, rootCBar = vp.plot_roots(pd, "linear_index", "segment index plot", False) """ vizualise soil """ grid = vp.uniform_grid(min_, max_, res_) # for visualization meshActor, meshCBar = vp.plot_mesh(grid, "", "", False) vp.render_window([meshActor, rootActor], "Test mapping", rootCBar, grid.GetBounds()).Start()
import plantbox as pb import vtk_plot as vp rs = pb.RootSystem() path = "../../../modelparameter/rootsystem/" name = "Anagallis_femina_Leitner_2010" rs.readParameters(path + name + ".xml") # Modify axial resolution for p in rs.getRootRandomParameter(): p.dx = 0.1 # adjust resolution # Simulate rs.initialize() rs.simulate(60) # days # Export results as segments ana = pb.SegmentAnalyser(rs) ana.write("results/example_3e.vtp") ana.mapPeriodic(15, 10) ana.write("results/example_3e_periodic.vtp") # Export geometry as Paraview Python script box = pb.SDF_PlantBox(15, 10, 35) rs.setGeometry(box) rs.write("results/example_3e_periodic.py") # Plot final (periodic) image, using vtk vp.plot_roots(ana, "creationTime", True, 'oblique')
p_s = np.linspace(-14000, -10000, 3001) p_s[0:10] = -300 # 3 meter down, resolution in mm, dry with moist top soil_index = lambda x, y, z: int(-10 * z) r.rs.setSoilGrid(soil_index) """ Numerical solution""" rx = r.solve_neumann( simtime, -0., p_s, True) # True: matric potential given per cell (not per segment) print("Transpiration", r.collar_flux(0., rx, [p_s]), "cm3/day") eswp = 0. n = len(r.rs.segments) seg2cell = r.rs.seg2cell for i in range(0, n): eswp += suf[i] * p_s[seg2cell[i]] print() print("Equivalent soil water potential", eswp) z = r.rs.nodes[1].z print("Root collar potential ", rx[1], "node z", z, "psi", p_s[soil_index(0, 0, z)]) print() """ Additional vtk plot """ ana = pb.SegmentAnalyser(r.rs) ana.addData("rx", rx) # node data are converted to segment data pd = vp.segs_to_polydata( ana, 1., ["radius", "subType", "creationTime", "length", "rx", "suf"]) vp.plot_roots(pd, "rx")
import plantbox as pb import vtk_plot as vp rs = pb.RootSystem() path = "../../../modelparameter/rootsystem/" name = "Anagallis_femina_Leitner_2010" rs.readParameters(path + name + ".xml") # Modify axial resolution for p in rs.getRootRandomParameter(): p.dx = 0.1 # adjust resolution # Simulate rs.initialize() rs.simulate(60) # days # Export results as segments ana = pb.SegmentAnalyser(rs) ana.write("results/example_3e.vtp") ana.mapPeriodic(15, 10) ana.write("results/example_3e_periodic.vtp") # Export geometry as Paraview Python script box = pb.SDF_PlantBox(15, 10, 35) rs.setGeometry(box) rs.write("results/example_3e_periodic.py") # Plot final (periodic) image, using vtk vp.plot_roots(ana, "creationTime")
simtime = 14 # [day] for task b """ root system """ rs = pb.MappedRootSystem() path = "../../../modelparameter/rootsystem/" name = "Anagallis_femina_Leitner_2010" # Zea_mays_1_Leitner_2010 rs.readParameters(path + name + ".xml") rs.initialize() rs.simulate(simtime, False) """ root problem """ r = XylemFluxPython(rs) r.setKr([kr]) r.setKx([kz]) nodes = r.get_nodes() soil_index = lambda x, y, z: 0 r.rs.setSoilGrid(soil_index) """ Numerical solution """ rx = r.solve_dirichlet(0., p0, p_s, [p_s], True) fluxes = r.segFluxes(simtime, rx, -200 * np.ones(rx.shape), False) # cm3/day print("Transpiration", r.collar_flux(simtime, rx, [p_s]), "cm3/day") """ plot results """ plt.plot(rx, nodes[:, 2], "r*") plt.xlabel("Xylem pressure (cm)") plt.ylabel("Depth (m)") plt.title("Xylem matric potential (cm)") plt.show() """ Additional vtk plot """ ana = pb.SegmentAnalyser(r.rs) ana.addData("rx", rx) ana.addData("fluxes", np.maximum(fluxes, -1.e-3)) # cut off for vizualisation vp.plot_roots(ana, "rx", "Xylem matric potential (cm)") # "fluxes"
import rsml_reader as rsml import estimate_root_params as es from xylem_flux import XylemFluxPython import vtk_plot as vp import plantbox as pb time = range(1, 3) # measurement times (not in the rsml) name = ["RSML/m1/dicot/lupin/lupin_d{:g}.rsml".format(a) for a in range(1, 10)] # time = range(1, 3) # measurement times (not in the rsml) # name = ["RSML/m1/monocot/maize/PL0{:g}_DAS0{:g}.rsml".format(1, a) for a in range(1, 8)] # time = [75] # measurement times (not in the rsml) # name = ["RSML/Maize_Kutschera.rsml"] rs = XylemFluxPython( name[0]) # parses rsml, XylemFluxPython.rs is of type MappedRootSegments ana = pb.SegmentAnalyser( rs.rs) # convert MappedRootSegments to a SegmentAnalyser # radii = ana.data["radius"] # DOES NOT WORK (why?) # for i in range(0, len(radii)): # radii[i] /= 116.93 # ana.data["radius"] = radii pd = vp.segs_to_polydata( ana, 1. / 116.93) # makes a vtkPolydata (to save as .vtp, or visualize with vtk) vp.plot_roots(pd, "radius") # plots vtkPolydata into an interactive window
distp = 6 # inter-plant distance within the rows [cm] # Initializes N*M root systems allRS = [] for i in range(0, N): for j in range(0, M): rs = pb.RootSystem() rs.readParameters(path + name + ".xml") rs.getRootSystemParameter().seedPos = pb.Vector3d( distp * i, dist * j, -3.) # cm rs.initialize(False) # verbose = False allRS.append(rs) # Simulate rs.setSeed(2) for rs in allRS: rs.simulate(simtime, False) # verbose = False # Export results as single vtp files (as polylines) ana = pb.SegmentAnalyser() # see example 3b for i, rs in enumerate(allRS): vtpname = "results/" + name + "/" + str(i) + ".vtp" rs.write(vtpname) ana.addSegments(rs) # collect all # Write all into single file (segments) ana.write("results/" + name + "/" + "soybean_all.vtp") # Plot, using vtk vp.plot_roots(ana, "radius", True, 'oblique')
""" name = "soybean_Honly-00001" # name = "dumux_c12_2cm" # to not convert m->cm for this file # name = "Glycine_max_154days" # consists of polylines, cannot written as rsml pd = vp.read_vtp(name + ".vtp") print(pd.GetBounds()) # xmin, xmax, ymin, ymax, zmin, zmax # Rename radius for plot_roots radius = pd.GetPointData().GetAbstractArray("radius [m]") radius.SetName("radius") # Convert from m to cm np_points = vt.np_points(pd) # np_points = np_points * 100 # m -> cm points = vt.vtk_points(np_points) pd.SetPoints(points) print("Number of points opened: ", np_points.shape[0]) vp.plot_roots(pd, "p xylem [cm]") # "p xylem [cm]", "subType" # write RSML - this will only work for non-periodic vtp # roots of periodic vtp will end at domain boundary (since no connection is defined in the vtp) meta = rsml_writer.Metadata() vt.write_rsml( name + ".rsml", pd, meta, 2) # 6 is the data index of root order; 2 for Glycine_max_154days print("fin")
for p in rs.getRootRandomParameter(): p.dx = 0.25 # adjust resolutionx p.tropismS = sigma[p.subType - 1] p.f_se = soilprop # 1. Scale elongation # simulation rs.initialize() simtime = 60. dt = 1. for i in range(0, round(simtime / dt)): # in a dynamic setting change soilprop here rs.simulate(dt, False) # analysis l = rs.getSummed("length") al = pb.SegmentAnalyser(rs) al.crop(left) ll = al.getSummed("length") ar = pb.SegmentAnalyser(rs) ar.crop(right) lr = ar.getSummed("length") print('\nLeft compartment total root length {:g} cm, {:g}%'.format(ll, 100 * ll / l)) print('\nRight compartment total root length {:g} cm, {:g}% \n'.format(lr, 100 * lr / l)) # write results rs.write("results/example_5a.py") # compartment geometry rs.write("results/example_5a.vtp") # root system # plot, using vtk vp.plot_roots(rs, "rootLength") # press 'y'
p.las = p.la * s p.lns = p.ln * s p.rs = p.r * s p.a_s = p.a * s rs = pb.RootSystem() # set_all_sd(rs, 0.) # Open plant and root parameter from a file path = "" name = "m1_maize" rs.readParameters(path + name + ".xml") print(rs.getRootRandomParameter(1)) # Initialize rs.initializeLB(1, 5) # change basal to tap # rs.initialize() # Simulate rs.simulate(8, True) ana = pb.SegmentAnalyser(rs) # ana.filter("subType", 1) ana.map2D() # Export final result (as vtp) ana.write("m1_maize.vtp") # Plot, using vtk vp.plot_roots(ana, "subType") # "creationTime", "subType"
def vector_3d(a): return pb.Vector3d(a[0], a[1], a[2]) """ root problem """ r = XylemFluxPython("RootSystem.rsml") # returns a MappedSegments object segs = r.rs.segments nodes = r.rs.nodes for i in range(0, len(nodes)): nodes[i] = vector_3d(np.array(nodes[i]) / 100.) r.rs.nodes = nodes """ Mixed plot """ ana = pb.SegmentAnalyser(r.rs) pd = vp.segs_to_polydata(ana, 1.e-2, ["radius", "subType", "creationTime"]) print("Root system bounds", pd.GetBounds()) rootActor, rootCBar = vp.plot_roots(pd, "creationTime", False) ug = vp.read_vtu("benchmark3d_2-00001.vtu") print("Mesh bounds", ug.GetBounds()) meshActor, meshCBar = vp.plot_mesh( ug, "water content", "", False) # "pressure head" # e.g. "S_liq" "water content" vp.render_window([rootActor, meshActor], "mixed fun", meshCBar).Start() # # Plot, using vtk # rootActor, cBar = vp.plot_roots(rs, "creationTime", False) # rootActor.RotateX(90) # to look at it from top # vp.render_window(rootActor,"top view", cBar).Start()
ana = pb.SegmentAnalyser(rs) anim = vp.AnimateRoots(ana) anim.root_name = "creationTime" anim.file = "example5b" anim.min = np.array([-10, -10, -50]) anim.max = np.array([10, 10, 0.]) anim.res = np.array([1, 1, 1]) anim.start() simtime = 60. dt = 0.1 # small, for animation for i in range(0, round(simtime / dt)): # Simulation # update soil model (e.g. soil_strength) # update scales (e.g. from water content, soil_strength) scales = np.exp(-0.4 * soil_strength) # (TODO) # copy scales into scaling funciton scale_elongation.data = scales rs.simulate(dt, False) ana = pb.SegmentAnalyser(rs) anim.rootsystem = ana anim.update() rs.write("../results/example_5b.vtp") vp.plot_roots(rs, "age")
maxS = 0.7 # maximal minS = 0.1 # minimal slope = 5 # linear gradient between min and max (cm) box = pb.SDF_PlantBox(30, 30, 2) # cm layer = pb.SDF_RotateTranslate(box, pb.Vector3d(0, 0, -16)) soil_prop = pb.SoilLookUpSDF(layer, maxS, minS, slope) # Set the soil properties before calling initialize rs.setSoil(soil_prop) # Initialize rs.initialize() # Simulate simtime = 100 # e.g. 30 or 60 days dt = 1 N = round(simtime / dt) for _ in range(0, N): # in a dynamic soil setting you would need to update the soil properties (soil_prop) rs.simulate(dt) # Export results (as vtp) rs.write("results/example_4a.vtp") # Export geometry of static soil rs.setGeometry(layer) # just for vizualisation rs.write("results/example_4a.py") # Plot, using vtk vp.plot_roots(rs, "type")
rhizoX = pb.SDF_RotateTranslate(rhizotube, 90, pb.SDF_Axis.yaxis, pb.Vector3d(96 / 2, 0, 0)) rhizotubes_ = [] y_ = (-30, -18, -6, 6, 18, 30) z_ = (-10, -20, -40, -60, -80, -120) tube = [] for i in range(0, len(y_)): v = pb.Vector3d(0, y_[i], z_[i]) tube.append(pb.SDF_RotateTranslate(rhizoX, v)) rhizotubes_.append(tube[i]) rhizotubes = pb.SDF_Union(rhizotubes_) rhizoTube = pb.SDF_Difference(box, rhizotubes) # Set geometry: rotatedRhizotron, splitBox, or rhizoTube rs.setGeometry(rotatedRhizotron) # Simulate rs.initialize() rs.simulate(90) # days # Export results (as vtp) rs.write("results/example_1c.vtp") # Export container geometry as Paraview Python script rs.write("results/example_1c.py") # Plot, using vtk vp.plot_roots(rs, "type", True, 'oblique')