X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fstructure%2FStructureSelectionManager.java;h=ed5ee2d4cb4afb58a51d8695075c536cdc1f76f5;hb=466c5639624028f92e214121672dc409ad10514b;hp=3fead00381c533f9f3a267978e36cba46c20bf3c;hpb=2a4301b8fdda9f4e9d77473402d9b91b51009735;p=jalview.git diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index 3fead00..ed5ee2d 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -1,6 +1,6 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * @@ -24,27 +24,27 @@ import jalview.analysis.AlignSeq; import jalview.api.StructureSelectionManagerProvider; import jalview.commands.CommandI; import jalview.commands.EditCommand; -import jalview.commands.EditCommand.Action; -import jalview.commands.EditCommand.Edit; +import jalview.commands.OrderCommand; import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; import jalview.datamodel.Annotation; import jalview.datamodel.PDBEntry; import jalview.datamodel.SearchResults; -import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; import jalview.io.AppletFormatAdapter; +import jalview.util.MappingUtils; import jalview.util.MessageManager; -import jalview.util.StringUtils; import java.io.PrintStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.IdentityHashMap; -import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Vector; import MCview.Atom; @@ -54,17 +54,29 @@ public class StructureSelectionManager { static IdentityHashMap instances; - StructureMapping[] mappings; + private List mappings = new ArrayList(); - private boolean processSecondaryStructure = false, - secStructServices = false, addTempFacAnnot = false; + private boolean processSecondaryStructure = false; - List seqmappings = null; + private boolean secStructServices = false; - private int[] seqmappingrefs = null; // refcount for seqmappings elements + private boolean addTempFacAnnot = false; + + /* + * Set of any registered mappings between (dataset) sequences. + */ + Set seqmappings = new LinkedHashSet(); + + /* + * Reference counters for the above mappings. Remove mappings when ref count + * goes to zero. + */ + Map seqMappingRefCounts = new HashMap(); private List commandListeners = new ArrayList(); + private List sel_listeners = new ArrayList(); + /** * @return true if will try to use external services for processing secondary * structure @@ -131,17 +143,18 @@ public class StructureSelectionManager */ public void reportMapping() { - if (mappings == null) + if (mappings.isEmpty()) { System.err.println("reportMapping: No PDB/Sequence mappings."); } else { - System.err.println("reportMapping: There are " + mappings.length + System.err.println("reportMapping: There are " + mappings.size() + " mappings."); - for (int m = 0; m < mappings.length; m++) + int i = 0; + for (StructureMapping sm : mappings) { - System.err.println("mapping " + m + " : " + mappings[m].pdbfile); + System.err.println("mapping " + i++ + " : " + sm.pdbfile); } } } @@ -262,16 +275,19 @@ public class StructureSelectionManager } } + /** + * Returns the file name for a mapped PDB id (or null if not mapped). + * + * @param pdbid + * @return + */ public String alreadyMappedToFile(String pdbid) { - if (mappings != null) + for (StructureMapping sm : mappings) { - for (int i = 0; i < mappings.length; i++) + if (sm.getPdbId().equals(pdbid)) { - if (mappings[i].getPdbId().equals(pdbid)) - { - return mappings[i].pdbfile; - } + return sm.pdbfile; } } return null; @@ -498,19 +514,7 @@ public class StructureSelectionManager mappingDetails.toString()); if (forStructureView) { - - if (mappings == null) - { - mappings = new StructureMapping[1]; - } - else - { - StructureMapping[] tmp = new StructureMapping[mappings.length + 1]; - System.arraycopy(mappings, 0, tmp, 0, mappings.length); - mappings = tmp; - } - - mappings[mappings.length - 1] = newMapping; + mappings.add(newMapping); } maxChain.transferResidueAnnotation(newMapping, sqmpping); } @@ -562,19 +566,18 @@ public class StructureSelectionManager } } - if (pdbs.size() > 0 && mappings != null) + if (pdbs.size() > 0) { - Vector tmp = new Vector(); - for (int i = 0; i < mappings.length; i++) + List tmp = new ArrayList(); + for (StructureMapping sm : mappings) { - if (!pdbs.contains(mappings[i].pdbfile)) + if (!pdbs.contains(sm.pdbfile)) { - tmp.addElement(mappings[i]); + tmp.add(sm); } } - mappings = new StructureMapping[tmp.size()]; - tmp.copyInto(mappings); + mappings = tmp; } } @@ -585,7 +588,6 @@ public class StructureSelectionManager // old or prematurely sent event return; } - boolean hasSequenceListeners = handlingVamsasMo || seqmappings != null; SearchResults results = null; SequenceI lastseq = null; int lastipos = -1, indexpos; @@ -597,28 +599,20 @@ public class StructureSelectionManager { results = new SearchResults(); } - if (mappings != null) + for (StructureMapping sm : mappings) { - for (int j = 0; j < mappings.length; j++) + if (sm.pdbfile.equals(pdbfile) && sm.pdbchain.equals(chain)) { - if (mappings[j].pdbfile.equals(pdbfile) - && mappings[j].pdbchain.equals(chain)) + indexpos = sm.getSeqPos(pdbResNum); + if (lastipos != indexpos && lastseq != sm.sequence) { - indexpos = mappings[j].getSeqPos(pdbResNum); - if (lastipos != indexpos && lastseq != mappings[j].sequence) + results.addResult(sm.sequence, indexpos, indexpos); + lastipos = indexpos; + lastseq = sm.sequence; + // construct highlighted sequence list + for (AlignedCodonFrame acf : seqmappings) { - results.addResult(mappings[j].sequence, indexpos, indexpos); - lastipos = indexpos; - lastseq = mappings[j].sequence; - // construct highlighted sequence list - if (seqmappings != null) - { - for (AlignedCodonFrame acf : seqmappings) - { - acf.markMappedRegion(mappings[j].sequence, indexpos, - results); - } - } + acf.markMappedRegion(sm.sequence, indexpos, results); } } } @@ -652,7 +646,8 @@ public class StructureSelectionManager public void mouseOverSequence(SequenceI seq, int indexpos, int index, VamsasSource source) { - boolean hasSequenceListeners = handlingVamsasMo || seqmappings != null; + boolean hasSequenceListeners = handlingVamsasMo + || !seqmappings.isEmpty(); SearchResults results = null; if (index == -1) { @@ -683,7 +678,13 @@ public class StructureSelectionManager { if (results == null) { - results = buildSearchResults(seq, index); + results = MappingUtils.buildSearchResults(seq, index, + seqmappings); + } + if (handlingVamsasMo) + { + results.addResult(seq, index, index); + } seqListener.highlightSequence(results); } @@ -704,39 +705,6 @@ public class StructureSelectionManager } /** - * Returns a SearchResults object describing the mapped region corresponding - * to the specified sequence position. - * - * @param seq - * @param index - * @return - */ - protected SearchResults buildSearchResults(SequenceI seq, int index) - { - SearchResults results; - results = new SearchResults(); - if (index >= seq.getStart() && index <= seq.getEnd()) - { - if (seqmappings != null) - { - for (AlignedCodonFrame acf : seqmappings) - { - acf.markMappedRegion(seq, index, results); - } - } - // hasSequenceListeners = results.getSize() > 0; - if (handlingVamsasMo) - { - // maybe have to resolve seq to a dataset sequence... - // add in additional direct sequence and/or dataset sequence - // highlighting - results.addResult(seq, index, index); - } - } - return results; - } - - /** * Send suitable messages to a StructureListener to highlight atoms * corresponding to the given sequence position. * @@ -748,26 +716,21 @@ public class StructureSelectionManager int index) { int atomNo; - if (mappings != null) + List atoms = new ArrayList(); + for (StructureMapping sm : mappings) { - List atoms = new ArrayList(); - for (int j = 0; j < mappings.length; j++) + if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()) { - if (mappings[j].sequence == seq - || mappings[j].sequence == seq.getDatasetSequence()) - { - atomNo = mappings[j].getAtomNum(index); + atomNo = sm.getAtomNum(index); - if (atomNo > 0) - { - atoms.add(new AtomSpec(mappings[j].pdbfile, - mappings[j].pdbchain, mappings[j].getPDBResNum(index), - atomNo)); - } + if (atomNo > 0) + { + atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm + .getPDBResNum(index), atomNo)); } } - sl.highlightAtoms(atoms); } + sl.highlightAtoms(atoms); } /** @@ -856,117 +819,114 @@ public class StructureSelectionManager public StructureMapping[] getMapping(String pdbfile) { - Vector tmp = new Vector(); - if (mappings != null) - { - for (int i = 0; i < mappings.length; i++) + List tmp = new ArrayList(); + for (StructureMapping sm : mappings) { - if (mappings[i].pdbfile.equals(pdbfile)) + if (sm.pdbfile.equals(pdbfile)) { - tmp.addElement(mappings[i]); + tmp.add(sm); } - } } - StructureMapping[] ret = new StructureMapping[tmp.size()]; - for (int i = 0; i < tmp.size(); i++) - { - ret[i] = (StructureMapping) tmp.elementAt(i); - } - - return ret; + return tmp.toArray(new StructureMapping[tmp.size()]); } public String printMapping(String pdbfile) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < mappings.length; i++) + StringBuilder sb = new StringBuilder(64); + for (StructureMapping sm : mappings) { - if (mappings[i].pdbfile.equals(pdbfile)) + if (sm.pdbfile.equals(pdbfile)) { - sb.append(mappings[i].mappingDetails); + sb.append(sm.mappingDetails); } } return sb.toString(); } - private synchronized void modifySeqMappingList(boolean add, - AlignedCodonFrame[] codonFrames) + /** + * Decrement the reference counter for each of the given mappings, and remove + * it entirely if its reference counter reduces to zero. + * + * @param set + */ + public void removeMappings(Set set) { - if (!add && (seqmappings == null || seqmappings.size() == 0)) + if (set != null) { - return; - } - if (seqmappings == null) - { - seqmappings = new ArrayList(); + for (AlignedCodonFrame acf : set) + { + removeMapping(acf); + } } - if (codonFrames != null && codonFrames.length > 0) + } + + /** + * Decrement the reference counter for the given mapping, and remove it + * entirely if its reference counter reduces to zero. + * + * @param acf + */ + public void removeMapping(AlignedCodonFrame acf) + { + if (acf != null && seqmappings.contains(acf)) { - for (int cf = 0; cf < codonFrames.length; cf++) + int count = seqMappingRefCounts.get(acf); + count--; + if (count > 0) { - if (seqmappings.contains(codonFrames[cf])) - { - if (add) - { - seqmappingrefs[seqmappings.indexOf(codonFrames[cf])]++; - } - else - { - if (--seqmappingrefs[seqmappings.indexOf(codonFrames[cf])] <= 0) - { - int pos = seqmappings.indexOf(codonFrames[cf]); - int[] nr = new int[seqmappingrefs.length - 1]; - if (pos > 0) - { - System.arraycopy(seqmappingrefs, 0, nr, 0, pos); - } - if (pos < seqmappingrefs.length - 1) - { - System.arraycopy(seqmappingrefs, pos + 1, nr, 0, - seqmappingrefs.length - pos - 2); - } - } - } - } - else - { - if (add) - { - seqmappings.add(codonFrames[cf]); - - int[] nsr = new int[(seqmappingrefs == null) ? 1 - : seqmappingrefs.length + 1]; - if (seqmappingrefs != null && seqmappingrefs.length > 0) - { - System.arraycopy(seqmappingrefs, 0, nsr, 0, - seqmappingrefs.length); - } - nsr[(seqmappingrefs == null) ? 0 : seqmappingrefs.length] = 1; - seqmappingrefs = nsr; - } - } + seqMappingRefCounts.put(acf, count); + } + else + { + seqmappings.remove(acf); + seqMappingRefCounts.remove(acf); } } } - public void removeMappings(AlignedCodonFrame[] codonFrames) + /** + * Add each of the given codonFrames to the stored set. If not aready present, + * increments its reference count instead. + * + * @param set + */ + public void addMappings(Set set) { - modifySeqMappingList(false, codonFrames); + if (set != null) + { + for (AlignedCodonFrame acf : set) + { + addMapping(acf); + } + } } - public void addMappings(AlignedCodonFrame[] codonFrames) + /** + * Add the given mapping to the stored set, or if already stored, increment + * its reference counter. + */ + public void addMapping(AlignedCodonFrame acf) { - modifySeqMappingList(true, codonFrames); + if (acf != null) + { + if (seqmappings.contains(acf)) + { + seqMappingRefCounts.put(acf, seqMappingRefCounts.get(acf) + 1); + } + else + { + seqmappings.add(acf); + seqMappingRefCounts.put(acf, 1); + } + } } - Vector sel_listeners = new Vector(); - public void addSelectionListener(SelectionListener selecter) { if (!sel_listeners.contains(selecter)) { - sel_listeners.addElement(selecter); + sel_listeners.add(selecter); } } @@ -974,7 +934,7 @@ public class StructureSelectionManager { if (sel_listeners.contains(toremove)) { - sel_listeners.removeElement(toremove); + sel_listeners.remove(toremove); } } @@ -982,18 +942,11 @@ public class StructureSelectionManager jalview.datamodel.SequenceGroup selection, jalview.datamodel.ColumnSelection colsel, SelectionSource source) { - if (sel_listeners != null && sel_listeners.size() > 0) + for (SelectionListener slis : sel_listeners) { - Enumeration listeners = sel_listeners.elements(); - while (listeners.hasMoreElements()) + if (slis != source) { - SelectionListener slis = ((SelectionListener) listeners - .nextElement()); - if (slis != source) - { - slis.selection(selection, colsel, source); - } - ; + slis.selection(selection, colsel, source); } } } @@ -1021,32 +974,6 @@ public class StructureSelectionManager } } - public void finalize() throws Throwable - { - if (listeners != null) - { - listeners.clear(); - listeners = null; - } - if (pdbIdFileName != null) - { - pdbIdFileName.clear(); - pdbIdFileName = null; - } - if (sel_listeners != null) - { - sel_listeners.clear(); - sel_listeners = null; - } - if (view_listeners != null) - { - view_listeners.clear(); - view_listeners = null; - } - mappings = null; - seqmappingrefs = null; - } - /** * release all references associated with this manager provider * @@ -1070,7 +997,6 @@ public class StructureSelectionManager } catch (Throwable x) { } - ; } } } @@ -1097,7 +1023,7 @@ public class StructureSelectionManager return this.commandListeners.contains(cl); } - public boolean removeEditListener(CommandListener l) + public boolean removeCommandListener(CommandListener l) { return commandListeners.remove(l); } @@ -1117,143 +1043,34 @@ public class StructureSelectionManager { for (CommandListener listener : commandListeners) { - if (listener.getVamsasSource() != source) - { - listener.mirrorCommand(command, undo, this); - } + listener.mirrorCommand(command, undo, this, source); } } /** - * Returns a new EditCommand representing the given command as mapped to the - * given sequences. If there is no mapping, returns an empty EditCommand. + * Returns a new CommandI representing the given command as mapped to the + * given sequences. If no mapping could be made, or the command is not of a + * mappable kind, returns null. * * @param command * @param undo - * @param targetSeqs + * @param mapTo * @param gapChar * @return */ - public EditCommand mapEditCommand(EditCommand command, boolean undo, - final List targetSeqs, char gapChar) + public CommandI mapCommand(CommandI command, boolean undo, + final AlignmentI mapTo, char gapChar) { - /* - * Cache a copy of the target sequences so we can mimic successive edits on - * them. This lets us compute mappings for all edits in the set. - */ - Map targetCopies = new HashMap(); - for (SequenceI seq : targetSeqs) + if (command instanceof EditCommand) { - SequenceI ds = seq.getDatasetSequence(); - if (ds != null) - { - final Sequence copy = new Sequence("", new String(seq.getSequence())); - copy.setDatasetSequence(ds); - targetCopies.put(ds, copy); - } + return MappingUtils.mapEditCommand((EditCommand) command, undo, + mapTo, gapChar, seqmappings); } - - /* - * Compute 'source' sequences as they were before applying edits: - */ - Map originalSequences = command.priorState(undo); - - EditCommand result = new EditCommand(); - Iterator edits = command.getEditIterator(!undo); - while (edits.hasNext()) + else if (command instanceof OrderCommand) { - Edit edit = edits.next(); - Action action = edit.getAction(); - - /* - * Invert sense of action if an Undo. - */ - if (undo) - { - action = action == Action.INSERT_GAP ? Action.DELETE_GAP - : (action == Action.DELETE_GAP ? Action.INSERT_GAP : action); - } - final int count = edit.getNumber(); - final int editPos = edit.getPosition(); - for (SequenceI seq : edit.getSequences()) - { - /* - * Get residue position at (or to right of) edit location. Note we use - * our 'copy' of the sequence before editing for this. - */ - SequenceI ds = seq.getDatasetSequence(); - if (ds == null) - { - continue; - } - final SequenceI actedOn = originalSequences.get(ds); - final int seqpos = actedOn.findPosition(editPos); - - /* - * Determine all mappings from this position to mapped sequences. - */ - SearchResults sr = buildSearchResults(seq, seqpos); - - if (!sr.isEmpty()) - { - for (SequenceI targetSeq : targetSeqs) - { - ds = targetSeq.getDatasetSequence(); - if (ds == null) - { - continue; - } - SequenceI copyTarget = targetCopies.get(ds); - final int[] match = sr.getResults(copyTarget, 0, - copyTarget.getLength()); - if (match != null) - { - final int ratio = 3; // TODO: compute this - how? - final int mappedCount = count * ratio; - - /* - * Shift Delete start position left, as it acts on positions to - * its right. - */ - int mappedEditPos = action == Action.DELETE_GAP ? match[0] - - mappedCount : match[0]; - Edit e = new EditCommand().new Edit(action, new SequenceI[] - { targetSeq }, mappedEditPos, mappedCount, gapChar); - result.addEdit(e); - - /* - * and 'apply' the edit to our copy of its target sequence - */ - if (action == Action.INSERT_GAP) - { - copyTarget.setSequence(new String(StringUtils.insertCharAt( - copyTarget.getSequence(), mappedEditPos, - mappedCount, - gapChar))); - } - else if (action == Action.DELETE_GAP) - { - copyTarget.setSequence(new String(StringUtils.deleteChars( - copyTarget.getSequence(), mappedEditPos, - mappedEditPos + mappedCount))); - } - } - } - } - /* - * and 'apply' the edit to our copy of its source sequence - */ - if (action == Action.INSERT_GAP) { - actedOn.setSequence(new String(StringUtils.insertCharAt( - actedOn.getSequence(), editPos, count, gapChar))); - } - else if (action == Action.DELETE_GAP) - { - actedOn.setSequence(new String(StringUtils.deleteChars( - actedOn.getSequence(), editPos, editPos + count))); - } - } + return MappingUtils.mapOrderCommand((OrderCommand) command, undo, + mapTo, seqmappings); } - return result; + return null; } }