Source code for VirtualMicrobes.mutate.Mutation

#from virtual_cell.Cell import Cell
from abc import abstractmethod

[docs]class MutationError(Exception): pass
[docs]class MutationAlreadyAppliedError(MutationError): def __init__(self, value="Cannot 'reapply' if already applied"): self.value = value def __str__(self): return repr(self.value)
[docs]class MutationNotAppliedError(Exception): def __init__(self, value="Cannot 'rewind' if not already applied"): self.value = value def __str__(self): return repr(self.value)
[docs]class Mutation(object): """ :version: :author: """ uid = 0 __slots__ = ['applied', 'genomic_target', 'post_mutation', 'genomic_unit', 'time'] def __init__(self, target, genomic_unit): self.applied = False self.genomic_target = target self.genomic_unit = genomic_unit @abstractmethod
[docs] def mutate(self, time): self.applied = True self.time = time
@abstractmethod
[docs] def reapply(self): if self.applied: raise MutationAlreadyAppliedError self.applied = True
@abstractmethod
[docs] def rewind(self): """ Go back to the ancestral state by patching the mutated cell with the unmutated genomic state. It should make a check that the genomic element is a part of this cell. :param virtual_cell.Cell mutant : On which cell do we play the reversal? :return : :author """ if not self.applied: raise MutationNotAppliedError self.applied = False
[docs]class ChromosomalMutation (Mutation): """ """ __slots__ = () def __init__(self, chromosomes,genome): super(ChromosomalMutation,self).__init__(chromosomes,genome)
[docs]class ChromosomeDuplication (ChromosomalMutation): __slots__ = () def __init__(self,chromosome, genome): super(ChromosomeDuplication,self).__init__(chromosome,genome)
[docs] def mutate(self, time): copy1,copy2 = self.genomic_target.duplicate(time) self.post_mutation = [copy1,copy2] self.genomic_unit.del_chromosome(self.genomic_target, remove_genes=False) self.genomic_unit.add_chromosome(copy1) #.chromosomes += [copy1,copy2] self.genomic_unit.add_chromosome(copy2) super(ChromosomeDuplication,self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(ChromosomeDuplication,self).reapply() self.genomic_unit.del_chromosome(self.genomic_target, remove_genes=False) for chrom in self.post_mutation: self.genomic_unit.add_chromosome(chrom) return self.genomic_unit
[docs] def rewind(self): super(ChromosomeDuplication,self).rewind() for chrom in self.post_mutation: self.genomic_unit.del_chromosome(chrom, remove_genes=False) self.genomic_unit.add_chromosome(self.genomic_target) return self.genomic_unit
[docs]class StretchMutation(Mutation): __slots__ = ['start_pos', 'end_pos', 'stretch'] def __init__(self, chromosome, genome, start_pos=None, end_pos=None, stretch=None): super(StretchMutation, self).__init__(chromosome, genome) self.start_pos = start_pos self.end_pos = end_pos self.stretch = stretch self.positive_positions()
[docs] def positive_positions(self): if self.start_pos is not None and self.start_pos < 0: # ensure that we are working with purely positive indexes shift = len(self.genomic_target) # this allows wrapping around to work properly in the case of circular genomes self.start_pos += shift if self.end_pos is not None: self.end_pos += shift
#print 'start-end shifted to', self.start_pos, self.end_pos
[docs]class StretchDeletion(StretchMutation): __slots__ = () def __init__(self, chromosome, genome, start_pos, end_pos): ''' Tandem Duplication affects a single chromosome. It has a start and end position of the duplication stretch. ''' super(StretchDeletion, self).__init__(chromosome,genome, start_pos, end_pos)
[docs] def mutate(self, time): self.stretch = self.genomic_target.delete_stretch(self.start_pos, self.end_pos) assert len(self.stretch) self.genomic_unit.update_genome_removed_genes(self.stretch) super(StretchDeletion,self).mutate(time) return self.genomic_unit
[docs] def rewind(self): super(StretchDeletion, self).rewind() self.genomic_target.insert_stretch(self.stretch, self.start_pos) return self.genomic_unit
[docs] def reapply(self): super(StretchDeletion, self).reapply() self.genomic_target.delete_stretch(self.start_pos, self.end_pos) self.genomic_unit.update_genome_removed_genes(self.stretch) return self.genomic_unit
[docs]class TandemDuplication (StretchMutation): __slots__ = () def __init__(self, chromosome, genome, start_pos, end_pos): ''' Tandem Duplication affects a single chromosome. It has a start and end position of the duplication stretch. ''' super(TandemDuplication, self).__init__(chromosome,genome, start_pos, end_pos)
[docs] def mutate(self, time): self.stretch = self.genomic_target.tandem_duplicate(self.start_pos, self.end_pos) assert len(self.stretch) super(TandemDuplication,self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(TandemDuplication, self).reapply() self.genomic_target.insert_stretch(self.stretch, self.end_pos) return self.genomic_unit
[docs] def rewind(self): super(TandemDuplication, self).rewind() self.genomic_target.delete_stretch(self.start_pos, self.end_pos) return self.genomic_unit
[docs]class Inversion (StretchMutation): __slots__ = () def __init__(self,chromosome, genome, start_pos, end_pos): super(Inversion,self).__init__(chromosome, genome, start_pos, end_pos)
[docs] def mutate(self, time): '''The invert is in place, hence pre- and post- mutation will appear the same''' self.stretch = self.genomic_target.invert(self.start_pos, self.end_pos) assert len(self.stretch) != 0 super(Inversion, self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(Inversion, self).reapply() self.genomic_target.invert(self.start_pos, self.end_pos) self.applied = False return self.genomic_unit
[docs] def rewind(self): super(Inversion, self).rewind() self.genomic_target.invert(self.start_pos, self.end_pos) self.applied = False return self.genomic_unit
[docs]class Insertion (StretchMutation): ''' Insertion of a stretch of exogenous genomic material ''' __slots__ = ['insert_pos', 'is_external'] def __init__(self, chromosome, genome, stretch, insert_pos, is_external): super(Insertion, self).__init__(chromosome, genome, stretch=stretch) self.insert_pos = insert_pos self.is_external = is_external
[docs] def mutate(self, time): assert len(self.stretch) self.genomic_target.insert_stretch(self.stretch, self.insert_pos) super(Insertion, self).mutate(time)
[docs] def rewind(self): super(Insertion, self).rewind() start_del_pos = self.insert_pos - len(self.stretch) self.genomic_target.delete_stretch(start_del_pos, self.insert_pos) self.genomic_unit.update_genome_removed_genes(self.stretch)
[docs] def reapply(self): super(Insertion, self).reapply() self.genomic_target.insert_stretch(self.stretch, self.insert_pos)
[docs]class Translocation (StretchMutation): __slots__ = ['insert_pos','invert'] def __init__(self, chromosome, genome, start_pos, end_pos, target_chrom, insert_pos, invert): super(Translocation, self).__init__((chromosome, target_chrom), genome, start_pos, end_pos) self.insert_pos = insert_pos self.invert = invert
[docs] def positive_positions(self): if self.start_pos is not None and self.start_pos < 0: shift = len(self.genomic_target[0]) self.start_pos += shift if self.end_pos is not None: self.end_pos += shift
#print 'start-end shifted to', self.start_pos, self.end_pos
[docs] def mutate(self, time): orig, orig_target = self.genomic_target self.stretch = orig.delete_stretch(self.start_pos, self.end_pos) assert len(self.stretch) if self.invert: self.stretch.reverse() orig_target.insert_stretch(self.stretch, self.insert_pos) super(Translocation, self).mutate(time)
[docs] def rewind(self): super(Translocation, self).rewind() orig, orig_target = self.genomic_target if self.invert: self.stretch.reverse() orig.insert_stretch(self.stretch, self.start_pos) start_del_pos = self.insert_pos - len(self.stretch) orig_target.delete_stretch(start_del_pos, self.insert_pos)
[docs] def reapply(self): super(Translocation, self).reapply() orig, orig_target = self.genomic_target orig.delete_stretch(self.start_pos, self.end_pos) if self.invert: self.stretch.reverse() orig_target.insert_stretch(self.stretch, self.insert_pos)
[docs]class ChromosomeDeletion (ChromosomalMutation): __slots__ = () def __init__(self,chromosome, genome): super(ChromosomeDeletion,self).__init__(chromosome,genome)
[docs] def mutate(self, time): self.post_mutation = [] self.genomic_unit.del_chromosome(self.genomic_target) super(ChromosomeDeletion,self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(ChromosomeDeletion, self).reapply() self.genomic_unit.del_chromosome(self.genomic_target) return self.genomic_unit
[docs] def rewind(self): super(ChromosomeDeletion, self).rewind() self.genomic_unit.add_chromosome(self.genomic_target) return self.genomic_unit
[docs]class Fusion (ChromosomalMutation): __slots__ = ['end1', 'end2'] def __init__(self,chrom1, chrom2, genome, end1, end2): super(Fusion,self).__init__((chrom1,chrom2), genome) self.end1 = end1 self.end2 = end2
[docs] def mutate(self, time): target_cls = self.genomic_target[0].__class__ fusion = target_cls.fuse(self.genomic_target[0], self.genomic_target[1], time, self.end1, self.end2) self.post_mutation = fusion for chrom in self.genomic_target: self.genomic_unit.del_chromosome(chrom, remove_genes=False) self.genomic_unit.add_chromosome(fusion) super(Fusion,self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(Fusion, self).reapply() for chrom in self.genomic_target: self.genomic_unit.del_chromosome(chrom, remove_genes=False) self.genomic_unit.add_chromosome(self.post_mutation) return self.genomic_unit
[docs] def rewind(self): super(Fusion, self).rewind() self.genomic_unit.del_chromosome(self.post_mutation, remove_genes=False) for chrom in self.genomic_target: self.genomic_unit.add_chromosome(chrom) return self.genomic_unit
[docs]class Fission (ChromosomalMutation): __slots__ = ['pos'] def __init__(self,chromosome, genome, pos): super(Fission,self).__init__(chromosome, genome) self.pos = pos
[docs] def mutate(self, time): subchrom1, subchrom2 = self.genomic_target.fiss(self.pos, time) self.post_mutation = [subchrom1, subchrom2] self.genomic_unit.del_chromosome(self.genomic_target, remove_genes=False) self.genomic_unit.add_chromosome(subchrom1) self.genomic_unit.add_chromosome(subchrom2) super(Fission, self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(Fission, self).reapply() self.genomic_unit.del_chromosome(self.genomic_target, remove_genes=False) for _chrom in self.post_mutation: self.genomic_unit.add_chromosome(self.post_mutation)
[docs] def rewind(self): super(Fission, self).rewind() for chrom in self.post_mutation: self.genomic_unit.del_chromosome(chrom, remove_genes=False) self.genomic_unit.add_chromosome(self.genomic_target) return self.genomic_unit
[docs]class SingleGeneMutation (Mutation): __slots__ = ['pos'] def __init__(self, gene , chromosome, pos): super(SingleGeneMutation,self).__init__(gene, chromosome) self.pos = pos
[docs] def mutate(self, time): return super(SingleGeneMutation, self).mutate(time)
[docs] def reapply(self): super(SingleGeneMutation, self).reapply()
[docs] def rewind(self): super(SingleGeneMutation, self).rewind()
[docs]class SGDeletion (SingleGeneMutation): pass
[docs]class SGDuplication (SingleGeneMutation): pass
[docs]class PointMutation (SingleGeneMutation): __slots__ = ['par', 'new_val'] def __init__(self,gene, chromosome, par, new_val, pos): super(PointMutation,self).__init__(gene, chromosome, pos) self.par = par self.new_val = new_val
[docs] def mutate(self, time): self.post_mutation = self.genomic_target.mutated(self.par, self.new_val, time) self.genomic_unit.positions[self.pos] = self.post_mutation super(PointMutation, self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(PointMutation, self).reapply() self.genomic_unit.positions[self.pos] = self.post_mutation return self.genomic_unit
[docs] def rewind(self): super(PointMutation, self).rewind() self.genomic_unit.positions[self.pos] = self.genomic_target return self.genomic_unit
[docs]class OperatorInsertion (SingleGeneMutation): __slots__ = ['par', 'new_val'] def __init__(self,gene, chromosome, new_val, pos): super(OperatorInsertion,self).__init__(gene, chromosome, pos) self.par = 'operator' self.new_val = new_val
[docs] def mutate(self, time): self.post_mutation = self.genomic_target.mutated(self.par, self.new_val, time) self.genomic_unit.positions[self.pos] = self.post_mutation super(OperatorInsertion, self).mutate(time) return self.genomic_unit
[docs] def reapply(self): super(OperatorInsertion, self).reapply() self.genomic_unit.positions[self.pos] = self.post_mutation return self.genomic_unit
[docs] def rewind(self): super(OperatorInsertion, self).rewind() self.genomic_unit.positions[self.pos] = self.genomic_target return self.genomic_unit