def check_letters_in_residue_numeration(self):
     """Checks whether identifiers of residues contain any letters."""
     for resi in self:
         if re.findall('[a-z,A-Z]', resi.identifier):
             log.write_message('Structure contains residues with letters in numeration eg.: %s.' %resi.identifier)
             return True
     return False
Exemple #2
0
def get_sequence(structure):
    """*get_sequence(structure)*

Retrieves the one-letter-sequence from the coordinates of a structure (template or model). In the sequence, standard RNA bases are denoted by 
upper case letters, DNA bases by lowercase. For many modifications, one-letter ASCII abbreviations exist (according to McCloskey). 
All nucleotides that do not have a one-letter abbreviation are represented by the x letter.
Nucleotides that cannot be recognized (e.g. base missing) are represented by the '.' character.

For determining the sequence, the residues are processed according to their numbers. 
If an unusually long bond is found anywhere in the backbone between two bases, 
an additional "_" symbol is inserted in the sequence to mark this discontinuity.

Also see http://www.genesilico.pl/modomics

:Arguments:
    * structure - a Template or RnaModel object
    """
    # KR: sequence should be written to logfile.
    # KR: discontinuities should get an extra logfile message.
    # MM: is it good place for that or should be sone in get_sequence in ModernaStructure?
    structure = validate_structure(structure)
    seq = structure.get_sequence()
    log.write_message('Checking sequence: \n%s\n' % seq.seq_with_modifications)
    if '_' in seq.seq_with_modifications:
        log.write_message('SEQUENCE IS DISCONTINUOUS !!!\n')
    return seq
    def renumber_chain(self, start_residue='1'):
        """
        Changes chain numeration. Provides continous chain numeration 
        starting from given number (by default 1)

        Arguments:
        * start number (by default 1)
        """
        try:
            num = int(start_residue)
        except ValueError: 
            raise ModernaStructureError('Cannot start numeration with %s, requires number' % str(start_residue)) 
        
        self.sort_residues()
        counter = num
        temp_resi_list = []
        for resi in self:
            temp_resi = resi
            self.remove_residue(resi.identifier)
            temp_resi.change_number(str(counter))
            temp_resi.id = (temp_resi.id[0], temp_resi.id[1], ' ')
            temp_resi_list.append(temp_resi)
            counter += 1

        for resi in temp_resi_list:
            self.add_residue(resi)
        self.sort_residues()
        
        log.write_message('Chain was renumbered. The first residue is now %s.' % str(start_residue))
Exemple #4
0
 def copy_residue_backbone(self, residue, number_in_model=None, strict=True):
     """
     """
     temp_res = RNAResidue(residue)
     num = number_in_model or str(temp_res.id[1]).strip()+temp_res.id[2].strip()
     make_backbone_only_residue(temp_res)
     self.add_residue(temp_res, num, strict = strict)        
     log.write_message('Residue %s: residues backbone atoms copied from template to model.' %num)       
Exemple #5
0
 def remove_one_modification_copy(self, residue, number_in_model):
     """
     """
     temp_resi = RNAResidue(residue)
     num = number_in_model or temp_resi.number
     remove_modification(temp_resi)
     self.add_residue(temp_resi, str(num))
     log.write_message('Residue %s: modification removed (%s ---> %s).' %(num, residue.long_abbrev, temp_resi.long_abbrev))
Exemple #6
0
 def add_one_modification_copy(self, residue, modification_long_abbrev, number_in_model):
     """
     """
     temp_res = RNAResidue(residue)
     num = number_in_model or temp_res.identifier
     add_modification(temp_res, modification_long_abbrev)
     self.add_residue(temp_res, num, False)
     log.write_message('Residue %s: modification added (%s ---> %s).' %(num, residue.long_abbrev, modification_long_abbrev))
 def fix_backbone(self):
     """Attempts to fix all backbone breaks."""
     log.write_message('\nChecking structure for interrupted backbones:')
     for i in range(2): # run twice to improve result
         #TODO: create better method for backbone fixing.
         last = None
         for resi in self:
             if last:
                 self.fix_backbone_between_resis(last, resi)
             last = resi
     log.write_message('Checking and repairing backbones finished.')
