2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.structure;
23 import jalview.analysis.AlignSeq;
24 import jalview.api.StructureSelectionManagerProvider;
25 import jalview.commands.CommandI;
26 import jalview.commands.EditCommand;
27 import jalview.commands.OrderCommand;
28 import jalview.datamodel.AlignedCodonFrame;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.Annotation;
32 import jalview.datamodel.PDBEntry;
33 import jalview.datamodel.SearchResults;
34 import jalview.datamodel.SequenceI;
35 import jalview.gui.IProgressIndicator;
36 import jalview.io.AppletFormatAdapter;
37 import jalview.io.StructureFile;
38 import jalview.util.MappingUtils;
39 import jalview.util.MessageManager;
40 import jalview.ws.sifts.SiftsClient;
41 import jalview.ws.sifts.SiftsException;
42 import jalview.ws.sifts.SiftsSettings;
44 import java.io.PrintStream;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.Enumeration;
49 import java.util.HashMap;
50 import java.util.IdentityHashMap;
51 import java.util.List;
53 import java.util.Vector;
56 import MCview.PDBChain;
57 import MCview.PDBfile;
59 public class StructureSelectionManager
61 public final static String NEWLINE = System.lineSeparator();
63 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
65 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
67 private boolean processSecondaryStructure = false;
69 private boolean secStructServices = false;
71 private boolean addTempFacAnnot = false;
73 private IProgressIndicator progressIndicator;
75 private SiftsClient siftsClient = null;
77 private long progressSessionId;
80 * Set of any registered mappings between (dataset) sequences.
82 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
84 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
86 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
89 * @return true if will try to use external services for processing secondary
92 public boolean isSecStructServices()
94 return secStructServices;
98 * control use of external services for processing secondary structure
100 * @param secStructServices
102 public void setSecStructServices(boolean secStructServices)
104 this.secStructServices = secStructServices;
108 * flag controlling addition of any kind of structural annotation
110 * @return true if temperature factor annotation will be added
112 public boolean isAddTempFacAnnot()
114 return addTempFacAnnot;
118 * set flag controlling addition of structural annotation
120 * @param addTempFacAnnot
122 public void setAddTempFacAnnot(boolean addTempFacAnnot)
124 this.addTempFacAnnot = addTempFacAnnot;
129 * @return if true, the structure manager will attempt to add secondary
130 * structure lines for unannotated sequences
133 public boolean isProcessSecondaryStructure()
135 return processSecondaryStructure;
139 * Control whether structure manager will try to annotate mapped sequences
140 * with secondary structure from PDB data.
144 public void setProcessSecondaryStructure(boolean enable)
146 processSecondaryStructure = enable;
150 * debug function - write all mappings to stdout
152 public void reportMapping()
154 if (mappings.isEmpty())
156 System.err.println("reportMapping: No PDB/Sequence mappings.");
160 System.err.println("reportMapping: There are " + mappings.size()
163 for (StructureMapping sm : mappings)
165 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
171 * map between the PDB IDs (or structure identifiers) used by Jalview and the
172 * absolute filenames for PDB data that corresponds to it
174 Map<String, String> pdbIdFileName = new HashMap<String, String>();
176 Map<String, String> pdbFileNameId = new HashMap<String, String>();
178 public void registerPDBFile(String idForFile, String absoluteFile)
180 pdbIdFileName.put(idForFile, absoluteFile);
181 pdbFileNameId.put(absoluteFile, idForFile);
184 public String findIdForPDBFile(String idOrFile)
186 String id = pdbFileNameId.get(idOrFile);
190 public String findFileForPDBId(String idOrFile)
192 String id = pdbIdFileName.get(idOrFile);
196 public boolean isPDBFileRegistered(String idOrFile)
198 return pdbFileNameId.containsKey(idOrFile)
199 || pdbIdFileName.containsKey(idOrFile);
202 private static StructureSelectionManager nullProvider = null;
204 public static StructureSelectionManager getStructureSelectionManager(
205 StructureSelectionManagerProvider context)
209 if (nullProvider == null)
211 if (instances != null)
215 .getString("error.implementation_error_structure_selection_manager_null"),
216 new NullPointerException(MessageManager
217 .getString("exception.ssm_context_is_null")));
221 nullProvider = new StructureSelectionManager();
226 if (instances == null)
228 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
230 StructureSelectionManager instance = instances.get(context);
231 if (instance == null)
233 if (nullProvider != null)
235 instance = nullProvider;
239 instance = new StructureSelectionManager();
241 instances.put(context, instance);
247 * flag controlling whether SeqMappings are relayed from received sequence
248 * mouse over events to other sequences
250 boolean relaySeqMappings = true;
253 * Enable or disable relay of seqMapping events to other sequences. You might
254 * want to do this if there are many sequence mappings and the host computer
259 public void setRelaySeqMappings(boolean relay)
261 relaySeqMappings = relay;
265 * get the state of the relay seqMappings flag.
267 * @return true if sequence mouse overs are being relayed to other mapped
270 public boolean isRelaySeqMappingsEnabled()
272 return relaySeqMappings;
275 Vector listeners = new Vector();
278 * register a listener for alignment sequence mouseover events
282 public void addStructureViewerListener(Object svl)
284 if (!listeners.contains(svl))
286 listeners.addElement(svl);
291 * Returns the file name for a mapped PDB id (or null if not mapped).
296 public String alreadyMappedToFile(String pdbid)
298 for (StructureMapping sm : mappings)
300 if (sm.getPdbId().equals(pdbid))
309 * Import structure data and register a structure mapping for broadcasting
310 * colouring, mouseovers and selection events (convenience wrapper).
313 * - one or more sequences to be mapped to pdbFile
314 * @param targetChains
315 * - optional chain specification for mapping each sequence to pdb
316 * (may be nill, individual elements may be nill)
318 * - structure data resource
320 * - how to resolve data from resource
321 * @return null or the structure data parsed as a pdb file
323 synchronized public StructureFile setMapping(SequenceI[] sequence,
324 String[] targetChains, String pdbFile, String protocol)
326 return setMapping(true, sequence, targetChains, pdbFile, protocol);
331 * create sequence structure mappings between each sequence and the given
332 * pdbFile (retrieved via the given protocol).
334 * @param forStructureView
335 * when true, record the mapping for use in mouseOvers
337 * @param sequenceArray
338 * - one or more sequences to be mapped to pdbFile
339 * @param targetChainIds
340 * - optional chain specification for mapping each sequence to pdb
341 * (may be nill, individual elements may be nill)
343 * - structure data resource
345 * - how to resolve data from resource
346 * @return null or the structure data parsed as a pdb file
348 synchronized public StructureFile setMapping(boolean forStructureView,
349 SequenceI[] sequenceArray, String[] targetChainIds,
354 * There will be better ways of doing this in the future, for now we'll use
355 * the tried and tested MCview pdb mapping
357 boolean parseSecStr = processSecondaryStructure;
358 if (isPDBFileRegistered(pdbFile))
360 for (SequenceI sq : sequenceArray)
363 while (ds.getDatasetSequence() != null)
365 ds = ds.getDatasetSequence();
368 if (ds.getAnnotation() != null)
370 for (AlignmentAnnotation ala : ds.getAnnotation())
372 // false if any annotation present from this structure
373 // JBPNote this fails for jmol/chimera view because the *file* is
374 // passed, not the structure data ID -
375 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
383 StructureFile pdb = null;
384 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
388 boolean isParseWithJMOL = StructureImportSettings
389 .getDefaultPDBFileParser().equalsIgnoreCase(
390 StructureImportSettings.StructureParser.JMOL_PARSER
392 if (isParseWithJMOL || (pdbFile != null && isCIFFile(pdbFile)))
394 pdb = new jalview.ext.jmol.JmolParser(addTempFacAnnot, parseSecStr,
395 secStructServices, pdbFile, protocol);
399 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
403 if (pdb.getId() != null && pdb.getId().trim().length() > 0
404 && AppletFormatAdapter.FILE.equals(protocol))
406 registerPDBFile(pdb.getId().trim(), pdbFile);
408 } catch (Exception ex)
410 ex.printStackTrace();
418 siftsClient = new SiftsClient(pdb);
420 } catch (SiftsException e)
422 isMapUsingSIFTs = false;
426 String targetChainId;
427 for (int s = 0; s < sequenceArray.length; s++)
429 boolean infChain = true;
430 final SequenceI seq = sequenceArray[s];
431 if (targetChainIds != null && targetChainIds[s] != null)
434 targetChainId = targetChainIds[s];
436 else if (seq.getName().indexOf("|") > -1)
438 targetChainId = seq.getName().substring(
439 seq.getName().lastIndexOf("|") + 1);
440 if (targetChainId.length() > 1)
442 if (targetChainId.trim().length() == 0)
448 // not a valid chain identifier
459 * Attempt pairwise alignment of the sequence with each chain in the PDB,
460 * and remember the highest scoring chain
463 AlignSeq maxAlignseq = null;
464 String maxChainId = " ";
465 PDBChain maxChain = null;
466 boolean first = true;
467 for (PDBChain chain : pdb.getChains())
469 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
472 continue; // don't try to map chains don't match.
474 // TODO: correctly determine sequence type for mixed na/peptide
476 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
477 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
480 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
481 // as.calcScoreMatrix();
482 // as.traceAlignment();
484 if (first || as.maxscore > max
485 || (as.maxscore == max && chain.id.equals(targetChainId)))
491 maxChainId = chain.id;
494 if (maxChain == null)
499 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
501 pdbFile = "INLINE" + pdb.getId();
504 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
507 setProgressBar(null);
508 setProgressBar(MessageManager
509 .getString("status.obtaining_mapping_with_sifts"));
510 jalview.datamodel.Mapping sqmpping = maxAlignseq
511 .getMappingFromS1(false);
512 if (targetChainId != null && !targetChainId.trim().isEmpty())
514 StructureMapping siftsMapping;
517 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
518 pdb, maxChain, sqmpping, maxAlignseq);
519 seqToStrucMapping.add(siftsMapping);
520 maxChain.makeExactMapping(maxAlignseq, seq);
521 maxChain.transferRESNUMFeatures(seq, null);
522 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
523 } catch (SiftsException e)
525 // fall back to NW alignment
526 System.err.println(e.getMessage());
527 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
528 targetChainId, maxChain, pdb, maxAlignseq);
529 seqToStrucMapping.add(nwMapping);
534 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
535 for (PDBChain chain : pdb.getChains())
539 StructureMapping siftsMapping = getStructureMapping(seq,
541 chain.id, pdb, chain, sqmpping, maxAlignseq);
542 foundSiftsMappings.add(siftsMapping);
543 } catch (SiftsException e)
545 System.err.println(e.getMessage());
548 if (!foundSiftsMappings.isEmpty())
550 seqToStrucMapping.addAll(foundSiftsMappings);
551 maxChain.makeExactMapping(maxAlignseq, seq);
552 maxChain.transferRESNUMFeatures(seq, null);
553 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
558 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
559 maxChainId, maxChain, pdb, maxAlignseq);
560 seqToStrucMapping.add(nwMapping);
566 setProgressBar(null);
567 setProgressBar(MessageManager
568 .getString("status.obtaining_mapping_with_nw_alignment"));
569 seqToStrucMapping.add(getNWMappings(seq, pdbFile, maxChainId,
570 maxChain, pdb, maxAlignseq));
573 if (forStructureView)
575 mappings.addAll(seqToStrucMapping);
581 private boolean isCIFFile(String filename)
583 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
585 return "cif".equalsIgnoreCase(fileExt);
588 private StructureMapping getStructureMapping(SequenceI seq,
589 String pdbFile, String targetChainId, StructureFile pdb,
590 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
591 AlignSeq maxAlignseq) throws SiftsException
593 StructureMapping curChainMapping = siftsClient
594 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
597 PDBChain chain = pdb.findChain(targetChainId);
600 chain.transferResidueAnnotation(curChainMapping, sqmpping);
602 } catch (Exception e)
606 return curChainMapping;
609 private StructureMapping getNWMappings(SequenceI seq,
611 String maxChainId, PDBChain maxChain, StructureFile pdb,
612 AlignSeq maxAlignseq)
614 final StringBuilder mappingDetails = new StringBuilder(128);
615 mappingDetails.append(NEWLINE).append(
616 "Sequence \u27f7 Structure mapping details");
617 mappingDetails.append(NEWLINE);
619 .append("Method: inferred with Needleman & Wunsch alignment");
620 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
621 .append(NEWLINE).append("Sequence = ")
622 .append(maxChain.sequence.getSequenceAsString());
623 mappingDetails.append(NEWLINE).append("No of residues = ")
624 .append(maxChain.residues.size()).append(NEWLINE)
626 PrintStream ps = new PrintStream(System.out)
629 public void print(String x)
631 mappingDetails.append(x);
635 public void println()
637 mappingDetails.append(NEWLINE);
641 maxAlignseq.printAlignment(ps);
643 mappingDetails.append(NEWLINE).append("PDB start/end ");
644 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
646 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
647 mappingDetails.append(NEWLINE).append("SEQ start/end ");
648 mappingDetails.append(
649 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
651 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
652 + (seq.getStart() - 1)));
653 mappingDetails.append(NEWLINE);
654 maxChain.makeExactMapping(maxAlignseq, seq);
655 jalview.datamodel.Mapping sqmpping = maxAlignseq
656 .getMappingFromS1(false);
657 maxChain.transferRESNUMFeatures(seq, null);
659 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
666 Atom tmp = maxChain.atoms.elementAt(index);
667 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
668 && tmp.alignmentMapping != -1)
670 resNum = tmp.resNumber;
671 insCode = tmp.insCode;
672 if (tmp.alignmentMapping >= -1)
674 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
680 } while (index < maxChain.atoms.size());
682 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
683 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
684 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
688 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
690 listeners.removeElement(svl);
691 if (svl instanceof SequenceListener)
693 for (int i = 0; i < listeners.size(); i++)
695 if (listeners.elementAt(i) instanceof StructureListener)
697 ((StructureListener) listeners.elementAt(i))
698 .releaseReferences(svl);
703 if (pdbfiles == null)
709 * Remove mappings to the closed listener's PDB files, but first check if
710 * another listener is still interested
712 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
714 StructureListener sl;
715 for (int i = 0; i < listeners.size(); i++)
717 if (listeners.elementAt(i) instanceof StructureListener)
719 sl = (StructureListener) listeners.elementAt(i);
720 for (String pdbfile : sl.getPdbFile())
722 pdbs.remove(pdbfile);
728 * Rebuild the mappings set, retaining only those which are for 'other' PDB
733 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
734 for (StructureMapping sm : mappings)
736 if (!pdbs.contains(sm.pdbfile))
747 * Propagate mouseover of a single position in a structure
753 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
755 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
756 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
757 mouseOverStructure(atoms);
761 * Propagate mouseover or selection of multiple positions in a structure
765 public void mouseOverStructure(List<AtomSpec> atoms)
767 if (listeners == null)
769 // old or prematurely sent event
772 boolean hasSequenceListener = false;
773 for (int i = 0; i < listeners.size(); i++)
775 if (listeners.elementAt(i) instanceof SequenceListener)
777 hasSequenceListener = true;
780 if (!hasSequenceListener)
785 SearchResults results = new SearchResults();
786 for (AtomSpec atom : atoms)
788 SequenceI lastseq = null;
790 for (StructureMapping sm : mappings)
792 if (sm.pdbfile.equals(atom.getPdbFile())
793 && sm.pdbchain.equals(atom.getChain()))
795 int indexpos = sm.getSeqPos(atom.getPdbResNum());
796 if (lastipos != indexpos && lastseq != sm.sequence)
798 results.addResult(sm.sequence, indexpos, indexpos);
800 lastseq = sm.sequence;
801 // construct highlighted sequence list
802 for (AlignedCodonFrame acf : seqmappings)
804 acf.markMappedRegion(sm.sequence, indexpos, results);
810 for (Object li : listeners)
812 if (li instanceof SequenceListener)
814 ((SequenceListener) li).highlightSequence(results);
820 * highlight regions associated with a position (indexpos) in seq
823 * the sequence that the mouse over occurred on
825 * the absolute position being mouseovered in seq (0 to seq.length())
827 * the sequence position (if -1, seq.findPosition is called to
828 * resolve the residue number)
830 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
833 boolean hasSequenceListeners = handlingVamsasMo
834 || !seqmappings.isEmpty();
835 SearchResults results = null;
838 seqPos = seq.findPosition(indexpos);
840 for (int i = 0; i < listeners.size(); i++)
842 Object listener = listeners.elementAt(i);
843 if (listener == source)
845 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
846 // Temporary fudge with SequenceListener.getVamsasSource()
849 if (listener instanceof StructureListener)
851 highlightStructure((StructureListener) listener, seq, seqPos);
855 if (listener instanceof SequenceListener)
857 final SequenceListener seqListener = (SequenceListener) listener;
858 if (hasSequenceListeners
859 && seqListener.getVamsasSource() != source)
861 if (relaySeqMappings)
865 results = MappingUtils.buildSearchResults(seq, seqPos,
868 if (handlingVamsasMo)
870 results.addResult(seq, seqPos, seqPos);
873 if (!results.isEmpty())
875 seqListener.highlightSequence(results);
880 else if (listener instanceof VamsasListener && !handlingVamsasMo)
882 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
885 else if (listener instanceof SecondaryStructureListener)
887 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
895 * Send suitable messages to a StructureListener to highlight atoms
896 * corresponding to the given sequence position(s)
902 public void highlightStructure(StructureListener sl, SequenceI seq,
905 if (!sl.isListeningFor(seq))
910 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
911 for (StructureMapping sm : mappings)
913 if (sm.sequence == seq
914 || sm.sequence == seq.getDatasetSequence()
915 || (sm.sequence.getDatasetSequence() != null && sm.sequence
916 .getDatasetSequence() == seq.getDatasetSequence()))
918 for (int index : positions)
920 atomNo = sm.getAtomNum(index);
924 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
925 .getPDBResNum(index), atomNo));
930 sl.highlightAtoms(atoms);
934 * true if a mouse over event from an external (ie Vamsas) source is being
937 boolean handlingVamsasMo = false;
942 * as mouseOverSequence but only route event to SequenceListeners
946 * in an alignment sequence
948 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
951 handlingVamsasMo = true;
952 long msg = sequenceI.hashCode() * (1 + position);
956 mouseOverSequence(sequenceI, position, -1, source);
958 handlingVamsasMo = false;
961 public Annotation[] colourSequenceFromStructure(SequenceI seq,
965 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
966 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
968 * Annotation [] annotations = new Annotation[seq.getLength()];
970 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
971 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
972 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
974 * for (int j = 0; j < mappings.length; j++) {
976 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
977 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
978 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
979 * "+mappings[j].pdbfile);
981 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
982 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
984 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
985 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
986 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
987 * mappings[j].pdbfile); }
989 * annotations[index] = new Annotation("X",null,' ',0,col); } return
990 * annotations; } } } }
992 * return annotations;
996 public void structureSelectionChanged()
1000 public void sequenceSelectionChanged()
1004 public void sequenceColoursChanged(Object source)
1006 StructureListener sl;
1007 for (int i = 0; i < listeners.size(); i++)
1009 if (listeners.elementAt(i) instanceof StructureListener)
1011 sl = (StructureListener) listeners.elementAt(i);
1012 sl.updateColours(source);
1017 public StructureMapping[] getMapping(String pdbfile)
1019 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1020 for (StructureMapping sm : mappings)
1022 if (sm.pdbfile.equals(pdbfile))
1027 return tmp.toArray(new StructureMapping[tmp.size()]);
1031 * Returns a readable description of all mappings for the given pdbfile to any
1032 * of the given sequences
1038 public String printMappings(String pdbfile, List<SequenceI> seqs)
1040 if (pdbfile == null || seqs == null || seqs.isEmpty())
1045 StringBuilder sb = new StringBuilder(64);
1046 for (StructureMapping sm : mappings)
1048 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1050 sb.append(sm.mappingDetails);
1052 // separator makes it easier to read multiple mappings
1053 sb.append("=====================");
1059 return sb.toString();
1063 * Remove the given mapping
1067 public void deregisterMapping(AlignedCodonFrame acf)
1071 boolean removed = seqmappings.remove(acf);
1072 if (removed && seqmappings.isEmpty())
1074 System.out.println("All mappings removed");
1080 * Add each of the given codonFrames to the stored set, if not aready present.
1084 public void registerMappings(List<AlignedCodonFrame> mappings)
1086 if (mappings != null)
1088 for (AlignedCodonFrame acf : mappings)
1090 registerMapping(acf);
1096 * Add the given mapping to the stored set, unless already stored.
1098 public void registerMapping(AlignedCodonFrame acf)
1102 if (!seqmappings.contains(acf))
1104 seqmappings.add(acf);
1110 * Resets this object to its initial state by removing all registered
1111 * listeners, codon mappings, PDB file mappings
1113 public void resetAll()
1115 if (mappings != null)
1119 if (seqmappings != null)
1121 seqmappings.clear();
1123 if (sel_listeners != null)
1125 sel_listeners.clear();
1127 if (listeners != null)
1131 if (commandListeners != null)
1133 commandListeners.clear();
1135 if (view_listeners != null)
1137 view_listeners.clear();
1139 if (pdbFileNameId != null)
1141 pdbFileNameId.clear();
1143 if (pdbIdFileName != null)
1145 pdbIdFileName.clear();
1149 public void addSelectionListener(SelectionListener selecter)
1151 if (!sel_listeners.contains(selecter))
1153 sel_listeners.add(selecter);
1157 public void removeSelectionListener(SelectionListener toremove)
1159 if (sel_listeners.contains(toremove))
1161 sel_listeners.remove(toremove);
1165 public synchronized void sendSelection(
1166 jalview.datamodel.SequenceGroup selection,
1167 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1169 for (SelectionListener slis : sel_listeners)
1173 slis.selection(selection, colsel, source);
1178 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1180 public synchronized void sendViewPosition(
1181 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1182 int startSeq, int endSeq)
1185 if (view_listeners != null && view_listeners.size() > 0)
1187 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1189 while (listeners.hasMoreElements())
1191 AlignmentViewPanelListener slis = listeners.nextElement();
1194 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1202 * release all references associated with this manager provider
1204 * @param jalviewLite
1206 public static void release(StructureSelectionManagerProvider jalviewLite)
1208 // synchronized (instances)
1210 if (instances == null)
1214 StructureSelectionManager mnger = (instances.get(jalviewLite));
1217 instances.remove(jalviewLite);
1221 } catch (Throwable x)
1228 public void registerPDBEntry(PDBEntry pdbentry)
1230 if (pdbentry.getFile() != null
1231 && pdbentry.getFile().trim().length() > 0)
1233 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1237 public void addCommandListener(CommandListener cl)
1239 if (!commandListeners.contains(cl))
1241 commandListeners.add(cl);
1245 public boolean hasCommandListener(CommandListener cl)
1247 return this.commandListeners.contains(cl);
1250 public boolean removeCommandListener(CommandListener l)
1252 return commandListeners.remove(l);
1256 * Forward a command to any command listeners (except for the command's
1260 * the command to be broadcast (in its form after being performed)
1262 * if true, the command was being 'undone'
1265 public void commandPerformed(CommandI command, boolean undo,
1266 VamsasSource source)
1268 for (CommandListener listener : commandListeners)
1270 listener.mirrorCommand(command, undo, this, source);
1275 * Returns a new CommandI representing the given command as mapped to the
1276 * given sequences. If no mapping could be made, or the command is not of a
1277 * mappable kind, returns null.
1285 public CommandI mapCommand(CommandI command, boolean undo,
1286 final AlignmentI mapTo, char gapChar)
1288 if (command instanceof EditCommand)
1290 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1291 mapTo, gapChar, seqmappings);
1293 else if (command instanceof OrderCommand)
1295 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1296 mapTo, seqmappings);
1301 public IProgressIndicator getProgressIndicator()
1303 return progressIndicator;
1306 public void setProgressIndicator(IProgressIndicator progressIndicator)
1308 this.progressIndicator = progressIndicator;
1311 public long getProgressSessionId()
1313 return progressSessionId;
1316 public void setProgressSessionId(long progressSessionId)
1318 this.progressSessionId = progressSessionId;
1321 public void setProgressBar(String message)
1323 if (progressIndicator == null)
1327 progressIndicator.setProgressBar(message, progressSessionId);
1330 public List<AlignedCodonFrame> getSequenceMappings()