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;
388 * do we extract and transfer annotation from 3D data ?
390 // FIXME: possibly should just delete
392 boolean parseSecStr = processSecondaryStructure
393 ? isStructureFileProcessed(pdbFile, sequenceArray)
396 StructureFile pdb = null;
397 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
400 // FIXME if sourceType is not null, we've lost data here
401 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
402 pdb = new JmolParser(pdbFile, sourceType);
404 if (pdb.getId() != null && pdb.getId().trim().length() > 0
405 && DataSourceType.FILE == sourceType)
407 registerPDBFile(pdb.getId().trim(), pdbFile);
409 // if PDBId is unavailable then skip SIFTS mapping execution path
410 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
412 } catch (Exception ex)
414 ex.printStackTrace();
422 siftsClient = new SiftsClient(pdb);
424 } catch (SiftsException e)
426 isMapUsingSIFTs = false;
430 String targetChainId;
431 for (int s = 0; s < sequenceArray.length; s++)
433 boolean infChain = true;
434 final SequenceI seq = sequenceArray[s];
436 while (ds.getDatasetSequence() != null)
438 ds = ds.getDatasetSequence();
441 if (targetChainIds != null && targetChainIds[s] != null)
444 targetChainId = targetChainIds[s];
446 else if (seq.getName().indexOf("|") > -1)
448 targetChainId = seq.getName()
449 .substring(seq.getName().lastIndexOf("|") + 1);
450 if (targetChainId.length() > 1)
452 if (targetChainId.trim().length() == 0)
458 // not a valid chain identifier
469 * Attempt pairwise alignment of the sequence with each chain in the PDB,
470 * and remember the highest scoring chain
473 AlignSeq maxAlignseq = null;
474 String maxChainId = " ";
475 PDBChain maxChain = null;
476 boolean first = true;
477 for (PDBChain chain : pdb.getChains())
479 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
482 continue; // don't try to map chains don't match.
484 // TODO: correctly determine sequence type for mixed na/peptide
486 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
487 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
490 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
491 // as.calcScoreMatrix();
492 // as.traceAlignment();
494 if (first || as.maxscore > max
495 || (as.maxscore == max && chain.id.equals(targetChainId)))
501 maxChainId = chain.id;
504 if (maxChain == null)
509 if (sourceType == DataSourceType.PASTE)
511 pdbFile = "INLINE" + pdb.getId();
514 List<StructureMapping> seqToStrucMapping = new ArrayList<>();
515 if (isMapUsingSIFTs && seq.isProtein())
517 if (progress!=null) {
518 progress.setProgressBar(MessageManager
519 .getString("status.obtaining_mapping_with_sifts"),
522 jalview.datamodel.Mapping sqmpping = maxAlignseq
523 .getMappingFromS1(false);
524 if (targetChainId != null && !targetChainId.trim().isEmpty())
526 StructureMapping siftsMapping;
529 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
530 pdb, maxChain, sqmpping, maxAlignseq);
531 seqToStrucMapping.add(siftsMapping);
532 maxChain.makeExactMapping(siftsMapping, seq);
533 maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
535 maxChain.transferResidueAnnotation(siftsMapping, null);
536 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
538 } catch (SiftsException e)
540 // fall back to NW alignment
541 System.err.println(e.getMessage());
542 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
543 targetChainId, maxChain, pdb, maxAlignseq);
544 seqToStrucMapping.add(nwMapping);
545 maxChain.makeExactMapping(maxAlignseq, seq);
546 maxChain.transferRESNUMFeatures(seq, "IEA:Jalview"); // FIXME: is
549 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
550 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
555 List<StructureMapping> foundSiftsMappings = new ArrayList<>();
556 for (PDBChain chain : pdb.getChains())
558 StructureMapping siftsMapping = null;
561 siftsMapping = getStructureMapping(seq,
562 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
563 foundSiftsMappings.add(siftsMapping);
564 chain.makeExactMapping(siftsMapping, seq);
565 chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
567 chain.transferResidueAnnotation(siftsMapping, null);
568 } catch (SiftsException e)
570 System.err.println(e.getMessage());
573 if (!foundSiftsMappings.isEmpty())
575 seqToStrucMapping.addAll(foundSiftsMappings);
576 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
580 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
581 maxChainId, maxChain, pdb, maxAlignseq);
582 seqToStrucMapping.add(nwMapping);
583 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
585 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
586 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
592 if (progress != null)
594 progress.setProgressBar(MessageManager
595 .getString("status.obtaining_mapping_with_nw_alignment"),
598 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
599 maxChain, pdb, maxAlignseq);
600 seqToStrucMapping.add(nwMapping);
601 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
603 if (forStructureView)
605 mappings.addAll(seqToStrucMapping);
607 if (progress != null)
609 progress.setProgressBar(null, progressSessionId);
616 * check if we need to extract secondary structure from given pdbFile and
617 * transfer to sequences
620 * @param sequenceArray
623 private boolean isStructureFileProcessed(String pdbFile,
624 SequenceI[] sequenceArray)
626 boolean parseSecStr = true;
627 if (isPDBFileRegistered(pdbFile))
629 for (SequenceI sq : sequenceArray)
632 while (ds.getDatasetSequence() != null)
634 ds = ds.getDatasetSequence();
637 if (ds.getAnnotation() != null)
639 for (AlignmentAnnotation ala : ds.getAnnotation())
641 // false if any annotation present from this structure
642 // JBPNote this fails for jmol/chimera view because the *file* is
643 // passed, not the structure data ID -
644 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
655 public void addStructureMapping(StructureMapping sm)
661 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
666 * @param targetChainId
672 * @throws SiftsException
674 private StructureMapping getStructureMapping(SequenceI seq,
675 String pdbFile, String targetChainId, StructureFile pdb,
676 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
677 AlignSeq maxAlignseq) throws SiftsException
679 StructureMapping curChainMapping = siftsClient
680 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
683 PDBChain chain = pdb.findChain(targetChainId);
686 chain.transferResidueAnnotation(curChainMapping, null);
688 } catch (Exception e)
692 return curChainMapping;
695 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
696 String maxChainId, PDBChain maxChain, StructureFile pdb,
697 AlignSeq maxAlignseq)
699 final StringBuilder mappingDetails = new StringBuilder(128);
700 mappingDetails.append(NEWLINE)
701 .append("Sequence \u27f7 Structure mapping details");
702 mappingDetails.append(NEWLINE);
704 .append("Method: inferred with Needleman & Wunsch alignment");
705 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
706 .append(NEWLINE).append("Sequence = ")
707 .append(maxChain.sequence.getSequenceAsString());
708 mappingDetails.append(NEWLINE).append("No of residues = ")
709 .append(maxChain.residues.size()).append(NEWLINE)
711 PrintStream ps = new PrintStream(System.out)
714 public void print(String x)
716 mappingDetails.append(x);
720 public void println()
722 mappingDetails.append(NEWLINE);
726 maxAlignseq.printAlignment(ps);
728 mappingDetails.append(NEWLINE).append("PDB start/end ");
729 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
731 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
732 mappingDetails.append(NEWLINE).append("SEQ start/end ");
735 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
737 mappingDetails.append(
738 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
739 mappingDetails.append(NEWLINE);
740 maxChain.makeExactMapping(maxAlignseq, seq);
741 jalview.datamodel.Mapping sqmpping = maxAlignseq
742 .getMappingFromS1(false);
743 maxChain.transferRESNUMFeatures(seq, null);
745 HashMap<Integer, int[]> mapping = new HashMap<>();
752 Atom tmp = maxChain.atoms.elementAt(index);
753 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
754 && tmp.alignmentMapping != -1)
756 resNum = tmp.resNumber;
757 insCode = tmp.insCode;
758 if (tmp.alignmentMapping >= -1)
760 mapping.put(tmp.alignmentMapping + 1,
762 { tmp.resNumber, tmp.atomIndex });
767 } while (index < maxChain.atoms.size());
769 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
770 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
771 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
775 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
777 listeners.removeElement(svl);
778 if (svl instanceof SequenceListener)
780 for (int i = 0; i < listeners.size(); i++)
782 if (listeners.elementAt(i) instanceof StructureListener)
784 ((StructureListener) listeners.elementAt(i))
785 .releaseReferences(svl);
790 if (pdbfiles == null)
796 * Remove mappings to the closed listener's PDB files, but first check if
797 * another listener is still interested
799 List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
801 StructureListener sl;
802 for (int i = 0; i < listeners.size(); i++)
804 if (listeners.elementAt(i) instanceof StructureListener)
806 sl = (StructureListener) listeners.elementAt(i);
807 for (String pdbfile : sl.getStructureFiles())
809 pdbs.remove(pdbfile);
815 * Rebuild the mappings set, retaining only those which are for 'other' PDB
820 List<StructureMapping> tmp = new ArrayList<>();
821 for (StructureMapping sm : mappings)
823 if (!pdbs.contains(sm.pdbfile))
834 * Propagate mouseover of a single position in a structure
840 public void mouseOverStructure(int pdbResNum, String chain,
843 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
844 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
845 mouseOverStructure(atoms);
849 * Propagate mouseover or selection of multiple positions in a structure
853 public void mouseOverStructure(List<AtomSpec> atoms)
855 if (listeners == null)
857 // old or prematurely sent event
860 boolean hasSequenceListener = false;
861 for (int i = 0; i < listeners.size(); i++)
863 if (listeners.elementAt(i) instanceof SequenceListener)
865 hasSequenceListener = true;
868 if (!hasSequenceListener)
873 SearchResultsI results = findAlignmentPositionsForStructurePositions(
875 for (Object li : listeners)
877 if (li instanceof SequenceListener)
879 ((SequenceListener) li).highlightSequence(results);
885 * Constructs a SearchResults object holding regions (if any) in the Jalview
886 * alignment which have a mapping to the structure viewer positions in the
892 public SearchResultsI findAlignmentPositionsForStructurePositions(
893 List<AtomSpec> atoms)
895 SearchResultsI results = new SearchResults();
896 for (AtomSpec atom : atoms)
898 SequenceI lastseq = null;
900 for (StructureMapping sm : mappings)
902 if (sm.pdbfile.equals(atom.getPdbFile())
903 && sm.pdbchain.equals(atom.getChain()))
905 int indexpos = sm.getSeqPos(atom.getPdbResNum());
906 if (lastipos != indexpos || lastseq != sm.sequence)
908 results.addResult(sm.sequence, indexpos, indexpos);
910 lastseq = sm.sequence;
911 // construct highlighted sequence list
912 for (AlignedCodonFrame acf : seqmappings)
914 acf.markMappedRegion(sm.sequence, indexpos, results);
924 * highlight regions associated with a position (indexpos) in seq
927 * the sequence that the mouse over occurred on
929 * the absolute position being mouseovered in seq (0 to seq.length())
931 * the sequence position (if -1, seq.findPosition is called to
932 * resolve the residue number)
934 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
937 boolean hasSequenceListeners = handlingVamsasMo
938 || !seqmappings.isEmpty();
939 SearchResultsI results = null;
942 seqPos = seq.findPosition(indexpos);
944 for (int i = 0; i < listeners.size(); i++)
946 Object listener = listeners.elementAt(i);
947 if (listener == source)
949 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
950 // Temporary fudge with SequenceListener.getVamsasSource()
953 if (listener instanceof StructureListener)
955 highlightStructure((StructureListener) listener, seq, seqPos);
959 if (listener instanceof SequenceListener)
961 final SequenceListener seqListener = (SequenceListener) listener;
962 if (hasSequenceListeners
963 && seqListener.getVamsasSource() != source)
965 if (relaySeqMappings)
969 results = MappingUtils.buildSearchResults(seq, seqPos,
972 if (handlingVamsasMo)
974 results.addResult(seq, seqPos, seqPos);
977 if (!results.isEmpty())
979 seqListener.highlightSequence(results);
984 else if (listener instanceof VamsasListener && !handlingVamsasMo)
986 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
989 else if (listener instanceof SecondaryStructureListener)
991 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
999 * Send suitable messages to a StructureListener to highlight atoms
1000 * corresponding to the given sequence position(s)
1006 public void highlightStructure(StructureListener sl, SequenceI seq,
1009 if (!sl.isListeningFor(seq))
1014 List<AtomSpec> atoms = new ArrayList<>();
1015 for (StructureMapping sm : mappings)
1017 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
1018 || (sm.sequence.getDatasetSequence() != null && sm.sequence
1019 .getDatasetSequence() == seq.getDatasetSequence()))
1021 for (int index : positions)
1023 atomNo = sm.getAtomNum(index);
1027 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
1028 sm.getPDBResNum(index), atomNo));
1033 sl.highlightAtoms(atoms);
1037 * true if a mouse over event from an external (ie Vamsas) source is being
1040 boolean handlingVamsasMo = false;
1045 * as mouseOverSequence but only route event to SequenceListeners
1049 * in an alignment sequence
1051 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1052 VamsasSource source)
1054 handlingVamsasMo = true;
1055 long msg = sequenceI.hashCode() * (1 + position);
1059 mouseOverSequence(sequenceI, position, -1, source);
1061 handlingVamsasMo = false;
1064 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1068 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1069 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1071 * Annotation [] annotations = new Annotation[seq.getLength()];
1073 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1074 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1075 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1077 * for (int j = 0; j < mappings.length; j++) {
1079 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1080 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1081 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1082 * "+mappings[j].pdbfile);
1084 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1085 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1087 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1088 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1089 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1090 * mappings[j].pdbfile); }
1092 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1093 * annotations; } } } }
1095 * return annotations;
1099 public void structureSelectionChanged()
1103 public void sequenceSelectionChanged()
1107 public void sequenceColoursChanged(Object source)
1109 StructureListener sl;
1110 for (int i = 0; i < listeners.size(); i++)
1112 if (listeners.elementAt(i) instanceof StructureListener)
1114 sl = (StructureListener) listeners.elementAt(i);
1115 sl.updateColours(source);
1120 public StructureMapping[] getMapping(String pdbfile)
1122 List<StructureMapping> tmp = new ArrayList<>();
1123 for (StructureMapping sm : mappings)
1125 if (sm.pdbfile.equals(pdbfile))
1130 return tmp.toArray(new StructureMapping[tmp.size()]);
1134 * Returns a readable description of all mappings for the given pdbfile to any
1135 * of the given sequences
1141 public String printMappings(String pdbfile, List<SequenceI> seqs)
1143 if (pdbfile == null || seqs == null || seqs.isEmpty())
1148 StringBuilder sb = new StringBuilder(64);
1149 for (StructureMapping sm : mappings)
1151 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1153 sb.append(sm.mappingDetails);
1155 // separator makes it easier to read multiple mappings
1156 sb.append("=====================");
1162 return sb.toString();
1166 * Remove the given mapping
1170 public void deregisterMapping(AlignedCodonFrame acf)
1174 boolean removed = seqmappings.remove(acf);
1175 if (removed && seqmappings.isEmpty())
1177 System.out.println("All mappings removed");
1183 * Add each of the given codonFrames to the stored set, if not aready present.
1187 public void registerMappings(List<AlignedCodonFrame> mappings)
1189 if (mappings != null)
1191 for (AlignedCodonFrame acf : mappings)
1193 registerMapping(acf);
1199 * Add the given mapping to the stored set, unless already stored.
1201 public void registerMapping(AlignedCodonFrame acf)
1205 if (!seqmappings.contains(acf))
1207 seqmappings.add(acf);
1213 * Resets this object to its initial state by removing all registered
1214 * listeners, codon mappings, PDB file mappings
1216 public void resetAll()
1218 if (mappings != null)
1222 if (seqmappings != null)
1224 seqmappings.clear();
1226 if (sel_listeners != null)
1228 sel_listeners.clear();
1230 if (listeners != null)
1234 if (commandListeners != null)
1236 commandListeners.clear();
1238 if (view_listeners != null)
1240 view_listeners.clear();
1242 if (pdbFileNameId != null)
1244 pdbFileNameId.clear();
1246 if (pdbIdFileName != null)
1248 pdbIdFileName.clear();
1252 public void addSelectionListener(SelectionListener selecter)
1254 if (!sel_listeners.contains(selecter))
1256 sel_listeners.add(selecter);
1260 public void removeSelectionListener(SelectionListener toremove)
1262 if (sel_listeners.contains(toremove))
1264 sel_listeners.remove(toremove);
1268 public synchronized void sendSelection(
1269 jalview.datamodel.SequenceGroup selection,
1270 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1271 SelectionSource source)
1273 for (SelectionListener slis : sel_listeners)
1277 slis.selection(selection, colsel, hidden, source);
1282 Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
1284 public synchronized void sendViewPosition(
1285 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1286 int startSeq, int endSeq)
1289 if (view_listeners != null && view_listeners.size() > 0)
1291 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1293 while (listeners.hasMoreElements())
1295 AlignmentViewPanelListener slis = listeners.nextElement();
1298 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1306 * release all references associated with this manager provider
1308 * @param jalviewLite
1310 public static void release(StructureSelectionManagerProvider jalviewLite)
1312 // synchronized (instances)
1314 if (instances == null)
1318 StructureSelectionManager mnger = (instances.get(jalviewLite));
1321 instances.remove(jalviewLite);
1325 } catch (Throwable x)
1332 public void registerPDBEntry(PDBEntry pdbentry)
1334 if (pdbentry.getFile() != null
1335 && pdbentry.getFile().trim().length() > 0)
1337 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1341 public void addCommandListener(CommandListener cl)
1343 if (!commandListeners.contains(cl))
1345 commandListeners.add(cl);
1349 public boolean hasCommandListener(CommandListener cl)
1351 return this.commandListeners.contains(cl);
1354 public boolean removeCommandListener(CommandListener l)
1356 return commandListeners.remove(l);
1360 * Forward a command to any command listeners (except for the command's
1364 * the command to be broadcast (in its form after being performed)
1366 * if true, the command was being 'undone'
1369 public void commandPerformed(CommandI command, boolean undo,
1370 VamsasSource source)
1372 for (CommandListener listener : commandListeners)
1374 listener.mirrorCommand(command, undo, this, source);
1379 * Returns a new CommandI representing the given command as mapped to the
1380 * given sequences. If no mapping could be made, or the command is not of a
1381 * mappable kind, returns null.
1389 public CommandI mapCommand(CommandI command, boolean undo,
1390 final AlignmentI mapTo, char gapChar)
1392 if (command instanceof EditCommand)
1394 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1395 gapChar, seqmappings);
1397 else if (command instanceof OrderCommand)
1399 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1400 mapTo, seqmappings);
1405 public List<AlignedCodonFrame> getSequenceMappings()