Exemple #8
0
 def add_all_modifications_copy(self):
     """
     """
     if self.alignment and self.template:
         for ap in self.recipe.add_modifications:
             temp_resi = RNAResidue(self.template.template_residues[str(ap.template_position)])
             old_name = temp_resi.long_abbrev
             add_modification(temp_resi, ap.target_letter.long_abbrev)
             self.add_residue(temp_resi)
             log.write_message('Residue %s: modification added (%s ---> %s).' %(temp_resi.identifier, old_name, temp_resi.long_abbrev))
     else: raise RnaModelError('There is no template or/and alignmnt')
Exemple #9
0
def get_secstruc(structure):
    """*get_secstruc(structure)*

Retrieves the dot-bracket secondary structure from the coordinates of a structure (template or model). 
Base pairs (only Watson-Crick pairings AU and GC, and GU Wobble pairs) \ are indicated by round brackets,
all other residues by dots.

:Arguments:
    * structure - a Template or RNAModel object
"""
    secstruc = structure.get_secstruc()
    log.write_message('Secondary structure: \n%s\n' % secstruc)
    return secstruc
Exemple #10
0
def write_secstruc(struct, file_name='secstruc.vienna'):
    """*write_secstruc(model, file_name='secstruc.vienna')*
    
Writes secondary struture to a vienna file. 

:Arguments:    
    * Structure object (model or template)
    * name of the vienna file (optional; by default secstruc.vienna)
    """
    struct = validate_structure(struct)
    file_name = validate_filename(file_name)

    struct.write_secstruc(file_name)
    log.write_message('Secondary structure written to %s' % file_name)
    def renumber_residue(self, old_number, new_number):
        """
        Changes residue identifier.

        Arguments:
        * an old residue identifier
        * a new residue identifier
        """
        if type(new_number) != str or new_number[0] not in [str(x) for x in range(0, 10)] or len(new_number)>5 or len(re.findall('[a-zA-Z]', new_number))>1:
            raise ModernaStructureError('Cannot change residue %s number for %s. The new number need to be string less than 5 characters long with digit in first position and including at most 1 letter.' % (str(old_number),  str(new_number)))
        resi = self[old_number]
        self.remove_residue(old_number)
        self.add_residue(resi, new_number)    
        log.write_message('Residue %s ---> renumbered to %s' % (str(old_number),  str(new_number)))
Exemple #12
0
    def copy_residue(self, residue, number_in_model=None, strict=True):
        """
        Copies a residue to a model in the given position.

        Arguments:
        - residue to copy (as a RNAResidue or PDB.Residue.Residue instance)
        - position in model (by default position in previous structure)  
        """
        temp_res = RNAResidue(residue)
        redit = ResidueEditor()
        redit.set_bfactor(temp_res, B_FACTOR_COPY)
        num = number_in_model or temp_res.identifier
        self.add_residue(temp_res, num, strict = strict)
        log.write_message('Residue %s: residue copied from template residue %s to model.' %(num, temp_res.identifier))
Exemple #13
0
def write_model(model, pdb_file_name='moderna_model.pdb'):
    """*write_model(model, pdb_file_name='moderna_model.pdb')*
    
Writes a model to a PDB file. The residues in the file are sorted.
All residues keep their numbers as last assigned.

:Arguments:    
    * Structure object (model or template)
    * name of the PDB file (optional; by default moderna_model.pdb)
    """
    model = validate_structure(model)
    pdb_file_name = validate_filename(pdb_file_name)

    if model.__class__ == RnaModel: model.refine_model()
    model.write_pdb_file(pdb_file_name)
    log.write_message('Model written to %s' % pdb_file_name)
Exemple #14
0
    def remove_all_modifications_copy(self):
        """
        Removes all unnecessary modifications from model acordong given alignment.
        Copies all this residues without modification into model.
        """
        if self.alignment and self.template:
            for ap in self.recipe.remove_modifications:
                res = self.template.template_residues[str(ap.template_position)]
                temp_resi = RNAResidue(res)
                remove_modification(temp_resi)

                if temp_resi != ap.target_letter:
                    exchange_base(temp_resi, ap.target_letter.original_base)
                self.add_residue(temp_resi)
                log.write_message('Residue %s: modification removed (%s ---> %s).' %(temp_resi.identifier, res.long_abbrev, temp_resi.long_abbrev))
        else: raise RnaModelError('There is no template or/and alignmnt')
