Mercurial > code > home > repos > light9
view light9/curvecalc/subterm.py @ 1536:7a85229d07a0
currentgraphstate now returns readonly (not actually snapshotted) view of the graph, not a copy
Ignore-this: 7db0291740fe8dee0ad25b24571b171b
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Thu, 11 May 2017 05:20:15 +0000 |
parents | 512381de45bd |
children | 6fa4288da8a6 |
line wrap: on
line source
import math, os, random, logging from rdflib import Graph, URIRef, RDF, RDFS, Literal from louie import dispatcher import light9.Effects from light9 import Submaster, showconfig, prof from light9.Patch import get_dmx_channel from light9.rdfdb.patch import Patch from light9.namespaces import L9 log = logging.getLogger() class Expr(object): """singleton, provides functions for use in subterm expressions, e.g. chases""" def __init__(self): self.effectGlobals = light9.Effects.configExprGlobals() def exprGlobals(self, startDict, t): """globals dict for use by expressions""" glo = startDict.copy() # add in functions from Effects glo.update(self.effectGlobals) def chan(name): return Submaster.Submaster( name=name, levels={get_dmx_channel(name) : 1.0}) glo['chan'] = chan glo['within'] = lambda a, b: a < t < b glo['bef'] = lambda x: t < x def aft(t, x, smooth=0): left = x - smooth / 2 right = x + smooth / 2 if left < t < right: return light9.Effects.smoove((t - left) / (right - left)) return t > x glo['aft'] = lambda x, smooth=0: aft(t, x, smooth) glo['smooth_random'] = lambda speed=1: glo['smooth_random2'](t, speed) glo['notch_random'] = lambda speed=1: glo['notch_random2'](t, speed) glo['noise'] = glo['smooth_random'] glo['notch'] = glo['notch_random'] return glo exprglo = Expr() class Subterm(object): """one Submaster and its expression evaluator""" def __init__(self, graph, subterm, saveContext, curveset): self.graph, self.uri = graph, subterm self.saveContext = saveContext self.curveset = curveset self.ensureExpression(saveContext) self.submasters = Submaster.get_global_submasters(self.graph) def ensureExpression(self, saveCtx): with self.graph.currentState(tripleFilter=(self.uri, None, None)) as current: if current.value(self.uri, L9['expression']) is None: self.graph.patch(Patch(addQuads=[ (self.uri, L9['expression'], Literal("..."), saveCtx), ])) def scaled(self, t): with self.graph.currentState(tripleFilter=(self.uri, None, None)) as current: subexpr_eval = self.eval(current, t) # we prevent any exceptions from escaping, since they cause us to # stop sending levels try: if isinstance(subexpr_eval, Submaster.Submaster): # if the expression returns a submaster, just return it return subexpr_eval else: # otherwise, return our submaster multiplied by the value # returned if subexpr_eval == 0: return Submaster.Submaster("zero", {}) subUri = current.value(self.uri, L9['sub']) sub = self.submasters.get_sub_by_uri(subUri) return sub * subexpr_eval except Exception, e: dispatcher.send("expr_error", sender=self.uri, exc=repr(e)) return Submaster.Submaster(name='Error: %s' % str(e), levels={}) def curves_used_by_expr(self): """names of curves that are (maybe) used in this expression""" with self.graph.currentState(tripleFilter=(self.uri, None, None)) as current: expr = current.value(self.uri, L9['expression']) used = [] for name in self.curveset.curveNamesInOrder(): if name in expr: used.append(name) return used def eval(self, current, t): """current graph is being passed as an optimization. It should be equivalent to use self.graph in here.""" objs = list(current.objects(self.uri, L9['expression'])) if len(objs) > 1: raise ValueError("found multiple expressions for %s: %s" % (self.uri, objs)) expr = current.value(self.uri, L9['expression']) if not expr: dispatcher.send("expr_error", sender=self.uri, exc="no expr, using 0") return 0 glo = self.curveset.globalsdict() glo['t'] = t glo = exprglo.exprGlobals(glo, t) glo['getsub'] = lambda name: self.submasters.get_sub_by_name(name) glo['chan'] = lambda name: Submaster.Submaster("chan", {get_dmx_channel(name): 1}) try: self.lasteval = eval(expr, glo) except Exception,e: dispatcher.send("expr_error", sender=self.uri, exc=e) return Submaster.Submaster("zero", {}) else: dispatcher.send("expr_error", sender=self.uri, exc="ok") return self.lasteval def __repr__(self): return "<Subterm %s>" % self.uri