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 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
401 pdb = new JmolParser(pdbFile, sourceType);
403 if (pdb.getId() != null && pdb.getId().trim().length() > 0
404 && DataSourceType.FILE == sourceType)
406 registerPDBFile(pdb.getId().trim(), pdbFile);
408 // if PDBId is unavailable then skip SIFTS mapping execution path
409 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
411 } catch (Exception ex)
413 ex.printStackTrace();
421 siftsClient = new SiftsClient(pdb);
423 } catch (SiftsException e)
425 isMapUsingSIFTs = false;
429 String targetChainId;
430 for (int s = 0; s < sequenceArray.length; s++)
432 boolean infChain = true;
433 final SequenceI seq = sequenceArray[s];
435 while (ds.getDatasetSequence() != null)
437 ds = ds.getDatasetSequence();
440 if (targetChainIds != null && targetChainIds[s] != null)
443 targetChainId = targetChainIds[s];
445 else if (seq.getName().indexOf("|") > -1)
447 targetChainId = seq.getName()
448 .substring(seq.getName().lastIndexOf("|") + 1);
449 if (targetChainId.length() > 1)
451 if (targetChainId.trim().length() == 0)
457 // not a valid chain identifier
468 * Attempt pairwise alignment of the sequence with each chain in the PDB,
469 * and remember the highest scoring chain
472 AlignSeq maxAlignseq = null;
473 String maxChainId = " ";
474 PDBChain maxChain = null;
475 boolean first = true;
476 for (PDBChain chain : pdb.getChains())
478 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
481 continue; // don't try to map chains don't match.
483 // TODO: correctly determine sequence type for mixed na/peptide
485 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
486 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
489 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
490 // as.calcScoreMatrix();
491 // as.traceAlignment();
493 if (first || as.maxscore > max
494 || (as.maxscore == max && chain.id.equals(targetChainId)))
500 maxChainId = chain.id;
503 if (maxChain == null)
508 if (sourceType == DataSourceType.PASTE)
510 pdbFile = "INLINE" + pdb.getId();
513 List<StructureMapping> seqToStrucMapping = new ArrayList<>();
514 if (isMapUsingSIFTs && seq.isProtein())
516 if (progress!=null) {
517 progress.setProgressBar(MessageManager
518 .getString("status.obtaining_mapping_with_sifts"),
521 jalview.datamodel.Mapping sqmpping = maxAlignseq
522 .getMappingFromS1(false);
523 if (targetChainId != null && !targetChainId.trim().isEmpty())
525 StructureMapping siftsMapping;
528 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
529 pdb, maxChain, sqmpping, maxAlignseq);
530 seqToStrucMapping.add(siftsMapping);
531 maxChain.makeExactMapping(siftsMapping, seq);
532 maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
534 maxChain.transferResidueAnnotation(siftsMapping, null);
535 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
537 } catch (SiftsException e)
539 // fall back to NW alignment
540 System.err.println(e.getMessage());
541 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
542 targetChainId, maxChain, pdb, maxAlignseq);
543 seqToStrucMapping.add(nwMapping);
544 maxChain.makeExactMapping(maxAlignseq, seq);
545 maxChain.transferRESNUMFeatures(seq, "IEA:Jalview"); // FIXME: is
548 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
549 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
554 List<StructureMapping> foundSiftsMappings = new ArrayList<>();
555 for (PDBChain chain : pdb.getChains())
557 StructureMapping siftsMapping = null;
560 siftsMapping = getStructureMapping(seq,
561 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
562 foundSiftsMappings.add(siftsMapping);
563 chain.makeExactMapping(siftsMapping, seq);
564 chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
566 chain.transferResidueAnnotation(siftsMapping, null);
567 } catch (SiftsException e)
569 System.err.println(e.getMessage());
572 if (!foundSiftsMappings.isEmpty())
574 seqToStrucMapping.addAll(foundSiftsMappings);
575 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
579 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
580 maxChainId, maxChain, pdb, maxAlignseq);
581 seqToStrucMapping.add(nwMapping);
582 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
584 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
585 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
591 if (progress != null)
593 progress.setProgressBar(MessageManager
594 .getString("status.obtaining_mapping_with_nw_alignment"),
597 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
598 maxChain, pdb, maxAlignseq);
599 seqToStrucMapping.add(nwMapping);
600 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
602 if (forStructureView)
604 mappings.addAll(seqToStrucMapping);
606 if (progress != null)
608 progress.setProgressBar(null, progressSessionId);
615 * check if we need to extract secondary structure from given pdbFile and
616 * transfer to sequences
619 * @param sequenceArray
622 private boolean isStructureFileProcessed(String pdbFile,
623 SequenceI[] sequenceArray)
625 boolean parseSecStr = true;
626 if (isPDBFileRegistered(pdbFile))
628 for (SequenceI sq : sequenceArray)
631 while (ds.getDatasetSequence() != null)
633 ds = ds.getDatasetSequence();
636 if (ds.getAnnotation() != null)
638 for (AlignmentAnnotation ala : ds.getAnnotation())
640 // false if any annotation present from this structure
641 // JBPNote this fails for jmol/chimera view because the *file* is
642 // passed, not the structure data ID -
643 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
654 public void addStructureMapping(StructureMapping sm)
660 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
665 * @param targetChainId
671 * @throws SiftsException
673 private StructureMapping getStructureMapping(SequenceI seq,
674 String pdbFile, String targetChainId, StructureFile pdb,
675 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
676 AlignSeq maxAlignseq) throws SiftsException
678 StructureMapping curChainMapping = siftsClient
679 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
682 PDBChain chain = pdb.findChain(targetChainId);
685 chain.transferResidueAnnotation(curChainMapping, null);
687 } catch (Exception e)
691 return curChainMapping;
694 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
695 String maxChainId, PDBChain maxChain, StructureFile pdb,
696 AlignSeq maxAlignseq)
698 final StringBuilder mappingDetails = new StringBuilder(128);
699 mappingDetails.append(NEWLINE)
700 .append("Sequence \u27f7 Structure mapping details");
701 mappingDetails.append(NEWLINE);
703 .append("Method: inferred with Needleman & Wunsch alignment");
704 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
705 .append(NEWLINE).append("Sequence = ")
706 .append(maxChain.sequence.getSequenceAsString());
707 mappingDetails.append(NEWLINE).append("No of residues = ")
708 .append(maxChain.residues.size()).append(NEWLINE)
710 PrintStream ps = new PrintStream(System.out)
713 public void print(String x)
715 mappingDetails.append(x);
719 public void println()
721 mappingDetails.append(NEWLINE);
725 maxAlignseq.printAlignment(ps);
727 mappingDetails.append(NEWLINE).append("PDB start/end ");
728 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
730 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
731 mappingDetails.append(NEWLINE).append("SEQ start/end ");
734 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
736 mappingDetails.append(
737 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
738 mappingDetails.append(NEWLINE);
739 maxChain.makeExactMapping(maxAlignseq, seq);
740 jalview.datamodel.Mapping sqmpping = maxAlignseq
741 .getMappingFromS1(false);
742 maxChain.transferRESNUMFeatures(seq, null);
744 HashMap<Integer, int[]> mapping = new HashMap<>();
751 Atom tmp = maxChain.atoms.elementAt(index);
752 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
753 && tmp.alignmentMapping != -1)
755 resNum = tmp.resNumber;
756 insCode = tmp.insCode;
757 if (tmp.alignmentMapping >= -1)
759 mapping.put(tmp.alignmentMapping + 1,
761 { tmp.resNumber, tmp.atomIndex });
766 } while (index < maxChain.atoms.size());
768 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
769 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
770 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
774 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
776 listeners.removeElement(svl);
777 if (svl instanceof SequenceListener)
779 for (int i = 0; i < listeners.size(); i++)
781 if (listeners.elementAt(i) instanceof StructureListener)
783 ((StructureListener) listeners.elementAt(i))
784 .releaseReferences(svl);
789 if (pdbfiles == null)
795 * Remove mappings to the closed listener's PDB files, but first check if
796 * another listener is still interested
798 List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
800 StructureListener sl;
801 for (int i = 0; i < listeners.size(); i++)
803 if (listeners.elementAt(i) instanceof StructureListener)
805 sl = (StructureListener) listeners.elementAt(i);
806 for (String pdbfile : sl.getStructureFiles())
808 pdbs.remove(pdbfile);
814 * Rebuild the mappings set, retaining only those which are for 'other' PDB
819 List<StructureMapping> tmp = new ArrayList<>();
820 for (StructureMapping sm : mappings)
822 if (!pdbs.contains(sm.pdbfile))
833 * Propagate mouseover of a single position in a structure
839 public void mouseOverStructure(int pdbResNum, String chain,
842 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
843 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
844 mouseOverStructure(atoms);
848 * Propagate mouseover or selection of multiple positions in a structure
852 public void mouseOverStructure(List<AtomSpec> atoms)
854 if (listeners == null)
856 // old or prematurely sent event
859 boolean hasSequenceListener = false;
860 for (int i = 0; i < listeners.size(); i++)
862 if (listeners.elementAt(i) instanceof SequenceListener)
864 hasSequenceListener = true;
867 if (!hasSequenceListener)
872 SearchResultsI results = findAlignmentPositionsForStructurePositions(
874 for (Object li : listeners)
876 if (li instanceof SequenceListener)
878 ((SequenceListener) li).highlightSequence(results);
884 * Constructs a SearchResults object holding regions (if any) in the Jalview
885 * alignment which have a mapping to the structure viewer positions in the
891 public SearchResultsI findAlignmentPositionsForStructurePositions(
892 List<AtomSpec> atoms)
894 SearchResultsI results = new SearchResults();
895 for (AtomSpec atom : atoms)
897 SequenceI lastseq = null;
899 for (StructureMapping sm : mappings)
901 if (sm.pdbfile.equals(atom.getPdbFile())
902 && sm.pdbchain.equals(atom.getChain()))
904 int indexpos = sm.getSeqPos(atom.getPdbResNum());
905 if (lastipos != indexpos || lastseq != sm.sequence)
907 results.addResult(sm.sequence, indexpos, indexpos);
909 lastseq = sm.sequence;
910 // construct highlighted sequence list
911 for (AlignedCodonFrame acf : seqmappings)
913 acf.markMappedRegion(sm.sequence, indexpos, results);
923 * highlight regions associated with a position (indexpos) in seq
926 * the sequence that the mouse over occurred on
928 * the absolute position being mouseovered in seq (0 to seq.length())
930 * the sequence position (if -1, seq.findPosition is called to
931 * resolve the residue number)
933 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
936 boolean hasSequenceListeners = handlingVamsasMo
937 || !seqmappings.isEmpty();
938 SearchResultsI results = null;
941 seqPos = seq.findPosition(indexpos);
943 for (int i = 0; i < listeners.size(); i++)
945 Object listener = listeners.elementAt(i);
946 if (listener == source)
948 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
949 // Temporary fudge with SequenceListener.getVamsasSource()
952 if (listener instanceof StructureListener)
954 highlightStructure((StructureListener) listener, seq, seqPos);
958 if (listener instanceof SequenceListener)
960 final SequenceListener seqListener = (SequenceListener) listener;
961 if (hasSequenceListeners
962 && seqListener.getVamsasSource() != source)
964 if (relaySeqMappings)
968 results = MappingUtils.buildSearchResults(seq, seqPos,
971 if (handlingVamsasMo)
973 results.addResult(seq, seqPos, seqPos);
976 if (!results.isEmpty())
978 seqListener.highlightSequence(results);
983 else if (listener instanceof VamsasListener && !handlingVamsasMo)
985 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
988 else if (listener instanceof SecondaryStructureListener)
990 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
998 * Send suitable messages to a StructureListener to highlight atoms
999 * corresponding to the given sequence position(s)
1005 public void highlightStructure(StructureListener sl, SequenceI seq,
1008 if (!sl.isListeningFor(seq))
1013 List<AtomSpec> atoms = new ArrayList<>();
1014 for (StructureMapping sm : mappings)
1016 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
1017 || (sm.sequence.getDatasetSequence() != null && sm.sequence
1018 .getDatasetSequence() == seq.getDatasetSequence()))
1020 for (int index : positions)
1022 atomNo = sm.getAtomNum(index);
1026 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
1027 sm.getPDBResNum(index), atomNo));
1032 sl.highlightAtoms(atoms);
1036 * true if a mouse over event from an external (ie Vamsas) source is being
1039 boolean handlingVamsasMo = false;
1044 * as mouseOverSequence but only route event to SequenceListeners
1048 * in an alignment sequence
1050 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1051 VamsasSource source)
1053 handlingVamsasMo = true;
1054 long msg = sequenceI.hashCode() * (1 + position);
1058 mouseOverSequence(sequenceI, position, -1, source);
1060 handlingVamsasMo = false;
1063 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1067 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1068 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1070 * Annotation [] annotations = new Annotation[seq.getLength()];
1072 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1073 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1074 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1076 * for (int j = 0; j < mappings.length; j++) {
1078 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1079 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1080 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1081 * "+mappings[j].pdbfile);
1083 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1084 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1086 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1087 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1088 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1089 * mappings[j].pdbfile); }
1091 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1092 * annotations; } } } }
1094 * return annotations;
1098 public void structureSelectionChanged()
1102 public void sequenceSelectionChanged()
1106 public void sequenceColoursChanged(Object source)
1108 StructureListener sl;
1109 for (int i = 0; i < listeners.size(); i++)
1111 if (listeners.elementAt(i) instanceof StructureListener)
1113 sl = (StructureListener) listeners.elementAt(i);
1114 sl.updateColours(source);
1119 public StructureMapping[] getMapping(String pdbfile)
1121 List<StructureMapping> tmp = new ArrayList<>();
1122 for (StructureMapping sm : mappings)
1124 if (sm.pdbfile.equals(pdbfile))
1129 return tmp.toArray(new StructureMapping[tmp.size()]);
1133 * Returns a readable description of all mappings for the given pdbfile to any
1134 * of the given sequences
1140 public String printMappings(String pdbfile, List<SequenceI> seqs)
1142 if (pdbfile == null || seqs == null || seqs.isEmpty())
1147 StringBuilder sb = new StringBuilder(64);
1148 for (StructureMapping sm : mappings)
1150 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1152 sb.append(sm.mappingDetails);
1154 // separator makes it easier to read multiple mappings
1155 sb.append("=====================");
1161 return sb.toString();
1165 * Remove the given mapping
1169 public void deregisterMapping(AlignedCodonFrame acf)
1173 boolean removed = seqmappings.remove(acf);
1174 if (removed && seqmappings.isEmpty())
1176 System.out.println("All mappings removed");
1182 * Add each of the given codonFrames to the stored set, if not aready present.
1186 public void registerMappings(List<AlignedCodonFrame> mappings)
1188 if (mappings != null)
1190 for (AlignedCodonFrame acf : mappings)
1192 registerMapping(acf);
1198 * Add the given mapping to the stored set, unless already stored.
1200 public void registerMapping(AlignedCodonFrame acf)
1204 if (!seqmappings.contains(acf))
1206 seqmappings.add(acf);
1212 * Resets this object to its initial state by removing all registered
1213 * listeners, codon mappings, PDB file mappings
1215 public void resetAll()
1217 if (mappings != null)
1221 if (seqmappings != null)
1223 seqmappings.clear();
1225 if (sel_listeners != null)
1227 sel_listeners.clear();
1229 if (listeners != null)
1233 if (commandListeners != null)
1235 commandListeners.clear();
1237 if (view_listeners != null)
1239 view_listeners.clear();
1241 if (pdbFileNameId != null)
1243 pdbFileNameId.clear();
1245 if (pdbIdFileName != null)
1247 pdbIdFileName.clear();
1251 public void addSelectionListener(SelectionListener selecter)
1253 if (!sel_listeners.contains(selecter))
1255 sel_listeners.add(selecter);
1259 public void removeSelectionListener(SelectionListener toremove)
1261 if (sel_listeners.contains(toremove))
1263 sel_listeners.remove(toremove);
1267 public synchronized void sendSelection(
1268 jalview.datamodel.SequenceGroup selection,
1269 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1270 SelectionSource source)
1272 for (SelectionListener slis : sel_listeners)
1276 slis.selection(selection, colsel, hidden, source);
1281 Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
1283 public synchronized void sendViewPosition(
1284 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1285 int startSeq, int endSeq)
1288 if (view_listeners != null && view_listeners.size() > 0)
1290 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1292 while (listeners.hasMoreElements())
1294 AlignmentViewPanelListener slis = listeners.nextElement();
1297 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1305 * release all references associated with this manager provider
1307 * @param jalviewLite
1309 public static void release(StructureSelectionManagerProvider jalviewLite)
1311 // synchronized (instances)
1313 if (instances == null)
1317 StructureSelectionManager mnger = (instances.get(jalviewLite));
1320 instances.remove(jalviewLite);
1324 } catch (Throwable x)
1331 public void registerPDBEntry(PDBEntry pdbentry)
1333 if (pdbentry.getFile() != null
1334 && pdbentry.getFile().trim().length() > 0)
1336 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1340 public void addCommandListener(CommandListener cl)
1342 if (!commandListeners.contains(cl))
1344 commandListeners.add(cl);
1348 public boolean hasCommandListener(CommandListener cl)
1350 return this.commandListeners.contains(cl);
1353 public boolean removeCommandListener(CommandListener l)
1355 return commandListeners.remove(l);
1359 * Forward a command to any command listeners (except for the command's
1363 * the command to be broadcast (in its form after being performed)
1365 * if true, the command was being 'undone'
1368 public void commandPerformed(CommandI command, boolean undo,
1369 VamsasSource source)
1371 for (CommandListener listener : commandListeners)
1373 listener.mirrorCommand(command, undo, this, source);
1378 * Returns a new CommandI representing the given command as mapped to the
1379 * given sequences. If no mapping could be made, or the command is not of a
1380 * mappable kind, returns null.
1388 public CommandI mapCommand(CommandI command, boolean undo,
1389 final AlignmentI mapTo, char gapChar)
1391 if (command instanceof EditCommand)
1393 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1394 gapChar, seqmappings);
1396 else if (command instanceof OrderCommand)
1398 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1399 mapTo, seqmappings);
1404 public List<AlignedCodonFrame> getSequenceMappings()