55import mitsuba
66
77
8- def xml_sensor (direction = None , target = None , xpixel = 1 ):
8+ def dict_sensor (direction = None , target = None , fwidth = 1 ):
99 if direction is None :
10- xml_direction = ""
10+ dict_direction = {}
1111 else :
12- if type (direction ) is not str :
13- direction = "," .join ([str (x ) for x in direction ])
14- xml_direction = f"""<vector name="direction" value="{ direction } "/>"""
12+ dict_direction = {"direction" : direction }
1513
1614 if target is None :
17- xml_target = ""
15+ dict_target = {}
1816 else :
19- if type (target ) is not str :
20- target = "," .join ([str (x ) for x in target ])
21- xml_target = f"""<point name="target" value="{ target } "/>"""
17+ dict_target = {"target" : target }
2218
23- xml_film = f"""<film type="hdrfilm">
24- <integer name="width" value="{ xpixel } "/>
25- <integer name="height" value="1"/>
26- <rfilter type="box"/>
27- </film>"""
19+ dict_film = {
20+ "type" : "hdrfilm" ,
21+ "width" : fwidth ,
22+ "height" : 1 ,
23+ "rfilter" : {"type" : "box" }
24+ }
2825
29- return f"""<sensor version="2.0.0" type="distant">
30- { xml_direction }
31- { xml_target }
32- { xml_film }
33- </sensor>"""
26+ return {
27+ "type" : "distant" ,
28+ ** dict_direction ,
29+ ** dict_target ,
30+ "film" : dict_film ,
31+ }
3432
3533
36- def make_sensor (direction = None , target = None , xpixel = 1 ):
37- from mitsuba .core .xml import load_string
38- return load_string ( xml_sensor (direction , target , xpixel ))
34+ def make_sensor (direction = None , target = None , fwidth = 1 ):
35+ from mitsuba .core .xml import load_dict
36+ return load_dict ( dict_sensor (direction , target , fwidth ))
3937
4038
4139def test_construct (variant_scalar_rgb ):
42- from mitsuba .core .xml import load_string
40+ from mitsuba .core .xml import load_string , load_dict
4341
4442 # Construct without parameters (wrong film size)
4543 with pytest .raises (RuntimeError ):
46- sensor = load_string ( """<sensor version="2.0.0" type=" distant"/>""" )
44+ sensor = load_dict ({ "type" : " distant"} )
4745
4846 # Construct with wrong film size
4947 with pytest .raises (RuntimeError ):
50- sensor = make_sensor (xpixel = 2 )
48+ sensor = make_sensor (fwidth = 2 )
5149
5250 # Construct with minimal parameters
5351 sensor = make_sensor ()
@@ -110,16 +108,15 @@ def test_sample_ray(variant_scalar_rgb, direction, target, ray_kind):
110108
111109
112110def make_scene (direction = [0 , 0 , - 1 ], target = None ):
113- from mitsuba .core .xml import load_string
111+ from mitsuba .core .xml import load_dict
114112
115- scene_xml = f"""
116- <scene version="2.0.0">
117- { xml_sensor (direction , target )}
118- <shape type="rectangle"/>
119- </scene>
120- """
113+ dict_scene = {
114+ "type" : "scene" ,
115+ "sensor" : dict_sensor (direction , target ),
116+ "surface" : {"type" : "rectangle" }
117+ }
121118
122- return load_string ( scene_xml )
119+ return load_dict ( dict_scene )
123120
124121
125122@pytest .mark .parametrize ("target" , [[0 , 0 , 0 ], [0.5 , 0 , 1 ]])
@@ -143,12 +140,12 @@ def test_target(variant_scalar_rgb, target):
143140@pytest .mark .parametrize ("direction" , [[0 , 0 , - 1 ], [0.5 , 0.5 , - 1 ]])
144141def test_intersection (variant_scalar_rgb , direction ):
145142 # Check if the sensor correctly casts rays spread uniformly in the scene
146- direction = ek .normalize (direction )
143+ direction = list ( ek .normalize (direction ) )
147144 scene = make_scene (direction = direction )
148145 sensor = scene .sensors ()[0 ]
149146 sampler = sensor .sampler ()
150147
151- n_rays = 10000
148+ n_rays = 1000
152149 isect = np .empty ((n_rays , 3 ))
153150
154151 for i in range (n_rays ):
@@ -168,7 +165,7 @@ def test_intersection(variant_scalar_rgb, direction):
168165 # Average intersection locations should be (in average) centered
169166 # around (0, 0, 0)
170167 isect_valid = isect [~ np .isnan (isect ).all (axis = 1 )]
171- assert np .allclose (isect_valid [:, :2 ].mean (axis = 0 ), 0. , atol = 1e -2 )
168+ assert np .allclose (isect_valid [:, :2 ].mean (axis = 0 ), 0. , atol = 5e -2 )
172169 assert np .allclose (isect_valid [:, 2 ], 0. , atol = 1e-5 )
173170
174171 # Check number of invalid intersections
@@ -177,42 +174,47 @@ def test_intersection(variant_scalar_rgb, direction):
177174 # slanting factor (cos theta) w.r.t the sensor's direction
178175 n_invalid = np .count_nonzero (np .isnan (isect ).all (axis = 1 ))
179176 assert np .allclose (n_invalid / n_rays , 1. - 2. / np .pi *
180- ek .dot (direction , [0 , 0 , - 1 ]), atol = 1e-2 )
177+ ek .dot (direction , [0 , 0 , - 1 ]), atol = 0.1 )
181178
182179
183180@pytest .mark .parametrize ("radiance" , [10 ** x for x in range (- 3 , 4 )])
184181def test_render (variant_scalar_rgb , radiance ):
185182 # Test render results with a simple scene
186- from mitsuba .core .xml import load_string
187- import numpy as np
188-
189- scene_xml = """
190- <scene version="2.0.0">
191- <default name="radiance" value="1.0"/>
192- <default name="spp" value="1"/>
193-
194- <integrator type="path"/>
195-
196- <sensor type="distant">
197- <film type="hdrfilm">
198- <integer name="width" value="1"/>
199- <integer name="height" value="1"/>
200- <string name="pixel_format" value="rgb"/>
201- <rfilter type="box"/>
202- </film>
203-
204- <sampler type="independent">
205- <integer name="sample_count" value="$spp"/>
206- </sampler>
207- </sensor>
208-
209- <emitter type="constant">
210- <spectrum name="radiance" value="$radiance"/>
211- </emitter>
212- </scene>
213- """
214-
215- scene = load_string (scene_xml , spp = 1 , radiance = radiance )
183+ from mitsuba .core .xml import load_dict
184+ from mitsuba .core import Bitmap , Struct
185+
186+ def dict_scene (radiance = 1.0 , spp = 1 ):
187+ return {
188+ "type" : "scene" ,
189+ "shape" : {
190+ "type" : "rectangle" ,
191+ "bsdf" : {"type" : "conductor" },
192+ },
193+ "integrator" : {"type" : "path" },
194+ "sensor" : {
195+ "type" : "distant" ,
196+ "film" : {
197+ "type" : "hdrfilm" ,
198+ "width" : 1 ,
199+ "height" : 1 ,
200+ "pixel_format" : "rgb" ,
201+ "rfilter" : {"type" : "box" },
202+ },
203+ "sampler" : {
204+ "type" : "independent" ,
205+ "sample_count" : spp
206+ },
207+ },
208+ "emitter" : {
209+ "type" : "constant" ,
210+ "radiance" : {
211+ "type" : "spectrum" ,
212+ "value" : radiance
213+ }
214+ }
215+ }
216+
217+ scene = load_dict (dict_scene (spp = 1 , radiance = radiance ))
216218 sensor = scene .sensors ()[0 ]
217219 scene .integrator ().render (scene , sensor )
218220 img = sensor .film ().bitmap ()
0 commit comments