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.SearchResultsI;
35 import jalview.datamodel.SequenceI;
36 import jalview.ext.jmol.JmolParser;
37 import jalview.gui.IProgressIndicator;
38 import jalview.io.DataSourceType;
39 import jalview.io.StructureFile;
40 import jalview.util.MappingUtils;
41 import jalview.util.MessageManager;
42 import jalview.ws.phyre2.Phyre2Client;
43 import jalview.ws.sifts.SiftsClient;
44 import jalview.ws.sifts.SiftsException;
45 import jalview.ws.sifts.SiftsSettings;
47 import java.io.PrintStream;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collections;
51 import java.util.Enumeration;
52 import java.util.HashMap;
53 import java.util.Hashtable;
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;
85 * Set of any registered mappings between (dataset) sequences.
87 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
89 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
91 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
93 private Map<String, String> phyre2ModelTemplates = new Hashtable<String, String>();
96 * @return true if will try to use external services for processing secondary
99 public boolean isSecStructServices()
101 return secStructServices;
105 * control use of external services for processing secondary structure
107 * @param secStructServices
109 public void setSecStructServices(boolean secStructServices)
111 this.secStructServices = secStructServices;
115 * flag controlling addition of any kind of structural annotation
117 * @return true if temperature factor annotation will be added
119 public boolean isAddTempFacAnnot()
121 return addTempFacAnnot;
125 * set flag controlling addition of structural annotation
127 * @param addTempFacAnnot
129 public void setAddTempFacAnnot(boolean addTempFacAnnot)
131 this.addTempFacAnnot = addTempFacAnnot;
136 * @return if true, the structure manager will attempt to add secondary
137 * structure lines for unannotated sequences
140 public boolean isProcessSecondaryStructure()
142 return processSecondaryStructure;
146 * Control whether structure manager will try to annotate mapped sequences
147 * with secondary structure from PDB data.
151 public void setProcessSecondaryStructure(boolean enable)
153 processSecondaryStructure = enable;
157 * debug function - write all mappings to stdout
159 public void reportMapping()
161 if (mappings.isEmpty())
163 System.err.println("reportMapping: No PDB/Sequence mappings.");
167 System.err.println("reportMapping: There are " + mappings.size()
170 for (StructureMapping sm : mappings)
172 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
178 * map between the PDB IDs (or structure identifiers) used by Jalview and the
179 * absolute filenames for PDB data that corresponds to it
181 Map<String, String> pdbIdFileName = new HashMap<String, String>();
183 Map<String, String> pdbFileNameId = new HashMap<String, String>();
185 public void registerPDBFile(String idForFile, String absoluteFile)
187 pdbIdFileName.put(idForFile, absoluteFile);
188 pdbFileNameId.put(absoluteFile, idForFile);
191 public String findIdForPDBFile(String idOrFile)
193 String id = pdbFileNameId.get(idOrFile);
197 public String findFileForPDBId(String idOrFile)
199 String id = pdbIdFileName.get(idOrFile);
203 public boolean isPDBFileRegistered(String idOrFile)
205 return pdbFileNameId.containsKey(idOrFile)
206 || pdbIdFileName.containsKey(idOrFile);
209 private static StructureSelectionManager nullProvider = null;
211 public static StructureSelectionManager getStructureSelectionManager(
212 StructureSelectionManagerProvider context)
216 if (nullProvider == null)
218 if (instances != null)
222 .getString("error.implementation_error_structure_selection_manager_null"),
223 new NullPointerException(MessageManager
224 .getString("exception.ssm_context_is_null")));
228 nullProvider = new StructureSelectionManager();
233 if (instances == null)
235 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
237 StructureSelectionManager instance = instances.get(context);
238 if (instance == null)
240 if (nullProvider != null)
242 instance = nullProvider;
246 instance = new StructureSelectionManager();
248 instances.put(context, instance);
254 * flag controlling whether SeqMappings are relayed from received sequence
255 * mouse over events to other sequences
257 boolean relaySeqMappings = true;
260 * Enable or disable relay of seqMapping events to other sequences. You might
261 * want to do this if there are many sequence mappings and the host computer
266 public void setRelaySeqMappings(boolean relay)
268 relaySeqMappings = relay;
272 * get the state of the relay seqMappings flag.
274 * @return true if sequence mouse overs are being relayed to other mapped
277 public boolean isRelaySeqMappingsEnabled()
279 return relaySeqMappings;
282 Vector listeners = new Vector();
285 * register a listener for alignment sequence mouseover events
289 public void addStructureViewerListener(Object svl)
291 if (!listeners.contains(svl))
293 listeners.addElement(svl);
298 * Returns the file name for a mapped PDB id (or null if not mapped).
303 public String alreadyMappedToFile(String pdbid)
305 for (StructureMapping sm : mappings)
307 if (sm.getPdbId().equals(pdbid))
316 * Import structure data and register a structure mapping for broadcasting
317 * colouring, mouseovers and selection events (convenience wrapper).
320 * - one or more sequences to be mapped to pdbFile
321 * @param targetChains
322 * - optional chain specification for mapping each sequence to pdb
323 * (may be nill, individual elements may be nill)
325 * - structure data resource
327 * - how to resolve data from resource
328 * @return null or the structure data parsed as a pdb file
330 synchronized public StructureFile setMapping(SequenceI[] sequence,
331 String[] targetChains, String pdbFile, DataSourceType protocol,
332 IProgressIndicator progress)
334 return computeMapping(true, sequence, targetChains, pdbFile, protocol,
340 * create sequence structure mappings between each sequence and the given
341 * pdbFile (retrieved via the given protocol).
343 * @param forStructureView
344 * when true, record the mapping for use in mouseOvers
346 * @param sequenceArray
347 * - one or more sequences to be mapped to pdbFile
348 * @param targetChainIds
349 * - optional chain specification for mapping each sequence to pdb
350 * (may be null, individual elements may be null)
352 * - structure data resource
354 * - how to resolve data from resource
355 * @return null or the structure data parsed as a pdb file
357 synchronized public StructureFile setMapping(boolean forStructureView,
358 SequenceI[] sequenceArray, String[] targetChainIds,
359 String pdbFile, DataSourceType protocol)
361 return computeMapping(forStructureView, sequenceArray, targetChainIds,
362 pdbFile, protocol, null);
365 synchronized public StructureFile computeMapping(
366 boolean forStructureView, SequenceI[] sequenceArray,
367 String[] targetChainIds, String pdbFile, DataSourceType protocol,
368 IProgressIndicator progress)
370 long progressSessionId = System.currentTimeMillis() * 3;
372 * There will be better ways of doing this in the future, for now we'll use
373 * the tried and tested MCview pdb mapping
375 boolean parseSecStr = processSecondaryStructure;
376 if (isPDBFileRegistered(pdbFile))
378 for (SequenceI sq : sequenceArray)
381 while (ds.getDatasetSequence() != null)
383 ds = ds.getDatasetSequence();
386 if (ds.getAnnotation() != null)
388 for (AlignmentAnnotation ala : ds.getAnnotation())
390 // false if any annotation present from this structure
391 // JBPNote this fails for jmol/chimera view because the *file* is
392 // passed, not the structure data ID -
393 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
401 StructureFile pdb = null;
402 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
405 pdb = new JmolParser(pdbFile, protocol);
407 if (pdb.getId() != null && pdb.getId().trim().length() > 0
408 && DataSourceType.FILE == protocol)
410 registerPDBFile(pdb.getId().trim(), pdbFile);
412 // if PDBId is unavailable then skip SIFTS mapping execution path
413 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
415 } catch (Exception ex)
417 ex.printStackTrace();
425 siftsClient = new SiftsClient(pdb);
427 } catch (SiftsException e)
429 isMapUsingSIFTs = false;
433 String targetChainId;
434 for (int s = 0; s < sequenceArray.length; s++)
436 boolean infChain = true;
437 final SequenceI seq = sequenceArray[s];
439 while (ds.getDatasetSequence() != null)
441 ds = ds.getDatasetSequence();
444 if (targetChainIds != null && targetChainIds[s] != null)
447 targetChainId = targetChainIds[s];
449 else if (seq.getName().indexOf("|") > -1)
451 targetChainId = seq.getName().substring(
452 seq.getName().lastIndexOf("|") + 1);
453 if (targetChainId.length() > 1)
455 if (targetChainId.trim().length() == 0)
457 targetChainId = StructureMapping.NO_CHAIN;
461 // not a valid chain identifier
472 * Attempt pairwise alignment of the sequence with each chain in the PDB,
473 * and remember the highest scoring chain
476 AlignSeq maxAlignseq = null;
477 String maxChainId = StructureMapping.NO_CHAIN; // space
478 PDBChain maxChain = null;
479 boolean first = true;
480 for (PDBChain chain : pdb.getChains())
482 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
485 continue; // don't try to map chains don't match.
487 // TODO: correctly determine sequence type for mixed na/peptide
489 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
490 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
493 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
494 // as.calcScoreMatrix();
495 // as.traceAlignment();
497 if (first || as.maxscore > max
498 || (as.maxscore == max && chain.id.equals(targetChainId)))
504 maxChainId = chain.id;
507 if (maxChain == null)
512 if (protocol.equals(DataSourceType.PASTE))
514 pdbFile = "INLINE" + pdb.getId();
516 boolean phyre2Template = isPhyre2Template(pdbFile);
517 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
518 if (!phyre2Template && isMapUsingSIFTs && seq.isProtein())
520 if (progress!=null) {
521 progress.setProgressBar(MessageManager
522 .getString("status.obtaining_mapping_with_sifts"),
525 jalview.datamodel.Mapping sqmpping = maxAlignseq
526 .getMappingFromS1(false);
527 if (targetChainId != null && !targetChainId.trim().isEmpty())
529 StructureMapping siftsMapping;
532 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
533 pdb, maxChain, sqmpping, maxAlignseq);
534 seqToStrucMapping.add(siftsMapping);
535 maxChain.makeExactMapping(maxAlignseq, seq);
536 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
538 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
539 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
541 } catch (SiftsException e)
543 // fall back to NW alignment
544 System.err.println(e.getMessage());
545 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
546 targetChainId, maxChain, pdb, maxAlignseq);
547 seqToStrucMapping.add(nwMapping);
548 maxChain.makeExactMapping(maxAlignseq, seq);
549 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
551 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
552 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
553 } catch (Exception e)
560 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
561 for (PDBChain chain : pdb.getChains())
565 StructureMapping siftsMapping = getStructureMapping(seq,
566 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
567 foundSiftsMappings.add(siftsMapping);
568 } catch (SiftsException e)
570 System.err.println(e.getMessage());
571 } catch (Exception e)
576 if (!foundSiftsMappings.isEmpty())
578 seqToStrucMapping.addAll(foundSiftsMappings);
579 maxChain.makeExactMapping(maxAlignseq, seq);
580 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
582 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
584 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
588 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
589 maxChainId, maxChain, pdb, maxAlignseq);
590 seqToStrucMapping.add(nwMapping);
591 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
593 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
594 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
598 else if (phyre2Template)
600 setProgressBar(null);
601 setProgressBar(MessageManager
602 .getString("status.obtaining_mapping_with_phyre2_template_alignment"));
603 String fastaFile = getPhyre2FastaFileFor(pdbFile);
604 StructureMapping phyre2ModelMapping = new Phyre2Client(pdb)
605 .getStructureMapping(seq, pdbFile, fastaFile,
606 StructureMapping.NO_CHAIN);
607 seqToStrucMapping.add(phyre2ModelMapping);
608 maxChain.makeExactMapping(maxAlignseq, seq);
609 maxChain.transferRESNUMFeatures(seq, null);
610 jalview.datamodel.Mapping sqmpping = maxAlignseq
611 .getMappingFromS1(false);
612 maxChain.transferResidueAnnotation(phyre2ModelMapping, sqmpping);
613 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
617 if (progress != null)
619 progress.setProgressBar(MessageManager
620 .getString("status.obtaining_mapping_with_nw_alignment"),
623 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
624 maxChainId, maxChain, pdb, maxAlignseq);
625 seqToStrucMapping.add(nwMapping);
626 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
630 if (forStructureView)
632 mappings.addAll(seqToStrucMapping);
638 public void registerPhyre2Template(String phyre2Template,
639 String fastaMappingFile)
641 phyre2ModelTemplates.put(phyre2Template, fastaMappingFile);
645 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
650 * @param targetChainId
656 * @throws SiftsException
658 private StructureMapping getStructureMapping(SequenceI seq,
659 String pdbFile, String targetChainId, StructureFile pdb,
660 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
661 AlignSeq maxAlignseq) throws Exception
663 StructureMapping curChainMapping = siftsClient
664 .getStructureMapping(seq, pdbFile, targetChainId);
667 PDBChain chain = pdb.findChain(targetChainId);
670 chain.transferResidueAnnotation(curChainMapping, sqmpping);
672 } catch (Exception e)
676 return curChainMapping;
679 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
680 String maxChainId, PDBChain maxChain, StructureFile pdb,
681 AlignSeq maxAlignseq)
683 final StringBuilder mappingDetails = new StringBuilder(128);
684 mappingDetails.append(NEWLINE).append(
685 "Sequence \u27f7 Structure mapping details");
686 mappingDetails.append(NEWLINE);
688 .append("Method: inferred with Needleman & Wunsch alignment");
689 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
690 .append(NEWLINE).append("Sequence = ")
691 .append(maxChain.sequence.getSequenceAsString());
692 mappingDetails.append(NEWLINE).append("No of residues = ")
693 .append(maxChain.residues.size()).append(NEWLINE)
695 PrintStream ps = new PrintStream(System.out)
698 public void print(String x)
700 mappingDetails.append(x);
704 public void println()
706 mappingDetails.append(NEWLINE);
710 maxAlignseq.printAlignment(ps);
712 mappingDetails.append(NEWLINE).append("PDB start/end ");
713 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
715 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
716 mappingDetails.append(NEWLINE).append("SEQ start/end ");
717 mappingDetails.append(
718 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
720 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
721 + (seq.getStart() - 1)));
722 mappingDetails.append(NEWLINE);
723 maxChain.makeExactMapping(maxAlignseq, seq);
724 jalview.datamodel.Mapping sqmpping = maxAlignseq
725 .getMappingFromS1(false);
726 maxChain.transferRESNUMFeatures(seq, null);
728 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
735 Atom tmp = maxChain.atoms.elementAt(index);
736 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
737 && tmp.alignmentMapping != -1)
739 resNum = tmp.resNumber;
740 insCode = tmp.insCode;
741 if (tmp.alignmentMapping >= -1)
743 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
749 } while (index < maxChain.atoms.size());
751 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
752 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
753 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
757 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
759 listeners.removeElement(svl);
760 if (svl instanceof SequenceListener)
762 for (int i = 0; i < listeners.size(); i++)
764 if (listeners.elementAt(i) instanceof StructureListener)
766 ((StructureListener) listeners.elementAt(i))
767 .releaseReferences(svl);
772 if (pdbfiles == null)
778 * Remove mappings to the closed listener's PDB files, but first check if
779 * another listener is still interested
781 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
783 StructureListener sl;
784 for (int i = 0; i < listeners.size(); i++)
786 if (listeners.elementAt(i) instanceof StructureListener)
788 sl = (StructureListener) listeners.elementAt(i);
789 for (String pdbfile : sl.getStructureFiles())
791 pdbs.remove(pdbfile);
797 * Rebuild the mappings set, retaining only those which are for 'other' PDB
802 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
803 for (StructureMapping sm : mappings)
805 if (!pdbs.contains(sm.pdbfile))
816 * Propagate mouseover of a single position in a structure
822 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
824 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
825 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
826 mouseOverStructure(atoms);
830 * Propagate mouseover or selection of multiple positions in a structure
834 public void mouseOverStructure(List<AtomSpec> atoms)
836 if (listeners == null)
838 // old or prematurely sent event
841 boolean hasSequenceListener = false;
842 for (int i = 0; i < listeners.size(); i++)
844 if (listeners.elementAt(i) instanceof SequenceListener)
846 hasSequenceListener = true;
849 if (!hasSequenceListener)
854 SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms);
855 for (Object li : listeners)
857 if (li instanceof SequenceListener)
859 ((SequenceListener) li).highlightSequence(results);
865 * Constructs a SearchResults object holding regions (if any) in the Jalview
866 * alignment which have a mapping to the structure viewer positions in the
872 public SearchResultsI findAlignmentPositionsForStructurePositions(
873 List<AtomSpec> atoms)
875 SearchResultsI results = new SearchResults();
876 for (AtomSpec atom : atoms)
878 SequenceI lastseq = null;
880 for (StructureMapping sm : mappings)
882 if (sm.pdbfile.equals(atom.getPdbFile())
883 && sm.pdbchain.equals(atom.getChain()))
885 int indexpos = sm.getSeqPos(atom.getPdbResNum());
886 if (lastipos != indexpos || lastseq != sm.sequence)
888 results.addResult(sm.sequence, indexpos, indexpos);
890 lastseq = sm.sequence;
891 // construct highlighted sequence list
892 for (AlignedCodonFrame acf : seqmappings)
894 acf.markMappedRegion(sm.sequence, indexpos, results);
904 * highlight regions associated with a position (indexpos) in seq
907 * the sequence that the mouse over occurred on
909 * the absolute position being mouseovered in seq (0 to seq.length())
911 * the sequence position (if -1, seq.findPosition is called to
912 * resolve the residue number)
914 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
917 boolean hasSequenceListeners = handlingVamsasMo
918 || !seqmappings.isEmpty();
919 SearchResultsI results = null;
922 seqPos = seq.findPosition(indexpos);
924 for (int i = 0; i < listeners.size(); i++)
926 Object listener = listeners.elementAt(i);
927 if (listener == source)
929 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
930 // Temporary fudge with SequenceListener.getVamsasSource()
933 if (listener instanceof StructureListener)
935 highlightStructure((StructureListener) listener, seq, seqPos);
939 if (listener instanceof SequenceListener)
941 final SequenceListener seqListener = (SequenceListener) listener;
942 if (hasSequenceListeners
943 && seqListener.getVamsasSource() != source)
945 if (relaySeqMappings)
949 results = MappingUtils.buildSearchResults(seq, seqPos,
952 if (handlingVamsasMo)
954 results.addResult(seq, seqPos, seqPos);
957 if (!results.isEmpty())
959 seqListener.highlightSequence(results);
964 else if (listener instanceof VamsasListener && !handlingVamsasMo)
966 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
969 else if (listener instanceof SecondaryStructureListener)
971 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
979 * Send suitable messages to a StructureListener to highlight atoms
980 * corresponding to the given sequence position(s)
986 public void highlightStructure(StructureListener sl, SequenceI seq,
989 if (!sl.isListeningFor(seq))
994 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
995 for (StructureMapping sm : mappings)
997 if (sm.sequence == seq
998 || sm.sequence == seq.getDatasetSequence()
999 || (sm.sequence.getDatasetSequence() != null && sm.sequence
1000 .getDatasetSequence() == seq.getDatasetSequence()))
1002 for (int index : positions)
1004 atomNo = sm.getAtomNum(index);
1008 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
1009 .getPDBResNum(index), atomNo));
1014 sl.highlightAtoms(atoms);
1018 * true if a mouse over event from an external (ie Vamsas) source is being
1021 boolean handlingVamsasMo = false;
1026 * as mouseOverSequence but only route event to SequenceListeners
1030 * in an alignment sequence
1032 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1033 VamsasSource source)
1035 handlingVamsasMo = true;
1036 long msg = sequenceI.hashCode() * (1 + position);
1040 mouseOverSequence(sequenceI, position, -1, source);
1042 handlingVamsasMo = false;
1045 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1049 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1050 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1052 * Annotation [] annotations = new Annotation[seq.getLength()];
1054 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1055 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1056 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1058 * for (int j = 0; j < mappings.length; j++) {
1060 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1061 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1062 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1063 * "+mappings[j].pdbfile);
1065 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1066 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1068 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1069 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1070 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1071 * mappings[j].pdbfile); }
1073 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1074 * annotations; } } } }
1076 * return annotations;
1080 public void structureSelectionChanged()
1084 public void sequenceSelectionChanged()
1088 public void sequenceColoursChanged(Object source)
1090 StructureListener sl;
1091 for (int i = 0; i < listeners.size(); i++)
1093 if (listeners.elementAt(i) instanceof StructureListener)
1095 sl = (StructureListener) listeners.elementAt(i);
1096 sl.updateColours(source);
1101 public StructureMapping[] getMapping(String pdbfile)
1103 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1104 for (StructureMapping sm : mappings)
1106 if (sm.pdbfile.equals(pdbfile))
1111 return tmp.toArray(new StructureMapping[tmp.size()]);
1115 * Returns a readable description of all mappings for the given pdbfile to any
1116 * of the given sequences
1122 public String printMappings(String pdbfile, List<SequenceI> seqs)
1124 if (pdbfile == null || seqs == null || seqs.isEmpty())
1129 StringBuilder sb = new StringBuilder(64);
1130 for (StructureMapping sm : mappings)
1132 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1134 sb.append(sm.mappingDetails);
1136 // separator makes it easier to read multiple mappings
1137 sb.append("=====================");
1143 return sb.toString();
1147 * Remove the given mapping
1151 public void deregisterMapping(AlignedCodonFrame acf)
1155 boolean removed = seqmappings.remove(acf);
1156 if (removed && seqmappings.isEmpty())
1158 System.out.println("All mappings removed");
1164 * Add each of the given codonFrames to the stored set, if not aready present.
1168 public void registerMappings(List<AlignedCodonFrame> mappings)
1170 if (mappings != null)
1172 for (AlignedCodonFrame acf : mappings)
1174 registerMapping(acf);
1180 * Add the given mapping to the stored set, unless already stored.
1182 public void registerMapping(AlignedCodonFrame acf)
1186 if (!seqmappings.contains(acf))
1188 seqmappings.add(acf);
1194 * Resets this object to its initial state by removing all registered
1195 * listeners, codon mappings, PDB file mappings
1197 public void resetAll()
1199 if (mappings != null)
1203 if (seqmappings != null)
1205 seqmappings.clear();
1207 if (sel_listeners != null)
1209 sel_listeners.clear();
1211 if (listeners != null)
1215 if (commandListeners != null)
1217 commandListeners.clear();
1219 if (view_listeners != null)
1221 view_listeners.clear();
1223 if (pdbFileNameId != null)
1225 pdbFileNameId.clear();
1227 if (pdbIdFileName != null)
1229 pdbIdFileName.clear();
1233 public void addSelectionListener(SelectionListener selecter)
1235 if (!sel_listeners.contains(selecter))
1237 sel_listeners.add(selecter);
1241 public void removeSelectionListener(SelectionListener toremove)
1243 if (sel_listeners.contains(toremove))
1245 sel_listeners.remove(toremove);
1249 public synchronized void sendSelection(
1250 jalview.datamodel.SequenceGroup selection,
1251 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1253 for (SelectionListener slis : sel_listeners)
1257 slis.selection(selection, colsel, source);
1262 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1264 public synchronized void sendViewPosition(
1265 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1266 int startSeq, int endSeq)
1269 if (view_listeners != null && view_listeners.size() > 0)
1271 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1273 while (listeners.hasMoreElements())
1275 AlignmentViewPanelListener slis = listeners.nextElement();
1278 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1286 * release all references associated with this manager provider
1288 * @param jalviewLite
1290 public static void release(StructureSelectionManagerProvider jalviewLite)
1292 // synchronized (instances)
1294 if (instances == null)
1298 StructureSelectionManager mnger = (instances.get(jalviewLite));
1301 instances.remove(jalviewLite);
1305 } catch (Throwable x)
1312 public void registerPDBEntry(PDBEntry pdbentry)
1314 if (pdbentry.getFile() != null
1315 && pdbentry.getFile().trim().length() > 0)
1317 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1321 public void addCommandListener(CommandListener cl)
1323 if (!commandListeners.contains(cl))
1325 commandListeners.add(cl);
1329 public boolean hasCommandListener(CommandListener cl)
1331 return this.commandListeners.contains(cl);
1334 public boolean removeCommandListener(CommandListener l)
1336 return commandListeners.remove(l);
1340 * Forward a command to any command listeners (except for the command's
1344 * the command to be broadcast (in its form after being performed)
1346 * if true, the command was being 'undone'
1349 public void commandPerformed(CommandI command, boolean undo,
1350 VamsasSource source)
1352 for (CommandListener listener : commandListeners)
1354 listener.mirrorCommand(command, undo, this, source);
1359 * Returns a new CommandI representing the given command as mapped to the
1360 * given sequences. If no mapping could be made, or the command is not of a
1361 * mappable kind, returns null.
1369 public CommandI mapCommand(CommandI command, boolean undo,
1370 final AlignmentI mapTo, char gapChar)
1372 if (command instanceof EditCommand)
1374 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1375 mapTo, gapChar, seqmappings);
1377 else if (command instanceof OrderCommand)
1379 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1380 mapTo, seqmappings);
1385 public IProgressIndicator getProgressIndicator()
1387 return progressIndicator;
1390 public void setProgressIndicator(IProgressIndicator progressIndicator)
1392 this.progressIndicator = progressIndicator;
1395 public long getProgressSessionId()
1397 return progressSessionId;
1400 public void setProgressSessionId(long progressSessionId)
1402 this.progressSessionId = progressSessionId;
1405 public void setProgressBar(String message)
1407 if (progressIndicator == null)
1411 progressIndicator.setProgressBar(message, progressSessionId);
1414 public List<AlignedCodonFrame> getSequenceMappings()
1419 public boolean isPhyre2Template(String structureFile)
1421 if (structureFile == null || phyre2ModelTemplates == null
1422 || phyre2ModelTemplates.isEmpty())
1426 return phyre2ModelTemplates.get(structureFile) != null
1427 && !phyre2ModelTemplates.get(structureFile).isEmpty();
1430 public String getPhyre2FastaFileFor(String structureFile)
1432 return phyre2ModelTemplates.get(structureFile);
1436 public static StructureSelectionManager getStructureSelectionManager()
1438 return instances.values().iterator().next();
1441 public void addStructureMapping(StructureMapping smapping)
1443 mappings.add(smapping);