def read_rsml(file_name:str, verbose=True): """ reads an RSML file and converts to MappedSegments with units [cm] @file_name the file name of the rsml, including file extension (e.g. "test.rsml" ) @return a CPlantBox MappedSegments object """ polylines, props, funcs = rsml.read_rsml(file_name) bn = 0 # count base roots for i, _ in enumerate(polylines): if props["parent-poly"][i] < 0: bn += 1 if bn > 1: polylines, props, funcs = rsml.artificial_shoot(polylines, props, funcs) if verbose: print("XylemFluxPython.read_rsml: added an artificial shoot") nodes, segs = rsml.get_segments(polylines, props) radii, seg_ct, types = rsml.get_parameter(polylines, funcs, props) if verbose: print("XylemFluxPython.read_rsml: read rsml with", len(nodes), "nodes and", len(segs), "segments") nodes = np.array(nodes) # for slicing in the plots nodes2 = [] # Conversions... for n in nodes: nodes2.append(pb.Vector3d(n[0] , n[1] , n[2])) segs2 = [] nodeCTs = np.zeros((len(nodes), 1)) # we need node creation times for i, s in enumerate(segs): nodeCTs[s[1]] = seg_ct[i] segs2.append(pb.Vector2i(int(s[0]), int(s[1]))) radii = np.array(radii) types = np.array(types, dtype=np.int64) - 1 # index must start with 0 if verbose: print(" nodeCTs [{:g}, {:g}] days".format(np.min(nodeCTs), np.max(nodeCTs))) print(" raddii [{:g}, {:g}] cm".format(np.min(radii), np.max(radii))) print(" subTypes [{:g}, {:g}] ".format(np.min(types), np.max(types))) return pb.MappedSegments(nodes2, nodeCTs, segs2, radii, types) # root system grid
def add_artificial_shoot(self): """ adds a 1 cm shoot element, connecting all base roots the type for looking up conductivities is set to 10 """ nodes = self.analyser.nodes bni = self.base_nodes print("DataModel.add_artificial_shoot() base node indices are", bni) mid = np.zeros((3,)) for i in bni: mid += np.array([nodes[i].x, nodes[i].y, nodes[i].z]) mid /= len(bni) print("DataModel.add_artificial_shoot() mid point is", mid) rsml_reader.artificial_shoot(self.polylines, self.properties, self.functions) # append artifial shoot (default values) radii, cts, types, tagnames = rsml_reader.get_parameter(self.polylines, self.functions, self.properties) # paramter per node # change default values from artificial shoot collar = mid.copy() mid[2] += 0.1 # shift a bit up collar[2] += 1.1 # 1 cm shoot length self.polylines[0][0] = collar self.polylines[0][1] = mid self.set_selected(radii, cts, types, tagnames) self.scale_selected_() self.radii[0] = 0.1 # cm self.radii[1] = 0.1 # cm self.types[0] = 10 self.types[1] = 10 # print("after ADD SHOOT") # print(self.polylines) # print(self.properties["parent-poly"]) # print(self.properties["parent-node"]) # print("radii", radii) # print("cts", cts) # print("types", types) self.convert_to_xylem_flux_()
def open_rsml(self, fname, shift_z=False): """ opens an rsml file into self.data, using rsml_reader (in CPlantBox/src/python_modules) converts units to cm and day if necessary converts 2d -> 3d, """ polylines, properties, functions, metadata = rsml_reader.read_rsml(fname) print("DataModel.open_rsml(): scale to cm", metadata.scale_to_cm) self.set_rsml(polylines, properties, functions, metadata) self.scale_polylines_() # converts units self.check_polylines_2d_(shift_z) # 2d -> 3d radii, cts, types, tagnames = rsml_reader.get_parameter(polylines, functions, properties) # paramter per node self.set_selected(radii, cts, types, tagnames) self.scale_selected_() # converts units of special fields radii, cts, types
def read_rsml(file_name: str, verbose=True): """ reads an RSML file and converts to MappedSegments with units [cm] @file_name the file name of the rsml, including file extension (e.g. "test.rsml" ) @return a CPlantBox MappedSegments object """ polylines, props, funcs, _ = rsml.read_rsml(file_name) bn = 0 # count base roots for i, _ in enumerate(polylines): if props["parent-poly"][i] < 0: bn += 1 if bn > 1: rsml.artificial_shoot(polylines, props, funcs) if verbose: print("XylemFluxPython.read_rsml: added an artificial shoot") nodes, segs = rsml.get_segments(polylines, props) if verbose: print("XylemFluxPython.read_rsml: read rsml with", len(nodes), "nodes and", len(segs), "segments") nodes2 = [pb.Vector3d(n[0], n[1], n[2]) for n in nodes] # Conversions to PlantBox types segs2 = [pb.Vector2i(int(s[0]), int(s[1])) for s in segs] radii, cts, types, tag_names = rsml.get_parameter( polylines, funcs, props) segRadii = np.zeros( (segs.shape[0], 1)) # convert to paramter per segment segTypes = np.zeros((segs.shape[0], 1)) for i, s in enumerate(segs): segRadii[i] = radii[s[1]] # seg to node index segTypes[i] = types[s[1]] if verbose: print(" cts [{:g}, {:g}] days".format( np.min(cts), np.max(cts))) print(" raddii [{:g}, {:g}] cm".format( np.min(radii), np.max(radii))) print(" subTypes [{:g}, {:g}] ".format( np.min(types), np.max(types))) print() return pb.MappedSegments(nodes2, cts, segs2, segRadii, segTypes) # root system grid
def read_rsml(file_name: str): """ Reads an RSML file and converts to MappedSegments with units [cm] """ polylines, props, funcs = rsml.read_rsml(file_name) nodes, segs = rsml.get_segments(polylines, props) radii, seg_ct, types = rsml.get_parameter(polylines, funcs, props) print("Read rsml:", len(nodes), "nodes", len(radii), "radii") nodes = np.array(nodes) # for slicing in the plots nodes2 = [] # Conversions... for n in nodes: nodes2.append(pb.Vector3d(n[0], n[1], n[2])) segs2 = [] nodeCTs = np.zeros((len(nodes), 1)) # we need node creation times for i, s in enumerate(segs): nodeCTs[s[1]] = seg_ct[i] segs2.append(pb.Vector2i(int(s[0]), int(s[1]))) radii = np.array(radii) types = np.array(types, dtype=np.int64) - 1 # index must start with 0 return pb.MappedSegments(nodes2, nodeCTs, segs2, radii, types) # root system grid
def add_creation_times(self): """ lineary interpolates creation times assuming a lateral delay time of one day """ pl_ = self.polylines # rename self.functions["creation_time"] = [None] * len(pl_) for i, pl in enumerate(pl_): if self.properties["parent-poly"][i] == -1: self.functions["creation_time"][i] = np.zeros((len(pl,))) if not (i == 0 and len(pl) == 2): # not artifical shoot, else [0,0] is fine ct = self.functions["creation_time"][i] # rename lt = self.get_length_(pl) l = 0 ct[0] = 0 for j in range(0, len(pl) - 1): l += np.linalg.norm(np.array(pl[j + 1]) - np.array(pl[j])) ct[j + 1] = self.max_ct * (l / lt) for i, pl in enumerate(pl_): if self.functions["creation_time"][i] is None: self.add_creation_times_(i) radii, cts, types, tagnames = rsml_reader.get_parameter(self.polylines, self.functions, self.properties) # paramter per node self.set_selected(radii, cts, types, tagnames) self.scale_selected_() self.convert_to_xylem_flux_()