Exemple #15
0
    def insert_best_fragment(self, start, stop, sequence,  candidates_number=NUMBER_OF_FRAGMENT_CANDIDATES):
        """
        Makes a LIR search to fill a gap at a given position.
        looks for possible candidates, checks the first ~20 for clashes,
        takes the best, removes anchor residue and inserts it in the model.        

        Arguments:
        - start position as a string (residue identifier)e.g. '3' - this is an identifier of the preceding anchor residue
        - stop position as above - this is an identifier of the fallowing anchor residue
        - fragment sequence as a Sequence object
        - number of fragment candidates.
        """
        log.write_message('\nSearching fragment between residue %s and residue %s.' %(str(start),str(stop)))
        fragment_finder = FragmentFinder(self[start],  self[stop],  sequence, self,  candidates_number)
        best_fragment=fragment_finder.find_fragment()
        log.write_message('\nBest fragment:\n%s'%str(best_fragment))
        self.insert_fragment(best_fragment)
Exemple #16
0
def examine_structure(st, ex_log=None, verbose=True):
    """*examine_structure(structure)*

Checks whether the given structure has any features that may cause any problems during the modeling process.
The user needs to give a structure object, and optionally a name of the file the report is written to.

:Arguments:
    * Stucture object
    * name of logfile (optional)
    """
    struc = validate_structure(st)

    pc = PdbController(st)
    if ex_log: pc.write_log(ex_log)
    else: log.write_message(str(pc))
    if verbose: print pc
    return pc
Exemple #17
0
def load_template(file_path, chain_name='A'):
    """*load_template(file_path, chain_name='A')*
    
Loads a template structure from a PDB file.
Produces a Template object that can be saved in a variable.

Each template in ModeRNA has only one chain. By default, the chain
with id 'A' is loaded. Another chain id can be specified optionally

:Arguments:    
    * path+filename of a PDB structure file
    * chain id (by default 'A')
    """
    file_path = validate_filename(file_path)

    t = Template(file_path, 'file', chain_name)
    log.write_message('Template loaded from %s.\nTemplate sequence:\n%s\n' %
                      (file_path, t.get_sequence().seq_with_modifications))
    return t
Exemple #18
0
def write_fragment_candidates(fragment_candidates,
                              output_directory='fragment_candidates',
                              with_model=True,
                              fragment_log_file=True):
    """*write_fragment_candidates(fragment_candidates, output_directory='fragment_candidates')*

Writes a list of fragment candidates to a set of PDB files. 
The candidates are numbered according to the geometrical fit of their backbones.

:Arguments:
    * fragment candidates list (obtained by the find_fragment command)
    * output directory name
    """
    fragment_candidates = validate_frag_candidate_list(fragment_candidates)
    output_directory = validate_path(output_directory)

    fragment_candidates.write_fragment_candidates(output_directory, True,
                                                  with_model, False,
                                                  fragment_log_file)
    log.write_message('Fragment candidates written to %s.' % output_directory)
Exemple #19
0
def match_template_with_alignment(template, alignment):
    """*match_template_with_alignment(template, alignment)*
    
Checks, if the sequence of the template structure is equal 
to the second sequence in the alignment. Writes an according message and returns True or False.
Small inconsistencies between both sequences, e.g. backbone breaks, or missing modification symbols
are corrected automatically in the alignment, and changes are reported in the logfile.

Both sequences also count as equal if one has modified nucleotides, and 
the other the corresponding unmodified nucleotides in the same position, 
or if one of the sequences contains the wildcard symbol '.'. 
Thus, the sequence "AGU" is equal to both "A7Y" and "A.U".

:Arguments:
    * Template object
    * Alignment object
    """
    template = validate_template(template)
    alignment = validate_alignment(alignment)

    log.write_message('Checking whether template matches with alignment.')
    am = AlignmentMatcher(alignment)
    seq = template.get_sequence()
    am.fix_template_seq(seq)
    result = am.is_template_identical(seq)
    if result:
        log.write_message("template and alignment match.\n")
    else:
        log.write_message("TEMPLATE AND ALIGNMENT DO NOT MATCH!\n")
    return result
