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.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 pdb = new JmolParser(pdbFile, sourceType);
390 if (pdb.getId() != null && pdb.getId().trim().length() > 0
391 && DataSourceType.FILE == sourceType)
393 registerPDBFile(pdb.getId().trim(), pdbFile);
395 // if PDBId is unavailable then skip SIFTS mapping execution path
396 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
398 } catch (Exception ex)
400 ex.printStackTrace();
408 siftsClient = new SiftsClient(pdb);
410 } catch (SiftsException e)
412 isMapUsingSIFTs = false;
416 String targetChainId;
417 for (int s = 0; s < sequenceArray.length; s++)
419 boolean infChain = true;
420 final SequenceI seq = sequenceArray[s];
422 while (ds.getDatasetSequence() != null)
424 ds = ds.getDatasetSequence();
427 if (targetChainIds != null && targetChainIds[s] != null)
430 targetChainId = targetChainIds[s];
432 else if (seq.getName().indexOf("|") > -1)
434 targetChainId = seq.getName().substring(
435 seq.getName().lastIndexOf("|") + 1);
436 if (targetChainId.length() > 1)
438 if (targetChainId.trim().length() == 0)
444 // not a valid chain identifier
455 * Attempt pairwise alignment of the sequence with each chain in the PDB,
456 * and remember the highest scoring chain
459 AlignSeq maxAlignseq = null;
460 String maxChainId = " ";
461 PDBChain maxChain = null;
462 boolean first = true;
463 for (PDBChain chain : pdb.getChains())
465 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
468 continue; // don't try to map chains don't match.
470 // TODO: correctly determine sequence type for mixed na/peptide
472 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
473 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
476 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
477 // as.calcScoreMatrix();
478 // as.traceAlignment();
480 if (first || as.maxscore > max
481 || (as.maxscore == max && chain.id.equals(targetChainId)))
487 maxChainId = chain.id;
490 if (maxChain == null)
495 if (sourceType == DataSourceType.PASTE)
497 pdbFile = "INLINE" + pdb.getId();
500 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
501 if (isMapUsingSIFTs && seq.isProtein())
503 setProgressBar(null);
504 setProgressBar(MessageManager
505 .getString("status.obtaining_mapping_with_sifts"));
506 jalview.datamodel.Mapping sqmpping = maxAlignseq
507 .getMappingFromS1(false);
508 if (targetChainId != null && !targetChainId.trim().isEmpty())
510 StructureMapping siftsMapping;
513 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
514 pdb, maxChain, sqmpping, maxAlignseq);
515 seqToStrucMapping.add(siftsMapping);
516 maxChain.makeExactMapping(maxAlignseq, seq);
517 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
519 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
520 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
522 } catch (SiftsException e)
524 // fall back to NW alignment
525 System.err.println(e.getMessage());
526 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
527 targetChainId, maxChain, pdb, maxAlignseq);
528 seqToStrucMapping.add(nwMapping);
529 maxChain.makeExactMapping(maxAlignseq, seq);
530 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
532 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
533 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
538 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
539 for (PDBChain chain : pdb.getChains())
543 StructureMapping siftsMapping = getStructureMapping(seq,
544 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
545 foundSiftsMappings.add(siftsMapping);
546 } catch (SiftsException e)
548 System.err.println(e.getMessage());
551 if (!foundSiftsMappings.isEmpty())
553 seqToStrucMapping.addAll(foundSiftsMappings);
554 maxChain.makeExactMapping(maxAlignseq, seq);
555 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
557 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
559 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
563 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
564 maxChainId, maxChain, pdb, maxAlignseq);
565 seqToStrucMapping.add(nwMapping);
566 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
568 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
569 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
575 setProgressBar(null);
576 setProgressBar(MessageManager
577 .getString("status.obtaining_mapping_with_nw_alignment"));
578 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
579 maxChainId, maxChain, pdb, maxAlignseq);
580 seqToStrucMapping.add(nwMapping);
581 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
585 if (forStructureView)
587 mappings.addAll(seqToStrucMapping);
593 public void addStructureMapping(StructureMapping sm)
599 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
604 * @param targetChainId
610 * @throws SiftsException
612 private StructureMapping getStructureMapping(SequenceI seq,
613 String pdbFile, String targetChainId, StructureFile pdb,
614 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
615 AlignSeq maxAlignseq) throws SiftsException
617 StructureMapping curChainMapping = siftsClient
618 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
621 PDBChain chain = pdb.findChain(targetChainId);
624 chain.transferResidueAnnotation(curChainMapping, sqmpping);
626 } catch (Exception e)
630 return curChainMapping;
633 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
634 String maxChainId, PDBChain maxChain, StructureFile pdb,
635 AlignSeq maxAlignseq)
637 final StringBuilder mappingDetails = new StringBuilder(128);
638 mappingDetails.append(NEWLINE).append(
639 "Sequence \u27f7 Structure mapping details");
640 mappingDetails.append(NEWLINE);
642 .append("Method: inferred with Needleman & Wunsch alignment");
643 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
644 .append(NEWLINE).append("Sequence = ")
645 .append(maxChain.sequence.getSequenceAsString());
646 mappingDetails.append(NEWLINE).append("No of residues = ")
647 .append(maxChain.residues.size()).append(NEWLINE)
649 PrintStream ps = new PrintStream(System.out)
652 public void print(String x)
654 mappingDetails.append(x);
658 public void println()
660 mappingDetails.append(NEWLINE);
664 maxAlignseq.printAlignment(ps);
666 mappingDetails.append(NEWLINE).append("PDB start/end ");
667 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
669 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
670 mappingDetails.append(NEWLINE).append("SEQ start/end ");
671 mappingDetails.append(
672 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
674 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
675 + (seq.getStart() - 1)));
676 mappingDetails.append(NEWLINE);
677 maxChain.makeExactMapping(maxAlignseq, seq);
678 jalview.datamodel.Mapping sqmpping = maxAlignseq
679 .getMappingFromS1(false);
680 maxChain.transferRESNUMFeatures(seq, null);
682 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
689 Atom tmp = maxChain.atoms.elementAt(index);
690 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
691 && tmp.alignmentMapping != -1)
693 resNum = tmp.resNumber;
694 insCode = tmp.insCode;
695 if (tmp.alignmentMapping >= -1)
697 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
703 } while (index < maxChain.atoms.size());
705 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
706 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
707 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
711 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
713 listeners.removeElement(svl);
714 if (svl instanceof SequenceListener)
716 for (int i = 0; i < listeners.size(); i++)
718 if (listeners.elementAt(i) instanceof StructureListener)
720 ((StructureListener) listeners.elementAt(i))
721 .releaseReferences(svl);
726 if (pdbfiles == null)
732 * Remove mappings to the closed listener's PDB files, but first check if
733 * another listener is still interested
735 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
737 StructureListener sl;
738 for (int i = 0; i < listeners.size(); i++)
740 if (listeners.elementAt(i) instanceof StructureListener)
742 sl = (StructureListener) listeners.elementAt(i);
743 for (String pdbfile : sl.getPdbFile())
745 pdbs.remove(pdbfile);
751 * Rebuild the mappings set, retaining only those which are for 'other' PDB
756 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
757 for (StructureMapping sm : mappings)
759 if (!pdbs.contains(sm.pdbfile))
770 * Propagate mouseover of a single position in a structure
776 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
778 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
779 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
780 mouseOverStructure(atoms);
784 * Propagate mouseover or selection of multiple positions in a structure
788 public void mouseOverStructure(List<AtomSpec> atoms)
790 if (listeners == null)
792 // old or prematurely sent event
795 boolean hasSequenceListener = false;
796 for (int i = 0; i < listeners.size(); i++)
798 if (listeners.elementAt(i) instanceof SequenceListener)
800 hasSequenceListener = true;
803 if (!hasSequenceListener)
808 SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms);
809 for (Object li : listeners)
811 if (li instanceof SequenceListener)
813 ((SequenceListener) li).highlightSequence(results);
819 * Constructs a SearchResults object holding regions (if any) in the Jalview
820 * alignment which have a mapping to the structure viewer positions in the
826 public SearchResultsI findAlignmentPositionsForStructurePositions(
827 List<AtomSpec> atoms)
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);
858 * highlight regions associated with a position (indexpos) in seq
861 * the sequence that the mouse over occurred on
863 * the absolute position being mouseovered in seq (0 to seq.length())
865 * the sequence position (if -1, seq.findPosition is called to
866 * resolve the residue number)
868 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
871 boolean hasSequenceListeners = handlingVamsasMo
872 || !seqmappings.isEmpty();
873 SearchResultsI results = null;
876 seqPos = seq.findPosition(indexpos);
878 for (int i = 0; i < listeners.size(); i++)
880 Object listener = listeners.elementAt(i);
881 if (listener == source)
883 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
884 // Temporary fudge with SequenceListener.getVamsasSource()
887 if (listener instanceof StructureListener)
889 highlightStructure((StructureListener) listener, seq, seqPos);
893 if (listener instanceof SequenceListener)
895 final SequenceListener seqListener = (SequenceListener) listener;
896 if (hasSequenceListeners
897 && seqListener.getVamsasSource() != source)
899 if (relaySeqMappings)
903 results = MappingUtils.buildSearchResults(seq, seqPos,
906 if (handlingVamsasMo)
908 results.addResult(seq, seqPos, seqPos);
911 if (!results.isEmpty())
913 seqListener.highlightSequence(results);
918 else if (listener instanceof VamsasListener && !handlingVamsasMo)
920 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
923 else if (listener instanceof SecondaryStructureListener)
925 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
933 * Send suitable messages to a StructureListener to highlight atoms
934 * corresponding to the given sequence position(s)
940 public void highlightStructure(StructureListener sl, SequenceI seq,
943 if (!sl.isListeningFor(seq))
948 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
949 for (StructureMapping sm : mappings)
951 if (sm.sequence == seq
952 || sm.sequence == seq.getDatasetSequence()
953 || (sm.sequence.getDatasetSequence() != null && sm.sequence
954 .getDatasetSequence() == seq.getDatasetSequence()))
956 for (int index : positions)
958 atomNo = sm.getAtomNum(index);
962 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
963 .getPDBResNum(index), atomNo));
968 sl.highlightAtoms(atoms);
972 * true if a mouse over event from an external (ie Vamsas) source is being
975 boolean handlingVamsasMo = false;
980 * as mouseOverSequence but only route event to SequenceListeners
984 * in an alignment sequence
986 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
989 handlingVamsasMo = true;
990 long msg = sequenceI.hashCode() * (1 + position);
994 mouseOverSequence(sequenceI, position, -1, source);
996 handlingVamsasMo = false;
999 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1003 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1004 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1006 * Annotation [] annotations = new Annotation[seq.getLength()];
1008 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1009 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1010 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1012 * for (int j = 0; j < mappings.length; j++) {
1014 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1015 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1016 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1017 * "+mappings[j].pdbfile);
1019 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1020 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1022 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1023 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1024 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1025 * mappings[j].pdbfile); }
1027 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1028 * annotations; } } } }
1030 * return annotations;
1034 public void structureSelectionChanged()
1038 public void sequenceSelectionChanged()
1042 public void sequenceColoursChanged(Object source)
1044 StructureListener sl;
1045 for (int i = 0; i < listeners.size(); i++)
1047 if (listeners.elementAt(i) instanceof StructureListener)
1049 sl = (StructureListener) listeners.elementAt(i);
1050 sl.updateColours(source);
1055 public StructureMapping[] getMapping(String pdbfile)
1057 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1058 for (StructureMapping sm : mappings)
1060 if (sm.pdbfile.equals(pdbfile))
1065 return tmp.toArray(new StructureMapping[tmp.size()]);
1069 * Returns a readable description of all mappings for the given pdbfile to any
1070 * of the given sequences
1076 public String printMappings(String pdbfile, List<SequenceI> seqs)
1078 if (pdbfile == null || seqs == null || seqs.isEmpty())
1083 StringBuilder sb = new StringBuilder(64);
1084 for (StructureMapping sm : mappings)
1086 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1088 sb.append(sm.mappingDetails);
1090 // separator makes it easier to read multiple mappings
1091 sb.append("=====================");
1097 return sb.toString();
1101 * Remove the given mapping
1105 public void deregisterMapping(AlignedCodonFrame acf)
1109 boolean removed = seqmappings.remove(acf);
1110 if (removed && seqmappings.isEmpty())
1112 System.out.println("All mappings removed");
1118 * Add each of the given codonFrames to the stored set, if not aready present.
1122 public void registerMappings(List<AlignedCodonFrame> mappings)
1124 if (mappings != null)
1126 for (AlignedCodonFrame acf : mappings)
1128 registerMapping(acf);
1134 * Add the given mapping to the stored set, unless already stored.
1136 public void registerMapping(AlignedCodonFrame acf)
1140 if (!seqmappings.contains(acf))
1142 seqmappings.add(acf);
1148 * Resets this object to its initial state by removing all registered
1149 * listeners, codon mappings, PDB file mappings
1151 public void resetAll()
1153 if (mappings != null)
1157 if (seqmappings != null)
1159 seqmappings.clear();
1161 if (sel_listeners != null)
1163 sel_listeners.clear();
1165 if (listeners != null)
1169 if (commandListeners != null)
1171 commandListeners.clear();
1173 if (view_listeners != null)
1175 view_listeners.clear();
1177 if (pdbFileNameId != null)
1179 pdbFileNameId.clear();
1181 if (pdbIdFileName != null)
1183 pdbIdFileName.clear();
1187 public void addSelectionListener(SelectionListener selecter)
1189 if (!sel_listeners.contains(selecter))
1191 sel_listeners.add(selecter);
1195 public void removeSelectionListener(SelectionListener toremove)
1197 if (sel_listeners.contains(toremove))
1199 sel_listeners.remove(toremove);
1203 public synchronized void sendSelection(
1204 jalview.datamodel.SequenceGroup selection,
1205 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1206 SelectionSource source)
1208 for (SelectionListener slis : sel_listeners)
1212 slis.selection(selection, colsel, hidden, 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()