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
00039
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
00064
00065
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
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
00098
00099
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
00115 if(cache_instream != null){
00116 try{
00117 xmfa = (XMFAAlignment)cache_instream.readObject();
00118 xmfa.setFile(inputFile);
00119 }catch(ClassNotFoundException cnfe){
00120
00121 cache_instream = null;
00122 }catch(ClassCastException cce){
00123
00124 cache_instream = null;
00125 }catch(InvalidClassException ice){
00126 cache_instream = null;
00127 }
00128 }
00129
00130 if(cache_instream == null)
00131 xmfa = new XMFAAlignment(inputFile);
00132
00133
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
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
00167
00168 g = getGenomeBySourceIndex(seqI);
00169 }
00170 }
00171
00172
00173 try{
00174 bb_list = BackboneListBuilder.build(this,xmfa);
00175 if( bb_list != null )
00176 {
00177
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
00188 for (int seqI = 0; seqI < xmfa.seq_count; seqI++)
00189 {
00190 Genome g = getGenomeBySourceIndex(seqI);
00191
00192 if(cache_instream != null){
00193 try{
00194 sim[seqI] = (SimilarityIndex)cache_instream.readObject();
00195 }catch(ClassNotFoundException cnfe){
00196
00197 cache_instream = null;
00198 }catch(ClassCastException cce){
00199
00200 cache_instream = null;
00201 }catch(InvalidClassException ice){
00202 cache_instream = null;
00203 }
00204 }
00205
00206 if(cache_instream == null)
00207 sim[seqI] = new SimilarityIndex(g, xmfa, bb_list);
00208 }
00209
00210
00211
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
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
00231 setColorScheme(new LCBColorScheme());
00232 if( bb_list != null )
00233 setColorScheme(new BackboneLcbColor());
00234 initModelLCBs();
00235
00236
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
00244 LCB[] splitLCBs = PermutationExporter.getSplitLCBs(this);
00245 setSplitLcbList(splitLCBs);
00246
00247
00248
00249 }
00250
00251 MauveDisplayCommunicator mdCommunicator = null;
00252 WargDisplayCommunicator wdCommunicator = null;
00253
00254
00255
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
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
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
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
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
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
00513 e.printStackTrace ();
00514 } catch (IOException e) {
00515
00516 e.printStackTrace ();
00517 }
00518
00519 fireReloadEndEvent ();
00520 }
00521
00522 protected void fireReloadEndEvent () {
00523
00524 Object [] listeners = listenerList.getListenerList ();
00525
00526
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
00536 Object [] listeners = listenerList.getListenerList ();
00537
00538
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;
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 }