Exemple #20
0
    def add_P_atom(self):
        """
        Adds missing P atoms (just when O5' and C5' are already there).
        """
        ms_id = [x.identifier for x in self.ms]
        new_P_missing = []

        for resi in self.P_missing:
            if resi.identifier in ms_id:
                add_P = True
                for at in ["C4'", "C5'", "O5'"]:
                    if not resi.has_id(at):
                        add_P = False
                        log.write_message(
                            "Could not add P atom to residue %s. %s atom missing."
                            % (resi.identifier, at))
                if add_P:
                    try:
                        tp = TerminalPhosphateBuilder(resi, self.ms)
                        tp.build_phosphate_group()
                        log.write_message(
                            "Phosphate group constructed on residue %s." %
                            (resi.identifier))
                    except:
                        log.write_message(
                            "Could not add P atom to residue %s.")
                        new_P_missing.append(resi)
                else:
                    new_P_missing.append(resi)
        self.P_missing = new_P_missing
Exemple #21
0
def match_alignment_with_model(alignment, model):
    """*match_alignment_with_model(alignment, model)*

Checks, if the sequence of a model structure is equal to the first sequence in the alignment. 
Writes an according message and returns True or False.

Both sequences also count as equal if one has modified nucleotides, and 
the other the corresponding unmodified nucleotides in the same position, 
or if one of the sequences contains the wildcard symbol '.'. 
Thus, the sequence "AGU" is equal to both "A7Y" and "A.U".
    
:Arguments:
    * Alignment object
    * RnaModel object
    """
    alignment = validate_alignment(alignment)
    model = validate_model(model)

    log.write_message('\nChecking whether alignment matches with model.')
    am = AlignmentMatcher(alignment)
    seq = model.get_sequence()
    result = am.is_target_identical(seq)
    if not result:
        log.write_message("alignment and model match.\n")
    else:
        log.write_message(
            "ALIGNMENT AND MODEL SEQUENCES DO NOT MATCH YET !!!\n")
    return result
Exemple #22
0
def analyze_geometry(struc, file_name=None):
    """*analyze_geometry(struc, file_name=None)*

Analyses geometry of a structure. Checks whether all angles and bonds length values
are close to reference values determined from the PDB. 
Writes the result of the analysis to log file or to an output file when specified.

:Arguments:
    * RNAModel object
    * Name of an output file
    """
    struc = validate_structure(struc)
    if file_name: file_name = validate_filename(file_name)

    analyzer = GeometryAnalyzer(struc)
    analyzer.analyze()
    raport = str(analyzer)
    if file_name:
        f = open(file_name, 'w')
        f.write(raport)
    log.write_message(raport)
    return analyzer
Exemple #23
0
def find_clashes(residues):
    """*find_clashes(residues)*
    
Detects interatomic clashes (overlapping atom VdW radii)
between atoms from two distinct residues. As input,
a template, a model or a list of residues is taken.

Returns a list of clashing residue pairs. If no clashes
are detected, the list is empty.

:Arguments:
    * list of residues or ModernaStructure object
    """
    residues = validate_resi_list(residues)

    # KR: result should be written to logfile
    cr = ClashRecognizer()
    clashes = cr.find_clashes_in_residues(residues)
    if clashes:
        log.write_message('Checking clashes: some residues are clashing %s' %
                          str(clashes))
    else:
        log.write_message('Checking clashes: there are no clashes')
    return clashes
Exemple #24
0
def clean_structure(st, write_structure=False):
    """*clean_structure(structure, write_structure=False)*

Eliminates features that may cause problems during modeling from a template or model structure:
    * water molecules, ions, amino acids, and unidentified residues are deleted.
    * old atom names are replaced (C1* becomes C1', O1P becomes OP1). 
    * missing phosphate groups are added (also adds the OP3 atom for these)
    * reports whether the chain is continuous.

In case some feature cannot be fixed (e.g. chain discontinuity) this is written to the logfile. 
It is  recommended to include such features in the alignment
('.' characters for strange residues, and '_' for backbone breaks).

:Arguments:
    * Stucture object (RnaModel or Template)
    * True/False - whether structure should be written to a PDB file (optional)
    """
    struc = validate_structure(st)

    pc = PdbController(st)
    pc.clean_structure()
    log.write_message(str(pc))
    if write_structure: pc.write_structure('fixed_structure.pdb')
    return pc
    def get_modified_residues(self):
        """
        Returns a dict with all modified residues in the structure.

        key - residue identifier
        value - ModernaResidue instance
        """
        log.write_message('Looking for modifications.')
        modified_residues = {}
        for resi in self:
            if resi.modified:
                modified_residues[resi.identifier] = resi
                log.write_message('Residue %s: is modified (%s)'%(resi.identifier, resi.long_abbrev))
        if not modified_residues:
            log.write_message('There are no modifications in the structure.')
        return modified_residues