package fr.orsay.lri.varna.models.treealign; import java.util.ArrayList; import java.util.List; import fr.orsay.lri.varna.exceptions.MappingException; import fr.orsay.lri.varna.models.rna.Mapping; import fr.orsay.lri.varna.models.rna.ModeleBase; import fr.orsay.lri.varna.models.rna.ModeleBaseNucleotide; import fr.orsay.lri.varna.models.rna.ModeleBP; import fr.orsay.lri.varna.models.rna.RNA; /** * This class contains all functions that are specific to trees * (class Tree) of RNA. * * @author Raphael Champeimont * */ public class RNATree { /** * Convert an RNA object into a RNA tree. * The root node will have a null value because it is a fake * node added to have a tree (otherwise we would have a forest). */ public static Tree<RNANodeValue> RNATreeFromRNA(RNA rna) { ConvertToTree converter = new ConvertToTree(rna); return converter.toTreeAux(0); } private static class ConvertToTree { private RNA rna; private int i = 0; /** Starts at the current position i in the sequence and converts the sequence * to a tree. * @return the created tree */ public Tree<RNANodeValue> toTreeAux(int depth) { Tree<RNANodeValue> tree = new Tree<RNANodeValue>(); List<Tree<RNANodeValue>> children = tree.getChildren(); // No value because it is a fake root tree.setValue(null); int length = rna.getSize(); while (i < length) { ModeleBase base = rna.getBaseAt(i); int indexOfAssociatedBase = base.getElementStructure(); if (indexOfAssociatedBase >= 0) { if (indexOfAssociatedBase > i) { // left parenthesis, we must analyze the children RNANodeValue childValue = new RNANodeValue(); childValue.setLeftBasePosition(i); childValue.setRightBasePosition(indexOfAssociatedBase); childValue.setOrigin(RNANodeValue.Origin.BASE_PAIR_FROM_HELIX); if (base instanceof ModeleBaseNucleotide) { childValue.setLeftNucleotide(((ModeleBaseNucleotide) base).get_c()); childValue.setRightNucleotide(((ModeleBaseNucleotide) rna.getBaseAt(indexOfAssociatedBase)).get_c()); } i++; Tree<RNANodeValue> child = toTreeAux(depth+1); child.setValue(childValue); children.add(child); } else { // right parenthesis, we have finished analyzing the children i++; break; } } else { // we have a non-paired base Tree<RNANodeValue> child = new Tree<RNANodeValue>(); RNANodeValue childValue = new RNANodeValue(); childValue.setLeftBasePosition(i); if (base instanceof ModeleBaseNucleotide) { childValue.setLeftNucleotide(((ModeleBaseNucleotide) base).get_c()); } // Even in this case (getElementStructure() < 0) // this base may still come from an helix which may have // been broken to remove a pseudoknot. childValue.setOrigin(RNANodeValue.Origin.BASE_FROM_UNPAIRED_REGION); ArrayList<ModeleBP> auxBasePairs = rna.getAuxBPs(i); for (ModeleBP auxBasePair: auxBasePairs) { if (auxBasePair.isCanonical()) { int partner5 = ((ModeleBaseNucleotide) auxBasePair.getPartner5()).getIndex(); int partner3 = ((ModeleBaseNucleotide) auxBasePair.getPartner3()).getIndex(); if (i == partner5) { childValue.setOrigin(RNANodeValue.Origin.BASE_FROM_HELIX_STRAND5); } else if (i == partner3) { childValue.setOrigin(RNANodeValue.Origin.BASE_FROM_HELIX_STRAND3); } else { System.err.println("Warning: Base index is " + i + " but neither endpoint matches it (edge endpoints are " + partner5 + " and " + partner3 + ")."); } } } child.setValue(childValue); children.add(child); i++; } } return tree; } public ConvertToTree(RNA rna) { this.rna = rna; } } /** * Convert an RNA tree alignment into a Mapping. */ public static Mapping mappingFromAlignment(Tree<AlignedNode<RNANodeValue,RNANodeValue>> alignment) throws MappingException { ConvertToMapping converter = new ConvertToMapping(); return converter.convert(alignment); } private static class ConvertToMapping { private Mapping m; public Mapping convert(Tree<AlignedNode<RNANodeValue,RNANodeValue>> tree) throws MappingException { m = new Mapping(); convertSubTree(tree); return m; } private void convertSubTree(Tree<AlignedNode<RNANodeValue,RNANodeValue>> tree) throws MappingException { AlignedNode<RNANodeValue,RNANodeValue> alignedNode = tree.getValue(); Tree<RNANodeValue> leftNode = alignedNode.getLeftNode(); Tree<RNANodeValue> rightNode = alignedNode.getRightNode(); if (leftNode != null && rightNode != null) { RNANodeValue v1 = leftNode.getValue(); RNANodeValue v2 = rightNode.getValue(); int l1 = v1.getLeftBasePosition(); int r1 = v1.getRightBasePosition(); int l2 = v2.getLeftBasePosition(); int r2 = v2.getRightBasePosition(); if (l1 >= 0 && l2 >= 0) { m.addCouple(l1, l2); } if (r1 >= 0 && r2 >= 0) { m.addCouple(r1, r2); } } for (Tree<AlignedNode<RNANodeValue,RNANodeValue>> child: tree.getChildren()) { convertSubTree(child); } } } }