Update the genome specs a bit

This commit is contained in:
Steven Robertson 2012-04-14 22:55:00 -07:00
parent ee2d571e9d
commit a4178c60fb
6 changed files with 58 additions and 62 deletions

View File

@ -118,7 +118,4 @@ class ColorClip(Filter, ClsMod):
filter_map = dict(bilateral=Bilateral, logscale=Logscale, haloclip=HaloClip,
colorclip=ColorClip)
def create(gprof):
# TODO: redesign this (should not have to care about internals of
# use.Wrapper in order to find types from TypedList elements)
filts = gprof._val.get('filters') or gprof.spec['filters'].defaults
return [filter_map[f['type']]() for f in filts]
return [filter_map[f]() for f in gprof.filter_order]

View File

@ -105,9 +105,7 @@ def convert_xforms(flame):
xfs.update(make_symm_xforms(float(flame['symmetry']), len(xfs)))
return xfs
split_to_dict = lambda keys: lambda v: dict(zip(keys, map(float, v.split())))
pair = split_to_dict('xy')
rgb_triple = split_to_dict('rgb')
pair = lambda v: dict(zip('xy', map(float, v.split())))
xform_structure = (
('pre_affine', 'coefs', convert_affine),
@ -125,22 +123,20 @@ xform_structure = (
# (dst, cvt_dict) for properties that are built from multiple source keys.
# If a function returns 'None', its key is dropped from the result.
flame_structure = (
('info.author', 'nick', str),
('info.author_url', 'url', lambda s: 'http://' + str(s)),
('info.name', 'name', str),
('author.name', 'nick', str),
('author.url', 'url', lambda s: 'http://' + str(s)),
('name', 'name', str),
('camera.center', 'center', pair),
('camera.rotation', 'rotate', float),
('camera.dither_width', 'filter', float),
('camera.center', 'center', pair),
('camera.rotation', 'rotate', float),
('camera.dither_width', 'filter', float),
('camera.scale',
lambda d: float(d['scale']) / float(d['size'].split()[0])),
('filters.colorclip.gamma', 'filter', float),
('filters.colorclip.gamma', 'gamma', float),
('filters.colorclip.gamma_threshold', 'gamma_threshold', float),
('filters.colorclip.highlight_power', 'highlight_power', float),
('filters.colorclip.vibrance', 'vibrancy', float),
# Not sure about putting this one on colorclip
('filters.colorclip.background', 'background', rgb_triple),
('filters.de.curve', 'estimator_curve', float),
('filters.de.radius', 'estimator_radius', float),
@ -149,6 +145,8 @@ flame_structure = (
float(d.get('estimator_radius', 11)))
if 'estimator_minimum' in d else None),
('filters.logscale.brightness', 'brightness', float),
('palette', 'palette', util.palette_encode),
('xforms', convert_xforms),
('final_xform', 'finalxform', convert_xform),

View File

@ -18,12 +18,16 @@ xform = (
, 'variations': var_params
})
# Since the structure of the info element differs between anims, nodes and
# edges, we pull out some of the common elements here
author = String('Attribution in the form: "Name [<email>][, url]"')
name = String('A human-readable name for this entity')
src = String('The identifier of the source node')
dst = String('The identifier of the destination node')
author = (
{ 'name': String("Human-readable name of author")
, 'user': String("Email or other unique identifier")
, 'url': String("Website or other link provided by author")
})
link = (
{ 'src': String("Origin node ID and temporal offset")
, 'dst': String("Destination node ID and temporal offset")
})
filters = (
{ 'bilateral':
@ -39,7 +43,7 @@ filters = (
, 'colorclip':
{ 'gamma': scalespline(4)
, 'gamma_threshold': spline(0.01, 0, 1)
, 'highlight_power': spline(-1, -1, 1)
, 'highlight_power': spline(-1, -1)
, 'vibrance': scalespline()
}
, 'de':
@ -65,37 +69,33 @@ time = (
})
base = (
{ 'camera': camera
{ 'name': String("Human-readable name of this work")
, 'camera': camera
, 'filters': filters
, 'palette': list_(Palette())
, 'xforms': map_(xform)
, 'final_xform': xform
})
anim = dict(base)
anim.update(type='animation', time=time,
info=dict(authors=list_(author), name=name, src=src, dst=dst,
origin=string_()))
# TODO
node = dict(base)
node.update(type='node', info=dict(author=author, author_url=string_(),
id=string_(), name=name))
node.update(type='node', blend=blend, author=author)
# TODO
edge = dict(anim)
edge.update(type='edge',
info=dict(author=author, id=string_(), src=src, dst=dst),
edge = dict(base)
edge.update(type='edge', author=author, blend=blend, link=link, time=time,
xforms=dict(src=map_(xform), dst=map_(xform)))
anim = dict(base)
anim.update(type='animation', authors=list_(author), link=link, time=time)
default_filters = ['bilateral', 'logscale', 'colorclip']
# Yeah, now I'm just messing around.
prof_filters = dict([(fk, dict([(k, refscalar(1, '.'.join(['filters', fk, k])))
for k in fv])) for fk, fv in filters.items()])
# And here's a completely stupid hack to drag scale into the logscale filter
prof_filters['logscale']['scale'] = refscalar(1, 'camera.scale')
default_filters = [{'type': k} for k in ['bilateral', 'logscale', 'colorclip']]
profile = (
{ 'duration': RefScalar(30, 'time.duration', 'Base duration in seconds')
, 'fps': Scalar(24, 'Frames per second')
@ -104,8 +104,8 @@ profile = (
, 'frame_width': refscalar(1, 'time.frame_width')
, 'spp': RefScalar(2000, 'camera.spp', 'Base samples per pixel')
, 'skip': Scalar(0, 'Skip this many frames between each rendered frame')
, 'filters': TypedList(prof_filters, default_filters,
'Ordered list of filters to apply')
, 'filter_order': list_(enum(filters.keys()), default_filters)
, 'filters': prof_filters
})
# Types recognized as independent units with a 'type' key

View File

@ -3,13 +3,8 @@ from collections import namedtuple
Map = namedtuple('Map', 'type doc')
map_ = lambda type, d=None: Map(type, d)
List = namedtuple('List', 'type doc')
list_ = lambda type, d=None: List(type, d)
# A list as above, but where each element is a dict with a 'type' parameter
# corresponding to one of the specs listed in the 'types' dict on this spec.
TypedList = namedtuple('TypedList', 'types defaults doc')
typedlist = lambda types, defaults=[], d=None: TypedList(types, defaults, d)
List = namedtuple('List', 'type default doc')
list_ = lambda type, default=(), d=None: List(type, default, d)
Spline = namedtuple('Spline', 'default min max interp period doc var')
def spline(default=0, min=None, max=None, interp='linear', period=None, d=None):
@ -37,9 +32,11 @@ refscalar = lambda default, ref, d=None: RefScalar(default, ref, d)
String = namedtuple('String', 'doc')
def string_(d=None):
return String(d)
Enum = namedtuple('Enum', 'choices doc')
def enum(choices, d=None):
"""Enum helper. 'choices' is a space-separated string."""
return Enum(choices.split(), d)
Enum = namedtuple('Enum', 'choices default doc')
def enum(choices, default=None, d=None):
"""Enum helper. 'choices' is a list or a space-separated string."""
if isinstance(choices, basestring):
choices = choices.split()
return Enum(choices, default, d)
Palette = namedtuple('Palette', '')

View File

@ -1,18 +1,26 @@
import numpy as np
from spectypes import Spline, Scalar, RefScalar, Map, List, TypedList
from spectypes import Enum, Spline, Scalar, RefScalar, Map, List
from specs import toplevels
class Wrapper(object):
"""
Weird reverse visitor. Traversals of the tree are normally done externally
(via property accessors, in a lot of cases). This class alters the
returned representation of the underlying genome according to the provided
spec without imposing flow control.
"""
def __init__(self, val, spec=None, path=()):
if spec is None:
assert val.get('type') in toplevels, 'Unrecognized dict type'
spec = toplevels[val['type']]
# plain 'val' would conflict with some variation property names
self._val, self.spec, self.path = val, spec, path
def wrap(self, name, spec, val):
# Oh, a visitor. How... pedestrian.
path = self.path + (name,)
if isinstance(spec, Enum):
return self.wrap_enum(path, spec, val)
if isinstance(spec, Spline):
return self.wrap_spline(path, spec, val)
elif isinstance(spec, Scalar):
@ -25,13 +33,14 @@ class Wrapper(object):
return self.wrap_Map(path, spec, val)
elif isinstance(spec, List):
return self.wrap_List(path, spec, val)
elif isinstance(spec, TypedList):
return self.wrap_TypedList(path, spec, val)
return self.wrap_default(path, spec, val)
def wrap_default(self, path, spec, val):
return val
def wrap_enum(self, path, spec, val):
return val or spec.default
def wrap_spline(self, path, spec, val):
return val
@ -45,12 +54,8 @@ class Wrapper(object):
return self.wrap_dict(path, spec, val)
def wrap_List(self, path, spec, val):
return [self.wrap(spec.type, v) for v in val]
def wrap_TypedList(self, path, spec, val):
val = val if val is not None else spec.defaults
return [self.wrap(path+(str(i),), spec.types[v['type']], v)
for i, v in enumerate(val)]
val = val if val is not None else spec.default
return [self.wrap(path, spec.type, v) for v in val]
def get_spec(self, name):
if isinstance(self.spec, Map):
@ -73,7 +78,6 @@ class Wrapper(object):
def __getitem__(self, name):
return getattr(self, str(name))
class RefWrapper(Wrapper):
"""
Wrapper that handles RefScalars, as with profile objects.

View File

@ -210,7 +210,6 @@ class Renderer(object):
del self._modrefs[:]
self._modrefs.append(self.mod)
# TODO: make these customizable
self.filts = filters.create(gprof)
self.out = output.PILOutput()
@ -359,7 +358,8 @@ class RenderManager(ClsMod):
self._iter(rdr, gnm, gprof, dim, tc)
if self.copy_evt:
self.stream_a.wait_for_event(self.copy_evt)
for filt, params in zip(rdr.filts, gprof.filters):
for filt, name in zip(rdr.filts, gprof.filter_order):
params = getattr(gprof.filters, name)
filt.apply(self.fb, gprof, params, dim, tc, self.stream_a)
rdr.out.convert(self.fb, gprof, dim, self.stream_a)
self.filt_evt = cuda.Event().record(self.stream_a)