Source code for openalea.rsml.measurements

"""
Module that provide measuring tools on continuous RSML-type MTG
"""
from openalea.mtg import MTG 

from .misc import root_vertices
from .misc import root_tree
from .misc import root_order

def _segment_length(geometry):
    """ return an array of the segment length along the root `geometry` """
    import numpy as np
    pos = np.array(geometry)
    vec = np.diff(pos,axis=0)**2
    return (vec.sum(axis=1)**.5)


[docs] def root_length(g, roots=None): """ return a dictionary of (root, root-length) """ geometry = g.property('geometry') length = g.properties().get('length',{}).copy() if roots is None: roots=root_vertices(g) for root in roots: if root not in length: geom = geometry.get(root) if geom is None: length[root] = 0 else: length[root] = _segment_length(geom).sum() return length
[docs] def parent_position(g, distance2tip=False, roots=None): """ (Try to) compute the parent postion of root sub-axes The parent position is computed as follow: - Use the root axe 'parent-position' property, if present, - Otherwise, compute it using 'parent-node', if present, - Otherwise, return None The values are returned as a dictionary of (root-id, root-parent-position) for all `root-id` in `roots`, if given, or all root axes in `g` otherwise if `distance2tip`==True, the return calues are the distance from the branching position to the tip of the parent axes. """ parent_pos0 = g.properties().get('parent-position', {}) parent_node = g.properties().get('parent-node', {}) # root arclength computed for parent of subaxes with parent_node prop cumlen = {} geometry = g.properties().get('geometry') def cumlength(root): if root not in cumlen: cumlen[root] = _segment_length(geometry[root]).cumsum() return cumlen[root] def get_branching_distance(root): if root not in parent_node: return None pnode = parent_node[root] if pnode==0: return 0 parent = g.parent(root) clen = cumlength(parent) if distance2tip: return clen[-1] - clen[pnode-1] else: return clen[pnode-1] # parse all root axes parent_pos = {} if roots is None: roots = root_vertices(g) for root in roots: if root in parent_pos0: parent_pos[root] = parent_pos0[root] else: parent_pos[root] = get_branching_distance(root) return parent_pos
[docs] class RSML_Measurements(list): """ Class to store a list of root measurements Root are stored in tree order (i.e. depth-first-order) Each row is a dictionary of measurements use the `add` method to add measurements from a root MTG """ def __init__(self): """ Contrust a RSML_Measurement """ pass
[docs] def add(self, g, name=None): """ Add measurements of roots in `g` """ from . import properties as prop parpos = parent_position(g) tree = root_tree(g, suborder=parpos) order = root_order(g, tree=tree) length = root_length(g) ids = prop.set_ids(g) acc = prop.set_accession(g, root_order=order) parent = [(root,g.parent(root)) for root in tree] parent = dict((r, None if p is None else ids[p]) for r,p in parent) table = [None]*len(tree) for i,root in enumerate(tree): table[i] = dict(id=ids[root], order=order[root], accession=acc[root], parent=parent[root], parent_position=parpos[root], length=length[root], name=name) self.extend(table) return self
[docs] def export_csv(self, filename, sep='\t'): """ export file `filename` with csv format Use `sep` as csv file separator """ keys = ['name','id','order','accession','parent','parent_position','length'] default = ' '*len(keys) # convert table entries to a list of string, then table rows to string csv = [list(map(str,list(map(row.get,keys,default)))) for row in self] csv = [sep.join(row)+'\n' for row in csv] # export to given filename with open(filename,'w') as f: f.write(sep.join(keys)+'\n') f.writelines(csv)
[docs] def import_csv(self, filename, sep='\t'): from csv import reader from ast import literal_eval def try_eval(s): try: return literal_eval(s) except: return s with open(filename) as f: content = reader(f,delimiter=sep) keys = next(content) for row in content: self.append(dict(list(zip(keys,list(map(try_eval,row))))))