diff --git a/src/main/java/pl/poznan/put/structure/secondary/ConflictMap.java b/src/main/java/pl/poznan/put/structure/secondary/ConflictMap.java new file mode 100644 index 00000000..2c33dac1 --- /dev/null +++ b/src/main/java/pl/poznan/put/structure/secondary/ConflictMap.java @@ -0,0 +1,65 @@ +package pl.poznan.put.structure.secondary; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class ConflictMap { + + private HashMap> conflicts = new HashMap>(); + + + // Create a basic 2DMap from which tells about conflicts. It can return if given Region have conflicts and give these conflicts + public ConflictMap (Map idToRegion) { + boolean conflict = false; + + for(int i = 0; i < idToRegion.size(); i++) { + conflicts.put(i, new HashMap()); + } + + for(int i = 0; i < idToRegion.size(); i++) { + for(int j = i+1; j < idToRegion.size(); j++) { + conflict = isConflicting(idToRegion.get(i), idToRegion.get(j)); + if(conflict){ + conflicts.get(i).put(j, true); + conflicts.get(j).put(i, true); + } + } + } + + for(int i = 0; i < idToRegion.size(); i++) { + if(conflicts.get(i).isEmpty()) conflicts.remove(i); + } + } + + // Return array of ids that are still conflicting + public ArrayList conflicting() { + ArrayList conflictsVector = new ArrayList(conflicts.keySet()); + + return conflictsVector; + } + + // Check if given Regions are conflicting + private boolean isConflicting(Region first, Region second) { + int startFirst = first.start, endFirst = first.end, startSecond = second.start, endSecond = second.end; + + return (((startFirst < startSecond) && (endFirst < endSecond) && (startSecond < endFirst)) || ((startSecond < startFirst) && (endSecond < endFirst) && (startFirst < endSecond))); + } + + // Remove Region and all associated conflicts with it + public void remove(int idToRemove) { + int id; + ArrayList conflictingIDs = new ArrayList(conflicts.get(idToRemove).keySet()); + for(int i = 0; i < conflictingIDs.size(); i++) { + id = conflictingIDs.get(i); + conflicts.get(id).remove(idToRemove); + if(conflicts.get(id).isEmpty()) conflicts.remove(id); + } + conflicts.remove(idToRemove); + } + + // Return all Regions (ID) that conflicts with given Region + public ArrayList conflictsWith(int id) { + return new ArrayList(conflicts.get(id).keySet()); + } +} diff --git a/src/main/java/pl/poznan/put/structure/secondary/KnotRemoval.java b/src/main/java/pl/poznan/put/structure/secondary/KnotRemoval.java new file mode 100644 index 00000000..b9453bf6 --- /dev/null +++ b/src/main/java/pl/poznan/put/structure/secondary/KnotRemoval.java @@ -0,0 +1,490 @@ +package pl.poznan.put.structure.secondary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class KnotRemoval { + + private static char[] openingBracket = {'(', '[', '{', '<', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + private static char[] closingBracket = {')', ']', '}', '>', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; + // Dynamic Programming + public static RNAStructure dynamicProgramming(RNAStructure structure) { + // Create a deep copy of RNAStructure + RNAStructure str = new RNAStructure (structure); + str.DP = true; + int bracket = -1; + while(havePairs(str)) { + ++bracket; + Map idMap = new HashMap(); + ArrayList connections = filterNotConnected(str.originalConnections, idMap); + + connections = addOuterRange(connections); + int size = connections.size(); + + // Create array of ranges and sort them + ArrayList ranges = createRanges(connections); + Collections.sort(ranges); + + // Initialize arrays needed for dynamic programming (it takes approximately 2/3 of program execution time) + int[][] dpScore = new int[size][size]; + int[][] dpPosition = new int[size][size]; + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + dpPosition[i][j] = -1; + + // Fill dp array for results + for(Range range : ranges) { + int[] prefixesScore = dpScore[range.left + 1]; + int[] prefixesPosition = dpPosition[range.left + 1]; + + for(int pos = range.left + 1; pos < range.right; pos++){ + int paired = connections.get(pos); + + if(pos == range.left + 1) continue; + + if(!range.contains(paired) || (paired > pos)) { + if(prefixesScore[pos] < prefixesScore[pos-1]) { + prefixesScore[pos] = prefixesScore[pos-1]; + prefixesPosition[pos] = prefixesPosition[pos-1]; + } + } else if(paired < pos) { + if(prefixesScore[pos-1] < (prefixesScore[paired-1] + dpScore[paired][pos]) && prefixesScore[pos] < (prefixesScore[paired-1] + dpScore[paired][pos])) { + prefixesScore[pos] = prefixesScore[paired-1] + dpScore[paired][pos]; + prefixesPosition[pos] = pos; + } else if(prefixesScore[pos] < prefixesScore[pos-1]){ + prefixesScore[pos] = prefixesScore[pos-1]; + prefixesPosition[pos] = prefixesPosition[pos-1]; + } + } + } + dpScore[range.left][range.right] = 1 + prefixesScore[range.right-1]; + dpPosition[range.left][range.right] = range.right; + } + + + ArrayList correctConnections = new ArrayList(); + appendCorrectConnections(1, size - 2, connections, dpPosition, correctConnections); + + ArrayList nonConflicting = keepSelected(connections, correctConnections); + nonConflicting = removeOuterRange(nonConflicting); + + str.correctConnections = mapBack(str.originalConnections, nonConflicting, idMap); + + updateDotBracket(str, bracket); + removeUsedConnections(str); + } + + return str; + } + + // Elimination Gain + public static RNAStructure eliminationGain(RNAStructure structure) { + + // Make a deep copy of processing structure + RNAStructure str = new RNAStructure (structure); + int bracket = -1; + while(havePairs(str)) { + ++bracket; + + // Initialize all variables for Elimination Gain function + ArrayList regions = new ArrayList(createRegions(str)); + Map idToRegion = createMap(regions); + ConflictMap cm = new ConflictMap(idToRegion); + ArrayList conflicts = cm.conflicting(); + ArrayList removed = new ArrayList(); + + int idToRemove; + + // Main loop with function + while (!conflicts.isEmpty()) { + idToRemove = findMinGain(conflicts, cm, idToRegion); + removed.add(idToRegion.get(idToRemove)); + regions.get(idToRemove).remove(); + idToRegion.remove(idToRemove); + cm.remove(idToRemove); + conflicts = cm.conflicting(); + } + + // Check if removed regions are still conflicting, if not add them back + ArrayList addBackRegions = new ArrayList(addBackNonConflicting(idToRegion, removed)); + + for(int i = 0; i < addBackRegions.size(); i++) { + regions.add(addBackRegions.get(i)); + } + + // Change Regions to pairs + str.connections = toPairs(regions); + + updateConnectionsFromPairs(str); + updateDotBracket(str, bracket); + removeUsedConnections(str); + updateConnectionPairs(str); + } + + return str; //new RNAStructure(structure.connections, structure.rnaSequence); + } + + /////////////////////////////////// + // Elimination Gain functions + /////////////////////////////////// + + // Create Array of Regions from connections stored in RNAStructure + private static ArrayList createRegions (RNAStructure structure) { + + ArrayList regions = new ArrayList(); + ArrayList currentRegion = new ArrayList(); + int regionID = -1; + + for (int i = 0; i < structure.connections.size(); i++) { + if (currentRegion.isEmpty()) { + currentRegion.add(structure.connections.get(i)); + } + else { + if (structure.connections.get(i).getFirst() == currentRegion.get(currentRegion.size()-1).getFirst()+1 && + structure.connections.get(i).getSecond() == currentRegion.get(currentRegion.size()-1).getSecond()-1){ + currentRegion.add(structure.connections.get(i)); + } + else { + regionID++; + regions.add(new Region(currentRegion, regionID)); + currentRegion.clear(); + currentRegion.add(structure.connections.get(i)); + } + } + } + if(!currentRegion.isEmpty()){ + regionID++; + regions.add(new Region(currentRegion, regionID)); + } + + return regions; + } + + // Create map of Regions + private static Map createMap(ArrayList regions){ + Map idToRegion = new HashMap(); + + for(int i = 0; i < regions.size(); i++){ + idToRegion.put(regions.get(i).ID, regions.get(i)); + } + + return idToRegion; + } + + public static ArrayList toPairs(ArrayList regions) { + ArrayList connections = new ArrayList(); + int start, end; + + + + for(int i = 0; i < regions.size(); i++) { + if(!regions.get(i).isRemoved()) { + start = regions.get(i).start; + end = regions.get(i).end; + for(int j = 0; j < regions.get(i).length; j++) { + connections.add(new Pair(start + j, end - j)); + } + } + } + + return connections; + } + + // Rewritten find_min_gain function from PyCogent-1.5.3 + private static Integer findMinGain(ArrayList conflicts, ConflictMap cm, Map idToRegion){ + int id, regionLength, conflictLength, lenDiff, lenDiffMin = 2000000000, noc, nocMax = -100, start, startMax = -100; + ArrayList conflictsWith = new ArrayList(); + SortedMap > lenDiffs = new TreeMap >(); + SortedMap > numberOfConflicts = new TreeMap >(); + SortedMap startValues = new TreeMap(); + + for(int i = 0; i < conflicts.size(); i++) { + id = conflicts.get(i); + regionLength = idToRegion.get(id).length; + conflictLength = 0; + conflictsWith = cm.conflictsWith(id); + for(int j = 0; j < conflictsWith.size(); j++) { + conflictLength += idToRegion.get(conflictsWith.get(j)).length; + } + lenDiff = regionLength - conflictLength; + if(!lenDiffs.containsKey(lenDiff)) + lenDiffs.put(lenDiff, new ArrayList()); + lenDiffs.get(lenDiff).add(id); + lenDiffMin = Math.min(lenDiff, lenDiffMin); + } + + ArrayList minIDs = new ArrayList(lenDiffs.get(lenDiffMin)); + if(minIDs.size() == 1) { + return minIDs.get(0); + } else { + for(int i = 0; i < minIDs.size(); i++) { + id = minIDs.get(i); + noc = cm.conflictsWith(id).size(); + if(!numberOfConflicts.containsKey(noc)) + numberOfConflicts.put(noc, new ArrayList()); + numberOfConflicts.get(noc).add(id); + nocMax = Math.max(nocMax, noc); + } + ArrayList maxIDs = new ArrayList(numberOfConflicts.get(nocMax)); + + if(maxIDs.size() == 1) { + return maxIDs.get(0); + } else { + for(int i = 0; i < minIDs.size(); i++) { + start = idToRegion.get(minIDs.get(i)).start; + startValues.put(start, minIDs.get(i)); + startMax = Math.max(startMax, start); + } + return startValues.get(startMax); + } + } + } + + // Create Array of Regions from connections stored in RNAStructure + public ArrayList Regions (RNAStructure structure) { + + ArrayList regions = new ArrayList(); + ArrayList currentRegion = new ArrayList(); + int regionID = -1; + + for (int i = 0; i < structure.connections.size(); i++) { + if (currentRegion.isEmpty()) { + currentRegion.add(structure.connections.get(i)); + } + else { + if (structure.connections.get(i).getFirst() == currentRegion.get(currentRegion.size()-1).getFirst()+1 && + structure.connections.get(i).getSecond() == currentRegion.get(currentRegion.size()-1).getSecond()-1){ + currentRegion.add(structure.connections.get(i)); + } + else { + regionID++; + regions.add(new Region(currentRegion, regionID)); + currentRegion.clear(); + currentRegion.add(structure.connections.get(i)); + } + } + } + if(!currentRegion.isEmpty()){ + regionID++; + regions.add(new Region(currentRegion, regionID)); + } + + return regions; + } + + // Returns Array of Regions that were removed but can be added back because the are not conflicting anymore + private static ArrayList addBackNonConflicting(Map idToRegion, ArrayList removed) { + ArrayList addBack = new ArrayList(); + SortedMap order = new TreeMap(); + Map idToRemovedRegion = createMap(removed); + boolean added = true, conflicting; + + for(int i = 0; i < removed.size(); i++) { + order.put(removed.get(i).start, removed.get(i).ID); + } + + while(added) { + added = false; + for(Integer start: order.keySet()) { + conflicting = false; + for(Region pr2: idToRegion.values()) { + if(isConflicting(idToRemovedRegion.get(order.get(start)), pr2)) { + conflicting = true; + break; + } + } + if(!conflicting) { + idToRegion.put(order.get(start), idToRemovedRegion.get(order.get(start))); + idToRemovedRegion.get(order.get(start)).restore(); + addBack.add(idToRemovedRegion.get(order.get(start))); + idToRemovedRegion.remove(order.get(start)); + for(int k = 0; k < removed.size(); k++) { + if(removed.get(k).ID == order.get(start)) + removed.remove(k); + } + order.remove(start); + added = true; + break; + } + } + } + return addBack; + } + + // Check if given Regions are conflicting + private static boolean isConflicting(Region first, Region second) { + int startFirst = first.start, endFirst = first.end, startSecond = second.start, endSecond = second.end; + + return (((startFirst < startSecond) && (endFirst < endSecond) && (startSecond < endFirst)) || ((startSecond < startFirst) && (endSecond < endFirst) && (startFirst < endSecond))); + } + + // Update correct connections from pairs + private static void updateConnectionsFromPairs(RNAStructure str) { + ArrayList correctConnections = new ArrayList(); + int size = str.rnaSequence.size(); + int[] temp = new int[size+2]; + + for(int i = 0; i < str.connections.size(); i++) { + temp[str.connections.get(i).getFirst()] = str.connections.get(i).getSecond(); + temp[str.connections.get(i).getSecond()] = str.connections.get(i).getFirst(); + } + for(int i = 0; i < str.rnaSequence.size(); i++) + correctConnections.add(temp[i+1]); + str.correctConnections = correctConnections; + } + + ///////////////////////////////////// + // Dynamic Programming functions + ///////////////////////////////////// + + // Create idMap to access connections and Array of connections + private static ArrayList filterNotConnected(ArrayList originalConnections, Map idMap) { + ArrayList filtered = new ArrayList(); + int id = 0; + Map originalToFiltered = new HashMap(); + for(int i = 0; i < originalConnections.size(); i++) { + if(originalConnections.get(i) != -1) { + originalToFiltered.put(i, id); + idMap.put(id++, i); + filtered.add(originalConnections.get(i)); + } + } + + for(int i = 0; i < filtered.size(); i++) { + int pos = filtered.get(i); + filtered.set(i, originalToFiltered.get(pos)); + } + return filtered; + } + + // Create one range that contains all of the other + private static ArrayList addOuterRange(ArrayList connections) { + ArrayList res = new ArrayList(); + + res.add(connections.size() + 1); + for(int i = 0; i < connections.size(); i++) { + res.add(connections.get(i) + 1); + } + res.add(0); + + return res; + } + + // Create Ranges from given connections + private static ArrayList createRanges(ArrayList connections) { + ArrayList res = new ArrayList(); + + for(int i = 0; i < connections.size(); i++) { + if(i < connections.get(i)) { + res.add(new Range(i, connections.get(i))); + } + } + return res; + } + + // If connections is correct add them to final connections array (make final correct connections) + private static void appendCorrectConnections(int a, int b, ArrayList connections, int[][] dpPosition, ArrayList appendTo) { + if(a >= b) return; + if(dpPosition[a][b] != -1) { + int right = dpPosition[a][b]; + int left = connections.get(right); + + appendTo.add(left); + appendTo.add(right); + + appendCorrectConnections(left + 1, right -1, connections, dpPosition, appendTo); + appendCorrectConnections(a, left - 1, connections, dpPosition, appendTo); + } + } + + // Tell which connections should be as the final ones + private static ArrayList keepSelected(ArrayList connections, ArrayList toKeep) { + boolean[] shouldKeep = new boolean[connections.size()]; + Arrays.fill(shouldKeep, false); + for(int c : toKeep) shouldKeep[c] = true; + ArrayList res = new ArrayList(connections); + for(int i = 0; i < res.size(); i++) { + if(!shouldKeep[i]) { + res.set(i, -1); + } + } + return res; + } + + // Remove helping range that contains everything + private static ArrayList removeOuterRange(ArrayList connections) { + ArrayList res = new ArrayList(); + + for(int i = 1; i < connections.size() - 1; i++) { + if(connections.get(i) == -1) { + res.add(-1); + } else { + res.add(connections.get(i) - 1); + } + } + + return res; + } + + // Build final connections using idMap and filtered connections + private static ArrayList mapBack(ArrayList original, ArrayList filtered, Map idMap) { + ArrayList result = new ArrayList(original); + + for(int i = 0; i < filtered.size(); i++) { + if(filtered.get(i) == -1) { + result.set(idMap.get(i), -1); + } + } + + return result; + } + + ///////////////////////////////////// + // Misc functions + ///////////////////////////////////// + + private static boolean havePairs(RNAStructure structure) { + int isDP = 0; + if (structure.DP) isDP = -1; + for (int i : structure.originalConnections) + if (i != isDP) return true; + return false; + } + + private static void updateDotBracket(RNAStructure str, int bracket) { + int isDP = 0; + if (str.DP) isDP = -1; + for (int i = 0; i < str.correctConnections.size(); i++) { + if (str.correctConnections.get(i) > i && str.correctConnections.get(i) != isDP) str.DotBracket.set(i, openingBracket[bracket]); + else if (str.correctConnections.get(i) <= i && str.correctConnections.get(i) != isDP) str.DotBracket.set(i, closingBracket[bracket]); + } + } + + private static void removeUsedConnections(RNAStructure str) { + int isDP = 1; + if (str.DP) isDP = 0; + for (int i = 0; i < str.correctConnections.size(); i++) { + if (str.originalConnections.get(i) + isDP == str.correctConnections.get(i)) { + str.originalConnections.set(i, isDP-1); + str.correctConnections.set(i, isDP-1); + } + } + } + + private static void updateConnectionPairs(RNAStructure str) { + str.connections.clear(); + for (int i = 0; i < str.originalConnections.size(); i++) { + if(i < str.originalConnections.get(i)) + str.connections.add(new Pair(i+1, str.originalConnections.get(i)+1)); + } + } +} diff --git a/src/main/java/pl/poznan/put/structure/secondary/Pair.java b/src/main/java/pl/poznan/put/structure/secondary/Pair.java new file mode 100644 index 00000000..31d14752 --- /dev/null +++ b/src/main/java/pl/poznan/put/structure/secondary/Pair.java @@ -0,0 +1,17 @@ +package pl.poznan.put.structure.secondary; + + +public class Pair { + private int ST; + private int ND; + + public Pair(int _ST, int _ND) { + ST = _ST; + ND = _ND; + } + + public Pair(Pair rhs) { ST = rhs.ST; ND = rhs.ND;} + + public int getFirst() { return ST; } + public int getSecond() { return ND; } +} diff --git a/src/main/java/pl/poznan/put/structure/secondary/RNAStructure.java b/src/main/java/pl/poznan/put/structure/secondary/RNAStructure.java new file mode 100644 index 00000000..234cefd2 --- /dev/null +++ b/src/main/java/pl/poznan/put/structure/secondary/RNAStructure.java @@ -0,0 +1,133 @@ +package pl.poznan.put.structure.secondary; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; + +import pl.poznan.put.structure.secondary.formats.BpSeq; + +public class RNAStructure { + + public ArrayList rnaSequence = new ArrayList(); + public ArrayList connections = new ArrayList(); + public ArrayList originalConnections = new ArrayList(); + public ArrayList correctConnections = new ArrayList(); + public ArrayList DotBracket = new ArrayList(); + public boolean DP = false; + + + // Function to create a deep copy of RNAStructure class + public RNAStructure(RNAStructure rhs) { + for(int i = 0; i < rhs.connections.size(); i++) { + connections.add(new Pair(rhs.connections.get(i))); + rnaSequence.add(rhs.rnaSequence.get(i)); + DotBracket.add(rhs.DotBracket.get(i)); + originalConnections.add(rhs.originalConnections.get(i)); + } + for(int i = rhs.connections.size(); i < rhs.rnaSequence.size(); i++){ + rnaSequence.add(rhs.rnaSequence.get(i)); + DotBracket.add(rhs.DotBracket.get(i)); + originalConnections.add(rhs.originalConnections.get(i)); + } + } + + + // Initial function that analyse input file and parse lines to make connections and RNA sequence + public RNAStructure(String filename) { + try { + BufferedReader reader = new BufferedReader(new FileReader(filename)); + String line; + while ((line = reader.readLine()) != null) { + parseLine(line); + } + reader.close(); + } + catch (IOException e) { + System.err.format("Exception occurred trying to read '%s'.", filename); + e.printStackTrace(); + } + } + + public RNAStructure(BpSeq bpSeq) { + for (BpSeq.Entry e : bpSeq.getEntries()) { + rnaSequence.add(e.getSeq()); + originalConnections.add(e.getPair() - 1); + DotBracket.add('.'); + if (e.getIndex() < e.getPair()) + connections.add(new Pair(e.getIndex(), e.getPair())); + } + } + + public String getSequence() { + String Seq = ""; + for (char c : rnaSequence) + Seq += c; + return Seq; + } + + public String getStructure() { + String Str = ""; + for (int i : originalConnections) + Str += Integer.toString(i); + return Str; + } + + public String getDotBracketStructure() { + String Str = ""; + for (char c : DotBracket) + Str += c; + return Str; + } + + // Save optimal structure to output file + public void saveFile(String filename) { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(filename)); + // check if Dynamic Programming algorithm was used. It returns a slightly different Protein Structure + if(!DP) { + int[] output = createOutput(); + + for(int i = 0; i < rnaSequence.size(); i++) { + writer.write(i+1 + " " + rnaSequence.get(i) + " " + output[i+1]); + writer.newLine(); + } + } else { + for(int i = 0; i < rnaSequence.size(); i++) { + writer.write(i+1 + " " + rnaSequence.get(i) + " " + (correctConnections.get(i)+1)); + writer.newLine(); + } + } + writer.close(); + } catch (IOException e) { + System.err.format("Exception occurred trying to save '%s'.", filename); + e.printStackTrace(); + } + } + + // Parse line from .bpseq input to RNA sequence and connections + private void parseLine(String line){ + int index = line.indexOf(' '); + DotBracket.add('.'); + rnaSequence.add(line.charAt(index+1)); + int first = Integer.parseInt(line.substring(0, index)), second = Integer.parseInt(line.substring(index + 3)); + if(first < second) + connections.add(new Pair(first, second)); + originalConnections.add(second-1); + } + + // Create temporary array from pairs for output simplicity + private int[] createOutput(){ + int size = rnaSequence.size(); + int[] output = new int[size+2]; + + for(int i = 0; i < connections.size(); i++){ + output[connections.get(i).getFirst()] = connections.get(i).getSecond(); + output[connections.get(i).getSecond()] = connections.get(i).getFirst(); + } + + return output; + } +} diff --git a/src/main/java/pl/poznan/put/structure/secondary/Range.java b/src/main/java/pl/poznan/put/structure/secondary/Range.java new file mode 100644 index 00000000..91e7cc7c --- /dev/null +++ b/src/main/java/pl/poznan/put/structure/secondary/Range.java @@ -0,0 +1,31 @@ +package pl.poznan.put.structure.secondary; + + +public class Range implements Comparable { + + public int left; + public int right; + + + public Range(int l, int r) { + left = l; + right = r; + } + + public int size() { + return Math.abs(left - right); + } + + public boolean contains(int node) { + return ((node <= right) && (node >= left)); + } + + @Override + public int compareTo(Range rhs) { + if (size() < rhs.size()) return -1; + if (size() > rhs.size()) return 1; + if (left < rhs.left) return -1; + return 1; + } + +} diff --git a/src/main/java/pl/poznan/put/structure/secondary/Region.java b/src/main/java/pl/poznan/put/structure/secondary/Region.java new file mode 100644 index 00000000..728b68e6 --- /dev/null +++ b/src/main/java/pl/poznan/put/structure/secondary/Region.java @@ -0,0 +1,70 @@ +package pl.poznan.put.structure.secondary; + +import java.util.ArrayList; + +// Class that contains compressed connections +public class Region { + + private ArrayList contain = null; + public int ID, start, end, length; + private boolean isRemoved; + + // Create a region + public Region(ArrayList currentRegions, int regionID){ + contain = new ArrayList(currentRegions); + start = currentRegions.get(0).getFirst(); + end = currentRegions.get(0).getSecond(); + length = currentRegions.size(); + ID = regionID; + isRemoved = false; + } + + // Create Array of Regions from connections stored in RNAStructure + public ArrayList Regions (RNAStructure structure) { + + ArrayList regions = new ArrayList(); + ArrayList currentRegion = new ArrayList(); + int regionID = -1; + + for (int i = 0; i < structure.connections.size(); i++) { + if (currentRegion.isEmpty()) { + currentRegion.add(structure.connections.get(i)); + } + else { + if (structure.connections.get(i).getFirst() == currentRegion.get(currentRegion.size()-1).getFirst()+1 && + structure.connections.get(i).getSecond() == currentRegion.get(currentRegion.size()-1).getSecond()-1){ + currentRegion.add(structure.connections.get(i)); + } + else { + regionID++; + regions.add(new Region(currentRegion, regionID)); + currentRegion.clear(); + currentRegion.add(structure.connections.get(i)); + } + } + } + if(!currentRegion.isEmpty()){ + regionID++; + regions.add(new Region(currentRegion, regionID)); + } + + return regions; + } + + public ArrayList getPairs(){ + return contain; + } + + public boolean isRemoved(){ + return isRemoved; + } + + public void remove(){ + isRemoved = true; + } + + public void restore(){ + isRemoved = false; + } + +}