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 if (pdbFile != null && isCIFFile(pdbFile))
391 pdb = new JmolParser(addTempFacAnnot, parseSecStr,
392 secStructServices, pdbFile, sourceType);
396 pdb = new PDBfile(addTempFacAnnot, parseSecStr, secStructServices,
397 pdbFile, sourceType);
400 if (pdb.getId() != null && pdb.getId().trim().length() > 0
401 && sourceType == DataSourceType.FILE)
403 registerPDBFile(pdb.getId().trim(), pdbFile);
405 } catch (Exception ex)
407 ex.printStackTrace();
415 siftsClient = new SiftsClient(pdb);
417 } catch (SiftsException e)
419 isMapUsingSIFTs = false;
423 String targetChainId;
424 for (int s = 0; s < sequenceArray.length; s++)
426 boolean infChain = true;
427 final SequenceI seq = sequenceArray[s];
428 if (targetChainIds != null && targetChainIds[s] != null)
431 targetChainId = targetChainIds[s];
433 else if (seq.getName().indexOf("|") > -1)
435 targetChainId = seq.getName().substring(
436 seq.getName().lastIndexOf("|") + 1);
437 if (targetChainId.length() > 1)
439 if (targetChainId.trim().length() == 0)
445 // not a valid chain identifier
456 * Attempt pairwise alignment of the sequence with each chain in the PDB,
457 * and remember the highest scoring chain
460 AlignSeq maxAlignseq = null;
461 String maxChainId = " ";
462 PDBChain maxChain = null;
463 boolean first = true;
464 for (PDBChain chain : pdb.getChains())
466 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
469 continue; // don't try to map chains don't match.
471 // TODO: correctly determine sequence type for mixed na/peptide
473 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
474 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
477 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
478 // as.calcScoreMatrix();
479 // as.traceAlignment();
481 if (first || as.maxscore > max
482 || (as.maxscore == max && chain.id.equals(targetChainId)))
488 maxChainId = chain.id;
491 if (maxChain == null)
496 if (sourceType == DataSourceType.PASTE)
498 pdbFile = "INLINE" + pdb.getId();
501 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
504 setProgressBar(null);
505 setProgressBar(MessageManager
506 .getString("status.obtaining_mapping_with_sifts"));
507 jalview.datamodel.Mapping sqmpping = maxAlignseq
508 .getMappingFromS1(false);
509 if (targetChainId != null && !targetChainId.trim().isEmpty())
511 StructureMapping siftsMapping;
514 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
515 pdb, maxChain, sqmpping, maxAlignseq);
516 seqToStrucMapping.add(siftsMapping);
517 maxChain.makeExactMapping(maxAlignseq, seq);
518 maxChain.transferRESNUMFeatures(seq, null);
519 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
520 } catch (SiftsException e)
522 // fall back to NW alignment
523 System.err.println(e.getMessage());
524 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
525 targetChainId, maxChain, pdb, maxAlignseq);
526 seqToStrucMapping.add(nwMapping);
531 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
532 for (PDBChain chain : pdb.getChains())
536 StructureMapping siftsMapping = getStructureMapping(seq,
538 chain.id, pdb, chain, sqmpping, maxAlignseq);
539 foundSiftsMappings.add(siftsMapping);
540 } catch (SiftsException e)
542 System.err.println(e.getMessage());
545 if (!foundSiftsMappings.isEmpty())
547 seqToStrucMapping.addAll(foundSiftsMappings);
548 maxChain.makeExactMapping(maxAlignseq, seq);
549 maxChain.transferRESNUMFeatures(seq, null);
550 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
555 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
556 maxChainId, maxChain, pdb, maxAlignseq);
557 seqToStrucMapping.add(nwMapping);
563 setProgressBar(null);
564 setProgressBar(MessageManager
565 .getString("status.obtaining_mapping_with_nw_alignment"));
566 seqToStrucMapping.add(getNWMappings(seq, pdbFile, maxChainId,
567 maxChain, pdb, maxAlignseq));
570 if (forStructureView)
572 mappings.addAll(seqToStrucMapping);
578 private boolean isCIFFile(String filename)
580 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
582 return "cif".equalsIgnoreCase(fileExt);
585 private StructureMapping getStructureMapping(SequenceI seq,
586 String pdbFile, String targetChainId, StructureFile pdb,
587 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
588 AlignSeq maxAlignseq) throws SiftsException
590 StructureMapping curChainMapping = siftsClient
591 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
594 PDBChain chain = pdb.findChain(targetChainId);
597 chain.transferResidueAnnotation(curChainMapping, sqmpping);
599 } catch (Exception e)
603 return curChainMapping;
606 private StructureMapping getNWMappings(SequenceI seq,
608 String maxChainId, PDBChain maxChain, StructureFile pdb,
609 AlignSeq maxAlignseq)
611 final StringBuilder mappingDetails = new StringBuilder(128);
612 mappingDetails.append(NEWLINE).append(
613 "Sequence \u27f7 Structure mapping details");
614 mappingDetails.append(NEWLINE);
616 .append("Method: inferred with Needleman & Wunsch alignment");
617 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
618 .append(NEWLINE).append("Sequence = ")
619 .append(maxChain.sequence.getSequenceAsString());
620 mappingDetails.append(NEWLINE).append("No of residues = ")
621 .append(maxChain.residues.size()).append(NEWLINE)
623 PrintStream ps = new PrintStream(System.out)
626 public void print(String x)
628 mappingDetails.append(x);
632 public void println()
634 mappingDetails.append(NEWLINE);
638 maxAlignseq.printAlignment(ps);
640 mappingDetails.append(NEWLINE).append("PDB start/end ");
641 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
643 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
644 mappingDetails.append(NEWLINE).append("SEQ start/end ");
645 mappingDetails.append(
646 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
648 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
649 + (seq.getStart() - 1)));
650 mappingDetails.append(NEWLINE);
651 maxChain.makeExactMapping(maxAlignseq, seq);
652 jalview.datamodel.Mapping sqmpping = maxAlignseq
653 .getMappingFromS1(false);
654 maxChain.transferRESNUMFeatures(seq, null);
656 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
663 Atom tmp = maxChain.atoms.elementAt(index);
664 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
665 && tmp.alignmentMapping != -1)
667 resNum = tmp.resNumber;
668 insCode = tmp.insCode;
669 if (tmp.alignmentMapping >= -1)
671 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
677 } while (index < maxChain.atoms.size());
679 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
680 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
681 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
685 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
687 listeners.removeElement(svl);
688 if (svl instanceof SequenceListener)
690 for (int i = 0; i < listeners.size(); i++)
692 if (listeners.elementAt(i) instanceof StructureListener)
694 ((StructureListener) listeners.elementAt(i))
695 .releaseReferences(svl);
700 if (pdbfiles == null)
706 * Remove mappings to the closed listener's PDB files, but first check if
707 * another listener is still interested
709 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
711 StructureListener sl;
712 for (int i = 0; i < listeners.size(); i++)
714 if (listeners.elementAt(i) instanceof StructureListener)
716 sl = (StructureListener) listeners.elementAt(i);
717 for (String pdbfile : sl.getPdbFile())
719 pdbs.remove(pdbfile);
725 * Rebuild the mappings set, retaining only those which are for 'other' PDB
730 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
731 for (StructureMapping sm : mappings)
733 if (!pdbs.contains(sm.pdbfile))
744 * Propagate mouseover of a single position in a structure
750 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
752 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
753 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
754 mouseOverStructure(atoms);
758 * Propagate mouseover or selection of multiple positions in a structure
762 public void mouseOverStructure(List<AtomSpec> atoms)
764 if (listeners == null)
766 // old or prematurely sent event
769 boolean hasSequenceListener = false;
770 for (int i = 0; i < listeners.size(); i++)
772 if (listeners.elementAt(i) instanceof SequenceListener)
774 hasSequenceListener = true;
777 if (!hasSequenceListener)
782 SearchResults results = new SearchResults();
783 for (AtomSpec atom : atoms)
785 SequenceI lastseq = null;
787 for (StructureMapping sm : mappings)
789 if (sm.pdbfile.equals(atom.getPdbFile())
790 && sm.pdbchain.equals(atom.getChain()))
792 int indexpos = sm.getSeqPos(atom.getPdbResNum());
793 if (lastipos != indexpos && lastseq != sm.sequence)
795 results.addResult(sm.sequence, indexpos, indexpos);
797 lastseq = sm.sequence;
798 // construct highlighted sequence list
799 for (AlignedCodonFrame acf : seqmappings)
801 acf.markMappedRegion(sm.sequence, indexpos, results);
807 for (Object li : listeners)
809 if (li instanceof SequenceListener)
811 ((SequenceListener) li).highlightSequence(results);
817 * highlight regions associated with a position (indexpos) in seq
820 * the sequence that the mouse over occurred on
822 * the absolute position being mouseovered in seq (0 to seq.length())
824 * the sequence position (if -1, seq.findPosition is called to
825 * resolve the residue number)
827 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
830 boolean hasSequenceListeners = handlingVamsasMo
831 || !seqmappings.isEmpty();
832 SearchResults results = null;
835 seqPos = seq.findPosition(indexpos);
837 for (int i = 0; i < listeners.size(); i++)
839 Object listener = listeners.elementAt(i);
840 if (listener == source)
842 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
843 // Temporary fudge with SequenceListener.getVamsasSource()
846 if (listener instanceof StructureListener)
848 highlightStructure((StructureListener) listener, seq, seqPos);
852 if (listener instanceof SequenceListener)
854 final SequenceListener seqListener = (SequenceListener) listener;
855 if (hasSequenceListeners
856 && seqListener.getVamsasSource() != source)
858 if (relaySeqMappings)
862 results = MappingUtils.buildSearchResults(seq, seqPos,
865 if (handlingVamsasMo)
867 results.addResult(seq, seqPos, seqPos);
870 if (!results.isEmpty())
872 seqListener.highlightSequence(results);
877 else if (listener instanceof VamsasListener && !handlingVamsasMo)
879 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
882 else if (listener instanceof SecondaryStructureListener)
884 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
892 * Send suitable messages to a StructureListener to highlight atoms
893 * corresponding to the given sequence position(s)
899 public void highlightStructure(StructureListener sl, SequenceI seq,
902 if (!sl.isListeningFor(seq))
907 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
908 for (StructureMapping sm : mappings)
910 if (sm.sequence == seq
911 || sm.sequence == seq.getDatasetSequence()
912 || (sm.sequence.getDatasetSequence() != null && sm.sequence
913 .getDatasetSequence() == seq.getDatasetSequence()))
915 for (int index : positions)
917 atomNo = sm.getAtomNum(index);
921 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
922 .getPDBResNum(index), atomNo));
927 sl.highlightAtoms(atoms);
931 * true if a mouse over event from an external (ie Vamsas) source is being
934 boolean handlingVamsasMo = false;
939 * as mouseOverSequence but only route event to SequenceListeners
943 * in an alignment sequence
945 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
948 handlingVamsasMo = true;
949 long msg = sequenceI.hashCode() * (1 + position);
953 mouseOverSequence(sequenceI, position, -1, source);
955 handlingVamsasMo = false;
958 public Annotation[] colourSequenceFromStructure(SequenceI seq,
962 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
963 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
965 * Annotation [] annotations = new Annotation[seq.getLength()];
967 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
968 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
969 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
971 * for (int j = 0; j < mappings.length; j++) {
973 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
974 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
975 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
976 * "+mappings[j].pdbfile);
978 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
979 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
981 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
982 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
983 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
984 * mappings[j].pdbfile); }
986 * annotations[index] = new Annotation("X",null,' ',0,col); } return
987 * annotations; } } } }
989 * return annotations;
993 public void structureSelectionChanged()
997 public void sequenceSelectionChanged()
1001 public void sequenceColoursChanged(Object source)
1003 StructureListener sl;
1004 for (int i = 0; i < listeners.size(); i++)
1006 if (listeners.elementAt(i) instanceof StructureListener)
1008 sl = (StructureListener) listeners.elementAt(i);
1009 sl.updateColours(source);
1014 public StructureMapping[] getMapping(String pdbfile)
1016 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1017 for (StructureMapping sm : mappings)
1019 if (sm.pdbfile.equals(pdbfile))
1024 return tmp.toArray(new StructureMapping[tmp.size()]);
1028 * Returns a readable description of all mappings for the given pdbfile to any
1029 * of the given sequences
1035 public String printMappings(String pdbfile, List<SequenceI> seqs)
1037 if (pdbfile == null || seqs == null || seqs.isEmpty())
1042 StringBuilder sb = new StringBuilder(64);
1043 for (StructureMapping sm : mappings)
1045 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1047 sb.append(sm.mappingDetails);
1049 // separator makes it easier to read multiple mappings
1050 sb.append("=====================");
1056 return sb.toString();
1060 * Remove the given mapping
1064 public void deregisterMapping(AlignedCodonFrame acf)
1068 boolean removed = seqmappings.remove(acf);
1069 if (removed && seqmappings.isEmpty())
1071 System.out.println("All mappings removed");
1077 * Add each of the given codonFrames to the stored set, if not aready present.
1081 public void registerMappings(List<AlignedCodonFrame> mappings)
1083 if (mappings != null)
1085 for (AlignedCodonFrame acf : mappings)
1087 registerMapping(acf);
1093 * Add the given mapping to the stored set, unless already stored.
1095 public void registerMapping(AlignedCodonFrame acf)
1099 if (!seqmappings.contains(acf))
1101 seqmappings.add(acf);
1107 * Resets this object to its initial state by removing all registered
1108 * listeners, codon mappings, PDB file mappings
1110 public void resetAll()
1112 if (mappings != null)
1116 if (seqmappings != null)
1118 seqmappings.clear();
1120 if (sel_listeners != null)
1122 sel_listeners.clear();
1124 if (listeners != null)
1128 if (commandListeners != null)
1130 commandListeners.clear();
1132 if (view_listeners != null)
1134 view_listeners.clear();
1136 if (pdbFileNameId != null)
1138 pdbFileNameId.clear();
1140 if (pdbIdFileName != null)
1142 pdbIdFileName.clear();
1146 public void addSelectionListener(SelectionListener selecter)
1148 if (!sel_listeners.contains(selecter))
1150 sel_listeners.add(selecter);
1154 public void removeSelectionListener(SelectionListener toremove)
1156 if (sel_listeners.contains(toremove))
1158 sel_listeners.remove(toremove);
1162 public synchronized void sendSelection(
1163 jalview.datamodel.SequenceGroup selection,
1164 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1166 for (SelectionListener slis : sel_listeners)
1170 slis.selection(selection, colsel, source);
1175 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1177 public synchronized void sendViewPosition(
1178 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1179 int startSeq, int endSeq)
1182 if (view_listeners != null && view_listeners.size() > 0)
1184 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1186 while (listeners.hasMoreElements())
1188 AlignmentViewPanelListener slis = listeners.nextElement();
1191 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1199 * release all references associated with this manager provider
1201 * @param jalviewLite
1203 public static void release(StructureSelectionManagerProvider jalviewLite)
1205 // synchronized (instances)
1207 if (instances == null)
1211 StructureSelectionManager mnger = (instances.get(jalviewLite));
1214 instances.remove(jalviewLite);
1218 } catch (Throwable x)
1225 public void registerPDBEntry(PDBEntry pdbentry)
1227 if (pdbentry.getFile() != null
1228 && pdbentry.getFile().trim().length() > 0)
1230 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1234 public void addCommandListener(CommandListener cl)
1236 if (!commandListeners.contains(cl))
1238 commandListeners.add(cl);
1242 public boolean hasCommandListener(CommandListener cl)
1244 return this.commandListeners.contains(cl);
1247 public boolean removeCommandListener(CommandListener l)
1249 return commandListeners.remove(l);
1253 * Forward a command to any command listeners (except for the command's
1257 * the command to be broadcast (in its form after being performed)
1259 * if true, the command was being 'undone'
1262 public void commandPerformed(CommandI command, boolean undo,
1263 VamsasSource source)
1265 for (CommandListener listener : commandListeners)
1267 listener.mirrorCommand(command, undo, this, source);
1272 * Returns a new CommandI representing the given command as mapped to the
1273 * given sequences. If no mapping could be made, or the command is not of a
1274 * mappable kind, returns null.
1282 public CommandI mapCommand(CommandI command, boolean undo,
1283 final AlignmentI mapTo, char gapChar)
1285 if (command instanceof EditCommand)
1287 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1288 mapTo, gapChar, seqmappings);
1290 else if (command instanceof OrderCommand)
1292 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1293 mapTo, seqmappings);
1298 public IProgressIndicator getProgressIndicator()
1300 return progressIndicator;
1303 public void setProgressIndicator(IProgressIndicator progressIndicator)
1305 this.progressIndicator = progressIndicator;
1308 public long getProgressSessionId()
1310 return progressSessionId;
1313 public void setProgressSessionId(long progressSessionId)
1315 this.progressSessionId = progressSessionId;
1318 public void setProgressBar(String message)
1320 if (progressIndicator == null)
1324 progressIndicator.setProgressBar(message, progressSessionId);
1327 public List<AlignedCodonFrame> getSequenceMappings()