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.SequenceI;
35 import jalview.ext.jmol.JmolParser;
36 import jalview.gui.IProgressIndicator;
37 import jalview.io.DataSourceType;
38 import jalview.io.StructureFile;
39 import jalview.util.MappingUtils;
40 import jalview.util.MessageManager;
41 import jalview.ws.sifts.SiftsClient;
42 import jalview.ws.sifts.SiftsException;
43 import jalview.ws.sifts.SiftsSettings;
45 import java.io.PrintStream;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Collections;
49 import java.util.Enumeration;
50 import java.util.HashMap;
51 import java.util.IdentityHashMap;
52 import java.util.List;
54 import java.util.Vector;
57 import MCview.PDBChain;
58 import MCview.PDBfile;
60 public class StructureSelectionManager
62 public final static String NEWLINE = System.lineSeparator();
64 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
66 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
68 private boolean processSecondaryStructure = false;
70 private boolean secStructServices = false;
72 private boolean addTempFacAnnot = false;
74 private IProgressIndicator progressIndicator;
76 private SiftsClient siftsClient = null;
78 private long progressSessionId;
81 * Set of any registered mappings between (dataset) sequences.
83 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
85 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
87 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
90 * @return true if will try to use external services for processing secondary
93 public boolean isSecStructServices()
95 return secStructServices;
99 * control use of external services for processing secondary structure
101 * @param secStructServices
103 public void setSecStructServices(boolean secStructServices)
105 this.secStructServices = secStructServices;
109 * flag controlling addition of any kind of structural annotation
111 * @return true if temperature factor annotation will be added
113 public boolean isAddTempFacAnnot()
115 return addTempFacAnnot;
119 * set flag controlling addition of structural annotation
121 * @param addTempFacAnnot
123 public void setAddTempFacAnnot(boolean addTempFacAnnot)
125 this.addTempFacAnnot = addTempFacAnnot;
130 * @return if true, the structure manager will attempt to add secondary
131 * structure lines for unannotated sequences
134 public boolean isProcessSecondaryStructure()
136 return processSecondaryStructure;
140 * Control whether structure manager will try to annotate mapped sequences
141 * with secondary structure from PDB data.
145 public void setProcessSecondaryStructure(boolean enable)
147 processSecondaryStructure = enable;
151 * debug function - write all mappings to stdout
153 public void reportMapping()
155 if (mappings.isEmpty())
157 System.err.println("reportMapping: No PDB/Sequence mappings.");
161 System.err.println("reportMapping: There are " + mappings.size()
164 for (StructureMapping sm : mappings)
166 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
172 * map between the PDB IDs (or structure identifiers) used by Jalview and the
173 * absolute filenames for PDB data that corresponds to it
175 Map<String, String> pdbIdFileName = new HashMap<String, String>();
177 Map<String, String> pdbFileNameId = new HashMap<String, String>();
179 public void registerPDBFile(String idForFile, String absoluteFile)
181 pdbIdFileName.put(idForFile, absoluteFile);
182 pdbFileNameId.put(absoluteFile, idForFile);
185 public String findIdForPDBFile(String idOrFile)
187 String id = pdbFileNameId.get(idOrFile);
191 public String findFileForPDBId(String idOrFile)
193 String id = pdbIdFileName.get(idOrFile);
197 public boolean isPDBFileRegistered(String idOrFile)
199 return pdbFileNameId.containsKey(idOrFile)
200 || pdbIdFileName.containsKey(idOrFile);
203 private static StructureSelectionManager nullProvider = null;
205 public static StructureSelectionManager getStructureSelectionManager(
206 StructureSelectionManagerProvider context)
210 if (nullProvider == null)
212 if (instances != null)
216 .getString("error.implementation_error_structure_selection_manager_null"),
217 new NullPointerException(MessageManager
218 .getString("exception.ssm_context_is_null")));
222 nullProvider = new StructureSelectionManager();
227 if (instances == null)
229 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
231 StructureSelectionManager instance = instances.get(context);
232 if (instance == null)
234 if (nullProvider != null)
236 instance = nullProvider;
240 instance = new StructureSelectionManager();
242 instances.put(context, instance);
248 * flag controlling whether SeqMappings are relayed from received sequence
249 * mouse over events to other sequences
251 boolean relaySeqMappings = true;
254 * Enable or disable relay of seqMapping events to other sequences. You might
255 * want to do this if there are many sequence mappings and the host computer
260 public void setRelaySeqMappings(boolean relay)
262 relaySeqMappings = relay;
266 * get the state of the relay seqMappings flag.
268 * @return true if sequence mouse overs are being relayed to other mapped
271 public boolean isRelaySeqMappingsEnabled()
273 return relaySeqMappings;
276 Vector listeners = new Vector();
279 * register a listener for alignment sequence mouseover events
283 public void addStructureViewerListener(Object svl)
285 if (!listeners.contains(svl))
287 listeners.addElement(svl);
292 * Returns the file name for a mapped PDB id (or null if not mapped).
297 public String alreadyMappedToFile(String pdbid)
299 for (StructureMapping sm : mappings)
301 if (sm.getPdbId().equals(pdbid))
310 * Import structure data and register a structure mapping for broadcasting
311 * colouring, mouseovers and selection events (convenience wrapper).
314 * - one or more sequences to be mapped to pdbFile
315 * @param targetChains
316 * - optional chain specification for mapping each sequence to pdb
317 * (may be nill, individual elements may be nill)
319 * - structure data resource
321 * - how to resolve data from resource
322 * @return null or the structure data parsed as a pdb file
324 synchronized public StructureFile setMapping(SequenceI[] sequence,
325 String[] targetChains, String pdbFile, DataSourceType paste)
327 return setMapping(true, sequence, targetChains, pdbFile, paste);
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,
352 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();
389 boolean isParseWithJMOL = StructureImportSettings
390 .getDefaultPDBFileParser().equalsIgnoreCase(
391 StructureImportSettings.StructureParser.JMOL_PARSER
393 if (isParseWithJMOL || (pdbFile != null && isCIFFile(pdbFile)))
395 pdb = new JmolParser(addTempFacAnnot, parseSecStr,
396 secStructServices, pdbFile, sourceType);
400 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
401 pdbFile, sourceType);
404 if (pdb.getId() != null && pdb.getId().trim().length() > 0
405 && sourceType == DataSourceType.FILE)
407 registerPDBFile(pdb.getId().trim(), pdbFile);
409 } catch (Exception ex)
411 ex.printStackTrace();
419 siftsClient = new SiftsClient(pdb);
421 } catch (SiftsException e)
423 isMapUsingSIFTs = false;
427 String targetChainId;
428 for (int s = 0; s < sequenceArray.length; s++)
430 boolean infChain = true;
431 final SequenceI seq = sequenceArray[s];
432 if (targetChainIds != null && targetChainIds[s] != null)
435 targetChainId = targetChainIds[s];
437 else if (seq.getName().indexOf("|") > -1)
439 targetChainId = seq.getName().substring(
440 seq.getName().lastIndexOf("|") + 1);
441 if (targetChainId.length() > 1)
443 if (targetChainId.trim().length() == 0)
449 // not a valid chain identifier
460 * Attempt pairwise alignment of the sequence with each chain in the PDB,
461 * and remember the highest scoring chain
464 AlignSeq maxAlignseq = null;
465 String maxChainId = " ";
466 PDBChain maxChain = null;
467 boolean first = true;
468 for (PDBChain chain : pdb.getChains())
470 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
473 continue; // don't try to map chains don't match.
475 // TODO: correctly determine sequence type for mixed na/peptide
477 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
478 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
481 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
482 // as.calcScoreMatrix();
483 // as.traceAlignment();
485 if (first || as.maxscore > max
486 || (as.maxscore == max && chain.id.equals(targetChainId)))
492 maxChainId = chain.id;
495 if (maxChain == null)
500 if (sourceType == DataSourceType.PASTE)
502 pdbFile = "INLINE" + pdb.getId();
505 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
508 setProgressBar(null);
509 setProgressBar(MessageManager
510 .getString("status.obtaining_mapping_with_sifts"));
511 jalview.datamodel.Mapping sqmpping = maxAlignseq
512 .getMappingFromS1(false);
513 if (targetChainId != null && !targetChainId.trim().isEmpty())
515 StructureMapping siftsMapping;
518 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
519 pdb, maxChain, sqmpping, maxAlignseq);
520 seqToStrucMapping.add(siftsMapping);
521 maxChain.makeExactMapping(maxAlignseq, seq);
522 maxChain.transferRESNUMFeatures(seq, null);
523 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
524 } catch (SiftsException e)
526 // fall back to NW alignment
527 System.err.println(e.getMessage());
528 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
529 targetChainId, maxChain, pdb, maxAlignseq);
530 seqToStrucMapping.add(nwMapping);
535 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
536 for (PDBChain chain : pdb.getChains())
540 StructureMapping siftsMapping = getStructureMapping(seq,
542 chain.id, pdb, chain, sqmpping, maxAlignseq);
543 foundSiftsMappings.add(siftsMapping);
544 } catch (SiftsException e)
546 System.err.println(e.getMessage());
549 if (!foundSiftsMappings.isEmpty())
551 seqToStrucMapping.addAll(foundSiftsMappings);
552 maxChain.makeExactMapping(maxAlignseq, seq);
553 maxChain.transferRESNUMFeatures(seq, null);
554 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
559 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
560 maxChainId, maxChain, pdb, maxAlignseq);
561 seqToStrucMapping.add(nwMapping);
567 setProgressBar(null);
568 setProgressBar(MessageManager
569 .getString("status.obtaining_mapping_with_nw_alignment"));
570 seqToStrucMapping.add(getNWMappings(seq, pdbFile, maxChainId,
571 maxChain, pdb, maxAlignseq));
574 if (forStructureView)
576 mappings.addAll(seqToStrucMapping);
582 private boolean isCIFFile(String filename)
584 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
586 return "cif".equalsIgnoreCase(fileExt);
589 private StructureMapping getStructureMapping(SequenceI seq,
590 String pdbFile, String targetChainId, StructureFile pdb,
591 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
592 AlignSeq maxAlignseq) throws SiftsException
594 StructureMapping curChainMapping = siftsClient
595 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
598 PDBChain chain = pdb.findChain(targetChainId);
601 chain.transferResidueAnnotation(curChainMapping, sqmpping);
603 } catch (Exception e)
607 return curChainMapping;
610 private StructureMapping getNWMappings(SequenceI seq,
612 String maxChainId, PDBChain maxChain, StructureFile pdb,
613 AlignSeq maxAlignseq)
615 final StringBuilder mappingDetails = new StringBuilder(128);
616 mappingDetails.append(NEWLINE).append(
617 "Sequence \u27f7 Structure mapping details");
618 mappingDetails.append(NEWLINE);
620 .append("Method: inferred with Needleman & Wunsch alignment");
621 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
622 .append(NEWLINE).append("Sequence = ")
623 .append(maxChain.sequence.getSequenceAsString());
624 mappingDetails.append(NEWLINE).append("No of residues = ")
625 .append(maxChain.residues.size()).append(NEWLINE)
627 PrintStream ps = new PrintStream(System.out)
630 public void print(String x)
632 mappingDetails.append(x);
636 public void println()
638 mappingDetails.append(NEWLINE);
642 maxAlignseq.printAlignment(ps);
644 mappingDetails.append(NEWLINE).append("PDB start/end ");
645 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
647 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
648 mappingDetails.append(NEWLINE).append("SEQ start/end ");
649 mappingDetails.append(
650 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
652 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
653 + (seq.getStart() - 1)));
654 mappingDetails.append(NEWLINE);
655 maxChain.makeExactMapping(maxAlignseq, seq);
656 jalview.datamodel.Mapping sqmpping = maxAlignseq
657 .getMappingFromS1(false);
658 maxChain.transferRESNUMFeatures(seq, null);
660 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
667 Atom tmp = maxChain.atoms.elementAt(index);
668 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
669 && tmp.alignmentMapping != -1)
671 resNum = tmp.resNumber;
672 insCode = tmp.insCode;
673 if (tmp.alignmentMapping >= -1)
675 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
681 } while (index < maxChain.atoms.size());
683 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
684 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
685 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
689 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
691 listeners.removeElement(svl);
692 if (svl instanceof SequenceListener)
694 for (int i = 0; i < listeners.size(); i++)
696 if (listeners.elementAt(i) instanceof StructureListener)
698 ((StructureListener) listeners.elementAt(i))
699 .releaseReferences(svl);
704 if (pdbfiles == null)
710 * Remove mappings to the closed listener's PDB files, but first check if
711 * another listener is still interested
713 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
715 StructureListener sl;
716 for (int i = 0; i < listeners.size(); i++)
718 if (listeners.elementAt(i) instanceof StructureListener)
720 sl = (StructureListener) listeners.elementAt(i);
721 for (String pdbfile : sl.getPdbFile())
723 pdbs.remove(pdbfile);
729 * Rebuild the mappings set, retaining only those which are for 'other' PDB
734 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
735 for (StructureMapping sm : mappings)
737 if (!pdbs.contains(sm.pdbfile))
748 * Propagate mouseover of a single position in a structure
754 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
756 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
757 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
758 mouseOverStructure(atoms);
762 * Propagate mouseover or selection of multiple positions in a structure
766 public void mouseOverStructure(List<AtomSpec> atoms)
768 if (listeners == null)
770 // old or prematurely sent event
773 boolean hasSequenceListener = false;
774 for (int i = 0; i < listeners.size(); i++)
776 if (listeners.elementAt(i) instanceof SequenceListener)
778 hasSequenceListener = true;
781 if (!hasSequenceListener)
786 SearchResults results = new SearchResults();
787 for (AtomSpec atom : atoms)
789 SequenceI lastseq = null;
791 for (StructureMapping sm : mappings)
793 if (sm.pdbfile.equals(atom.getPdbFile())
794 && sm.pdbchain.equals(atom.getChain()))
796 int indexpos = sm.getSeqPos(atom.getPdbResNum());
797 if (lastipos != indexpos && lastseq != sm.sequence)
799 results.addResult(sm.sequence, indexpos, indexpos);
801 lastseq = sm.sequence;
802 // construct highlighted sequence list
803 for (AlignedCodonFrame acf : seqmappings)
805 acf.markMappedRegion(sm.sequence, indexpos, results);
811 for (Object li : listeners)
813 if (li instanceof SequenceListener)
815 ((SequenceListener) li).highlightSequence(results);
821 * highlight regions associated with a position (indexpos) in seq
824 * the sequence that the mouse over occurred on
826 * the absolute position being mouseovered in seq (0 to seq.length())
828 * the sequence position (if -1, seq.findPosition is called to
829 * resolve the residue number)
831 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
834 boolean hasSequenceListeners = handlingVamsasMo
835 || !seqmappings.isEmpty();
836 SearchResults results = null;
839 seqPos = seq.findPosition(indexpos);
841 for (int i = 0; i < listeners.size(); i++)
843 Object listener = listeners.elementAt(i);
844 if (listener == source)
846 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
847 // Temporary fudge with SequenceListener.getVamsasSource()
850 if (listener instanceof StructureListener)
852 highlightStructure((StructureListener) listener, seq, seqPos);
856 if (listener instanceof SequenceListener)
858 final SequenceListener seqListener = (SequenceListener) listener;
859 if (hasSequenceListeners
860 && seqListener.getVamsasSource() != source)
862 if (relaySeqMappings)
866 results = MappingUtils.buildSearchResults(seq, seqPos,
869 if (handlingVamsasMo)
871 results.addResult(seq, seqPos, seqPos);
874 if (!results.isEmpty())
876 seqListener.highlightSequence(results);
881 else if (listener instanceof VamsasListener && !handlingVamsasMo)
883 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
886 else if (listener instanceof SecondaryStructureListener)
888 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
896 * Send suitable messages to a StructureListener to highlight atoms
897 * corresponding to the given sequence position(s)
903 public void highlightStructure(StructureListener sl, SequenceI seq,
906 if (!sl.isListeningFor(seq))
911 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
912 for (StructureMapping sm : mappings)
914 if (sm.sequence == seq
915 || sm.sequence == seq.getDatasetSequence()
916 || (sm.sequence.getDatasetSequence() != null && sm.sequence
917 .getDatasetSequence() == seq.getDatasetSequence()))
919 for (int index : positions)
921 atomNo = sm.getAtomNum(index);
925 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
926 .getPDBResNum(index), atomNo));
931 sl.highlightAtoms(atoms);
935 * true if a mouse over event from an external (ie Vamsas) source is being
938 boolean handlingVamsasMo = false;
943 * as mouseOverSequence but only route event to SequenceListeners
947 * in an alignment sequence
949 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
952 handlingVamsasMo = true;
953 long msg = sequenceI.hashCode() * (1 + position);
957 mouseOverSequence(sequenceI, position, -1, source);
959 handlingVamsasMo = false;
962 public Annotation[] colourSequenceFromStructure(SequenceI seq,
966 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
967 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
969 * Annotation [] annotations = new Annotation[seq.getLength()];
971 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
972 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
973 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
975 * for (int j = 0; j < mappings.length; j++) {
977 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
978 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
979 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
980 * "+mappings[j].pdbfile);
982 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
983 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
985 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
986 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
987 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
988 * mappings[j].pdbfile); }
990 * annotations[index] = new Annotation("X",null,' ',0,col); } return
991 * annotations; } } } }
993 * return annotations;
997 public void structureSelectionChanged()
1001 public void sequenceSelectionChanged()
1005 public void sequenceColoursChanged(Object source)
1007 StructureListener sl;
1008 for (int i = 0; i < listeners.size(); i++)
1010 if (listeners.elementAt(i) instanceof StructureListener)
1012 sl = (StructureListener) listeners.elementAt(i);
1013 sl.updateColours(source);
1018 public StructureMapping[] getMapping(String pdbfile)
1020 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1021 for (StructureMapping sm : mappings)
1023 if (sm.pdbfile.equals(pdbfile))
1028 return tmp.toArray(new StructureMapping[tmp.size()]);
1032 * Returns a readable description of all mappings for the given pdbfile to any
1033 * of the given sequences
1039 public String printMappings(String pdbfile, List<SequenceI> seqs)
1041 if (pdbfile == null || seqs == null || seqs.isEmpty())
1046 StringBuilder sb = new StringBuilder(64);
1047 for (StructureMapping sm : mappings)
1049 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1051 sb.append(sm.mappingDetails);
1053 // separator makes it easier to read multiple mappings
1054 sb.append("=====================");
1060 return sb.toString();
1064 * Remove the given mapping
1068 public void deregisterMapping(AlignedCodonFrame acf)
1072 boolean removed = seqmappings.remove(acf);
1073 if (removed && seqmappings.isEmpty())
1075 System.out.println("All mappings removed");
1081 * Add each of the given codonFrames to the stored set, if not aready present.
1085 public void registerMappings(List<AlignedCodonFrame> mappings)
1087 if (mappings != null)
1089 for (AlignedCodonFrame acf : mappings)
1091 registerMapping(acf);
1097 * Add the given mapping to the stored set, unless already stored.
1099 public void registerMapping(AlignedCodonFrame acf)
1103 if (!seqmappings.contains(acf))
1105 seqmappings.add(acf);
1111 * Resets this object to its initial state by removing all registered
1112 * listeners, codon mappings, PDB file mappings
1114 public void resetAll()
1116 if (mappings != null)
1120 if (seqmappings != null)
1122 seqmappings.clear();
1124 if (sel_listeners != null)
1126 sel_listeners.clear();
1128 if (listeners != null)
1132 if (commandListeners != null)
1134 commandListeners.clear();
1136 if (view_listeners != null)
1138 view_listeners.clear();
1140 if (pdbFileNameId != null)
1142 pdbFileNameId.clear();
1144 if (pdbIdFileName != null)
1146 pdbIdFileName.clear();
1150 public void addSelectionListener(SelectionListener selecter)
1152 if (!sel_listeners.contains(selecter))
1154 sel_listeners.add(selecter);
1158 public void removeSelectionListener(SelectionListener toremove)
1160 if (sel_listeners.contains(toremove))
1162 sel_listeners.remove(toremove);
1166 public synchronized void sendSelection(
1167 jalview.datamodel.SequenceGroup selection,
1168 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1170 for (SelectionListener slis : sel_listeners)
1174 slis.selection(selection, colsel, source);
1179 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1181 public synchronized void sendViewPosition(
1182 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1183 int startSeq, int endSeq)
1186 if (view_listeners != null && view_listeners.size() > 0)
1188 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1190 while (listeners.hasMoreElements())
1192 AlignmentViewPanelListener slis = listeners.nextElement();
1195 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1203 * release all references associated with this manager provider
1205 * @param jalviewLite
1207 public static void release(StructureSelectionManagerProvider jalviewLite)
1209 // synchronized (instances)
1211 if (instances == null)
1215 StructureSelectionManager mnger = (instances.get(jalviewLite));
1218 instances.remove(jalviewLite);
1222 } catch (Throwable x)
1229 public void registerPDBEntry(PDBEntry pdbentry)
1231 if (pdbentry.getFile() != null
1232 && pdbentry.getFile().trim().length() > 0)
1234 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1238 public void addCommandListener(CommandListener cl)
1240 if (!commandListeners.contains(cl))
1242 commandListeners.add(cl);
1246 public boolean hasCommandListener(CommandListener cl)
1248 return this.commandListeners.contains(cl);
1251 public boolean removeCommandListener(CommandListener l)
1253 return commandListeners.remove(l);
1257 * Forward a command to any command listeners (except for the command's
1261 * the command to be broadcast (in its form after being performed)
1263 * if true, the command was being 'undone'
1266 public void commandPerformed(CommandI command, boolean undo,
1267 VamsasSource source)
1269 for (CommandListener listener : commandListeners)
1271 listener.mirrorCommand(command, undo, this, source);
1276 * Returns a new CommandI representing the given command as mapped to the
1277 * given sequences. If no mapping could be made, or the command is not of a
1278 * mappable kind, returns null.
1286 public CommandI mapCommand(CommandI command, boolean undo,
1287 final AlignmentI mapTo, char gapChar)
1289 if (command instanceof EditCommand)
1291 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1292 mapTo, gapChar, seqmappings);
1294 else if (command instanceof OrderCommand)
1296 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1297 mapTo, seqmappings);
1302 public IProgressIndicator getProgressIndicator()
1304 return progressIndicator;
1307 public void setProgressIndicator(IProgressIndicator progressIndicator)
1309 this.progressIndicator = progressIndicator;
1312 public long getProgressSessionId()
1314 return progressSessionId;
1317 public void setProgressSessionId(long progressSessionId)
1319 this.progressSessionId = progressSessionId;
1322 public void setProgressBar(String message)
1324 if (progressIndicator == null)
1328 progressIndicator.setProgressBar(message, progressSessionId);
1331 public List<AlignedCodonFrame> getSequenceMappings()