Commit ff940d3d authored by Frédéric Escudié's avatar Frédéric Escudié
Browse files

Prevent bug with default parameter values in python.

parent 0344aea1
...@@ -138,8 +138,9 @@ class DenseData( list ): ...@@ -138,8 +138,9 @@ class DenseData( list ):
class SparseData( dict ): class SparseData( dict ):
def __init__( self, list=list() ): def __init__( self, list=None ):
for data in list: ini_list = list if list is not None else list()
for data in ini_list:
if not self.has_key( data[0] ): if not self.has_key( data[0] ):
self[data[0]] = dict() self[data[0]] = dict()
self[data[0]][data[1]] = data[2] self[data[0]][data[1]] = data[2]
...@@ -299,22 +300,35 @@ class Biom: ...@@ -299,22 +300,35 @@ class Biom:
""" """
def __init__( self, id=None, format="Biological Observation Matrix 1.0.0-dev", def __init__( self, id=None, format="Biological Observation Matrix 1.0.0-dev",
format_url="http://biom-format.org", type="OTU table", generated_by=None, format_url="http://biom-format.org", type="OTU table", generated_by=None,
date=time.strftime('%y-%m-%dT%H:%M:%S',time.localtime()), rows=list(), date=None, rows=None, columns=None, matrix_type="dense", matrix_element_type="int",
columns=list(), matrix_type="dense", matrix_element_type="int", data=None ):
data=list() ): """
@param id : [int]
@param format : [str]
@param format_url : [str]
@param type : [str]
@param generated_by : [str]
@param date : [str]
@param rows : [list]
@param columns : [list]
@param matrix_type : [str]
@param matrix_element_type : [str]
@param data : [list]
"""
self.id = id self.id = id
self.format = format self.format = format
self.format_url = format_url self.format_url = format_url
self.type = type self.type = type
self.generated_by = generated_by self.generated_by = generated_by
self.date = date self.date = date if date is not None else time.strftime('%y-%m-%dT%H:%M:%S',time.localtime())
self.rows = rows self.rows = rows if rows is not None else list()
self.columns = columns self.columns = columns if columns is not None else list()
self.matrix_element_type = matrix_element_type self.matrix_element_type = matrix_element_type
ini_data = data if data is not None else list()
if matrix_type == "dense": if matrix_type == "dense":
self.data = DenseData( data ) self.data = DenseData( ini_data )
else: else:
self.data = SparseData( data ) self.data = SparseData( ini_data )
def __str__(self): def __str__(self):
return str( self.__dict__ ) return str( self.__dict__ )
...@@ -535,38 +549,40 @@ class Biom: ...@@ -535,38 +549,40 @@ class Biom:
col_idx = self.find_idx( self.columns, sample_name ) col_idx = self.find_idx( self.columns, sample_name )
self.data.add( row_idx, col_idx, value ) self.data.add( row_idx, col_idx, value )
def add_observation( self, observation_name, metadata=dict() ): def add_observation( self, observation_name, metadata=None ):
""" """
@summary : Add one observation in biom. @summary : Add one observation in biom.
@param observation_name : [str] The observation name. @param observation_name : [str] The observation name.
@param metadata : [dict] The metadata (keys : metadata names ; values : metadata values). @param metadata : [dict] The metadata (keys : metadata names ; values : metadata values).
""" """
ini_metadata = metadata if metadata is not None else dict()
try: try:
self.find_idx( self.rows, observation_name ) self.find_idx( self.rows, observation_name )
# Observation doesn't exist # Observation doesn't exist
except ValueError: except ValueError:
self.rows.append( {'id':observation_name, 'metadata':None } ) self.rows.append( {'id':observation_name, 'metadata':None } )
self.data.add_row() self.data.add_row()
for metadata_name in metadata.keys(): for metadata_name in ini_metadata.keys():
self.add_metadata( observation_name, metadata_name, metadata[metadata_name], "observation" ) self.add_metadata( observation_name, metadata_name, ini_metadata[metadata_name], "observation" )
# Observation already exists # Observation already exists
else: else:
raise ValueError( "The observation '" + observation_name + "' already exists." ) raise ValueError( "The observation '" + observation_name + "' already exists." )
def add_sample( self, sample_name, metadata=dict() ): def add_sample( self, sample_name, metadata=None ):
""" """
@summary : Add one sample in biom. @summary : Add one sample in biom.
@param sample_name : [str] The sample name. @param sample_name : [str] The sample name.
@param metadata : [dict] The metadata (keys : metadata names ; values : metadata values). @param metadata : [dict] The metadata (keys : metadata names ; values : metadata values).
""" """
ini_metadata = metadata if metadata is not None else dict()
try: try:
self.find_idx( self.columns, sample_name ) self.find_idx( self.columns, sample_name )
# Sample doesn't exist # Sample doesn't exist
except ValueError: except ValueError:
self.columns.append( {'id':sample_name, 'metadata':None } ) self.columns.append( {'id':sample_name, 'metadata':None } )
self.data.add_column() self.data.add_column()
for metadata_name in metadata.keys(): for metadata_name in ini_metadata.keys():
self.add_metadata( sample_name, metadata_name, metadata[metadata_name], "sample" ) self.add_metadata( sample_name, metadata_name, ini_metadata[metadata_name], "sample" )
# Sample already exists # Sample already exists
else: else:
raise ValueError( "The sample '" + sample_name + "' already exists." ) raise ValueError( "The sample '" + sample_name + "' already exists." )
...@@ -578,7 +594,7 @@ class Biom: ...@@ -578,7 +594,7 @@ class Biom:
""" """
for col in self.columns: for col in self.columns:
yield col["id"] yield col["id"]
def get_observations_names( self ): def get_observations_names( self ):
""" """
@summary : Returns a generator to iterate on observations names. @summary : Returns a generator to iterate on observations names.
...@@ -617,15 +633,15 @@ class Biom: ...@@ -617,15 +633,15 @@ class Biom:
@example : nb_removed_elts = 100, nb_selected_elts = 10, nb_selection_round = 2 @example : nb_removed_elts = 100, nb_selected_elts = 10, nb_selection_round = 2
and sample A = { sea:800, lake:150, air:50 } and sample A = { sea:800, lake:150, air:50 }
ROUND 1 remove selection ROUND 1 remove selection
sea 720 9 sea 720 9
lake 145 1 lake 145 1
air 35 0 air 35 0
ROUND 2 remove selection ROUND 2 remove selection
sea 730 7 sea 730 7
lake 130 2 lake 130 2
air 40 1 air 40 1
Result Result
sea 16 sea 16
lake 3 lake 3
air 1 air 1
""" """
...@@ -686,7 +702,7 @@ class BiomIO: ...@@ -686,7 +702,7 @@ class BiomIO:
The BIOM file format is a json format designed to be a general-use format for representing biological sample by observation contingency tables. The BIOM file format is a json format designed to be a general-use format for representing biological sample by observation contingency tables.
BIOM is a recognized standard for the Earth Microbiome Project and is a Genomics Standards Consortium candidate project. BIOM is a recognized standard for the Earth Microbiome Project and is a Genomics Standards Consortium candidate project.
@see : https://github.com/biom-format @see : https://github.com/biom-format
""" """
@staticmethod @staticmethod
def from_count_table( count_file, generated_by=None ): def from_count_table( count_file, generated_by=None ):
""" """
...@@ -702,7 +718,7 @@ class BiomIO: ...@@ -702,7 +718,7 @@ class BiomIO:
biom = Biom() biom = Biom()
biom.data = SparseData() biom.data = SparseData()
biom.generated_by = generated_by biom.generated_by = generated_by
count_fh = open( count_file ) count_fh = open( count_file )
row_idx = 0 row_idx = 0
for line in count_fh: for line in count_fh:
...@@ -731,9 +747,9 @@ class BiomIO: ...@@ -731,9 +747,9 @@ class BiomIO:
col_idx += 1 col_idx += 1
row_idx += 1 row_idx += 1
count_fh.close() count_fh.close()
return biom return biom
@staticmethod @staticmethod
def from_json( path ): def from_json( path ):
""" """
...@@ -744,7 +760,7 @@ class BiomIO: ...@@ -744,7 +760,7 @@ class BiomIO:
json_data = open( path ) json_data = open( path )
python_dict = json.load( json_data ) python_dict = json.load( json_data )
json_data.close() json_data.close()
return Biom( python_dict["id"], return Biom( python_dict["id"],
python_dict["format"], python_dict["format"],
python_dict["format_url"], python_dict["format_url"],
...@@ -779,7 +795,7 @@ class BiomIO: ...@@ -779,7 +795,7 @@ class BiomIO:
for line in biom.to_count_table(): for line in biom.to_count_table():
out_fh.write( "\t".join(map(str, line)) + "\n" ) out_fh.write( "\t".join(map(str, line)) + "\n" )
out_fh.close() out_fh.close()
@staticmethod @staticmethod
def write_krona_table( path, biom ): def write_krona_table( path, biom ):
""" """
...@@ -795,8 +811,8 @@ class BiomIO: ...@@ -795,8 +811,8 @@ class BiomIO:
tax = str( tax ) tax = str( tax )
tax = "\t".join( map(str.strip, tax.split(";")) ) # Replace space separator between ranks by tabulation tax = "\t".join( map(str.strip, tax.split(";")) ) # Replace space separator between ranks by tabulation
out_fh.write( str(count) + "\t" + tax + "\n" ) out_fh.write( str(count) + "\t" + tax + "\n" )
out_fh.close() out_fh.close()
@staticmethod @staticmethod
def write_krona_table_by_sample( path, biom, sample ): def write_krona_table_by_sample( path, biom, sample ):
""" """
...@@ -814,10 +830,10 @@ class BiomIO: ...@@ -814,10 +830,10 @@ class BiomIO:
tax = str( tax ) tax = str( tax )
tax = "\t".join( map(str.strip, tax.split(";")) ) # Replace space separator between ranks by tabulation tax = "\t".join( map(str.strip, tax.split(";")) ) # Replace space separator between ranks by tabulation
out_fh.write( str(count) + "\t" + tax + "\n" ) out_fh.write( str(count) + "\t" + tax + "\n" )
out_fh.close() out_fh.close()
@staticmethod @staticmethod
def load_metadata( biom, metadata_file, subject_type="sample", types={}, list_sep={} ): def load_metadata( biom, metadata_file, subject_type="sample", types=None, list_sep=None ):
""" """
@summary : Add to biom several metadata from metadata file. @summary : Add to biom several metadata from metadata file.
@param biom : [Biom] The Biom object to update. @param biom : [Biom] The Biom object to update.
...@@ -829,7 +845,7 @@ class BiomIO: ...@@ -829,7 +845,7 @@ class BiomIO:
@param subject_type : [str] The type of subject : "sample" or "observation". @param subject_type : [str] The type of subject : "sample" or "observation".
@param types : [dict] Types for of the metadata values ("str", "int", "float"). @param types : [dict] Types for of the metadata values ("str", "int", "float").
Example : Example :
{ {
'confidence' : 'float', 'confidence' : 'float',
'rank' : 'int' 'rank' : 'int'
} }
...@@ -838,8 +854,10 @@ class BiomIO: ...@@ -838,8 +854,10 @@ class BiomIO:
{ {
'taxonomy' : ';', # Bacteria;Proteobacteria 'taxonomy' : ';', # Bacteria;Proteobacteria
'environnement' : '/' # Sea/Ocean 'environnement' : '/' # Sea/Ocean
} }
""" """
ini_types = types if types is not None else dict()
ini_list_sep = list_sep if list_sep is not None else dict()
metadata_fh = open( metadata_file ) metadata_fh = open( metadata_file )
metadata = list() metadata = list()
# Names and type of metadata # Names and type of metadata
...@@ -847,11 +865,11 @@ class BiomIO: ...@@ -847,11 +865,11 @@ class BiomIO:
title_fields = title_line.split() title_fields = title_line.split()
for metadata_name in title_fields[1:]: for metadata_name in title_fields[1:]:
metadata_type = "str" metadata_type = "str"
if types.has_key( metadata_name ): if ini_types.has_key( metadata_name ):
metadata_type = types[metadata_name] metadata_type = ini_types[metadata_name]
metadata_list_sep = None metadata_list_sep = None
if list_sep.has_key( metadata_name ): if ini_list_sep.has_key( metadata_name ):
metadata_list_sep = list_sep[metadata_name] metadata_list_sep = ini_list_sep[metadata_name]
metadata.append( { metadata.append( {
'name' : metadata_name, 'name' : metadata_name,
'type' : metadata_type, 'type' : metadata_type,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment