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(maxAlignseq, seq);
530 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
532 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
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, null); // FIXME: is this
545 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
546 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
551 List<StructureMapping> foundSiftsMappings = new ArrayList<>();
552 for (PDBChain chain : pdb.getChains())
556 StructureMapping siftsMapping = getStructureMapping(seq,
557 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
558 foundSiftsMappings.add(siftsMapping);
559 } catch (SiftsException e)
561 System.err.println(e.getMessage());
564 if (!foundSiftsMappings.isEmpty())
566 seqToStrucMapping.addAll(foundSiftsMappings);
567 maxChain.makeExactMapping(maxAlignseq, seq);
568 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
570 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
572 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
576 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
577 maxChainId, maxChain, pdb, maxAlignseq);
578 seqToStrucMapping.add(nwMapping);
579 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
581 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
582 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
588 if (progress != null)
590 progress.setProgressBar(MessageManager
591 .getString("status.obtaining_mapping_with_nw_alignment"),
594 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
595 maxChain, pdb, maxAlignseq);
596 seqToStrucMapping.add(nwMapping);
597 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
599 if (forStructureView)
601 mappings.addAll(seqToStrucMapping);
603 if (progress != null)
605 progress.setProgressBar(null, progressSessionId);
611 public void addStructureMapping(StructureMapping sm)
617 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
622 * @param targetChainId
628 * @throws SiftsException
630 private StructureMapping getStructureMapping(SequenceI seq,
631 String pdbFile, String targetChainId, StructureFile pdb,
632 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
633 AlignSeq maxAlignseq) throws SiftsException
635 StructureMapping curChainMapping = siftsClient
636 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
639 PDBChain chain = pdb.findChain(targetChainId);
642 chain.transferResidueAnnotation(curChainMapping, sqmpping);
644 } catch (Exception e)
648 return curChainMapping;
651 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
652 String maxChainId, PDBChain maxChain, StructureFile pdb,
653 AlignSeq maxAlignseq)
655 final StringBuilder mappingDetails = new StringBuilder(128);
656 mappingDetails.append(NEWLINE)
657 .append("Sequence \u27f7 Structure mapping details");
658 mappingDetails.append(NEWLINE);
660 .append("Method: inferred with Needleman & Wunsch alignment");
661 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
662 .append(NEWLINE).append("Sequence = ")
663 .append(maxChain.sequence.getSequenceAsString());
664 mappingDetails.append(NEWLINE).append("No of residues = ")
665 .append(maxChain.residues.size()).append(NEWLINE)
667 PrintStream ps = new PrintStream(System.out)
670 public void print(String x)
672 mappingDetails.append(x);
676 public void println()
678 mappingDetails.append(NEWLINE);
682 maxAlignseq.printAlignment(ps);
684 mappingDetails.append(NEWLINE).append("PDB start/end ");
685 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
687 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
688 mappingDetails.append(NEWLINE).append("SEQ start/end ");
691 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
693 mappingDetails.append(
694 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
695 mappingDetails.append(NEWLINE);
696 maxChain.makeExactMapping(maxAlignseq, seq);
697 jalview.datamodel.Mapping sqmpping = maxAlignseq
698 .getMappingFromS1(false);
699 maxChain.transferRESNUMFeatures(seq, null);
701 HashMap<Integer, int[]> mapping = new HashMap<>();
708 Atom tmp = maxChain.atoms.elementAt(index);
709 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
710 && tmp.alignmentMapping != -1)
712 resNum = tmp.resNumber;
713 insCode = tmp.insCode;
714 if (tmp.alignmentMapping >= -1)
716 mapping.put(tmp.alignmentMapping + 1,
718 { tmp.resNumber, tmp.atomIndex });
723 } while (index < maxChain.atoms.size());
725 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
726 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
727 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
731 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
733 listeners.removeElement(svl);
734 if (svl instanceof SequenceListener)
736 for (int i = 0; i < listeners.size(); i++)
738 if (listeners.elementAt(i) instanceof StructureListener)
740 ((StructureListener) listeners.elementAt(i))
741 .releaseReferences(svl);
746 if (pdbfiles == null)
752 * Remove mappings to the closed listener's PDB files, but first check if
753 * another listener is still interested
755 List<String> pdbs = new ArrayList<>(Arrays.asList(pdbfiles));
757 StructureListener sl;
758 for (int i = 0; i < listeners.size(); i++)
760 if (listeners.elementAt(i) instanceof StructureListener)
762 sl = (StructureListener) listeners.elementAt(i);
763 for (String pdbfile : sl.getStructureFiles())
765 pdbs.remove(pdbfile);
771 * Rebuild the mappings set, retaining only those which are for 'other' PDB
776 List<StructureMapping> tmp = new ArrayList<>();
777 for (StructureMapping sm : mappings)
779 if (!pdbs.contains(sm.pdbfile))
790 * Propagate mouseover of a single position in a structure
796 public void mouseOverStructure(int pdbResNum, String chain,
799 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
800 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
801 mouseOverStructure(atoms);
805 * Propagate mouseover or selection of multiple positions in a structure
809 public void mouseOverStructure(List<AtomSpec> atoms)
811 if (listeners == null)
813 // old or prematurely sent event
816 boolean hasSequenceListener = false;
817 for (int i = 0; i < listeners.size(); i++)
819 if (listeners.elementAt(i) instanceof SequenceListener)
821 hasSequenceListener = true;
824 if (!hasSequenceListener)
829 SearchResultsI results = findAlignmentPositionsForStructurePositions(
831 for (Object li : listeners)
833 if (li instanceof SequenceListener)
835 ((SequenceListener) li).highlightSequence(results);
841 * Constructs a SearchResults object holding regions (if any) in the Jalview
842 * alignment which have a mapping to the structure viewer positions in the
848 public SearchResultsI findAlignmentPositionsForStructurePositions(
849 List<AtomSpec> atoms)
851 SearchResultsI results = new SearchResults();
852 for (AtomSpec atom : atoms)
854 SequenceI lastseq = null;
856 for (StructureMapping sm : mappings)
858 if (sm.pdbfile.equals(atom.getPdbFile())
859 && sm.pdbchain.equals(atom.getChain()))
861 int indexpos = sm.getSeqPos(atom.getPdbResNum());
862 if (lastipos != indexpos || lastseq != sm.sequence)
864 results.addResult(sm.sequence, indexpos, indexpos);
866 lastseq = sm.sequence;
867 // construct highlighted sequence list
868 for (AlignedCodonFrame acf : seqmappings)
870 acf.markMappedRegion(sm.sequence, indexpos, results);
880 * highlight regions associated with a position (indexpos) in seq
883 * the sequence that the mouse over occurred on
885 * the absolute position being mouseovered in seq (0 to seq.length())
887 * the sequence position (if -1, seq.findPosition is called to
888 * resolve the residue number)
890 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
893 boolean hasSequenceListeners = handlingVamsasMo
894 || !seqmappings.isEmpty();
895 SearchResultsI results = null;
898 seqPos = seq.findPosition(indexpos);
900 for (int i = 0; i < listeners.size(); i++)
902 Object listener = listeners.elementAt(i);
903 if (listener == source)
905 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
906 // Temporary fudge with SequenceListener.getVamsasSource()
909 if (listener instanceof StructureListener)
911 highlightStructure((StructureListener) listener, seq, seqPos);
915 if (listener instanceof SequenceListener)
917 final SequenceListener seqListener = (SequenceListener) listener;
918 if (hasSequenceListeners
919 && seqListener.getVamsasSource() != source)
921 if (relaySeqMappings)
925 results = MappingUtils.buildSearchResults(seq, seqPos,
928 if (handlingVamsasMo)
930 results.addResult(seq, seqPos, seqPos);
933 if (!results.isEmpty())
935 seqListener.highlightSequence(results);
940 else if (listener instanceof VamsasListener && !handlingVamsasMo)
942 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
945 else if (listener instanceof SecondaryStructureListener)
947 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
955 * Send suitable messages to a StructureListener to highlight atoms
956 * corresponding to the given sequence position(s)
962 public void highlightStructure(StructureListener sl, SequenceI seq,
965 if (!sl.isListeningFor(seq))
970 List<AtomSpec> atoms = new ArrayList<>();
971 for (StructureMapping sm : mappings)
973 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
974 || (sm.sequence.getDatasetSequence() != null && sm.sequence
975 .getDatasetSequence() == seq.getDatasetSequence()))
977 for (int index : positions)
979 atomNo = sm.getAtomNum(index);
983 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
984 sm.getPDBResNum(index), atomNo));
989 sl.highlightAtoms(atoms);
993 * true if a mouse over event from an external (ie Vamsas) source is being
996 boolean handlingVamsasMo = false;
1001 * as mouseOverSequence but only route event to SequenceListeners
1005 * in an alignment sequence
1007 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1008 VamsasSource source)
1010 handlingVamsasMo = true;
1011 long msg = sequenceI.hashCode() * (1 + position);
1015 mouseOverSequence(sequenceI, position, -1, source);
1017 handlingVamsasMo = false;
1020 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1024 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1025 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1027 * Annotation [] annotations = new Annotation[seq.getLength()];
1029 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1030 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1031 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1033 * for (int j = 0; j < mappings.length; j++) {
1035 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1036 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1037 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1038 * "+mappings[j].pdbfile);
1040 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1041 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1043 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1044 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1045 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1046 * mappings[j].pdbfile); }
1048 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1049 * annotations; } } } }
1051 * return annotations;
1055 public void structureSelectionChanged()
1059 public void sequenceSelectionChanged()
1063 public void sequenceColoursChanged(Object source)
1065 StructureListener sl;
1066 for (int i = 0; i < listeners.size(); i++)
1068 if (listeners.elementAt(i) instanceof StructureListener)
1070 sl = (StructureListener) listeners.elementAt(i);
1071 sl.updateColours(source);
1076 public StructureMapping[] getMapping(String pdbfile)
1078 List<StructureMapping> tmp = new ArrayList<>();
1079 for (StructureMapping sm : mappings)
1081 if (sm.pdbfile.equals(pdbfile))
1086 return tmp.toArray(new StructureMapping[tmp.size()]);
1090 * Returns a readable description of all mappings for the given pdbfile to any
1091 * of the given sequences
1097 public String printMappings(String pdbfile, List<SequenceI> seqs)
1099 if (pdbfile == null || seqs == null || seqs.isEmpty())
1104 StringBuilder sb = new StringBuilder(64);
1105 for (StructureMapping sm : mappings)
1107 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1109 sb.append(sm.mappingDetails);
1111 // separator makes it easier to read multiple mappings
1112 sb.append("=====================");
1118 return sb.toString();
1122 * Remove the given mapping
1126 public void deregisterMapping(AlignedCodonFrame acf)
1130 boolean removed = seqmappings.remove(acf);
1131 if (removed && seqmappings.isEmpty())
1133 System.out.println("All mappings removed");
1139 * Add each of the given codonFrames to the stored set, if not aready present.
1143 public void registerMappings(List<AlignedCodonFrame> mappings)
1145 if (mappings != null)
1147 for (AlignedCodonFrame acf : mappings)
1149 registerMapping(acf);
1155 * Add the given mapping to the stored set, unless already stored.
1157 public void registerMapping(AlignedCodonFrame acf)
1161 if (!seqmappings.contains(acf))
1163 seqmappings.add(acf);
1169 * Resets this object to its initial state by removing all registered
1170 * listeners, codon mappings, PDB file mappings
1172 public void resetAll()
1174 if (mappings != null)
1178 if (seqmappings != null)
1180 seqmappings.clear();
1182 if (sel_listeners != null)
1184 sel_listeners.clear();
1186 if (listeners != null)
1190 if (commandListeners != null)
1192 commandListeners.clear();
1194 if (view_listeners != null)
1196 view_listeners.clear();
1198 if (pdbFileNameId != null)
1200 pdbFileNameId.clear();
1202 if (pdbIdFileName != null)
1204 pdbIdFileName.clear();
1208 public void addSelectionListener(SelectionListener selecter)
1210 if (!sel_listeners.contains(selecter))
1212 sel_listeners.add(selecter);
1216 public void removeSelectionListener(SelectionListener toremove)
1218 if (sel_listeners.contains(toremove))
1220 sel_listeners.remove(toremove);
1224 public synchronized void sendSelection(
1225 jalview.datamodel.SequenceGroup selection,
1226 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1227 SelectionSource source)
1229 for (SelectionListener slis : sel_listeners)
1233 slis.selection(selection, colsel, hidden, source);
1238 Vector<AlignmentViewPanelListener> view_listeners = new Vector<>();
1240 public synchronized void sendViewPosition(
1241 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1242 int startSeq, int endSeq)
1245 if (view_listeners != null && view_listeners.size() > 0)
1247 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1249 while (listeners.hasMoreElements())
1251 AlignmentViewPanelListener slis = listeners.nextElement();
1254 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1262 * release all references associated with this manager provider
1264 * @param jalviewLite
1266 public static void release(StructureSelectionManagerProvider jalviewLite)
1268 // synchronized (instances)
1270 if (instances == null)
1274 StructureSelectionManager mnger = (instances.get(jalviewLite));
1277 instances.remove(jalviewLite);
1281 } catch (Throwable x)
1288 public void registerPDBEntry(PDBEntry pdbentry)
1290 if (pdbentry.getFile() != null
1291 && pdbentry.getFile().trim().length() > 0)
1293 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1297 public void addCommandListener(CommandListener cl)
1299 if (!commandListeners.contains(cl))
1301 commandListeners.add(cl);
1305 public boolean hasCommandListener(CommandListener cl)
1307 return this.commandListeners.contains(cl);
1310 public boolean removeCommandListener(CommandListener l)
1312 return commandListeners.remove(l);
1316 * Forward a command to any command listeners (except for the command's
1320 * the command to be broadcast (in its form after being performed)
1322 * if true, the command was being 'undone'
1325 public void commandPerformed(CommandI command, boolean undo,
1326 VamsasSource source)
1328 for (CommandListener listener : commandListeners)
1330 listener.mirrorCommand(command, undo, this, source);
1335 * Returns a new CommandI representing the given command as mapped to the
1336 * given sequences. If no mapping could be made, or the command is not of a
1337 * mappable kind, returns null.
1345 public CommandI mapCommand(CommandI command, boolean undo,
1346 final AlignmentI mapTo, char gapChar)
1348 if (command instanceof EditCommand)
1350 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1351 gapChar, seqmappings);
1353 else if (command instanceof OrderCommand)
1355 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1356 mapTo, seqmappings);
1361 public List<AlignedCodonFrame> getSequenceMappings()