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.StructureFile;
40 import jalview.util.MappingUtils;
41 import jalview.util.MessageManager;
42 import jalview.ws.sifts.SiftsClient;
43 import jalview.ws.sifts.SiftsException;
44 import jalview.ws.sifts.SiftsSettings;
46 import java.io.PrintStream;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.Collections;
50 import java.util.Enumeration;
51 import java.util.HashMap;
52 import java.util.IdentityHashMap;
53 import java.util.List;
55 import java.util.Vector;
58 import MCview.PDBChain;
59 import MCview.PDBfile;
61 public class StructureSelectionManager
63 public final static String NEWLINE = System.lineSeparator();
65 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
67 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
69 private boolean processSecondaryStructure = false;
71 private boolean secStructServices = false;
73 private boolean addTempFacAnnot = false;
75 private IProgressIndicator progressIndicator;
77 private SiftsClient siftsClient = null;
79 private long progressSessionId;
82 * Set of any registered mappings between (dataset) sequences.
84 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
86 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
88 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
91 * @return true if will try to use external services for processing secondary
94 public boolean isSecStructServices()
96 return secStructServices;
100 * control use of external services for processing secondary structure
102 * @param secStructServices
104 public void setSecStructServices(boolean secStructServices)
106 this.secStructServices = secStructServices;
110 * flag controlling addition of any kind of structural annotation
112 * @return true if temperature factor annotation will be added
114 public boolean isAddTempFacAnnot()
116 return addTempFacAnnot;
120 * set flag controlling addition of structural annotation
122 * @param addTempFacAnnot
124 public void setAddTempFacAnnot(boolean addTempFacAnnot)
126 this.addTempFacAnnot = addTempFacAnnot;
131 * @return if true, the structure manager will attempt to add secondary
132 * structure lines for unannotated sequences
135 public boolean isProcessSecondaryStructure()
137 return processSecondaryStructure;
141 * Control whether structure manager will try to annotate mapped sequences
142 * with secondary structure from PDB data.
146 public void setProcessSecondaryStructure(boolean enable)
148 processSecondaryStructure = enable;
152 * debug function - write all mappings to stdout
154 public void reportMapping()
156 if (mappings.isEmpty())
158 System.err.println("reportMapping: No PDB/Sequence mappings.");
162 System.err.println("reportMapping: There are " + mappings.size()
165 for (StructureMapping sm : mappings)
167 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
173 * map between the PDB IDs (or structure identifiers) used by Jalview and the
174 * absolute filenames for PDB data that corresponds to it
176 Map<String, String> pdbIdFileName = new HashMap<String, String>();
178 Map<String, String> pdbFileNameId = new HashMap<String, String>();
180 public void registerPDBFile(String idForFile, String absoluteFile)
182 pdbIdFileName.put(idForFile, absoluteFile);
183 pdbFileNameId.put(absoluteFile, idForFile);
186 public String findIdForPDBFile(String idOrFile)
188 String id = pdbFileNameId.get(idOrFile);
192 public String findFileForPDBId(String idOrFile)
194 String id = pdbIdFileName.get(idOrFile);
198 public boolean isPDBFileRegistered(String idOrFile)
200 return pdbFileNameId.containsKey(idOrFile)
201 || pdbIdFileName.containsKey(idOrFile);
204 private static StructureSelectionManager nullProvider = null;
206 public static StructureSelectionManager getStructureSelectionManager(
207 StructureSelectionManagerProvider context)
211 if (nullProvider == null)
213 if (instances != null)
217 .getString("error.implementation_error_structure_selection_manager_null"),
218 new NullPointerException(MessageManager
219 .getString("exception.ssm_context_is_null")));
223 nullProvider = new StructureSelectionManager();
228 if (instances == null)
230 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
232 StructureSelectionManager instance = instances.get(context);
233 if (instance == null)
235 if (nullProvider != null)
237 instance = nullProvider;
241 instance = new StructureSelectionManager();
243 instances.put(context, instance);
249 * flag controlling whether SeqMappings are relayed from received sequence
250 * mouse over events to other sequences
252 boolean relaySeqMappings = true;
255 * Enable or disable relay of seqMapping events to other sequences. You might
256 * want to do this if there are many sequence mappings and the host computer
261 public void setRelaySeqMappings(boolean relay)
263 relaySeqMappings = relay;
267 * get the state of the relay seqMappings flag.
269 * @return true if sequence mouse overs are being relayed to other mapped
272 public boolean isRelaySeqMappingsEnabled()
274 return relaySeqMappings;
277 Vector listeners = new Vector();
280 * register a listener for alignment sequence mouseover events
284 public void addStructureViewerListener(Object svl)
286 if (!listeners.contains(svl))
288 listeners.addElement(svl);
293 * Returns the file name for a mapped PDB id (or null if not mapped).
298 public String alreadyMappedToFile(String pdbid)
300 for (StructureMapping sm : mappings)
302 if (sm.getPdbId().equals(pdbid))
311 * Import structure data and register a structure mapping for broadcasting
312 * colouring, mouseovers and selection events (convenience wrapper).
315 * - one or more sequences to be mapped to pdbFile
316 * @param targetChains
317 * - optional chain specification for mapping each sequence to pdb
318 * (may be nill, individual elements may be nill)
320 * - structure data resource
322 * - how to resolve data from resource
323 * @return null or the structure data parsed as a pdb file
325 synchronized public StructureFile setMapping(SequenceI[] sequence,
326 String[] targetChains, String pdbFile, String protocol)
328 return setMapping(true, sequence, targetChains, pdbFile, protocol);
332 * create sequence structure mappings between each sequence and the given
333 * pdbFile (retrieved via the given protocol).
335 * @param forStructureView
336 * when true, record the mapping for use in mouseOvers
338 * @param sequenceArray
339 * - one or more sequences to be mapped to pdbFile
340 * @param targetChainIds
341 * - optional chain specification for mapping each sequence to pdb
342 * (may be nill, individual elements may be nill)
344 * - structure data resource
346 * - how to resolve data from resource
347 * @return null or the structure data parsed as a pdb file
349 synchronized public StructureFile setMapping(boolean forStructureView,
350 SequenceI[] sequenceArray, String[] targetChainIds,
351 String pdbFile, String protocol)
354 * There will be better ways of doing this in the future, for now we'll use
355 * the tried and tested MCview pdb mapping
357 boolean parseSecStr = processSecondaryStructure;
358 if (isPDBFileRegistered(pdbFile))
360 for (SequenceI sq : sequenceArray)
363 while (ds.getDatasetSequence() != null)
365 ds = ds.getDatasetSequence();
368 if (ds.getAnnotation() != null)
370 for (AlignmentAnnotation ala : ds.getAnnotation())
372 // false if any annotation present from this structure
373 // JBPNote this fails for jmol/chimera view because the *file* is
374 // passed, not the structure data ID -
375 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
383 StructureFile pdb = null;
384 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
387 pdb = new JmolParser(pdbFile, protocol);
389 if (pdb.getId() != null && pdb.getId().trim().length() > 0
390 && AppletFormatAdapter.FILE.equals(protocol))
392 registerPDBFile(pdb.getId().trim(), pdbFile);
394 // if PDBId is unavailable then skip SIFTS mapping execution path
395 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
397 } catch (Exception ex)
399 ex.printStackTrace();
407 siftsClient = new SiftsClient(pdb);
409 } catch (SiftsException e)
411 isMapUsingSIFTs = false;
415 String targetChainId;
416 for (int s = 0; s < sequenceArray.length; s++)
418 boolean infChain = true;
419 final SequenceI seq = sequenceArray[s];
421 while (ds.getDatasetSequence() != null)
423 ds = ds.getDatasetSequence();
426 if (targetChainIds != null && targetChainIds[s] != null)
429 targetChainId = targetChainIds[s];
431 else if (seq.getName().indexOf("|") > -1)
433 targetChainId = seq.getName().substring(
434 seq.getName().lastIndexOf("|") + 1);
435 if (targetChainId.length() > 1)
437 if (targetChainId.trim().length() == 0)
443 // not a valid chain identifier
454 * Attempt pairwise alignment of the sequence with each chain in the PDB,
455 * and remember the highest scoring chain
458 AlignSeq maxAlignseq = null;
459 String maxChainId = " ";
460 PDBChain maxChain = null;
461 boolean first = true;
462 for (PDBChain chain : pdb.getChains())
464 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
467 continue; // don't try to map chains don't match.
469 // TODO: correctly determine sequence type for mixed na/peptide
471 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
472 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
475 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
476 // as.calcScoreMatrix();
477 // as.traceAlignment();
479 if (first || as.maxscore > max
480 || (as.maxscore == max && chain.id.equals(targetChainId)))
486 maxChainId = chain.id;
489 if (maxChain == null)
494 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
496 pdbFile = "INLINE" + pdb.getId();
499 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
500 if (isMapUsingSIFTs && seq.isProtein())
502 setProgressBar(null);
503 setProgressBar(MessageManager
504 .getString("status.obtaining_mapping_with_sifts"));
505 jalview.datamodel.Mapping sqmpping = maxAlignseq
506 .getMappingFromS1(false);
507 if (targetChainId != null && !targetChainId.trim().isEmpty())
509 StructureMapping siftsMapping;
512 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
513 pdb, maxChain, sqmpping, maxAlignseq);
514 seqToStrucMapping.add(siftsMapping);
515 maxChain.makeExactMapping(maxAlignseq, seq);
516 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
518 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
519 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
521 } catch (SiftsException e)
523 // fall back to NW alignment
524 System.err.println(e.getMessage());
525 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
526 targetChainId, maxChain, pdb, maxAlignseq);
527 seqToStrucMapping.add(nwMapping);
528 maxChain.makeExactMapping(maxAlignseq, seq);
529 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
531 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
532 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
537 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
538 for (PDBChain chain : pdb.getChains())
542 StructureMapping siftsMapping = getStructureMapping(seq,
543 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
544 foundSiftsMappings.add(siftsMapping);
545 } catch (SiftsException e)
547 System.err.println(e.getMessage());
550 if (!foundSiftsMappings.isEmpty())
552 seqToStrucMapping.addAll(foundSiftsMappings);
553 maxChain.makeExactMapping(maxAlignseq, seq);
554 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
556 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
558 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
562 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
563 maxChainId, maxChain, pdb, maxAlignseq);
564 seqToStrucMapping.add(nwMapping);
565 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
567 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
568 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
574 setProgressBar(null);
575 setProgressBar(MessageManager
576 .getString("status.obtaining_mapping_with_nw_alignment"));
577 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
578 maxChainId, maxChain, pdb, maxAlignseq);
579 seqToStrucMapping.add(nwMapping);
580 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
584 if (forStructureView)
586 mappings.addAll(seqToStrucMapping);
592 private boolean isCIFFile(String filename)
594 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
596 return "cif".equalsIgnoreCase(fileExt);
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.getPdbFile())
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 SearchResults findAlignmentPositionsForStructurePositions(
828 List<AtomSpec> atoms)
830 SearchResults 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()