Error handling

This test covers typical runtime error outputs from Lightmetrica.

[1]:
%load_ext autoreload
%autoreload 2
[2]:
import lmenv
lmenv.load('.lmenv')
[2]:
Namespace(bin_path='/lightmetrica-v3/_build/bin', path='/lightmetrica-v3', scene_path='/lm3/scenes')
[3]:
import os
import traceback
import imageio
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import lightmetrica as lm
[4]:
%load_ext lightmetrica_jupyter

Calling Lightmetrica API without initialization

Calling Lightmetrica API without initialization causes an exception.

[5]:
try:
    # This causes an exception
    lm.info()
except Exception:
    traceback.print_exc()
Traceback (most recent call last):
  File "/tmp/ipykernel_321/3996180219.py", line 3, in <module>
    lm.info()
pylm.Exception: Lightmetrica is not initialize. Call lm::init() function. [err='Uninitialized']
[6]:
# Initializing Lightmetrica fixes the problem
lm.init()

No outputs in Jupyter notebook

Lightmetrica initializes default logger that outputs messages into standard output of the console. If you are using Jupyter notebook, you need to initialize the logger using logger::jupyter.

[7]:
# No output in Jupyter notebook
lm.info()
[I|0.014|92@user   ] Lightmetrica -- Version 3.0.0 (rev. 70601db) Linux x64
[8]:
# Initialize the logger with logger::jupyter
lm.log.init('jupyter')
[9]:
lm.info()
[I|0.016] Lightmetrica -- Version 3.0.0 (rev. 70601db) Linux x64

Wrong asset name

If you specify the wrong asset name, the framework will rause an exception.

[10]:
try:
    # Wrong: bitmapp
    lm.load_film('film1', 'bitmapp', w=1920, h=1080)
except Exception:
    traceback.print_exc()
[I|0.032] Loading asset [name='film1']
[E|0.032] .. Missing component [key='film::bitmapp']. Check if
[E|0.032] .. - Key is wrong
[E|0.032] .. - Component with the key is not registered
[E|0.032] .. - Plugin containing the component is not loaded
[E|0.032] .. Failed to create an asset [name='film1', key='film::bitmapp']
[11]:
# Correct: bitmap
lm.load_film('film1', 'bitmap', w=1920, h=1080)
[I|0.050] Loading asset [name='film1']
[11]:
<pylm.Film at 0x7f599084beb0>

Invalid parameter

The framework will cause an exception if you try to create an asset with invalid parameters. The framework will not generate an error for the unnecessasry parameters.

[12]:
try:
    # vfov is missing
    lm.load_camera('camera1', 'pinhole',
        position=[0,0,5],
        center=[0,0,0],
        up=[0,1,0],
        aspect=16/9)
except Exception:
    traceback.print_exc()
[I|0.149] Loading asset [name='camera1']
Traceback (most recent call last):
  File "/tmp/ipykernel_321/2622328980.py", line 7, in <module>
    aspect=16/9)
pylm.Exception: Missing property [name='vfov'] [err='InvalidArgumnt']
[13]:
try:
    lm.load_camera('camera1', 'pinhole',
        # Parameter type is wrong. position must be an array.
        position=5,
        center=[0,0,0],
        up=[0,1,0],
        aspect=16/9,
        fov=30)
except Exception:
    traceback.print_exc()
[I|0.167] Loading asset [name='camera1']
[I|0.167] .. Asset [name='camera1'] has been already loaded. Replacing..
Traceback (most recent call last):
  File "/tmp/ipykernel_321/3903153117.py", line 8, in <module>
    fov=30)
pylm.Exception: Invalid JSON type [expected='array', actual='number'] [err='InvalidArgumnt']
[14]:
# This is correct
lm.load_camera('camera1', 'pinhole',
    # Parameter type is wrong. position must be an array.
    position=[0,0,5],
    center=[0,0,0],
    up=[0,1,0],
    aspect=16/9,
    vfov=30)
[I|0.186] Loading asset [name='camera1']
[I|0.186] .. Asset [name='camera1'] has been already loaded. Replacing..
[14]:
<pylm.Camera at 0x7f5990850db0>

Missing reference

[15]:
lm.load_mesh('mesh1', 'raw',
    ps=[-1,-1,-1,1,-1,-1,1,1,-1,-1,1,-1],
    ns=[0,0,1],
    ts=[0,0,1,0,1,1,0,1],
    fs={
        'p': [0,1,2,0,2,3],
        'n': [0,0,0,0,0,0],
        't': [0,1,2,0,2,3]
    })
[I|0.206] Loading asset [name='mesh1']
[15]:
<pylm.Mesh at 0x7f5990843d70>
[16]:
accel = lm.load_accel('accel', 'sahbvh')
scene = lm.load_scene('scene', 'default', accel=accel)
[I|0.225] Loading asset [name='accel']
[I|0.225] Loading asset [name='scene']
[17]:
try:
    # material1 is undefined
    scene.add_primitive(mesh='$.assets.mesh1', material='$.assets.material1')
except Exception:
    traceback.print_exc()
[E|0.241] Invalid asset name [name='material1']
[E|0.241] Failed to find a component with locator [loc='$.assets.material1']
Traceback (most recent call last):
  File "/tmp/ipykernel_321/1872909071.py", line 3, in <module>
    scene.add_primitive(mesh='$.assets.mesh1', material='$.assets.material1')
pylm.Exception: You must specify both mesh and material. [err='InvalidArgumnt']
[18]:
# Define a missing asset
lm.load_material('material1', 'diffuse', Kd=[1,1,1])
[I|0.258] Loading asset [name='material1']
[18]:
<pylm.Material at 0x7f59908508b0>
[19]:
try:
    # 'material1' is not a valid locator
    scene.add_primitive(mesh='$.assets.mesh1', material='material1')
except Exception:
    traceback.print_exc()
[E|0.277] Locator must start with '$' [loc='material1'].
Traceback (most recent call last):
  File "/tmp/ipykernel_321/3705454848.py", line 3, in <module>
    scene.add_primitive(mesh='$.assets.mesh1', material='material1')
pylm.Exception: You must specify both mesh and material. [err='InvalidArgumnt']
[20]:
# This is correct
scene.add_primitive(mesh='$.assets.mesh1', material='$.assets.material1')

Rendering with invalid scene

[21]:
renderer = lm.load_renderer('renderer', 'raycast',
    scene=scene,
    output='$.assets.film1',
    color=[0,0,0])
[I|0.311] Loading asset [name='renderer']
[22]:
try:
    # Without camera
    renderer.render()
except Exception:
    traceback.print_exc()
Traceback (most recent call last):
  File "/tmp/ipykernel_321/2934345131.py", line 3, in <module>
    renderer.render()
pylm.Exception: Missing camera primitive. Use lm::primitive() function to add camera primitive. [err='Unsupported']
[23]:
# Add camera primitive
scene.add_primitive(camera='$.assets.camera1')
[24]:
try:
    # With camera, but without build()
    renderer.render()
except Exception:
    traceback.print_exc()
[I|0.496] Processing [completed]
Traceback (most recent call last):
  File "/tmp/ipykernel_321/1082868316.py", line 3, in <module>
    renderer.render()
IndexError: vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
[25]:
scene.build()
[I|0.515] Building acceleration structure [name='accel']
[I|0.515] .. Flattening scene
[I|0.515] .. Building
[26]:
# OK
renderer.render()
[I|1.154] Processing [iter=1864200/2073600, progress=89.9%, ETA=0.1s]
[I|1.206] Processing [completed]
[26]:
{'elapsed': 0.553086479}