RuntimeScene

  1# coding: utf-8
  2# This script construct a less scene, which supports the modification of non-structural parameters dynamically
  3import os
  4import sys
  5from importlib import reload
  6import multiprocessing
  7import json
  8import numpy as np
  9from PostProcessing import RasterHelper
 10from Observation import ObservationOrthographic
 11from Terrain import TERRAIN_BRDF_TYPE
 12
 13
 14class RuntimeScene(object):
 15    def __init__(self, simulation):
 16        self.__simulation = simulation
 17        self.less_runtime_scene = None
 18        self.__sim_mode = "devel11"
 19
 20        # load mitsuba
 21        self.__init_mitsuba_path()
 22        globals()["mitsuba"] = __import__("mitsuba")
 23        reload(mitsuba)
 24
 25        self.pmgr = mitsuba.core.PluginManager.getInstance()
 26
 27        # for simulation
 28        self.queue = mitsuba.render.RenderQueue()
 29        # prepare for simulation
 30        self.scheduler = mitsuba.core.Scheduler.getInstance()
 31        # Start up the scheduling system with one worker per local core
 32        min_cores = min(multiprocessing.cpu_count(),
 33                        int(self.__simulation.get_scene().get_advanced_params().number_of_cores))
 34        print("INFO: Using number of cores:", min_cores)
 35        if not self.scheduler.isRunning():
 36            for i in range(0, min_cores):
 37                self.scheduler.registerWorker(mitsuba.core.LocalWorker(i, 'wrk%i' % i))
 38            self.scheduler.start()
 39
 40    def shutdown_simulator(self):
 41        self.queue.join()
 42        self.scheduler.stop()
 43
 44    def __init_mitsuba_path(self):
 45        band_num = self.__simulation.get_scene().get_sensor().get_number_of_bands()
 46        if not os.path.exists(".less"):
 47            os.mkdir(".less")
 48        with open(".less/num.cfg", "w") as f:
 49            f.write(str(band_num))
 50        with open(".less/range.cfg", "w") as f:
 51            f.write("360 830")
 52        pyd_dir = ""
 53        dll_path = ""
 54        currdir = os.path.split(os.path.realpath(__file__))[0]
 55        if currdir.startswith(r"E:\03-Coding\lessrt"):
 56            self.__sim_mode = "devel"
 57        if self.__sim_mode == "devel":
 58            lessrt_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
 59            pyd_dir = os.path.join(lessrt_dir, "python", "lesspy", "bin", "rt", "lessrt", "python", "3.10")
 60            dll_path = os.path.join(lessrt_dir, "python", "lesspy", "bin", "rt", "lessrt")
 61        else:
 62            root_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
 63            pyd_dir = os.path.join(root_dir, "bin", "scripts", "Lesspy", "bin", "rt", "lessrt", "python", "3.10")
 64            dll_path = os.path.join(root_dir, "bin", "scripts", "Lesspy", "bin", "rt", "lessrt")
 65
 66        sys.path.append(pyd_dir)
 67        os.add_dll_directory(dll_path)
 68        # os.environ['PATH'] = dll_path + os.pathsep + os.environ['PATH']
 69
 70    def get_xml_dir(self):
 71        sim_dir = self.__simulation.get_sim_dir()
 72        xml_dir = os.path.join(sim_dir, "Parameters", "_scenefile")
 73        return xml_dir
 74
 75    def load_scene(self, scene_name="main.xml"):
 76        xml_dir = self.get_xml_dir()
 77        fileResolver = mitsuba.core.Thread.getThread().getFileResolver()
 78        logger = mitsuba.core.Thread.getThread().getLogger()
 79        # logger.clearAppenders()
 80        fileResolver.appendPath(str(xml_dir))
 81        self.less_runtime_scene = mitsuba.render.SceneHandler.loadScene(
 82            fileResolver.resolve(os.path.join(xml_dir, scene_name)))
 83        self.less_runtime_scene.configure()
 84        self.less_runtime_scene.initialize()
 85
 86    def update_parameters(self):
 87        cwd = os.getcwd()
 88        sim_dir = sim_dir = self.__simulation.get_sim_dir()
 89        os.chdir(sim_dir)
 90        interpreter = self.__simulation.get_scene_helper().get_py_interpreter_path()
 91        script_lesspy_path = self.__simulation.get_scene_helper().get_script_less_py_path()
 92        os.system(interpreter + " " + script_lesspy_path + " -g v1")
 93        os.chdir(cwd)
 94
 95        xml_dir = self.get_xml_dir()
 96        fileResolver = mitsuba.core.Thread.getThread().getFileResolver()
 97        logger = mitsuba.core.Thread.getThread().getLogger()
 98        # logger.clearAppenders()
 99        fileResolver.appendPath(str(xml_dir))
