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 * create sequence structure mappings between each sequence and the given
332 * pdbFile (retrieved via the given protocol).
334 * @param forStructureView
335 * when true, record the mapping for use in mouseOvers
337 * @param sequenceArray
338 * - one or more sequences to be mapped to pdbFile
339 * @param targetChainIds
340 * - optional chain specification for mapping each sequence to pdb
341 * (may be nill, individual elements may be nill) - JBPNote: JAL-2693
342 * - this should be List<List<String>>, empty lists indicate no
343 * predefined mappings
345 * - structure data resource
347 * - how to resolve data from resource
348 * @return null or the structure data parsed as a pdb file
350 synchronized public StructureFile setMapping(boolean forStructureView,
351 SequenceI[] sequenceArray, String[] targetChainIds,
352 String pdbFile, DataSourceType sourceType)
354 return computeMapping(forStructureView, sequenceArray, targetChainIds,
355 pdbFile, sourceType, null);
358 synchronized public StructureFile computeMapping(
359 boolean forStructureView, SequenceI[] sequenceArray,
360 String[] targetChainIds, String pdbFile, DataSourceType sourceType,
361 IProgressIndicator progress)
363 long progressSessionId = System.currentTimeMillis() * 3;
365 * There will be better ways of doing this in the future, for now we'll use
366 * the tried and tested MCview pdb mapping
368 boolean parseSecStr = processSecondaryStructure;
369 if (isPDBFileRegistered(pdbFile))
371 for (SequenceI sq : sequenceArray)
374 while (ds.getDatasetSequence() != null)
376 ds = ds.getDatasetSequence();
379 if (ds.getAnnotation() != null)
381 for (AlignmentAnnotation ala : ds.getAnnotation())
383 // false if any annotation present from this structure
384 // JBPNote this fails for jmol/chimera view because the *file* is
385 // passed, not the structure data ID -
386 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
394 StructureFile pdb = null;
395 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
398 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
399 pdb = new JmolParser(pdbFile, sourceType);
401 if (pdb.getId() != null && pdb.getId().trim().length() > 0
402 && DataSourceType.FILE == sourceType)
404 registerPDBFile(pdb.getId().trim(), pdbFile);
406 // if PDBId is unavailable then skip SIFTS mapping execution path
407 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
409 } catch (Exception ex)
411 ex.printStackTrace();
419 siftsClient = new SiftsClient(pdb);
421 } catch (SiftsException e)
423 isMapUsingSIFTs = false;
427 String targetChainId;
428 for (int s = 0; s < sequenceArray.length; s++)
430 boolean infChain = true;
431 final SequenceI seq = sequenceArray[s];
433 while (ds.getDatasetSequence() != null)
435 ds = ds.getDatasetSequence();
438 if (targetChainIds != null && targetChainIds[s] != null)
441 targetChainId = targetChainIds[s];
443 else if (seq.getName().indexOf("|") > -1)
445 targetChainId = seq.getName()
446 .substring(seq.getName().lastIndexOf("|") + 1);
447 if (targetChainId.length() > 1)
449 if (targetChainId.trim().length() == 0)
455 // not a valid chain identifier
466 * Attempt pairwise alignment of the sequence with each chain in the PDB,
467 * and remember the highest scoring chain
470 AlignSeq maxAlignseq = null;
471 String maxChainId = " ";
472 PDBChain maxChain = null;
473 boolean first = true;
474 for (PDBChain chain : pdb.getChains())
476 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
479 continue; // don't try to map chains don't match.
481 // TODO: correctly determine sequence type for mixed na/peptide
483 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
484 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
487 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
488 // as.calcScoreMatrix();
489 // as.traceAlignment();
491 if (first || as.maxscore > max
492 || (as.maxscore == max && chain.id.equals(targetChainId)))
498 maxChainId = chain.id;
501 if (maxChain == null)
506 if (sourceType == DataSourceType.PASTE)
508 pdbFile = "INLINE" + pdb.getId();
511 List<StructureMapping> seqToStrucMapping = new ArrayList<>();
512 if (isMapUsingSIFTs && seq.isProtein())
514 if (progress!=null) {
515 progress.setProgressBar(MessageManager
516 .getString("status.obtaining_mapping_with_sifts"),
519 jalview.datamodel.Mapping sqmpping = maxAlignseq
520 .getMappingFromS1(false);
521 if (targetChainId != null && !targetChainId.trim().isEmpty())
523 StructureMapping siftsMapping;
526 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
527 pdb, maxChain, sqmpping, maxAlignseq);
528 seqToStrucMapping.add(siftsMapping);
529 maxChain.makeExactMapping(siftsMapping, seq);
530 maxChain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
532 maxChain.transferResidueAnnotation(siftsMapping, null);
533 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
535 } catch (SiftsException e)
537 // fall back to NW alignment
538 System.err.println(e.getMessage());
539 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
540 targetChainId, maxChain, pdb, maxAlignseq);
541 seqToStrucMapping.add(nwMapping);
542 maxChain.makeExactMapping(maxAlignseq, seq);
543 maxChain.transferRESNUMFeatures(seq, "IEA:Jalview"); // FIXME: is
546 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
547 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
552 List<StructureMapping> foundSiftsMappings = new ArrayList<>();
553 for (PDBChain chain : pdb.getChains())
555 StructureMapping siftsMapping = null;
558 siftsMapping = getStructureMapping(seq,
559 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
560 foundSiftsMappings.add(siftsMapping);
561 chain.makeExactMapping(siftsMapping, seq);
562 chain.transferRESNUMFeatures(seq, "IEA: SIFTS");// FIXME: is this
564 chain.transferResidueAnnotation(siftsMapping, null);
565 } catch (SiftsException e)
567 System.err.println(e.getMessage());
570 if (!foundSiftsMappings.isEmpty())
572 seqToStrucMapping.addAll(foundSiftsMappings);
573 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
577 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
578 maxChainId, maxChain, pdb, maxAlignseq);
579 seqToStrucMapping.add(nwMapping);
580 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
582 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
583 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
589 if (progress != null)
591 progress.setProgressBar(MessageManager
592 .getString("status.obtaining_mapping_with_nw_alignment"),
595 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
596 maxChain, pdb, maxAlignseq);
597 seqToStrucMapping.add(nwMapping);
598 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
600 if (forStructureView)
602 mappings.addAll(seqToStrucMapping);
604 if (progress != null)
606 progress.setProgressBar(null, progressSessionId);
612 public void addStructureMapping(StructureMapping sm)
618 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
623 * @param targetChainId
629 * @throws SiftsException
631 private StructureMapping getStructureMapping(SequenceI seq,
632 String pdbFile, String targetChainId, StructureFile pdb,
633 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
634 AlignSeq maxAlignseq) throws SiftsException
636 StructureMapping curChainMapping = siftsClient
637 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
640 PDBChain chain = pdb.findChain(targetChainId);
643 chain.transferResidueAnnotation(curChainMapping, null);
645 } catch (Exception e)
649 return curChainMapping;
652 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
653 String maxChainId, PDBChain maxChain, StructureFile pdb,
654 AlignSeq maxAlignseq)
656 final StringBuilder mappingDetails = new StringBuilder(128);
657 mappingDetails.append(NEWLINE)
658 .append("Sequence \u27f7 Structure mapping details");
659 mappingDetails.append(NEWLINE);
661 .append("Method: inferred with Needleman & Wunsch alignment");
662 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
663 .append(NEWLINE).append("Sequence = ")
664 .append(maxChain.sequence.getSequenceAsString());
665 mappingDetails.append(NEWLINE).append("No of residues = ")
666 .append(maxChain.residues.size()).append(NEWLINE)
668 PrintStream ps = new PrintStream(System.out)
671 public void print(String x)
673 mappingDetails.append(x);
677 public void println()
679 mappingDetails.append(NEWLINE);
683 maxAlignseq.printAlignment(ps);
685 mappingDetails.append(NEWLINE).append("PDB start/end ");
686 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
688 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
689 mappingDetails.append(NEWLINE).append("SEQ start/end ");
692 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
694 mappingDetails.append(
695 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
696 mappingDetails.append(NEWLINE);
697 maxChain.makeExactMapping(maxAlignseq, seq);
698 jalview.datamodel.Mapping sqmpping = maxAlignseq
699 .getMappingFromS1(false);
700 maxChain.transferRESNUMFeatures(seq, null);
702 HashMap<Integer, int[]> mapping = new HashMap<>();
709 Atom tmp = maxChain.atoms.elementAt(index);
710 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
711 && tmp.alignmentMapping != -1)
713 resNum = tmp.resNumber;
714 insCode = tmp.insCode;
715 if (tmp.alignmentMapping >= -1)
717 mapping.put(tmp.alignmentMapping + 1,
719 { tmp.resNumber, tmp.atomIndex });
724 } while (index < maxChain.atoms.size());
726 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
727 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
728 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
732 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
734 listeners.removeElement(svl);
735 if (svl instanceof SequenceListener)
737 for (int i = 0; i < listeners.size(); i++)
739 if (listeners.elementAt(i) instanceof StructureListener)
741 ((StructureListener) listeners.elementAt(i))
742 .releaseReferences(svl);
747 if (pdbfiles == null)
753 * Remove mappings to the closed listener's PDB files, but first check if
754 * another listener is still interested
756 List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
758 StructureListener sl;
759 for (int i = 0; i < listeners.size(); i++)
761 if (listeners.elementAt(i) instanceof StructureListener)
763 sl = (StructureListener) listeners.elementAt(i);
764 for (String pdbfile : sl.getStructureFiles())
766 pdbs.remove(pdbfile);
772 * Rebuild the mappings set, retaining only those which are for 'other' PDB
777 List<StructureMapping> tmp = new ArrayList<>();
778 for (StructureMapping sm : mappings)
780 if (!pdbs.contains(sm.pdbfile))
791 * Propagate mouseover of a single position in a structure
797 public void mouseOverStructure(int pdbResNum, String chain,
800 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
801 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
802 mouseOverStructure(atoms);
806 * Propagate mouseover or selection of multiple positions in a structure
810 public void mouseOverStructure(List<AtomSpec> atoms)
812 if (listeners == null)
814 // old or prematurely sent event
817 boolean hasSequenceListener = false;
818 for (int i = 0; i < listeners.size(); i++)
820 if (listeners.elementAt(i) instanceof SequenceListener)
822 hasSequenceListener = true;
825 if (!hasSequenceListener)
830 SearchResultsI results = findAlignmentPositionsForStructurePositions(
832 for (Object li : listeners)
834 if (li instanceof SequenceListener)
836 ((SequenceListener) li).highlightSequence(results);
842 * Constructs a SearchResults object holding regions (if any) in the Jalview
843 * alignment which have a mapping to the structure viewer positions in the
849 public SearchResultsI findAlignmentPositionsForStructurePositions(
850 List<AtomSpec> atoms)
852 SearchResultsI results = new SearchResults();
853 for (AtomSpec atom : atoms)
855 SequenceI lastseq = null;
857 for (StructureMapping sm : mappings)
859 if (sm.pdbfile.equals(atom.getPdbFile())
860 && sm.pdbchain.equals(atom.getChain()))
862 int indexpos = sm.getSeqPos(atom.getPdbResNum());
863 if (lastipos != indexpos || lastseq != sm.sequence)
865 results.addResult(sm.sequence, indexpos, indexpos);
867 lastseq = sm.sequence;
868 // construct highlighted sequence list
869 for (AlignedCodonFrame acf : seqmappings)
871 acf.markMappedRegion(sm.sequence, indexpos, results);
881 * highlight regions associated with a position (indexpos) in seq
884 * the sequence that the mouse over occurred on
886 * the absolute position being mouseovered in seq (0 to seq.length())
888 * the sequence position (if -1, seq.findPosition is called to
889 * resolve the residue number)
891 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
894 boolean hasSequenceListeners = handlingVamsasMo
895 || !seqmappings.isEmpty();
896 SearchResultsI results = null;
899 seqPos = seq.findPosition(indexpos);
901 for (int i = 0; i < listeners.size(); i++)
903 Object listener = listeners.elementAt(i);
904 if (listener == source)
906 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
907 // Temporary fudge with SequenceListener.getVamsasSource()
910 if (listener instanceof StructureListener)
912 highlightStructure((StructureListener) listener, seq, seqPos);
916 if (listener instanceof SequenceListener)
918 final SequenceListener seqListener = (SequenceListener) listener;
919 if (hasSequenceListeners
920 && seqListener.getVamsasSource() != source)
922 if (relaySeqMappings)
926 results = MappingUtils.buildSearchResults(seq, seqPos,
929 if (handlingVamsasMo)
931 results.addResult(seq, seqPos, seqPos);
934 if (!results.isEmpty())
936 seqListener.highlightSequence(results);
941 else if (listener instanceof VamsasListener && !handlingVamsasMo)
943 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
946 else if (listener instanceof SecondaryStructureListener)
948 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
956 * Send suitable messages to a StructureListener to highlight atoms
957 * corresponding to the given sequence position(s)
963 public void highlightStructure(StructureListener sl, SequenceI seq,
966 if (!sl.isListeningFor(seq))
971 List<AtomSpec> atoms = new ArrayList<>();
972 for (StructureMapping sm : mappings)
974 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
975 || (sm.sequence.getDatasetSequence() != null && sm.sequence
976 .getDatasetSequence() == seq.getDatasetSequence()))
978 for (int index : positions)
980 atomNo = sm.getAtomNum(index);
984 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
985 sm.getPDBResNum(index), atomNo));
990 sl.highlightAtoms(atoms);
994 * true if a mouse over event from an external (ie Vamsas) source is being
997 boolean handlingVamsasMo = false;
1002 * as mouseOverSequence but only route event to SequenceListeners
1006 * in an alignment sequence
1008 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1009 VamsasSource source)
1011 handlingVamsasMo = true;
1012 long msg = sequenceI.hashCode() * (1 + position);
1016 mouseOverSequence(sequenceI, position, -1, source);
1018 handlingVamsasMo = false;
1021 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1025 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1026 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1028 * Annotation [] annotations = new Annotation[seq.getLength()];
1030 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1031 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1032 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1034 * for (int j = 0; j < mappings.length; j++) {
1036 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1037 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1038 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1039 * "+mappings[j].pdbfile);
1041 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1042 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1044 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1045 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1046 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1047 * mappings[j].pdbfile); }
1049 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1050 * annotations; } } } }
1052 * return annotations;
1056 public void structureSelectionChanged()
1060 public void sequenceSelectionChanged()
1064 public void sequenceColoursChanged(Object source)
1066 StructureListener sl;
1067 for (int i = 0; i < listeners.size(); i++)
1069 if (listeners.elementAt(i) instanceof StructureListener)
1071 sl = (StructureListener) listeners.elementAt(i);
1072 sl.updateColours(source);
1077 public StructureMapping[] getMapping(String pdbfile)
1079 List<StructureMapping> tmp = new ArrayList<>();
1080 for (StructureMapping sm : mappings)
1082 if (sm.pdbfile.equals(pdbfile))
1087 return tmp.toArray(new StructureMapping[tmp.size()]);
1091 * Returns a readable description of all mappings for the given pdbfile to any
1092 * of the given sequences
1098 public String printMappings(String pdbfile, List<SequenceI> seqs)
1100 if (pdbfile == null || seqs == null || seqs.isEmpty())
1105 StringBuilder sb = new StringBuilder(64);
1106 for (StructureMapping sm : mappings)
1108 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1110 sb.append(sm.mappingDetails);
1112 // separator makes it easier to read multiple mappings
1113 sb.append("=====================");
1119 return sb.toString();
1123 * Remove the given mapping
1127 public void deregisterMapping(AlignedCodonFrame acf)
1131 boolean removed = seqmappings.remove(acf);
1132 if (removed && seqmappings.isEmpty())
1134 System.out.println("All mappings removed");
1140 * Add each of the given codonFrames to the stored set, if not aready present.
1144 public void registerMappings(List<AlignedCodonFrame> mappings)
1146 if (mappings != null)
1148 for (AlignedCodonFrame acf : mappings)
1150 registerMapping(acf);
1156 * Add the given mapping to the stored set, unless already stored.
1158 public void registerMapping(AlignedCodonFrame acf)
1162 if (!seqmappings.contains(acf))
1164 seqmappings.add(acf);
1170 * Resets this object to its initial state by removing all registered
1171 * listeners, codon mappings, PDB file mappings
1173 public void resetAll()
1175 if (mappings != null)
1179 if (seqmappings != null)
1181 seqmappings.clear();
1183 if (sel_listeners != null)
1185 sel_listeners.clear();
1187 if (listeners != null)
1191 if (commandListeners != null)
1193 commandListeners.clear();
1195 if (view_listeners != null)
1197 view_listeners.clear();
1199 if (pdbFileNameId != null)
1201 pdbFileNameId.clear();
1203 if (pdbIdFileName != null)
1205 pdbIdFileName.clear();
1209 public void addSelectionListener(SelectionListener selecter)
1211 if (!sel_listeners.contains(selecter))
1213 sel_listeners.add(selecter);
1217 public void removeSelectionListener(SelectionListener toremove)
1219 if (sel_listeners.contains(toremove))
1221 sel_listeners.remove(toremove);
1225 public synchronized void sendSelection(
1226 jalview.datamodel.SequenceGroup selection,
1227 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1228 SelectionSource source)
1230 for (SelectionListener slis : sel_listeners)
1234 slis.selection(selection, colsel, hidden, source);
1239 Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
1241 public synchronized void sendViewPosition(
1242 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1243 int startSeq, int endSeq)
1246 if (view_listeners != null && view_listeners.size() > 0)
1248 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1250 while (listeners.hasMoreElements())
1252 AlignmentViewPanelListener slis = listeners.nextElement();
1255 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1263 * release all references associated with this manager provider
1265 * @param jalviewLite
1267 public static void release(StructureSelectionManagerProvider jalviewLite)
1269 // synchronized (instances)
1271 if (instances == null)
1275 StructureSelectionManager mnger = (instances.get(jalviewLite));
1278 instances.remove(jalviewLite);
1282 } catch (Throwable x)
1289 public void registerPDBEntry(PDBEntry pdbentry)
1291 if (pdbentry.getFile() != null
1292 && pdbentry.getFile().trim().length() > 0)
1294 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1298 public void addCommandListener(CommandListener cl)
1300 if (!commandListeners.contains(cl))
1302 commandListeners.add(cl);
1306 public boolean hasCommandListener(CommandListener cl)
1308 return this.commandListeners.contains(cl);
1311 public boolean removeCommandListener(CommandListener l)
1313 return commandListeners.remove(l);
1317 * Forward a command to any command listeners (except for the command's
1321 * the command to be broadcast (in its form after being performed)
1323 * if true, the command was being 'undone'
1326 public void commandPerformed(CommandI command, boolean undo,
1327 VamsasSource source)
1329 for (CommandListener listener : commandListeners)
1331 listener.mirrorCommand(command, undo, this, source);
1336 * Returns a new CommandI representing the given command as mapped to the
1337 * given sequences. If no mapping could be made, or the command is not of a
1338 * mappable kind, returns null.
1346 public CommandI mapCommand(CommandI command, boolean undo,
1347 final AlignmentI mapTo, char gapChar)
1349 if (command instanceof EditCommand)
1351 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1352 gapChar, seqmappings);
1354 else if (command instanceof OrderCommand)
1356 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1357 mapTo, seqmappings);
1362 public List<AlignedCodonFrame> getSequenceMappings()