2017-09-13 11 views
2

J'utilise Python 2.6.6 et je suis en train de retirer fastq lit dans file2 qui se chevauchent (à savoir, sont identiques à) se lit dans file1. Voici le code que je suis en train de mettre en œuvre:Supprimer un élément dans un dictionnaire généré par SeqIO.index

ref_reads = SeqIO.index("file1.fastq", "fastq") 
spk_reads = SeqIO.index("file2.fastq", "fastq") 

for spk in spk_reads: 
    if spk in ref_reads: 
    del ref_reads[spk] 

Cependant, je reçois cette erreur lié à mon utilisation de del:

AttributeError: instance _IndexedSeqFileDict n'a pas d'attribut '__delitem__'

Est -il possible de supprimer un élément en utilisant la formulation actuelle? Comment puis-je supprimer un élément d'un dictionnaire généré à l'aide de SeqIO.index()?

J'ai aussi essayé ce qui suit:

# import read data 
ref_reads = SeqIO.index("main.fastq", "fastq") 
spk_reads = SeqIO.index("over.fastq", "fastq") 

# note that ref_reads.keys() doesn't return a list but a 'dictionary-  keyiterator', 
# so we turn it into a set to work with it 
ref_keys = set(ref_reads.keys()) 
spk_keys = set(spk_reads.keys()) 

# loop to remove overlap reads 
for spk in spk_keys: 
    if spk in ref_keys: 
     del ref_keys[spk] 

# output data 
output_handle = open(fname_out, "w") 
SeqIO.write(ref_reads[ref_keys], output_handle, "fastq") 
output_handle.close() 

Répondre

1

SeqIO.index() ne retourne pas un vrai dictionnaire, mais a dictionary like object, giving the SeqRecord objects as values:

Note that this pseudo dictionary will not support all the methods of a true Python dictionary, for example values() is not defined since this would require loading all of the records into memory at once.

Ce dictionnaire comme objet est une instance _IndexedSeqFileDict. Le docstring mentionne:

Note that this dictionary is essentially read only. You cannot add or change values, pop values, nor clear the dictionary.

Donc, vous devez convertir votre fichier fastq à un Python en mémoire dictionnaire à l'aide SeqIO.parse() et SeqIO.to_dict():

from Bio import SeqIO 

ref_reads = SeqIO.parse("file1.fastq", "fastq") 
spk_reads = SeqIO.parse("file1.fastq", "fastq") 

ref_reads_dict = SeqIO.to_dict(ref_reads) 

for spk in spk_reads: 
    if spk.id in ref_reads_dict: 
     del ref_reads_dict[spk.id] 

Si vos fichiers sont si importants que le travail avec SeqIO.parse() n'est pas possible, alors je ferais quelque chose comme ceci:

from Bio import SeqIO 

ref_reads = SeqIO.index("file1.fastq", "fastq") 
spk_reads = SeqIO.index("file2.fastq", "fastq") 

# note that ref_reads.keys() doesn't return a list but a 'dictionary-keyiterator', 
# so we turn it into a set to work with it 
ref_keys = set(ref_reads.keys()) 
spk_keys = set(spk_reads.keys()) 

unique_ref_keys = ref_keys - spk_keys 

# this step might take a long time if your files are large 
unique_ref_reads = {key: ref_reads[key] for key in unique_ref_keys} 

Modifier, réponse à votre commentaire :

how can I again solve the original problem of deleting items from SeqIO.index("file1.fastq", "fastq")?

Comme je l'ai dit plus haut, SeqIO.index("file1.fastq", "fastq") retourne un objet en lecture seule _IndexedSeqFileDict. Donc vous ne pouvez pas, par conception, supprimer des éléments de celui-ci.

Le code mis à jour ci-dessous montre comment créer un nouveau fichier fastq dans lequel les lectures superposées sont supprimées. Si vous voulez vraiment un nouvel objet SeqIO.index(), vous pouvez relire ce fichier avec SeqIO.index().

from Bio import SeqIO 

ref_reads = SeqIO.index("file1.fastq", "fastq") 
spk_reads = SeqIO.index("file2.fastq", "fastq") 

ref_keys = set(ref_reads.keys()) 
spk_keys = set(spk_reads.keys()) 

unique_ref_keys = ref_keys - spk_keys 

# conserve memory by using a generator expression 
unique_ref_records = (ref_reads[key] for key in unique_ref_keys) 

# output new file with overlapping reads removed 
with open(fname_out, "w") as output_handle: 
    SeqIO.write(unique_ref_records , output_handle, "fastq") 

# optionally, create a new SeqIO.index() object 
unique_ref_reads = SeqIO.index(fname_out, "fastq") 
+0

Thnk pour le conseil utile. La première solution a fonctionné, mais elle était lente par rapport au code que j'essaie d'améliorer. Pourriez-vous s'il vous plaît fournir des informations supplémentaires concernant votre deuxième bloc de code? J'essaye de supprimer des lectures de file1.fastq qui sont également dans file2.fastq. Basé sur votre deuxième solution, comment puis-je résoudre à nouveau le problème original de la suppression des éléments de SeqIO.index ("file1.fastq", "fastq")? J'ai mis à jour la question pour refléter ma dernière tentative. – wa3j

+0

@ wa3j: voir mon édition ci-dessus. – BioGeek