def convert_to_xylem_flux_(self): """ converts the polylines to a SegmentAnalyser and a MappedSegments object, and stores max_ct uses: properties["parent-poly"], properties["parent-nodes"] radii, cts, types """ nodes, segs = rsml_reader.get_segments(self.polylines, self.properties) # fetch nodes and segments segRadii = np.zeros((segs.shape[0], 1)) # convert to paramter per segment segCTs = np.zeros((segs.shape[0], 1)) subTypes = np.zeros((segs.shape[0], 1)) for i, s in enumerate(segs): segRadii[i] = self.radii[s[1]] # seg to node index segCTs[i] = self.cts[s[1]] subTypes[i] = self.types[s[1]] if np.isnan(subTypes[0]): subTypes = np.ones((len(segs),), dtype=np.int64) segs_ = [pb.Vector2i(s[0], s[1]) for s in segs] # convert to CPlantBox types nodes_ = [pb.Vector3d(n[0], n[1], n[2]) for n in nodes] self.analyser = pb.SegmentAnalyser(nodes_, segs_, segCTs, segRadii) self.analyser.addData("subType", subTypes) ms = pb.MappedSegments(self.analyser.nodes, np.array(self.cts), segs_, np.array(segRadii), np.array(subTypes)) self.xylem_flux = xylem_flux.XylemFluxPython(ms) self.base_nodes = self.get_base_node_indices_() self.xylem_flux.neumann_ind = self.base_nodes # needed for suf self.xylem_flux.dirichlet_ind = self.base_nodes # needed for krs self.base_segs = self.xylem_flux.find_base_segments()
def plot_depth_profile(analyser, ax, j: int): """ analyser pb.SegmentAnalyser class ax matplotlib axis j type of plot (0: "length", 1: "surface", 2: "volume") """ type_str = ["length", "surface", "volume"] unit_str = ["(cm)", "(cm$^2$)", "(cm$^3$)"] ax.clear() n = int(np.ceil(-analyser.getMinBounds().z)) z_ = np.linspace(-0.5, -n + 0.5, n) d = analyser.distribution(type_str[j], 0., float(-n), int(n), True) ax.plot(d, z_, "-*", label="total") max_type = int(np.max(analyser.data["subType"])) for i in range(0, max_type + 1): ana = pb.SegmentAnalyser(analyser) # copy ana.filter("subType", i) segn = len(ana.segments) if segn > 0: d = ana.distribution(type_str[j], 0., float(-n), int(n), True) ax.plot(d, z_, "-*", label="type {:g}".format(i)) ax.set_ylabel("Depth (cm)") ax.set_xlabel("Root system " + type_str[j] + " per 1 cm layer " + unit_str[j]) ax.legend()
def test_CPlantBox_analysis(self): """tests the functions needed by CPlantBox_analysis defined in CPlantBox_PiafMunch.py""" p = pb.Plant() p.openXML(path + "Heliantus_Pagès_2013.xml") p.initialize() p.simulate(76) ana = pb.SegmentAnalyser(p) ana.write("morningglory_ama.vtp")
def get_result(allRS: list, time: float): """ Retrieves a the state of the root systems at a certain time in a single SegmentAnalyser object @param allRS list of root systems @param time of the simulation result (days) @return SegmentAnalyser object conaining the segments of all root sytstems at the specific time """ a = pb.SegmentAnalyser() for rs in allRS: a_ = pb.SegmentAnalyser(rs) a_.filter("creationTime", 0., time) a_.pack() a.addSegments(a_) return a
def CPlantBox_analysis(name, time, output = "output"): #define a function, in line 20, we can run it in one line of code plant = pb.Plant() plant.openXML("../../modelparameter/plant/" + name) plant.initialize(True) plant.simulate(time) #plant.write("../../results/{}.vtp".format(output),15) ana = pb.SegmentAnalyser(plant) ana.write("{}.vtp".format(str(output))) ana.write("{}.txt".format(str(output))) return plant;
def plot_roots_and_soil(rs, pname: str, rp, s, periodic: bool, min_b, max_b, cell_number, filename: str, sol_ind=0): """ Plots soil slices and roots, additionally saves both grids as files @param rs some Organism (e.g. RootSystem, MappedRootSystem, ...) or MappedSegments @param pname root and soil parameter that will be visualized ("pressure head", or "water content") @param s @param rp root parameter segment data (will be added) @param periodic if yes the root system will be mapped into the domain @param min_b minimum of domain boundaries @param max_b maximum of domain boundaries @param cell_number domain resolution @param filename file name (without extension) """ ana = pb.SegmentAnalyser(rs) ana.addData(pname, rp) if periodic: w = np.array(max_b) - np.array(min_b) ana.mapPeriodic(w[0], w[1]) pd = segs_to_polydata(ana, 1., ["radius", "subType", "creationTime", pname]) pname_mesh = pname soil_grid = uniform_grid(np.array(min_b), np.array(max_b), np.array(cell_number)) soil_water_content = vtk_data(np.array(s.getWaterContent())) soil_water_content.SetName("water content") soil_grid.GetCellData().AddArray(soil_water_content) soil_pressure = vtk_data(np.array(s.getSolutionHead())) soil_pressure.SetName("pressure head") # in macroscopic soil soil_grid.GetCellData().AddArray(soil_pressure) if sol_ind > 0: d = vtk_data(np.array(s.getSolution(sol_ind))) pname_mesh = "solute" + str(sol_ind) d.SetName(pname_mesh) # in macroscopic soil soil_grid.GetCellData().AddArray(d) rootActor, rootCBar = plot_roots(pd, pname, "", False) meshActors, meshCBar = plot_mesh_cuts(soil_grid, pname_mesh, 7, "", False) lut = meshActors[-1].GetMapper().GetLookupTable() # same same rootActor.GetMapper().SetLookupTable(lut) meshActors.extend([rootActor]) render_window(meshActors, filename, meshCBar, pd.GetBounds()).Start() if filename: path = "results/" write_vtp(path + filename + ".vtp", pd) write_vtu(path + filename + ".vtu", soil_grid)
def plot_suf(data, ax3, j): """ plots suf versus depth per root type data DataModel (in viewer_data.poy) ax3 matplotlib axis j scenario hard coded in viewer_conductivities.py """ ax3.clear() if j == 0: viewer_conductivities.init_constant_scenario1(data.xylem_flux) elif j == 1: viewer_conductivities.init_constant_scenario2(data.xylem_flux) elif j == 2: viewer_conductivities.init_dynamic_scenario1(data.xylem_flux) elif j == 3: viewer_conductivities.init_dynamic_scenario2(data.xylem_flux) print(data.max_ct) print(data.base_segs) krs, _ = data.xylem_flux.get_krs(data.max_ct, data.base_segs) suf = data.xylem_flux.get_suf(data.max_ct) data.analyser.addData("SUF", suf) n = int(np.ceil(-data.analyser.getMinBounds().z)) z_ = np.linspace(-0.5, -n + 0.5, n) d = data.analyser.distribution("SUF", 0., float(-n), int(n), False) # False!!! print("SUF total", np.min(d), np.max(d), np.mean(d)) ax3.plot(d, z_, "-*", label="total") max_type = int(np.max(data.analyser.data["subType"])) for i in range(0, max_type + 1): ana = pb.SegmentAnalyser(data.analyser) # copy ana.filter("subType", i) segn = len(ana.segments) if segn > 0: d = ana.distribution("SUF", 0., float(-n), int(n), False) ax3.plot(d, z_, "-*", label="type {:g}".format(i)) print("SUF", i, np.min(d), np.max(d), np.mean(d)) ax3.set_title("Root system krs {:g}".format(krs)) ax3.set_ylabel("Depth (cm)") ax3.set_xlabel( "Root system surface uptake fraction (SUF) per 1 cm layer (1)") ax3.legend()
def segs_to_polydata(rs, zoom_factor=10., param_names=["radius", "type", "creationTime"]): """ Creates vtkPolydata from a RootSystem or Plant using segments @param rs A RootSystem, Plant, or SegmentAnalyser @param zoom_factor The radial zoom factor, since root are sometimes too thin for vizualisation @param param_names Parameter names of scalar fields, that are copied to the polydata @return A vtkPolydata object of the root system """ if isinstance(rs, pb.Organism): ana = pb.SegmentAnalyser(rs) # for Organism like Plant or RootSystem else: ana = rs nodes = np_convert(ana.nodes) segs = np_convert(ana.segments) points = vtk_points(nodes) cells = vtk_cells(segs) pd = vtk.vtkPolyData() pd.SetPoints(points) pd.SetLines(cells) # check SetPolys for n in param_names: param = np.array(ana.getParameter(n)) if param.shape[0] == segs.shape[0]: if n == "radius": param *= zoom_factor data = vtk_data(param) data.SetName(n) pd.GetCellData().AddArray(data) else: print( "segs_to_polydata: Warning parameter " + n + " is sikpped because of wrong size", param.shape[0], "instead of", segs.shape[0]) c2p = vtk.vtkCellDataToPointData() c2p.SetPassCellData(True) c2p.SetInputData(pd) c2p.Update() return c2p.GetPolyDataOutput()
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()
""" nodes and segments from measurements """ import sys sys.path.append("../../..") import plantbox as pb # Data from any source, as Python types nodes = [ [0, 1, 0], [0, 1, -1], [0, 1, -2], [0, 1, -3], ] segs = [[0, 1], [1, 2], [2, 3]] cts = [0., 0., 0.] radii = [0.1, 0.1, 0.1] # convert from Python to C++ binding types nodes = [pb.Vector3d(n[0], n[1], n[2]) for n in nodes] segs = [pb.Vector2i(s[0], s[1]) for s in segs] # create the SegmentAnalyser without underlying RootSystem ana = pb.SegmentAnalyser(nodes, segs, cts, radii) print("length", ana.getSummed("length")) ana.write("results/example_3d.vtp", ["creationTime", "radius"])
# Soil core analysis depth, layers = 100., 20 interrow = 1 # inter-row spacing row = 1 # row spacing layerVolume = depth / layers * interrow * row simtime = 200 dt = 0.5 N = round(simtime / dt) z_ = np.linspace(0, -1 * depth, layers) rs.initialize() time = np.linspace(0, simtime - 1, N) rld = np.zeros(N) for i in range(0, N): rs.simulate(dt, True) ana = pb.SegmentAnalyser(rs) rl = ana.distribution("length", 0., -depth, layers, True) rl = np.array(rl) rld[i] = rl[2] / layerVolume rs.write("RAC_unimpeded.vtp") fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(16, 8)) axes.plot(time, rld) axes.set_title('RAC') ################################################################################# rs = pb.RootSystem() rs.readParameters(path + name + ".xml") rs.setSeed(1) # Manually set scale elongation function scale_elongation = pb.EquidistantGrid1D(
def plot_rootsystem_development(analyser, ax2, j): """ analyser pb.SegmentAnalyser class ax2 matplotlib axis j type of plot (0: "length", 1: "surface", 2: "volume") """ type_str = ["length", "surface", "volume"] unit_str = ["(cm)", "(cm$^2$)", "(cm$^3$)"] ax2.clear() radii = analyser.data["radius"] # copy once if j == 0: weights = [ analyser.getSegmentLength(i) for i in range(0, len(analyser.segments)) ] elif j == 1: weights = [ 2 * np.pi * radii[i] * analyser.getSegmentLength(i) for i in range(0, len(analyser.segments)) ] elif j == 2: weights = [ np.pi * radii[i] * radii[i] * analyser.getSegmentLength(i) for i in range(0, len(analyser.segments)) ] cts = np.array(analyser.data["creationTime"]) try: l_, t_ = np.histogram(cts, 100, weights=weights) ax2.plot(0.5 * (t_[1:] + t_[:-1]), np.cumsum(l_), "-", label="total") max_type = int(np.max(analyser.data["subType"])) for i in range(0, max_type + 1): ana = pb.SegmentAnalyser(analyser) # copy ana.filter("subType", i) n = len(ana.segments) if n > 0: radii = ana.data["radius"] # copy once if j == 0: weights = [ ana.getSegmentLength(i) for i in range(0, len(ana.segments)) ] elif j == 1: weights = [ 2 * np.pi * radii[i] * ana.getSegmentLength(i) for i in range(0, len(ana.segments)) ] elif j == 2: weights = [ np.pi * radii[i] * radii[i] * ana.getSegmentLength(i) for i in range(0, len(ana.segments)) ] cts = np.array(ana.data["creationTime"]) l_, t_ = np.histogram(cts, 100, weights=weights) ax2.plot(0.5 * (t_[1:] + t_[:-1]), np.cumsum(l_), "-", label="type {:g}".format(i)) ax2.legend() except: pass ax2.set_xlabel("Time (days)") ax2.set_ylabel("Root system " + type_str[j] + " " + unit_str[j])
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')
simDuration += dt if step *dt % (60) == 0: #choose how often get output #### # # copy of phi # #### reorderedPhi = np.array([x for _,x in sorted(zip(phl.cellsID,phl.phi.value))]) reorderedOutFlow = np.array([x for _,x in sorted(zip(phl.cellsID,cumulOut))]) reorderedRm = np.array([x for _,x in sorted(zip(phl.cellsID,cumulRm))]) reorderedGrSink = np.array([x for _,x in sorted(zip(phl.cellsID,cumulGr))]) orgNum = np.array([phl.newCell2organID[xi] for xi in phl.newCell2organID]) reorderedorgNum = np.array([x for _,x in sorted(zip(phl.cellsID,orgNum))]) reorderedVolume = np.array([x for _,x in sorted(zip(phl.cellsID,phl.mesh.cellVolumes))]) ana = pb.SegmentAnalyser(phl.rs) ana.addData("phi", np.around(reorderedPhi, 5)) ana.addData("outFlow", np.around(reorderedOutFlow/reorderedVolume, 5)) ana.addData("Rm", np.around(reorderedRm/reorderedVolume, 5)) ana.addData("GrSink", np.around(reorderedGrSink/reorderedVolume, 5)) ana.addData("rx", phl.Px) ana.addData("fluxes", fluxes) ana.addData("orgNr", reorderedorgNum) ana.write("results/%s_example9a.vtp" %(step), ["radius", "surface", "phi", "outFlow", "Rm", "GrSink", "rx","fluxes","orgNr"]) if step % 1 == 0: #choose how often get output #### # # check balance # ####
print("roots") for p in plant.getOrganRandomParameter(pb.root): if (p.subType > 0): print(p.subType, p.a, p.successor) if p.subType == 1: # taproot p.theta = 0. p.a = 0.05 p.a_s = 0 soil = pb.SDF_PlantContainer(1.e6, 1.e6, 1.e6, False) # plant.setGeometry(soil) # increase resolution for p in plant.getOrganRandomParameter(pb.root): p.dx = 0.2 # Initialize plant.initialize() # Simulate plant.simulate(30, True) # Export final result (as vtp) plant.write("results/example_plant.vtp") ana = pb.SegmentAnalyser(plant) ana.write("results/example_plant_segs.vtp") # Plot, using vtk vp.plot_plant(plant, "organType")
soilcolumn2 = pb.SDF_RotateTranslate(soilcolumn, 0, 0, pb.Vector3d(10, 0, 0)) # shift 10 cm # pick one geometry for further analysis geom = soilcolumn z_ = np.linspace(0, -1 * depth, layers) fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(16, 8)) for a in axes: a.set_xlabel('RLD (cm/cm^3)') # layer size is 1 cm a.set_ylabel('Depth (cm)') # Make a root length distribution layerVolume = depth / layers * 20 * 20 times = [120, 60, 30, 10] ana = pb.SegmentAnalyser(rs) ana.cropDomain(20, 20, depth) # ana.mapPeriodic(20, 20) rl_ = [] axes[0].set_title('All roots in 20*20*100') for t in times: ana.filter("creationTime", 0, t) rl_.append(ana.distribution("length", 0., -depth, layers, True)) axes[0].plot(np.array(rl_[-1]) / layerVolume, z_) axes[0].legend(["10 days", "30 days", "60 days", "120 days"]) # Make a root length distribution along the soil core layerVolume = depth / layers * r * r * np.pi ana = pb.SegmentAnalyser(rs) ana.crop(geom) ana.pack() rl_ = []
sigma = [0.4, 1., 1., 1., 1.] * 2 for p in rs.getRootRandomParameter(): 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
min_ = np.array([-5, -5, -15]) max_ = np.array([5, 5, 0.]) res_ = np.array([1, 3, 5]) if not periodic: sdf = pb.SDF_PlantBox(0.99 * (max_[0] - min_[0]), 0.99 * (max_[1] - min_[1]), 0.99 * (max_[2] - min_[2])) rs.setGeometry(sdf) rs.setRectangularGrid(pb.Vector3d(min_), pb.Vector3d(max_), pb.Vector3d(res_), False) # cut and map segments rs.initialize() rs.simulate(rs_age, False) N = round(sim_time / dt) ana = pb.SegmentAnalyser(rs.mappedSegments()) anim = vp.AnimateRoots(ana) anim.min = min_ anim.max = max_ anim.res = res_ anim.file = "results/example7a" anim.start() for i in range(0, N): rs.simulate(dt, False) """ add segment indices """ segs = rs.segments x = np.zeros(len(segs)) for i, s in enumerate(segs): try:
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 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_)
def err (fitparams): #parameters to be optimized lmaxp=fitparams[0] tropismNp=fitparams[1] tropismSp=fitparams[2] rp=fitparams[3] simtime = 120 M = 4 # number of plants in rows N = 2 # number of rows distp = 3 # distance between the root systems along row[cm] distr =12 # distance between the rows[cm] interrow=N*distr # inter-row spacing row=M*distp # row spacing r, depth, layers = 5, 100., 11 # Soil core analysis layerVolume = depth / layers * r * r * np.pi z_ = np.linspace(0, -1 * depth, layers) times = [120, 60, 30, 10] soilcolumn = pb.SDF_PlantContainer(r, r, depth, False) # in the center of the root soilcolumn1 = pb.SDF_RotateTranslate(soilcolumn, 0, 0, pb.Vector3d(-6, 0, 0)) soilcolumn2 = pb.SDF_RotateTranslate(soilcolumn, 0, 0, pb.Vector3d(6, 0, 0)) soilcolumns=[soilcolumn1,soilcolumn, soilcolumn2] with open('rld.pkl','rb') as f: measured_RLD = pkl.load(f) real_RLD=np.reshape(measured_RLD,(measured_RLD.shape[0]*measured_RLD.shape[1]*measured_RLD.shape[2],1)) rld=np.zeros([measured_RLD.shape[0],measured_RLD.shape[1],measured_RLD.shape[2]]) # rld=np.zeros([len(soilcolumns),len(times),layers]) path = "../../modelparameter/rootsystem/" name = "wheat" # fig, axes = plt.subplots(nrows = 1, ncols = len(soilcolumns), figsize = (16, 8)) # Make a root length distribution along the soil cores for k in range(len(soilcolumns)): # 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") p1 = rs.getRootRandomParameter(1) # tap and basal root type p1.lmax = lmaxp p1.tropismN=tropismNp p1.tropismS=tropismSp p1.r=rp for p in rs.getRootRandomParameter(): p.lns = 0 p.rs = 0 p.lmaxs = 0 p.thetas = 0 p.las = 0 p.lbs=0 rs.setSeed(1) rs.getRootSystemParameter().seedPos = pb.Vector3d(distr * i, distp * j, -3.) # cm rs.initialize() allRS.append(rs) # Simulate for rs in allRS: rs.simulate(simtime) # Export results as single vtp files (as polylines) ana = pb.SegmentAnalyser() # see example 3b for z, rs in enumerate(allRS): # vtpname = "results/rlds/plant_" + str(z) + ".vtp" # rs.write(vtpname) ana.addSegments(rs) # collect all # Write all into single file (segments) # ana.write("results/rlds/all_plants.vtp") ana.mapPeriodic(interrow, row) # ana.write("results/rlds/plant_periodic.vtp") rl_ = [] ana.crop(soilcolumns[k]) ana.pack() # ana.write("results/rlds/core"+str(k+1)+".vtp") # axes[k].set_title('Soil core'+' ' +str(k+1)) for j in range(len(times)): ana.filter("creationTime", 0, times[j]) rl_.append(ana.distribution("length", 0., -depth, layers, True)) # axes[k].plot(np.array(rl_[-1]) / layerVolume, z_) # axes[k].legend(["120 days", "60 days", "30 days", "15 days"]) rld[k]=np.array(rl_)/layerVolume # for a in axes: # a.set_xlabel('RLD $(cm/cm^3)$') # a.set_ylabel('Depth $(cm)$') # a.set_xlim(0,np.max(rld)) # fig.subplots_adjust() # plt.savefig("results/rlds/rld_plot.png") # plt.show() RLD=np.reshape(rld,(rld.shape[0]*rld.shape[1]*rld.shape[2],1)) # print(rld) # with open('results/rlds/rld.pkl','wb') as f: # pkl.dump(rld, f) # sys.exit() err = math.sqrt(sum(((np.subtract(RLD,real_RLD)))**2)/len(RLD)) #NRMSE return err
plt.show() fig, ax = plt.subplots() name = ["root", "stem", "leaf"] color = ['tab:blue', 'tab:orange', 'tab:green'] for ndType in [2, 3, 4]: segIdx = r.get_segments_index(ndType) nodesy = segIdx + np.ones(segIdx.shape, dtype=np.int64) y = nodes[nodesy] #coordinates x = fluxes[segIdx] ax.scatter(x, y[:, 2], c=color[ndType - 2], label=name[ndType - 2], alpha=0.3, edgecolors='none') ax.legend() ax.grid(True) plt.xlabel("Fluxes (cm3/day)") plt.ylabel("Depth (cm)") plt.title("water fluxes") plt.show() #Additional vtk plot ana = pb.SegmentAnalyser(r.rs) ana.addData("rx", rx) ana.addData("fluxes", fluxes) # cut off for vizualisation ana.write("results/example_6f.vtp", ["radius", "surface", "rx", "fluxes"]) # #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