100        tmp_scene = mitsuba.render.SceneHandler.loadScene(
101            fileResolver.resolve(os.path.join(xml_dir, "tmp_main.xml")))
102        tmp_scene.configure()
103
104        # update sensor
105        new_sensor = tmp_scene.getSensor()
106        self.less_runtime_scene.addSensor(new_sensor)
107        self.less_runtime_scene.setSensor(new_sensor)
108        # directly create sensor from properties is not possible from python because the properties are not complete
109        # new_sensor_props = tmp_scene.getSensor().getProperties()
110        # tmp_sensor = self.pmgr.createObject(new_sensor_props)
111        # tmp_film = self.pmgr.createObject(tmp_scene.getFilm().getProperties())
112        # tmp_film.configure()
113        # tmp_sensor.addChild(tmp_film)
114        # tmp_sensor.configure()
115        # self.less_runtime_scene.addSensor(tmp_sensor)
116        # self.less_runtime_scene.setSensor(tmp_sensor)
117        # self.less_runtime_scene.setSampler(tmp_scene.getSampler())
118
119        # update illumination
120        for emitter in self.less_runtime_scene.getEmitters():
121            self.less_runtime_scene.removeEmitter(emitter)
122        emitters = tmp_scene.getEmitters()
123        for emitter in emitters:
124            self.less_runtime_scene.addChild(emitter)
125
126        # update BSDF
127        # update terrain BRDF
128        landscape = self.__simulation.get_scene().get_landscape()
129        if landscape.get_terrain().get_terr_brdf_type() != TERRAIN_BRDF_TYPE.LAMBERTIAN:
130            print("INFO: Only Lambertian supports runtime modification of scene properties currently, If"
131                  "you want to use other BRDF types, plase contact [email protected]")
132            sys.exit(0)
133        terrain_op_name = landscape.get_terrain().get_optical()
134        terrain_ref = landscape.get_op_item(terrain_op_name).get_op_front_reflectance()
135        soil_op_obj = self.__create_terrain_bsdf(terrain_ref)
136        for shape in self.less_runtime_scene.getShapes():
137            if shape.getID() == "terrain":
138                shape.setBSDF(soil_op_obj)
139                break
140
141        ## update op
142        sgroups = landscape.get_objects()
143        group_names = list(sgroups.keys())
144        modified_phases = []
145        for ins_shape in self.less_runtime_scene.getShapes():
146            if ins_shape.getID() != "terrain":
147                shape_group_id = ins_shape.getShapeGroup().getID()
148                if shape_group_id in group_names:
149                    mesh_shapes = ins_shape.getShapeGroup().getKDTree().getShapes()
150                    values = list(sgroups[shape_group_id].values())
151                    idx = 0
152                    for mesh_shape in mesh_shapes:
153                        op_name = values[idx]["op_name"]
154                        is_turbid = values[idx]["is_turbid"]
155                        lad = values[idx]["lad"]
156                        op_item = landscape.get_op_item(op_name)
157                        if not is_turbid:
158                            mix_bsdf = self.__create_mixture_bsdf(op_item.get_op_front_reflectance(),
159                                                                  op_item.get_op_back_reflectance(),
160                                                                  op_item.get_op_transmittance())
161                            mesh_shape.addChild(mix_bsdf)
162                        else:  # turbid medium: modifying phase function and configure medium
163                            inter_medium = mesh_shape.getInteriorMedium()
164                            leaf_density = values[idx]["leaf_density"]
165                            hotspot_factor = values[idx]["hotspot_factor"]
166                            optical_lad = op_name + "_" + lad
167                            if optical_lad not in modified_phases:  # 当前组分所使用的phase function如果没更新,则更新
168                                modified_phases.append(optical_lad)
169                                phase_function = inter_medium.getPhaseFunction()
170                                phase_function.isConfigured = False  # reset the configuration to recompute phase values
171                                phase_function.frontRef = mitsuba.core.Spectrum(op_item.get_op_front_reflectance())
172                                phase_function.backRef = mitsuba.core.Spectrum(op_item.get_op_back_reflectance())
173                                phase_function.transmittance = mitsuba.core.Spectrum(op_item.get_op_transmittance())
174                                phase_function.opticalName = op_name
175                                phase_function.ladType = self.__get_lad_type(lad)
176                                phase_function.configure()
177                            inter_medium.ladType = self.__get_lad_type(lad)
178                            inter_medium.leafAreaDensity = leaf_density
179                            inter_medium.hotspotFactor = hotspot_factor
180                            inter_medium.configure()
181                        idx += 1
182                    group_names.remove(shape_group_id)
183                if len(group_names) == 0:
184                    break
185
186    def start(self):
187        job = mitsuba.render.RenderJob('Simulating', self.less_runtime_scene, self.queue)
188        job.start()
189        self.queue.waitLeft(0)
190        self.__post_processing()
191
192    def __create_terrain_bsdf(self, reflectance):
193        bsdf = self.__create_object('diffuse', {'reflectance': mitsuba.core.Spectrum(reflectance)})
194        bsdf.configure()
195        return bsdf
196
197    def __create_object(self, name: str, properties: {}):
198        props = mitsuba.core.Properties(name)
199        for key in properties:
200            props[key] = properties[key]
201        return self.pmgr.createObject(props)
202
203    def __create_mixture_bsdf(self, reflectance_front=0.4, reflectance_back=0.4, transmittance=0.4):
204        mixbsdf = self.__create_object('mixturebsdf', {'ensureEnergyConservation': False, 'weights': '1, 1'})
205        twosidedbsdf = self.__create_object('twosided', {})
206        refbsdf = self.__create_object("diffuse", {'reflectance': mitsuba.core.Spectrum(reflectance_front)})
207        refbsdf.configure()
208        twosidedbsdf.addChild(refbsdf)
209        refbsdf = self.__create_object("diffuse", {'reflectance': mitsuba.core.Spectrum(reflectance_back)})
210        refbsdf.configure()
211        twosidedbsdf.addChild(refbsdf)
212        twosidedbsdf.configure()
213        transbsdf = self.__create_object('difftrans', {'transmittance': mitsuba.core.Spectrum(transmittance)})
214        transbsdf.configure()
215        mixbsdf.addChild(twosidedbsdf)
216        mixbsdf.addChild(transbsdf)
217        mixbsdf.configure()
218        return mixbsdf
219
220    def __get_lad_type(self, lad_str):
221        if lad_str == "Spherical":
222            return mitsuba.render.PhaseFunction.ESpherical
223        if lad_str == "Uniform":
224            return mitsuba.render.PhaseFunction.EUniform
225        if lad_str == "Planophile":
226            return mitsuba.render.PhaseFunction.EPlanophile
227        if lad_str == "Erectophile":
228            return mitsuba.render.PhaseFunction.EErectophile
229        if lad_str == "Plagiophile":
230            return mitsuba.render.PhaseFunction.EPlagiophile
231        if lad_str == "Extremophile":
232            return mitsuba.render.PhaseFunction.EExtremophile
233        return mitsuba.render.ELadType.EINVALIDE
234
235    def __post_processing(self):
236        sim_dir = self.__simulation.get_sim_dir()
237        distFile = self.__simulation.get_dist_file()
238        infofile = os.path.join(sim_dir, "Results", "spectral.txt")
239        f = open(infofile, 'w')
240        f.write(os.path.basename(distFile))
241        f.close()
242
243        cfgfile = os.path.join(sim_dir, "Parameters", "input.conf")
244        f = open(cfgfile, 'r')
245        cfg = json.load(f)
246
247        output_format = "ENVI"
248        if cfg["sensor"]["sensor_type"] == "PhotonTracing":
249            out_file_no_extension = distFile + "_downwelling"
250            output_fileName = distFile + "_downwelling.npy"
251            if output_format not in ("npy", "NPY") and os.path.exists(output_fileName):
252                data = np.load(output_fileName)
253                bandlist = cfg["sensor"]["bands"].split(",")
254                RasterHelper.saveToHdr_no_transform(data, out_file_no_extension, bandlist, output_format)
255                os.remove(output_fileName)
256            out_file_no_extension = distFile + "_upwelling"
257            output_fileName = distFile + "_upwelling.npy"
258            if output_format not in ("npy", "NPY") and os.path.exists(output_fileName):
259                data = np.load(output_fileName)
260                bandlist = cfg["sensor"]["bands"].split(",")
261                RasterHelper.saveToHdr_no_transform(data, out_file_no_extension, bandlist, output_format)
262                os.remove(output_fileName)
263        else:
264            out_file_no_extension = distFile + "_4Components"
265            output_fileName = distFile + "_4Components.npy"
266
267            if output_format not in ("npy", "NPY") and os.path.exists(output_fileName):
268                data = np.load(output_fileName)
269                dshape = data.shape
270                if len(dshape) == 3:
271                    if dshape[2] <= 4:
272                        data = data[:, :, 0]
273                    else:
274                        data = data[:, :, 0:5]
275                bandlist = []
276                RasterHelper.saveToHdr_no_transform(data, out_file_no_extension, bandlist, output_format)
277                os.remove(output_fileName)
278
279            if output_format not in ("npy", "NPY") and os.path.exists(distFile + ".npy"):
280                data = np.load(distFile + ".npy")
281
282                # converte to brightness temperature
283                if cfg["sensor"]["thermal_radiation"]:
284                    bandlist = cfg["sensor"]["bands"].split(",")
285                    data = RasterHelper.convertRadiance2BTimage(data, bandlist)
286
287                bandlist = cfg["sensor"]["bands"].split(",")
288                RasterHelper.saveToHdr_no_transform(data, distFile, bandlist, output_format)
289                os.remove(distFile + ".npy")
290        print("INFO: Finished")
class RuntimeScene:
 15class RuntimeScene(object):
 16    def __init__(self, simulation):
 17        self.__simulation = simulation
 18        self.less_runtime_scene = None
 19        self.__sim_mode = "devel11"
 20
 21        # load mitsuba
 22        self.__init_mitsuba_path()
 23        globals()["mitsuba"] = __import__("mitsuba")
 24        reload(mitsuba)
 25
 26        self.pmgr = mitsuba.core.PluginManager.getInstance()
 27
 28        # for simulation
 29        self.queue = mitsuba.render.RenderQueue()
 30        # prepare for simulation
 31        self.scheduler = mitsuba.core.Scheduler.getInstance()
 32        # Start up the scheduling system with one worker per local core
 33        min_cores = min(multiprocessing.cpu_count(),
 34                        int(self.__simulation.get_scene().get_advanced_params().number_of_cores))
 35        print("INFO: Using number of cores:", min_cores)
 36        if not self.scheduler.isRunning():
 37            for i in range(0, min_cores):
 38                self.scheduler.registerWorker(mitsuba.core.LocalWorker(i, 'wrk%i' % i))
 39            self.scheduler.start()
 40
 41    def shutdown_simulator(self):
 42        self.queue.join()
 43        self.scheduler.stop()
 44
 45    def __init_mitsuba_path(self):
 46        band_num = self.__simulation.get_scene().get_sensor().get_number_of_bands()
 47        if not os.path.exists(".less"):
 48            os.mkdir(".less")
 49        with open(".less/num.cfg", "w") as f:
 50            f.write(str(band_num))
 51        with open(".less/range.cfg", "w") as f:
 52            f.write("360 830")
 53        pyd_dir = ""
 54        dll_path = ""
 55        currdir = os.path.split(os.path.realpath(__file__))[0]
 56        if currdir.startswith(r"E:\03-Coding\lessrt"):
 57            self.__sim_mode = "devel"
 58        if self.__sim_mode == "devel":
 59            lessrt_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
 60            pyd_dir = os.path.join(lessrt_dir, "python", "lesspy", "bin", "rt", "lessrt", "python", "3.10")
 61            dll_path = os.path.join(lessrt_dir, "python", "lesspy", "bin", "rt", "lessrt")
 62        else:
 63            root_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
 64            pyd_dir = os.path.join(root_dir, "bin", "scripts", "Lesspy", "bin", "rt", "lessrt", "python", "3.10")
 65            dll_path = os.path.join(root_dir, "bin", "scripts", "Lesspy", "bin", "rt", "lessrt")
 66
 67        sys.path.append(pyd_dir)
 68        os.add_dll_directory(dll_path)
 69        # os.environ['PATH'] = dll_path + os.pathsep + os.environ['PATH']
 70
 71    def get_xml_dir(self):
 72        sim_dir = self.__simulation.get_sim_dir()
 73        xml_dir = os.path.join(sim_dir, "Parameters", "_scenefile")
 74        return xml_dir
 75
 76    def load_scene(self, scene_name="main.xml"):
 77        xml_dir = self.get_xml_dir()
 78        fileResolver = mitsuba.core.Thread.getThread().getFileResolver()
 79        logger = mitsuba.core.Thread.getThread().getLogger()
 80        # logger.clearAppenders()
 81        fileResolver.appendPath(str(xml_dir))
 82        self.less_runtime_scene = mitsuba.render.SceneHandler.loadScene(
 83            fileResolver.resolve(os.path.join(xml_dir, scene_name)))
 84        self.less_runtime_scene.configure()
 85        self.less_runtime_scene.initialize()
 86
 87    def update_parameters(self):
 88        cwd = os.getcwd()
 89        sim_dir = sim_dir = self.__simulation.get_sim_dir()
 90        os.chdir(sim_dir)
 91        interpreter = self.__simulation.get_scene_helper().get_py_interpreter_path()
 92        script_lesspy_path = self.__simulation.get_scene_helper().get_script_less_py_path()
 93        os.system(interpreter + " " + script_lesspy_path + " -g v1")
 94        os.chdir(cwd)
 95
 96        xml_dir = self.get_xml_dir()
 97        fileResolver = mitsuba.core.Thread.getThread().getFileResolver()
 98        logger = mitsuba.core.Thread.getThread().getLogger()
 99        # logger.clearAppenders()
