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 if (pdbFile != null && isCIFFile(pdbFile))
390 pdb = new jalview.ext.jmol.JmolParser(addTempFacAnnot, parseSecStr,
391 secStructServices, pdbFile, protocol);
395 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
399 if (pdb.getId() != null && pdb.getId().trim().length() > 0
400 && AppletFormatAdapter.FILE.equals(protocol))
402 registerPDBFile(pdb.getId().trim(), pdbFile);
404 } catch (Exception ex)
406 ex.printStackTrace();
414 siftsClient = new SiftsClient(pdb);
416 } catch (SiftsException e)
418 isMapUsingSIFTs = false;
422 String targetChainId;
423 for (int s = 0; s < sequenceArray.length; s++)
425 boolean infChain = true;
426 final SequenceI seq = sequenceArray[s];
427 if (targetChainIds != null && targetChainIds[s] != null)
430 targetChainId = targetChainIds[s];
432 else if (seq.getName().indexOf("|") > -1)
434 targetChainId = seq.getName().substring(
435 seq.getName().lastIndexOf("|") + 1);
436 if (targetChainId.length() > 1)
438 if (targetChainId.trim().length() == 0)
444 // not a valid chain identifier
455 * Attempt pairwise alignment of the sequence with each chain in the PDB,
456 * and remember the highest scoring chain
459 AlignSeq maxAlignseq = null;
460 String maxChainId = " ";
461 PDBChain maxChain = null;
462 boolean first = true;
463 for (PDBChain chain : pdb.getChains())
465 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
468 continue; // don't try to map chains don't match.
470 // TODO: correctly determine sequence type for mixed na/peptide
472 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
473 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
476 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
477 // as.calcScoreMatrix();
478 // as.traceAlignment();
480 if (first || as.maxscore > max
481 || (as.maxscore == max && chain.id.equals(targetChainId)))
487 maxChainId = chain.id;
490 if (maxChain == null)
495 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
497 pdbFile = "INLINE" + pdb.getId();
500 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
503 setProgressBar(null);
504 setProgressBar(MessageManager
505 .getString("status.obtaining_mapping_with_sifts"));
506 jalview.datamodel.Mapping sqmpping = maxAlignseq
507 .getMappingFromS1(false);
508 if (targetChainId != null && !targetChainId.trim().isEmpty())
510 StructureMapping siftsMapping;
513 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
514 pdb, maxChain, sqmpping, maxAlignseq);
515 seqToStrucMapping.add(siftsMapping);
516 maxChain.makeExactMapping(maxAlignseq, seq);
517 maxChain.transferRESNUMFeatures(seq, null);
518 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
519 } catch (SiftsException e)
521 // fall back to NW alignment
522 System.err.println(e.getMessage());
523 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
524 targetChainId, maxChain, pdb, maxAlignseq);
525 seqToStrucMapping.add(nwMapping);
530 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
531 for (PDBChain chain : pdb.getChains())
535 StructureMapping siftsMapping = getStructureMapping(seq,
537 chain.id, pdb, chain, sqmpping, maxAlignseq);
538 foundSiftsMappings.add(siftsMapping);
539 } catch (SiftsException e)
541 System.err.println(e.getMessage());
544 if (!foundSiftsMappings.isEmpty())
546 seqToStrucMapping.addAll(foundSiftsMappings);
547 maxChain.makeExactMapping(maxAlignseq, seq);
548 maxChain.transferRESNUMFeatures(seq, null);
549 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
554 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
555 maxChainId, maxChain, pdb, maxAlignseq);
556 seqToStrucMapping.add(nwMapping);
562 setProgressBar(null);
563 setProgressBar(MessageManager
564 .getString("status.obtaining_mapping_with_nw_alignment"));
565 seqToStrucMapping.add(getNWMappings(seq, pdbFile, maxChainId,
566 maxChain, pdb, maxAlignseq));
569 if (forStructureView)
571 mappings.addAll(seqToStrucMapping);
577 private boolean isCIFFile(String filename)
579 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
581 return "cif".equalsIgnoreCase(fileExt);
584 private StructureMapping getStructureMapping(SequenceI seq,
585 String pdbFile, String targetChainId, StructureFile pdb,
586 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
587 AlignSeq maxAlignseq) throws SiftsException
589 StructureMapping curChainMapping = siftsClient
590 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
593 PDBChain chain = pdb.findChain(targetChainId);
596 chain.transferResidueAnnotation(curChainMapping, sqmpping);
598 } catch (Exception e)
602 return curChainMapping;
605 private StructureMapping getNWMappings(SequenceI seq,
607 String maxChainId, PDBChain maxChain, StructureFile pdb,
608 AlignSeq maxAlignseq)
610 final StringBuilder mappingDetails = new StringBuilder(128);
611 mappingDetails.append(NEWLINE).append(
612 "Sequence \u27f7 Structure mapping details");
613 mappingDetails.append(NEWLINE);
615 .append("Method: inferred with Needleman & Wunsch alignment");
616 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
617 .append(NEWLINE).append("Sequence = ")
618 .append(maxChain.sequence.getSequenceAsString());
619 mappingDetails.append(NEWLINE).append("No of residues = ")
620 .append(maxChain.residues.size()).append(NEWLINE)
622 PrintStream ps = new PrintStream(System.out)
625 public void print(String x)
627 mappingDetails.append(x);
631 public void println()
633 mappingDetails.append(NEWLINE);
637 maxAlignseq.printAlignment(ps);
639 mappingDetails.append(NEWLINE).append("PDB start/end ");
640 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
642 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
643 mappingDetails.append(NEWLINE).append("SEQ start/end ");
644 mappingDetails.append(
645 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
647 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
648 + (seq.getStart() - 1)));
649 mappingDetails.append(NEWLINE);
650 maxChain.makeExactMapping(maxAlignseq, seq);
651 jalview.datamodel.Mapping sqmpping = maxAlignseq
652 .getMappingFromS1(false);
653 maxChain.transferRESNUMFeatures(seq, null);
655 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
662 Atom tmp = maxChain.atoms.elementAt(index);
663 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
664 && tmp.alignmentMapping != -1)
666 resNum = tmp.resNumber;
667 insCode = tmp.insCode;
668 if (tmp.alignmentMapping >= -1)
670 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
676 } while (index < maxChain.atoms.size());
678 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
679 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
680 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
684 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
686 listeners.removeElement(svl);
687 if (svl instanceof SequenceListener)
689 for (int i = 0; i < listeners.size(); i++)
691 if (listeners.elementAt(i) instanceof StructureListener)
693 ((StructureListener) listeners.elementAt(i))
694 .releaseReferences(svl);
699 if (pdbfiles == null)
705 * Remove mappings to the closed listener's PDB files, but first check if
706 * another listener is still interested
708 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
710 StructureListener sl;
711 for (int i = 0; i < listeners.size(); i++)
713 if (listeners.elementAt(i) instanceof StructureListener)
715 sl = (StructureListener) listeners.elementAt(i);
716 for (String pdbfile : sl.getPdbFile())
718 pdbs.remove(pdbfile);
724 * Rebuild the mappings set, retaining only those which are for 'other' PDB
729 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
730 for (StructureMapping sm : mappings)
732 if (!pdbs.contains(sm.pdbfile))
743 * Propagate mouseover of a single position in a structure
749 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
751 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
752 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
753 mouseOverStructure(atoms);
757 * Propagate mouseover or selection of multiple positions in a structure
761 public void mouseOverStructure(List<AtomSpec> atoms)
763 if (listeners == null)
765 // old or prematurely sent event
768 boolean hasSequenceListener = false;
769 for (int i = 0; i < listeners.size(); i++)
771 if (listeners.elementAt(i) instanceof SequenceListener)
773 hasSequenceListener = true;
776 if (!hasSequenceListener)
781 SearchResults results = new SearchResults();
782 for (AtomSpec atom : atoms)
784 SequenceI lastseq = null;
786 for (StructureMapping sm : mappings)
788 if (sm.pdbfile.equals(atom.getPdbFile())
789 && sm.pdbchain.equals(atom.getChain()))
791 int indexpos = sm.getSeqPos(atom.getPdbResNum());
792 if (lastipos != indexpos && lastseq != sm.sequence)
794 results.addResult(sm.sequence, indexpos, indexpos);
796 lastseq = sm.sequence;
797 // construct highlighted sequence list
798 for (AlignedCodonFrame acf : seqmappings)
800 acf.markMappedRegion(sm.sequence, indexpos, results);
806 for (Object li : listeners)
808 if (li instanceof SequenceListener)
810 ((SequenceListener) li).highlightSequence(results);
816 * highlight regions associated with a position (indexpos) in seq
819 * the sequence that the mouse over occurred on
821 * the absolute position being mouseovered in seq (0 to seq.length())
823 * the sequence position (if -1, seq.findPosition is called to
824 * resolve the residue number)
826 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
829 boolean hasSequenceListeners = handlingVamsasMo
830 || !seqmappings.isEmpty();
831 SearchResults results = null;
834 seqPos = seq.findPosition(indexpos);
836 for (int i = 0; i < listeners.size(); i++)
838 Object listener = listeners.elementAt(i);
839 if (listener == source)
841 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
842 // Temporary fudge with SequenceListener.getVamsasSource()
845 if (listener instanceof StructureListener)
847 highlightStructure((StructureListener) listener, seq, seqPos);
851 if (listener instanceof SequenceListener)
853 final SequenceListener seqListener = (SequenceListener) listener;
854 if (hasSequenceListeners
855 && seqListener.getVamsasSource() != source)
857 if (relaySeqMappings)
861 results = MappingUtils.buildSearchResults(seq, seqPos,
864 if (handlingVamsasMo)
866 results.addResult(seq, seqPos, seqPos);
869 if (!results.isEmpty())
871 seqListener.highlightSequence(results);
876 else if (listener instanceof VamsasListener && !handlingVamsasMo)
878 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
881 else if (listener instanceof SecondaryStructureListener)
883 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
891 * Send suitable messages to a StructureListener to highlight atoms
892 * corresponding to the given sequence position(s)
898 public void highlightStructure(StructureListener sl, SequenceI seq,
901 if (!sl.isListeningFor(seq))
906 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
907 for (StructureMapping sm : mappings)
909 if (sm.sequence == seq
910 || sm.sequence == seq.getDatasetSequence()
911 || (sm.sequence.getDatasetSequence() != null && sm.sequence
912 .getDatasetSequence() == seq.getDatasetSequence()))
914 for (int index : positions)
916 atomNo = sm.getAtomNum(index);
920 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
921 .getPDBResNum(index), atomNo));
926 sl.highlightAtoms(atoms);
930 * true if a mouse over event from an external (ie Vamsas) source is being
933 boolean handlingVamsasMo = false;
938 * as mouseOverSequence but only route event to SequenceListeners
942 * in an alignment sequence
944 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
947 handlingVamsasMo = true;
948 long msg = sequenceI.hashCode() * (1 + position);
952 mouseOverSequence(sequenceI, position, -1, source);
954 handlingVamsasMo = false;
957 public Annotation[] colourSequenceFromStructure(SequenceI seq,
961 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
962 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
964 * Annotation [] annotations = new Annotation[seq.getLength()];
966 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
967 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
968 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
970 * for (int j = 0; j < mappings.length; j++) {
972 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
973 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
974 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
975 * "+mappings[j].pdbfile);
977 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
978 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
980 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
981 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
982 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
983 * mappings[j].pdbfile); }
985 * annotations[index] = new Annotation("X",null,' ',0,col); } return
986 * annotations; } } } }
988 * return annotations;
992 public void structureSelectionChanged()
996 public void sequenceSelectionChanged()
1000 public void sequenceColoursChanged(Object source)
1002 StructureListener sl;
1003 for (int i = 0; i < listeners.size(); i++)
1005 if (listeners.elementAt(i) instanceof StructureListener)
1007 sl = (StructureListener) listeners.elementAt(i);
1008 sl.updateColours(source);
1013 public StructureMapping[] getMapping(String pdbfile)
1015 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1016 for (StructureMapping sm : mappings)
1018 if (sm.pdbfile.equals(pdbfile))
1023 return tmp.toArray(new StructureMapping[tmp.size()]);
1027 * Returns a readable description of all mappings for the given pdbfile to any
1028 * of the given sequences
1034 public String printMappings(String pdbfile, List<SequenceI> seqs)
1036 if (pdbfile == null || seqs == null || seqs.isEmpty())
1041 StringBuilder sb = new StringBuilder(64);
1042 for (StructureMapping sm : mappings)
1044 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1046 sb.append(sm.mappingDetails);
1048 // separator makes it easier to read multiple mappings
1049 sb.append("=====================");
1055 return sb.toString();
1059 * Remove the given mapping
1063 public void deregisterMapping(AlignedCodonFrame acf)
1067 boolean removed = seqmappings.remove(acf);
1068 if (removed && seqmappings.isEmpty())
1070 System.out.println("All mappings removed");
1076 * Add each of the given codonFrames to the stored set, if not aready present.
1080 public void registerMappings(List<AlignedCodonFrame> mappings)
1082 if (mappings != null)
1084 for (AlignedCodonFrame acf : mappings)
1086 registerMapping(acf);
1092 * Add the given mapping to the stored set, unless already stored.
1094 public void registerMapping(AlignedCodonFrame acf)
1098 if (!seqmappings.contains(acf))
1100 seqmappings.add(acf);
1106 * Resets this object to its initial state by removing all registered
1107 * listeners, codon mappings, PDB file mappings
1109 public void resetAll()
1111 if (mappings != null)
1115 if (seqmappings != null)
1117 seqmappings.clear();
1119 if (sel_listeners != null)
1121 sel_listeners.clear();
1123 if (listeners != null)
1127 if (commandListeners != null)
1129 commandListeners.clear();
1131 if (view_listeners != null)
1133 view_listeners.clear();
1135 if (pdbFileNameId != null)
1137 pdbFileNameId.clear();
1139 if (pdbIdFileName != null)
1141 pdbIdFileName.clear();
1145 public void addSelectionListener(SelectionListener selecter)
1147 if (!sel_listeners.contains(selecter))
1149 sel_listeners.add(selecter);
1153 public void removeSelectionListener(SelectionListener toremove)
1155 if (sel_listeners.contains(toremove))
1157 sel_listeners.remove(toremove);
1161 public synchronized void sendSelection(
1162 jalview.datamodel.SequenceGroup selection,
1163 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1165 for (SelectionListener slis : sel_listeners)
1169 slis.selection(selection, colsel, source);
1174 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1176 public synchronized void sendViewPosition(
1177 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1178 int startSeq, int endSeq)
1181 if (view_listeners != null && view_listeners.size() > 0)
1183 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1185 while (listeners.hasMoreElements())
1187 AlignmentViewPanelListener slis = listeners.nextElement();
1190 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1198 * release all references associated with this manager provider
1200 * @param jalviewLite
1202 public static void release(StructureSelectionManagerProvider jalviewLite)
1204 // synchronized (instances)
1206 if (instances == null)
1210 StructureSelectionManager mnger = (instances.get(jalviewLite));
1213 instances.remove(jalviewLite);
1217 } catch (Throwable x)
1224 public void registerPDBEntry(PDBEntry pdbentry)
1226 if (pdbentry.getFile() != null
1227 && pdbentry.getFile().trim().length() > 0)
1229 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1233 public void addCommandListener(CommandListener cl)
1235 if (!commandListeners.contains(cl))
1237 commandListeners.add(cl);
1241 public boolean hasCommandListener(CommandListener cl)
1243 return this.commandListeners.contains(cl);
1246 public boolean removeCommandListener(CommandListener l)
1248 return commandListeners.remove(l);
1252 * Forward a command to any command listeners (except for the command's
1256 * the command to be broadcast (in its form after being performed)
1258 * if true, the command was being 'undone'
1261 public void commandPerformed(CommandI command, boolean undo,
1262 VamsasSource source)
1264 for (CommandListener listener : commandListeners)
1266 listener.mirrorCommand(command, undo, this, source);
1271 * Returns a new CommandI representing the given command as mapped to the
1272 * given sequences. If no mapping could be made, or the command is not of a
1273 * mappable kind, returns null.
1281 public CommandI mapCommand(CommandI command, boolean undo,
1282 final AlignmentI mapTo, char gapChar)
1284 if (command instanceof EditCommand)
1286 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1287 mapTo, gapChar, seqmappings);
1289 else if (command instanceof OrderCommand)
1291 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1292 mapTo, seqmappings);
1297 public IProgressIndicator getProgressIndicator()
1299 return progressIndicator;
1302 public void setProgressIndicator(IProgressIndicator progressIndicator)
1304 this.progressIndicator = progressIndicator;
1307 public long getProgressSessionId()
1309 return progressSessionId;
1312 public void setProgressSessionId(long progressSessionId)
1314 this.progressSessionId = progressSessionId;
1317 public void setProgressBar(String message)
1319 if (progressIndicator == null)
1323 progressIndicator.setProgressBar(message, progressSessionId);
1326 public List<AlignedCodonFrame> getSequenceMappings()