def parse_extern_modules(lpyfile): """ Parse an lpyfile to retrieve its modules and expected extern parameters """ lines = list(open(lpyfile).readlines()) externs = set() def f(**kwd): nonlocal externs externs = externs.union(set(kwd.keys())) code = ''.join([l for l in lines if l.startswith('extern')]) n = {'extern' : f, 'externs' : externs} exec(code, n, n) code2 = ''.join([l for l in lines if l.startswith('module')]) from openalea.lpy import Lsystem l = Lsystem() l.setCode(code2) l.makeCurrent() modules = {} for m in l.execContext().declaredModules(): modules[m.name] = m.parameterNames l.done() return externs, modules
""" N = 2 derivation length: N production: F(x) : produce F(x/3.0)+F(x/3.0)--F(x/3.0)+F(x/3.0) endlsystem ''' lsystem.setCode(str(code), context) lsystem.axiom = "_(0.01)-(90)F(1)" print('\n----lsystem:') print(lsystem) print('\n----axialtree:', axialtree) axialtree = lsystem.iterate(3) print('\n----lsystem:') print(lsystem) print('\n----axialtree:', axialtree) lsystem.getLastIterationNb() # iterate 4 -> getLastIterationNb == 3 lsystem.derivationLength # see keyword in lpy code
class LPyModel(PythonModel): dtype = 'LSystem' mimetype = 'text/vnd-lpy' def __init__(self, *args, **kwargs): PythonModel.__init__(self, *args, **kwargs) if self.name is None: self.name = 'LPyModel' self._step = 1 self.lsystem = Lsystem() self.axialtree = AxialTree() self.scene_name = self.name + '_scene' def __copy__(self): m = PythonModel.__copy__(self) m.set_code(self._initial_code) m.lsystem = self.lsystem m.axialtree = self.axialtree m.scene_name = self.scene_name return m def init(self, *args, **kwds): self._step = 1 self._push_ns() self._fill_namespace(*args, **kwds) # BEGIN ACTUAL CODE RUN self.lsystem.setCode(str(self.code), self._ns) if "axiom" in self._ns and self._ns['axiom']: self.lsystem.axiom = self._ns['axiom'] elif "lstring" in self._ns and self._ns['lstring']: self.lsystem.axiom = self._ns['lstring'] self.axialtree = self.lsystem.axiom # END ACTUAL CODE RUN self._populate_ns() self._pop_ns() return self.output_from_ns(self._ns) def output_from_ns(self, namespace): # get outputs from namespace outputs = [] if self.outputs_info: if len(self.outputs_info) > 0: for outp in self.outputs_info: if outp.name.lower() in ["axialtree", "lstring"]: outputs.append(self.axialtree) elif outp.name.lower() == "lsystem": outputs.append(self.lsystem) elif outp.name.lower() == "scene": outputs.append(self.lsystem.sceneInterpretation(self.axialtree)) elif outp.name in namespace: outputs.append(namespace[outp.name]) else: continue # Add output to namespace # if output is not in namespace, this line is not run (see "continue" above) self._ns[outp.name] = outputs[-1] if len(outputs) == 0: return None elif len(outputs) == 1: return outputs[0] else: return outputs def run(self, *args, **kwds): nstep = kwds.pop('nstep', None) self.init(*args, **kwds) if nstep is None: self.axialtree = self.lsystem.iterate() else: self.axialtree = self.lsystem.iterate(nstep) self.lsystem.context().getNamespace(self._ns) self.outputs = self.output_from_ns(self._ns) return self.outputs def step(self, *args, **kwds): nstep = kwds.pop('nstep', None) if self._step > self.lsystem.derivationLength: self._step = 0 if nstep is None: self.axialtree = self.lsystem.iterate(self._step) else: self.axialtree = self.lsystem.iterate(nstep) self.outputs = self.output_from_ns(self._ns) self._step += 1 return self.outputs def animate(self, *args, **kwds): self.init() self.axialtree = self.lsystem.animate() self.outputs = self.output_from_ns(self._ns) self._step = self.lsystem.derivationLength + 1 return self.outputs def set_code(self, code): """ Set the content and parse it to get docstring, inputs and outputs info, some methods """ self._initial_code, control = import_lpy_file(code) self._doc = get_docstring(code) docstring = parse_lpy(code) if docstring is not None: model, self.inputs_info, self.outputs_info = parse_doc(docstring) # Default input if self.inputs_info == []: self.inputs_info = [InputObj('lstring:IStr')] # Default output if self.outputs_info == []: self.outputs_info = [OutputObj("lstring:IStr")] def _set_code(self, code): self.set_code(code) def _set_axialtree(self, axialtree): self._axialtree = adapt_axialtree(axialtree, self.lsystem) code = property(fget=lambda self: self._initial_code, fset=_set_code) axialtree = property(fget=lambda self: self._axialtree, fset=_set_axialtree)