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>();
505 if (isMapUsingSIFTs && seq.isProtein())
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);
589 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
594 * @param targetChainId
600 * @throws SiftsException
602 private StructureMapping getStructureMapping(SequenceI seq,
603 String pdbFile, String targetChainId, StructureFile pdb,
604 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
605 AlignSeq maxAlignseq) throws SiftsException
607 StructureMapping curChainMapping = siftsClient
608 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
611 PDBChain chain = pdb.findChain(targetChainId);
614 chain.transferResidueAnnotation(curChainMapping, sqmpping);
616 } catch (Exception e)
620 return curChainMapping;
623 private StructureMapping getNWMappings(SequenceI seq,
625 String maxChainId, PDBChain maxChain, StructureFile pdb,
626 AlignSeq maxAlignseq)
628 final StringBuilder mappingDetails = new StringBuilder(128);
629 mappingDetails.append(NEWLINE).append(
630 "Sequence \u27f7 Structure mapping details");
631 mappingDetails.append(NEWLINE);
633 .append("Method: inferred with Needleman & Wunsch alignment");
634 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
635 .append(NEWLINE).append("Sequence = ")
636 .append(maxChain.sequence.getSequenceAsString());
637 mappingDetails.append(NEWLINE).append("No of residues = ")
638 .append(maxChain.residues.size()).append(NEWLINE)
640 PrintStream ps = new PrintStream(System.out)
643 public void print(String x)
645 mappingDetails.append(x);
649 public void println()
651 mappingDetails.append(NEWLINE);
655 maxAlignseq.printAlignment(ps);
657 mappingDetails.append(NEWLINE).append("PDB start/end ");
658 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
660 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
661 mappingDetails.append(NEWLINE).append("SEQ start/end ");
662 mappingDetails.append(
663 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
665 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
666 + (seq.getStart() - 1)));
667 mappingDetails.append(NEWLINE);
668 maxChain.makeExactMapping(maxAlignseq, seq);
669 jalview.datamodel.Mapping sqmpping = maxAlignseq
670 .getMappingFromS1(false);
671 maxChain.transferRESNUMFeatures(seq, null);
673 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
680 Atom tmp = maxChain.atoms.elementAt(index);
681 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
682 && tmp.alignmentMapping != -1)
684 resNum = tmp.resNumber;
685 insCode = tmp.insCode;
686 if (tmp.alignmentMapping >= -1)
688 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
694 } while (index < maxChain.atoms.size());
696 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
697 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
698 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
702 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
704 listeners.removeElement(svl);
705 if (svl instanceof SequenceListener)
707 for (int i = 0; i < listeners.size(); i++)
709 if (listeners.elementAt(i) instanceof StructureListener)
711 ((StructureListener) listeners.elementAt(i))
712 .releaseReferences(svl);
717 if (pdbfiles == null)
723 * Remove mappings to the closed listener's PDB files, but first check if
724 * another listener is still interested
726 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
728 StructureListener sl;
729 for (int i = 0; i < listeners.size(); i++)
731 if (listeners.elementAt(i) instanceof StructureListener)
733 sl = (StructureListener) listeners.elementAt(i);
734 for (String pdbfile : sl.getPdbFile())
736 pdbs.remove(pdbfile);
742 * Rebuild the mappings set, retaining only those which are for 'other' PDB
747 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
748 for (StructureMapping sm : mappings)
750 if (!pdbs.contains(sm.pdbfile))
761 * Propagate mouseover of a single position in a structure
767 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
769 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
770 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
771 mouseOverStructure(atoms);
775 * Propagate mouseover or selection of multiple positions in a structure
779 public void mouseOverStructure(List<AtomSpec> atoms)
781 if (listeners == null)
783 // old or prematurely sent event
786 boolean hasSequenceListener = false;
787 for (int i = 0; i < listeners.size(); i++)
789 if (listeners.elementAt(i) instanceof SequenceListener)
791 hasSequenceListener = true;
794 if (!hasSequenceListener)
799 SearchResults results = new SearchResults();
800 for (AtomSpec atom : atoms)
802 SequenceI lastseq = null;
804 for (StructureMapping sm : mappings)
806 if (sm.pdbfile.equals(atom.getPdbFile())
807 && sm.pdbchain.equals(atom.getChain()))
809 int indexpos = sm.getSeqPos(atom.getPdbResNum());
810 if (lastipos != indexpos && lastseq != sm.sequence)
812 results.addResult(sm.sequence, indexpos, indexpos);
814 lastseq = sm.sequence;
815 // construct highlighted sequence list
816 for (AlignedCodonFrame acf : seqmappings)
818 acf.markMappedRegion(sm.sequence, indexpos, results);
824 for (Object li : listeners)
826 if (li instanceof SequenceListener)
828 ((SequenceListener) li).highlightSequence(results);
834 * highlight regions associated with a position (indexpos) in seq
837 * the sequence that the mouse over occurred on
839 * the absolute position being mouseovered in seq (0 to seq.length())
841 * the sequence position (if -1, seq.findPosition is called to
842 * resolve the residue number)
844 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
847 boolean hasSequenceListeners = handlingVamsasMo
848 || !seqmappings.isEmpty();
849 SearchResults results = null;
852 seqPos = seq.findPosition(indexpos);
854 for (int i = 0; i < listeners.size(); i++)
856 Object listener = listeners.elementAt(i);
857 if (listener == source)
859 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
860 // Temporary fudge with SequenceListener.getVamsasSource()
863 if (listener instanceof StructureListener)
865 highlightStructure((StructureListener) listener, seq, seqPos);
869 if (listener instanceof SequenceListener)
871 final SequenceListener seqListener = (SequenceListener) listener;
872 if (hasSequenceListeners
873 && seqListener.getVamsasSource() != source)
875 if (relaySeqMappings)
879 results = MappingUtils.buildSearchResults(seq, seqPos,
882 if (handlingVamsasMo)
884 results.addResult(seq, seqPos, seqPos);
887 if (!results.isEmpty())
889 seqListener.highlightSequence(results);
894 else if (listener instanceof VamsasListener && !handlingVamsasMo)
896 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
899 else if (listener instanceof SecondaryStructureListener)
901 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
909 * Send suitable messages to a StructureListener to highlight atoms
910 * corresponding to the given sequence position(s)
916 public void highlightStructure(StructureListener sl, SequenceI seq,
919 if (!sl.isListeningFor(seq))
924 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
925 for (StructureMapping sm : mappings)
927 if (sm.sequence == seq
928 || sm.sequence == seq.getDatasetSequence()
929 || (sm.sequence.getDatasetSequence() != null && sm.sequence
930 .getDatasetSequence() == seq.getDatasetSequence()))
932 for (int index : positions)
934 atomNo = sm.getAtomNum(index);
938 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
939 .getPDBResNum(index), atomNo));
944 sl.highlightAtoms(atoms);
948 * true if a mouse over event from an external (ie Vamsas) source is being
951 boolean handlingVamsasMo = false;
956 * as mouseOverSequence but only route event to SequenceListeners
960 * in an alignment sequence
962 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
965 handlingVamsasMo = true;
966 long msg = sequenceI.hashCode() * (1 + position);
970 mouseOverSequence(sequenceI, position, -1, source);
972 handlingVamsasMo = false;
975 public Annotation[] colourSequenceFromStructure(SequenceI seq,
979 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
980 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
982 * Annotation [] annotations = new Annotation[seq.getLength()];
984 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
985 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
986 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
988 * for (int j = 0; j < mappings.length; j++) {
990 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
991 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
992 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
993 * "+mappings[j].pdbfile);
995 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
996 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
998 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
999 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1000 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1001 * mappings[j].pdbfile); }
1003 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1004 * annotations; } } } }
1006 * return annotations;
1010 public void structureSelectionChanged()
1014 public void sequenceSelectionChanged()
1018 public void sequenceColoursChanged(Object source)
1020 StructureListener sl;
1021 for (int i = 0; i < listeners.size(); i++)
1023 if (listeners.elementAt(i) instanceof StructureListener)
1025 sl = (StructureListener) listeners.elementAt(i);
1026 sl.updateColours(source);
1031 public StructureMapping[] getMapping(String pdbfile)
1033 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1034 for (StructureMapping sm : mappings)
1036 if (sm.pdbfile.equals(pdbfile))
1041 return tmp.toArray(new StructureMapping[tmp.size()]);
1045 * Returns a readable description of all mappings for the given pdbfile to any
1046 * of the given sequences
1052 public String printMappings(String pdbfile, List<SequenceI> seqs)
1054 if (pdbfile == null || seqs == null || seqs.isEmpty())
1059 StringBuilder sb = new StringBuilder(64);
1060 for (StructureMapping sm : mappings)
1062 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1064 sb.append(sm.mappingDetails);
1066 // separator makes it easier to read multiple mappings
1067 sb.append("=====================");
1073 return sb.toString();
1077 * Remove the given mapping
1081 public void deregisterMapping(AlignedCodonFrame acf)
1085 boolean removed = seqmappings.remove(acf);
1086 if (removed && seqmappings.isEmpty())
1088 System.out.println("All mappings removed");
1094 * Add each of the given codonFrames to the stored set, if not aready present.
1098 public void registerMappings(List<AlignedCodonFrame> mappings)
1100 if (mappings != null)
1102 for (AlignedCodonFrame acf : mappings)
1104 registerMapping(acf);
1110 * Add the given mapping to the stored set, unless already stored.
1112 public void registerMapping(AlignedCodonFrame acf)
1116 if (!seqmappings.contains(acf))
1118 seqmappings.add(acf);
1124 * Resets this object to its initial state by removing all registered
1125 * listeners, codon mappings, PDB file mappings
1127 public void resetAll()
1129 if (mappings != null)
1133 if (seqmappings != null)
1135 seqmappings.clear();
1137 if (sel_listeners != null)
1139 sel_listeners.clear();
1141 if (listeners != null)
1145 if (commandListeners != null)
1147 commandListeners.clear();
1149 if (view_listeners != null)
1151 view_listeners.clear();
1153 if (pdbFileNameId != null)
1155 pdbFileNameId.clear();
1157 if (pdbIdFileName != null)
1159 pdbIdFileName.clear();
1163 public void addSelectionListener(SelectionListener selecter)
1165 if (!sel_listeners.contains(selecter))
1167 sel_listeners.add(selecter);
1171 public void removeSelectionListener(SelectionListener toremove)
1173 if (sel_listeners.contains(toremove))
1175 sel_listeners.remove(toremove);
1179 public synchronized void sendSelection(
1180 jalview.datamodel.SequenceGroup selection,
1181 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1183 for (SelectionListener slis : sel_listeners)
1187 slis.selection(selection, colsel, source);
1192 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1194 public synchronized void sendViewPosition(
1195 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1196 int startSeq, int endSeq)
1199 if (view_listeners != null && view_listeners.size() > 0)
1201 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1203 while (listeners.hasMoreElements())
1205 AlignmentViewPanelListener slis = listeners.nextElement();
1208 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1216 * release all references associated with this manager provider
1218 * @param jalviewLite
1220 public static void release(StructureSelectionManagerProvider jalviewLite)
1222 // synchronized (instances)
1224 if (instances == null)
1228 StructureSelectionManager mnger = (instances.get(jalviewLite));
1231 instances.remove(jalviewLite);
1235 } catch (Throwable x)
1242 public void registerPDBEntry(PDBEntry pdbentry)
1244 if (pdbentry.getFile() != null
1245 && pdbentry.getFile().trim().length() > 0)
1247 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1251 public void addCommandListener(CommandListener cl)
1253 if (!commandListeners.contains(cl))
1255 commandListeners.add(cl);
1259 public boolean hasCommandListener(CommandListener cl)
1261 return this.commandListeners.contains(cl);
1264 public boolean removeCommandListener(CommandListener l)
1266 return commandListeners.remove(l);
1270 * Forward a command to any command listeners (except for the command's
1274 * the command to be broadcast (in its form after being performed)
1276 * if true, the command was being 'undone'
1279 public void commandPerformed(CommandI command, boolean undo,
1280 VamsasSource source)
1282 for (CommandListener listener : commandListeners)
1284 listener.mirrorCommand(command, undo, this, source);
1289 * Returns a new CommandI representing the given command as mapped to the
1290 * given sequences. If no mapping could be made, or the command is not of a
1291 * mappable kind, returns null.
1299 public CommandI mapCommand(CommandI command, boolean undo,
1300 final AlignmentI mapTo, char gapChar)
1302 if (command instanceof EditCommand)
1304 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1305 mapTo, gapChar, seqmappings);
1307 else if (command instanceof OrderCommand)
1309 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1310 mapTo, seqmappings);
1315 public IProgressIndicator getProgressIndicator()
1317 return progressIndicator;
1320 public void setProgressIndicator(IProgressIndicator progressIndicator)
1322 this.progressIndicator = progressIndicator;
1325 public long getProgressSessionId()
1327 return progressSessionId;
1330 public void setProgressSessionId(long progressSessionId)
1332 this.progressSessionId = progressSessionId;
1335 public void setProgressBar(String message)
1337 if (progressIndicator == null)
1341 progressIndicator.setProgressBar(message, progressSessionId);
1344 public List<AlignedCodonFrame> getSequenceMappings()