src/org/gel/mauve/BaseViewerModel.java

Go to the documentation of this file.
00001 package org.gel.mauve;
00002 
00003 import java.io.File;
00004 import java.net.URL;
00005 import java.util.ArrayList;
00006 import java.util.Collections;
00007 import java.util.Comparator;
00008 import java.util.HashMap;
00009 import java.util.LinkedList;
00010 import java.util.List;
00011 import java.util.ListIterator;
00012 import java.util.Vector;
00013 
00014 import javax.swing.event.EventListenerList;
00015 
00016 import org.gel.mauve.contigs.DefaultContigHandler;
00017 
00028 public class BaseViewerModel {
00029         // Genomes, stored in the order in which they are being viewed.
00030         protected Genome [] genomes;
00031 
00032         // Genomes, stored in the order in which they appear in the source file.
00033         private Genome [] sourceGenomes;
00034 
00035         // Current viewer mode.
00036         private ViewerMode mode = ViewerMode.NORMAL;
00037 
00038         // Listeners for changes to model, and event to use.
00039         protected EventListenerList listenerList = new EventListenerList ();
00040 
00041         protected ModelEvent modelEvent = new ModelEvent (this);
00042 
00043         // Length of longest genome.
00044         private long longestRange = -1;
00045 
00046         // Color scheme to be used.
00047         private ColorScheme colorScheme;
00048 
00049         // Set of matches.
00050         private Vector matchVector = new Vector ();
00051 
00052         // The list of boxes to highlight
00053         private LinkedList highBoxes = new LinkedList ();
00054 
00055         // The reference genome, for displaying reversals.
00056         private Genome referenceGenome;
00057 
00058         // The highlighted genome.
00059         private Genome highlightGenome;
00060 
00061         // The sequence coordinate for the current highlight.
00062         private long highlightCoordinate;
00063 
00064         // Whether to draw matches.
00065         private boolean drawMatches = true;
00066 
00067         // Whether to draw contig/chromosome boundary lines.
00068         private boolean drawChromosomeBoundaries = true;
00069 
00070         // Whether or not to draw the mouse cursor
00071         private boolean drawMouseHighlighting = true;
00072         
00073         // Original source file for this model.
00074         private File src;
00075 
00076         // Original source url for this model, if applicable.
00077         private URL sourceURL = null;
00078 
00079         // The genome in which a range of sequence has been highlighted
00080         private Genome rangeHighlightGenome = null;
00081 
00082         // the left end of the highlight range
00083         private long rangeHighlightLeft = -1;
00084 
00085         // the right end of the highlight range
00086         private long rangeHighlightRight = -1;
00087         
00088         //changes coordinates to and from contig to pseudogene system
00089         protected DefaultContigHandler contig_handler;
00090 
00100         public BaseViewerModel (File src) {
00101                 this.src = src;
00102                 contig_handler = new DefaultContigHandler (this);
00103         }
00104 
00110         public File getSrc () {
00111                 return src;
00112         }
00113 
00119         public void setSourceURL (URL url) {
00120                 this.sourceURL = url;
00121         }
00122 
00128         public URL getSourceURL () {
00129                 return sourceURL;
00130         }
00131 
00139         public void setSequenceCount (int sequenceCount) {
00140                 // NEWTODO Make the list of genomes simply a list
00141                 genomes = new Genome [sequenceCount];
00142                 sourceGenomes = new Genome [sequenceCount];
00143         }
00144 
00148         public int getSequenceCount () {
00149                 return genomes.length;
00150         }
00151 
00160         public Genome getGenomeByViewingIndex (int viewIndex) {
00161                 return genomes[viewIndex];
00162         }
00163 
00164         public Genome getGenomeBySourceIndex (int sourceIndex) {
00165                 return sourceGenomes[sourceIndex];
00166         }
00167 
00173         public Vector<Genome> getGenomes () {
00174                 Vector ret = new Vector ();
00175                 for (int i = 0; i < genomes.length; i++)
00176                         ret.add (genomes[i]);
00177                 return ret;
00178         }
00179         
00180         public int numGenomes(){
00181                 return genomes.length;
00182         }
00183 
00192         public void setGenome (int viewIndex, Genome g) {
00193                 genomes[viewIndex] = g;
00194                 g.setViewIndex (viewIndex);
00195 
00196                 sourceGenomes[g.getSourceIndex ()] = g;
00197 
00198                 // Update longest range.
00199                 if (longestRange < g.getLength ()) {
00200                         longestRange = g.getLength ();
00201                 }
00202 
00203                 // Set lengths.
00204                 for (int i = 0; i < genomes.length; i++) {
00205                         Genome genome = genomes[i];
00206                         if (genome != null) {
00207                                 genome.setViewLength (longestRange);
00208                         }
00209                 }
00210         }
00211 
00217         public int getMatchCount () {
00218                 return matchVector.size ();
00219         }
00220 
00227         public Match getMatch (int index) {
00228                 return (Match) matchVector.elementAt (index);
00229         }
00230 
00240         public Vector sortedMatches (Comparator c) {
00241                 Vector sorted = (Vector) matchVector.clone ();
00242                 if (c != null)
00243                         Collections.sort (sorted, c);
00244                 return sorted;
00245         }
00246 
00253         public void addMatch (Match m) {
00254                 matchVector.add (m);
00255         }
00256 
00266         public void setColorScheme (ColorScheme colorScheme) {
00267                 if (!colorScheme.equals (this.colorScheme)) {
00268                         this.colorScheme = colorScheme;
00269                         colorScheme.apply (this);
00270 
00271                         fireColorEvent ();
00272                 }
00273         }
00274 
00280         public ColorScheme getColorScheme () {
00281                 return colorScheme;
00282         }
00283 
00290         public void addModelListener (ModelListener l) {
00291                 listenerList.add (ModelListener.class, l);
00292         }
00293 
00300         public void removeModelListener (ModelListener l) {
00301                 listenerList.remove (ModelListener.class, l);
00302         }
00303 
00310         public void addHighlightListener (HighlightListener l) {
00311                 listenerList.add (HighlightListener.class, l);
00312         }
00313 
00320         public void removeHighlightListener (HighlightListener l) {
00321                 listenerList.remove (HighlightListener.class, l);
00322         }
00323 
00328         protected void fireHighlightEvent () {
00329                 Object [] listeners = listenerList.getListenerList ();
00330                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00331                         if (listeners[i] == HighlightListener.class) {
00332                                 ((HighlightListener) listeners[i + 1])
00333                                                 .highlightChanged (modelEvent);
00334                         }
00335                 }
00336         }
00337 
00342         protected void fireColorEvent () {
00343                 Object [] listeners = listenerList.getListenerList ();
00344                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00345                         if (listeners[i] == ModelListener.class) {
00346                                 ((ModelListener) listeners[i + 1]).colorChanged (modelEvent);
00347                         }
00348                 }
00349         }
00350 
00355         protected void fireWeightEvent () {
00356                 Object [] listeners = listenerList.getListenerList ();
00357                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00358                         if (listeners[i] == ModelListener.class) {
00359                                 ((ModelListener) listeners[i + 1]).weightChanged (modelEvent);
00360                         }
00361                 }
00362         }
00363 
00368         protected void fireDrawingSettingsEvent () {
00369                 Object [] listeners = listenerList.getListenerList ();
00370                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00371                         if (listeners[i] == ModelListener.class) {
00372                                 ((ModelListener) listeners[i + 1])
00373                                                 .drawingSettingsChanged (modelEvent);
00374                         }
00375                 }
00376         }
00377 
00382         protected void fireModeEvent () {
00383                 Object [] listeners = listenerList.getListenerList ();
00384                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00385                         if (listeners[i] == ModelListener.class) {
00386                                 ((ModelListener) listeners[i + 1]).modeChanged (modelEvent);
00387                         }
00388                 }
00389         }
00390 
00395         public void firePrintingStartEvent() {
00396                 Object [] listeners = listenerList.getListenerList ();
00397                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00398                         if (listeners[i] == ModelListener.class) {
00399                                 ((ModelListener) listeners[i + 1])
00400                                                 .printingStart (modelEvent);
00401                         }
00402                 }
00403         }
00404 
00409         public void firePrintingEndEvent() {
00410                 Object [] listeners = listenerList.getListenerList ();
00411                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00412                         if (listeners[i] == ModelListener.class) {
00413                                 ((ModelListener) listeners[i + 1])
00414                                                 .printingEnd (modelEvent);
00415                         }
00416                 }
00417         }
00418 
00423         public void fireViewableRangeEvent () {
00424                 Object [] listeners = listenerList.getListenerList ();
00425                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00426                         if (listeners[i] == ModelListener.class) {
00427                                 ((ModelListener) listeners[i + 1])
00428                                                 .viewableRangeChanged (modelEvent);
00429                         }
00430                 }
00431         }
00432 
00437         protected void fireViewableRangeStartEvent () {
00438                 Object [] listeners = listenerList.getListenerList ();
00439                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00440                         if (listeners[i] == ModelListener.class) {
00441                                 ((ModelListener) listeners[i + 1])
00442                                                 .viewableRangeChangeStart (modelEvent);
00443                         }
00444                 }
00445         }
00446 
00451         protected void fireViewableRangeEndEvent () {
00452                 Object [] listeners = listenerList.getListenerList ();
00453                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00454                         if (listeners[i] == ModelListener.class) {
00455                                 ((ModelListener) listeners[i + 1])
00456                                                 .viewableRangeChangeEnd (modelEvent);
00457                         }
00458                 }
00459         }
00460 
00465         protected void fireReorderGenomeEvent () {
00466                 Object [] listeners = listenerList.getListenerList ();
00467                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00468                         if (listeners[i] == ModelListener.class) {
00469                                 ((ModelListener) listeners[i + 1])
00470                                                 .genomesReordered (modelEvent);
00471                         }
00472                 }
00473         }
00474 
00479         protected void fireReferenceChangedEvent () {
00480                 Object [] listeners = listenerList.getListenerList ();
00481                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00482                         if (listeners[i] == ModelListener.class) {
00483                                 ((ModelListener) listeners[i + 1])
00484                                                 .referenceChanged (modelEvent);
00485                         }
00486                 }
00487         }
00488 
00494         public ViewerMode getMode () {
00495                 return mode;
00496         }
00497 
00505         public void setMode (ViewerMode mode) {
00506                 if (this.mode != mode) {
00507                         this.mode = mode;
00508                         fireModeEvent ();
00509                 }
00510         }
00511 
00525         public void reorderSequences (int [] new_order) {
00526                 // Reorder genomes
00527                 Genome [] newGenomes = new Genome [genomes.length];
00528                 for (int seqI = 0; seqI < genomes.length; seqI++) {
00529                         newGenomes[seqI] = genomes[new_order[seqI]];
00530                         newGenomes[seqI].setViewIndex (seqI);
00531                 }
00532                 genomes = newGenomes;
00533 
00534                 fireReorderGenomeEvent ();
00535         }
00536 
00537         public void setReference (Genome g) {
00538                 referenceGenome = g;
00539                 referenceUpdated ();
00540                 fireReferenceChangedEvent ();
00541         }
00542 
00543         public Genome getReference () {
00544                 return referenceGenome;
00545         }
00546 
00547         protected void referenceUpdated () {
00548                 // Hook for subclasses.
00549         }
00550 
00551     public void setVisible(Genome g, boolean visible)
00552     {
00553         if(g.getVisible() != visible )
00554         {
00555                 g.setVisible(visible);
00556                 fireGenomeVisibilityChangedEvent();
00557         }
00558     }
00559     
00560     public void fireGenomeVisibilityChangedEvent()
00561     {
00562         Object[] listeners = listenerList.getListenerList();
00563         for (int i = listeners.length-2; i>=0; i-=2) {
00564             if (listeners[i]==ModelListener.class) {
00565                 ((ModelListener)listeners[i+1]).genomeVisibilityChanged(modelEvent);
00566             }
00567         }
00568     }
00569 
00570         private void correctMatchReversals () {
00571                 // Correct the orientation due to reversals.
00572                 for (int matchI = 0; matchI < getMatchCount (); matchI++) {
00573                         Match m = getMatch (matchI);
00574 
00575                         // Find the first genome with something to show for each match
00576                         // and make that the reference orientation.
00577                         for (int seqI = 0; seqI < genomes.length; seqI++) {
00578                                 Genome g = getGenomeByViewingIndex (seqI);
00579 
00580                                 if (m.getStart (g) != 0) {
00581                                         if (m.getReverse (g)) {
00582                                                 for (int seqJ = seqI; seqJ < genomes.length; seqJ++) {
00583                                                         Genome g2 = getGenomeByViewingIndex (seqJ);
00584                                                         m.setReverse (g2, !m.getReverse (g2));
00585                                                 }
00586                                         }
00587                                         break;
00588                                 }
00589                         }
00590                 }
00591         }
00592 
00606         public void getMatchRange (Genome g, long start_coord, long end_coord,
00607                         int [] match_range) {
00608                 Vector sortedMatches = g.getSortedMatches ();
00609 
00610                 if (sortedMatches.size () == 0) {
00611                         match_range[0] = -1;
00612                         match_range[1] = -1;
00613                         return;
00614                 }
00615 
00616                 MatchStartComparator matchComparator = new MatchStartComparator (g);
00617                 Match f_match = new Match ((Match) sortedMatches.get (0));
00618 
00619                 f_match.setStart (g, start_coord);
00620                 if (f_match.getStart (g) < 1)
00621                         f_match.setStart (g, 1);
00622 
00623                 int match_startI = Collections.binarySearch (sortedMatches, f_match,
00624                                 matchComparator);
00625                 match_startI = match_startI >= 0 ? match_startI : -match_startI - 1;
00626 
00627                 f_match.setStart (g, end_coord + 1);
00628                 int match_endI = Collections.binarySearch (sortedMatches, f_match,
00629                                 matchComparator);
00630                 match_endI = match_endI >= 0 ? match_endI : -match_endI - 1;
00631 
00632                 // now look backwards 1 match for an intersection
00633                 if (match_startI > 0) {
00634                         Match prev_match = (Match) sortedMatches.get (match_startI - 1);
00635 
00636                         if (prev_match.getStart (g) + prev_match.getLength (g) > start_coord
00637                                         && prev_match.getStart (g) != Match.NO_MATCH)
00638                                 match_startI--;
00639                 }
00640                 match_range[0] = match_startI;
00641                 match_range[1] = match_endI;
00642         }
00643 
00650         public void addMatchHighlight (Match highlighted_box) {
00651                 ListIterator high_iter = highBoxes.listIterator ();
00652                 while (high_iter.hasNext ()) {
00653                         if (high_iter.next () == highlighted_box) {
00654                                 return;
00655                         }
00656                 }
00657                 highlighted_box.highlighted = true;
00658                 highBoxes.addLast (highlighted_box);
00659 
00660                 fireHighlightEvent ();
00661         }
00662 
00663         public Match lastMatchHighlight () {
00664                 if (highBoxes.isEmpty ())
00665                         return null;
00666 
00667                 return (Match) highBoxes.getLast ();
00668 
00669         }
00670 
00674         public void clearMatchHighlights () {
00675                 ListIterator high_iter = highBoxes.listIterator ();
00676                 while (high_iter.hasNext ()) {
00677                         Match next_box = (Match) high_iter.next ();
00678                         next_box.highlighted = false;
00679                 }
00680                 highBoxes.clear ();
00681 
00682                 fireHighlightEvent ();
00683         }
00684 
00685         public long getHighlightCoordinate () {
00686                 return highlightCoordinate;
00687         }
00688 
00689         public Genome getHighlightGenome () {
00690                 return highlightGenome;
00691         }
00692 
00693         public long getRangeHighlightLeft () {
00694                 return rangeHighlightLeft;
00695         }
00696 
00697         public long getRangeHighlightRight () {
00698                 return rangeHighlightRight;
00699         }
00700 
00701         public Genome getRangeHighlightGenome () {
00702                 return rangeHighlightGenome;
00703         }
00704 
00705         public void updateHighlight (Genome g, long coordinate) {
00706                 highlightGenome = g;
00707                 highlightCoordinate = coordinate;
00708                 fireHighlightEvent ();
00709         }
00710 
00711         public void setDrawMatches (boolean value) {
00712                 if (value != drawMatches) {
00713                         this.drawMatches = value;
00714                         this.fireDrawingSettingsEvent ();
00715                 }
00716         }
00717 
00718         public boolean getDrawMatches () {
00719                 return drawMatches;
00720         }
00721 
00722         public void setDrawChromosomeBoundaries (boolean value) {
00723                 if (value != drawChromosomeBoundaries) {
00724                         this.drawChromosomeBoundaries = value;
00725                         this.fireDrawingSettingsEvent ();
00726                 }
00727         }
00728 
00729         public boolean getDrawChromosomeBoundaries () {
00730                 return drawChromosomeBoundaries;
00731         }
00732 
00733         public void setDrawMouseCursor (boolean value) {
00734                 if (value != drawMouseHighlighting) {
00735                         this.drawMouseHighlighting = value;
00736                         this.fireDrawingSettingsEvent ();
00737                 }
00738         }
00739 
00740         public boolean getDrawMouseHighlighting () {
00741                 return drawMouseHighlighting;
00742         }
00743 
00744         public void setFocus (String sequenceID, long start, long end, String contig) {
00745                 Genome g = null;
00746                 for (int i = 0; i < genomes.length; i++) {
00747                         if (sequenceID.equals (genomes[i].getID ())) {
00748                                 g = genomes[i];
00749                                 break;
00750                         }
00751                 }
00752                 if (g == null) {
00753                         System.err
00754                                         .println ("Received focus request for nonexistent sequence id "
00755                                                         + sequenceID);
00756                         return;
00757                 }
00758                 if (contig != null) {
00759                         start = contig_handler.getPseudoCoord(g.getSourceIndex(), start, contig);
00760                         end = contig_handler.getPseudoCoord(g.getSourceIndex(), end, contig);
00761                 }
00762                 long len = (end - start) * 5;
00763                 int zoom = (int) (100 * g.getViewLength () / (double) len);
00764                 long center = start + ((end - start) / 2);
00765                 zoomAndCenter (g, zoom, center);
00766                 // highlight this part of the display
00767                 highlightRange (g, start, end);
00768         }
00769 
00775         public void alignView (long [] align_coords, Genome selected) {
00776                 fireViewableRangeStartEvent ();
00777 
00778                 // adjust everything to the same zoom level as the selected sequence
00779 
00780                 long start_offset = align_coords[selected.getSourceIndex ()]
00781                                 - selected.getViewStart ();
00782                 for (int seqI = 0; seqI < getSequenceCount (); seqI++) {
00783                         if (seqI != selected.getSourceIndex ()
00784                                         && align_coords[seqI] != Match.NO_MATCH) {
00785                                 Genome g = getGenomeBySourceIndex (seqI);
00786                                 g.setViewStart (align_coords[seqI] - start_offset);
00787                                 g.setViewLength (selected.getViewLength ());
00788                         }
00789                 }
00790                 fireViewableRangeEvent ();
00791 
00792                 fireViewableRangeEndEvent ();
00793         }
00794 
00795         public void alignView (Match align_match, Genome g) {
00796                 long [] align_coords = new long [getSequenceCount ()];
00797 
00798                 for (int i = 0; i < getSequenceCount (); i++) {
00799                         align_coords[i] = align_match.getStart (getGenomeBySourceIndex (i));
00800                 }
00801 
00802                 alignView (align_coords, g);
00803         }
00804 
00819         public void zoomAndMove (int zoom_percent, int move_percent) {
00820                 for (int i = 0; i < genomes.length; i++) {
00821                         zoomAndMove (genomes[i], zoom_percent, move_percent);
00822                 }
00823         }
00824 
00825         public void zoomAndMove (int zoom_percent, long offset) {
00826                 for (int i = 0; i < genomes.length; i++) {
00827                         zoomAndMove (genomes[i], zoom_percent, offset);
00828                 }
00829         }
00830 
00845         public void zoomAndMove (Genome g, int zoom_percent, int move_percent) {
00846 
00847                 if (move_percent != 0) {
00848                         double move = ((double) g.getViewLength ()) * (move_percent / 100d);
00849                         if (Math.abs (move) < 1) {
00850                                 move = (move < 0) ? -1 : 1;
00851                         }
00852                         zoomAndMove (g, zoom_percent, (long) move);
00853                 } else {
00854                         zoomAndMove (g, zoom_percent, 0L);
00855                 }
00856         }
00857 
00858         private void zoomAndMove (Genome g, int zoom_percent, long offset) {
00859                 fireViewableRangeStartEvent ();
00860 
00861                 // move before zooming so that we end up on the right coordinates!
00862                 if (offset != 0) {
00863                         // calculate the new viewable coordinates.
00864                         long new_view_start = g.getViewStart () + offset;
00865 
00866                         // don't let the sequence get completely out of range
00867                         if (new_view_start + g.getViewLength () < 1) {
00868                                 new_view_start = 1 - g.getViewLength ();
00869                         } else if (new_view_start > g.getLength ()) {
00870                                 new_view_start = g.getLength ();
00871                         }
00872                         g.setViewStart (new_view_start);
00873                 }
00874 
00875                 if (zoom_percent == 0) {
00876                         // zoom all the way out.
00877                         g.setViewStart (1);
00878                         g.setViewLength (longestRange);
00879                 } else if (zoom_percent != 100) {
00880                         // calculate the new viewable coordinates.
00881                         long new_view_length = (long) ((100d * g.getViewLength ()) / zoom_percent);
00882                         // don't let the view length get too big or small
00883                         if (new_view_length < 5)
00884                                 new_view_length = 5;
00885                         if (new_view_length > longestRange)
00886                                 new_view_length = longestRange;
00887 
00888                         long new_view_start = g.getViewStart ()
00889                                         + ((g.getViewLength () - new_view_length) / 2);
00890 
00891                         // don't let the sequence get completely out of range
00892                         if (new_view_start + new_view_length < 1)
00893                                 new_view_start = 1 - g.getViewLength ();
00894                         else if (new_view_start > g.getLength ())
00895                                 new_view_start = g.getLength ();
00896 
00897                         g.setViewStart (new_view_start);
00898                         g.setViewLength (new_view_length);
00899                 }
00900 
00901                 fireViewableRangeEvent ();
00902 
00903                 fireViewableRangeEndEvent ();
00904         }
00905 
00906         public void zoomAndCenter (Genome g, int zoom_percent, long coord) {
00907                 long offset = coord - (g.getViewStart () + (g.getViewLength () / 2));
00908                 zoomAndMove (zoom_percent, offset);
00909         }
00910 
00912         public void highlightRange (Genome g, long left_end, long right_end) {
00913                 rangeHighlightGenome = g;
00914                 rangeHighlightLeft = left_end;
00915                 rangeHighlightRight = right_end;
00916                 fireHighlightEvent ();
00917         }
00918 
00919         private HashMap<Genome,List> attributes = new HashMap<Genome,List>();
00920         public void addGenomeAttribute(Genome g, Object o){
00921                 List l = attributes.get(g);
00922                 if(l==null){
00923                         l = new ArrayList();
00924                         attributes.put(g,l);
00925                 }
00926                 l.add(o);
00927                 fireAttributesEvent();
00928         }
00929         public List getGenomeAttributes(Genome g){
00930                 return attributes.get(g);
00931         }
00932         boolean drawAttributes = false;
00933         public boolean getDrawAttributes() {
00934                 return drawAttributes;
00935         }
00936         public void setDrawAttributes(boolean drawAttributes) {
00937                 this.drawAttributes = drawAttributes;
00938                 fireAttributesEvent();
00939         }
00940 
00945         protected void fireAttributesEvent () {
00946                 Object [] listeners = listenerList.getListenerList ();
00947                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00948                         if (listeners[i] == ModelListener.class) {
00949                                 ((ModelListener) listeners[i + 1]).attributesChanged (modelEvent);
00950                         }
00951                 }
00952         }
00953 
00954 }

Generated on Mon Aug 19 06:03:40 2013 for Mauve by doxygen 1.3.6