def soil_cores(x :list, y :list, r :float, h :float): """ A lsit of soil core geometries with a fixed location in the field @param x x coordinates of the soil cores (cm) @param y y coordinates of the soil cores (cm) @param r radius of the soil core (cm) @param h height of the soil core (cm) """ assert len(x) == len(y), "coordinate length must be equal" core = pb.SDF_PlantContainer(r, r, h, False) cores = [] for i in range(0, len(x)): cores.append(pb.SDF_RotateTranslate(core, 0., pb.SDF_Axis.xaxis, pb.Vector3d(x[i], y[i], 0.))) # just translate return cores;
rs.readParameters(path + name + ".xml") # Manually set tropism to hydrotropism for the first ten root types sigma = [0.4, 1., 1., 1., 1.] * 2 for p in rs.getRootRandomParameter(): p.dx = 0.25 # adjust resolution p.tropismT = pb.TropismType.hydro p.tropismN = 2 # strength of tropism p.tropismS = sigma[p.subType - 1] # Static soil property in a thin layer 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)
"""scales insertion angle""" import sys sys.path.append("../../..") import numpy as np 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") # box with a left and a right compartment for analysis sideBox = pb.SDF_PlantBox(10, 20, 50) left = pb.SDF_RotateTranslate(sideBox, pb.Vector3d(-4.99, 0, 0)) right = pb.SDF_RotateTranslate(sideBox, pb.Vector3d(4.99, 0, 0)) leftright = pb.SDF_Union(left, right) rs.setGeometry(leftright) # left compartment has a minimum of 0.01, 1 elsewhere maxS = 1. # maximal minS = 0.1 # minimal slope = 1. # [cm] linear gradient between min and max leftC = pb.SDF_Complement(left) soilprop = pb.SoilLookUpSDF(leftC, maxS, minS, slope) # Manually set scaling function and tropism parameters sigma = [0.4, 1., 1., 1., 1.] * 2 for p in rs.getRootRandomParameter(): if p.subType > 2: p.dx = 0.25 # adjust resolution
import math rs = pb.RootSystem() # Open plant and root parameter from a file path = "../../../modelparameter/rootsystem/" name = "Zea_mays_4_Leitner_2014" rs.readParameters(path + name + ".xml") # 1. Creates a square rhizotron r*r, with height h, rotated around the x-axis r, h, alpha = 20, 4, 45 rhizotron2 = pb.SDF_PlantContainer(r, r, h, True) posA = pb.Vector3d(0, r, -h / 2) # origin before rotation A = pb.Matrix3d.rotX(alpha / 180. * math.pi) posA = A.times(posA) # origin after rotation rotatedRhizotron = pb.SDF_RotateTranslate(rhizotron2, alpha, 0, posA.times(-1)) # 2. A split pot experiment topBox = pb.SDF_PlantBox(22, 20, 5) sideBox = pb.SDF_PlantBox(10, 20, 35) left = pb.SDF_RotateTranslate(sideBox, pb.Vector3d(-6, 0, -5)) right = pb.SDF_RotateTranslate(sideBox, pb.Vector3d(6, 0, -5)) box_ = [] box_.append(topBox) box_.append(left) box_.append(right) splitBox = pb.SDF_Union(box_) # 3. Rhizotubes as obstacles box = pb.SDF_PlantBox(96, 126, 130) # box rhizotube = pb.SDF_PlantContainer(6.4, 6.4, 96, False) # a single rhizotube
import plantbox as pb path = "../../../modelparameter/rootsystem/" name = "Zea_mays_1_Leitner_2010" # Zea_mays_1_Leitner_2010, Brassica_napus_a_Leitner_2010 rs = pb.RootSystem() rs.readParameters(path + name + ".xml") rs.initialize() rs.simulate(120) rs.write("results/example_3b.vtp") r, depth, layers = 5, 100., 100 # Soil core analysis soilcolumn = pb.SDF_PlantContainer(r, r, depth, False) # in the center of the root 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)
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