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.PDBEntry;
33 import jalview.datamodel.SearchResults;
34 import jalview.datamodel.SearchResultsI;
35 import jalview.datamodel.SequenceI;
36 import jalview.ext.jmol.JmolParser;
37 import jalview.gui.IProgressIndicator;
38 import jalview.io.DataSourceType;
39 import jalview.io.StructureFile;
40 import jalview.util.MappingUtils;
41 import jalview.util.MessageManager;
42 import jalview.ws.phyre2.Phyre2Client;
43 import jalview.ws.sifts.SiftsClient;
44 import jalview.ws.sifts.SiftsException;
45 import jalview.ws.sifts.SiftsSettings;
47 import java.io.PrintStream;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collections;
51 import java.util.Enumeration;
52 import java.util.HashMap;
53 import java.util.IdentityHashMap;
54 import java.util.List;
56 import java.util.Vector;
59 import MCview.PDBChain;
60 import MCview.PDBfile;
62 public class StructureSelectionManager
64 public final static String NEWLINE = System.lineSeparator();
66 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
68 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
70 private boolean processSecondaryStructure = false;
72 private boolean secStructServices = false;
74 private boolean addTempFacAnnot = false;
76 private IProgressIndicator progressIndicator;
78 private SiftsClient siftsClient = null;
80 private long progressSessionId;
82 private boolean mappingForPhyre2Model;
85 * Set of any registered mappings between (dataset) sequences.
87 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
89 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
91 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
94 * @return true if will try to use external services for processing secondary
97 public boolean isSecStructServices()
99 return secStructServices;
103 * control use of external services for processing secondary structure
105 * @param secStructServices
107 public void setSecStructServices(boolean secStructServices)
109 this.secStructServices = secStructServices;
113 * flag controlling addition of any kind of structural annotation
115 * @return true if temperature factor annotation will be added
117 public boolean isAddTempFacAnnot()
119 return addTempFacAnnot;
123 * set flag controlling addition of structural annotation
125 * @param addTempFacAnnot
127 public void setAddTempFacAnnot(boolean addTempFacAnnot)
129 this.addTempFacAnnot = addTempFacAnnot;
134 * @return if true, the structure manager will attempt to add secondary
135 * structure lines for unannotated sequences
138 public boolean isProcessSecondaryStructure()
140 return processSecondaryStructure;
144 * Control whether structure manager will try to annotate mapped sequences
145 * with secondary structure from PDB data.
149 public void setProcessSecondaryStructure(boolean enable)
151 processSecondaryStructure = enable;
155 * debug function - write all mappings to stdout
157 public void reportMapping()
159 if (mappings.isEmpty())
161 System.err.println("reportMapping: No PDB/Sequence mappings.");
165 System.err.println("reportMapping: There are " + mappings.size()
168 for (StructureMapping sm : mappings)
170 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
176 * map between the PDB IDs (or structure identifiers) used by Jalview and the
177 * absolute filenames for PDB data that corresponds to it
179 Map<String, String> pdbIdFileName = new HashMap<String, String>();
181 Map<String, String> pdbFileNameId = new HashMap<String, String>();
183 public void registerPDBFile(String idForFile, String absoluteFile)
185 pdbIdFileName.put(idForFile, absoluteFile);
186 pdbFileNameId.put(absoluteFile, idForFile);
189 public String findIdForPDBFile(String idOrFile)
191 String id = pdbFileNameId.get(idOrFile);
195 public String findFileForPDBId(String idOrFile)
197 String id = pdbIdFileName.get(idOrFile);
201 public boolean isPDBFileRegistered(String idOrFile)
203 return pdbFileNameId.containsKey(idOrFile)
204 || pdbIdFileName.containsKey(idOrFile);
207 private static StructureSelectionManager nullProvider = null;
209 public static StructureSelectionManager getStructureSelectionManager(
210 StructureSelectionManagerProvider context)
214 if (nullProvider == null)
216 if (instances != null)
220 .getString("error.implementation_error_structure_selection_manager_null"),
221 new NullPointerException(MessageManager
222 .getString("exception.ssm_context_is_null")));
226 nullProvider = new StructureSelectionManager();
231 if (instances == null)
233 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
235 StructureSelectionManager instance = instances.get(context);
236 if (instance == null)
238 if (nullProvider != null)
240 instance = nullProvider;
244 instance = new StructureSelectionManager();
246 instances.put(context, instance);
252 * flag controlling whether SeqMappings are relayed from received sequence
253 * mouse over events to other sequences
255 boolean relaySeqMappings = true;
258 * Enable or disable relay of seqMapping events to other sequences. You might
259 * want to do this if there are many sequence mappings and the host computer
264 public void setRelaySeqMappings(boolean relay)
266 relaySeqMappings = relay;
270 * get the state of the relay seqMappings flag.
272 * @return true if sequence mouse overs are being relayed to other mapped
275 public boolean isRelaySeqMappingsEnabled()
277 return relaySeqMappings;
280 Vector listeners = new Vector();
283 * register a listener for alignment sequence mouseover events
287 public void addStructureViewerListener(Object svl)
289 if (!listeners.contains(svl))
291 listeners.addElement(svl);
296 * Returns the file name for a mapped PDB id (or null if not mapped).
301 public String alreadyMappedToFile(String pdbid)
303 for (StructureMapping sm : mappings)
305 if (sm.getPdbId().equals(pdbid))
314 * Import structure data and register a structure mapping for broadcasting
315 * colouring, mouseovers and selection events (convenience wrapper).
318 * - one or more sequences to be mapped to pdbFile
319 * @param targetChains
320 * - optional chain specification for mapping each sequence to pdb
321 * (may be nill, individual elements may be nill)
323 * - structure data resource
325 * - how to resolve data from resource
326 * @return null or the structure data parsed as a pdb file
328 synchronized public StructureFile setMapping(SequenceI[] sequence,
329 String[] targetChains, String pdbFile, DataSourceType protocol)
331 return setMapping(true, sequence, targetChains, pdbFile, protocol);
335 * create sequence structure mappings between each sequence and the given
336 * pdbFile (retrieved via the given protocol).
338 * @param forStructureView
339 * when true, record the mapping for use in mouseOvers
341 * @param sequenceArray
342 * - one or more sequences to be mapped to pdbFile
343 * @param targetChainIds
344 * - optional chain specification for mapping each sequence to pdb
345 * (may be nill, individual elements may be nill)
347 * - structure data resource
349 * - how to resolve data from resource
350 * @return null or the structure data parsed as a pdb file
352 synchronized public StructureFile setMapping(boolean forStructureView,
353 SequenceI[] sequenceArray, String[] targetChainIds,
354 String pdbFile, DataSourceType sourceType)
357 * There will be better ways of doing this in the future, for now we'll use
358 * the tried and tested MCview pdb mapping
360 boolean parseSecStr = processSecondaryStructure;
361 if (isPDBFileRegistered(pdbFile))
363 for (SequenceI sq : sequenceArray)
366 while (ds.getDatasetSequence() != null)
368 ds = ds.getDatasetSequence();
371 if (ds.getAnnotation() != null)
373 for (AlignmentAnnotation ala : ds.getAnnotation())
375 // false if any annotation present from this structure
376 // JBPNote this fails for jmol/chimera view because the *file* is
377 // passed, not the structure data ID -
378 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
386 StructureFile pdb = null;
387 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
390 pdb = new JmolParser(pdbFile, sourceType);
392 if (pdb.getId() != null && pdb.getId().trim().length() > 0
393 && DataSourceType.FILE == sourceType)
395 registerPDBFile(pdb.getId().trim(), pdbFile);
397 // if PDBId is unavailable then skip SIFTS mapping execution path
398 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
400 } catch (Exception ex)
402 ex.printStackTrace();
410 siftsClient = new SiftsClient(pdb);
412 } catch (SiftsException e)
414 isMapUsingSIFTs = false;
418 String targetChainId;
419 for (int s = 0; s < sequenceArray.length; s++)
421 boolean infChain = true;
422 final SequenceI seq = sequenceArray[s];
424 while (ds.getDatasetSequence() != null)
426 ds = ds.getDatasetSequence();
429 if (targetChainIds != null && targetChainIds[s] != null)
432 targetChainId = targetChainIds[s];
434 else if (seq.getName().indexOf("|") > -1)
436 targetChainId = seq.getName().substring(
437 seq.getName().lastIndexOf("|") + 1);
438 if (targetChainId.length() > 1)
440 if (targetChainId.trim().length() == 0)
446 // not a valid chain identifier
457 * Attempt pairwise alignment of the sequence with each chain in the PDB,
458 * and remember the highest scoring chain
461 AlignSeq maxAlignseq = null;
462 String maxChainId = " ";
463 PDBChain maxChain = null;
464 boolean first = true;
465 for (PDBChain chain : pdb.getChains())
467 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
470 continue; // don't try to map chains don't match.
472 // TODO: correctly determine sequence type for mixed na/peptide
474 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
475 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
478 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
479 // as.calcScoreMatrix();
480 // as.traceAlignment();
482 if (first || as.maxscore > max
483 || (as.maxscore == max && chain.id.equals(targetChainId)))
489 maxChainId = chain.id;
492 if (maxChain == null)
497 if (sourceType == DataSourceType.PASTE)
499 pdbFile = "INLINE" + pdb.getId();
502 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
503 if (!isMappingForPhyre2Model() && isMapUsingSIFTs && seq.isProtein())
505 setProgressBar(null);
506 setProgressBar(MessageManager
507 .getString("status.obtaining_mapping_with_sifts"));
508 jalview.datamodel.Mapping sqmpping = maxAlignseq
509 .getMappingFromS1(false);
510 if (targetChainId != null && !targetChainId.trim().isEmpty())
512 StructureMapping siftsMapping;
515 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
516 pdb, maxChain, sqmpping, maxAlignseq);
517 seqToStrucMapping.add(siftsMapping);
518 maxChain.makeExactMapping(maxAlignseq, seq);
519 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
521 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
522 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
524 } catch (SiftsException e)
526 // fall back to NW alignment
527 System.err.println(e.getMessage());
528 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
529 targetChainId, maxChain, pdb, maxAlignseq);
530 seqToStrucMapping.add(nwMapping);
531 maxChain.makeExactMapping(maxAlignseq, seq);
532 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
534 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
535 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
536 } catch (Exception e)
543 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
544 for (PDBChain chain : pdb.getChains())
548 StructureMapping siftsMapping = getStructureMapping(seq,
549 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
550 foundSiftsMappings.add(siftsMapping);
551 } catch (SiftsException e)
553 System.err.println(e.getMessage());
554 } catch (Exception e)
559 if (!foundSiftsMappings.isEmpty())
561 seqToStrucMapping.addAll(foundSiftsMappings);
562 maxChain.makeExactMapping(maxAlignseq, seq);
563 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
565 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
567 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
571 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
572 maxChainId, maxChain, pdb, maxAlignseq);
573 seqToStrucMapping.add(nwMapping);
574 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
576 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
577 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
581 else if (isMappingForPhyre2Model())
583 setProgressBar(null);
584 setProgressBar(MessageManager
585 .getString("status.obtaining_mapping_with_phyre2_template_alignment"));
586 StructureMapping phyre2ModelMapping = new Phyre2Client(pdb)
587 .getStructureMapping(seq, pdbFile, " ");
589 seqToStrucMapping.add(phyre2ModelMapping);
590 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
594 setProgressBar(null);
595 setProgressBar(MessageManager
596 .getString("status.obtaining_mapping_with_nw_alignment"));
597 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
598 maxChainId, maxChain, pdb, maxAlignseq);
599 seqToStrucMapping.add(nwMapping);
600 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
604 if (forStructureView)
606 mappings.addAll(seqToStrucMapping);
612 private boolean isCIFFile(String filename)
614 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
616 return "cif".equalsIgnoreCase(fileExt);
620 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
625 * @param targetChainId
631 * @throws SiftsException
633 private StructureMapping getStructureMapping(SequenceI seq,
634 String pdbFile, String targetChainId, StructureFile pdb,
635 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
636 AlignSeq maxAlignseq) throws Exception
638 StructureMapping curChainMapping = siftsClient
639 .getStructureMapping(seq, pdbFile, targetChainId);
642 PDBChain chain = pdb.findChain(targetChainId);
645 chain.transferResidueAnnotation(curChainMapping, sqmpping);
647 } catch (Exception e)
651 return curChainMapping;
654 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
655 String maxChainId, PDBChain maxChain, StructureFile pdb,
656 AlignSeq maxAlignseq)
658 final StringBuilder mappingDetails = new StringBuilder(128);
659 mappingDetails.append(NEWLINE).append(
660 "Sequence \u27f7 Structure mapping details");
661 mappingDetails.append(NEWLINE);
663 .append("Method: inferred with Needleman & Wunsch alignment");
664 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
665 .append(NEWLINE).append("Sequence = ")
666 .append(maxChain.sequence.getSequenceAsString());
667 mappingDetails.append(NEWLINE).append("No of residues = ")
668 .append(maxChain.residues.size()).append(NEWLINE)
670 PrintStream ps = new PrintStream(System.out)
673 public void print(String x)
675 mappingDetails.append(x);
679 public void println()
681 mappingDetails.append(NEWLINE);
685 maxAlignseq.printAlignment(ps);
687 mappingDetails.append(NEWLINE).append("PDB start/end ");
688 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
690 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
691 mappingDetails.append(NEWLINE).append("SEQ start/end ");
692 mappingDetails.append(
693 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
695 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
696 + (seq.getStart() - 1)));
697 mappingDetails.append(NEWLINE);
698 maxChain.makeExactMapping(maxAlignseq, seq);
699 jalview.datamodel.Mapping sqmpping = maxAlignseq
700 .getMappingFromS1(false);
701 maxChain.transferRESNUMFeatures(seq, null);
703 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
710 Atom tmp = maxChain.atoms.elementAt(index);
711 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
712 && tmp.alignmentMapping != -1)
714 resNum = tmp.resNumber;
715 insCode = tmp.insCode;
716 if (tmp.alignmentMapping >= -1)
718 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
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<String>(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.getPdbFile())
766 pdbs.remove(pdbfile);
772 * Rebuild the mappings set, retaining only those which are for 'other' PDB
777 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
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, String pdbfile)
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 = new SearchResults();
830 for (AtomSpec atom : atoms)
832 SequenceI lastseq = null;
834 for (StructureMapping sm : mappings)
836 if (sm.pdbfile.equals(atom.getPdbFile())
837 && sm.pdbchain.equals(atom.getChain()))
839 int indexpos = sm.getSeqPos(atom.getPdbResNum());
840 if (lastipos != indexpos && lastseq != sm.sequence)
842 results.addResult(sm.sequence, indexpos, indexpos);
844 lastseq = sm.sequence;
845 // construct highlighted sequence list
846 for (AlignedCodonFrame acf : seqmappings)
848 acf.markMappedRegion(sm.sequence, indexpos, results);
854 for (Object li : listeners)
856 if (li instanceof SequenceListener)
858 ((SequenceListener) li).highlightSequence(results);
864 * highlight regions associated with a position (indexpos) in seq
867 * the sequence that the mouse over occurred on
869 * the absolute position being mouseovered in seq (0 to seq.length())
871 * the sequence position (if -1, seq.findPosition is called to
872 * resolve the residue number)
874 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
877 boolean hasSequenceListeners = handlingVamsasMo
878 || !seqmappings.isEmpty();
879 SearchResultsI results = null;
882 seqPos = seq.findPosition(indexpos);
884 for (int i = 0; i < listeners.size(); i++)
886 Object listener = listeners.elementAt(i);
887 if (listener == source)
889 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
890 // Temporary fudge with SequenceListener.getVamsasSource()
893 if (listener instanceof StructureListener)
895 highlightStructure((StructureListener) listener, seq, seqPos);
899 if (listener instanceof SequenceListener)
901 final SequenceListener seqListener = (SequenceListener) listener;
902 if (hasSequenceListeners
903 && seqListener.getVamsasSource() != source)
905 if (relaySeqMappings)
909 results = MappingUtils.buildSearchResults(seq, seqPos,
912 if (handlingVamsasMo)
914 results.addResult(seq, seqPos, seqPos);
917 if (!results.isEmpty())
919 seqListener.highlightSequence(results);
924 else if (listener instanceof VamsasListener && !handlingVamsasMo)
926 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
929 else if (listener instanceof SecondaryStructureListener)
931 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
939 * Send suitable messages to a StructureListener to highlight atoms
940 * corresponding to the given sequence position(s)
946 public void highlightStructure(StructureListener sl, SequenceI seq,
949 if (!sl.isListeningFor(seq))
954 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
955 for (StructureMapping sm : mappings)
957 if (sm.sequence == seq
958 || sm.sequence == seq.getDatasetSequence()
959 || (sm.sequence.getDatasetSequence() != null && sm.sequence
960 .getDatasetSequence() == seq.getDatasetSequence()))
962 for (int index : positions)
964 atomNo = sm.getAtomNum(index);
968 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
969 .getPDBResNum(index), atomNo));
974 sl.highlightAtoms(atoms);
978 * true if a mouse over event from an external (ie Vamsas) source is being
981 boolean handlingVamsasMo = false;
986 * as mouseOverSequence but only route event to SequenceListeners
990 * in an alignment sequence
992 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
995 handlingVamsasMo = true;
996 long msg = sequenceI.hashCode() * (1 + position);
1000 mouseOverSequence(sequenceI, position, -1, source);
1002 handlingVamsasMo = false;
1005 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1009 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1010 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1012 * Annotation [] annotations = new Annotation[seq.getLength()];
1014 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1015 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1016 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1018 * for (int j = 0; j < mappings.length; j++) {
1020 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1021 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1022 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1023 * "+mappings[j].pdbfile);
1025 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1026 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1028 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1029 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1030 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1031 * mappings[j].pdbfile); }
1033 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1034 * annotations; } } } }
1036 * return annotations;
1040 public void structureSelectionChanged()
1044 public void sequenceSelectionChanged()
1048 public void sequenceColoursChanged(Object source)
1050 StructureListener sl;
1051 for (int i = 0; i < listeners.size(); i++)
1053 if (listeners.elementAt(i) instanceof StructureListener)
1055 sl = (StructureListener) listeners.elementAt(i);
1056 sl.updateColours(source);
1061 public StructureMapping[] getMapping(String pdbfile)
1063 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1064 for (StructureMapping sm : mappings)
1066 if (sm.pdbfile.equals(pdbfile))
1071 return tmp.toArray(new StructureMapping[tmp.size()]);
1075 * Returns a readable description of all mappings for the given pdbfile to any
1076 * of the given sequences
1082 public String printMappings(String pdbfile, List<SequenceI> seqs)
1084 if (pdbfile == null || seqs == null || seqs.isEmpty())
1089 StringBuilder sb = new StringBuilder(64);
1090 for (StructureMapping sm : mappings)
1092 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1094 sb.append(sm.mappingDetails);
1096 // separator makes it easier to read multiple mappings
1097 sb.append("=====================");
1103 return sb.toString();
1107 * Remove the given mapping
1111 public void deregisterMapping(AlignedCodonFrame acf)
1115 boolean removed = seqmappings.remove(acf);
1116 if (removed && seqmappings.isEmpty())
1118 System.out.println("All mappings removed");
1124 * Add each of the given codonFrames to the stored set, if not aready present.
1128 public void registerMappings(List<AlignedCodonFrame> mappings)
1130 if (mappings != null)
1132 for (AlignedCodonFrame acf : mappings)
1134 registerMapping(acf);
1140 * Add the given mapping to the stored set, unless already stored.
1142 public void registerMapping(AlignedCodonFrame acf)
1146 if (!seqmappings.contains(acf))
1148 seqmappings.add(acf);
1154 * Resets this object to its initial state by removing all registered
1155 * listeners, codon mappings, PDB file mappings
1157 public void resetAll()
1159 if (mappings != null)
1163 if (seqmappings != null)
1165 seqmappings.clear();
1167 if (sel_listeners != null)
1169 sel_listeners.clear();
1171 if (listeners != null)
1175 if (commandListeners != null)
1177 commandListeners.clear();
1179 if (view_listeners != null)
1181 view_listeners.clear();
1183 if (pdbFileNameId != null)
1185 pdbFileNameId.clear();
1187 if (pdbIdFileName != null)
1189 pdbIdFileName.clear();
1193 public void addSelectionListener(SelectionListener selecter)
1195 if (!sel_listeners.contains(selecter))
1197 sel_listeners.add(selecter);
1201 public void removeSelectionListener(SelectionListener toremove)
1203 if (sel_listeners.contains(toremove))
1205 sel_listeners.remove(toremove);
1209 public synchronized void sendSelection(
1210 jalview.datamodel.SequenceGroup selection,
1211 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1213 for (SelectionListener slis : sel_listeners)
1217 slis.selection(selection, colsel, source);
1222 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1224 public synchronized void sendViewPosition(
1225 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1226 int startSeq, int endSeq)
1229 if (view_listeners != null && view_listeners.size() > 0)
1231 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1233 while (listeners.hasMoreElements())
1235 AlignmentViewPanelListener slis = listeners.nextElement();
1238 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1246 * release all references associated with this manager provider
1248 * @param jalviewLite
1250 public static void release(StructureSelectionManagerProvider jalviewLite)
1252 // synchronized (instances)
1254 if (instances == null)
1258 StructureSelectionManager mnger = (instances.get(jalviewLite));
1261 instances.remove(jalviewLite);
1265 } catch (Throwable x)
1272 public void registerPDBEntry(PDBEntry pdbentry)
1274 if (pdbentry.getFile() != null
1275 && pdbentry.getFile().trim().length() > 0)
1277 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1281 public void addCommandListener(CommandListener cl)
1283 if (!commandListeners.contains(cl))
1285 commandListeners.add(cl);
1289 public boolean hasCommandListener(CommandListener cl)
1291 return this.commandListeners.contains(cl);
1294 public boolean removeCommandListener(CommandListener l)
1296 return commandListeners.remove(l);
1300 * Forward a command to any command listeners (except for the command's
1304 * the command to be broadcast (in its form after being performed)
1306 * if true, the command was being 'undone'
1309 public void commandPerformed(CommandI command, boolean undo,
1310 VamsasSource source)
1312 for (CommandListener listener : commandListeners)
1314 listener.mirrorCommand(command, undo, this, source);
1319 * Returns a new CommandI representing the given command as mapped to the
1320 * given sequences. If no mapping could be made, or the command is not of a
1321 * mappable kind, returns null.
1329 public CommandI mapCommand(CommandI command, boolean undo,
1330 final AlignmentI mapTo, char gapChar)
1332 if (command instanceof EditCommand)
1334 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1335 mapTo, gapChar, seqmappings);
1337 else if (command instanceof OrderCommand)
1339 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1340 mapTo, seqmappings);
1345 public IProgressIndicator getProgressIndicator()
1347 return progressIndicator;
1350 public void setProgressIndicator(IProgressIndicator progressIndicator)
1352 this.progressIndicator = progressIndicator;
1355 public long getProgressSessionId()
1357 return progressSessionId;
1360 public void setProgressSessionId(long progressSessionId)
1362 this.progressSessionId = progressSessionId;
1365 public void setProgressBar(String message)
1367 if (progressIndicator == null)
1371 progressIndicator.setProgressBar(message, progressSessionId);
1374 public List<AlignedCodonFrame> getSequenceMappings()
1379 public boolean isMappingForPhyre2Model()
1381 return mappingForPhyre2Model;
1384 public void setMappingForPhyre2Model(boolean mappingForPhyre2Model)
1386 this.mappingForPhyre2Model = mappingForPhyre2Model;
1389 public static StructureSelectionManager getStructureSelectionManager()
1391 return instances.values().iterator().next();