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<>();
71 private boolean processSecondaryStructure = false;
73 private boolean secStructServices = false;
75 private boolean addTempFacAnnot = false;
77 private SiftsClient siftsClient = null;
80 * Set of any registered mappings between (dataset) sequences.
82 private List<AlignedCodonFrame> seqmappings = new ArrayList<>();
84 private List<CommandListener> commandListeners = new ArrayList<>();
86 private List<SelectionListener> sel_listeners = new ArrayList<>();
89 * @return true if will try to use external services for processing secondary
92 public boolean isSecStructServices()
94 return secStructServices;
98 * control use of external services for processing secondary structure
100 * @param secStructServices
102 public void setSecStructServices(boolean secStructServices)
104 this.secStructServices = secStructServices;
108 * flag controlling addition of any kind of structural annotation
110 * @return true if temperature factor annotation will be added
112 public boolean isAddTempFacAnnot()
114 return addTempFacAnnot;
118 * set flag controlling addition of structural annotation
120 * @param addTempFacAnnot
122 public void setAddTempFacAnnot(boolean addTempFacAnnot)
124 this.addTempFacAnnot = addTempFacAnnot;
129 * @return if true, the structure manager will attempt to add secondary
130 * structure lines for unannotated sequences
133 public boolean isProcessSecondaryStructure()
135 return processSecondaryStructure;
139 * Control whether structure manager will try to annotate mapped sequences
140 * with secondary structure from PDB data.
144 public void setProcessSecondaryStructure(boolean enable)
146 processSecondaryStructure = enable;
150 * debug function - write all mappings to stdout
152 public void reportMapping()
154 if (mappings.isEmpty())
156 System.err.println("reportMapping: No PDB/Sequence mappings.");
161 "reportMapping: There are " + mappings.size() + " mappings.");
163 for (StructureMapping sm : mappings)
165 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
171 * map between the PDB IDs (or structure identifiers) used by Jalview and the
172 * absolute filenames for PDB data that corresponds to it
174 Map<String, String> pdbIdFileName = new HashMap<>();
176 Map<String, String> pdbFileNameId = new HashMap<>();
178 public void registerPDBFile(String idForFile, String absoluteFile)
180 pdbIdFileName.put(idForFile, absoluteFile);
181 pdbFileNameId.put(absoluteFile, idForFile);
184 public String findIdForPDBFile(String idOrFile)
186 String id = pdbFileNameId.get(idOrFile);
190 public String findFileForPDBId(String idOrFile)
192 String id = pdbIdFileName.get(idOrFile);
196 public boolean isPDBFileRegistered(String idOrFile)
198 return pdbFileNameId.containsKey(idOrFile)
199 || pdbIdFileName.containsKey(idOrFile);
202 private static StructureSelectionManager nullProvider = null;
204 public static StructureSelectionManager getStructureSelectionManager(
205 StructureSelectionManagerProvider context)
209 if (nullProvider == null)
211 if (instances != null)
213 throw new Error(MessageManager.getString(
214 "error.implementation_error_structure_selection_manager_null"),
215 new NullPointerException(MessageManager
216 .getString("exception.ssm_context_is_null")));
220 nullProvider = new StructureSelectionManager();
225 if (instances == null)
227 instances = new java.util.IdentityHashMap<>();
229 StructureSelectionManager instance = instances.get(context);
230 if (instance == null)
232 if (nullProvider != null)
234 instance = nullProvider;
238 instance = new StructureSelectionManager();
240 instances.put(context, instance);
246 * flag controlling whether SeqMappings are relayed from received sequence
247 * mouse over events to other sequences
249 boolean relaySeqMappings = true;
252 * Enable or disable relay of seqMapping events to other sequences. You might
253 * want to do this if there are many sequence mappings and the host computer
258 public void setRelaySeqMappings(boolean relay)
260 relaySeqMappings = relay;
264 * get the state of the relay seqMappings flag.
266 * @return true if sequence mouse overs are being relayed to other mapped
269 public boolean isRelaySeqMappingsEnabled()
271 return relaySeqMappings;
274 Vector listeners = new Vector();
277 * register a listener for alignment sequence mouseover events
281 public void addStructureViewerListener(Object svl)
283 if (!listeners.contains(svl))
285 listeners.addElement(svl);
290 * Returns the file name for a mapped PDB id (or null if not mapped).
295 public String alreadyMappedToFile(String pdbid)
297 for (StructureMapping sm : mappings)
299 if (sm.getPdbId().equals(pdbid))
308 * Import structure data and register a structure mapping for broadcasting
309 * colouring, mouseovers and selection events (convenience wrapper).
312 * - one or more sequences to be mapped to pdbFile
313 * @param targetChains
314 * - optional chain specification for mapping each sequence to pdb
315 * (may be nill, individual elements may be nill)
317 * - structure data resource
319 * - how to resolve data from resource
320 * @return null or the structure data parsed as a pdb file
322 synchronized public StructureFile setMapping(SequenceI[] sequence,
323 String[] targetChains, String pdbFile, DataSourceType protocol,
324 IProgressIndicator progress)
326 return computeMapping(true, sequence, targetChains, pdbFile, protocol,
331 * Import a single structure file and register sequence structure mappings for
332 * broadcasting colouring, mouseovers and selection events (convenience
335 * @param forStructureView
336 * when true, record the mapping for use in mouseOvers
338 * - one or more sequences to be mapped to pdbFile
339 * @param targetChains
340 * - optional chain specification for mapping each sequence to pdb
341 * (may be nill, individual elements may be nill)
343 * - structure data resource
345 * - how to resolve data from resource
346 * @return null or the structure data parsed as a pdb file
348 synchronized public StructureFile setMapping(boolean forStructureView,
349 SequenceI[] sequenceArray, String[] targetChainIds,
350 String pdbFile, DataSourceType sourceType)
352 return computeMapping(forStructureView, sequenceArray, targetChainIds,
353 pdbFile, sourceType, null);
357 * create sequence structure mappings between each sequence and the given
358 * pdbFile (retrieved via the given protocol). Either constructs a mapping
359 * using NW alignment or derives one from any available SIFTS mapping data.
361 * @param forStructureView
362 * when true, record the mapping for use in mouseOvers
364 * @param sequenceArray
365 * - one or more sequences to be mapped to pdbFile
366 * @param targetChainIds
367 * - optional chain specification for mapping each sequence to pdb
368 * (may be nill, individual elements may be nill) - JBPNote: JAL-2693
369 * - this should be List<List<String>>, empty lists indicate no
370 * predefined mappings
372 * - structure data resource
374 * - how to resolve data from resource
375 * @param IProgressIndicator
376 * reference to UI component that maintains a progress bar for the
378 * @return null or the structure data parsed as a pdb file
380 synchronized public StructureFile computeMapping(
381 boolean forStructureView, SequenceI[] sequenceArray,
382 String[] targetChainIds, String pdbFile, DataSourceType sourceType,
383 IProgressIndicator progress)
385 long progressSessionId = System.currentTimeMillis() * 3;
387 boolean parseSecStr = processSecondaryStructure;
388 if (isPDBFileRegistered(pdbFile))
390 for (SequenceI sq : sequenceArray)
393 while (ds.getDatasetSequence() != null)
395 ds = ds.getDatasetSequence();
398 if (ds.getAnnotation() != null)
400 for (AlignmentAnnotation ala : ds.getAnnotation())
402 // false if any annotation present from this structure
403 // JBPNote this fails for jmol/chimera view because the *file* is
404 // passed, not the structure data ID -
405 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
413 StructureFile pdb = null;
414 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
417 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
418 pdb = new JmolParser(pdbFile, sourceType);
420 if (pdb.getId() != null && pdb.getId().trim().length() > 0
421 && DataSourceType.FILE == sourceType)
423 registerPDBFile(pdb.getId().trim(), pdbFile);
425 // if PDBId is unavailable then skip SIFTS mapping execution path
426 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
428 } catch (Exception ex)
430 ex.printStackTrace();
438 siftsClient = new SiftsClient(pdb);
440 } catch (SiftsException e)
442 isMapUsingSIFTs = false;
446 String targetChainId;
447 for (int s = 0; s < sequenceArray.length; s++)
449 boolean infChain = true;
450 final SequenceI seq = sequenceArray[s];
452 while (ds.getDatasetSequence() != null)
454 ds = ds.getDatasetSequence();
457 if (targetChainIds != null && targetChainIds[s] != null)
460 targetChainId = targetChainIds[s];
462 else if (seq.getName().indexOf("|") > -1)
464 targetChainId = seq.getName()
465 .substring(seq.getName().lastIndexOf("|") + 1);
466 if (targetChainId.length() > 1)
468 if (targetChainId.trim().length() == 0)
474 // not a valid chain identifier
485 * Attempt pairwise alignment of the sequence with each chain in the PDB,
486 * and remember the highest scoring chain
489 AlignSeq maxAlignseq = null;
490 String maxChainId = " ";
491 PDBChain maxChain = null;
492 boolean first = true;
493 for (PDBChain chain : pdb.getChains())
495 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
498 continue; // don't try to map chains don't match.
500 // TODO: correctly determine sequence type for mixed na/peptide
502 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
503 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
506 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
507 // as.calcScoreMatrix();
508 // as.traceAlignment();
510 if (first || as.maxscore > max
511 || (as.maxscore == max && chain.id.equals(targetChainId)))
517 maxChainId = chain.id;
520 if (maxChain == null)
525 if (sourceType == DataSourceType.PASTE)
527 pdbFile = "INLINE" + pdb.getId();
530 List<StructureMapping> seqToStrucMapping = new ArrayList<>();
531 if (isMapUsingSIFTs && seq.isProtein())
533 if (progress!=null) {
534 progress.setProgressBar(MessageManager
535 .getString("status.obtaining_mapping_with_sifts"),
538 jalview.datamodel.Mapping sqmpping = maxAlignseq
539 .getMappingFromS1(false);
540 if (targetChainId != null && !targetChainId.trim().isEmpty())
542 StructureMapping siftsMapping;
545 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
546 pdb, maxChain, sqmpping, maxAlignseq);
547 seqToStrucMapping.add(siftsMapping);
548 maxChain.makeExactMapping(siftsMapping, seq);
549 maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
551 maxChain.transferResidueAnnotation(siftsMapping, null);
552 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
554 } catch (SiftsException e)
556 // fall back to NW alignment
557 System.err.println(e.getMessage());
558 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
559 targetChainId, maxChain, pdb, maxAlignseq);
560 seqToStrucMapping.add(nwMapping);
561 maxChain.makeExactMapping(maxAlignseq, seq);
562 maxChain.transferRESNUMFeatures(seq, "IEA:Jalview"); // FIXME: is
565 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
566 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
571 List<StructureMapping> foundSiftsMappings = new ArrayList<>();
572 for (PDBChain chain : pdb.getChains())
574 StructureMapping siftsMapping = null;
577 siftsMapping = getStructureMapping(seq,
578 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
579 foundSiftsMappings.add(siftsMapping);
580 chain.makeExactMapping(siftsMapping, seq);
581 chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
583 chain.transferResidueAnnotation(siftsMapping, null);
584 } catch (SiftsException e)
586 System.err.println(e.getMessage());
589 if (!foundSiftsMappings.isEmpty())
591 seqToStrucMapping.addAll(foundSiftsMappings);
592 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
596 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
597 maxChainId, maxChain, pdb, maxAlignseq);
598 seqToStrucMapping.add(nwMapping);
599 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
601 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
602 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
608 if (progress != null)
610 progress.setProgressBar(MessageManager
611 .getString("status.obtaining_mapping_with_nw_alignment"),
614 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
615 maxChain, pdb, maxAlignseq);
616 seqToStrucMapping.add(nwMapping);
617 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
619 if (forStructureView)
621 mappings.addAll(seqToStrucMapping);
623 if (progress != null)
625 progress.setProgressBar(null, progressSessionId);
631 public void addStructureMapping(StructureMapping sm)
637 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
642 * @param targetChainId
648 * @throws SiftsException
650 private StructureMapping getStructureMapping(SequenceI seq,
651 String pdbFile, String targetChainId, StructureFile pdb,
652 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
653 AlignSeq maxAlignseq) throws SiftsException
655 StructureMapping curChainMapping = siftsClient
656 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
659 PDBChain chain = pdb.findChain(targetChainId);
662 chain.transferResidueAnnotation(curChainMapping, null);
664 } catch (Exception e)
668 return curChainMapping;
671 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
672 String maxChainId, PDBChain maxChain, StructureFile pdb,
673 AlignSeq maxAlignseq)
675 final StringBuilder mappingDetails = new StringBuilder(128);
676 mappingDetails.append(NEWLINE)
677 .append("Sequence \u27f7 Structure mapping details");
678 mappingDetails.append(NEWLINE);
680 .append("Method: inferred with Needleman & Wunsch alignment");
681 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
682 .append(NEWLINE).append("Sequence = ")
683 .append(maxChain.sequence.getSequenceAsString());
684 mappingDetails.append(NEWLINE).append("No of residues = ")
685 .append(maxChain.residues.size()).append(NEWLINE)
687 PrintStream ps = new PrintStream(System.out)
690 public void print(String x)
692 mappingDetails.append(x);
696 public void println()
698 mappingDetails.append(NEWLINE);
702 maxAlignseq.printAlignment(ps);
704 mappingDetails.append(NEWLINE).append("PDB start/end ");
705 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
707 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
708 mappingDetails.append(NEWLINE).append("SEQ start/end ");
711 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
713 mappingDetails.append(
714 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
715 mappingDetails.append(NEWLINE);
716 maxChain.makeExactMapping(maxAlignseq, seq);
717 jalview.datamodel.Mapping sqmpping = maxAlignseq
718 .getMappingFromS1(false);
719 maxChain.transferRESNUMFeatures(seq, null);
721 HashMap<Integer, int[]> mapping = new HashMap<>();
728 Atom tmp = maxChain.atoms.elementAt(index);
729 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
730 && tmp.alignmentMapping != -1)
732 resNum = tmp.resNumber;
733 insCode = tmp.insCode;
734 if (tmp.alignmentMapping >= -1)
736 mapping.put(tmp.alignmentMapping + 1,
738 { tmp.resNumber, tmp.atomIndex });
743 } while (index < maxChain.atoms.size());
745 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
746 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
747 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
751 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
753 listeners.removeElement(svl);
754 if (svl instanceof SequenceListener)
756 for (int i = 0; i < listeners.size(); i++)
758 if (listeners.elementAt(i) instanceof StructureListener)
760 ((StructureListener) listeners.elementAt(i))
761 .releaseReferences(svl);
766 if (pdbfiles == null)
772 * Remove mappings to the closed listener's PDB files, but first check if
773 * another listener is still interested
775 List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
777 StructureListener sl;
778 for (int i = 0; i < listeners.size(); i++)
780 if (listeners.elementAt(i) instanceof StructureListener)
782 sl = (StructureListener) listeners.elementAt(i);
783 for (String pdbfile : sl.getStructureFiles())
785 pdbs.remove(pdbfile);
791 * Rebuild the mappings set, retaining only those which are for 'other' PDB
796 List<StructureMapping> tmp = new ArrayList<>();
797 for (StructureMapping sm : mappings)
799 if (!pdbs.contains(sm.pdbfile))
810 * Propagate mouseover of a single position in a structure
816 public void mouseOverStructure(int pdbResNum, String chain,
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 = findAlignmentPositionsForStructurePositions(
851 for (Object li : listeners)
853 if (li instanceof SequenceListener)
855 ((SequenceListener) li).highlightSequence(results);
861 * Constructs a SearchResults object holding regions (if any) in the Jalview
862 * alignment which have a mapping to the structure viewer positions in the
868 public SearchResultsI findAlignmentPositionsForStructurePositions(
869 List<AtomSpec> atoms)
871 SearchResultsI results = new SearchResults();
872 for (AtomSpec atom : atoms)
874 SequenceI lastseq = null;
876 for (StructureMapping sm : mappings)
878 if (sm.pdbfile.equals(atom.getPdbFile())
879 && sm.pdbchain.equals(atom.getChain()))
881 int indexpos = sm.getSeqPos(atom.getPdbResNum());
882 if (lastipos != indexpos || lastseq != sm.sequence)
884 results.addResult(sm.sequence, indexpos, indexpos);
886 lastseq = sm.sequence;
887 // construct highlighted sequence list
888 for (AlignedCodonFrame acf : seqmappings)
890 acf.markMappedRegion(sm.sequence, indexpos, results);
900 * highlight regions associated with a position (indexpos) in seq
903 * the sequence that the mouse over occurred on
905 * the absolute position being mouseovered in seq (0 to seq.length())
907 * the sequence position (if -1, seq.findPosition is called to
908 * resolve the residue number)
910 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
913 boolean hasSequenceListeners = handlingVamsasMo
914 || !seqmappings.isEmpty();
915 SearchResultsI results = null;
918 seqPos = seq.findPosition(indexpos);
920 for (int i = 0; i < listeners.size(); i++)
922 Object listener = listeners.elementAt(i);
923 if (listener == source)
925 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
926 // Temporary fudge with SequenceListener.getVamsasSource()
929 if (listener instanceof StructureListener)
931 highlightStructure((StructureListener) listener, seq, seqPos);
935 if (listener instanceof SequenceListener)
937 final SequenceListener seqListener = (SequenceListener) listener;
938 if (hasSequenceListeners
939 && seqListener.getVamsasSource() != source)
941 if (relaySeqMappings)
945 results = MappingUtils.buildSearchResults(seq, seqPos,
948 if (handlingVamsasMo)
950 results.addResult(seq, seqPos, seqPos);
953 if (!results.isEmpty())
955 seqListener.highlightSequence(results);
960 else if (listener instanceof VamsasListener && !handlingVamsasMo)
962 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
965 else if (listener instanceof SecondaryStructureListener)
967 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
975 * Send suitable messages to a StructureListener to highlight atoms
976 * corresponding to the given sequence position(s)
982 public void highlightStructure(StructureListener sl, SequenceI seq,
985 if (!sl.isListeningFor(seq))
990 List<AtomSpec> atoms = new ArrayList<>();
991 for (StructureMapping sm : mappings)
993 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
994 || (sm.sequence.getDatasetSequence() != null && sm.sequence
995 .getDatasetSequence() == seq.getDatasetSequence()))
997 for (int index : positions)
999 atomNo = sm.getAtomNum(index);
1003 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
1004 sm.getPDBResNum(index), atomNo));
1009 sl.highlightAtoms(atoms);
1013 * true if a mouse over event from an external (ie Vamsas) source is being
1016 boolean handlingVamsasMo = false;
1021 * as mouseOverSequence but only route event to SequenceListeners
1025 * in an alignment sequence
1027 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1028 VamsasSource source)
1030 handlingVamsasMo = true;
1031 long msg = sequenceI.hashCode() * (1 + position);
1035 mouseOverSequence(sequenceI, position, -1, source);
1037 handlingVamsasMo = false;
1040 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1044 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1045 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1047 * Annotation [] annotations = new Annotation[seq.getLength()];
1049 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1050 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1051 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1053 * for (int j = 0; j < mappings.length; j++) {
1055 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1056 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1057 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1058 * "+mappings[j].pdbfile);
1060 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1061 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1063 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1064 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1065 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1066 * mappings[j].pdbfile); }
1068 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1069 * annotations; } } } }
1071 * return annotations;
1075 public void structureSelectionChanged()
1079 public void sequenceSelectionChanged()
1083 public void sequenceColoursChanged(Object source)
1085 StructureListener sl;
1086 for (int i = 0; i < listeners.size(); i++)
1088 if (listeners.elementAt(i) instanceof StructureListener)
1090 sl = (StructureListener) listeners.elementAt(i);
1091 sl.updateColours(source);
1096 public StructureMapping[] getMapping(String pdbfile)
1098 List<StructureMapping> tmp = new ArrayList<>();
1099 for (StructureMapping sm : mappings)
1101 if (sm.pdbfile.equals(pdbfile))
1106 return tmp.toArray(new StructureMapping[tmp.size()]);
1110 * Returns a readable description of all mappings for the given pdbfile to any
1111 * of the given sequences
1117 public String printMappings(String pdbfile, List<SequenceI> seqs)
1119 if (pdbfile == null || seqs == null || seqs.isEmpty())
1124 StringBuilder sb = new StringBuilder(64);
1125 for (StructureMapping sm : mappings)
1127 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1129 sb.append(sm.mappingDetails);
1131 // separator makes it easier to read multiple mappings
1132 sb.append("=====================");
1138 return sb.toString();
1142 * Remove the given mapping
1146 public void deregisterMapping(AlignedCodonFrame acf)
1150 boolean removed = seqmappings.remove(acf);
1151 if (removed && seqmappings.isEmpty())
1153 System.out.println("All mappings removed");
1159 * Add each of the given codonFrames to the stored set, if not aready present.
1163 public void registerMappings(List<AlignedCodonFrame> mappings)
1165 if (mappings != null)
1167 for (AlignedCodonFrame acf : mappings)
1169 registerMapping(acf);
1175 * Add the given mapping to the stored set, unless already stored.
1177 public void registerMapping(AlignedCodonFrame acf)
1181 if (!seqmappings.contains(acf))
1183 seqmappings.add(acf);
1189 * Resets this object to its initial state by removing all registered
1190 * listeners, codon mappings, PDB file mappings
1192 public void resetAll()
1194 if (mappings != null)
1198 if (seqmappings != null)
1200 seqmappings.clear();
1202 if (sel_listeners != null)
1204 sel_listeners.clear();
1206 if (listeners != null)
1210 if (commandListeners != null)
1212 commandListeners.clear();
1214 if (view_listeners != null)
1216 view_listeners.clear();
1218 if (pdbFileNameId != null)
1220 pdbFileNameId.clear();
1222 if (pdbIdFileName != null)
1224 pdbIdFileName.clear();
1228 public void addSelectionListener(SelectionListener selecter)
1230 if (!sel_listeners.contains(selecter))
1232 sel_listeners.add(selecter);
1236 public void removeSelectionListener(SelectionListener toremove)
1238 if (sel_listeners.contains(toremove))
1240 sel_listeners.remove(toremove);
1244 public synchronized void sendSelection(
1245 jalview.datamodel.SequenceGroup selection,
1246 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1247 SelectionSource source)
1249 for (SelectionListener slis : sel_listeners)
1253 slis.selection(selection, colsel, hidden, source);
1258 Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
1260 public synchronized void sendViewPosition(
1261 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1262 int startSeq, int endSeq)
1265 if (view_listeners != null && view_listeners.size() > 0)
1267 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1269 while (listeners.hasMoreElements())
1271 AlignmentViewPanelListener slis = listeners.nextElement();
1274 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1282 * release all references associated with this manager provider
1284 * @param jalviewLite
1286 public static void release(StructureSelectionManagerProvider jalviewLite)
1288 // synchronized (instances)
1290 if (instances == null)
1294 StructureSelectionManager mnger = (instances.get(jalviewLite));
1297 instances.remove(jalviewLite);
1301 } catch (Throwable x)
1308 public void registerPDBEntry(PDBEntry pdbentry)
1310 if (pdbentry.getFile() != null
1311 && pdbentry.getFile().trim().length() > 0)
1313 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1317 public void addCommandListener(CommandListener cl)
1319 if (!commandListeners.contains(cl))
1321 commandListeners.add(cl);
1325 public boolean hasCommandListener(CommandListener cl)
1327 return this.commandListeners.contains(cl);
1330 public boolean removeCommandListener(CommandListener l)
1332 return commandListeners.remove(l);
1336 * Forward a command to any command listeners (except for the command's
1340 * the command to be broadcast (in its form after being performed)
1342 * if true, the command was being 'undone'
1345 public void commandPerformed(CommandI command, boolean undo,
1346 VamsasSource source)
1348 for (CommandListener listener : commandListeners)
1350 listener.mirrorCommand(command, undo, this, source);
1355 * Returns a new CommandI representing the given command as mapped to the
1356 * given sequences. If no mapping could be made, or the command is not of a
1357 * mappable kind, returns null.
1365 public CommandI mapCommand(CommandI command, boolean undo,
1366 final AlignmentI mapTo, char gapChar)
1368 if (command instanceof EditCommand)
1370 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1371 gapChar, seqmappings);
1373 else if (command instanceof OrderCommand)
1375 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1376 mapTo, seqmappings);
1381 public List<AlignedCodonFrame> getSequenceMappings()