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<StructureMapping>();
71 private boolean processSecondaryStructure = false;
73 private boolean secStructServices = false;
75 private boolean addTempFacAnnot = false;
77 private IProgressIndicator progressIndicator;
79 private SiftsClient siftsClient = null;
81 private long progressSessionId;
84 * Set of any registered mappings between (dataset) sequences.
86 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
88 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
90 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
93 * @return true if will try to use external services for processing secondary
96 public boolean isSecStructServices()
98 return secStructServices;
102 * control use of external services for processing secondary structure
104 * @param secStructServices
106 public void setSecStructServices(boolean secStructServices)
108 this.secStructServices = secStructServices;
112 * flag controlling addition of any kind of structural annotation
114 * @return true if temperature factor annotation will be added
116 public boolean isAddTempFacAnnot()
118 return addTempFacAnnot;
122 * set flag controlling addition of structural annotation
124 * @param addTempFacAnnot
126 public void setAddTempFacAnnot(boolean addTempFacAnnot)
128 this.addTempFacAnnot = addTempFacAnnot;
133 * @return if true, the structure manager will attempt to add secondary
134 * structure lines for unannotated sequences
137 public boolean isProcessSecondaryStructure()
139 return processSecondaryStructure;
143 * Control whether structure manager will try to annotate mapped sequences
144 * with secondary structure from PDB data.
148 public void setProcessSecondaryStructure(boolean enable)
150 processSecondaryStructure = enable;
154 * debug function - write all mappings to stdout
156 public void reportMapping()
158 if (mappings.isEmpty())
160 System.err.println("reportMapping: No PDB/Sequence mappings.");
165 "reportMapping: There are " + mappings.size() + " mappings.");
167 for (StructureMapping sm : mappings)
169 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
175 * map between the PDB IDs (or structure identifiers) used by Jalview and the
176 * absolute filenames for PDB data that corresponds to it
178 Map<String, String> pdbIdFileName = new HashMap<String, String>();
180 Map<String, String> pdbFileNameId = new HashMap<String, String>();
182 public void registerPDBFile(String idForFile, String absoluteFile)
184 pdbIdFileName.put(idForFile, absoluteFile);
185 pdbFileNameId.put(absoluteFile, idForFile);
188 public String findIdForPDBFile(String idOrFile)
190 String id = pdbFileNameId.get(idOrFile);
194 public String findFileForPDBId(String idOrFile)
196 String id = pdbIdFileName.get(idOrFile);
200 public boolean isPDBFileRegistered(String idOrFile)
202 return pdbFileNameId.containsKey(idOrFile)
203 || pdbIdFileName.containsKey(idOrFile);
206 private static StructureSelectionManager nullProvider = null;
208 public static StructureSelectionManager getStructureSelectionManager(
209 StructureSelectionManagerProvider context)
213 if (nullProvider == null)
215 if (instances != null)
217 throw new Error(MessageManager.getString(
218 "error.implementation_error_structure_selection_manager_null"),
219 new NullPointerException(MessageManager
220 .getString("exception.ssm_context_is_null")));
224 nullProvider = new StructureSelectionManager();
229 if (instances == null)
231 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
233 StructureSelectionManager instance = instances.get(context);
234 if (instance == null)
236 if (nullProvider != null)
238 instance = nullProvider;
242 instance = new StructureSelectionManager();
244 instances.put(context, instance);
250 * flag controlling whether SeqMappings are relayed from received sequence
251 * mouse over events to other sequences
253 boolean relaySeqMappings = true;
256 * Enable or disable relay of seqMapping events to other sequences. You might
257 * want to do this if there are many sequence mappings and the host computer
262 public void setRelaySeqMappings(boolean relay)
264 relaySeqMappings = relay;
268 * get the state of the relay seqMappings flag.
270 * @return true if sequence mouse overs are being relayed to other mapped
273 public boolean isRelaySeqMappingsEnabled()
275 return relaySeqMappings;
278 Vector listeners = new Vector();
281 * register a listener for alignment sequence mouseover events
285 public void addStructureViewerListener(Object svl)
287 if (!listeners.contains(svl))
289 listeners.addElement(svl);
294 * Returns the file name for a mapped PDB id (or null if not mapped).
299 public String alreadyMappedToFile(String pdbid)
301 for (StructureMapping sm : mappings)
303 if (sm.getPdbId().equals(pdbid))
312 * Import structure data and register a structure mapping for broadcasting
313 * colouring, mouseovers and selection events (convenience wrapper).
316 * - one or more sequences to be mapped to pdbFile
317 * @param targetChains
318 * - optional chain specification for mapping each sequence to pdb
319 * (may be nill, individual elements may be nill)
321 * - structure data resource
323 * - how to resolve data from resource
324 * @return null or the structure data parsed as a pdb file
326 synchronized public StructureFile setMapping(SequenceI[] sequence,
327 String[] targetChains, String pdbFile, DataSourceType protocol)
329 return setMapping(true, sequence, targetChains, pdbFile, protocol);
333 * create sequence structure mappings between each sequence and the given
334 * pdbFile (retrieved via the given protocol).
336 * @param forStructureView
337 * when true, record the mapping for use in mouseOvers
339 * @param sequenceArray
340 * - one or more sequences to be mapped to pdbFile
341 * @param targetChainIds
342 * - optional chain specification for mapping each sequence to pdb
343 * (may be nill, individual elements may be nill)
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)
355 * There will be better ways of doing this in the future, for now we'll use
356 * the tried and tested MCview pdb mapping
358 boolean parseSecStr = processSecondaryStructure;
359 if (isPDBFileRegistered(pdbFile))
361 for (SequenceI sq : sequenceArray)
364 while (ds.getDatasetSequence() != null)
366 ds = ds.getDatasetSequence();
369 if (ds.getAnnotation() != null)
371 for (AlignmentAnnotation ala : ds.getAnnotation())
373 // false if any annotation present from this structure
374 // JBPNote this fails for jmol/chimera view because the *file* is
375 // passed, not the structure data ID -
376 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
384 StructureFile pdb = null;
385 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
388 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
389 pdb = new JmolParser(pdbFile, sourceType);
391 if (pdb.getId() != null && pdb.getId().trim().length() > 0
392 && DataSourceType.FILE == sourceType)
394 registerPDBFile(pdb.getId().trim(), pdbFile);
396 // if PDBId is unavailable then skip SIFTS mapping execution path
397 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
399 } catch (Exception ex)
401 ex.printStackTrace();
409 siftsClient = new SiftsClient(pdb);
411 } catch (SiftsException e)
413 isMapUsingSIFTs = false;
417 String targetChainId;
418 for (int s = 0; s < sequenceArray.length; s++)
420 boolean infChain = true;
421 final SequenceI seq = sequenceArray[s];
423 while (ds.getDatasetSequence() != null)
425 ds = ds.getDatasetSequence();
428 if (targetChainIds != null && targetChainIds[s] != null)
431 targetChainId = targetChainIds[s];
433 else if (seq.getName().indexOf("|") > -1)
435 targetChainId = seq.getName()
436 .substring(seq.getName().lastIndexOf("|") + 1);
437 if (targetChainId.length() > 1)
439 if (targetChainId.trim().length() == 0)
445 // not a valid chain identifier
456 * Attempt pairwise alignment of the sequence with each chain in the PDB,
457 * and remember the highest scoring chain
460 AlignSeq maxAlignseq = null;
461 String maxChainId = " ";
462 PDBChain maxChain = null;
463 boolean first = true;
464 for (PDBChain chain : pdb.getChains())
466 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
469 continue; // don't try to map chains don't match.
471 // TODO: correctly determine sequence type for mixed na/peptide
473 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
474 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
477 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
478 // as.calcScoreMatrix();
479 // as.traceAlignment();
481 if (first || as.maxscore > max
482 || (as.maxscore == max && chain.id.equals(targetChainId)))
488 maxChainId = chain.id;
491 if (maxChain == null)
496 if (sourceType == DataSourceType.PASTE)
498 pdbFile = "INLINE" + pdb.getId();
501 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
502 if (isMapUsingSIFTs && seq.isProtein())
504 setProgressBar(null);
505 setProgressBar(MessageManager
506 .getString("status.obtaining_mapping_with_sifts"));
507 jalview.datamodel.Mapping sqmpping = maxAlignseq
508 .getMappingFromS1(false);
509 if (targetChainId != null && !targetChainId.trim().isEmpty())
511 StructureMapping siftsMapping;
514 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
515 pdb, maxChain, sqmpping, maxAlignseq);
516 seqToStrucMapping.add(siftsMapping);
517 maxChain.makeExactMapping(maxAlignseq, seq);
518 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
520 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
521 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
523 } catch (SiftsException e)
525 // fall back to NW alignment
526 System.err.println(e.getMessage());
527 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
528 targetChainId, maxChain, pdb, maxAlignseq);
529 seqToStrucMapping.add(nwMapping);
530 maxChain.makeExactMapping(maxAlignseq, seq);
531 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
533 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
534 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
539 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
540 for (PDBChain chain : pdb.getChains())
544 StructureMapping siftsMapping = getStructureMapping(seq,
545 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
546 foundSiftsMappings.add(siftsMapping);
547 } catch (SiftsException e)
549 System.err.println(e.getMessage());
552 if (!foundSiftsMappings.isEmpty())
554 seqToStrucMapping.addAll(foundSiftsMappings);
555 maxChain.makeExactMapping(maxAlignseq, seq);
556 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
558 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
560 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
564 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
565 maxChainId, maxChain, pdb, maxAlignseq);
566 seqToStrucMapping.add(nwMapping);
567 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
569 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
570 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
576 setProgressBar(null);
577 setProgressBar(MessageManager
578 .getString("status.obtaining_mapping_with_nw_alignment"));
579 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
580 maxChain, pdb, maxAlignseq);
581 seqToStrucMapping.add(nwMapping);
582 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
586 if (forStructureView)
588 mappings.addAll(seqToStrucMapping);
594 public void addStructureMapping(StructureMapping sm)
600 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
605 * @param targetChainId
611 * @throws SiftsException
613 private StructureMapping getStructureMapping(SequenceI seq,
614 String pdbFile, String targetChainId, StructureFile pdb,
615 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
616 AlignSeq maxAlignseq) throws SiftsException
618 StructureMapping curChainMapping = siftsClient
619 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
622 PDBChain chain = pdb.findChain(targetChainId);
625 chain.transferResidueAnnotation(curChainMapping, sqmpping);
627 } catch (Exception e)
631 return curChainMapping;
634 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
635 String maxChainId, PDBChain maxChain, StructureFile pdb,
636 AlignSeq maxAlignseq)
638 final StringBuilder mappingDetails = new StringBuilder(128);
639 mappingDetails.append(NEWLINE)
640 .append("Sequence \u27f7 Structure mapping details");
641 mappingDetails.append(NEWLINE);
643 .append("Method: inferred with Needleman & Wunsch alignment");
644 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
645 .append(NEWLINE).append("Sequence = ")
646 .append(maxChain.sequence.getSequenceAsString());
647 mappingDetails.append(NEWLINE).append("No of residues = ")
648 .append(maxChain.residues.size()).append(NEWLINE)
650 PrintStream ps = new PrintStream(System.out)
653 public void print(String x)
655 mappingDetails.append(x);
659 public void println()
661 mappingDetails.append(NEWLINE);
665 maxAlignseq.printAlignment(ps);
667 mappingDetails.append(NEWLINE).append("PDB start/end ");
668 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
670 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
671 mappingDetails.append(NEWLINE).append("SEQ start/end ");
674 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
676 mappingDetails.append(
677 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
678 mappingDetails.append(NEWLINE);
679 maxChain.makeExactMapping(maxAlignseq, seq);
680 jalview.datamodel.Mapping sqmpping = maxAlignseq
681 .getMappingFromS1(false);
682 maxChain.transferRESNUMFeatures(seq, null);
684 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
691 Atom tmp = maxChain.atoms.elementAt(index);
692 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
693 && tmp.alignmentMapping != -1)
695 resNum = tmp.resNumber;
696 insCode = tmp.insCode;
697 if (tmp.alignmentMapping >= -1)
699 mapping.put(tmp.alignmentMapping + 1,
701 { tmp.resNumber, tmp.atomIndex });
706 } while (index < maxChain.atoms.size());
708 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
709 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
710 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
714 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
716 listeners.removeElement(svl);
717 if (svl instanceof SequenceListener)
719 for (int i = 0; i < listeners.size(); i++)
721 if (listeners.elementAt(i) instanceof StructureListener)
723 ((StructureListener) listeners.elementAt(i))
724 .releaseReferences(svl);
729 if (pdbfiles == null)
735 * Remove mappings to the closed listener's PDB files, but first check if
736 * another listener is still interested
738 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
740 StructureListener sl;
741 for (int i = 0; i < listeners.size(); i++)
743 if (listeners.elementAt(i) instanceof StructureListener)
745 sl = (StructureListener) listeners.elementAt(i);
746 for (String pdbfile : sl.getStructureFiles())
748 pdbs.remove(pdbfile);
754 * Rebuild the mappings set, retaining only those which are for 'other' PDB
759 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
760 for (StructureMapping sm : mappings)
762 if (!pdbs.contains(sm.pdbfile))
773 * Propagate mouseover of a single position in a structure
779 public void mouseOverStructure(int pdbResNum, String chain,
782 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
783 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
784 mouseOverStructure(atoms);
788 * Propagate mouseover or selection of multiple positions in a structure
792 public void mouseOverStructure(List<AtomSpec> atoms)
794 if (listeners == null)
796 // old or prematurely sent event
799 boolean hasSequenceListener = false;
800 for (int i = 0; i < listeners.size(); i++)
802 if (listeners.elementAt(i) instanceof SequenceListener)
804 hasSequenceListener = true;
807 if (!hasSequenceListener)
812 SearchResultsI results = findAlignmentPositionsForStructurePositions(
814 for (Object li : listeners)
816 if (li instanceof SequenceListener)
818 ((SequenceListener) li).highlightSequence(results);
824 * Constructs a SearchResults object holding regions (if any) in the Jalview
825 * alignment which have a mapping to the structure viewer positions in the
831 public SearchResultsI findAlignmentPositionsForStructurePositions(
832 List<AtomSpec> atoms)
834 SearchResultsI results = new SearchResults();
835 for (AtomSpec atom : atoms)
837 SequenceI lastseq = null;
839 for (StructureMapping sm : mappings)
841 if (sm.pdbfile.equals(atom.getPdbFile())
842 && sm.pdbchain.equals(atom.getChain()))
844 int indexpos = sm.getSeqPos(atom.getPdbResNum());
845 if (lastipos != indexpos && lastseq != sm.sequence)
847 results.addResult(sm.sequence, indexpos, indexpos);
849 lastseq = sm.sequence;
850 // construct highlighted sequence list
851 for (AlignedCodonFrame acf : seqmappings)
853 acf.markMappedRegion(sm.sequence, indexpos, results);
863 * highlight regions associated with a position (indexpos) in seq
866 * the sequence that the mouse over occurred on
868 * the absolute position being mouseovered in seq (0 to seq.length())
870 * the sequence position (if -1, seq.findPosition is called to
871 * resolve the residue number)
873 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
876 boolean hasSequenceListeners = handlingVamsasMo
877 || !seqmappings.isEmpty();
878 SearchResultsI results = null;
881 seqPos = seq.findPosition(indexpos);
883 for (int i = 0; i < listeners.size(); i++)
885 Object listener = listeners.elementAt(i);
886 if (listener == source)
888 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
889 // Temporary fudge with SequenceListener.getVamsasSource()
892 if (listener instanceof StructureListener)
894 highlightStructure((StructureListener) listener, seq, seqPos);
898 if (listener instanceof SequenceListener)
900 final SequenceListener seqListener = (SequenceListener) listener;
901 if (hasSequenceListeners
902 && seqListener.getVamsasSource() != source)
904 if (relaySeqMappings)
908 results = MappingUtils.buildSearchResults(seq, seqPos,
911 if (handlingVamsasMo)
913 results.addResult(seq, seqPos, seqPos);
916 if (!results.isEmpty())
918 seqListener.highlightSequence(results);
923 else if (listener instanceof VamsasListener && !handlingVamsasMo)
925 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
928 else if (listener instanceof SecondaryStructureListener)
930 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
938 * Send suitable messages to a StructureListener to highlight atoms
939 * corresponding to the given sequence position(s)
945 public void highlightStructure(StructureListener sl, SequenceI seq,
948 if (!sl.isListeningFor(seq))
953 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
954 for (StructureMapping sm : mappings)
956 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
957 || (sm.sequence.getDatasetSequence() != null && sm.sequence
958 .getDatasetSequence() == seq.getDatasetSequence()))
960 for (int index : positions)
962 atomNo = sm.getAtomNum(index);
966 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
967 sm.getPDBResNum(index), atomNo));
972 sl.highlightAtoms(atoms);
976 * true if a mouse over event from an external (ie Vamsas) source is being
979 boolean handlingVamsasMo = false;
984 * as mouseOverSequence but only route event to SequenceListeners
988 * in an alignment sequence
990 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
993 handlingVamsasMo = true;
994 long msg = sequenceI.hashCode() * (1 + position);
998 mouseOverSequence(sequenceI, position, -1, source);
1000 handlingVamsasMo = false;
1003 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1007 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1008 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1010 * Annotation [] annotations = new Annotation[seq.getLength()];
1012 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1013 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1014 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1016 * for (int j = 0; j < mappings.length; j++) {
1018 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1019 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1020 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1021 * "+mappings[j].pdbfile);
1023 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1024 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1026 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1027 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1028 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1029 * mappings[j].pdbfile); }
1031 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1032 * annotations; } } } }
1034 * return annotations;
1038 public void structureSelectionChanged()
1042 public void sequenceSelectionChanged()
1046 public void sequenceColoursChanged(Object source)
1048 StructureListener sl;
1049 for (int i = 0; i < listeners.size(); i++)
1051 if (listeners.elementAt(i) instanceof StructureListener)
1053 sl = (StructureListener) listeners.elementAt(i);
1054 sl.updateColours(source);
1059 public StructureMapping[] getMapping(String pdbfile)
1061 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1062 for (StructureMapping sm : mappings)
1064 if (sm.pdbfile.equals(pdbfile))
1069 return tmp.toArray(new StructureMapping[tmp.size()]);
1073 * Returns a readable description of all mappings for the given pdbfile to any
1074 * of the given sequences
1080 public String printMappings(String pdbfile, List<SequenceI> seqs)
1082 if (pdbfile == null || seqs == null || seqs.isEmpty())
1087 StringBuilder sb = new StringBuilder(64);
1088 for (StructureMapping sm : mappings)
1090 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1092 sb.append(sm.mappingDetails);
1094 // separator makes it easier to read multiple mappings
1095 sb.append("=====================");
1101 return sb.toString();
1105 * Remove the given mapping
1109 public void deregisterMapping(AlignedCodonFrame acf)
1113 boolean removed = seqmappings.remove(acf);
1114 if (removed && seqmappings.isEmpty())
1116 System.out.println("All mappings removed");
1122 * Add each of the given codonFrames to the stored set, if not aready present.
1126 public void registerMappings(List<AlignedCodonFrame> mappings)
1128 if (mappings != null)
1130 for (AlignedCodonFrame acf : mappings)
1132 registerMapping(acf);
1138 * Add the given mapping to the stored set, unless already stored.
1140 public void registerMapping(AlignedCodonFrame acf)
1144 if (!seqmappings.contains(acf))
1146 seqmappings.add(acf);
1152 * Resets this object to its initial state by removing all registered
1153 * listeners, codon mappings, PDB file mappings
1155 public void resetAll()
1157 if (mappings != null)
1161 if (seqmappings != null)
1163 seqmappings.clear();
1165 if (sel_listeners != null)
1167 sel_listeners.clear();
1169 if (listeners != null)
1173 if (commandListeners != null)
1175 commandListeners.clear();
1177 if (view_listeners != null)
1179 view_listeners.clear();
1181 if (pdbFileNameId != null)
1183 pdbFileNameId.clear();
1185 if (pdbIdFileName != null)
1187 pdbIdFileName.clear();
1191 public void addSelectionListener(SelectionListener selecter)
1193 if (!sel_listeners.contains(selecter))
1195 sel_listeners.add(selecter);
1199 public void removeSelectionListener(SelectionListener toremove)
1201 if (sel_listeners.contains(toremove))
1203 sel_listeners.remove(toremove);
1207 public synchronized void sendSelection(
1208 jalview.datamodel.SequenceGroup selection,
1209 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1210 SelectionSource source)
1212 for (SelectionListener slis : sel_listeners)
1216 slis.selection(selection, colsel, hidden, source);
1221 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1223 public synchronized void sendViewPosition(
1224 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1225 int startSeq, int endSeq)
1228 if (view_listeners != null && view_listeners.size() > 0)
1230 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1232 while (listeners.hasMoreElements())
1234 AlignmentViewPanelListener slis = listeners.nextElement();
1237 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1245 * release all references associated with this manager provider
1247 * @param jalviewLite
1249 public static void release(StructureSelectionManagerProvider jalviewLite)
1251 // synchronized (instances)
1253 if (instances == null)
1257 StructureSelectionManager mnger = (instances.get(jalviewLite));
1260 instances.remove(jalviewLite);
1264 } catch (Throwable x)
1271 public void registerPDBEntry(PDBEntry pdbentry)
1273 if (pdbentry.getFile() != null
1274 && pdbentry.getFile().trim().length() > 0)
1276 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1280 public void addCommandListener(CommandListener cl)
1282 if (!commandListeners.contains(cl))
1284 commandListeners.add(cl);
1288 public boolean hasCommandListener(CommandListener cl)
1290 return this.commandListeners.contains(cl);
1293 public boolean removeCommandListener(CommandListener l)
1295 return commandListeners.remove(l);
1299 * Forward a command to any command listeners (except for the command's
1303 * the command to be broadcast (in its form after being performed)
1305 * if true, the command was being 'undone'
1308 public void commandPerformed(CommandI command, boolean undo,
1309 VamsasSource source)
1311 for (CommandListener listener : commandListeners)
1313 listener.mirrorCommand(command, undo, this, source);
1318 * Returns a new CommandI representing the given command as mapped to the
1319 * given sequences. If no mapping could be made, or the command is not of a
1320 * mappable kind, returns null.
1328 public CommandI mapCommand(CommandI command, boolean undo,
1329 final AlignmentI mapTo, char gapChar)
1331 if (command instanceof EditCommand)
1333 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1334 gapChar, seqmappings);
1336 else if (command instanceof OrderCommand)
1338 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1339 mapTo, seqmappings);
1344 public IProgressIndicator getProgressIndicator()
1346 return progressIndicator;
1349 public void setProgressIndicator(IProgressIndicator progressIndicator)
1351 this.progressIndicator = progressIndicator;
1354 public long getProgressSessionId()
1356 return progressSessionId;
1359 public void setProgressSessionId(long progressSessionId)
1361 this.progressSessionId = progressSessionId;
1364 public void setProgressBar(String message)
1366 if (progressIndicator == null)
1370 progressIndicator.setProgressBar(message, progressSessionId);
1373 public List<AlignedCodonFrame> getSequenceMappings()