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)
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 = " ";
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 StructureMapping phyre2ModelMapping = new Phyre2Client(pdb)
604 .getStructureMapping(seq, pdbFile,
605 getPhyre2FastaFileFor(pdbFile), " ");
607 seqToStrucMapping.add(phyre2ModelMapping);
608 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
612 if (progress != null)
614 progress.setProgressBar(MessageManager
615 .getString("status.obtaining_mapping_with_nw_alignment"),
618 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
619 maxChainId, maxChain, pdb, maxAlignseq);
620 seqToStrucMapping.add(nwMapping);
621 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
625 if (forStructureView)
627 mappings.addAll(seqToStrucMapping);
633 public void registerPhyre2Template(String phyre2Template,
634 String fastaMappingFile)
636 phyre2ModelTemplates.put(phyre2Template, fastaMappingFile);
640 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
645 * @param targetChainId
651 * @throws SiftsException
653 private StructureMapping getStructureMapping(SequenceI seq,
654 String pdbFile, String targetChainId, StructureFile pdb,
655 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
656 AlignSeq maxAlignseq) throws Exception
658 StructureMapping curChainMapping = siftsClient
659 .getStructureMapping(seq, pdbFile, targetChainId);
662 PDBChain chain = pdb.findChain(targetChainId);
665 chain.transferResidueAnnotation(curChainMapping, sqmpping);
667 } catch (Exception e)
671 return curChainMapping;
674 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
675 String maxChainId, PDBChain maxChain, StructureFile pdb,
676 AlignSeq maxAlignseq)
678 final StringBuilder mappingDetails = new StringBuilder(128);
679 mappingDetails.append(NEWLINE).append(
680 "Sequence \u27f7 Structure mapping details");
681 mappingDetails.append(NEWLINE);
683 .append("Method: inferred with Needleman & Wunsch alignment");
684 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
685 .append(NEWLINE).append("Sequence = ")
686 .append(maxChain.sequence.getSequenceAsString());
687 mappingDetails.append(NEWLINE).append("No of residues = ")
688 .append(maxChain.residues.size()).append(NEWLINE)
690 PrintStream ps = new PrintStream(System.out)
693 public void print(String x)
695 mappingDetails.append(x);
699 public void println()
701 mappingDetails.append(NEWLINE);
705 maxAlignseq.printAlignment(ps);
707 mappingDetails.append(NEWLINE).append("PDB start/end ");
708 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
710 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
711 mappingDetails.append(NEWLINE).append("SEQ start/end ");
712 mappingDetails.append(
713 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
715 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
716 + (seq.getStart() - 1)));
717 mappingDetails.append(NEWLINE);
718 maxChain.makeExactMapping(maxAlignseq, seq);
719 jalview.datamodel.Mapping sqmpping = maxAlignseq
720 .getMappingFromS1(false);
721 maxChain.transferRESNUMFeatures(seq, null);
723 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
730 Atom tmp = maxChain.atoms.elementAt(index);
731 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
732 && tmp.alignmentMapping != -1)
734 resNum = tmp.resNumber;
735 insCode = tmp.insCode;
736 if (tmp.alignmentMapping >= -1)
738 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
744 } while (index < maxChain.atoms.size());
746 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
747 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
748 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
752 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
754 listeners.removeElement(svl);
755 if (svl instanceof SequenceListener)
757 for (int i = 0; i < listeners.size(); i++)
759 if (listeners.elementAt(i) instanceof StructureListener)
761 ((StructureListener) listeners.elementAt(i))
762 .releaseReferences(svl);
767 if (pdbfiles == null)
773 * Remove mappings to the closed listener's PDB files, but first check if
774 * another listener is still interested
776 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
778 StructureListener sl;
779 for (int i = 0; i < listeners.size(); i++)
781 if (listeners.elementAt(i) instanceof StructureListener)
783 sl = (StructureListener) listeners.elementAt(i);
784 for (String pdbfile : sl.getPdbFile())
786 pdbs.remove(pdbfile);
792 * Rebuild the mappings set, retaining only those which are for 'other' PDB
797 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
798 for (StructureMapping sm : mappings)
800 if (!pdbs.contains(sm.pdbfile))
811 * Propagate mouseover of a single position in a structure
817 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
819 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
820 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
821 mouseOverStructure(atoms);
825 * Propagate mouseover or selection of multiple positions in a structure
829 public void mouseOverStructure(List<AtomSpec> atoms)
831 if (listeners == null)
833 // old or prematurely sent event
836 boolean hasSequenceListener = false;
837 for (int i = 0; i < listeners.size(); i++)
839 if (listeners.elementAt(i) instanceof SequenceListener)
841 hasSequenceListener = true;
844 if (!hasSequenceListener)
849 SearchResultsI results = new SearchResults();
850 for (AtomSpec atom : atoms)
852 SequenceI lastseq = null;
854 for (StructureMapping sm : mappings)
856 if (sm.pdbfile.equals(atom.getPdbFile())
857 && sm.pdbchain.equals(atom.getChain()))
859 int indexpos = sm.getSeqPos(atom.getPdbResNum());
860 if (lastipos != indexpos && lastseq != sm.sequence)
862 results.addResult(sm.sequence, indexpos, indexpos);
864 lastseq = sm.sequence;
865 // construct highlighted sequence list
866 for (AlignedCodonFrame acf : seqmappings)
868 acf.markMappedRegion(sm.sequence, indexpos, results);
874 for (Object li : listeners)
876 if (li instanceof SequenceListener)
878 ((SequenceListener) li).highlightSequence(results);
884 * highlight regions associated with a position (indexpos) in seq
887 * the sequence that the mouse over occurred on
889 * the absolute position being mouseovered in seq (0 to seq.length())
891 * the sequence position (if -1, seq.findPosition is called to
892 * resolve the residue number)
894 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
897 boolean hasSequenceListeners = handlingVamsasMo
898 || !seqmappings.isEmpty();
899 SearchResultsI results = null;
902 seqPos = seq.findPosition(indexpos);
904 for (int i = 0; i < listeners.size(); i++)
906 Object listener = listeners.elementAt(i);
907 if (listener == source)
909 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
910 // Temporary fudge with SequenceListener.getVamsasSource()
913 if (listener instanceof StructureListener)
915 highlightStructure((StructureListener) listener, seq, seqPos);
919 if (listener instanceof SequenceListener)
921 final SequenceListener seqListener = (SequenceListener) listener;
922 if (hasSequenceListeners
923 && seqListener.getVamsasSource() != source)
925 if (relaySeqMappings)
929 results = MappingUtils.buildSearchResults(seq, seqPos,
932 if (handlingVamsasMo)
934 results.addResult(seq, seqPos, seqPos);
937 if (!results.isEmpty())
939 seqListener.highlightSequence(results);
944 else if (listener instanceof VamsasListener && !handlingVamsasMo)
946 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
949 else if (listener instanceof SecondaryStructureListener)
951 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
959 * Send suitable messages to a StructureListener to highlight atoms
960 * corresponding to the given sequence position(s)
966 public void highlightStructure(StructureListener sl, SequenceI seq,
969 if (!sl.isListeningFor(seq))
974 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
975 for (StructureMapping sm : mappings)
977 if (sm.sequence == seq
978 || sm.sequence == seq.getDatasetSequence()
979 || (sm.sequence.getDatasetSequence() != null && sm.sequence
980 .getDatasetSequence() == seq.getDatasetSequence()))
982 for (int index : positions)
984 atomNo = sm.getAtomNum(index);
988 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
989 .getPDBResNum(index), atomNo));
994 sl.highlightAtoms(atoms);
998 * true if a mouse over event from an external (ie Vamsas) source is being
1001 boolean handlingVamsasMo = false;
1006 * as mouseOverSequence but only route event to SequenceListeners
1010 * in an alignment sequence
1012 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1013 VamsasSource source)
1015 handlingVamsasMo = true;
1016 long msg = sequenceI.hashCode() * (1 + position);
1020 mouseOverSequence(sequenceI, position, -1, source);
1022 handlingVamsasMo = false;
1025 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1029 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1030 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1032 * Annotation [] annotations = new Annotation[seq.getLength()];
1034 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1035 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1036 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1038 * for (int j = 0; j < mappings.length; j++) {
1040 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1041 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1042 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1043 * "+mappings[j].pdbfile);
1045 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1046 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1048 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1049 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1050 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1051 * mappings[j].pdbfile); }
1053 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1054 * annotations; } } } }
1056 * return annotations;
1060 public void structureSelectionChanged()
1064 public void sequenceSelectionChanged()
1068 public void sequenceColoursChanged(Object source)
1070 StructureListener sl;
1071 for (int i = 0; i < listeners.size(); i++)
1073 if (listeners.elementAt(i) instanceof StructureListener)
1075 sl = (StructureListener) listeners.elementAt(i);
1076 sl.updateColours(source);
1081 public StructureMapping[] getMapping(String pdbfile)
1083 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1084 for (StructureMapping sm : mappings)
1086 if (sm.pdbfile.equals(pdbfile))
1091 return tmp.toArray(new StructureMapping[tmp.size()]);
1095 * Returns a readable description of all mappings for the given pdbfile to any
1096 * of the given sequences
1102 public String printMappings(String pdbfile, List<SequenceI> seqs)
1104 if (pdbfile == null || seqs == null || seqs.isEmpty())
1109 StringBuilder sb = new StringBuilder(64);
1110 for (StructureMapping sm : mappings)
1112 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1114 sb.append(sm.mappingDetails);
1116 // separator makes it easier to read multiple mappings
1117 sb.append("=====================");
1123 return sb.toString();
1127 * Remove the given mapping
1131 public void deregisterMapping(AlignedCodonFrame acf)
1135 boolean removed = seqmappings.remove(acf);
1136 if (removed && seqmappings.isEmpty())
1138 System.out.println("All mappings removed");
1144 * Add each of the given codonFrames to the stored set, if not aready present.
1148 public void registerMappings(List<AlignedCodonFrame> mappings)
1150 if (mappings != null)
1152 for (AlignedCodonFrame acf : mappings)
1154 registerMapping(acf);
1160 * Add the given mapping to the stored set, unless already stored.
1162 public void registerMapping(AlignedCodonFrame acf)
1166 if (!seqmappings.contains(acf))
1168 seqmappings.add(acf);
1174 * Resets this object to its initial state by removing all registered
1175 * listeners, codon mappings, PDB file mappings
1177 public void resetAll()
1179 if (mappings != null)
1183 if (seqmappings != null)
1185 seqmappings.clear();
1187 if (sel_listeners != null)
1189 sel_listeners.clear();
1191 if (listeners != null)
1195 if (commandListeners != null)
1197 commandListeners.clear();
1199 if (view_listeners != null)
1201 view_listeners.clear();
1203 if (pdbFileNameId != null)
1205 pdbFileNameId.clear();
1207 if (pdbIdFileName != null)
1209 pdbIdFileName.clear();
1213 public void addSelectionListener(SelectionListener selecter)
1215 if (!sel_listeners.contains(selecter))
1217 sel_listeners.add(selecter);
1221 public void removeSelectionListener(SelectionListener toremove)
1223 if (sel_listeners.contains(toremove))
1225 sel_listeners.remove(toremove);
1229 public synchronized void sendSelection(
1230 jalview.datamodel.SequenceGroup selection,
1231 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1233 for (SelectionListener slis : sel_listeners)
1237 slis.selection(selection, colsel, source);
1242 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1244 public synchronized void sendViewPosition(
1245 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1246 int startSeq, int endSeq)
1249 if (view_listeners != null && view_listeners.size() > 0)
1251 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1253 while (listeners.hasMoreElements())
1255 AlignmentViewPanelListener slis = listeners.nextElement();
1258 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1266 * release all references associated with this manager provider
1268 * @param jalviewLite
1270 public static void release(StructureSelectionManagerProvider jalviewLite)
1272 // synchronized (instances)
1274 if (instances == null)
1278 StructureSelectionManager mnger = (instances.get(jalviewLite));
1281 instances.remove(jalviewLite);
1285 } catch (Throwable x)
1292 public void registerPDBEntry(PDBEntry pdbentry)
1294 if (pdbentry.getFile() != null
1295 && pdbentry.getFile().trim().length() > 0)
1297 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1301 public void addCommandListener(CommandListener cl)
1303 if (!commandListeners.contains(cl))
1305 commandListeners.add(cl);
1309 public boolean hasCommandListener(CommandListener cl)
1311 return this.commandListeners.contains(cl);
1314 public boolean removeCommandListener(CommandListener l)
1316 return commandListeners.remove(l);
1320 * Forward a command to any command listeners (except for the command's
1324 * the command to be broadcast (in its form after being performed)
1326 * if true, the command was being 'undone'
1329 public void commandPerformed(CommandI command, boolean undo,
1330 VamsasSource source)
1332 for (CommandListener listener : commandListeners)
1334 listener.mirrorCommand(command, undo, this, source);
1339 * Returns a new CommandI representing the given command as mapped to the
1340 * given sequences. If no mapping could be made, or the command is not of a
1341 * mappable kind, returns null.
1349 public CommandI mapCommand(CommandI command, boolean undo,
1350 final AlignmentI mapTo, char gapChar)
1352 if (command instanceof EditCommand)
1354 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1355 mapTo, gapChar, seqmappings);
1357 else if (command instanceof OrderCommand)
1359 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1360 mapTo, seqmappings);
1365 public IProgressIndicator getProgressIndicator()
1367 return progressIndicator;
1370 public void setProgressIndicator(IProgressIndicator progressIndicator)
1372 this.progressIndicator = progressIndicator;
1375 public long getProgressSessionId()
1377 return progressSessionId;
1380 public void setProgressSessionId(long progressSessionId)
1382 this.progressSessionId = progressSessionId;
1385 public void setProgressBar(String message)
1387 if (progressIndicator == null)
1391 progressIndicator.setProgressBar(message, progressSessionId);
1394 public List<AlignedCodonFrame> getSequenceMappings()
1399 public boolean isPhyre2Template(String structureFile)
1401 if (structureFile == null || phyre2ModelTemplates == null
1402 || phyre2ModelTemplates.isEmpty())
1406 return phyre2ModelTemplates.get(structureFile) != null
1407 && !phyre2ModelTemplates.get(structureFile).isEmpty();
1410 public String getPhyre2FastaFileFor(String structureFile)
1412 return phyre2ModelTemplates.get(structureFile);
1416 public static StructureSelectionManager getStructureSelectionManager()
1418 return instances.values().iterator().next();