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) - JBPNote: JAL-2693
344 * - this should be List<List<String>>, empty lists indicate no
345 * predefined mappings
347 * - structure data resource
349 * - how to resolve data from resource
350 * @return null or the structure data parsed as a pdb file
352 synchronized public StructureFile setMapping(boolean forStructureView,
353 SequenceI[] sequenceArray, String[] targetChainIds,
354 String pdbFile, DataSourceType sourceType)
357 * There will be better ways of doing this in the future, for now we'll use
358 * the tried and tested MCview pdb mapping
360 boolean parseSecStr = processSecondaryStructure;
361 if (isPDBFileRegistered(pdbFile))
363 for (SequenceI sq : sequenceArray)
366 while (ds.getDatasetSequence() != null)
368 ds = ds.getDatasetSequence();
371 if (ds.getAnnotation() != null)
373 for (AlignmentAnnotation ala : ds.getAnnotation())
375 // false if any annotation present from this structure
376 // JBPNote this fails for jmol/chimera view because the *file* is
377 // passed, not the structure data ID -
378 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
386 StructureFile pdb = null;
387 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
390 sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
391 pdb = new JmolParser(pdbFile, sourceType);
393 if (pdb.getId() != null && pdb.getId().trim().length() > 0
394 && DataSourceType.FILE == sourceType)
396 registerPDBFile(pdb.getId().trim(), pdbFile);
398 // if PDBId is unavailable then skip SIFTS mapping execution path
399 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
401 } catch (Exception ex)
403 ex.printStackTrace();
411 siftsClient = new SiftsClient(pdb);
413 } catch (SiftsException e)
415 isMapUsingSIFTs = false;
419 String targetChainId;
420 for (int s = 0; s < sequenceArray.length; s++)
422 boolean infChain = true;
423 final SequenceI seq = sequenceArray[s];
425 while (ds.getDatasetSequence() != null)
427 ds = ds.getDatasetSequence();
430 if (targetChainIds != null && targetChainIds[s] != null)
433 targetChainId = targetChainIds[s];
435 else if (seq.getName().indexOf("|") > -1)
437 targetChainId = seq.getName()
438 .substring(seq.getName().lastIndexOf("|") + 1);
439 if (targetChainId.length() > 1)
441 if (targetChainId.trim().length() == 0)
447 // not a valid chain identifier
458 * Attempt pairwise alignment of the sequence with each chain in the PDB,
459 * and remember the highest scoring chain
462 AlignSeq maxAlignseq = null;
463 String maxChainId = " ";
464 PDBChain maxChain = null;
465 boolean first = true;
466 for (PDBChain chain : pdb.getChains())
468 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
471 continue; // don't try to map chains don't match.
473 // TODO: correctly determine sequence type for mixed na/peptide
475 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
476 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
479 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
480 // as.calcScoreMatrix();
481 // as.traceAlignment();
483 if (first || as.maxscore > max
484 || (as.maxscore == max && chain.id.equals(targetChainId)))
490 maxChainId = chain.id;
493 if (maxChain == null)
498 if (sourceType == DataSourceType.PASTE)
500 pdbFile = "INLINE" + pdb.getId();
503 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
504 if (isMapUsingSIFTs && seq.isProtein())
506 setProgressBar(null);
507 setProgressBar(MessageManager
508 .getString("status.obtaining_mapping_with_sifts"));
509 jalview.datamodel.Mapping sqmpping = maxAlignseq
510 .getMappingFromS1(false);
511 if (targetChainId != null && !targetChainId.trim().isEmpty())
513 StructureMapping siftsMapping;
516 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
517 pdb, maxChain, sqmpping, maxAlignseq);
518 seqToStrucMapping.add(siftsMapping);
519 maxChain.makeExactMapping(maxAlignseq, seq);
520 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
522 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
523 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
525 } catch (SiftsException e)
527 // fall back to NW alignment
528 System.err.println(e.getMessage());
529 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
530 targetChainId, maxChain, pdb, maxAlignseq);
531 seqToStrucMapping.add(nwMapping);
532 maxChain.makeExactMapping(maxAlignseq, seq);
533 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
535 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
536 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
541 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
542 for (PDBChain chain : pdb.getChains())
546 StructureMapping siftsMapping = getStructureMapping(seq,
547 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
548 foundSiftsMappings.add(siftsMapping);
549 } catch (SiftsException e)
551 System.err.println(e.getMessage());
554 if (!foundSiftsMappings.isEmpty())
556 seqToStrucMapping.addAll(foundSiftsMappings);
557 maxChain.makeExactMapping(maxAlignseq, seq);
558 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
560 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
562 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
566 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
567 maxChainId, maxChain, pdb, maxAlignseq);
568 seqToStrucMapping.add(nwMapping);
569 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
571 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
572 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
578 setProgressBar(null);
579 setProgressBar(MessageManager
580 .getString("status.obtaining_mapping_with_nw_alignment"));
581 StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId,
582 maxChain, pdb, maxAlignseq);
583 seqToStrucMapping.add(nwMapping);
584 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
588 if (forStructureView)
590 mappings.addAll(seqToStrucMapping);
596 public void addStructureMapping(StructureMapping sm)
602 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
607 * @param targetChainId
613 * @throws SiftsException
615 private StructureMapping getStructureMapping(SequenceI seq,
616 String pdbFile, String targetChainId, StructureFile pdb,
617 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
618 AlignSeq maxAlignseq) throws SiftsException
620 StructureMapping curChainMapping = siftsClient
621 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
624 PDBChain chain = pdb.findChain(targetChainId);
627 chain.transferResidueAnnotation(curChainMapping, sqmpping);
629 } catch (Exception e)
633 return curChainMapping;
636 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
637 String maxChainId, PDBChain maxChain, StructureFile pdb,
638 AlignSeq maxAlignseq)
640 final StringBuilder mappingDetails = new StringBuilder(128);
641 mappingDetails.append(NEWLINE)
642 .append("Sequence \u27f7 Structure mapping details");
643 mappingDetails.append(NEWLINE);
645 .append("Method: inferred with Needleman & Wunsch alignment");
646 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
647 .append(NEWLINE).append("Sequence = ")
648 .append(maxChain.sequence.getSequenceAsString());
649 mappingDetails.append(NEWLINE).append("No of residues = ")
650 .append(maxChain.residues.size()).append(NEWLINE)
652 PrintStream ps = new PrintStream(System.out)
655 public void print(String x)
657 mappingDetails.append(x);
661 public void println()
663 mappingDetails.append(NEWLINE);
667 maxAlignseq.printAlignment(ps);
669 mappingDetails.append(NEWLINE).append("PDB start/end ");
670 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
672 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
673 mappingDetails.append(NEWLINE).append("SEQ start/end ");
676 .valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
678 mappingDetails.append(
679 String.valueOf(maxAlignseq.seq1end + (seq.getStart() - 1)));
680 mappingDetails.append(NEWLINE);
681 maxChain.makeExactMapping(maxAlignseq, seq);
682 jalview.datamodel.Mapping sqmpping = maxAlignseq
683 .getMappingFromS1(false);
684 maxChain.transferRESNUMFeatures(seq, null);
686 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
693 Atom tmp = maxChain.atoms.elementAt(index);
694 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
695 && tmp.alignmentMapping != -1)
697 resNum = tmp.resNumber;
698 insCode = tmp.insCode;
699 if (tmp.alignmentMapping >= -1)
701 mapping.put(tmp.alignmentMapping + 1,
703 { tmp.resNumber, tmp.atomIndex });
708 } while (index < maxChain.atoms.size());
710 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
711 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
712 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
716 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
718 listeners.removeElement(svl);
719 if (svl instanceof SequenceListener)
721 for (int i = 0; i < listeners.size(); i++)
723 if (listeners.elementAt(i) instanceof StructureListener)
725 ((StructureListener) listeners.elementAt(i))
726 .releaseReferences(svl);
731 if (pdbfiles == null)
737 * Remove mappings to the closed listener's PDB files, but first check if
738 * another listener is still interested
740 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
742 StructureListener sl;
743 for (int i = 0; i < listeners.size(); i++)
745 if (listeners.elementAt(i) instanceof StructureListener)
747 sl = (StructureListener) listeners.elementAt(i);
748 for (String pdbfile : sl.getStructureFiles())
750 pdbs.remove(pdbfile);
756 * Rebuild the mappings set, retaining only those which are for 'other' PDB
761 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
762 for (StructureMapping sm : mappings)
764 if (!pdbs.contains(sm.pdbfile))
775 * Propagate mouseover of a single position in a structure
781 public void mouseOverStructure(int pdbResNum, String chain,
784 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
785 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
786 mouseOverStructure(atoms);
790 * Propagate mouseover or selection of multiple positions in a structure
794 public void mouseOverStructure(List<AtomSpec> atoms)
796 if (listeners == null)
798 // old or prematurely sent event
801 boolean hasSequenceListener = false;
802 for (int i = 0; i < listeners.size(); i++)
804 if (listeners.elementAt(i) instanceof SequenceListener)
806 hasSequenceListener = true;
809 if (!hasSequenceListener)
814 SearchResultsI results = findAlignmentPositionsForStructurePositions(
816 for (Object li : listeners)
818 if (li instanceof SequenceListener)
820 ((SequenceListener) li).highlightSequence(results);
826 * Constructs a SearchResults object holding regions (if any) in the Jalview
827 * alignment which have a mapping to the structure viewer positions in the
833 public SearchResultsI findAlignmentPositionsForStructurePositions(
834 List<AtomSpec> atoms)
836 SearchResultsI results = new SearchResults();
837 for (AtomSpec atom : atoms)
839 SequenceI lastseq = null;
841 for (StructureMapping sm : mappings)
843 if (sm.pdbfile.equals(atom.getPdbFile())
844 && sm.pdbchain.equals(atom.getChain()))
846 int indexpos = sm.getSeqPos(atom.getPdbResNum());
847 if (lastipos != indexpos && lastseq != sm.sequence)
849 results.addResult(sm.sequence, indexpos, indexpos);
851 lastseq = sm.sequence;
852 // construct highlighted sequence list
853 for (AlignedCodonFrame acf : seqmappings)
855 acf.markMappedRegion(sm.sequence, indexpos, results);
865 * highlight regions associated with a position (indexpos) in seq
868 * the sequence that the mouse over occurred on
870 * the absolute position being mouseovered in seq (0 to seq.length())
872 * the sequence position (if -1, seq.findPosition is called to
873 * resolve the residue number)
875 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
878 boolean hasSequenceListeners = handlingVamsasMo
879 || !seqmappings.isEmpty();
880 SearchResultsI results = null;
883 seqPos = seq.findPosition(indexpos);
885 for (int i = 0; i < listeners.size(); i++)
887 Object listener = listeners.elementAt(i);
888 if (listener == source)
890 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
891 // Temporary fudge with SequenceListener.getVamsasSource()
894 if (listener instanceof StructureListener)
896 highlightStructure((StructureListener) listener, seq, seqPos);
900 if (listener instanceof SequenceListener)
902 final SequenceListener seqListener = (SequenceListener) listener;
903 if (hasSequenceListeners
904 && seqListener.getVamsasSource() != source)
906 if (relaySeqMappings)
910 results = MappingUtils.buildSearchResults(seq, seqPos,
913 if (handlingVamsasMo)
915 results.addResult(seq, seqPos, seqPos);
918 if (!results.isEmpty())
920 seqListener.highlightSequence(results);
925 else if (listener instanceof VamsasListener && !handlingVamsasMo)
927 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
930 else if (listener instanceof SecondaryStructureListener)
932 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
940 * Send suitable messages to a StructureListener to highlight atoms
941 * corresponding to the given sequence position(s)
947 public void highlightStructure(StructureListener sl, SequenceI seq,
950 if (!sl.isListeningFor(seq))
955 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
956 for (StructureMapping sm : mappings)
958 if (sm.sequence == seq || sm.sequence == seq.getDatasetSequence()
959 || (sm.sequence.getDatasetSequence() != null && sm.sequence
960 .getDatasetSequence() == seq.getDatasetSequence()))
962 for (int index : positions)
964 atomNo = sm.getAtomNum(index);
968 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain,
969 sm.getPDBResNum(index), atomNo));
974 sl.highlightAtoms(atoms);
978 * true if a mouse over event from an external (ie Vamsas) source is being
981 boolean handlingVamsasMo = false;
986 * as mouseOverSequence but only route event to SequenceListeners
990 * in an alignment sequence
992 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
995 handlingVamsasMo = true;
996 long msg = sequenceI.hashCode() * (1 + position);
1000 mouseOverSequence(sequenceI, position, -1, source);
1002 handlingVamsasMo = false;
1005 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1009 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1010 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1012 * Annotation [] annotations = new Annotation[seq.getLength()];
1014 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1015 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1016 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1018 * for (int j = 0; j < mappings.length; j++) {
1020 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1021 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1022 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1023 * "+mappings[j].pdbfile);
1025 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1026 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1028 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1029 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1030 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1031 * mappings[j].pdbfile); }
1033 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1034 * annotations; } } } }
1036 * return annotations;
1040 public void structureSelectionChanged()
1044 public void sequenceSelectionChanged()
1048 public void sequenceColoursChanged(Object source)
1050 StructureListener sl;
1051 for (int i = 0; i < listeners.size(); i++)
1053 if (listeners.elementAt(i) instanceof StructureListener)
1055 sl = (StructureListener) listeners.elementAt(i);
1056 sl.updateColours(source);
1061 public StructureMapping[] getMapping(String pdbfile)
1063 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1064 for (StructureMapping sm : mappings)
1066 if (sm.pdbfile.equals(pdbfile))
1071 return tmp.toArray(new StructureMapping[tmp.size()]);
1075 * Returns a readable description of all mappings for the given pdbfile to any
1076 * of the given sequences
1082 public String printMappings(String pdbfile, List<SequenceI> seqs)
1084 if (pdbfile == null || seqs == null || seqs.isEmpty())
1089 StringBuilder sb = new StringBuilder(64);
1090 for (StructureMapping sm : mappings)
1092 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1094 sb.append(sm.mappingDetails);
1096 // separator makes it easier to read multiple mappings
1097 sb.append("=====================");
1103 return sb.toString();
1107 * Remove the given mapping
1111 public void deregisterMapping(AlignedCodonFrame acf)
1115 boolean removed = seqmappings.remove(acf);
1116 if (removed && seqmappings.isEmpty())
1118 System.out.println("All mappings removed");
1124 * Add each of the given codonFrames to the stored set, if not aready present.
1128 public void registerMappings(List<AlignedCodonFrame> mappings)
1130 if (mappings != null)
1132 for (AlignedCodonFrame acf : mappings)
1134 registerMapping(acf);
1140 * Add the given mapping to the stored set, unless already stored.
1142 public void registerMapping(AlignedCodonFrame acf)
1146 if (!seqmappings.contains(acf))
1148 seqmappings.add(acf);
1154 * Resets this object to its initial state by removing all registered
1155 * listeners, codon mappings, PDB file mappings
1157 public void resetAll()
1159 if (mappings != null)
1163 if (seqmappings != null)
1165 seqmappings.clear();
1167 if (sel_listeners != null)
1169 sel_listeners.clear();
1171 if (listeners != null)
1175 if (commandListeners != null)
1177 commandListeners.clear();
1179 if (view_listeners != null)
1181 view_listeners.clear();
1183 if (pdbFileNameId != null)
1185 pdbFileNameId.clear();
1187 if (pdbIdFileName != null)
1189 pdbIdFileName.clear();
1193 public void addSelectionListener(SelectionListener selecter)
1195 if (!sel_listeners.contains(selecter))
1197 sel_listeners.add(selecter);
1201 public void removeSelectionListener(SelectionListener toremove)
1203 if (sel_listeners.contains(toremove))
1205 sel_listeners.remove(toremove);
1209 public synchronized void sendSelection(
1210 jalview.datamodel.SequenceGroup selection,
1211 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1212 SelectionSource source)
1214 for (SelectionListener slis : sel_listeners)
1218 slis.selection(selection, colsel, hidden, source);
1223 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1225 public synchronized void sendViewPosition(
1226 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1227 int startSeq, int endSeq)
1230 if (view_listeners != null && view_listeners.size() > 0)
1232 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1234 while (listeners.hasMoreElements())
1236 AlignmentViewPanelListener slis = listeners.nextElement();
1239 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1247 * release all references associated with this manager provider
1249 * @param jalviewLite
1251 public static void release(StructureSelectionManagerProvider jalviewLite)
1253 // synchronized (instances)
1255 if (instances == null)
1259 StructureSelectionManager mnger = (instances.get(jalviewLite));
1262 instances.remove(jalviewLite);
1266 } catch (Throwable x)
1273 public void registerPDBEntry(PDBEntry pdbentry)
1275 if (pdbentry.getFile() != null
1276 && pdbentry.getFile().trim().length() > 0)
1278 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1282 public void addCommandListener(CommandListener cl)
1284 if (!commandListeners.contains(cl))
1286 commandListeners.add(cl);
1290 public boolean hasCommandListener(CommandListener cl)
1292 return this.commandListeners.contains(cl);
1295 public boolean removeCommandListener(CommandListener l)
1297 return commandListeners.remove(l);
1301 * Forward a command to any command listeners (except for the command's
1305 * the command to be broadcast (in its form after being performed)
1307 * if true, the command was being 'undone'
1310 public void commandPerformed(CommandI command, boolean undo,
1311 VamsasSource source)
1313 for (CommandListener listener : commandListeners)
1315 listener.mirrorCommand(command, undo, this, source);
1320 * Returns a new CommandI representing the given command as mapped to the
1321 * given sequences. If no mapping could be made, or the command is not of a
1322 * mappable kind, returns null.
1330 public CommandI mapCommand(CommandI command, boolean undo,
1331 final AlignmentI mapTo, char gapChar)
1333 if (command instanceof EditCommand)
1335 return MappingUtils.mapEditCommand((EditCommand) command, undo, mapTo,
1336 gapChar, seqmappings);
1338 else if (command instanceof OrderCommand)
1340 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1341 mapTo, seqmappings);
1346 public IProgressIndicator getProgressIndicator()
1348 return progressIndicator;
1351 public void setProgressIndicator(IProgressIndicator progressIndicator)
1353 this.progressIndicator = progressIndicator;
1356 public long getProgressSessionId()
1358 return progressSessionId;
1361 public void setProgressSessionId(long progressSessionId)
1363 this.progressSessionId = progressSessionId;
1366 public void setProgressBar(String message)
1368 if (progressIndicator == null)
1372 progressIndicator.setProgressBar(message, progressSessionId);
1375 public List<AlignedCodonFrame> getSequenceMappings()