from __future__ import absolute_import
from __future__ import print_function
import pandas as pd
import numpy as np
from openpyxl import load_workbook
from openalea.plantgl.all import*
from openalea.mtg import io
from openalea.mtg import algo
from openalea.lpy import *
import openalea.strawberry
from openalea.mtg import MTG, algo
from openalea.deploy.shared_data import shared_data
[docs]def name(f):
"""return base name without extension
:param f: the file path
:type f: string
:return: basename
:rtype: string
"""
return f.basename().splitext()[0]
[docs]def import_mtgfile(filename):
"""Import a MTG file from genotype name, in sharedata repo
:param filename: genotype = name of the file
:type filename: string
:return: a MTG loaded from the file
:rtype: MTG
"""
filenames = filename
files = shared_data(openalea.strawberry).glob('*.mtg')
mtg_path = dict((name(f), f) for f in files)
mtgfile = dict((k,f) for k,f in mtg_path.items() if k in filenames)
if len(filenames) == 1:
g = MTG(mtgfile[filenames[0]])
return g
else:
metaMTG= MTG()
for i in mtgfile:
metaMTG = algo.union(metaMTG, MTG(mtgfile[i]))
return metaMTG
################
[docs]def read_file(file,sheet_name,convert=None):
"""read csv file in share data repo
:param file: filename of the csv
:type file: string
:param sheet_name name of sheet csv file
:type sheet_name: string
:param convert (optional): colname conversion if need to change colname
:type convert: dict
:return: a panda dataframe load from file
:rtype: panda.DataFram
"""
xls= pd.ExcelFile(file)
df=pd.read_excel(xls,sheet_name=sheet_name)
return df
[docs]def filter_none(d):
""" filter fonction for nan value
:param d: dict of dict of mtg properties
:type d: dict of dict contains for a dict of MTG properties name as key and for each key a dict with vids in key and property values
:return: a dict of dict of MTG properties without None values
:rtype: dict of dict containing MTG properties
"""
if isinstance(d, dict):
return {k: filter_none(v) for k, v in d.items() if v!='None'}
else:
return d
[docs]def topology(df, first_property):
""" Extract topology from csv file and transform it in string.
This function contain a string_conversion test to check if have not error in the conversion to string
:param df: data containing topological information
:type df: pandas.DataFrame
:param first_property: colname of the first properties associate to topology information
:type first_property: string
:return: string contain topological information
:rtype: string
"""
# select topological part of file
start_prop=df.columns.get_loc(first_property)
df = df.loc[:,list(df.columns[:start_prop])]
# convert in string
array = df.fillna(-1).to_numpy() #replace na value by -1 and convert to numpy array
# convert array to string
row_index = list(range(0,array.shape[0]))
column_index = list(range(0,array.shape[1]))
column_start = 0
string=[]
for row in row_index:
for column in column_index:
if array[row,column]!=-1:
break
if column == column_start:
string.append(array[row,column])
elif column < column_start:
string.extend([']',array[row,column]])
else:
string.extend(['[',array[row,column]])
column_start = column
string = "".join(map(str,string))
def test_string_convertion(string):
""" test the converion into string counting the number of open and close brackets
if the number of bracket == 0 conversion is ok
elif the number of bracket is >0 means that we have more of open bracket than closed bracket and vice versa and print error of conversion
:param string: string containing the transformation of csv into string
:type string: string
:return: nothing if ok or Error of conversion if error
:rtype: nothing or error message
"""
count=0
for x in string:
# print(x)
if x == "[":
count+=1
elif x == "]":
count-=1
return count
if test_string_convertion(string)==0:
return string
else:
print("Error in convertion dataframe to string")
[docs]def add_properties(g, df, first_property):
"""add properties to MTG from csv
:param g: MTG
:type g: MTG object
:param df: data frame containing properties
:type df: pandas.DataFrame
:param first_property: colname of the first property
:type first_property: string
:return: an MTG with his properties
:rtype: MTG object
"""
start_prop=df.columns.get_loc(first_property)
df = df.loc[:,list(df.columns[start_prop:])]
df=df.where(pd.notnull(df), None)
df.index = np.arange(1, len(df) + 1)
df=df.fillna('None')
property_dict=df.to_dict()
property_dict=filter_none(property_dict)
for key,value in property_dict.items():
g.properties()[key]=value
return g
[docs]def add_axis_scale(g):
"""add axis scale in mtg from csv
:param g: an MTG
:type g: MTG object
:return: an MTG with axis scale added
:rtype: MTG object
"""
vids=g.vertices(scale=3)
for vid in vids:
pid = g.parent(vid)
if g.edge_type(vid)=="+":
cpx=g.add_child_and_complex(pid,vid)[-1]
p_cpx = g.complex(pid)
g.add_child(p_cpx, cpx, label="A", edge_type="+")
g.reindex()
return g
[docs]def strawberry_reader_csv(file, first_property='experimental_name',symbole_at_scale = dict(P=1,T=2, F=3, f=3, b=3, HT=3, bt=3, ht=3,s=3)):
''' Main function to import MTG from csv file
:param file: filename of csv
:type file: string
:param first_property: colnames of the first property
:type first_property: string
:param symbole_at_scale: dict of label symbole and scale
:type symbole_at_scale: dict
:return: list of individuals mtg
:rtype: a list of mtg by csv
'''
workbook = load_workbook(file)
sheets= workbook.sheetnames
mtgs = list()
for sheet in sheets:
df = read_file(file=file, sheet_name=sheet)
string= topology(df,first_property=first_property)
scene = Scene()
l = LsysContext()
l.makeCurrent()
for module in symbole_at_scale:
l.declare(module)
axialtree = AxialTree(string)
g = io.axialtree2mtg(tree=axialtree, scale=symbole_at_scale, scene=scene)
l.done()
g= add_properties(g, df,first_property=first_property)
g.property("Stade")
g= add_axis_scale(g)
g.properties()["order"] = algo.orders(g)
mtgs.append(g)
return mtgs
[docs]def import_mtg_from_csv(files,first_property,symbol_at_scale=dict(P=1,T=2, F=3, f=3, b=3, HT=3, bt=3, ht=3,s=3)):
''' import mtg from multiple csv file
:param files: list of set of csv filenames
:type files: list
:param first_property: name of the first property
:type: string
:param symbole_at_scale: dict of label symbole and scale
:type: dict
:return: dict of list of mtg by file
:rtype: dict
'''
mtgs={}
for file in files:
name= str(file).split('\\')[-1].split(".")[0]
print(name)
mtg= strawberry_reader_csv(file)
mtgs[name]=mtg
return mtgs
[docs]def union(g):
""" Union of all mtg in one
:param g: MTGs
:type g: list of dict of MTG
:return: one MTG which are union of all mtg
:rtype: MTG
"""
if type(g) is list:
mtg_list= g
elif type(g) is dict:
mtg_list = [mtg for sub_mtg in g.values() for mtg in sub_mtg]
lg= algo.union(mtg_list[0],mtg_list[1])
for mtg in mtg_list[2:]:
lg = algo.union(lg,mtg)
return lg
###############
[docs]def plant_number_by_varieties(g):
"""Print plant number by varieties in a mtg
:param g: MTG
:type g: MTG
"""
genotype = set(g.property("Genotype").values())
for geno in genotype:
no_plants= list(g.property("Genotype").values()).count(geno)
print(geno, ":", no_plants, "plants")