Changeset - 669c4892a1ff
[Not reviewed]
default
9 7 9
Drew Perttula - 8 years ago 2017-06-03 20:01:27
drewp@bigasterisk.com
fix up tests
Ignore-this: ccde920eca1d7007c87b8fecf77855eb
16 files changed with 116 insertions and 51 deletions:
0 comments (0 inline, 0 general)
light9/effect/settings.py
Show inline comments
 
@@ -55,16 +55,16 @@ class _Settings(object):
 
                da = g.value(s, L9['deviceAttr'])
 
                v = getVal(g, s)
 
                settingsList.append((d, da, v))
 
        return cls(graph, settingsList)
 

	
 
    @classmethod
 
    def fromVector(cls, graph, vector):
 
    def fromVector(cls, graph, vector, deviceAttrFilter=None):
 
        compiled = {}
 
        i = 0
 
        for (d, a) in cls(graph, [])._vectorKeys():
 
        for (d, a) in cls(graph, [])._vectorKeys(deviceAttrFilter):
 
            if a == L9['color']:
 
                v = toHex(vector[i:i+3])
 
                i += 3
 
            else:
 
                v = vector[i]
 
                i += 1
 
@@ -84,13 +84,13 @@ class _Settings(object):
 
        out._delZeros()
 
        return out
 
        
 
    def _zeroForAttr(self, attr):
 
        if attr == L9['color']:
 
            return '#000000'
 
        return 0
 
        return 0.0
 

	
 
    def _delZeros(self):
 
        for dev, av in self._compiled.items():
 
            for attr, val in av.items():
 
                if val == self._zeroForAttr(attr):
 
                    del av[attr]
 
@@ -127,13 +127,13 @@ class _Settings(object):
 
        accum()
 
        return '<%s %s>' % (self.__class__.__name__, ' '.join(words))
 
        
 
    def getValue(self, dev, attr):
 
        return self._compiled.get(dev, {}).get(attr, self._zeroForAttr(attr))
 

	
 
    def _vectorKeys(self):
 
    def _vectorKeys(self, deviceAttrFilter=None):
 
        """stable order of all the dev,attr pairs for this type of settings"""
 
        raise NotImplementedError
 

	
 
    def asList(self):
 
        """old style list of (dev, attr, val) tuples"""
 
        out = []
 
@@ -142,16 +142,15 @@ class _Settings(object):
 
                out.append((dev, attr, val))
 
        return out
 

	
 
    def devices(self):
 
        return self._compiled.keys()
 
        
 
    def toVector(self):
 
    def toVector(self, deviceAttrFilter=None):
 
        out = []
 
        for dev, attr in self._vectorKeys():
 
            # color components may need to get spread out
 
        for dev, attr in self._vectorKeys(deviceAttrFilter):
 
            v = self.getValue(dev, attr)
 
            if attr == L9['color']:
 
                out.extend([x / 255 for x in parseHex(v)])
 
            else:
 
                out.append(v)
 
        return out
 
@@ -194,19 +193,22 @@ class _Settings(object):
 
            settingsSubgraphCache.add(setting)
 
            
 
        return add
 

	
 

	
 
class DeviceSettings(_Settings):
 
    def _vectorKeys(self):
 
    def _vectorKeys(self, deviceAttrFilter=None):
 
        with self.graph.currentState() as g:
 
            devs = set() # devclass, dev
 
            for dc in g.subjects(RDF.type, L9['DeviceClass']):
 
                for dev in g.subjects(RDF.type, dc):
 
                    devs.add((dc, dev))
 

	
 
            keys = []
 
            for dc, dev in sorted(devs):
 
                for attr in sorted(g.objects(dc, L9['deviceAttr'])):
 
                    keys.append((dev, attr))
 
                    key = (dev, attr)
 
                    if deviceAttrFilter and key not in deviceAttrFilter:
 
                        continue
 
                    keys.append(key)
 
        return keys
 
    
light9/effect/settings_test.py
Show inline comments
 
@@ -4,14 +4,14 @@ from light9.rdfdb.patch import Patch
 
from light9.rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.namespaces import RDF, L9, DEV
 
from light9.effect.settings import DeviceSettings
 

	
 
class TestDeviceSettings(unittest.TestCase):
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                             'show/dance2017/cam/test/bg.n3'])
 
        self.graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                             'test/cam/bg.n3'])
 

	
 
    def testToVectorZero(self):
 
        ds = DeviceSettings(self.graph, [])
 
        self.assertEqual([0] * 30, ds.toVector())
 

	
 
    def testEq(self):
