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.HiddenColumns;
33 import jalview.datamodel.PDBEntry;
34 import jalview.datamodel.SearchResults;
35 import jalview.datamodel.SearchResultsI;
36 import jalview.datamodel.SequenceI;
37 import jalview.ext.jmol.JmolParser;
38 import jalview.gui.IProgressIndicator;
39 import jalview.io.AppletFormatAdapter;
40 import jalview.io.DataSourceType;
41 import jalview.io.StructureFile;
42 import jalview.util.MappingUtils;
43 import jalview.util.MessageManager;
44 import jalview.ws.sifts.SiftsClient;
45 import jalview.ws.sifts.SiftsException;
46 import jalview.ws.sifts.SiftsSettings;
48 import java.io.PrintStream;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Collections;
52 import java.util.Enumeration;
53 import java.util.HashMap;
54 import java.util.IdentityHashMap;
55 import java.util.List;
57 import java.util.Vector;
60 import MCview.PDBChain;
61 import MCview.PDBfile;
63 public class StructureSelectionManager
65 public final static String NEWLINE = System.lineSeparator();
67 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
69 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
71 private boolean processSecondaryStructure = false;
73 private boolean secStructServices = false;
75 private boolean addTempFacAnnot = false;
77 private IProgressIndicator progressIndicator;
79 private SiftsClient siftsClient = null;
81 private long progressSessionId;
84 * Set of any registered mappings between (dataset) sequences.
86 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
88 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
90 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
93 * @return true if will try to use external services for processing secondary
96 public boolean isSecStructServices()
98 return secStructServices;
102 * control use of external services for processing secondary structure
104 * @param secStructServices
106 public void setSecStructServices(boolean secStructServices)
108 this.secStructServices = secStructServices;
112 * flag controlling addition of any kind of structural annotation
114 * @return true if temperature factor annotation will be added
116 public boolean isAddTempFacAnnot()
118 return addTempFacAnnot;
122 * set flag controlling addition of structural annotation
124 * @param addTempFacAnnot
126 public void setAddTempFacAnnot(boolean addTempFacAnnot)
128 this.addTempFacAnnot = addTempFacAnnot;
133 * @return if true, the structure manager will attempt to add secondary
134 * structure lines for unannotated sequences
137 public boolean isProcessSecondaryStructure()
139 return processSecondaryStructure;
143 * Control whether structure manager will try to annotate mapped sequences
144 * with secondary structure from PDB data.
148 public void setProcessSecondaryStructure(boolean enable)
150 processSecondaryStructure = enable;
154 * debug function - write all mappings to stdout
156 public void reportMapping()
158 if (mappings.isEmpty())
160 System.err.println("reportMapping: No PDB/Sequence mappings.");
164 System.err.println("reportMapping: There are " + mappings.size()
167 for (StructureMapping sm : mappings)
169 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
175 * map between the PDB IDs (or structure identifiers) used by Jalview and the
176 * absolute filenames for PDB data that corresponds to it
178 Map<String, String> pdbIdFileName = new HashMap<String, String>();
180 Map<String, String> pdbFileNameId = new HashMap<String, String>();
182 public void registerPDBFile(String idForFile, String absoluteFile)
184 pdbIdFileName.put(idForFile, absoluteFile);
185 pdbFileNameId.put(absoluteFile, idForFile);
188 public String findIdForPDBFile(String idOrFile)
190 String id = pdbFileNameId.get(idOrFile);
194 public String findFileForPDBId(String idOrFile)
196 String id = pdbIdFileName.get(idOrFile);
200 public boolean isPDBFileRegistered(String idOrFile)
202 return pdbFileNameId.containsKey(idOrFile)
203 || pdbIdFileName.containsKey(idOrFile);
206 private static StructureSelectionManager nullProvider = null;
208 public static StructureSelectionManager getStructureSelectionManager(
209 StructureSelectionManagerProvider context)
213 if (nullProvider == null)
215 if (instances != null)
219 .getString("error.implementation_error_structure_selection_manager_null"),
220 new NullPointerException(MessageManager
221 .getString("exception.ssm_context_is_null")));
225 nullProvider = new StructureSelectionManager();
230 if (instances == null)
232 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
234 StructureSelectionManager instance = instances.get(context);
235 if (instance == null)
237 if (nullProvider != null)
239 instance = nullProvider;
243 instance = new StructureSelectionManager();
245 instances.put(context, instance);
251 * flag controlling whether SeqMappings are relayed from received sequence
252 * mouse over events to other sequences
254 boolean relaySeqMappings = true;
257 * Enable or disable relay of seqMapping events to other sequences. You might
258 * want to do this if there are many sequence mappings and the host computer
263 public void setRelaySeqMappings(boolean relay)
265 relaySeqMappings = relay;
269 * get the state of the relay seqMappings flag.
271 * @return true if sequence mouse overs are being relayed to other mapped
274 public boolean isRelaySeqMappingsEnabled()
276 return relaySeqMappings;
279 Vector listeners = new Vector();
282 * register a listener for alignment sequence mouseover events
286 public void addStructureViewerListener(Object svl)
288 if (!listeners.contains(svl))
290 listeners.addElement(svl);
295 * Returns the file name for a mapped PDB id (or null if not mapped).
300 public String alreadyMappedToFile(String pdbid)
302 for (StructureMapping sm : mappings)
304 if (sm.getPdbId().equals(pdbid))
313 * Import structure data and register a structure mapping for broadcasting
314 * colouring, mouseovers and selection events (convenience wrapper).
317 * - one or more sequences to be mapped to pdbFile
318 * @param targetChains
319 * - optional chain specification for mapping each sequence to pdb
320 * (may be nill, individual elements may be nill)
322 * - structure data resource
324 * - how to resolve data from resource
325 * @return null or the structure data parsed as a pdb file
327 synchronized public StructureFile setMapping(SequenceI[] sequence,
328 String[] targetChains, String pdbFile, DataSourceType protocol)
330 return setMapping(true, sequence, targetChains, pdbFile, protocol);
334 * create sequence structure mappings between each sequence and the given
335 * pdbFile (retrieved via the given protocol).
337 * @param forStructureView
338 * when true, record the mapping for use in mouseOvers
340 * @param sequenceArray
341 * - one or more sequences to be mapped to pdbFile
342 * @param targetChainIds
343 * - optional chain specification for mapping each sequence to pdb
344 * (may be nill, individual elements may be nill)
346 * - structure data resource
348 * - how to resolve data from resource
349 * @return null or the structure data parsed as a pdb file
351 synchronized public StructureFile setMapping(boolean forStructureView,
352 SequenceI[] sequenceArray, String[] targetChainIds,
353 String pdbFile, DataSourceType sourceType)
356 * There will be better ways of doing this in the future, for now we'll use
357 * the tried and tested MCview pdb mapping
359 boolean parseSecStr = processSecondaryStructure;
360 if (isPDBFileRegistered(pdbFile))
362 for (SequenceI sq : sequenceArray)
365 while (ds.getDatasetSequence() != null)
367 ds = ds.getDatasetSequence();
370 if (ds.getAnnotation() != null)
372 for (AlignmentAnnotation ala : ds.getAnnotation())
374 // false if any annotation present from this structure
375 // JBPNote this fails for jmol/chimera view because the *file* is
376 // passed, not the structure data ID -
377 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
385 StructureFile pdb = null;
386 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
389 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
390 pdb = new JmolParser(pdbFile, sourceType);
392 if (pdb.getId() != null && pdb.getId().trim().length() > 0
393 && DataSourceType.FILE == sourceType)
395 registerPDBFile(pdb.getId().trim(), pdbFile);
397 // if PDBId is unavailable then skip SIFTS mapping execution path
398 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
400 } catch (Exception ex)
402 ex.printStackTrace();
410 siftsClient = new SiftsClient(pdb);
412 } catch (SiftsException e)
414 isMapUsingSIFTs = false;
418 String targetChainId;
419 for (int s = 0; s < sequenceArray.length; s++)
421 boolean infChain = true;
422 final SequenceI seq = sequenceArray[s];
424 while (ds.getDatasetSequence() != null)
426 ds = ds.getDatasetSequence();
429 if (targetChainIds != null && targetChainIds[s] != null)
432 targetChainId = targetChainIds[s];
434 else if (seq.getName().indexOf("|") > -1)
436 targetChainId = seq.getName().substring(
437 seq.getName().lastIndexOf("|") + 1);
438 if (targetChainId.length() > 1)
440 if (targetChainId.trim().length() == 0)
446 // not a valid chain identifier
457 * Attempt pairwise alignment of the sequence with each chain in the PDB,
458 * and remember the highest scoring chain
461 AlignSeq maxAlignseq = null;
462 String maxChainId = " ";
463 PDBChain maxChain = null;
464 boolean first = true;
465 for (PDBChain chain : pdb.getChains())
467 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
470 continue; // don't try to map chains don't match.
472 // TODO: correctly determine sequence type for mixed na/peptide
474 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
475 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
478 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
479 // as.calcScoreMatrix();
480 // as.traceAlignment();
482 if (first || as.maxscore > max
483 || (as.maxscore == max && chain.id.equals(targetChainId)))
489 maxChainId = chain.id;
492 if (maxChain == null)
497 if (sourceType == DataSourceType.PASTE)
499 pdbFile = "INLINE" + pdb.getId();
502 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
503 if (isMapUsingSIFTs && seq.isProtein())
505 setProgressBar(null);
506 setProgressBar(MessageManager
507 .getString("status.obtaining_mapping_with_sifts"));
508 jalview.datamodel.Mapping sqmpping = maxAlignseq
509 .getMappingFromS1(false);
510 if (targetChainId != null && !targetChainId.trim().isEmpty())
512 StructureMapping siftsMapping;
515 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
516 pdb, maxChain, sqmpping, maxAlignseq);
517 seqToStrucMapping.add(siftsMapping);
518 maxChain.makeExactMapping(maxAlignseq, seq);
519 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
521 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
522 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
524 } catch (SiftsException e)
526 // fall back to NW alignment
527 System.err.println(e.getMessage());
528 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
529 targetChainId, maxChain, pdb, maxAlignseq);
530 seqToStrucMapping.add(nwMapping);
531 maxChain.makeExactMapping(maxAlignseq, seq);
532 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
534 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
535 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
540 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
541 for (PDBChain chain : pdb.getChains())
545 StructureMapping siftsMapping = getStructureMapping(seq,
546 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
547 foundSiftsMappings.add(siftsMapping);
548 } catch (SiftsException e)
550 System.err.println(e.getMessage());
553 if (!foundSiftsMappings.isEmpty())
555 seqToStrucMapping.addAll(foundSiftsMappings);
556 maxChain.makeExactMapping(maxAlignseq, seq);
557 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
559 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
561 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
565 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
566 maxChainId, maxChain, pdb, maxAlignseq);
567 seqToStrucMapping.add(nwMapping);
568 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
570 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
571 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
577 setProgressBar(null);
578 setProgressBar(MessageManager
579 .getString("status.obtaining_mapping_with_nw_alignment"));
580 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
581 maxChainId, maxChain, pdb, maxAlignseq);
582 seqToStrucMapping.add(nwMapping);
583 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
587 if (forStructureView)
589 mappings.addAll(seqToStrucMapping);
595 public void addStructureMapping(StructureMapping sm)
601 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
606 * @param targetChainId
612 * @throws SiftsException
614 private StructureMapping getStructureMapping(SequenceI seq,
615 String pdbFile, String targetChainId, StructureFile pdb,
616 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
617 AlignSeq maxAlignseq) throws SiftsException
619 StructureMapping curChainMapping = siftsClient
620 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
623 PDBChain chain = pdb.findChain(targetChainId);
626 chain.transferResidueAnnotation(curChainMapping, sqmpping);
628 } catch (Exception e)
632 return curChainMapping;
635 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
636 String maxChainId, PDBChain maxChain, StructureFile pdb,
637 AlignSeq maxAlignseq)
639 final StringBuilder mappingDetails = new StringBuilder(128);
640 mappingDetails.append(NEWLINE).append(
641 "Sequence \u27f7 Structure mapping details");
642 mappingDetails.append(NEWLINE);
644 .append("Method: inferred with Needleman & Wunsch alignment");
645 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
646 .append(NEWLINE).append("Sequence = ")
647 .append(maxChain.sequence.getSequenceAsString());
648 mappingDetails.append(NEWLINE).append("No of residues = ")
649 .append(maxChain.residues.size()).append(NEWLINE)
651 PrintStream ps = new PrintStream(System.out)
654 public void print(String x)
656 mappingDetails.append(x);
660 public void println()
662 mappingDetails.append(NEWLINE);
666 maxAlignseq.printAlignment(ps);
668 mappingDetails.append(NEWLINE).append("PDB start/end ");
669 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
671 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
672 mappingDetails.append(NEWLINE).append("SEQ start/end ");
673 mappingDetails.append(
674 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
676 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
677 + (seq.getStart() - 1)));
678 mappingDetails.append(NEWLINE);
679 maxChain.makeExactMapping(maxAlignseq, seq);
680 jalview.datamodel.Mapping sqmpping = maxAlignseq
681 .getMappingFromS1(false);
682 maxChain.transferRESNUMFeatures(seq, null);
684 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
691 Atom tmp = maxChain.atoms.elementAt(index);
692 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
693 && tmp.alignmentMapping != -1)
695 resNum = tmp.resNumber;
696 insCode = tmp.insCode;
697 if (tmp.alignmentMapping >= -1)
699 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
705 } while (index < maxChain.atoms.size());
707 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
708 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
709 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
713 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
715 listeners.removeElement(svl);
716 if (svl instanceof SequenceListener)
718 for (int i = 0; i < listeners.size(); i++)
720 if (listeners.elementAt(i) instanceof StructureListener)
722 ((StructureListener) listeners.elementAt(i))
723 .releaseReferences(svl);
728 if (pdbfiles == null)
734 * Remove mappings to the closed listener's PDB files, but first check if
735 * another listener is still interested
737 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
739 StructureListener sl;
740 for (int i = 0; i < listeners.size(); i++)
742 if (listeners.elementAt(i) instanceof StructureListener)
744 sl = (StructureListener) listeners.elementAt(i);
745 for (String pdbfile : sl.getStructureFiles())
747 pdbs.remove(pdbfile);
753 * Rebuild the mappings set, retaining only those which are for 'other' PDB
758 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
759 for (StructureMapping sm : mappings)
761 if (!pdbs.contains(sm.pdbfile))
772 * Propagate mouseover of a single position in a structure
778 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
780 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
781 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
782 mouseOverStructure(atoms);
786 * Propagate mouseover or selection of multiple positions in a structure
790 public void mouseOverStructure(List<AtomSpec> atoms)
792 if (listeners == null)
794 // old or prematurely sent event
797 boolean hasSequenceListener = false;
798 for (int i = 0; i < listeners.size(); i++)
800 if (listeners.elementAt(i) instanceof SequenceListener)
802 hasSequenceListener = true;
805 if (!hasSequenceListener)
810 SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms);
811 for (Object li : listeners)
813 if (li instanceof SequenceListener)
815 ((SequenceListener) li).highlightSequence(results);
821 * Constructs a SearchResults object holding regions (if any) in the Jalview
822 * alignment which have a mapping to the structure viewer positions in the
828 public SearchResultsI findAlignmentPositionsForStructurePositions(
829 List<AtomSpec> atoms)
831 SearchResultsI results = new SearchResults();
832 for (AtomSpec atom : atoms)
834 SequenceI lastseq = null;
836 for (StructureMapping sm : mappings)
838 if (sm.pdbfile.equals(atom.getPdbFile())
839 && sm.pdbchain.equals(atom.getChain()))
841 int indexpos = sm.getSeqPos(atom.getPdbResNum());
842 if (lastipos != indexpos && lastseq != sm.sequence)
844 results.addResult(sm.sequence, indexpos, indexpos);
846 lastseq = sm.sequence;
847 // construct highlighted sequence list
848 for (AlignedCodonFrame acf : seqmappings)
850 acf.markMappedRegion(sm.sequence, indexpos, results);
860 * highlight regions associated with a position (indexpos) in seq
863 * the sequence that the mouse over occurred on
865 * the absolute position being mouseovered in seq (0 to seq.length())
867 * the sequence position (if -1, seq.findPosition is called to
868 * resolve the residue number)
870 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
873 boolean hasSequenceListeners = handlingVamsasMo
874 || !seqmappings.isEmpty();
875 SearchResultsI results = null;
878 seqPos = seq.findPosition(indexpos);
880 for (int i = 0; i < listeners.size(); i++)
882 Object listener = listeners.elementAt(i);
883 if (listener == source)
885 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
886 // Temporary fudge with SequenceListener.getVamsasSource()
889 if (listener instanceof StructureListener)
891 highlightStructure((StructureListener) listener, seq, seqPos);
895 if (listener instanceof SequenceListener)
897 final SequenceListener seqListener = (SequenceListener) listener;
898 if (hasSequenceListeners
899 && seqListener.getVamsasSource() != source)
901 if (relaySeqMappings)
905 results = MappingUtils.buildSearchResults(seq, seqPos,
908 if (handlingVamsasMo)
910 results.addResult(seq, seqPos, seqPos);
913 if (!results.isEmpty())
915 seqListener.highlightSequence(results);
920 else if (listener instanceof VamsasListener && !handlingVamsasMo)
922 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
925 else if (listener instanceof SecondaryStructureListener)
927 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
935 * Send suitable messages to a StructureListener to highlight atoms
936 * corresponding to the given sequence position(s)
942 public void highlightStructure(StructureListener sl, SequenceI seq,
945 if (!sl.isListeningFor(seq))
950 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
951 for (StructureMapping sm : mappings)
953 if (sm.sequence == seq
954 || sm.sequence == seq.getDatasetSequence()
955 || (sm.sequence.getDatasetSequence() != null && sm.sequence
956 .getDatasetSequence() == seq.getDatasetSequence()))
958 for (int index : positions)
960 atomNo = sm.getAtomNum(index);
964 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
965 .getPDBResNum(index), atomNo));
970 sl.highlightAtoms(atoms);
974 * true if a mouse over event from an external (ie Vamsas) source is being
977 boolean handlingVamsasMo = false;
982 * as mouseOverSequence but only route event to SequenceListeners
986 * in an alignment sequence
988 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
991 handlingVamsasMo = true;
992 long msg = sequenceI.hashCode() * (1 + position);
996 mouseOverSequence(sequenceI, position, -1, source);
998 handlingVamsasMo = false;
1001 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1005 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1006 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1008 * Annotation [] annotations = new Annotation[seq.getLength()];
1010 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1011 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1012 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1014 * for (int j = 0; j < mappings.length; j++) {
1016 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1017 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1018 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1019 * "+mappings[j].pdbfile);
1021 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1022 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1024 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1025 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1026 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1027 * mappings[j].pdbfile); }
1029 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1030 * annotations; } } } }
1032 * return annotations;
1036 public void structureSelectionChanged()
1040 public void sequenceSelectionChanged()
1044 public void sequenceColoursChanged(Object source)
1046 StructureListener sl;
1047 for (int i = 0; i < listeners.size(); i++)
1049 if (listeners.elementAt(i) instanceof StructureListener)
1051 sl = (StructureListener) listeners.elementAt(i);
1052 sl.updateColours(source);
1057 public StructureMapping[] getMapping(String pdbfile)
1059 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1060 for (StructureMapping sm : mappings)
1062 if (sm.pdbfile.equals(pdbfile))
1067 return tmp.toArray(new StructureMapping[tmp.size()]);
1071 * Returns a readable description of all mappings for the given pdbfile to any
1072 * of the given sequences
1078 public String printMappings(String pdbfile, List<SequenceI> seqs)
1080 if (pdbfile == null || seqs == null || seqs.isEmpty())
1085 StringBuilder sb = new StringBuilder(64);
1086 for (StructureMapping sm : mappings)
1088 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1090 sb.append(sm.mappingDetails);
1092 // separator makes it easier to read multiple mappings
1093 sb.append("=====================");
1099 return sb.toString();
1103 * Remove the given mapping
1107 public void deregisterMapping(AlignedCodonFrame acf)
1111 boolean removed = seqmappings.remove(acf);
1112 if (removed && seqmappings.isEmpty())
1114 System.out.println("All mappings removed");
1120 * Add each of the given codonFrames to the stored set, if not aready present.
1124 public void registerMappings(List<AlignedCodonFrame> mappings)
1126 if (mappings != null)
1128 for (AlignedCodonFrame acf : mappings)
1130 registerMapping(acf);
1136 * Add the given mapping to the stored set, unless already stored.
1138 public void registerMapping(AlignedCodonFrame acf)
1142 if (!seqmappings.contains(acf))
1144 seqmappings.add(acf);
1150 * Resets this object to its initial state by removing all registered
1151 * listeners, codon mappings, PDB file mappings
1153 public void resetAll()
1155 if (mappings != null)
1159 if (seqmappings != null)
1161 seqmappings.clear();
1163 if (sel_listeners != null)
1165 sel_listeners.clear();
1167 if (listeners != null)
1171 if (commandListeners != null)
1173 commandListeners.clear();
1175 if (view_listeners != null)
1177 view_listeners.clear();
1179 if (pdbFileNameId != null)
1181 pdbFileNameId.clear();
1183 if (pdbIdFileName != null)
1185 pdbIdFileName.clear();
1189 public void addSelectionListener(SelectionListener selecter)
1191 if (!sel_listeners.contains(selecter))
1193 sel_listeners.add(selecter);
1197 public void removeSelectionListener(SelectionListener toremove)
1199 if (sel_listeners.contains(toremove))
1201 sel_listeners.remove(toremove);
1205 public synchronized void sendSelection(
1206 jalview.datamodel.SequenceGroup selection,
1207 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1208 SelectionSource source)
1210 for (SelectionListener slis : sel_listeners)
1214 slis.selection(selection, colsel, hidden, source);
1219 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1221 public synchronized void sendViewPosition(
1222 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1223 int startSeq, int endSeq)
1226 if (view_listeners != null && view_listeners.size() > 0)
1228 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1230 while (listeners.hasMoreElements())
1232 AlignmentViewPanelListener slis = listeners.nextElement();
1235 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1243 * release all references associated with this manager provider
1245 * @param jalviewLite
1247 public static void release(StructureSelectionManagerProvider jalviewLite)
1249 // synchronized (instances)
1251 if (instances == null)
1255 StructureSelectionManager mnger = (instances.get(jalviewLite));
1258 instances.remove(jalviewLite);
1262 } catch (Throwable x)
1269 public void registerPDBEntry(PDBEntry pdbentry)
1271 if (pdbentry.getFile() != null
1272 && pdbentry.getFile().trim().length() > 0)
1274 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1278 public void addCommandListener(CommandListener cl)
1280 if (!commandListeners.contains(cl))
1282 commandListeners.add(cl);
1286 public boolean hasCommandListener(CommandListener cl)
1288 return this.commandListeners.contains(cl);
1291 public boolean removeCommandListener(CommandListener l)
1293 return commandListeners.remove(l);
1297 * Forward a command to any command listeners (except for the command's
1301 * the command to be broadcast (in its form after being performed)
1303 * if true, the command was being 'undone'
1306 public void commandPerformed(CommandI command, boolean undo,
1307 VamsasSource source)
1309 for (CommandListener listener : commandListeners)
1311 listener.mirrorCommand(command, undo, this, source);
1316 * Returns a new CommandI representing the given command as mapped to the
1317 * given sequences. If no mapping could be made, or the command is not of a
1318 * mappable kind, returns null.
1326 public CommandI mapCommand(CommandI command, boolean undo,
1327 final AlignmentI mapTo, char gapChar)
1329 if (command instanceof EditCommand)
1331 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1332 mapTo, gapChar, seqmappings);
1334 else if (command instanceof OrderCommand)
1336 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1337 mapTo, seqmappings);
1342 public IProgressIndicator getProgressIndicator()
1344 return progressIndicator;
1347 public void setProgressIndicator(IProgressIndicator progressIndicator)
1349 this.progressIndicator = progressIndicator;
1352 public long getProgressSessionId()
1354 return progressSessionId;
1357 public void setProgressSessionId(long progressSessionId)
1359 this.progressSessionId = progressSessionId;
1362 public void setProgressBar(String message)
1364 if (progressIndicator == null)
1368 progressIndicator.setProgressBar(message, progressSessionId);
1371 public List<AlignedCodonFrame> getSequenceMappings()