This page explores spherical gradient lighting, as trialled by Ma 2007 with USC ICT LS3-5 Lightstage by Debevec, et al.
The script loads a frame (the icosahedron 3v dome, with vertex numbering specified for the Aber Lightstage) orders the vertices by their x-axis position and applies a "spherical gradient" (a gradient value) to each light, corresponding to a smooth illumination of the target.
The gradient value can be used as a relative light wattage output value, within the constraints of control bit values per light's hardware interface. These spherical gradient values are proportional to their x-axis positions to the sphere, such that the target's illumination remains balanced.
The plots below help to illustrate how each gradient value is applied to each light, pre-ordered by it's x-axis position, and through a series of rotations culminating in a lighting sequence.
In [200]:
default_path = "../../src/"
import sys
sys.path.insert(0, default_path)
%matplotlib notebook
from spherical_gradient import GradientSequence_IntervalSpecified
from data_3d import WaveFront
import matplotlib.pyplot as plt
def barplot(x,y=None):
if y is not None:
fig, ax = plt.subplots(1,2)
d = [x,y]
for i in range(len(ax)):
a = ax[i]
b = d[i]
a.bar(range(len(b)), b)
else:
fig, ax = plt.subplots(1,1)
ax.bar(range(len(x)), x)
Next we import the lightstage frame, specifying where each LED is located [(x,y,z),..].
For the hardcoded_frame() case, we assume every frame vertex is going to have an LED. But it needn't be that way.
Note: the icosahedron frame's vertices' x-axis positions are not uniformly distributed around the x-axis of the sphere. We could apply a uniformly distributed set as light positions. You can try each out below to see the effect on gradient smoothness.
In [201]:
leds = WaveFront.get_hardcoded_frame( scale=8 )
# leds = zip( range(-8,9,1), range(-8,9,1), range(-8,9,1) )
print(len(leds))
Next we specify each light's baseline_intensity, that is the light's default wattage output value; which can be specified as 1.0 for no effect. Later, this will be used as a multiplier to the gradient value.
It can also be defined via a CSV file as a tuned set of values. See for example, (Brightness Control Tuning)[https://github.com/LightStage-Aber/LightStage-Repo#optimise-evenness-of-any-light-position-set--m3]. With this tool, we can minimise the effects of imperfectly balanced positions of the lights, thus further improving the lighting balance.
In [202]:
baseline_intensity = [1.0]*len(leds)
Next, we specify the scaled_range of 0.5-1.0 to each light. That is the min/max range of gradient value to be applied to each light position.
The quantity_of_intervals let us control the granularity of rotations. Each plot sequence below is an output of from the current rotation. The sphere of light positions is going to appear to rotate, with a number of granular stops. That's what this value defines.
Below, there are 5 granular rotations, defined by quantity_of_intervals.
Then we instantiate the GradientSequence object.
In [203]:
scaled_range = [0.5, 1.0]
quantity_of_intervals = 5
gs = GradientSequence_IntervalSpecified( leds, baseline_intensity, "x", scaled_range, quantity_of_intervals )
In [204]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
From the result, we extract data from the BaseSequenceContainer class objects, including c.get_index() for the vertex index and c.get_intensity() for the light's (relative) wattage output value.
Each light's c.get_intensity() wattage output value is multiplied by a wattage output value (baseline_intensity) that can be specified as 1.0 for no effect.
In [205]:
gradient_intensities = [ c.get_intensity() for c in l ]
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
# print(gradient_intensities)
barplot(gradient_intensities)
In [206]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
gradient_intensities = [ c.get_intensity() for c in l ]
barplot(gradient_intensities)
In [207]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
gradient_intensities = [ c.get_intensity() for c in l ]
barplot(gradient_intensities)
In [208]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
gradient_intensities = [ c.get_intensity() for c in l ]
barplot(gradient_intensities)
In [209]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
gradient_intensities = [ c.get_intensity() for c in l ]
barplot(gradient_intensities)
In [210]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
gradient_intensities = [ c.get_intensity() for c in l ]
barplot(gradient_intensities)
In [211]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
gradient_intensities = [ c.get_intensity() for c in l ]
barplot(gradient_intensities)
In [212]:
gs = GradientSequence_IntervalSpecified(
leds,
baseline_intensity,
axis="x",
scaled_range=[0.5, 1.0],
quantity_of_intervals=quantity_of_intervals
)
In [213]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [214]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [215]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [216]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [217]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [218]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [219]:
gs = GradientSequence_IntervalSpecified(
leds,
baseline_intensity,
axis="y",
scaled_range=[0.5, 1.0],
quantity_of_intervals=quantity_of_intervals
)
In [220]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [221]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [222]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [223]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [224]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [225]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [226]:
gs = GradientSequence_IntervalSpecified(
leds,
baseline_intensity,
axis="z",
scaled_range=[0.5, 1.0],
quantity_of_intervals=quantity_of_intervals
)
In [227]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [228]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [229]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [230]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [231]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)
In [232]:
l = gs.get_next_sequence()
num, loop_num = gs.get_sequence_number()
print(num)
print(loop_num)
l = list(l)
l2 = sorted(l, key=lambda x: x.get_index())
native_order = [ c.get_intensity() for c in l ]
axis_order = [ c.get_intensity() for c in l2 ]
barplot(native_order, axis_order)