Source code for pycropml.xml2wf

from __future__ import absolute_import
from __future__ import print_function
import sys
try:
    from openalea.core.external import *
    from openalea.core.pkgmanager import PackageManager
    from openalea.core import node
except:
    inter = None
    package = None
    node = None
    has_openalea = False
    
from pycropml.render_python import generate_doc
from pycropml.pparse import model_parser


[docs] class XmlToWf: def __init__(self, xmlwf,dir_, pkg_name): self.xmlwf = xmlwf self.dir=dir_ self.pkg_name = pkg_name self.inputLinks = self.xmlwf.inputlink self.outputLinks = self.xmlwf.outputlink self.internalLinks = self.xmlwf.internallink self.diff_in = self.xmlwf.diff_in self.diff_out = self.xmlwf.diff_out #print(self.diff_in) #print(self.diff_out) self.inputs = [] self.outputs = []
[docs] def run(self, pkg=None): self.doc = generate_doc(self.xmlwf) if pkg is None: self.pkg = self.retrievePackage(self.pkg_name) else: self.pkg = pkg self.compositeNodeInputs() self.compositeNodeOutputs() self.wf = CompositeNode(self.inputs_wf, self.outputs_wf) self.createNodes() # BUG: replace doc with description wf_factory = CompositeNodeFactory(self.xmlwf.name, description=self.doc) self.connectOutputs() self.connectInputs() self.connectInternal() self.layout() self.wf.to_factory(wf_factory) if wf_factory.name in self.pkg: del self.pkg[wf_factory.name] self.pkg.add_factory(wf_factory)
[docs] def retrievePackage(self, name): pm = PackageManager() pm.init(self.dir, False) print(pm.keys()) surname = name.split('.')[-1] pkg = pm[name] if name in pm else pm[surname] return pkg
[docs] def compoPack(self, name): for model in self.xmlwf.model: if model.name == name and model.package_name: self.dir = model.path
[docs] def compareInterface(self,interfaces): test= True n = 1 while(test and n!=len(interfaces)): if interfaces[n].min != interfaces[n-1].min: test=False break elif interfaces[n].max!=interfaces[n-1].max: test=False break elif interfaces[n].step!=interfaces[n-1].step: test=False break elif type(interfaces[n])!=type(interfaces[n-1]): test=False break n=n+1 return test
[docs] def compositeNodeInputs(self): ins=[] names = [] for link in self.inputLinks: name = link["source"] if name not in names: names.append(name) # some models can have the same inputs. These inputs must have the same interfaces for name in names: links_sameName = [link for link in self.inputLinks if link["source"]==name] #print(links_sameName) if len(links_sameName)!=1: interfaces=[] try: for j in links_sameName: model= j["target"].split('.')[0] inputs = self.pkg[model].inputs interface=[inp["interface"] for inp in inputs if inp["name"]==name] interfaces.append(interface[0]) #assert self.compareInterface(interfaces)== True except AssertionError: print(("inequal interface: %s %s"% (interfaces, links_sameName))) for inp in inputs: if inp["name"]==name and "value" in inp: value=inp["value"] break if value: din=dict(name=name, interface = interfaces[0], value=value) else: din=dict(name=name, interface = interfaces[0]) ins.append(din) self.inputs.append(name) else: value=None model= links_sameName[0]["target"].split('.')[0] if model in self.pkg: inputs = self.pkg[model].inputs if name in list(self.diff_in.values()): name = findname(name, self.diff_in) interface=[inp["interface"] for inp in inputs if inp["name"]==name] for inp in inputs: if inp["name"]==name and "value" in inp: value=inp["value"] break if value: din=dict(name=name, interface = interface[0], value=value) else: din=dict(name=name, interface = interface[0]) ins.append(din) self.inputs.append(name) self.inputs_wf = ins
[docs] def compositeNodeOutputs(self): outs=[] # model units outputs must be unique. So model composite output is targeted by an unique output link for link in self.outputLinks: name = link["target"] if name in list(self.diff_out.values()): name = findname(name, self.diff_out) model_src, out_src= link["source"].split('.') if model_src in self.pkg: outputs = self.pkg[model_src].outputs interface=[out["interface"] for out in outputs if out["name"]==name] dout= dict(name=name, interface = interface[0]) outs.append(dout) self.outputs.append(name) self.outputs_wf = outs
[docs] def createNodes(self): self.nodes = {} for m in self.xmlwf.model: if m.name in self.pkg: print('Node: ', m.name) nf = self.pkg[m.name].instantiate() nid = self.wf.add_node(nf) self.nodes[m.name] = nid
[docs] def connectInputs(self): for link in self.inputLinks: src, tgt = link['source'], link['target'] if src in list(self.diff_in.values()): src = findname(src, self.diff_in) port_out = src name_tgt, port_in = tgt.split('.') if name_tgt in self.nodes: ns, nt = self.wf.id_in, self.nodes[name_tgt] try: pout, pin = self.wf.node(ns).map_index_out[port_out], self.wf.node(nt).map_index_in[port_in] except KeyError: if port_out not in self.wf.node(ns).map_index_out: print('Error input link src : ', src) else: print(('Error input link tgt: ', tgt)) continue self.wf.connect(ns, pout, nt, pin)
[docs] def connectOutputs(self): for link in self.outputLinks: src, tgt = link['source'], link['target'] if tgt in list(self.diff_out.values()): tgt = findname(tgt, self.diff_out) name_src, port_out = src.split('.') port_in = tgt if name_src in self.nodes: ns, nt = self.nodes[name_src], self.wf.id_out try: pout, pin = self.wf.node(ns).map_index_out[port_out], self.wf.node(nt).map_index_in[port_in] except KeyError: if port_out not in self.wf.node(ns).map_index_out: print('Error output link src: ', src) else: print(('Error output link tgt: ', tgt)) continue self.wf.connect(ns, pout, nt, pin)
[docs] def connectInternal(self): for link in self.internalLinks: src, tgt = link['source'], link['target'] name_src, port_out = src.split('.') name_tgt, port_in = tgt.split('.') if name_tgt in self.nodes and name_src in self.nodes: ns, nt = self.nodes[name_src], self.nodes[name_tgt] try: pout, pin =self.wf.node(ns).map_index_out[port_out], self.wf.node(nt).map_index_in[port_in] except KeyError: if port_out not in self.wf.node(ns).map_index_out: print('Error : ', src) else: print(('Error : ', tgt)) continue self.wf.connect(ns, pout, nt, pin)
[docs] def layout(self): """ Compute automatic layout of nodes""" sg = self.wf # 1. defaults size = 500 n_in, n_out = 0, 1 d_in = sg.node(n_in).internal_data d_in['posx'] = size/2 d_in['posy'] = 0 d_out = sg.node(n_out).internal_data d_out['posx'] = size/2 d_out['posy'] = size # compute max_lentgh_path all_paths = [[0]] height, width = max_path_height_and_width(sg, all_paths, 1) height -=1 width -= 1 dy = size / max(height,1) dx = size / max(width,1) x, y = 0, 0 compute_layout(sg, n_in, x, dx, y, dy) #elt_data = wf_factory.elt_data #ad_hoc = wf_factory. for vid in sg.vertices(): x = sg.node(vid).internal_data['posx'] y = sg.node(vid).internal_data['posy'] sg.node(vid).get_ad_hoc_dict().set_metadata('position', [x,y])
[docs] def findname(val, dictionary): for k, v in dictionary.items(): if v == val: return k return None
[docs] def max_path_height_and_width(sg, paths, stop=1): """ Compute the max length of all paths from in to out node. """ res = [] done = False max_height = 0 max_width = 0 while not done: res = [] for p in paths: vid = p[-1] if vid == stop: max_height = max(len(p), max_height) max_width += 1 else: l = list(sg.out_neighbors(vid)) for v in l: res.append(p+[v]) if not res: done = True else: paths = res return max_height, max_width
[docs] def compute_layout(sg, vid, x, dx, y, dy): l = list(sg.out_neighbors(vid)) n = len(l) new_y = y+dy x0 = x - int((n-1) * dx / 2) for v in l: if v == 1: continue data = sg.node(v).internal_data ny = data['posy'] = new_y nx = data['posx'] = x0 x0 += dx compute_layout(sg, v, nx, dx, ny, dy)