light9/paint/solve.py
Show inline comments
 
@@ -66,13 +66,13 @@ class ImageDistAbs(object):
 
        return numpy.sum(numpy.absolute(self.a - img2), axis=None) / self.maxDist
 

	
 
        
 
class Solver(object):
 
    def __init__(self, graph, sessions=None, imgSize=(100, 75)):
 
        self.graph = graph
 
        self.sessions = sessions
 
        self.sessions = sessions # URIs of capture sessions to load
 
        self.imgSize = imgSize
 
        self.samples = {} # uri: Image array (float 0-255)
 
        self.fromPath = {} # imagePath: image array
 
        self.blurredSamples = {}
 
        self.sampleSettings = {} # (uri, path): DeviceSettings
 
        
 
@@ -143,17 +143,17 @@ class Solver(object):
 
        """
 
        pic0 = self.draw(painting).astype(numpy.float)
 
        pic0Blur = self._blur(pic0)
 
        saveNumpy('/tmp/sample_paint_%s.png' % len(painting['strokes']),
 
                  pic0Blur)
 
        sampleDist = {}
 
        dist = ImageDist(pic0Blur)
 
        for sample, picSample in sorted(self.blurredSamples.items()):
 
            #saveNumpy('/tmp/sample_%s.png' % sample.split('/')[-1],
 
            #          f(picSample))
 
            dist = self._imgDist(pic0Blur, picSample)
 
            sampleDist[sample] = dist
 
            sampleDist[sample] = dist.distanceTo(picSample)
 
        results = [(d, uri) for uri, d in sampleDist.items()]
 
        results.sort()
 

	
 
        sample = results[0][1]
 

	
 
        # this is wrong; some wrong-alignments ought to be dimmer than full
 
@@ -169,43 +169,45 @@ class Solver(object):
 
        # missing color scale, but it was wrong to operate on all devs at once
 
        return s
 

	
 
    def solveBrute(self, painting):
 
        pic0 = self.draw(painting).astype(numpy.float)
 

	
 
        colorSteps = 3
 
        colorSteps = 2
 
        colorStep = 1. / colorSteps
 

	
 
        # use toVector then add ranges
 
        dims = [
 
            (DEV['aura1'], L9['rx'], [slice(.2, .7+.1, .1)]),
 
            (DEV['aura1'], L9['rx'], [slice(.2, .7+.1, .2)]),
 
            (DEV['aura1'], L9['ry'], [slice(.573, .573+1, 1)]),
 
            (DEV['aura1'], L9['color'], [slice(0, 1 + colorStep, colorStep),
 
                                         slice(0, 1 + colorStep, colorStep),
 
                                         slice(0, 1 + colorStep, colorStep)]),
 
        ]
 
        
 
        deviceAttrFilter = [(d, a) for d,a,s in dims]
 

	
 
        dist = ImageDist(pic0)
 
        def drawError(x):
 
            settings = DeviceSettings.fromVector(self.graph, x)
 
            settings = DeviceSettings.fromVector(self.graph, x, deviceAttrFilter=deviceAttrFilter)
 
            preview = self.combineImages(self.simulationLayers(settings))
 
            saveNumpy('/tmp/x_%s.png' % abs(hash(settings)), preview)
 
            #saveNumpy('/tmp/x_%s.png' % abs(hash(settings)), preview)
 
            
 
            diff = preview.astype(numpy.float) - pic0
 
            out = scipy.sum(abs(diff))
 
            out = dist.distanceTo(preview)
 
            
 
            #print 'measure at', x, 'drawError=', out
 
            return out
 
            
 
        x0, fval, grid, Jout = scipy.optimize.brute(
 
            drawError,
 
            sum([s for dev, da, s in dims], []),
 
            func=drawError,
 
            ranges=sum([s for dev, da, s in dims], []),
 
            finish=None,
 
            disp=True,
 
            full_output=True)
 
        if fval > 30000:
 
            raise ValueError('solution has error of %s' % fval)
 
        return DeviceSettings.fromVector(self.graph, x0)
 
        return DeviceSettings.fromVector(self.graph, x0, deviceAttrFilter=deviceAttrFilter)
 
        
 
    def combineImages(self, layers):
 
        """make a result image from our self.samples images"""
 
        out = (self.fromPath.itervalues().next() * 0).astype(numpy.uint16)
 
        for layer in layers:
 
            colorScaled = self.fromPath[layer['path']] * layer['color']
light9/paint/solve_test.py
Show inline comments
 
@@ -5,22 +5,24 @@ from rdflib import Namespace
 
from light9.namespaces import RDF, L9, DEV
 
from light9.rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.effect.settings import DeviceSettings
 

	
 
class TestSolve(unittest.TestCase):
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                             'show/dance2017/cam/test/bg.n3'])
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48))
 
        self.graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                             'test/cam/bg.n3'])
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48), sessions=[L9['session0']])
 
        self.solver.loadSamples()
 
        self.solveMethod = self.solver.solve
 

	
 
    @unittest.skip('solveBrute unfinished')
 
    def testBlack(self):
 
        devAttrs = self.solveMethod({'strokes': []})
 
        self.assertEqual(DeviceSettings(self.graph, []), devAttrs)
 

	
 
    @unittest.skip("unfinished")
 
    def testSingleLightCloseMatch(self):
 
        devAttrs = self.solveMethod({'strokes': [{'pts': [[224, 141],
 
                                                 [223, 159]],
 
                                         'color': '#ffffff'}]})
 
        self.assertEqual(DeviceSettings(self.graph, [
 
            (DEV['aura1'], L9['color'], u"#ffffff"),
 
@@ -30,19 +32,19 @@ class TestSolve(unittest.TestCase):
 

	
 
class TestSolveBrute(TestSolve):
 
    def setUp(self):
 
        super(TestSolveBrute, self).setUp()
 
        self.solveMethod = self.solver.solveBrute
 

	
 
CAM_TEST = Namespace('http://light9.bigasterisk.com/show/dance2017/cam/test/')
 
CAM_TEST = Namespace('http://light9.bigasterisk.com/test/cam/')
 
        
 
class TestSimulationLayers(unittest.TestCase):
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                             'show/dance2017/cam/test/bg.n3'])
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48))
 
        self.graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                             'test/cam/bg.n3'])
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48), sessions=[L9['session0']])
 
        self.solver.loadSamples()
 
        
 
    def testBlack(self):
 
        self.assertEqual(
 
            [],
 
            self.solver.simulationLayers(settings=DeviceSettings(self.graph, [])))
 
@@ -74,33 +76,33 @@ class TestSimulationLayers(unittest.Test
 
            {'path': CAM_TEST['bg2-d.jpg'], 'color': (1, 1, 1)},
 
            {'path': CAM_TEST['bg2-f.jpg'], 'color': (1, 1, 1)},
 
                      ], layers)
 

	
 
class TestCombineImages(unittest.TestCase):
 
    def setUp(self):
 
        graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                        'show/dance2017/cam/test/bg.n3'])
 
        self.solver = solve.Solver(graph, imgSize=(100, 48))
 
        graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                        'test/cam/bg.n3'])
 
        self.solver = solve.Solver(graph, imgSize=(100, 48), sessions=[L9['session0']])
 
        self.solver.loadSamples()
 
    def test(self):
 
        out = self.solver.combineImages(layers=[
 
            {'path': CAM_TEST['bg2-d.jpg'], 'color': (.2, .2, .3)},
 
            {'path': CAM_TEST['bg2-a.jpg'], 'color': (.888, 0, .3)},
 
        ])
 
        solve.saveNumpy('/tmp/t.png', out)
 
        golden = solve.loadNumpy('show/dance2017/cam/test/layers_out1.png')
 
        golden = solve.loadNumpy('test/cam/layers_out1.png')
 
        numpy.testing.assert_array_equal(golden, out)
 

	
 
class TestBestMatch(unittest.TestCase):
 
    def setUp(self):
 
        graph = LocalSyncedGraph(files=['show/dance2017/cam/test/lightConfig.n3',
 
                                        'show/dance2017/cam/test/bg.n3'])
 
        self.solver = solve.Solver(graph, imgSize=(100, 48))
 
        graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                        'test/cam/bg.n3'])
 
        self.solver = solve.Solver(graph, imgSize=(100, 48), sessions=[L9['session0']])
 
        self.solver.loadSamples()
 
        
 
    def testRightSide(self):
 
        drawingOnRight = {"strokes":[{"pts":[[0.875,0.64],[0.854,0.644]],
 
                                      "color":"#aaaaaa"}]}
 
        drawImg = self.solver.draw(drawingOnRight)
 
        match, dist = self.solver.bestMatch(drawImg)
 
        self.assertEqual(L9['sample5'], match)
 
        self.assertAlmostEqual(0.06678758, dist)
 
        self.assertAlmostEqual(0.983855965, dist)
light9/rdfdb/graphfile_test.py
Show inline comments
 
@@ -13,25 +13,23 @@ class TestGraphFileOutput(unittest.TestC
 
        :foo n:bar :baz .
 
        ''')
 
        tf.flush()
 

	
 
        def getSubgraph(uri):
 
            return Graph()
 
        gf = GraphFile(mock.Mock(), tf.name, URIRef('uri'), mock.Mock(), getSubgraph)
 
        gf = GraphFile(mock.Mock(), tf.name, URIRef('uri'), mock.Mock(), getSubgraph, {}, {})
 
        gf.reread()
 
        
 
        newGraph = Graph()
 
        newGraph.add((URIRef('http://example.com/boo'),
 
                      URIRef('http://example.com/n/two'),
 
                      URIRef('http://example.com/other/ns')))
 
        gf.dirty(newGraph)
 
        gf.flush()
 
        wroteContent = open(tf.name).read()
 
        self.assertEqual('''@prefix : <http://example.com/> .
 
@prefix dev: <http://light9.bigasterisk.com/device/> .
 
@prefix effect: <http://light9.bigasterisk.com/effect/> .
 
@prefix n: <http://example.com/n/> .
 
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
 
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
 

	
light9/web/live/index.html
Show inline comments
 
@@ -90,13 +90,13 @@
 
             text-decoration: initial;
 
         }
 
        </style>
 
        <div class="device">
 
          <h2>
 
            <resource-display id="mainLabel" graph="{{graph}}" uri="{{uri}}"></resource-display>
 
            (device class <resource-display graph="{{graph}}" uri="{{deviceClass}}"></resource-display>)
 
            a <resource-display graph="{{graph}}" uri="{{deviceClass}}"></resource-display>
 
          </h2>
 
          <template is="dom-repeat" items="{{deviceAttrs}}" as="dattr">
 
            <div class="deviceAttr">
 
              <span>attr <resource-display graph="{{graph}}" uri="{{dattr.uri}}"></resource-display></span>
 
              <light9-live-control device="{{uri}}" device-attr="{{dattr}}"></light9-live-control>
 
            </div>
light9/web/resource-display.html
Show inline comments
 
@@ -41,13 +41,14 @@
 
           graph: { type: Object },
 
           uri: { type: String },
 
           label: { type: String },
 
           rename: { type: Boolean },
 
           renameTo: { type: String, notify: true },
 
       },
 
       ready: function() {
 
       observers: ['onUri(graph, uri)'],
 
       onUri: function(graph, uri) {
 
           this.graph.runHandler(this.setLabel.bind(this), `label ${this.uri}`);
 
       },
 
       setLabel: function() {
 
           if (!this.uri) {
 
               this.label = "<no uri>";
 
               return;
test/cam/bg.n3
Show inline comments
 
file renamed from show/dance2017/cam/test/bg.n3 to test/cam/bg.n3
 
@@ -4,44 +4,46 @@
 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
 
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
 

	
 
@prefix set: <http://light9.bigasterisk.com/setting/> .
 

	
 

	
 
:sample0 a :LightSample; :imagePath <http://light9.bigasterisk.com/show/dance2017/cam/test/bg2-a.jpg>;
 
:session0 a :CaptureSession;
 
     :capture :sample0, :sample1, :sample2, :sample3, :sample4, :sample5 .
 
     
 
:sample0 a :LightSample; :imagePath <http://light9.bigasterisk.com/test/cam/bg2-a.jpg>;
 
 :setting 
 
[ :device dev:aura1; :deviceAttr :color;  :scaledValue "#ffffff" ],
 
[ :device dev:aura1; :deviceAttr :rx;     :value 0.2 ],
 
[ :device dev:aura1; :deviceAttr :ry;     :value 0.573 ] .
 

	
 
:sample1 a :LightSample; :imagePath <http://light9.bigasterisk.com/show/dance2017/cam/test/bg2-b.jpg>;
 
:sample1 a :LightSample; :imagePath <http://light9.bigasterisk.com/test/cam/bg2-b.jpg>;
 
 :setting 
 
[ :device dev:aura1; :deviceAttr :color;  :scaledValue "#ffffff" ],
 
[ :device dev:aura1; :deviceAttr :rx;     :value 0.3 ],
 
[ :device dev:aura1; :deviceAttr :ry;     :value 0.573 ] .
 

	
 
:sample2 a :LightSample; :imagePath <http://light9.bigasterisk.com/show/dance2017/cam/test/bg2-c.jpg>;
 
:sample2 a :LightSample; :imagePath <http://light9.bigasterisk.com/test/cam/bg2-c.jpg>;
 
 :setting 
 
[ :device dev:aura1; :deviceAttr :color;  :scaledValue "#ffffff" ],
 
[ :device dev:aura1; :deviceAttr :rx;     :value 0.4 ],
 
[ :device dev:aura1; :deviceAttr :ry;     :value 0.573 ] .
 

	
 
:sample3 a :LightSample; :imagePath <http://light9.bigasterisk.com/show/dance2017/cam/test/bg2-d.jpg>;
 
:sample3 a :LightSample; :imagePath <http://light9.bigasterisk.com/test/cam/bg2-d.jpg>;
 
 :setting 
 
[ :device dev:aura1; :deviceAttr :color;  :scaledValue "#ffffff" ],
 
[ :device dev:aura1; :deviceAttr :rx;     :value 0.5 ],
 
[ :device dev:aura1; :deviceAttr :ry;     :value 0.573 ] .
 

	
 
:sample4 a :LightSample; :imagePath <http://light9.bigasterisk.com/show/dance2017/cam/test/bg2-e.jpg>;
 
:sample4 a :LightSample; :imagePath <http://light9.bigasterisk.com/test/cam/bg2-e.jpg>;
 
 :setting 
 
[ :device dev:aura1; :deviceAttr :color;  :scaledValue "#ffffff" ],
 
[ :device dev:aura1; :deviceAttr :rx;     :value 0.6 ],
 
[ :device dev:aura1; :deviceAttr :ry;     :value 0.573 ] .
 

	
 
# note: different device
 
:sample5 a :LightSample; :imagePath <http://light9.bigasterisk.com/show/dance2017/cam/test/bg2-f.jpg>;
 
:sample5 a :LightSample; :imagePath <http://light9.bigasterisk.com/test/cam/bg2-f.jpg>;
 
 :setting 
 
[ :device dev:aura2; :deviceAttr :color;  :scaledValue "#ffffff" ],
 
[ :device dev:aura2; :deviceAttr :rx;     :value 0.7 ],
 
[ :device dev:aura2; :deviceAttr :ry;     :value 0.573 ] .
 

	
test/cam/bg2-a.jpg
Show inline comments
 
file renamed from show/dance2017/cam/test/bg2-a.jpg to test/cam/bg2-a.jpg
Show images
test/cam/bg2-b.jpg
Show inline comments
 
file renamed from show/dance2017/cam/test/bg2-b.jpg to test/cam/bg2-b.jpg
Show images
test/cam/bg2-c.jpg
Show inline comments
 
file renamed from show/dance2017/cam/test/bg2-c.jpg to test/cam/bg2-c.jpg
Show images
test/cam/bg2-d.jpg
Show inline comments
 
file renamed from show/dance2017/cam/test/bg2-d.jpg to test/cam/bg2-d.jpg
Show images
test/cam/bg2-e.jpg
Show inline comments
 
file renamed from show/dance2017/cam/test/bg2-e.jpg to test/cam/bg2-e.jpg
Show images
test/cam/bg2-f.jpg
Show inline comments
 
file renamed from show/dance2017/cam/test/bg2-f.jpg to test/cam/bg2-f.jpg
Show images
test/cam/layers_out1.png
Show inline comments
 
file renamed from show/dance2017/cam/test/layers_out1.png to test/cam/layers_out1.png
Show images
test/cam/lightConfig.n3
Show inline comments
 
file renamed from show/dance2017/cam/test/lightConfig.n3 to test/cam/lightConfig.n3
 
@prefix : <http://light9.bigasterisk.com/> .
 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 
@prefix dev: <http://light9.bigasterisk.com/device/> .
 
@prefix udmxB: <http://light9.bigasterisk.com/output/udmx/> .
 

	
 
:color              a :DeviceAttr; :dataType :color .
 
:rx                 a :DeviceAttr; :dataType :angle .
 
:ry                 a :DeviceAttr; :dataType :angle .
 
:zoom               a :DeviceAttr; :dataType :scalar .
 

	
 
:MacAura a :DeviceClass; rdfs:label "MacAura";
 
  :deviceAttr :color, :rx, :ry, :zoom;
 
  :attr
 
    [ :dmxOffset 0 ; :outputAttr :shutter ], # use 22
 
    [ :dmxOffset 1 ; :outputAttr :dimmer ],
 
    [ :dmxOffset 2 ; :outputAttr :zoom ],
 
    [ :dmxOffset 3 ; :outputAttr :pan ],
 
    [ :dmxOffset 4 ; :outputAttr :panFine ],
 
    [ :dmxOffset 5 ; :outputAttr :tilt ],
 
    [ :dmxOffset 6 ; :outputAttr :tiltFine ],
 
    [ :dmxOffset 7 ; :outputAttr :fixtureControl ], # use 0
 
    [ :dmxOffset 8 ; :outputAttr :colorWheel ], # use 0
 
    [ :dmxOffset 9 ; :outputAttr :red ],
 
    [ :dmxOffset 10 ; :outputAttr :green ],
 
    [ :dmxOffset 11 ; :outputAttr :blue ],
 
    [ :dmxOffset 12 ; :outputAttr :white ],
 
    [ :dmxOffset 13 ; :outputAttr :colorTemperature ],
 
    [ :dmxOffset 14 ; :outputAttr :fx1Select ],
 
    [ :dmxOffset 15 ; :outputAttr :fx1Adjust ],
 
    [ :dmxOffset 16 ; :outputAttr :fx2Select ],
 
    [ :dmxOffset 17 ; :outputAttr :fx2Adjust ],
 
    [ :dmxOffset 18 ; :outputAttr :fxSync ],
 
    [ :dmxOffset 19 ; :outputAttr :auraShutter ], # use 22
 
    [ :dmxOffset 20 ; :outputAttr :auraDimmer ],
 
    [ :dmxOffset 21 ; :outputAttr :auraColorWheel ],
 
    [ :dmxOffset 22 ; :outputAttr :auraRed ],
 
    [ :dmxOffset 23 ; :outputAttr :auraGreen ],
 
    [ :dmxOffset 24 ; :outputAttr :auraBlue ] .
 

	
 

	
 
dev:aura1 a :MacAura; rdfs:label "aura1"; :dmxUniverse udmxB:; :dmxBase 406 .
 
dev:aura2 a :MacAura; rdfs:label "aura2"; :dmxUniverse udmxB:; :dmxBase 420 .
 
dev:aura3 a :MacAura; rdfs:label "aura3"; :dmxUniverse udmxB:; :dmxBase 434 .
 
dev:aura4 a :MacAura; rdfs:label "aura4"; :dmxUniverse udmxB:; :dmxBase 448 .
 
dev:aura5 a :MacAura; rdfs:label "aura5"; :dmxUniverse udmxB:; :dmxBase 462 .
 

	
 
dev:aura1 :outputAttrRange dev:aura1rx . dev:aura1rx :outputAttr :rx; :start 0.145; :end 0.275 .
 
dev:aura2 :outputAttrRange dev:aura2rx . dev:aura2rx :outputAttr :rx; :start 0.096; :end 0.259 .
 
dev:aura3 :outputAttrRange dev:aura3rx . dev:aura3rx :outputAttr :rx; :start 0.068; :end 0.25 .
 
dev:aura4 :outputAttrRange dev:aura4rx . dev:aura4rx :outputAttr :rx; :start 0.065; :end 0.21 .
 
dev:aura5 :outputAttrRange dev:aura5rx . dev:aura5rx :outputAttr :rx; :start 0.06; :end 0.194 .
 

	
 
dev:aura1 :outputAttrRange dev:aura1ry . dev:aura1ry :outputAttr :ry; :start 0.239; :end 0.153 .
 
dev:aura2 :outputAttrRange dev:aura2ry . dev:aura2ry :outputAttr :ry; :start 0.248; :end 0.148 .
 
dev:aura3 :outputAttrRange dev:aura3ry . dev:aura3ry :outputAttr :ry; :start 0.260; :end 0.151 .
 
dev:aura4 :outputAttrRange dev:aura4ry . dev:aura4ry :outputAttr :ry; :start 0.250; :end 0.153 .
 
dev:aura5 :outputAttrRange dev:aura5ry . dev:aura5ry :outputAttr :ry; :start 0.241; :end 0.151 .
 

	
0 comments (0 inline, 0 general)