100        fileResolver.appendPath(str(xml_dir))
101        tmp_scene = mitsuba.render.SceneHandler.loadScene(
102            fileResolver.resolve(os.path.join(xml_dir, "tmp_main.xml")))
103        tmp_scene.configure()
104
105        # update sensor
106        new_sensor = tmp_scene.getSensor()
107        self.less_runtime_scene.addSensor(new_sensor)
108        self.less_runtime_scene.setSensor(new_sensor)
109        # directly create sensor from properties is not possible from python because the properties are not complete
110        # new_sensor_props = tmp_scene.getSensor().getProperties()
111        # tmp_sensor = self.pmgr.createObject(new_sensor_props)
112        # tmp_film = self.pmgr.createObject(tmp_scene.getFilm().getProperties())
113        # tmp_film.configure()
114        # tmp_sensor.addChild(tmp_film)
115        # tmp_sensor.configure()
116        # self.less_runtime_scene.addSensor(tmp_sensor)
117        # self.less_runtime_scene.setSensor(tmp_sensor)
118        # self.less_runtime_scene.setSampler(tmp_scene.getSampler())
119
120        # update illumination
121        for emitter in self.less_runtime_scene.getEmitters():
122            self.less_runtime_scene.removeEmitter(emitter)
123        emitters = tmp_scene.getEmitters()
124        for emitter in emitters:
125            self.less_runtime_scene.addChild(emitter)
126
127        # update BSDF
128        # update terrain BRDF
129        landscape = self.__simulation.get_scene().get_landscape()
130        if landscape.get_terrain().get_terr_brdf_type() != TERRAIN_BRDF_TYPE.LAMBERTIAN:
131            print("INFO: Only Lambertian supports runtime modification of scene properties currently, If"
132                  "you want to use other BRDF types, plase contact [email protected]")
133            sys.exit(0)
134        terrain_op_name = landscape.get_terrain().get_optical()
135        terrain_ref = landscape.get_op_item(terrain_op_name).get_op_front_reflectance()
136        soil_op_obj = self.__create_terrain_bsdf(terrain_ref)
137        for shape in self.less_runtime_scene.getShapes():
138            if shape.getID() == "terrain":
139                shape.setBSDF(soil_op_obj)
140                break
141
142        ## update op
143        sgroups = landscape.get_objects()
144        group_names = list(sgroups.keys())
145        modified_phases = []
146        for ins_shape in self.less_runtime_scene.getShapes():
147            if ins_shape.getID() != "terrain":
148                shape_group_id = ins_shape.getShapeGroup().getID()
149                if shape_group_id in group_names:
150                    mesh_shapes = ins_shape.getShapeGroup().getKDTree().getShapes()
151                    values = list(sgroups[shape_group_id].values())
152                    idx = 0
153                    for mesh_shape in mesh_shapes:
154                        op_name = values[idx]["op_name"]
155                        is_turbid = values[idx]["is_turbid"]
156                        lad = values[idx]["lad"]
157                        op_item = landscape.get_op_item(op_name)
158                        if not is_turbid:
159                            mix_bsdf = self.__create_mixture_bsdf(op_item.get_op_front_reflectance(),
160                                                                  op_item.get_op_back_reflectance(),
161                                                                  op_item.get_op_transmittance())
162                            mesh_shape.addChild(mix_bsdf)
163                        else:  # turbid medium: modifying phase function and configure medium
164                            inter_medium = mesh_shape.getInteriorMedium()
165                            leaf_density = values[idx]["leaf_density"]
166                            hotspot_factor = values[idx]["hotspot_factor"]
167                            optical_lad = op_name + "_" + lad
168                            if optical_lad not in modified_phases:  # 当前组分所使用的phase function如果没更新,则更新
169                                modified_phases.append(optical_lad)
170                                phase_function = inter_medium.getPhaseFunction()
171                                phase_function.isConfigured = False  # reset the configuration to recompute phase values
172                                phase_function.frontRef = mitsuba.core.Spectrum(op_item.get_op_front_reflectance())
173                                phase_function.backRef = mitsuba.core.Spectrum(op_item.get_op_back_reflectance())
174                                phase_function.transmittance = mitsuba.core.Spectrum(op_item.get_op_transmittance())
175                                phase_function.opticalName = op_name
176                                phase_function.ladType = self.__get_lad_type(lad)
177                                phase_function.configure()
178                            inter_medium.ladType = self.__get_lad_type(lad)
179                            inter_medium.leafAreaDensity = leaf_density
180                            inter_medium.hotspotFactor = hotspot_factor
181                            inter_medium.configure()
182                        idx += 1
183                    group_names.remove(shape_group_id)
184                if len(group_names) == 0:
185                    break
186
187    def start(self):
188        job = mitsuba.render.RenderJob('Simulating', self.less_runtime_scene, self.queue)
189        job.start()
190        self.queue.waitLeft(0)
191        self.__post_processing()
192
193    def __create_terrain_bsdf(self, reflectance):
194        bsdf = self.__create_object('diffuse', {'reflectance': mitsuba.core.Spectrum(reflectance)})
195        bsdf.configure()
196        return bsdf
197
198    def __create_object(self, name: str, properties: {}):
199        props = mitsuba.core.Properties(name)
200        for key in properties:
201            props[key] = properties[key]
202        return self.pmgr.createObject(props)
203
204    def __create_mixture_bsdf(self, reflectance_front=0.4, reflectance_back=0.4, transmittance=0.4):
205        mixbsdf = self.__create_object('mixturebsdf', {'ensureEnergyConservation': False, 'weights': '1, 1'})
206        twosidedbsdf = self.__create_object('twosided', {})
207        refbsdf = self.__create_object("diffuse", {'reflectance': mitsuba.core.Spectrum(reflectance_front)})
208        refbsdf.configure()
209        twosidedbsdf.addChild(refbsdf)
210        refbsdf = self.__create_object("diffuse", {'reflectance': mitsuba.core.Spectrum(reflectance_back)})
211        refbsdf.configure()
212        twosidedbsdf.addChild(refbsdf)
213        twosidedbsdf.configure()
214        transbsdf = self.__create_object('difftrans', {'transmittance': mitsuba.core.Spectrum(transmittance)})
215        transbsdf.configure()
216        mixbsdf.addChild(twosidedbsdf)
217        mixbsdf.addChild(transbsdf)
218        mixbsdf.configure()
219        return mixbsdf
220
221    def __get_lad_type(self, lad_str):
222        if lad_str == "Spherical":
223            return mitsuba.render.PhaseFunction.ESpherical
224        if lad_str == "Uniform":
225            return mitsuba.render.PhaseFunction.EUniform
226        if lad_str == "Planophile":
227            return mitsuba.render.PhaseFunction.EPlanophile
228        if lad_str == "Erectophile":
229            return mitsuba.render.PhaseFunction.EErectophile
230        if lad_str == "Plagiophile":
231            return mitsuba.render.PhaseFunction.EPlagiophile
232        if lad_str == "Extremophile":
233            return mitsuba.render.PhaseFunction.EExtremophile
234        return mitsuba.render.ELadType.EINVALIDE
235
236    def __post_processing(self):
237        sim_dir = self.__simulation.get_sim_dir()
238        distFile = self.__simulation.get_dist_file()
239        infofile = os.path.join(sim_dir, "Results", "spectral.txt")
240        f = open(infofile, 'w')
241        f.write(os.path.basename(distFile))
242        f.close()
243
244        cfgfile = os.path.join(sim_dir, "Parameters", "input.conf")
245        f = open(cfgfile, 'r')
246        cfg = json.load(f)
247
248        output_format = "ENVI"
249        if cfg["sensor"]["sensor_type"] == "PhotonTracing":
250            out_file_no_extension = distFile + "_downwelling"
251            output_fileName = distFile + "_downwelling.npy"
252            if output_format not in ("npy", "NPY") and os.path.exists(output_fileName):
253                data = np.load(output_fileName)
254                bandlist = cfg["sensor"]["bands"].split(",")
255                RasterHelper.saveToHdr_no_transform(data, out_file_no_extension, bandlist, output_format)
256                os.remove(output_fileName)
257            out_file_no_extension = distFile + "_upwelling"
258            output_fileName = distFile + "_upwelling.npy"
259            if output_format not in ("npy", "NPY") and os.path.exists(output_fileName):
260                data = np.load(output_fileName)
261                bandlist = cfg["sensor"]["bands"].split(",")
262                RasterHelper.saveToHdr_no_transform(data, out_file_no_extension, bandlist, output_format)
263                os.remove(output_fileName)
264        else:
265            out_file_no_extension = distFile + "_4Components"
266            output_fileName = distFile + "_4Components.npy"
267
268            if output_format not in ("npy", "NPY") and os.path.exists(output_fileName):
269                data = np.load(output_fileName)
270                dshape = data.shape
271                if len(dshape) == 3:
272                    if dshape[2] <= 4:
273                        data = data[:, :, 0]
274                    else:
275                        data = data[:, :, 0:5]
276                bandlist = []
277                RasterHelper.saveToHdr_no_transform(data, out_file_no_extension, bandlist, output_format)
278                os.remove(output_fileName)
279
280            if output_format not in ("npy", "NPY") and os.path.exists(distFile + ".npy"):
281                data = np.load(distFile + ".npy")
282
283                # converte to brightness temperature
284                if cfg["sensor"]["thermal_radiation"]:
285                    bandlist = cfg["sensor"]["bands"].split(",")
286                    data = RasterHelper.convertRadiance2BTimage(data, bandlist)
287
288                bandlist = cfg["sensor"]["bands"].split(",")
289                RasterHelper.saveToHdr_no_transform(data, distFile, bandlist, output_format)
290                os.remove(distFile + ".npy")
291        print("INFO: Finished")
RuntimeScene(simulation)
16    def __init__(self, simulation):
17        self.__simulation = simulation
18        self.less_runtime_scene = None
19        self.__sim_mode = "devel11"
20
21        # load mitsuba
22        self.__init_mitsuba_path()
23        globals()["mitsuba"] = __import__("mitsuba")
24        reload(mitsuba)
25
26        self.pmgr = mitsuba.core.PluginManager.getInstance()
27
28        # for simulation
29        self.queue = mitsuba.render.RenderQueue()
30        # prepare for simulation
31        self.scheduler = mitsuba.core.Scheduler.getInstance()
32        # Start up the scheduling system with one worker per local core
33        min_cores = min(multiprocessing.cpu_count(),
34                        int(self.__simulation.get_scene().get_advanced_params().number_of_cores))
35        print("INFO: Using number of cores:", min_cores)
36        if not self.scheduler.isRunning():
37            for i in range(0, min_cores):
38                self.scheduler.registerWorker(mitsuba.core.LocalWorker(i, 'wrk%i' % i))
39            self.scheduler.start()
less_runtime_scene
pmgr
queue
scheduler
def shutdown_simulator(self):
41    def shutdown_simulator(self):
42        self.queue.join()
43        self.scheduler.stop()
def get_xml_dir(self):
71    def get_xml_dir(self):
72        sim_dir = self.__simulation.get_sim_dir()
73        xml_dir = os.path.join(sim_dir, "Parameters", "_scenefile")
74        return xml_dir
def load_scene(self, scene_name='main.xml'):
76    def load_scene(self, scene_name="main.xml"):
77        xml_dir = self.get_xml_dir()
78        fileResolver = mitsuba.core.Thread.getThread().getFileResolver()
79        logger = mitsuba.core.Thread.getThread().getLogger()
80        # logger.clearAppenders()
81        fileResolver.appendPath(str(xml_dir))
82        self.less_runtime_scene = mitsuba.render.SceneHandler.loadScene(
83            fileResolver.resolve(os.path.join(xml_dir, scene_name)))
84        self.less_runtime_scene.configure()
85        self.less_runtime_scene.initialize()
def update_parameters(self):
 87    def update_parameters(self):
 88        cwd = os.getcwd()
 89        sim_dir = sim_dir = self.__simulation.get_sim_dir()
 90        os.chdir(sim_dir)
 91        interpreter = self.__simulation.get_scene_helper().get_py_interpreter_path()
 92        script_lesspy_path = self.__simulation.get_scene_helper().get_script_less_py_path()
 93        os.system(interpreter + " " + script_lesspy_path + " -g v1")
 94        os.chdir(cwd)
 95
 96        xml_dir = self.get_xml_dir()
 97        fileResolver = mitsuba.core.Thread.getThread().getFileResolver()
 98        logger = mitsuba.core.Thread.getThread().getLogger()
 99        # logger.clearAppenders()
