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.AppletFormatAdapter;
39 import jalview.io.DataSourceType;
40 import jalview.io.StructureFile;
41 import jalview.util.MappingUtils;
42 import jalview.util.MessageManager;
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;
83 * Set of any registered mappings between (dataset) sequences.
85 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
87 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
89 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
92 * @return true if will try to use external services for processing secondary
95 public boolean isSecStructServices()
97 return secStructServices;
101 * control use of external services for processing secondary structure
103 * @param secStructServices
105 public void setSecStructServices(boolean secStructServices)
107 this.secStructServices = secStructServices;
111 * flag controlling addition of any kind of structural annotation
113 * @return true if temperature factor annotation will be added
115 public boolean isAddTempFacAnnot()
117 return addTempFacAnnot;
121 * set flag controlling addition of structural annotation
123 * @param addTempFacAnnot
125 public void setAddTempFacAnnot(boolean addTempFacAnnot)
127 this.addTempFacAnnot = addTempFacAnnot;
132 * @return if true, the structure manager will attempt to add secondary
133 * structure lines for unannotated sequences
136 public boolean isProcessSecondaryStructure()
138 return processSecondaryStructure;
142 * Control whether structure manager will try to annotate mapped sequences
143 * with secondary structure from PDB data.
147 public void setProcessSecondaryStructure(boolean enable)
149 processSecondaryStructure = enable;
153 * debug function - write all mappings to stdout
155 public void reportMapping()
157 if (mappings.isEmpty())
159 System.err.println("reportMapping: No PDB/Sequence mappings.");
163 System.err.println("reportMapping: There are " + mappings.size()
166 for (StructureMapping sm : mappings)
168 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
174 * map between the PDB IDs (or structure identifiers) used by Jalview and the
175 * absolute filenames for PDB data that corresponds to it
177 Map<String, String> pdbIdFileName = new HashMap<String, String>();
179 Map<String, String> pdbFileNameId = new HashMap<String, String>();
181 public void registerPDBFile(String idForFile, String absoluteFile)
183 pdbIdFileName.put(idForFile, absoluteFile);
184 pdbFileNameId.put(absoluteFile, idForFile);
187 public String findIdForPDBFile(String idOrFile)
189 String id = pdbFileNameId.get(idOrFile);
193 public String findFileForPDBId(String idOrFile)
195 String id = pdbIdFileName.get(idOrFile);
199 public boolean isPDBFileRegistered(String idOrFile)
201 return pdbFileNameId.containsKey(idOrFile)
202 || pdbIdFileName.containsKey(idOrFile);
205 private static StructureSelectionManager nullProvider = null;
207 public static StructureSelectionManager getStructureSelectionManager(
208 StructureSelectionManagerProvider context)
212 if (nullProvider == null)
214 if (instances != null)
218 .getString("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().substring(
436 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,
580 maxChainId, 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).append(
640 "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 ");
672 mappingDetails.append(
673 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
675 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
676 + (seq.getStart() - 1)));
677 mappingDetails.append(NEWLINE);
678 maxChain.makeExactMapping(maxAlignseq, seq);
679 jalview.datamodel.Mapping sqmpping = maxAlignseq
680 .getMappingFromS1(false);
681 maxChain.transferRESNUMFeatures(seq, null);
683 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
690 Atom tmp = maxChain.atoms.elementAt(index);
691 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
692 && tmp.alignmentMapping != -1)
694 resNum = tmp.resNumber;
695 insCode = tmp.insCode;
696 if (tmp.alignmentMapping >= -1)
698 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
704 } while (index < maxChain.atoms.size());
706 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
707 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
708 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
712 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
714 listeners.removeElement(svl);
715 if (svl instanceof SequenceListener)
717 for (int i = 0; i < listeners.size(); i++)
719 if (listeners.elementAt(i) instanceof StructureListener)
721 ((StructureListener) listeners.elementAt(i))
722 .releaseReferences(svl);
727 if (pdbfiles == null)
733 * Remove mappings to the closed listener's PDB files, but first check if
734 * another listener is still interested
736 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
738 StructureListener sl;
739 for (int i = 0; i < listeners.size(); i++)
741 if (listeners.elementAt(i) instanceof StructureListener)
743 sl = (StructureListener) listeners.elementAt(i);
744 for (String pdbfile : sl.getStructureFiles())
746 pdbs.remove(pdbfile);
752 * Rebuild the mappings set, retaining only those which are for 'other' PDB
757 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
758 for (StructureMapping sm : mappings)
760 if (!pdbs.contains(sm.pdbfile))
771 * Propagate mouseover of a single position in a structure
777 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
779 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
780 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
781 mouseOverStructure(atoms);
785 * Propagate mouseover or selection of multiple positions in a structure
789 public void mouseOverStructure(List<AtomSpec> atoms)
791 if (listeners == null)
793 // old or prematurely sent event
796 boolean hasSequenceListener = false;
797 for (int i = 0; i < listeners.size(); i++)
799 if (listeners.elementAt(i) instanceof SequenceListener)
801 hasSequenceListener = true;
804 if (!hasSequenceListener)
809 SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms);
810 for (Object li : listeners)
812 if (li instanceof SequenceListener)
814 ((SequenceListener) li).highlightSequence(results);
820 * Constructs a SearchResults object holding regions (if any) in the Jalview
821 * alignment which have a mapping to the structure viewer positions in the
827 public SearchResultsI findAlignmentPositionsForStructurePositions(
828 List<AtomSpec> atoms)
830 SearchResultsI results = new SearchResults();
831 for (AtomSpec atom : atoms)
833 SequenceI lastseq = null;
835 for (StructureMapping sm : mappings)
837 if (sm.pdbfile.equals(atom.getPdbFile())
838 && sm.pdbchain.equals(atom.getChain()))
840 int indexpos = sm.getSeqPos(atom.getPdbResNum());
841 if (lastipos != indexpos && lastseq != sm.sequence)
843 results.addResult(sm.sequence, indexpos, indexpos);
845 lastseq = sm.sequence;
846 // construct highlighted sequence list
847 for (AlignedCodonFrame acf : seqmappings)
849 acf.markMappedRegion(sm.sequence, indexpos, results);
859 * highlight regions associated with a position (indexpos) in seq
862 * the sequence that the mouse over occurred on
864 * the absolute position being mouseovered in seq (0 to seq.length())
866 * the sequence position (if -1, seq.findPosition is called to
867 * resolve the residue number)
869 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
872 boolean hasSequenceListeners = handlingVamsasMo
873 || !seqmappings.isEmpty();
874 SearchResultsI results = null;
877 seqPos = seq.findPosition(indexpos);
879 for (int i = 0; i < listeners.size(); i++)
881 Object listener = listeners.elementAt(i);
882 if (listener == source)
884 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
885 // Temporary fudge with SequenceListener.getVamsasSource()
888 if (listener instanceof StructureListener)
890 highlightStructure((StructureListener) listener, seq, seqPos);
894 if (listener instanceof SequenceListener)
896 final SequenceListener seqListener = (SequenceListener) listener;
897 if (hasSequenceListeners
898 && seqListener.getVamsasSource() != source)
900 if (relaySeqMappings)
904 results = MappingUtils.buildSearchResults(seq, seqPos,
907 if (handlingVamsasMo)
909 results.addResult(seq, seqPos, seqPos);
912 if (!results.isEmpty())
914 seqListener.highlightSequence(results);
919 else if (listener instanceof VamsasListener && !handlingVamsasMo)
921 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
924 else if (listener instanceof SecondaryStructureListener)
926 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
934 * Send suitable messages to a StructureListener to highlight atoms
935 * corresponding to the given sequence position(s)
941 public void highlightStructure(StructureListener sl, SequenceI seq,
944 if (!sl.isListeningFor(seq))
949 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
950 for (StructureMapping sm : mappings)
952 if (sm.sequence == seq
953 || sm.sequence == seq.getDatasetSequence()
954 || (sm.sequence.getDatasetSequence() != null && sm.sequence
955 .getDatasetSequence() == seq.getDatasetSequence()))
957 for (int index : positions)
959 atomNo = sm.getAtomNum(index);
963 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
964 .getPDBResNum(index), atomNo));
969 sl.highlightAtoms(atoms);
973 * true if a mouse over event from an external (ie Vamsas) source is being
976 boolean handlingVamsasMo = false;
981 * as mouseOverSequence but only route event to SequenceListeners
985 * in an alignment sequence
987 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
990 handlingVamsasMo = true;
991 long msg = sequenceI.hashCode() * (1 + position);
995 mouseOverSequence(sequenceI, position, -1, source);
997 handlingVamsasMo = false;
1000 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1004 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1005 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1007 * Annotation [] annotations = new Annotation[seq.getLength()];
1009 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1010 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1011 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1013 * for (int j = 0; j < mappings.length; j++) {
1015 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1016 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1017 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1018 * "+mappings[j].pdbfile);
1020 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1021 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1023 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1024 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1025 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1026 * mappings[j].pdbfile); }
1028 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1029 * annotations; } } } }
1031 * return annotations;
1035 public void structureSelectionChanged()
1039 public void sequenceSelectionChanged()
1043 public void sequenceColoursChanged(Object source)
1045 StructureListener sl;
1046 for (int i = 0; i < listeners.size(); i++)
1048 if (listeners.elementAt(i) instanceof StructureListener)
1050 sl = (StructureListener) listeners.elementAt(i);
1051 sl.updateColours(source);
1056 public StructureMapping[] getMapping(String pdbfile)
1058 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1059 for (StructureMapping sm : mappings)
1061 if (sm.pdbfile.equals(pdbfile))
1066 return tmp.toArray(new StructureMapping[tmp.size()]);
1070 * Returns a readable description of all mappings for the given pdbfile to any
1071 * of the given sequences
1077 public String printMappings(String pdbfile, List<SequenceI> seqs)
1079 if (pdbfile == null || seqs == null || seqs.isEmpty())
1084 StringBuilder sb = new StringBuilder(64);
1085 for (StructureMapping sm : mappings)
1087 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1089 sb.append(sm.mappingDetails);
1091 // separator makes it easier to read multiple mappings
1092 sb.append("=====================");
1098 return sb.toString();
1102 * Remove the given mapping
1106 public void deregisterMapping(AlignedCodonFrame acf)
1110 boolean removed = seqmappings.remove(acf);
1111 if (removed && seqmappings.isEmpty())
1113 System.out.println("All mappings removed");
1119 * Add each of the given codonFrames to the stored set, if not aready present.
1123 public void registerMappings(List<AlignedCodonFrame> mappings)
1125 if (mappings != null)
1127 for (AlignedCodonFrame acf : mappings)
1129 registerMapping(acf);
1135 * Add the given mapping to the stored set, unless already stored.
1137 public void registerMapping(AlignedCodonFrame acf)
1141 if (!seqmappings.contains(acf))
1143 seqmappings.add(acf);
1149 * Resets this object to its initial state by removing all registered
1150 * listeners, codon mappings, PDB file mappings
1152 public void resetAll()
1154 if (mappings != null)
1158 if (seqmappings != null)
1160 seqmappings.clear();
1162 if (sel_listeners != null)
1164 sel_listeners.clear();
1166 if (listeners != null)
1170 if (commandListeners != null)
1172 commandListeners.clear();
1174 if (view_listeners != null)
1176 view_listeners.clear();
1178 if (pdbFileNameId != null)
1180 pdbFileNameId.clear();
1182 if (pdbIdFileName != null)
1184 pdbIdFileName.clear();
1188 public void addSelectionListener(SelectionListener selecter)
1190 if (!sel_listeners.contains(selecter))
1192 sel_listeners.add(selecter);
1196 public void removeSelectionListener(SelectionListener toremove)
1198 if (sel_listeners.contains(toremove))
1200 sel_listeners.remove(toremove);
1204 public synchronized void sendSelection(
1205 jalview.datamodel.SequenceGroup selection,
1206 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1208 for (SelectionListener slis : sel_listeners)
1212 slis.selection(selection, colsel, source);
1217 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1219 public synchronized void sendViewPosition(
1220 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1221 int startSeq, int endSeq)
1224 if (view_listeners != null && view_listeners.size() > 0)
1226 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1228 while (listeners.hasMoreElements())
1230 AlignmentViewPanelListener slis = listeners.nextElement();
1233 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1241 * release all references associated with this manager provider
1243 * @param jalviewLite
1245 public static void release(StructureSelectionManagerProvider jalviewLite)
1247 // synchronized (instances)
1249 if (instances == null)
1253 StructureSelectionManager mnger = (instances.get(jalviewLite));
1256 instances.remove(jalviewLite);
1260 } catch (Throwable x)
1267 public void registerPDBEntry(PDBEntry pdbentry)
1269 if (pdbentry.getFile() != null
1270 && pdbentry.getFile().trim().length() > 0)
1272 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1276 public void addCommandListener(CommandListener cl)
1278 if (!commandListeners.contains(cl))
1280 commandListeners.add(cl);
1284 public boolean hasCommandListener(CommandListener cl)
1286 return this.commandListeners.contains(cl);
1289 public boolean removeCommandListener(CommandListener l)
1291 return commandListeners.remove(l);
1295 * Forward a command to any command listeners (except for the command's
1299 * the command to be broadcast (in its form after being performed)
1301 * if true, the command was being 'undone'
1304 public void commandPerformed(CommandI command, boolean undo,
1305 VamsasSource source)
1307 for (CommandListener listener : commandListeners)
1309 listener.mirrorCommand(command, undo, this, source);
1314 * Returns a new CommandI representing the given command as mapped to the
1315 * given sequences. If no mapping could be made, or the command is not of a
1316 * mappable kind, returns null.
1324 public CommandI mapCommand(CommandI command, boolean undo,
1325 final AlignmentI mapTo, char gapChar)
1327 if (command instanceof EditCommand)
1329 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1330 mapTo, gapChar, seqmappings);
1332 else if (command instanceof OrderCommand)
1334 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1335 mapTo, seqmappings);
1340 public IProgressIndicator getProgressIndicator()
1342 return progressIndicator;
1345 public void setProgressIndicator(IProgressIndicator progressIndicator)
1347 this.progressIndicator = progressIndicator;
1350 public long getProgressSessionId()
1352 return progressSessionId;
1355 public void setProgressSessionId(long progressSessionId)
1357 this.progressSessionId = progressSessionId;
1360 public void setProgressBar(String message)
1362 if (progressIndicator == null)
1366 progressIndicator.setProgressBar(message, progressSessionId);
1369 public List<AlignedCodonFrame> getSequenceMappings()