src/org/gel/mauve/XmfaViewerModel.java

Go to the documentation of this file.
00001 package org.gel.mauve;
00002 
00003 import java.io.File;
00004 import java.io.FileNotFoundException;
00005 import java.io.FileOutputStream;
00006 import java.io.IOException;
00007 import java.io.InvalidClassException;
00008 import java.io.ObjectInputStream;
00009 import java.io.ObjectOutputStream;
00010 import java.io.RandomAccessFile;
00011 import java.net.URL;
00012 import java.util.ArrayList;
00013 import java.util.Arrays;
00014 import java.util.HashMap;
00015 import java.util.List;
00016 import java.util.prefs.BackingStoreException;
00017 
00018 import org.biojava.bio.seq.DNATools;
00019 import org.biojava.bio.seq.Sequence;
00020 import org.biojava.bio.symbol.SymbolList;
00021 import org.gel.mauve.analysis.PermutationExporter;
00022 import org.gel.mauve.backbone.BackboneList;
00023 import org.gel.mauve.backbone.BackboneListBuilder;
00024 import org.gel.mauve.color.BackboneLcbColor;
00025 import org.gel.mauve.color.LCBColorScheme;
00026 import org.gel.mauve.histogram.HistogramBuilder;
00027 import org.gel.mauve.remote.MauveDisplayCommunicator;
00028 import org.gel.mauve.remote.WargDisplayCommunicator;
00029 
00036 public class XmfaViewerModel extends LcbViewerModel {
00037         private XMFAAlignment xmfa;
00038         // Sequence similarity profiles calculated over the length of each sequence
00039         // represented in an XMFA file
00040         private SimilarityIndex [] sim;
00041         private long [] highlights;
00042         private BackboneList bb_list;
00043 
00044         public void setSequenceCount (int sequenceCount) {
00045                 super.setSequenceCount (sequenceCount);
00046                 sim = new SimilarityIndex [sequenceCount];
00047         }
00048 
00049         public XmfaViewerModel (File src, ModelProgressListener listener)
00050                         throws IOException {
00051                 super (src);
00052                 super.setDrawLcbBounds(false);
00053                 init (listener, false);
00054         }
00055 
00061     private void init(ModelProgressListener listener, boolean isReloading) throws FileNotFoundException, IOException
00062     {
00063         // attempt to load data such as SimilarityIndexes from a
00064         // disk-based cache file
00065         // Find cached directory, if it exists.
00066         URL xmfa_url = new URL("file://" + getSrc());
00067         File dir = null;
00068         if(ModelBuilder.getUseDiskCache())
00069         {
00070                 try
00071                 {
00072                     dir = ModelBuilder.getCachedDirectory(xmfa_url);
00073                 }
00074                 catch (BackingStoreException e)
00075                 {
00076                     System.err.println("Error reading preferences.  Error follows.  Will load from server.");
00077                     e.printStackTrace();
00078                 }
00079         }
00080         if( ModelBuilder.getUseDiskCache() && dir == null ){
00081                 // Create a temporary directory.
00082                 dir = File.createTempFile("mauve", "dir");
00083                 dir.delete();
00084                 dir.mkdir();
00085                 if (!dir.exists() || !dir.isDirectory())
00086                 {
00087                     throw new IOException("Couldn't create temporary directory.");
00088                 }
00089                 ModelBuilder.saveCachedDirectory(xmfa_url, dir);
00090         }
00091         
00092         if (listener != null)
00093         {
00094             listener.alignmentStart();
00095         }
00096 
00097         // check whether XMFA has changed since the
00098         // cache was created!!
00099         // open object I/O for caching
00100         File cache_file = null;
00101         ObjectInputStream cache_instream = null;
00102         if(ModelBuilder.getUseDiskCache())
00103         {
00104             cache_file = new File(dir, "mauve.cache");
00105                 if(cache_file.exists() && cache_file.canRead() &&
00106                                 getSrc().lastModified() < cache_file.lastModified())
00107                 {
00108                         cache_instream = new ObjectInputStream(new java.io.FileInputStream(cache_file));
00109                 }
00110         }
00111 
00112         RandomAccessFile inputFile = new RandomAccessFile(getSrc(), "r");
00113         
00114         // read XMFA from object cache if possible
00115         if(cache_instream != null){
00116             try{
00117                 xmfa = (XMFAAlignment)cache_instream.readObject();
00118                 xmfa.setFile(inputFile);
00119             }catch(ClassNotFoundException cnfe){
00120                 // cache must be corrupt
00121                 cache_instream = null;
00122             }catch(ClassCastException cce){
00123                 // cache must be corrupt
00124                 cache_instream = null;
00125             }catch(InvalidClassException ice){
00126                 cache_instream = null;
00127             }
00128         }
00129         // it didn't get read from the cache
00130         if(cache_instream == null)
00131             xmfa = new XMFAAlignment(inputFile);
00132 
00133         // If no sequences are found, this is certainly an invalid file.
00134         if (xmfa.seq_count == 0)
00135         {
00136             throw new IOException("Not an XMFA file.  Please check that the" +
00137                         " input file is a properly formatted alignment.");
00138         }
00139         
00140         if (listener != null)
00141         {
00142             listener.alignmentEnd(xmfa.seq_count);
00143         }
00144 
00145         if (!isReloading)
00146         {
00147             setSequenceCount(xmfa.seq_count);
00148         }
00149 
00150         // now build genomes
00151         for (int seqI = 0; seqI < xmfa.seq_count; seqI++)
00152         {
00153             if (listener != null)
00154             {
00155                 listener.featureStart(seqI);
00156             }
00157 
00158             Genome g = null;
00159             if (!isReloading)
00160             {
00161                 g = GenomeBuilder.buildGenome(seqI, this);
00162                 setGenome(seqI, g);
00163             }
00164             else
00165             {
00166                 // If reloading, reorder the genomes to the same order as
00167                 // in the file.  reload() will take care of the reordering.
00168                 g = getGenomeBySourceIndex(seqI);
00169             }
00170         }
00171         
00172         // now try to read a backbone list
00173         try{
00174                 bb_list = BackboneListBuilder.build(this,xmfa);
00175                 if( bb_list != null )
00176                 {
00177                 // if the backbone is newer than the cache then clear the cache
00178                         File bb_file = BackboneListBuilder.getFileByKey(this,xmfa,"BackboneFile");
00179                     if( ModelBuilder.getUseDiskCache() && bb_file.lastModified() > cache_file.lastModified())
00180                         cache_instream = null;
00181                 }
00182         }catch(IOException ioe)
00183         {
00184                 bb_list = null;
00185         }
00186 
00187         // now compute SimilarityIndex
00188         for (int seqI = 0; seqI < xmfa.seq_count; seqI++)
00189         {
00190             Genome g = getGenomeBySourceIndex(seqI);
00191             // read the SimilarityIndex from object cache if possible
00192             if(cache_instream != null){
00193                 try{
00194                         sim[seqI] = (SimilarityIndex)cache_instream.readObject();
00195                 }catch(ClassNotFoundException cnfe){
00196                         // cache must be corrupt
00197                         cache_instream = null;
00198                 }catch(ClassCastException cce){
00199                         // cache must be corrupt
00200                         cache_instream = null;
00201                 }catch(InvalidClassException ice){
00202                         cache_instream = null;
00203                 }
00204             }
00205             // it didn't get read from the cache
00206             if(cache_instream == null)
00207                 sim[seqI] = new SimilarityIndex(g, xmfa, bb_list);
00208         }
00209 
00210         // if cache_instream is null there must have been a problem
00211         // reading the cache.  write out all objects that should be cached
00212         if(cache_instream == null && ModelBuilder.getUseDiskCache()){
00213                 ObjectOutputStream cache_outstream = null;
00214                 cache_outstream = new ObjectOutputStream(new FileOutputStream(cache_file));
00215                 cache_outstream.writeObject(xmfa);
00216                 for( int seqI = 0; seqI < xmfa.seq_count; seqI++ )
00217                 cache_outstream.writeObject(sim[seqI]);
00218         }
00219         
00220         // copy the LCB list
00221         setFullLcbList(new LCB[xmfa.lcb_list.length]);
00222         System.arraycopy(xmfa.lcb_list, 0, getFullLcbList(), 0, xmfa.lcb_list.length);
00223 
00224         setDelLcbList(new LCB[0]);
00225         setLcbCount(getFullLcbList().length);
00226         
00227         highlights = new long[getSequenceCount()];
00228         Arrays.fill(highlights, Match.NO_MATCH);
00229 
00230         // set LCB colors first
00231         setColorScheme(new LCBColorScheme());
00232         if( bb_list != null )
00233                 setColorScheme(new BackboneLcbColor());
00234         initModelLCBs();
00235         
00236         // check if there's a histogram
00237         File histFile = BackboneListBuilder.getFileByKey(this, xmfa, "HistogramFile");
00238         if(histFile != null){
00239                 RandomAccessFile raf = new RandomAccessFile(histFile, "r");
00240                 HistogramBuilder.build(raf, this);
00241         }
00242         
00243         // Now that we've initialized everything, we can make split LCBs
00244         LCB[] splitLCBs = PermutationExporter.getSplitLCBs(this); 
00245         setSplitLcbList(splitLCBs);
00246       //  LCB[] testSplitLCBs = PermutationExporter.splitLcbList(this, splitLCBs, genomes);
00247       //  System.err.println("");
00248         // try publishing this viewer model via DBus
00249     }
00250 
00251     MauveDisplayCommunicator mdCommunicator = null;
00252     WargDisplayCommunicator wdCommunicator = null;
00253     /*
00254      * Attempts to open two-way DBus communication with the weakarg app for this viewer model
00255      * Warning, when this fails, it currently fails silently!!
00256      */
00257     public void initDbusCommunication(){
00258         try{
00259         try{
00260         try{
00261                 mdCommunicator = new MauveDisplayCommunicator(this);
00262         }catch(UnsatisfiedLinkError ule){}
00263         }catch(NoClassDefFoundError ncdfe){}
00264         }catch(Exception e){}
00265         // try connecting to a warg instance
00266         try{
00267         try{
00268         try{
00269                 wdCommunicator = new WargDisplayCommunicator(this);
00270                 
00271         }catch(UnsatisfiedLinkError ule){}
00272         }catch(NoClassDefFoundError ncdfe){}
00273         }catch(Exception e){ }
00274     }
00275 
00276         protected void referenceUpdated () {
00277                 super.referenceUpdated ();
00278                 xmfa.setReference (getReference ());
00279         }
00280 
00285     public XMFAAlignment getXmfa()
00286     {
00287         return xmfa;
00288     }
00289 
00290         // NEWTODO: Sort sims on sourceIndex instead!
00291         public SimilarityIndex getSim (Genome g) {
00292                 return sim[g.getSourceIndex ()];
00293         }
00294 
00302         public long [] getLCBAndColumn (Genome g, long position) {
00303                 return xmfa.getLCBAndColumn (g, position);
00304         }
00305         
00306         public long[] getLCBAndColumn(int genSrcIdx, long position){
00307                 return this.getLCBAndColumn(genomes[genSrcIdx], position);
00308         }
00309 
00310         public int getLCBIndex (Genome g, long position) {
00311                 return xmfa.getLCB (g, position);
00312         }
00313         
00329         public byte[][] getSequenceRange(Genome g, long left, long right){
00330                 byte[][] tmp = xmfa.getRange(g, left, right);
00331                 for (int i = 0; i < tmp.length; i++){
00332                         tmp[i] = XMFAAlignment.filterNewlines(tmp[i]);
00333                 }
00334                 return tmp;
00335         }
00336         
00353         /* FIXME */
00354         public byte[][] getSequenceRange(int genSrcIdx, long left, long right){
00355                 return this.getSequenceRange(genomes[genSrcIdx], left, right);
00356         }
00357 
00363         public BackboneList getBackboneList () {
00364                 return bb_list;
00365         }
00366 
00377         public void getColumnCoordinates (int lcb, long column, long [] seq_coords, boolean [] gap) {
00378                 xmfa.getColumnCoordinates (this, lcb, column, seq_coords, gap);
00379         }
00380         
00393         public long getHomologousCoordinate(int genX, long pos, int genY){
00394                 long[] lcb = getLCBAndColumn(genomes[genX], pos);
00395                 long[] seq_coords = new long[genomes.length];
00396                 boolean[] gap = new boolean[genomes.length];
00397                 getColumnCoordinates((int) lcb[0], lcb[1], seq_coords, gap);
00398                 if (!gap[genY])
00399                         return seq_coords[genY];
00400                 else
00401                         return 0;
00402         }
00403         
00417         public char[] getSequence(long start, long end, int genSrcIdx){
00418                 Sequence annSeq = genomes[genSrcIdx].getAnnotationSequence();
00419                 if (annSeq == null){
00420                         return null;
00421                 } else {
00422                         try {
00423                                 if (start > end){
00424                                         return DNATools.reverseComplement(annSeq.subList((int)end, (int)start)).seqString().toCharArray();
00425                                 } else {
00426                                         return annSeq.subList((int) start, (int)end).seqString().toCharArray();
00427                                 }
00428                         } catch (Exception e){
00429                                 System.err.println("Error getting sequence coordinates (" 
00430                                                 +start+", "+end+ ") for " + genomes[genSrcIdx].getDisplayName());
00431                                 System.err.println("Sequence : " + annSeq.length());
00432                                 e.printStackTrace();
00433                         }
00434                 }
00435                 return null;
00436         }
00437 
00438         public void updateHighlight (Genome g, long coordinate) {
00439                 highlights = null;
00440                 // Wait til end to call super, since it fires event.
00441                 super.updateHighlight (g, coordinate);
00442         }
00443 
00444         public long getHighlight (Genome g) {
00445                 if (highlights == null) {
00446                         long [] iv_col = getLCBAndColumn (getHighlightGenome (),
00447                                         getHighlightCoordinate ());
00448                         boolean [] gap = new boolean [this.getSequenceCount ()];
00449                         ;
00450                         highlights = new long [this.getSequenceCount ()];
00451                         getColumnCoordinates ((int) iv_col[0], iv_col[1], highlights, gap);
00452                         for (int i = 0; i < highlights.length; ++i) {
00453                                 highlights[i] = Math.abs (highlights[i]);
00454                                 if (gap[i])
00455                                         highlights[i] *= -1;
00456                         }
00457                 }
00458                 return highlights[g.getSourceIndex ()];
00459         }
00460 
00466         public void alignView (Genome g, long position) {
00467                 long [] iv_col;
00468                 try {
00469                         iv_col = getLCBAndColumn (g, position);
00470                 } catch (ArrayIndexOutOfBoundsException e) {
00471                         // User clicked outside of bounds of sequence, so do nothing.
00472                         return;
00473                 }
00474                 long [] coords = new long [this.getSequenceCount ()];
00475                 ;
00476                 boolean [] gap = new boolean [this.getSequenceCount ()];
00477                 ;
00478                 getColumnCoordinates ((int) iv_col[0], iv_col[1], coords, gap);
00479                 alignView (coords, g);
00480         }
00481 
00486         public void setFocus (String sequenceID, long start, long end, String contig) {
00487                 super.setFocus (sequenceID, start, end, contig);
00488                 Genome g = null;
00489                 for (int i = 0; i < genomes.length; i++) {
00490                         if (sequenceID.equals (genomes[i].getID ())) {
00491                                 g = genomes[i];
00492                                 break;
00493                         }
00494                 }
00495                 if (g == null) {
00496                         System.err
00497                                         .println ("Received focus request for nonexistent sequence id "
00498                                                         + sequenceID);
00499                         return;
00500                 }
00501                 if (contig != null)
00502                         start = contig_handler.getPseudoCoord(g.getSourceIndex(), start, contig);
00503                 alignView (g, start);
00504         }
00505 
00506         public void reload () {
00507                 fireReloadStartEvent ();
00508 
00509                 try {
00510                         init (null, true);
00511                 } catch (FileNotFoundException e) {
00512                         // TODO Auto-generated catch block
00513                         e.printStackTrace ();
00514                 } catch (IOException e) {
00515                         // TODO Auto-generated catch block
00516                         e.printStackTrace ();
00517                 }
00518 
00519                 fireReloadEndEvent ();
00520         }
00521 
00522         protected void fireReloadEndEvent () {
00523                 // Guaranteed to return a non-null array
00524                 Object [] listeners = listenerList.getListenerList ();
00525                 // Process the listeners last to first, notifying
00526                 // those that are interested in this event
00527                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00528                         if (listeners[i] == ModelListener.class) {
00529                                 ((ModelListener) listeners[i + 1]).modelReloadEnd (modelEvent);
00530                         }
00531                 }
00532         }
00533 
00534         protected void fireReloadStartEvent () {
00535                 // Guaranteed to return a non-null array
00536                 Object [] listeners = listenerList.getListenerList ();
00537                 // Process the listeners last to first, notifying
00538                 // those that are interested in this event
00539                 for (int i = listeners.length - 2; i >= 0; i -= 2) {
00540                         if (listeners[i] == ModelListener.class) {
00541                                 ((ModelListener) listeners[i + 1])
00542                                                 .modelReloadStart (modelEvent);
00543                         }
00544                 }
00545         }
00546 
00547         boolean drawSimilarityRanges = true;    // whether or not the whole range of similarity values should be drawn
00548         public boolean getDrawSimilarityRanges() {
00549                 return drawSimilarityRanges;
00550         }
00551         public void setDrawSimilarityRanges(boolean drawSimilarityRanges) {
00552                 if (this.drawSimilarityRanges != drawSimilarityRanges) {
00553                         this.drawSimilarityRanges = drawSimilarityRanges;
00554                         fireDrawingSettingsEvent ();
00555                 }
00556         }
00557 }

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