100        fileResolver.appendPath(str(xml_dir))
101        tmp_scene = mitsuba.render.SceneHandler.loadScene(
102            fileResolver.resolve(os.path.join(xml_dir, "tmp_main.xml")))
103        tmp_scene.configure()
104
105        # update sensor
106        new_sensor = tmp_scene.getSensor()
107        self.less_runtime_scene.addSensor(new_sensor)
108        self.less_runtime_scene.setSensor(new_sensor)
109        # directly create sensor from properties is not possible from python because the properties are not complete
110        # new_sensor_props = tmp_scene.getSensor().getProperties()
111        # tmp_sensor = self.pmgr.createObject(new_sensor_props)
112        # tmp_film = self.pmgr.createObject(tmp_scene.getFilm().getProperties())
113        # tmp_film.configure()
114        # tmp_sensor.addChild(tmp_film)
115        # tmp_sensor.configure()
116        # self.less_runtime_scene.addSensor(tmp_sensor)
117        # self.less_runtime_scene.setSensor(tmp_sensor)
118        # self.less_runtime_scene.setSampler(tmp_scene.getSampler())
119
120        # update illumination
121        for emitter in self.less_runtime_scene.getEmitters():
122            self.less_runtime_scene.removeEmitter(emitter)
123        emitters = tmp_scene.getEmitters()
124        for emitter in emitters:
125            self.less_runtime_scene.addChild(emitter)
126
127        # update BSDF
128        # update terrain BRDF
129        landscape = self.__simulation.get_scene().get_landscape()
130        if landscape.get_terrain().get_terr_brdf_type() != TERRAIN_BRDF_TYPE.LAMBERTIAN:
131            print("INFO: Only Lambertian supports runtime modification of scene properties currently, If"
132                  "you want to use other BRDF types, plase contact [email protected]")
133            sys.exit(0)
134        terrain_op_name = landscape.get_terrain().get_optical()
135        terrain_ref = landscape.get_op_item(terrain_op_name).get_op_front_reflectance()
136        soil_op_obj = self.__create_terrain_bsdf(terrain_ref)
137        for shape in self.less_runtime_scene.getShapes():
138            if shape.getID() == "terrain":
139                shape.setBSDF(soil_op_obj)
140                break
141
142        ## update op
143        sgroups = landscape.get_objects()
144        group_names = list(sgroups.keys())
145        modified_phases = []
146        for ins_shape in self.less_runtime_scene.getShapes():
147            if ins_shape.getID() != "terrain":
148                shape_group_id = ins_shape.getShapeGroup().getID()
149                if shape_group_id in group_names:
150                    mesh_shapes = ins_shape.getShapeGroup().getKDTree().getShapes()
151                    values = list(sgroups[shape_group_id].values())
152                    idx = 0
153                    for mesh_shape in mesh_shapes:
154                        op_name = values[idx]["op_name"]
155                        is_turbid = values[idx]["is_turbid"]
156                        lad = values[idx]["lad"]
157                        op_item = landscape.get_op_item(op_name)
158                        if not is_turbid:
159                            mix_bsdf = self.__create_mixture_bsdf(op_item.get_op_front_reflectance(),
160                                                                  op_item.get_op_back_reflectance(),
161                                                                  op_item.get_op_transmittance())
162                            mesh_shape.addChild(mix_bsdf)
163                        else:  # turbid medium: modifying phase function and configure medium
164                            inter_medium = mesh_shape.getInteriorMedium()
165                            leaf_density = values[idx]["leaf_density"]
166                            hotspot_factor = values[idx]["hotspot_factor"]
167                            optical_lad = op_name + "_" + lad
168                            if optical_lad not in modified_phases:  # 当前组分所使用的phase function如果没更新,则更新
169                                modified_phases.append(optical_lad)
170                                phase_function = inter_medium.getPhaseFunction()
171                                phase_function.isConfigured = False  # reset the configuration to recompute phase values
172                                phase_function.frontRef = mitsuba.core.Spectrum(op_item.get_op_front_reflectance())
173                                phase_function.backRef = mitsuba.core.Spectrum(op_item.get_op_back_reflectance())
174                                phase_function.transmittance = mitsuba.core.Spectrum(op_item.get_op_transmittance())
175                                phase_function.opticalName = op_name
176                                phase_function.ladType = self.__get_lad_type(lad)
177                                phase_function.configure()
178                            inter_medium.ladType = self.__get_lad_type(lad)
179                            inter_medium.leafAreaDensity = leaf_density
180                            inter_medium.hotspotFactor = hotspot_factor
181                            inter_medium.configure()
182                        idx += 1
183                    group_names.remove(shape_group_id)
184                if len(group_names) == 0:
185                    break
def start(self):
187    def start(self):
188        job = mitsuba.render.RenderJob('Simulating', self.less_runtime_scene, self.queue)
189        job.start()
190        self.queue.waitLeft(0)
191        self.__post_processing()