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.gui.IProgressIndicator;
36 import jalview.io.AppletFormatAdapter;
37 import jalview.io.StructureFile;
38 import jalview.util.MappingUtils;
39 import jalview.util.MessageManager;
40 import jalview.ws.sifts.SiftsClient;
41 import jalview.ws.sifts.SiftsException;
42 import jalview.ws.sifts.SiftsSettings;
44 import java.io.PrintStream;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.Enumeration;
49 import java.util.HashMap;
50 import java.util.IdentityHashMap;
51 import java.util.List;
53 import java.util.Vector;
56 import MCview.PDBChain;
57 import MCview.PDBfile;
59 public class StructureSelectionManager
61 public final static String NEWLINE = System.lineSeparator();
63 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
65 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
67 private boolean processSecondaryStructure = false;
69 private boolean secStructServices = false;
71 private boolean addTempFacAnnot = false;
73 private SiftsClient siftsClient = null;
76 * Set of any registered mappings between (dataset) sequences.
78 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
80 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
82 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
85 * @return true if will try to use external services for processing secondary
88 public boolean isSecStructServices()
90 return secStructServices;
94 * control use of external services for processing secondary structure
96 * @param secStructServices
98 public void setSecStructServices(boolean secStructServices)
100 this.secStructServices = secStructServices;
104 * flag controlling addition of any kind of structural annotation
106 * @return true if temperature factor annotation will be added
108 public boolean isAddTempFacAnnot()
110 return addTempFacAnnot;
114 * set flag controlling addition of structural annotation
116 * @param addTempFacAnnot
118 public void setAddTempFacAnnot(boolean addTempFacAnnot)
120 this.addTempFacAnnot = addTempFacAnnot;
125 * @return if true, the structure manager will attempt to add secondary
126 * structure lines for unannotated sequences
129 public boolean isProcessSecondaryStructure()
131 return processSecondaryStructure;
135 * Control whether structure manager will try to annotate mapped sequences
136 * with secondary structure from PDB data.
140 public void setProcessSecondaryStructure(boolean enable)
142 processSecondaryStructure = enable;
146 * debug function - write all mappings to stdout
148 public void reportMapping()
150 if (mappings.isEmpty())
152 System.err.println("reportMapping: No PDB/Sequence mappings.");
156 System.err.println("reportMapping: There are " + mappings.size()
159 for (StructureMapping sm : mappings)
161 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
167 * map between the PDB IDs (or structure identifiers) used by Jalview and the
168 * absolute filenames for PDB data that corresponds to it
170 Map<String, String> pdbIdFileName = new HashMap<String, String>();
172 Map<String, String> pdbFileNameId = new HashMap<String, String>();
174 public void registerPDBFile(String idForFile, String absoluteFile)
176 pdbIdFileName.put(idForFile, absoluteFile);
177 pdbFileNameId.put(absoluteFile, idForFile);
180 public String findIdForPDBFile(String idOrFile)
182 String id = pdbFileNameId.get(idOrFile);
186 public String findFileForPDBId(String idOrFile)
188 String id = pdbIdFileName.get(idOrFile);
192 public boolean isPDBFileRegistered(String idOrFile)
194 return pdbFileNameId.containsKey(idOrFile)
195 || pdbIdFileName.containsKey(idOrFile);
198 private static StructureSelectionManager nullProvider = null;
200 public static StructureSelectionManager getStructureSelectionManager(
201 StructureSelectionManagerProvider context)
205 if (nullProvider == null)
207 if (instances != null)
211 .getString("error.implementation_error_structure_selection_manager_null"),
212 new NullPointerException(MessageManager
213 .getString("exception.ssm_context_is_null")));
217 nullProvider = new StructureSelectionManager();
222 if (instances == null)
224 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
226 StructureSelectionManager instance = instances.get(context);
227 if (instance == null)
229 if (nullProvider != null)
231 instance = nullProvider;
235 instance = new StructureSelectionManager();
237 instances.put(context, instance);
243 * flag controlling whether SeqMappings are relayed from received sequence
244 * mouse over events to other sequences
246 boolean relaySeqMappings = true;
249 * Enable or disable relay of seqMapping events to other sequences. You might
250 * want to do this if there are many sequence mappings and the host computer
255 public void setRelaySeqMappings(boolean relay)
257 relaySeqMappings = relay;
261 * get the state of the relay seqMappings flag.
263 * @return true if sequence mouse overs are being relayed to other mapped
266 public boolean isRelaySeqMappingsEnabled()
268 return relaySeqMappings;
271 Vector listeners = new Vector();
274 * register a listener for alignment sequence mouseover events
278 public void addStructureViewerListener(Object svl)
280 if (!listeners.contains(svl))
282 listeners.addElement(svl);
287 * Returns the file name for a mapped PDB id (or null if not mapped).
292 public String alreadyMappedToFile(String pdbid)
294 for (StructureMapping sm : mappings)
296 if (sm.getPdbId().equals(pdbid))
305 * Import structure data and register a structure mapping for broadcasting
306 * colouring, mouseovers and selection events (convenience wrapper).
309 * - one or more sequences to be mapped to pdbFile
310 * @param targetChains
311 * - optional chain specification for mapping each sequence to pdb
312 * (may be nill, individual elements may be nill)
314 * - structure data resource
316 * - how to resolve data from resource
317 * @return null or the structure data parsed as a pdb file
319 synchronized public StructureFile setMapping(SequenceI[] sequence,
320 String[] targetChains, String pdbFile, String protocol,
321 IProgressIndicator progress)
323 return computeMapping(true, sequence, targetChains, pdbFile, protocol,
329 * create sequence structure mappings between each sequence and the given
330 * pdbFile (retrieved via the given protocol).
332 * @param forStructureView
333 * when true, record the mapping for use in mouseOvers
335 * @param sequenceArray
336 * - one or more sequences to be mapped to pdbFile
337 * @param targetChainIds
338 * - optional chain specification for mapping each sequence to pdb
339 * (may be null, individual elements may be null)
341 * - structure data resource
343 * - how to resolve data from resource
344 * @return null or the structure data parsed as a pdb file
346 synchronized public StructureFile setMapping(boolean forStructureView,
347 SequenceI[] sequenceArray, String[] targetChainIds,
351 return computeMapping(forStructureView, sequenceArray, targetChainIds,
352 pdbFile, protocol, null);
355 synchronized public StructureFile computeMapping(
356 boolean forStructureView, SequenceI[] sequenceArray,
357 String[] targetChainIds, String pdbFile, String protocol,
358 IProgressIndicator progress)
360 long progressSessionId = System.currentTimeMillis() * 3;
362 * There will be better ways of doing this in the future, for now we'll use
363 * the tried and tested MCview pdb mapping
365 boolean parseSecStr = processSecondaryStructure;
366 if (isPDBFileRegistered(pdbFile))
368 for (SequenceI sq : sequenceArray)
371 while (ds.getDatasetSequence() != null)
373 ds = ds.getDatasetSequence();
376 if (ds.getAnnotation() != null)
378 for (AlignmentAnnotation ala : ds.getAnnotation())
380 // false if any annotation present from this structure
381 // JBPNote this fails for jmol/chimera view because the *file* is
382 // passed, not the structure data ID -
383 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
391 StructureFile pdb = null;
392 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
396 if (pdbFile != null && isCIFFile(pdbFile))
398 pdb = new jalview.ext.jmol.JmolParser(addTempFacAnnot, parseSecStr,
399 secStructServices, pdbFile, protocol);
403 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
407 if (pdb.getId() != null && pdb.getId().trim().length() > 0
408 && AppletFormatAdapter.FILE.equals(protocol))
410 registerPDBFile(pdb.getId().trim(), pdbFile);
412 } catch (Exception ex)
414 ex.printStackTrace();
422 siftsClient = new SiftsClient(pdb);
424 } catch (SiftsException e)
426 isMapUsingSIFTs = false;
430 String targetChainId;
431 for (int s = 0; s < sequenceArray.length; s++)
433 boolean infChain = true;
434 final SequenceI seq = sequenceArray[s];
435 if (targetChainIds != null && targetChainIds[s] != null)
438 targetChainId = targetChainIds[s];
440 else if (seq.getName().indexOf("|") > -1)
442 targetChainId = seq.getName().substring(
443 seq.getName().lastIndexOf("|") + 1);
444 if (targetChainId.length() > 1)
446 if (targetChainId.trim().length() == 0)
452 // not a valid chain identifier
463 * Attempt pairwise alignment of the sequence with each chain in the PDB,
464 * and remember the highest scoring chain
467 AlignSeq maxAlignseq = null;
468 String maxChainId = " ";
469 PDBChain maxChain = null;
470 boolean first = true;
471 for (PDBChain chain : pdb.getChains())
473 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
476 continue; // don't try to map chains don't match.
478 // TODO: correctly determine sequence type for mixed na/peptide
480 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
481 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
484 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
485 // as.calcScoreMatrix();
486 // as.traceAlignment();
488 if (first || as.maxscore > max
489 || (as.maxscore == max && chain.id.equals(targetChainId)))
495 maxChainId = chain.id;
498 if (maxChain == null)
503 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
505 pdbFile = "INLINE" + pdb.getId();
507 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
510 if (progress!=null) {
511 progress.setProgressBar(MessageManager
512 .getString("status.obtaining_mapping_with_sifts"),
515 jalview.datamodel.Mapping sqmpping = maxAlignseq
516 .getMappingFromS1(false);
517 if (targetChainId != null && !targetChainId.trim().isEmpty())
519 StructureMapping siftsMapping;
522 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
523 pdb, maxChain, sqmpping, maxAlignseq);
524 seqToStrucMapping.add(siftsMapping);
525 maxChain.makeExactMapping(maxAlignseq, seq);
526 maxChain.transferRESNUMFeatures(seq, null);
527 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
528 } catch (SiftsException e)
530 // fall back to NW alignment
531 System.err.println(e.getMessage());
532 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
533 targetChainId, maxChain, pdb, maxAlignseq);
534 seqToStrucMapping.add(nwMapping);
539 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
540 for (PDBChain chain : pdb.getChains())
544 StructureMapping siftsMapping = getStructureMapping(seq,
546 chain.id, pdb, chain, sqmpping, maxAlignseq);
547 foundSiftsMappings.add(siftsMapping);
548 } catch (SiftsException e)
550 System.err.println(e.getMessage());
553 if (!foundSiftsMappings.isEmpty())
555 seqToStrucMapping.addAll(foundSiftsMappings);
556 maxChain.makeExactMapping(maxAlignseq, seq);
557 maxChain.transferRESNUMFeatures(seq, null);
558 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
563 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
564 maxChainId, maxChain, pdb, maxAlignseq);
565 seqToStrucMapping.add(nwMapping);
571 if (progress != null)
573 progress.setProgressBar(MessageManager
574 .getString("status.obtaining_mapping_with_nw_alignment"),
577 seqToStrucMapping.add(getNWMappings(seq, pdbFile, maxChainId,
578 maxChain, pdb, maxAlignseq));
580 if (forStructureView)
582 mappings.addAll(seqToStrucMapping);
584 if (progress != null)
586 progress.setProgressBar(null, progressSessionId);
592 private boolean isCIFFile(String filename)
594 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
596 return "cif".equalsIgnoreCase(fileExt);
599 private StructureMapping getStructureMapping(SequenceI seq,
600 String pdbFile, String targetChainId, StructureFile pdb,
601 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
602 AlignSeq maxAlignseq) throws SiftsException
604 StructureMapping curChainMapping = siftsClient
605 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
608 PDBChain chain = pdb.findChain(targetChainId);
611 chain.transferResidueAnnotation(curChainMapping, sqmpping);
613 } catch (Exception e)
617 return curChainMapping;
620 private StructureMapping getNWMappings(SequenceI seq,
622 String maxChainId, PDBChain maxChain, StructureFile pdb,
623 AlignSeq maxAlignseq)
625 final StringBuilder mappingDetails = new StringBuilder(128);
626 mappingDetails.append(NEWLINE).append(
627 "Sequence \u27f7 Structure mapping details");
628 mappingDetails.append(NEWLINE);
630 .append("Method: inferred with Needleman & Wunsch alignment");
631 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
632 .append(NEWLINE).append("Sequence = ")
633 .append(maxChain.sequence.getSequenceAsString());
634 mappingDetails.append(NEWLINE).append("No of residues = ")
635 .append(maxChain.residues.size()).append(NEWLINE)
637 PrintStream ps = new PrintStream(System.out)
640 public void print(String x)
642 mappingDetails.append(x);
646 public void println()
648 mappingDetails.append(NEWLINE);
652 maxAlignseq.printAlignment(ps);
654 mappingDetails.append(NEWLINE).append("PDB start/end ");
655 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
657 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
658 mappingDetails.append(NEWLINE).append("SEQ start/end ");
659 mappingDetails.append(
660 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
662 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
663 + (seq.getStart() - 1)));
664 mappingDetails.append(NEWLINE);
665 maxChain.makeExactMapping(maxAlignseq, seq);
666 jalview.datamodel.Mapping sqmpping = maxAlignseq
667 .getMappingFromS1(false);
668 maxChain.transferRESNUMFeatures(seq, null);
670 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
677 Atom tmp = maxChain.atoms.elementAt(index);
678 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
679 && tmp.alignmentMapping != -1)
681 resNum = tmp.resNumber;
682 insCode = tmp.insCode;
683 if (tmp.alignmentMapping >= -1)
685 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
691 } while (index < maxChain.atoms.size());
693 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
694 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
695 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
699 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
701 listeners.removeElement(svl);
702 if (svl instanceof SequenceListener)
704 for (int i = 0; i < listeners.size(); i++)
706 if (listeners.elementAt(i) instanceof StructureListener)
708 ((StructureListener) listeners.elementAt(i))
709 .releaseReferences(svl);
714 if (pdbfiles == null)
720 * Remove mappings to the closed listener's PDB files, but first check if
721 * another listener is still interested
723 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
725 StructureListener sl;
726 for (int i = 0; i < listeners.size(); i++)
728 if (listeners.elementAt(i) instanceof StructureListener)
730 sl = (StructureListener) listeners.elementAt(i);
731 for (String pdbfile : sl.getPdbFile())
733 pdbs.remove(pdbfile);
739 * Rebuild the mappings set, retaining only those which are for 'other' PDB
744 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
745 for (StructureMapping sm : mappings)
747 if (!pdbs.contains(sm.pdbfile))
758 * Propagate mouseover of a single position in a structure
764 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
766 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
767 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
768 mouseOverStructure(atoms);
772 * Propagate mouseover or selection of multiple positions in a structure
776 public void mouseOverStructure(List<AtomSpec> atoms)
778 if (listeners == null)
780 // old or prematurely sent event
783 boolean hasSequenceListener = false;
784 for (int i = 0; i < listeners.size(); i++)
786 if (listeners.elementAt(i) instanceof SequenceListener)
788 hasSequenceListener = true;
791 if (!hasSequenceListener)
796 SearchResults results = new SearchResults();
797 for (AtomSpec atom : atoms)
799 SequenceI lastseq = null;
801 for (StructureMapping sm : mappings)
803 if (sm.pdbfile.equals(atom.getPdbFile())
804 && sm.pdbchain.equals(atom.getChain()))
806 int indexpos = sm.getSeqPos(atom.getPdbResNum());
807 if (lastipos != indexpos && lastseq != sm.sequence)
809 results.addResult(sm.sequence, indexpos, indexpos);
811 lastseq = sm.sequence;
812 // construct highlighted sequence list
813 for (AlignedCodonFrame acf : seqmappings)
815 acf.markMappedRegion(sm.sequence, indexpos, results);
821 for (Object li : listeners)
823 if (li instanceof SequenceListener)
825 ((SequenceListener) li).highlightSequence(results);
831 * highlight regions associated with a position (indexpos) in seq
834 * the sequence that the mouse over occurred on
836 * the absolute position being mouseovered in seq (0 to seq.length())
838 * the sequence position (if -1, seq.findPosition is called to
839 * resolve the residue number)
841 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
844 boolean hasSequenceListeners = handlingVamsasMo
845 || !seqmappings.isEmpty();
846 SearchResults results = null;
849 seqPos = seq.findPosition(indexpos);
851 for (int i = 0; i < listeners.size(); i++)
853 Object listener = listeners.elementAt(i);
854 if (listener == source)
856 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
857 // Temporary fudge with SequenceListener.getVamsasSource()
860 if (listener instanceof StructureListener)
862 highlightStructure((StructureListener) listener, seq, seqPos);
866 if (listener instanceof SequenceListener)
868 final SequenceListener seqListener = (SequenceListener) listener;
869 if (hasSequenceListeners
870 && seqListener.getVamsasSource() != source)
872 if (relaySeqMappings)
876 results = MappingUtils.buildSearchResults(seq, seqPos,
879 if (handlingVamsasMo)
881 results.addResult(seq, seqPos, seqPos);
884 if (!results.isEmpty())
886 seqListener.highlightSequence(results);
891 else if (listener instanceof VamsasListener && !handlingVamsasMo)
893 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
896 else if (listener instanceof SecondaryStructureListener)
898 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
906 * Send suitable messages to a StructureListener to highlight atoms
907 * corresponding to the given sequence position(s)
913 public void highlightStructure(StructureListener sl, SequenceI seq,
916 if (!sl.isListeningFor(seq))
921 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
922 for (StructureMapping sm : mappings)
924 if (sm.sequence == seq
925 || sm.sequence == seq.getDatasetSequence()
926 || (sm.sequence.getDatasetSequence() != null && sm.sequence
927 .getDatasetSequence() == seq.getDatasetSequence()))
929 for (int index : positions)
931 atomNo = sm.getAtomNum(index);
935 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
936 .getPDBResNum(index), atomNo));
941 sl.highlightAtoms(atoms);
945 * true if a mouse over event from an external (ie Vamsas) source is being
948 boolean handlingVamsasMo = false;
953 * as mouseOverSequence but only route event to SequenceListeners
957 * in an alignment sequence
959 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
962 handlingVamsasMo = true;
963 long msg = sequenceI.hashCode() * (1 + position);
967 mouseOverSequence(sequenceI, position, -1, source);
969 handlingVamsasMo = false;
972 public Annotation[] colourSequenceFromStructure(SequenceI seq,
976 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
977 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
979 * Annotation [] annotations = new Annotation[seq.getLength()];
981 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
982 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
983 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
985 * for (int j = 0; j < mappings.length; j++) {
987 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
988 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
989 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
990 * "+mappings[j].pdbfile);
992 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
993 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
995 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
996 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
997 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
998 * mappings[j].pdbfile); }
1000 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1001 * annotations; } } } }
1003 * return annotations;
1007 public void structureSelectionChanged()
1011 public void sequenceSelectionChanged()
1015 public void sequenceColoursChanged(Object source)
1017 StructureListener sl;
1018 for (int i = 0; i < listeners.size(); i++)
1020 if (listeners.elementAt(i) instanceof StructureListener)
1022 sl = (StructureListener) listeners.elementAt(i);
1023 sl.updateColours(source);
1028 public StructureMapping[] getMapping(String pdbfile)
1030 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1031 for (StructureMapping sm : mappings)
1033 if (sm.pdbfile.equals(pdbfile))
1038 return tmp.toArray(new StructureMapping[tmp.size()]);
1042 * Returns a readable description of all mappings for the given pdbfile to any
1043 * of the given sequences
1049 public String printMappings(String pdbfile, List<SequenceI> seqs)
1051 if (pdbfile == null || seqs == null || seqs.isEmpty())
1056 StringBuilder sb = new StringBuilder(64);
1057 for (StructureMapping sm : mappings)
1059 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1061 sb.append(sm.mappingDetails);
1063 // separator makes it easier to read multiple mappings
1064 sb.append("=====================");
1070 return sb.toString();
1074 * Remove the given mapping
1078 public void deregisterMapping(AlignedCodonFrame acf)
1082 boolean removed = seqmappings.remove(acf);
1083 if (removed && seqmappings.isEmpty())
1085 System.out.println("All mappings removed");
1091 * Add each of the given codonFrames to the stored set, if not aready present.
1095 public void registerMappings(List<AlignedCodonFrame> mappings)
1097 if (mappings != null)
1099 for (AlignedCodonFrame acf : mappings)
1101 registerMapping(acf);
1107 * Add the given mapping to the stored set, unless already stored.
1109 public void registerMapping(AlignedCodonFrame acf)
1113 if (!seqmappings.contains(acf))
1115 seqmappings.add(acf);
1121 * Resets this object to its initial state by removing all registered
1122 * listeners, codon mappings, PDB file mappings
1124 public void resetAll()
1126 if (mappings != null)
1130 if (seqmappings != null)
1132 seqmappings.clear();
1134 if (sel_listeners != null)
1136 sel_listeners.clear();
1138 if (listeners != null)
1142 if (commandListeners != null)
1144 commandListeners.clear();
1146 if (view_listeners != null)
1148 view_listeners.clear();
1150 if (pdbFileNameId != null)
1152 pdbFileNameId.clear();
1154 if (pdbIdFileName != null)
1156 pdbIdFileName.clear();
1160 public void addSelectionListener(SelectionListener selecter)
1162 if (!sel_listeners.contains(selecter))
1164 sel_listeners.add(selecter);
1168 public void removeSelectionListener(SelectionListener toremove)
1170 if (sel_listeners.contains(toremove))
1172 sel_listeners.remove(toremove);
1176 public synchronized void sendSelection(
1177 jalview.datamodel.SequenceGroup selection,
1178 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1180 for (SelectionListener slis : sel_listeners)
1184 slis.selection(selection, colsel, source);
1189 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1191 public synchronized void sendViewPosition(
1192 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1193 int startSeq, int endSeq)
1196 if (view_listeners != null && view_listeners.size() > 0)
1198 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1200 while (listeners.hasMoreElements())
1202 AlignmentViewPanelListener slis = listeners.nextElement();
1205 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1213 * release all references associated with this manager provider
1215 * @param jalviewLite
1217 public static void release(StructureSelectionManagerProvider jalviewLite)
1219 // synchronized (instances)
1221 if (instances == null)
1225 StructureSelectionManager mnger = (instances.get(jalviewLite));
1228 instances.remove(jalviewLite);
1232 } catch (Throwable x)
1239 public void registerPDBEntry(PDBEntry pdbentry)
1241 if (pdbentry.getFile() != null
1242 && pdbentry.getFile().trim().length() > 0)
1244 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1248 public void addCommandListener(CommandListener cl)
1250 if (!commandListeners.contains(cl))
1252 commandListeners.add(cl);
1256 public boolean hasCommandListener(CommandListener cl)
1258 return this.commandListeners.contains(cl);
1261 public boolean removeCommandListener(CommandListener l)
1263 return commandListeners.remove(l);
1267 * Forward a command to any command listeners (except for the command's
1271 * the command to be broadcast (in its form after being performed)
1273 * if true, the command was being 'undone'
1276 public void commandPerformed(CommandI command, boolean undo,
1277 VamsasSource source)
1279 for (CommandListener listener : commandListeners)
1281 listener.mirrorCommand(command, undo, this, source);
1286 * Returns a new CommandI representing the given command as mapped to the
1287 * given sequences. If no mapping could be made, or the command is not of a
1288 * mappable kind, returns null.
1296 public CommandI mapCommand(CommandI command, boolean undo,
1297 final AlignmentI mapTo, char gapChar)
1299 if (command instanceof EditCommand)
1301 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1302 mapTo, gapChar, seqmappings);
1304 else if (command instanceof OrderCommand)
1306 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1307 mapTo, seqmappings);
1312 public List<AlignedCodonFrame> getSequenceMappings()