def load(index=0, dir='./adel_saved', basename=None, load_geom=True): if basename is None: if not os.path.exists(dir): os.mkdir(dir) basename_geom = dir + '/scene%04d' % (index) basename_adel = dir + '/adel%04d' % (index) else: basename_adel = basename_geom = basename fgeom = basename_geom + '.bgeom' fg = basename_adel + '.pckl' if not os.path.exists(fgeom) or not os.path.exists(fg): raise IOError('adel cannot find saved files') f = open(fg) g = pickle.load(f) f.close() # backward compatibility if isinstance(g, list): g, age = g root = g.node(0) meta = {'canopy_age': age} if 'meta' not in g.property_names(): root.meta = meta else: root.meta.update(meta) if load_geom: s = Scene() s.read(fgeom, 'BGEOM') geom = {sh.id: sh.geometry for sh in s} g.add_property('geometry') g.property('geometry').update(geom) return g
def display(self, color=(190, 205, 205), add=False): """ Display the 2-cells of a 2-G-Map using the ordered orbit of its darts in PlantGL. For each face element, retrieve the position of its ordered face darts and add a FaceSet PlantGL object to the scene. Example : s += pgl.Shape(pgl.FaceSet( [[0,0,0],[1,0,0],[1,1,0],[0,1,0]], [[0,1,2,3]]) , pgl.Material((0,100,0))) # for a green square """ from openalea.plantgl.all import Scene, Shape, Material, FaceSet, Viewer from random import randint s = Scene() for facedart in self.elements(2): lastfart = facedart positions = [] for dart in self.oderedorbit(facedart, [0, 1]): if self.alpha(0, dart) != lastfart: positions.append(self.get_position(dart)) lastfart = dart if color is None: mat = Material( (randint(0, 255), randint(0, 255), randint(0, 255))) else: mat = Material(tuple(color), diffuse=0.25) s.add( Shape(FaceSet(positions, [range(len(positions))]), mat, facedart)) if add: Viewer.add(s) else: Viewer.display(s)
def scene(self, view="axis", scene=None): """ Compute a scene from a tree squeleton. view='axis', 'node', 'polyline' or 'point' view specify if we compute a shape by axis, a shape by node or just a polyline. """ if not scene: scene = Scene() server = self.server max_order = server.max_order for order in range(max_order): self.axes(order, view) if server.has_leaf(): if view not in ['point']: self.leaves() else: self.axes(max_order, view) map(lambda x: scene.add(x), self._shapes) return scene
def display(self, color=[190, 205, 205], add=False, transparency=0): from openalea.plantgl.all import Scene, Shape, Material, FaceSet, Viewer from random import randint s = Scene() for facedart in self.elements(2): lastdart = facedart positions = [] for dart in self.orderedorbit(facedart, [0, 1]): if self.alpha(0, dart) != lastdart: positions.append(self.get_position(dart)) lastdart = dart if color is None: mat = Material( (randint(0, 255), randint(0, 255), randint(0, 255)), transparency=transparency) else: mat = Material(tuple(color), diffuse=0.25, transparency=transparency) s.add( Shape(FaceSet(positions, [range(len(positions))]), mat, facedart)) if add: Viewer.add(s) else: Viewer.display(s)
def darts2pglscene(self, textsize = None): from openalea.plantgl.all import Scene, Shape, Material, FaceSet, Polyline, PointSet, Translated, Text, Font from numpy import array s = Scene() th = 0.1 matdart = Material((0,0,0)) matalphai = [Material((100,100,100)),Material((0,200,0)),Material((0,0,200)),Material((200,0,0))] matlabel = Material((0,0,0)) alphaipos = [{} for i in xrange(3)] vertex = [] font = Font(size=textsize if textsize else 10) def process_edge(dart, facecenter = None, fshift = [0.,0.,0.]): try: edgecenter = self.cell_center(dart,1) except: print 'Cannot display dart', dart,': no coordinates.' return eshift = array(fshift) if not facecenter is None : eshift += (facecenter-edgecenter)*2*th for cdart in [dart, self.alpha(0,dart)]: pi = self.get_position(cdart) pdir = (edgecenter-pi) pi = pi + (pdir*(th*3) + eshift) vertex.append(pi) dartlengthratio = 0.6 s.add(Shape(Polyline([pi,pi+pdir*dartlengthratio]) , matdart, id = cdart)) s.add(Shape(Translated(pi+pdir*0.5, Text(str(cdart),fontstyle=font)), matlabel, id=cdart)) for i in xrange(0,3): oppidart = self.alpha( i,cdart) if oppidart != cdart: if i == 0 : alphaidartpos = pi+pdir* dartlengthratio else: alphaidartpos = pi+pdir*(0.1*i) if alphaipos[i].has_key(oppidart): s.add(Shape(Polyline([alphaipos[i][oppidart],alphaidartpos],width=5) , matalphai[i])) else: alphaipos[i][cdart] = alphaidartpos def process_face(dart, cellcenter = None, cshift = [0.,0.,0.]): try: facecenter = self.cell_center(fid,2) except: facecenter = None fshift = cshift if not cellcenter is None and not facecenter is None: fshift = (cellcenter-facecenter)*th for dart in self.incident_cells(fid,2,1): process_edge(dart, facecenter, fshift) for fid in self.elements(2): process_face(fid) s.add(Shape(PointSet(vertex, width=5) ,Material((0,0,0)) )) return s
def convex(): s = Scene() s.read('pruning.geom') assert len(s) == 740 leaves = get_leaves_from_scene(s) assert len(leaves) == 177 return leaves
def save(self, obj, filename): """ Store obj into filename """ filename = Path(filename) try: from openalea.plantgl.all import Scene sc = Scene() sc.add(obj) return sc.save(str(filename), "BGEOM") except ImportError: warnings.warn("You must install PlantGL if you want to load a BGEOM object.") except Exception, e: print e warnings.warn("Impossible to save the scene for object %s into %s" % (obj, filename))
def get_leaves_from_scene(scene): """parse a scene and extract the leaves. :param Scene scene: a PGL scene :return: a new scene with leaves shapes only This is appropriate for the scene given by stocatree simulations only. where leaves are bezierPatch types. .. todo:: improve the code to be more robust and generic. """ shapes = [] from openalea.plantgl.all import BezierPatch, Scene for sh in scene: try: if type(sh.geometry.geometry.geometry.geometry.geometry ) == BezierPatch: shapes.append(sh) except: pass scene = Scene() for x in shapes: scene += x return scene
def generate_pov(i=0, nbpovprocess=1, maxstep=None): """ generate ith images modulo nbpovprocess """ print('Image generator ', i, ' launched') from openalea.plantgl.all import Scene, Tesselator, PovFilePrinter print('Look at', stepfile) wait_for_file(stepfile) if maxstep is None: maxstep = int(open(stepfile, 'r').read()) step = i os.chdir(workingrep) while step < maxstep: bgeomfname = bgeomfile.format(str(step).zfill(4)) steppovfile = povfile.format(str(step).zfill(4)) stepimgfile = imgfile.format(str(step).zfill(4)) if os.path.exists(stepimgfile): print('Image ', step, 'already computed ...') step += nbpovprocess continue wait_for_file(bgeomfname) lscene = Scene(bgeomfname) for sh in lscene: sh.setComputedName() lscene.save(steppovfile) #tess = Tesselator() #printer = PovFilePrinter(steppovfile,tess) #lscene.apply(printer) if os.path.exists(steppovfile): mpovtext = mainpovtemplate % ( imageresolution[0], imageresolution[1], steppovfile, step) mpovfile = mainpovfile.format(str(step).zfill(4)) file(mpovfile, 'w').write(mpovtext) cmd = povcomdline.format(mpovfile, stepimgfile, imageresolution[0], imageresolution[1]) print() print(i, '>>>', cmd) print('Image ', step, 'computed ...') os.system(cmd) if os.path.exists(stepimgfile): os.remove(mpovfile) os.remove(steppovfile) os.remove(bgeomfname) else: print('Error with image', step) else: print('Error with image', step) step += nbpovprocess
def run(self, exp_id, batch_dir): for date, experiment in self.lpk_files.iteritems(): ##experiment[str(exp_id)] is the name (including directory) of the ##corresponding mtg file #mtgp = Mtg_Processing(experiment[str(exp_id)]) #lstring = mtgp.crt_pseudo_lstring() pl = open(experiment[str(exp_id)]) lstring = cPickle.load(pl) pl.close() scene = self.bgeom_files[date][str(exp_id)] sc = Scene(scene) experiment_date = time.strftime( "%d/%m/%Y %I:%M:%S", time.localtime( os.path.getmtime(self.bgeom_files[date][str(exp_id)]))) #id_dict = mtgp.crt_envdic() print "###########################" Viewer.display(sc) star = STAR(lstring, sc) star.collect(lstring, sc) #star.process_shoot(lstring, sc) stat = Statistics(lstring=lstring, \ attribute_list = [\ "parent_observation",\ "length",\ "radius",\ "leaf_area",\ "leaf_state",\ "ta_pgl",\ "sa_pgl",\ "star_pgl",\ "parent_unit_id",\ "parent_fbr_id",\ "parent_tree_id",\ ],\ shoot_level = True,\ branch_level = True,\ tree_level = True,\ exp_id = exp_id, \ growth_date = date,\ exp_date = experiment_date,\ dir = batch_dir) #Pickle the lstring data structure with information lpk = open(batch_dir + str(exp_id) + "_lpk_" + date, "w") cPickle.dump(lstring, lpk, 0) lpk.close() #env = Envelope(id_dict,\ # scene,\ # output_dir = self.general_directory+date+"_Envelope\\") #env.intercept() gc.collect() gc.collect()
def display(self, degree = None, add = False, randomcolor = True): from openalea.plantgl.all import Scene, Shape, Material, FaceSet, Polyline, PointSet, Viewer from random import randint s = Scene() m = Material() if degree is None: degree = self.degree if degree >= 2: try: ccw = self.orientation() except ValueError: ccw = set() for fid in self.iterate_over_each_i_cell(2): if fid in ccw: ofid = self.alpha(0,fid) else: ofid = fid positions = [] for dart, deg in self.orderedorbit_iter(ofid,[0,1]): if deg != 1: positions.append(self.get_position(dart)) s.add(Shape(FaceSet(positions, [range(len(positions))]) , Material((randint(0,255),randint(0,255),randint(0,255))) if randomcolor else m)) elif degree == 1: for eid in self.iterate_over_each_i_cell(1): s.add(Shape(Polyline([self.get_position(eid),self.get_position(self.alpha(0,eid))]) ,Material((randint(0,255),randint(0,255),randint(0,255))) )) elif degree == 0: s.add(Shape(PointSet([self.get_position(pid) for pid in self.iterate_over_each_i_cell(0)]) ,Material((randint(0,255),randint(0,255),randint(0,255))) )) if add : Viewer.add(s) else : Viewer.display(s)
def load(self, filename): """ :param filename: filename to convert into python object :return: a python object interpreted from string "text" """ filename = Path(filename) if filename.exists(): try: from openalea.plantgl.all import Scene sc = Scene() sc.clear() sc.read(str(filename), "BGEOM") return sc except ImportError: warnings.warn("You must install PlantGL if you want to load a BGEOM object.") except Exception, e: print e warnings.warn("Impossible to load the scene")
def view(patch): import itertools patchView = Scene() opoints = patch.points for i0,i1 in [(0,1),(1,2),(0,2)]: for index in itertools.product(*[list(range(d)) for d in [opoints.shape[i0],opoints.shape[i1]]]): i = [slice(None,None),slice(None,None),slice(None,None)] i[i0] = index[0] i[i1] = index[1] points = opoints[tuple(i)] pid = ((i[2]*10000 if not isinstance(i[2],slice) else 0)+ (i[1]*100 if not isinstance(i[1],slice) else 0)+ (i[0] if not isinstance(i[0],slice) else 0)) patchView.add(Polyline([p.project() for p in points])) return patchView
def display(self, color = [205,205,205], add = False): from openalea.plantgl.all import Scene, Shape, Material, FaceSet, Viewer from random import randint s = Scene() for facedart in self.elements(2): lastdart = facedart positions = [] for dart in self.orderedorbit(facedart,[0,1]): if self.alpha(0, dart) != lastdart: positions.append(self.get_position(dart)) lastdart = dart if color is None: mat = Material((randint(0,255),randint(0,255),randint(0,255))) else: mat = Material(tuple(color),diffuse=0.25) s.add(Shape(FaceSet(positions, [range(len(positions))]) , mat )) if add : Viewer.add(s) else : Viewer.display(s)
def test_triangle(): from openalea.plantgl.all import TriangleSet, Scene, Shape, Vector3 from openalea.plantgl.light import scene_irradiance points = [(0, 0, 0), (0, 0, sqrt(2)), (0, sqrt(2), 0)] triangles = Scene([Shape(TriangleSet(points, [list(range(3))]), id=8)]) lights = [(0, 0, 1)] res = scene_irradiance(triangles, lights, screenresolution=0.0005) print(res)
def test_cvxhull(): leaves = convex() s = Scene() s += leaves hull = cvxHull(leaves) s += hull
def save(self, obj, filename): """ Store obj into filename """ filename = Path(filename) try: from openalea.plantgl.all import Scene sc = Scene() sc.add(obj) return sc.save(str(filename), "BGEOM") except ImportError: warnings.warn( "You must install PlantGL if you want to load a BGEOM object.") except Exception, e: print e warnings.warn( "Impossible to save the scene for object %s into %s" % (obj, filename))
def defaultScene(self): """ Create a default scene. Here she is empty. :return: the scene """ scene = Scene() return scene
def make_thumbnail(self): from .thumbnailmaker import make_thumbnail from openalea.plantgl.all import Scene if self.gleditor.tree_seleted is None: return points = self.gleditor.points.subset( self.gleditor.segmented_points[self.gleditor.tree_seleted][0]) return make_thumbnail(Scene([points]), (256, 256))
def plot_spline_surface(ctrl_net, points): """ Parameters ========== - ctrl_net : the net of control points (list of list) - points : a set of evaluated points (list of list) """ scene = Scene() n = len(points) m = len(points[0]) # Compute a mesh (i.e. TriangleSet) for the set of points pointList = [pt for rank in points for pt in rank] indexList = [] for i in range(n - 1): for j in range(m - 1): ii = i * m + j i1 = (ii, ii + 1, ii + m) i2 = (ii + 1, ii + m + 1, ii + m) indexList.append(i1) indexList.append(i2) surf = Shape(TriangleSet(pointList, indexList), appearance=Material((12, 125, 12))) scene.add(surf) # plot the control net n = len(ctrl_net) m = len(ctrl_net[0]) for pts in ctrl_net: crv = Shape(geometry=Polyline(pts), appearance=Material((125, 12, 12))) scene.add(crv) for pt in pts: scene.add(Shape(Translated(Vector3(pt), Sphere(radius=0.1)))) for i in range(m): pts = [ctrl_net[j][i] for j in range(n)] crv = Shape(geometry=Polyline(pts), appearance=Material((12, 12, 125))) scene.add(crv) Viewer.display(scene)
def load(self, index=0, dir = './adel_saved'): from openalea.plantgl.all import Scene fgeom = dir + '/scene%04d.bgeom'%(index) fg = dir + '/adel%04d.pckl'%(index) s = Scene() s.read(fgeom, 'BGEOM') geom = {sh.id:sh.geometry for sh in s} f = open(fg) g, TT = pickle.load(f) f.close() self.canopy_age = TT g.add_property('geometry') g.property('geometry').update(geom) return g, TT
def create_scene_from_mtg(mtg, leaf_material=None, stem_material=None, soil_material=None, colors=None): """ Returns a plantgl scene from an mtg. """ if colors is None: if leaf_material is None: leaf_material = Material(Color3(0, 180, 0)) if stem_material is None: stem_material = Material(Color3(0, 130, 0)) if soil_material is None: soil_material = Material(Color3(170, 85, 0)) # colors = g.property('color') geometries = mtg.property('geometry') greeness = mtg.property('is_green') labels = mtg.property('label') scene = Scene() def geom2shape(vid, mesh, scene, colors): shape = None if isinstance(mesh, list): for m in mesh: geom2shape(vid, m, scene, colors) return if mesh is None: return if isinstance(mesh, Shape): shape = mesh mesh = mesh.geometry label = labels.get(vid) is_green = greeness.get(vid) if colors: shape = Shape(mesh, Material(Color3(*colors.get(vid, [0, 0, 0])))) elif not greeness: if not shape: shape = Shape(mesh) elif label.startswith('Stem') and is_green: shape = Shape(mesh, stem_material) elif label.startswith('Leaf') and is_green: shape = Shape(mesh, leaf_material) elif not is_green: shape = Shape(mesh, soil_material) shape.id = vid scene.add(shape) for vid, mesh in geometries.iteritems(): geom2shape(vid, mesh, scene, colors) return scene
def test_boxcounting(): from openalea.plantgl.all import Scene s = Scene() s.read('pruning.geom') log_n_delta, log_inv_delta, n_delta, delta = boxcounting(s, show=False, maxd=5) try: log_n_delta_2, log_inv_delta_2, n_delta, delta_2 = boxcounting( s, show=False, maxd=5, library='fractalysis') assert log_n_delta == log_n_delta_2 assert log_inv_delta == log_inv_delta_2 assert n_delta == n_delta_2 except: pass try: boxcounting(s, show=False, maxd=5, library='wrong_name') assert False except: assert True
def _render(self, name=None, save=False, max_percentile=None): """ Low level method to render a tissue, colored by concentrations. Concentrations are taken from the table of concentrations of the Simulation. Uses JetMap as ColorMap. Parameters ---------- name : string Name of the species whose concentrations must be rendered save : bool Whether to save a picture or not """ if name == None: array = np.zeros(self.sim.n_cells) max_cmap = 0 else: array = self.sim.y.get_species( name) / self.sim.dilution_volumes.as_1d_array() if max_percentile is None: max_cmap = np.max(array) else: max_cmap = np.percentile(array, max_percentile) array = np.where(array <= max_cmap, array, max_cmap * np.ones(array.shape)) prop = dict(list(zip(self.sim.cids, array))) scene = Scene() scene += (guillaume.topomesh_display.drawPropertyTopomesh( self.sim.mesh, self.sim.get_pos(), 3, prop, JetMap, color_range=[0., max(max_cmap, 1e-6)], coef=0.99, transparent_min=False)) Viewer.display(scene) if save: timestamp = time.strftime('%Y%m%d_%H%M%S') + "_" + str( time.time() * 1000 % 1)[2:] Viewer.frameGL.saveImage("figures/" + name + "-" + timestamp + ".png") return max_cmap
def color_structures(fruiting_structures, mtg, scene): import matplotlib.pyplot as plt from openalea.plantgl.all import Material, Shape from random import randint, seed from numpy.random import seed as nseed seed(0) nseed(0) nbcolors = len(sum([inflos for inflos, gus in fruiting_structures], [])) #len(fruiting_structures) _colors = plt.get_cmap('jet', nbcolors) colors = lambda x: _colors(x) structures = dict() idmap = mtg.property('_axial_id') print('determine colors') colindex = determine_colorindex(fruiting_structures, mtg, scene) print(colindex) allinflos = [ lid for vid, lid in list(idmap.items()) if mtg.label(vid) == 'Inflorescence' ] for inflos, gus in fruiting_structures: i = colindex.pop(0) col = colors(i) mat = Material([int(c * 100) for c in col[:3]], 2) for j in inflos: structures[idmap[j]] = mat for j in gus: structures[idmap[j]] = mat print(col, inflos) definfmat = Material((50, 50, 50)) for inf in allinflos: if not inf in structures: structures[inf] = definfmat defmat = Material((0, 0, 0)) print('compute colored scene') nscene = Scene([ Shape(sh.geometry, structures.get(sh.id, defmat), sh.id, sh.parentId) for sh in scene ]) return nscene Viewer.display(nsc)
def plot_spline_crv(ctrls, pts): """ Parameters ========== - ctrl: control points - pts : evaluated points on the curve """ from openalea.plantgl.all import Scene, Shape, Material, FaceSet, Viewer, Polyline from random import randint scene = Scene() crv = Shape(geometry=Polyline(pts), appearance=Material((12, 12, 125))) scene.add(crv) ctrl = Shape(geometry=Polyline(ctrls), appearance=Material((12, 125, 12))) scene.add(ctrl) # To complete: Draw the control points and the line between each ones. Viewer.display(scene)
def load(self, filename): """ :param filename: filename to convert into python object :return: a python object interpreted from string "text" """ filename = Path(filename) if filename.exists(): try: from openalea.plantgl.all import Scene sc = Scene() sc.clear() sc.read(str(filename), "BGEOM") return sc except ImportError: warnings.warn( "You must install PlantGL if you want to load a BGEOM object." ) except Exception, e: print e warnings.warn("Impossible to load the scene")
# ============================================================================= # Construct the plant mock-up # ============================================================================= # Path for plant digitalization data. g = architecture.vine_mtg('digit.input') # Local Coordinates Correction for v in traversal.iter_mtg2(g, g.root): architecture.vine_phyto_modular(g, v) architecture.vine_petiole(g, v, pet_ins=90., pet_ins_cv=0., phyllo_angle=180) architecture.vine_leaf(g, v, leaf_inc=-45., leaf_inc_cv=100., lim_max=12.5, lim_min=5., order_lim_max=6., max_order=55, rand_rot_angle=90., cordon_vector=None) architecture.vine_mtg_properties(g, v) architecture.vine_mtg_geometry(g, v) architecture.vine_transform(g, v) # Display of the plant mock-up (result in 'fig_01_plant_mock_up.png') # scene = HSVisu.visu(g,def_elmnt_color_dict=True,scene=Scene(), # snap_shot_path='mockup.png') scene = display.visu(g, def_elmnt_color_dict=True, scene=Scene(), view_result=True) # ============================================================================= # Run HydroShoot # ============================================================================= model.run(g, str(getcwd()) + '/', scene)
N_max_order=6) architecture.vine_petiole(g, v, pet_ins=90., pet_ins_cv=0., phyllo_angle=180.) architecture.vine_leaf(g, v, leaf_inc=-45., leaf_inc_cv=100., lim_max=12.5, lim_min=5., order_lim_max=6, max_order=55, rand_rot_angle=90., cordon_vector=None) architecture.vine_mtg_properties(g, v) architecture.vine_mtg_geometry(g, v) architecture.vine_transform(g, v) scene = display.visu(g, def_elmnt_color_dict=True, scene=Scene(), view_result=True) # ============================================================================= # Run HydroShoot # ============================================================================= model.run(g, str(getcwd()) + '/', scene)
def run(g, wd, scene=None, write_result=True, **kwargs): """ Calculates leaf gas and energy exchange in addition to the hydraulic structure of an individual plant. :Parameters: - **g**: a multiscale tree graph object - **wd**: string, working directory - **scene**: PlantGl scene - **kwargs** can include: - **psi_soil**: [MPa] predawn soil water potential - **gdd_since_budbreak**: [°Cd] growing degree-day since bubreak - **sun2scene**: PlantGl scene, when prodivided, a sun object (sphere) is added to it - **soil_size**: [cm] length of squared mesh size """ print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++') print('+ Project: ', wd) print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++') time_on = datetime.now() # Read user parameters params_path = wd + 'params.json' params = Params(params_path) output_index = params.simulation.output_index # ============================================================================== # Initialisation # ============================================================================== # Climate data meteo_path = wd + params.simulation.meteo meteo_tab = read_csv(meteo_path, sep=';', decimal='.', header=0) meteo_tab.time = DatetimeIndex(meteo_tab.time) meteo_tab = meteo_tab.set_index(meteo_tab.time) # Adding missing data if 'Ca' not in meteo_tab.columns: meteo_tab['Ca'] = [400.] * len(meteo_tab) # ppm [CO2] if 'Pa' not in meteo_tab.columns: meteo_tab['Pa'] = [101.3] * len(meteo_tab) # atmospheric pressure # Determination of the simulation period sdate = datetime.strptime(params.simulation.sdate, "%Y-%m-%d %H:%M:%S") edate = datetime.strptime(params.simulation.edate, "%Y-%m-%d %H:%M:%S") datet = date_range(sdate, edate, freq='H') meteo = meteo_tab.loc[datet, :] time_conv = {'D': 86.4e3, 'H': 3600., 'T': 60., 'S': 1.}[datet.freqstr] # Reading available pre-dawn soil water potential data if 'psi_soil' in kwargs: psi_pd = DataFrame([kwargs['psi_soil']] * len(meteo.time), index=meteo.time, columns=['psi']) else: assert (isfile(wd + 'psi_soil.input')), "The 'psi_soil.input' file is missing." psi_pd = read_csv(wd + 'psi_soil.input', sep=';', decimal='.').set_index('time') psi_pd.index = [datetime.strptime(s, "%Y-%m-%d") for s in psi_pd.index] # Unit length conversion (from scene unit to the standard [m]) unit) unit_scene_length = params.simulation.unit_scene_length length_conv = {'mm': 1.e-3, 'cm': 1.e-2, 'm': 1.}[unit_scene_length] # Determination of cumulative degree-days parameter t_base = params.phenology.t_base budbreak_date = datetime.strptime(params.phenology.emdate, "%Y-%m-%d %H:%M:%S") if 'gdd_since_budbreak' in kwargs: gdd_since_budbreak = kwargs['gdd_since_budbreak'] elif min(meteo_tab.index) <= budbreak_date: tdays = date_range(budbreak_date, sdate, freq='D') tmeteo = meteo_tab.loc[tdays, :].Tac.to_frame() tmeteo = tmeteo.set_index(DatetimeIndex(tmeteo.index).normalize()) df_min = tmeteo.groupby(tmeteo.index).aggregate(np.min).Tac df_max = tmeteo.groupby(tmeteo.index).aggregate(np.max).Tac # df_tt = merge(df_max, df_min, how='inner', left_index=True, right_index=True) # df_tt.columns = ('max', 'min') # df_tt['gdd'] = df_tt.apply(lambda x: 0.5 * (x['max'] + x['min']) - t_base) # gdd_since_budbreak = df_tt['gdd'].cumsum()[-1] df_tt = 0.5 * (df_min + df_max) - t_base gdd_since_budbreak = df_tt.cumsum()[-1] else: raise ValueError('Cumulative degree-days temperature is not provided.') print('GDD since budbreak = %d °Cd' % gdd_since_budbreak) # Determination of perennial structure arms (for grapevine) # arm_vid = {g.node(vid).label: g.node(vid).components()[0]._vid for vid in g.VtxList(Scale=2) if # g.node(vid).label.startswith('arm')} # Soil reservoir dimensions (inter row, intra row, depth) [m] soil_dimensions = params.soil.soil_dimensions soil_total_volume = soil_dimensions[0] * soil_dimensions[1] * soil_dimensions[2] rhyzo_coeff = params.soil.rhyzo_coeff rhyzo_total_volume = rhyzo_coeff * np.pi * min(soil_dimensions[:2]) ** 2 / 4. * soil_dimensions[2] # Counter clockwise angle between the default X-axis direction (South) and # the real direction of X-axis. scene_rotation = params.irradiance.scene_rotation # Sky and cloud temperature [degreeC] t_sky = params.energy.t_sky t_cloud = params.energy.t_cloud # Topological location latitude = params.simulation.latitude longitude = params.simulation.longitude elevation = params.simulation.elevation geo_location = (latitude, longitude, elevation) # Pattern ymax, xmax = map(lambda dim: dim / length_conv, soil_dimensions[:2]) pattern = ((-xmax / 2.0, -ymax / 2.0), (xmax / 2.0, ymax / 2.0)) # Label prefix of the collar internode vtx_label = params.mtg_api.collar_label # Label prefix of the leaves leaf_lbl_prefix = params.mtg_api.leaf_lbl_prefix # Label prefices of stem elements stem_lbl_prefix = params.mtg_api.stem_lbl_prefix E_type = params.irradiance.E_type tzone = params.simulation.tzone turtle_sectors = params.irradiance.turtle_sectors icosphere_level = params.irradiance.icosphere_level turtle_format = params.irradiance.turtle_format energy_budget = params.simulation.energy_budget print('Energy_budget: %s' % energy_budget) # Optical properties opt_prop = params.irradiance.opt_prop print('Hydraulic structure: %s' % params.simulation.hydraulic_structure) psi_min = params.hydraulic.psi_min # Parameters of leaf Nitrogen content-related models Na_dict = params.exchange.Na_dict # Computation of the form factor matrix form_factors = None if energy_budget: print('Computing form factors...') form_factors = energy.form_factors_simplified( g, pattern=pattern, infinite=True, leaf_lbl_prefix=leaf_lbl_prefix, turtle_sectors=turtle_sectors, icosphere_level=icosphere_level, unit_scene_length=unit_scene_length) # Soil class soil_class = params.soil.soil_class print('Soil class: %s' % soil_class) # Rhyzosphere concentric radii determination rhyzo_radii = params.soil.rhyzo_radii rhyzo_number = len(rhyzo_radii) # Add rhyzosphere elements to mtg rhyzo_solution = params.soil.rhyzo_solution print('rhyzo_solution: %s' % rhyzo_solution) if rhyzo_solution: if not any(item.startswith('rhyzo') for item in g.property('label').values()): vid_collar = architecture.mtg_base(g, vtx_label=vtx_label) vid_base = architecture.add_soil_components(g, rhyzo_number, rhyzo_radii, soil_dimensions, soil_class, vtx_label) else: vid_collar = g.node(g.root).vid_collar vid_base = g.node(g.root).vid_base radius_prev = 0. for ivid, vid in enumerate(g.Ancestors(vid_collar)[1:]): radius = rhyzo_radii[ivid] g.node(vid).Length = radius - radius_prev g.node(vid).depth = soil_dimensions[2] / length_conv # [m] g.node(vid).TopDiameter = radius * 2. g.node(vid).BotDiameter = radius * 2. g.node(vid).soil_class = soil_class radius_prev = radius else: # Identifying and attaching the base node of a single MTG vid_collar = architecture.mtg_base(g, vtx_label=vtx_label) vid_base = vid_collar g.node(g.root).vid_base = vid_base g.node(g.root).vid_collar = vid_collar # Initializing sapflow to 0 for vtx_id in traversal.pre_order2(g, vid_base): g.node(vtx_id).Flux = 0. # Addition of a soil element if 'Soil' not in g.properties()['label'].values(): if 'soil_size' in kwargs: if kwargs['soil_size'] > 0.: architecture.add_soil(g, kwargs['soil_size']) else: architecture.add_soil(g, 500.) # Suppression of undesired geometry for light and energy calculations geom_prop = g.properties()['geometry'] vidkeys = [] for vid in g.properties()['geometry']: n = g.node(vid) if not n.label.startswith(('L', 'other', 'soil')): vidkeys.append(vid) [geom_prop.pop(x) for x in vidkeys] g.properties()['geometry'] = geom_prop # Attaching optical properties to MTG elements g = irradiance.optical_prop(g, leaf_lbl_prefix=leaf_lbl_prefix, stem_lbl_prefix=stem_lbl_prefix, wave_band='SW', opt_prop=opt_prop) # Estimation of Nitroen surface-based content according to Prieto et al. (2012) # Estimation of intercepted irradiance over past 10 days: if not 'Na' in g.property_names(): print('Computing Nitrogen profile...') assert (sdate - min( meteo_tab.index)).days >= 10, 'Meteorological data do not cover 10 days prior to simulation date.' ppfd10_date = sdate + timedelta(days=-10) ppfd10t = date_range(ppfd10_date, sdate, freq='H') ppfd10_meteo = meteo_tab.loc[ppfd10t, :] caribu_source, RdRsH_ratio = irradiance.irradiance_distribution(ppfd10_meteo, geo_location, E_type, tzone, turtle_sectors, turtle_format, None, scene_rotation, None) # Compute irradiance interception and absorbtion g, caribu_scene = irradiance.hsCaribu(mtg=g, unit_scene_length=unit_scene_length, source=caribu_source, direct=False, infinite=True, nz=50, ds=0.5, pattern=pattern) g.properties()['Ei10'] = {vid: g.node(vid).Ei * time_conv / 10. / 1.e6 for vid in g.property('Ei').keys()} # Estimation of leaf surface-based nitrogen content: for vid in g.VtxList(Scale=3): if g.node(vid).label.startswith(leaf_lbl_prefix): g.node(vid).Na = exchange.leaf_Na(gdd_since_budbreak, g.node(vid).Ei10, Na_dict['aN'], Na_dict['bN'], Na_dict['aM'], Na_dict['bM']) # Define path to folder output_path = wd + 'output' + output_index + '/' # Save geometry in an external file # HSArc.mtg_save_geometry(scene, output_path) # ============================================================================== # Simulations # ============================================================================== sapflow = [] # sapEast = [] # sapWest = [] an_ls = [] rg_ls = [] psi_stem = {} Tlc_dict = {} Ei_dict = {} an_dict = {} gs_dict = {} # The time loop +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ for date in meteo.time: print("=" * 72) print('Date', date, '\n') # Select of meteo data imeteo = meteo[meteo.time == date] # Add a date index to g g.date = datetime.strftime(date, "%Y%m%d%H%M%S") # Read soil water potntial at midnight if 'psi_soil' in kwargs: psi_soil = kwargs['psi_soil'] else: if date.hour == 0: try: psi_soil_init = psi_pd.loc[date, :][0] psi_soil = psi_soil_init except KeyError: pass # Estimate soil water potntial evolution due to transpiration else: psi_soil = hydraulic.soil_water_potential(psi_soil, g.node(vid_collar).Flux * time_conv, soil_class, soil_total_volume, psi_min) if 'sun2scene' not in kwargs or not kwargs['sun2scene']: sun2scene = None elif kwargs['sun2scene']: sun2scene = display.visu(g, def_elmnt_color_dict=True, scene=Scene()) # Compute irradiance distribution over the scene caribu_source, RdRsH_ratio = irradiance.irradiance_distribution(imeteo, geo_location, E_type, tzone, turtle_sectors, turtle_format, sun2scene, scene_rotation, None) # Compute irradiance interception and absorbtion g, caribu_scene = irradiance.hsCaribu(mtg=g, unit_scene_length=unit_scene_length, source=caribu_source, direct=False, infinite=True, nz=50, ds=0.5, pattern=pattern) # g.properties()['Ei'] = {vid: 1.2 * g.node(vid).Ei for vid in g.property('Ei').keys()} # Trace intercepted irradiance on each time step rg_ls.append(sum([g.node(vid).Ei / (0.48 * 4.6) * surface(g.node(vid).geometry) * (length_conv ** 2) \ for vid in g.property('geometry') if g.node(vid).label.startswith('L')])) # Hack forcing of soil temperture (model of soil temperature under development) t_soil = energy.forced_soil_temperature(imeteo) # Climatic data for energy balance module # TODO: Change the t_sky_eff formula (cf. Gliah et al., 2011, Heat and Mass Transfer, DOI: 10.1007/s00231-011-0780-1) t_sky_eff = RdRsH_ratio * t_cloud + (1 - RdRsH_ratio) * t_sky solver.solve_interactions(g, imeteo, psi_soil, t_soil, t_sky_eff, vid_collar, vid_base, length_conv, time_conv, rhyzo_total_volume, params, form_factors) # Write mtg to an external file if scene is not None: architecture.mtg_save(g, scene, output_path) # Plot stuff.. sapflow.append(g.node(vid_collar).Flux) # sapEast.append(g.node(arm_vid['arm1']).Flux) # sapWest.append(g.node(arm_vid['arm2']).Flux) an_ls.append(g.node(vid_collar).FluxC) psi_stem[date] = deepcopy(g.property('psi_head')) Tlc_dict[date] = deepcopy(g.property('Tlc')) Ei_dict[date] = deepcopy(g.property('Eabs')) an_dict[date] = deepcopy(g.property('An')) gs_dict[date] = deepcopy(g.property('gs')) print('---------------------------') print('psi_soil', round(psi_soil, 4)) print('psi_collar', round(g.node(3).psi_head, 4)) print('psi_leaf', round(np.median([g.node(vid).psi_head for vid in g.property('gs').keys()]), 4)) print('') # print('Rdiff/Rglob ', RdRsH_ratio) # print('t_sky_eff ', t_sky_eff) print('gs', np.median(list(g.property('gs').values()))) print('flux H2O', round(g.node(vid_collar).Flux * 1000. * time_conv, 4)) print('flux C2O', round(g.node(vid_collar).FluxC, 4)) print('Tleaf ', round(np.median([g.node(vid).Tlc for vid in g.property('gs').keys()]), 2), 'Tair ', round(imeteo.Tac[0], 4)) print('') print("=" * 72) # End time loop +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Write output # Plant total transpiration sapflow = [flow * time_conv * 1000. for flow in sapflow] # sapEast, sapWest = [np.array(flow) * time_conv * 1000. for i, flow in enumerate((sapEast, sapWest))] # Median leaf temperature t_ls = [np.median(list(Tlc_dict[date].values())) for date in meteo.time] # Intercepted global radiation rg_ls = np.array(rg_ls) / (soil_dimensions[0] * soil_dimensions[1]) results_dict = { 'Rg': rg_ls, 'An': an_ls, 'E': sapflow, # 'sapEast': sapEast, # 'sapWest': sapWest, 'Tleaf': t_ls } # Results DataFrame results_df = DataFrame(results_dict, index=meteo.time) # Write if write_result: results_df.to_csv(output_path + 'time_series.output', sep=';', decimal='.') time_off = datetime.now() print("") print("beg time", time_on) print("end time", time_off) print("--- Total runtime: %d minute(s) ---" % int((time_off - time_on).seconds / 60.)) return results_df
def build_scene(mtg, position=(0, 0, 0), orientation=0, leaf_material=None, stem_material=None, soil_material=None, colors=None): """ Returns a plantgl scene from an mtg. """ if not isinstance(mtg, list): mtg = [mtg] if not isinstance(position, list): position = [position] if not isinstance(orientation, list): orientation = [orientation] if colors is None: if leaf_material is None: leaf_material = Material(Color3(0, 180, 0)) if stem_material is None: stem_material = Material(Color3(0, 130, 0)) if soil_material is None: soil_material = Material(Color3(170, 85, 0)) # colors = g.property('color') scene = Scene() def geom2shape(vid, mesh, scene, colors, position, orientation, shape_id=None): shape = None if shape_id is None: shape_id = vid if isinstance(mesh, list): for m in mesh: geom2shape(vid, m, scene, colors, position, orientation) return if mesh is None: return if isinstance(mesh, Shape): shape = mesh mesh = mesh.geometry label = labels.get(vid) is_green = greeness.get(vid) mesh = Translated(position, AxisRotated((0, 0, 1), orientation, mesh)) if colors: shape = Shape(mesh, Material(Color3(*colors.get(vid, [0, 0, 0])))) elif not greeness: if not shape: shape = Shape(mesh) elif label.startswith('Stem') and is_green: shape = Shape(mesh, stem_material) elif label.startswith('Leaf') and is_green: shape = Shape(mesh, leaf_material) elif not is_green: shape = Shape(mesh, soil_material) shape.id = shape_id scene.add(shape) nump = [] count = 0 for i, (g, p, o) in enumerate(zip(cycle(mtg), position, cycle(orientation))): geometries = g.property('geometry') greeness = g.property('is_green') labels = g.property('label') for vid, mesh in geometries.items(): geom2shape(vid, mesh, scene, colors, p, o, vid + count) nump.append(i) count += len(g) return scene, nump
def plot(g): return Scene(g.property('geometry').values())
def py_Linetree2Scene(lt, scale="Micro"): id = Extract(lt, SceneId=scale) if id == 0: return None return Scene(Scene.pool().get(id))
def run(self, exp_id, batch_dir): for date, experiment in self.lpk_files.iteritems(): ##experiment[str(exp_id)] is the name (including directory) of the ##corresponding mtg file #mtgp = Mtg_Processing(experiment[str(exp_id)]) #lstring = mtgp.crt_pseudo_lstring() pl = open(experiment[str(exp_id)]) lstring = cPickle.load(pl) pl.close() fbr_id_add = 100000000 unit_id_add = 1000000 id_dicts = [{}, {}, {}] print len(lstring) for i in range(len(lstring)): if lstring[i][0].parent_tree_id == 0: new_fbr_id = lstring[i][0].parent_fbr_id + fbr_id_add new_unit_id = lstring[i][0].parent_unit_id + unit_id_add #If this element has not been processed yet #Note that id_dicts[2] is a list, so do not use # i not in id_dicts[2].values #ALSO: the selected metamer should have a leaf! #OTHERWISE it could cause errors when using envelope if i not in id_dicts[2] and lstring[i][0].leaf_area > 0: ##If the growth unit is a floral one, then consider ##it as part of the one before it #if lstring[i][0].parent_observation == "floral": # new_unit_id -= 1 #If the new_unit_id has already been there if new_unit_id in id_dicts[2].keys(): #Then only add the metamer id id_dicts[2][new_unit_id].append(i) #If the new_unit_id is not there else: id_dicts[2].update({new_unit_id: [i]}) #If the new_fbr_id has already been there if new_fbr_id in id_dicts[1].keys(): #Then only add the new_unit_id id_dicts[1][new_fbr_id].append(new_unit_id) else: id_dicts[1].update({new_fbr_id: [new_unit_id]}) #If the tree has been there already if lstring[i][0].parent_tree_id in id_dicts[ 0].keys(): #Then only add the new_fbr_id id_dicts[0][0].append(new_fbr_id) else: id_dicts[0].update({0: [new_fbr_id]}) else: continue else: continue #This is the remove the cases where one growth #unit only has one leaf for k in id_dicts[2].keys(): if len(id_dicts[2][k]) <= 1: print k id_dicts[2].pop(k) for t in id_dicts[1].keys(): if k in id_dicts[1][t]: id_dicts[1][t].remove(k) if len(id_dicts[1][t]) == 0: id_dicts[1].pop(t) for r in id_dicts[0].keys(): if t in id_dicts[0][r]: id_dicts[0][r].remove(t) if len(id_dicts[0][r]) == 0: id_dicts[0].pop(r) print "-----------------------------------------------------" idd_pk = open(batch_dir + str(exp_id) + "_" + date + "_" + ".idpk", "w") cPickle.dump(id_dicts, idd_pk, 0) idd_pk.close() idd_print = open( batch_dir + str(exp_id) + "_" + date + "_" + ".txt", "w") for d in id_dicts: for k, v in d.iteritems(): idd_print.write("{0}------{1}\n\n".format(k, v)) idd_print.write("####################\n\n") idd_print.close() scene = self.bgeom_files[date][str(exp_id)] sc = Scene(scene) experiment_date = time.strftime( "%d/%m/%Y %I:%M:%S", time.localtime( os.path.getmtime(self.bgeom_files[date][str(exp_id)]))) IntegratedMultiScaleStar(str(exp_id), sc, id_dicts, growth_date=date, distrib=[['R', 'R', 'R'], ['A', 'R', 'R'], ['A', 'A', 'R'], ['A', 'A', 'A']], save_pth=batch_dir, eid=exp_id) #nn is the new name for the package with envelope scenes and nn = str(exp_id) + "_" + date os.rename(str(exp_id), nn) #id_dict = mtgp.crt_envdic() print "###########################" gc.collect() gc.collect()
def make_thumbnail(): from .thumbnailmaker import make_thumbnail from openalea.plantgl.all import Scene return make_thumbnail(Scene([self.mtgeditor.points]), (256, 256))
g = xml2mtg(fn) gs.append(g) # Compute Color lut = {} lut[0] = (255, 110,50) lut[1] = (0,255,0) lut[2] = (0,0,255) for g in gs: ct = g.property('LGAtype') _colors = dict((v, lut.get(int(x),(0,127,127))) for v, x in ct.iteritems()) g.properties()['color'] = _colors labels = g.property('label') for v, label in labels.iteritems(): if label == 'Bud': _colors[v] = _colors[g.parent(v)] # Compute scenes scenes = [] i= 0 for g in gs: scene = lignum_turtle(g, has_color=True) scenes.append(scene) # Merge scenes scene = Scene() for sc in scenes: scene.merge(sc)
def py_Linetree2Scene(lt,scale = 'Micro'): id = Extract(lt,SceneId=scale) if id == 0: return None return Scene(Scene.pool().get(id))
for distance in distances: fs = fsm.determine_fruiting_structure(mtg, cycle=cycle, fruit_distance=distance) print() print('Nb of groups', len(fs)) #lfr = leaf_fruit_ratio(mtg, fs) #print [l/float(f) for l,f in lfr] #print np.mean([l/float(f) for l,f in lfr]) nbgus = [len(gus) for inflos, gus in fs] #print nbgus print(np.mean(nbgus), np.std(nbgus)) radii = [max([params[gu].radius for gu in gus]) for inflos, gus in fs] #print radii print(np.mean(radii), np.std(radii)) #fs = applymodel(mtg, 3, int(sys.argv[1]) if len(sys.argv) > 1 else 3) colorrepresentation = False if colorrepresentation: sc = Scene('structure-cycle' + str(cycle) + ('b' if lowres else '') + '.bgeom') print('Start coloring') nsc = color_structures(fs, mtg, sc) print('End coloring') nsc.save('structure-cycle' + str(cycle) + '-dist' + str(distance) + '.bgeom') #Viewer.display(nsc) nsc.save('structure-cycle' + str(cycle) + '-dist' + str(distance) + '-core.pov')