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.AppletFormatAdapter;
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, String protocol)
327 return setMapping(true, sequence, targetChains, pdbFile, protocol);
331 * create sequence structure mappings between each sequence and the given
332 * pdbFile (retrieved via the given protocol).
334 * @param forStructureView
335 * when true, record the mapping for use in mouseOvers
337 * @param sequenceArray
338 * - one or more sequences to be mapped to pdbFile
339 * @param targetChainIds
340 * - optional chain specification for mapping each sequence to pdb
341 * (may be nill, individual elements may be nill)
343 * - structure data resource
345 * - how to resolve data from resource
346 * @return null or the structure data parsed as a pdb file
348 synchronized public StructureFile setMapping(boolean forStructureView,
349 SequenceI[] sequenceArray, String[] targetChainIds,
350 String pdbFile, String protocol)
353 * There will be better ways of doing this in the future, for now we'll use
354 * the tried and tested MCview pdb mapping
356 boolean parseSecStr = processSecondaryStructure;
357 if (isPDBFileRegistered(pdbFile))
359 for (SequenceI sq : sequenceArray)
362 while (ds.getDatasetSequence() != null)
364 ds = ds.getDatasetSequence();
367 if (ds.getAnnotation() != null)
369 for (AlignmentAnnotation ala : ds.getAnnotation())
371 // false if any annotation present from this structure
372 // JBPNote this fails for jmol/chimera view because the *file* is
373 // passed, not the structure data ID -
374 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
382 StructureFile pdb = null;
383 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
386 pdb = new JmolParser(pdbFile, protocol);
388 if (pdb.getId() != null && pdb.getId().trim().length() > 0
389 && AppletFormatAdapter.FILE.equals(protocol))
391 registerPDBFile(pdb.getId().trim(), pdbFile);
393 // if PDBId is unavailable then skip SIFTS mapping execution path
394 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
396 } catch (Exception ex)
398 ex.printStackTrace();
406 siftsClient = new SiftsClient(pdb);
408 } catch (SiftsException e)
410 isMapUsingSIFTs = false;
414 String targetChainId;
415 for (int s = 0; s < sequenceArray.length; s++)
417 boolean infChain = true;
418 final SequenceI seq = sequenceArray[s];
420 while (ds.getDatasetSequence() != null)
422 ds = ds.getDatasetSequence();
425 if (targetChainIds != null && targetChainIds[s] != null)
428 targetChainId = targetChainIds[s];
430 else if (seq.getName().indexOf("|") > -1)
432 targetChainId = seq.getName().substring(
433 seq.getName().lastIndexOf("|") + 1);
434 if (targetChainId.length() > 1)
436 if (targetChainId.trim().length() == 0)
442 // not a valid chain identifier
453 * Attempt pairwise alignment of the sequence with each chain in the PDB,
454 * and remember the highest scoring chain
457 AlignSeq maxAlignseq = null;
458 String maxChainId = " ";
459 PDBChain maxChain = null;
460 boolean first = true;
461 for (PDBChain chain : pdb.getChains())
463 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
466 continue; // don't try to map chains don't match.
468 // TODO: correctly determine sequence type for mixed na/peptide
470 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
471 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
474 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
475 // as.calcScoreMatrix();
476 // as.traceAlignment();
478 if (first || as.maxscore > max
479 || (as.maxscore == max && chain.id.equals(targetChainId)))
485 maxChainId = chain.id;
488 if (maxChain == null)
493 if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
495 pdbFile = "INLINE" + pdb.getId();
498 ArrayList<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
499 if (isMapUsingSIFTs && seq.isProtein())
501 setProgressBar(null);
502 setProgressBar(MessageManager
503 .getString("status.obtaining_mapping_with_sifts"));
504 jalview.datamodel.Mapping sqmpping = maxAlignseq
505 .getMappingFromS1(false);
506 if (targetChainId != null && !targetChainId.trim().isEmpty())
508 StructureMapping siftsMapping;
511 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
512 pdb, maxChain, sqmpping, maxAlignseq);
513 seqToStrucMapping.add(siftsMapping);
514 maxChain.makeExactMapping(maxAlignseq, seq);
515 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
517 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
518 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
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);
527 maxChain.makeExactMapping(maxAlignseq, seq);
528 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
530 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
531 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
536 ArrayList<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
537 for (PDBChain chain : pdb.getChains())
541 StructureMapping siftsMapping = getStructureMapping(seq,
542 pdbFile, 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);// FIXME: is this
555 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
557 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
561 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
562 maxChainId, maxChain, pdb, maxAlignseq);
563 seqToStrucMapping.add(nwMapping);
564 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
566 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
567 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
573 setProgressBar(null);
574 setProgressBar(MessageManager
575 .getString("status.obtaining_mapping_with_nw_alignment"));
576 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
577 maxChainId, maxChain, pdb, maxAlignseq);
578 seqToStrucMapping.add(nwMapping);
579 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
583 if (forStructureView)
585 mappings.addAll(seqToStrucMapping);
591 private boolean isCIFFile(String filename)
593 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
595 return "cif".equalsIgnoreCase(fileExt);
599 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
604 * @param targetChainId
610 * @throws SiftsException
612 private StructureMapping getStructureMapping(SequenceI seq,
613 String pdbFile, String targetChainId, StructureFile pdb,
614 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
615 AlignSeq maxAlignseq) throws SiftsException
617 StructureMapping curChainMapping = siftsClient
618 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
621 PDBChain chain = pdb.findChain(targetChainId);
624 chain.transferResidueAnnotation(curChainMapping, sqmpping);
626 } catch (Exception e)
630 return curChainMapping;
633 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
634 String maxChainId, PDBChain maxChain, StructureFile pdb,
635 AlignSeq maxAlignseq)
637 final StringBuilder mappingDetails = new StringBuilder(128);
638 mappingDetails.append(NEWLINE).append(
639 "Sequence \u27f7 Structure mapping details");
640 mappingDetails.append(NEWLINE);
642 .append("Method: inferred with Needleman & Wunsch alignment");
643 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
644 .append(NEWLINE).append("Sequence = ")
645 .append(maxChain.sequence.getSequenceAsString());
646 mappingDetails.append(NEWLINE).append("No of residues = ")
647 .append(maxChain.residues.size()).append(NEWLINE)
649 PrintStream ps = new PrintStream(System.out)
652 public void print(String x)
654 mappingDetails.append(x);
658 public void println()
660 mappingDetails.append(NEWLINE);
664 maxAlignseq.printAlignment(ps);
666 mappingDetails.append(NEWLINE).append("PDB start/end ");
667 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
669 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
670 mappingDetails.append(NEWLINE).append("SEQ start/end ");
671 mappingDetails.append(
672 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
674 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
675 + (seq.getStart() - 1)));
676 mappingDetails.append(NEWLINE);
677 maxChain.makeExactMapping(maxAlignseq, seq);
678 jalview.datamodel.Mapping sqmpping = maxAlignseq
679 .getMappingFromS1(false);
680 maxChain.transferRESNUMFeatures(seq, null);
682 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
689 Atom tmp = maxChain.atoms.elementAt(index);
690 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
691 && tmp.alignmentMapping != -1)
693 resNum = tmp.resNumber;
694 insCode = tmp.insCode;
695 if (tmp.alignmentMapping >= -1)
697 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
703 } while (index < maxChain.atoms.size());
705 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
706 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
707 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
711 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
713 listeners.removeElement(svl);
714 if (svl instanceof SequenceListener)
716 for (int i = 0; i < listeners.size(); i++)
718 if (listeners.elementAt(i) instanceof StructureListener)
720 ((StructureListener) listeners.elementAt(i))
721 .releaseReferences(svl);
726 if (pdbfiles == null)
732 * Remove mappings to the closed listener's PDB files, but first check if
733 * another listener is still interested
735 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
737 StructureListener sl;
738 for (int i = 0; i < listeners.size(); i++)
740 if (listeners.elementAt(i) instanceof StructureListener)
742 sl = (StructureListener) listeners.elementAt(i);
743 for (String pdbfile : sl.getPdbFile())
745 pdbs.remove(pdbfile);
751 * Rebuild the mappings set, retaining only those which are for 'other' PDB
756 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
757 for (StructureMapping sm : mappings)
759 if (!pdbs.contains(sm.pdbfile))
770 * Propagate mouseover of a single position in a structure
776 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
778 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
779 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
780 mouseOverStructure(atoms);
784 * Propagate mouseover or selection of multiple positions in a structure
788 public void mouseOverStructure(List<AtomSpec> atoms)
790 if (listeners == null)
792 // old or prematurely sent event
795 boolean hasSequenceListener = false;
796 for (int i = 0; i < listeners.size(); i++)
798 if (listeners.elementAt(i) instanceof SequenceListener)
800 hasSequenceListener = true;
803 if (!hasSequenceListener)
808 SearchResults results = findAlignmentPositionsForStructurePositions(atoms);
809 for (Object li : listeners)
811 if (li instanceof SequenceListener)
813 ((SequenceListener) li).highlightSequence(results);
819 * Constructs a SearchResults object holding regions (if any) in the Jalview
820 * alignment which have a mapping to the structure viewer positions in the
826 public SearchResults findAlignmentPositionsForStructurePositions(
827 List<AtomSpec> atoms)
829 SearchResults results = new SearchResults();
830 for (AtomSpec atom : atoms)
832 SequenceI lastseq = null;
834 for (StructureMapping sm : mappings)
836 if (sm.pdbfile.equals(atom.getPdbFile())
837 && sm.pdbchain.equals(atom.getChain()))
839 int indexpos = sm.getSeqPos(atom.getPdbResNum());
840 if (lastipos != indexpos && lastseq != sm.sequence)
842 results.addResult(sm.sequence, indexpos, indexpos);
844 lastseq = sm.sequence;
845 // construct highlighted sequence list
846 for (AlignedCodonFrame acf : seqmappings)
848 acf.markMappedRegion(sm.sequence, indexpos, results);
858 * highlight regions associated with a position (indexpos) in seq
861 * the sequence that the mouse over occurred on
863 * the absolute position being mouseovered in seq (0 to seq.length())
865 * the sequence position (if -1, seq.findPosition is called to
866 * resolve the residue number)
868 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
871 boolean hasSequenceListeners = handlingVamsasMo
872 || !seqmappings.isEmpty();
873 SearchResults results = null;
876 seqPos = seq.findPosition(indexpos);
878 for (int i = 0; i < listeners.size(); i++)
880 Object listener = listeners.elementAt(i);
881 if (listener == source)
883 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
884 // Temporary fudge with SequenceListener.getVamsasSource()
887 if (listener instanceof StructureListener)
889 highlightStructure((StructureListener) listener, seq, seqPos);
893 if (listener instanceof SequenceListener)
895 final SequenceListener seqListener = (SequenceListener) listener;
896 if (hasSequenceListeners
897 && seqListener.getVamsasSource() != source)
899 if (relaySeqMappings)
903 results = MappingUtils.buildSearchResults(seq, seqPos,
906 if (handlingVamsasMo)
908 results.addResult(seq, seqPos, seqPos);
911 if (!results.isEmpty())
913 seqListener.highlightSequence(results);
918 else if (listener instanceof VamsasListener && !handlingVamsasMo)
920 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
923 else if (listener instanceof SecondaryStructureListener)
925 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
933 * Send suitable messages to a StructureListener to highlight atoms
934 * corresponding to the given sequence position(s)
940 public void highlightStructure(StructureListener sl, SequenceI seq,
943 if (!sl.isListeningFor(seq))
948 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
949 for (StructureMapping sm : mappings)
951 if (sm.sequence == seq
952 || sm.sequence == seq.getDatasetSequence()
953 || (sm.sequence.getDatasetSequence() != null && sm.sequence
954 .getDatasetSequence() == seq.getDatasetSequence()))
956 for (int index : positions)
958 atomNo = sm.getAtomNum(index);
962 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
963 .getPDBResNum(index), atomNo));
968 sl.highlightAtoms(atoms);
972 * true if a mouse over event from an external (ie Vamsas) source is being
975 boolean handlingVamsasMo = false;
980 * as mouseOverSequence but only route event to SequenceListeners
984 * in an alignment sequence
986 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
989 handlingVamsasMo = true;
990 long msg = sequenceI.hashCode() * (1 + position);
994 mouseOverSequence(sequenceI, position, -1, source);
996 handlingVamsasMo = false;
999 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1003 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1004 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1006 * Annotation [] annotations = new Annotation[seq.getLength()];
1008 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1009 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1010 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1012 * for (int j = 0; j < mappings.length; j++) {
1014 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1015 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1016 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1017 * "+mappings[j].pdbfile);
1019 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1020 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1022 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1023 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1024 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1025 * mappings[j].pdbfile); }
1027 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1028 * annotations; } } } }
1030 * return annotations;
1034 public void structureSelectionChanged()
1038 public void sequenceSelectionChanged()
1042 public void sequenceColoursChanged(Object source)
1044 StructureListener sl;
1045 for (int i = 0; i < listeners.size(); i++)
1047 if (listeners.elementAt(i) instanceof StructureListener)
1049 sl = (StructureListener) listeners.elementAt(i);
1050 sl.updateColours(source);
1055 public StructureMapping[] getMapping(String pdbfile)
1057 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1058 for (StructureMapping sm : mappings)
1060 if (sm.pdbfile.equals(pdbfile))
1065 return tmp.toArray(new StructureMapping[tmp.size()]);
1069 * Returns a readable description of all mappings for the given pdbfile to any
1070 * of the given sequences
1076 public String printMappings(String pdbfile, List<SequenceI> seqs)
1078 if (pdbfile == null || seqs == null || seqs.isEmpty())
1083 StringBuilder sb = new StringBuilder(64);
1084 for (StructureMapping sm : mappings)
1086 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1088 sb.append(sm.mappingDetails);
1090 // separator makes it easier to read multiple mappings
1091 sb.append("=====================");
1097 return sb.toString();
1101 * Remove the given mapping
1105 public void deregisterMapping(AlignedCodonFrame acf)
1109 boolean removed = seqmappings.remove(acf);
1110 if (removed && seqmappings.isEmpty())
1112 System.out.println("All mappings removed");
1118 * Add each of the given codonFrames to the stored set, if not aready present.
1122 public void registerMappings(List<AlignedCodonFrame> mappings)
1124 if (mappings != null)
1126 for (AlignedCodonFrame acf : mappings)
1128 registerMapping(acf);
1134 * Add the given mapping to the stored set, unless already stored.
1136 public void registerMapping(AlignedCodonFrame acf)
1140 if (!seqmappings.contains(acf))
1142 seqmappings.add(acf);
1148 * Resets this object to its initial state by removing all registered
1149 * listeners, codon mappings, PDB file mappings
1151 public void resetAll()
1153 if (mappings != null)
1157 if (seqmappings != null)
1159 seqmappings.clear();
1161 if (sel_listeners != null)
1163 sel_listeners.clear();
1165 if (listeners != null)
1169 if (commandListeners != null)
1171 commandListeners.clear();
1173 if (view_listeners != null)
1175 view_listeners.clear();
1177 if (pdbFileNameId != null)
1179 pdbFileNameId.clear();
1181 if (pdbIdFileName != null)
1183 pdbIdFileName.clear();
1187 public void addSelectionListener(SelectionListener selecter)
1189 if (!sel_listeners.contains(selecter))
1191 sel_listeners.add(selecter);
1195 public void removeSelectionListener(SelectionListener toremove)
1197 if (sel_listeners.contains(toremove))
1199 sel_listeners.remove(toremove);
1203 public synchronized void sendSelection(
1204 jalview.datamodel.SequenceGroup selection,
1205 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1207 for (SelectionListener slis : sel_listeners)
1211 slis.selection(selection, colsel, source);
1216 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1218 public synchronized void sendViewPosition(
1219 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1220 int startSeq, int endSeq)
1223 if (view_listeners != null && view_listeners.size() > 0)
1225 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1227 while (listeners.hasMoreElements())
1229 AlignmentViewPanelListener slis = listeners.nextElement();
1232 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1240 * release all references associated with this manager provider
1242 * @param jalviewLite
1244 public static void release(StructureSelectionManagerProvider jalviewLite)
1246 // synchronized (instances)
1248 if (instances == null)
1252 StructureSelectionManager mnger = (instances.get(jalviewLite));
1255 instances.remove(jalviewLite);
1259 } catch (Throwable x)
1266 public void registerPDBEntry(PDBEntry pdbentry)
1268 if (pdbentry.getFile() != null
1269 && pdbentry.getFile().trim().length() > 0)
1271 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1275 public void addCommandListener(CommandListener cl)
1277 if (!commandListeners.contains(cl))
1279 commandListeners.add(cl);
1283 public boolean hasCommandListener(CommandListener cl)
1285 return this.commandListeners.contains(cl);
1288 public boolean removeCommandListener(CommandListener l)
1290 return commandListeners.remove(l);
1294 * Forward a command to any command listeners (except for the command's
1298 * the command to be broadcast (in its form after being performed)
1300 * if true, the command was being 'undone'
1303 public void commandPerformed(CommandI command, boolean undo,
1304 VamsasSource source)
1306 for (CommandListener listener : commandListeners)
1308 listener.mirrorCommand(command, undo, this, source);
1313 * Returns a new CommandI representing the given command as mapped to the
1314 * given sequences. If no mapping could be made, or the command is not of a
1315 * mappable kind, returns null.
1323 public CommandI mapCommand(CommandI command, boolean undo,
1324 final AlignmentI mapTo, char gapChar)
1326 if (command instanceof EditCommand)
1328 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1329 mapTo, gapChar, seqmappings);
1331 else if (command instanceof OrderCommand)
1333 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1334 mapTo, seqmappings);
1339 public IProgressIndicator getProgressIndicator()
1341 return progressIndicator;
1344 public void setProgressIndicator(IProgressIndicator progressIndicator)
1346 this.progressIndicator = progressIndicator;
1349 public long getProgressSessionId()
1351 return progressSessionId;
1354 public void setProgressSessionId(long progressSessionId)
1356 this.progressSessionId = progressSessionId;
1359 public void setProgressBar(String message)
1361 if (progressIndicator == null)
1365 progressIndicator.setProgressBar(message, progressSessionId);
1368 public List<AlignedCodonFrame> getSequenceMappings()