def test_materials(): can = data_path('filterT.can') cscene = read_can(can) path = data_path('par.opt') n, s, opts = read_opt(path) materials = build_materials(cscene.keys(), opts, s) assert len(materials) == len(cscene) assert materials[materials.keys()[0]] == (0.1, 0.05) return materials
def test_opt(): path = data_path('par.opt') n, s, opts = read_opt(path) assert n == 2 assert s == 0.15 assert opts[1] == (0.1, 0.1, 0.05, 0.1, 0.05) return n, s, opts
def run_caribu(sources, scene, opticals='stem', optical_properties=None, output_by_triangle=False, domain=None, zsoil=None): """ Calls Caribu for differents energy sources :Parameters: ------------ - `sources` (int) - `scene` : any scene format accepted by CaribuScene. This will be cast to a list of plantGL shapes - opticals : a list of optical property labels ('leaf', 'soil', 'stem', 'ear' or 'awn') for all shapes in scene. If a shorter opticale list is provided, it will be recycled to match eength of shape list - `optical_properties`: a filename (*.opt). - `output_by_triangle` (bool) Default 'False'. Return is done by id of geometry. If 'True', return is done by triangle. :Returns: --------- - 'out_moy' (dict) A dict of intercepted variable (energy) per id - 'out_tri' (dict) only if output_by_triangle = True, return a tuple (out_moy, out_tri) A dict of intercepted variable (energy) per triangle """ raise DeprecationWarning('This function is deprecated, use CaribuScene / caribu_star instead') from alinea.caribu.label import simple_canlabel from alinea.caribu.file_adaptor import read_opt, build_materials n, soil_reflectance, po = read_opt(optical_properties) if not isinstance(opticals, list): opticals = [opticals] if len(opticals) < len(scene): opticals = opticals * (len(scene) / len(opticals)) + [opticals[i] for i in range(len(scene) % len(opticals))] labels = [simple_canlabel(opt) for opt in opticals] materials = build_materials(labels, po, soil_reflectance) band = CaribuScene.default_band c_scene = CaribuScene(scene=scene, light=sources, pattern=domain, opt={band: materials}, soil_reflectance={band: soil_reflectance}) ifty = False if domain is not None: ifty = True # if zsoil is not None: # idmap_soil = c_scene.addSoil(zsoil=zsoil) # idmap.update(idmap_soil) raw, aggregated = c_scene.run(direct=True, infinite=ifty, simplify=True) if output_by_triangle: out = raw else: out = aggregated return out
def __init__(self, scene=None, light=None, pattern=None, opt=None, soil_reflectance=None, soil_mesh=None, z_soil=None, scene_unit='m'): """ Initialise a CaribuScene Args: scene (dict): a {primitive_id: [triangles,]} dict.A triangle is a list of 3-tuples points coordinates Alternatively, scene can be a *.can file or a mtg with 'geometry' property or a plantGL scene. For the later case, shape.id are used as primitive_id. light (list): a list of (Energy, (vx, vy, vz)) tuples defining light sources Alternatively, a *.light file If None (default), a unit energy vertical light is used. Energy unit should be given per square-meter (m-2) pattern (tuple): 2D Coordinates of the domain bounding the scene for its replication. (xmin, ymin, xmax, ymax) scene is not bounded along z axis. Alternatively a *.8 file. if None (default), scene is not repeated opt (dict): a {band_name: {primitive_id: material}} dict of dict or a {band_name: material} dict of tuples. In the second form the material is used for all primitives. A material is a 1-, 2- or 4-tuple depending on its optical behavior. A 1-tuple encode an opaque material characterised by its reflectance A 2-tuple encode a symmetric translucent material defined by a reflectance and a transmittance A 4-tuple encode an asymmetric translucent material defined the reflectance and transmittance of the upper and lower side respectively Alternatively, a list of band_name.opt files (require scene to be given as a *.can file) If None (default), all primitive are associated to the default material of the class. soil_reflectance (dict): a {band_name: reflectance} dict. If None (default) class default soil reflectance is used for all bands If *.opt files are provided, the values in opt files are used in priority soil_mesh (int): a flag triggering for the creation of a soil mesh in the scene during computations If None (default) or -1, no soil is added If an int (n), a soil is added to the scene, with n subdivisions z_soil (float): the altitude of the soil. If None (default), the soil is placed at the bottom of the scene bounding box scene_unit (str): the unit of length used for scene coordinate and for pattern (should be one of class.units default) By default, scene_unit is considered to be 'm' (meter). Returns: A CaribuScene instance Note: File format specifications (*.can, *.light, *.8, *.opt) can be found in data/CanestraDoc.pdf """ if scene_unit not in self.units: raise ValueError('unrecognised scene unit: ' + scene_unit) self.conv_unit = self.units[scene_unit] self.scene = None if scene is not None: if isinstance(scene, dict): elt = scene[scene.keys()[0]] try: assert isinstance(elt, list) assert isinstance(elt[0], list) assert isinstance(elt[0][0], tuple) except: raise ValueError('Unrecognised scene format') self.scene = scene elif isinstance(scene, str): self.scene = read_can(scene) elif isinstance(scene, MTG): self.scene = mtg_to_cscene(scene) elif isinstance(scene, pglScene): self.scene = scene_to_cscene(scene) else: raise ValueError('Unrecognised scene format') self.light = [self.default_light] if light is not None: if isinstance(light, list): elt = light[0] try: assert isinstance(elt, tuple) assert isinstance(elt[1], tuple) except: raise ValueError('Unrecognised light format') self.light = light elif isinstance(light, str): self.light = read_light(light) else: raise ValueError('Unrecognised light format') self.pattern = None if pattern is not None: if isinstance(pattern, tuple): if len(pattern) == 2: pattern = sum(pattern, ()) if len(pattern) != 4: raise ValueError('Unrecognised pattern format') self.pattern = pattern elif isinstance(pattern, str): self.pattern = read_pattern(pattern) else: raise ValueError('Unrecognised pattern format') self.material = None if opt is None: if soil_reflectance is None: self.soil_reflectance = { self.default_band: self.default_soil_reflectance} bands = [self.default_band] else: self.soil_reflectance = soil_reflectance bands = soil_reflectance.keys() if self.scene is not None: self.material = {} for band in bands: self.material[band] = {pid: self.default_material for pid in self.scene} else: if isinstance(opt, list): if not isinstance(opt[0], str): raise ValueError('Unrecognised opt format') if not isinstance(scene, str): raise ValueError( 'un-compatible inputs types: opt file and scene not a can file') if self.scene is not None: self.material = {} self.soil_reflectance = {} for path in opt: band = os.path.basename(path).split('.')[0] n, ro_soil, po = read_opt(path) self.material[band] = build_materials(self.scene.keys(), po, ro_soil) self.soil_reflectance[band] = ro_soil elif isinstance(opt, dict): elt = opt[opt.keys()[0]] if not isinstance(elt, dict): if isinstance(elt, tuple): self.material = {} if self.scene is not None: for band in opt: self.material[band] = {pid: opt[band] for pid in self.scene} else: raise ValueError('Unrecognised opt format') else: self.material = opt if soil_reflectance is None: self.soil_reflectance = {band: self.default_soil_reflectance for band in self.material} else: if isinstance(soil_reflectance, dict): if not len(soil_reflectance) == len(opt): raise ValueError( 'the number of bands for optical properties and soil reflectance should match') self.soil_reflectance = soil_reflectance else: raise ValueError('Unrecognised soil_reflectance format') else: raise ValueError('Unrecognised opt format') self.soil = None if soil_mesh is not None: if soil_mesh != -1: if self.pattern is None: raise ValueError( 'Adding a soil needs the scene domain to be defined') if z_soil is None: if self.scene is None: z_soil = 0 else: triangles = reduce(lambda x, y: x + y, self.scene.values()) z = (pt[2] for tri in triangles for pt in tri) z_soil = min(z) self.soil = domain_mesh(self.pattern, z_soil, soil_mesh)
def __init__(self, scene=None, light=None, pattern=None, opt=None, soil_reflectance=None, soil_mesh=None, z_soil=None, scene_unit='m', debug=False, filecache=True): """ Initialise a CaribuScene Args: scene (dict): a {primitive_id: [triangles,]} dict.A triangle is a list of 3-tuples points coordinates Alternatively, scene can be a *.can file or a mtg with 'geometry' property or a plantGL scene. For the later case, shape.id are used as primitive_id. light (list): a list of (Energy, (vx, vy, vz)) tuples defining light sources Alternatively, a *.light file If None (default), a unit energy vertical light is used. Energy unit should be given per square-meter (m-2) pattern (tuple): 2D Coordinates of the domain bounding the scene for its replication. (xmin, ymin, xmax, ymax) scene is not bounded along z axis. Alternatively a *.8 file. if None (default), scene is not repeated opt (dict): a {band_name: {primitive_id: material}} dict of dict or a {band_name: material} dict of tuples. In the second form the material is used for all primitives. A material is a 1-, 2- or 4-tuple depending on its optical behavior. A 1-tuple encode an opaque material characterised by its reflectance A 2-tuple encode a symmetric translucent material defined by a reflectance and a transmittance A 4-tuple encode an asymmetric translucent material defined the reflectance and transmittance of the upper and lower side respectively Alternatively, a list of band_name.opt files (require scene to be given as a *.can file) If None (default), all primitive are associated to the default material of the class. soil_reflectance (dict): a {band_name: reflectance} dict. If None (default) class default soil reflectance is used for all bands If *.opt files are provided, the values in opt files are used in priority soil_mesh (int): a flag triggering for the creation of a soil mesh in the scene during computations If None (default) or -1, no soil is added If an int (n), a soil is added to the scene, with n subdivisions z_soil (float): the altitude of the soil. If None (default), the soil is placed at the bottom of the scene bounding box scene_unit (str): the unit of length used for scene coordinate and for pattern (should be one of class.units default) By default, scene_unit is considered to be 'm' (meter). Returns: A CaribuScene instance Note: File format specifications (*.can, *.light, *.8, *.opt) can be found in data/CanestraDoc.pdf """ self.debug = debug if scene_unit not in self.units: raise ValueError('unrecognised scene unit: ' + scene_unit) self.conv_unit = self.units[scene_unit] self.scene = None if scene is not None: if isinstance(scene, dict): elt = scene[list(scene.keys())[0]] try: assert isinstance(elt, list) assert isinstance(elt[0], list) assert isinstance(elt[0][0], tuple) except: raise ValueError('Unrecognised scene format') self.scene = CaribuTriangleSet(scene) elif isinstance(scene, str): self.scene = CaribuTriangleSet(read_can(scene)) elif isinstance(scene, MTG): self.scene = CaribuTriangleSet(mtg_to_cscene(scene)) elif isinstance(scene, pglScene): self.scene = CaribuTriangleSet(scene_to_cscene(scene)) elif isinstance(scene, AbstractCaribuTriangleSet): self.scene = scene else: raise ValueError('Unrecognised scene format') self.light = [self.default_light] if light is not None: self.setLight(light) self.pattern = None if pattern is not None: if isinstance(pattern, tuple): if len(pattern) == 2: pattern = sum(pattern, ()) if len(pattern) != 4: raise ValueError('Unrecognised pattern format') self.pattern = pattern elif isinstance(pattern, str): self.pattern = read_pattern(pattern) else: raise ValueError('Unrecognised pattern format') self.material = None if opt is None: if soil_reflectance is None: self.soil_reflectance = { self.default_band: self.default_soil_reflectance } bands = [self.default_band] else: self.soil_reflectance = soil_reflectance bands = list(soil_reflectance.keys()) if self.scene is not None: self.material = {} for band in bands: self.material[band] = { pid: self.default_material for pid in self.scene.keys() } else: if isinstance(opt, list): if not isinstance(opt[0], str): raise ValueError('Unrecognised opt format') if not isinstance(scene, str): raise ValueError( 'un-compatible inputs types: opt file and scene not a can file' ) if self.scene is not None: self.material = {} self.soil_reflectance = {} for path in opt: band = os.path.basename(path).split('.')[0] n, ro_soil, po = read_opt(path) self.material[band] = build_materials( list(self.scene.keys()), po, ro_soil) self.soil_reflectance[band] = ro_soil elif isinstance(opt, dict): elt = opt[list(opt.keys())[0]] if not isinstance(elt, dict): if isinstance(elt, tuple): self.material = {} if self.scene is not None: for band in opt: self.material[band] = { pid: opt[band] for pid in self.scene.keys() } else: raise ValueError('Unrecognised opt format') else: self.material = opt if soil_reflectance is None: self.soil_reflectance = { band: self.default_soil_reflectance for band in self.material } else: if isinstance(soil_reflectance, dict): if not len(soil_reflectance) == len(opt): raise ValueError( 'the number of bands for optical properties and soil reflectance should match' ) self.soil_reflectance = soil_reflectance else: raise ValueError( 'Unrecognised soil_reflectance format') else: raise ValueError('Unrecognised opt format') self.soil = None if soil_mesh is not None: if soil_mesh != -1: if self.pattern is None: raise ValueError( 'Adding a soil needs the scene domain to be defined') if z_soil is None: if self.scene is None: z_soil = 0 else: z_soil = self.scene.getZmin() self.soil = domain_mesh(self.pattern, z_soil, soil_mesh) self.tempdir = None if filecache: self.tempdir = tempfile.mkdtemp( ) if not debug else './caribuscene_' + str(id(self)) self.canfile = None self.optfile = None