improve error handling for loading
authorDiane Trout <diane@caltech.edu>
Fri, 3 Mar 2006 09:14:06 +0000 (09:14 +0000)
committerDiane Trout <diane@caltech.edu>
Fri, 3 Mar 2006 09:14:06 +0000 (09:14 +0000)
I think all of the mussa file loading code throws a mussa_load_error
when something doesn't work. (instead of returning an error string).
All the GUIs catch this error and display the error in their message box

One annoying thing was that loading a different analysis after you'd already
loaded one in the Qt version caused it to try to merge the two versions
and then die when it ran its analysis. I got around that by deleting the
old mussa pointer and replacing it with the newly loaded version.
Though I discovered I need to do the pointer swap _after_ I'd successfully
loaded a the new analysis.

Also the Qt version doesn't try to load anything when the user presses
the cancel button in the load dialog boxes.

13 files changed:
alg/mussa_class.cxx
alg/mussa_class.hh
alg/nway_paths.cxx
alg/nway_paths.hh
alg/parse_options.cxx
alg/sequence.cxx
alg/sequence.hh
alg/test/test_sequence.cxx
gui/ConnWindow.cxx
mussa.cxx
mussa_exceptions.hh
qui/PathScene.cxx
qui/PathScene.h

index bd86a2f6d7ef8e5c1c5da7595c12e20fb2c9176d..139a6bb25f42e6524739185183a2de893e638843 100644 (file)
@@ -164,7 +164,7 @@ Mussa::sequences() const
   return the_seqs;
 }
 
-string
+void
 Mussa::load_mupa_file(string para_file_path)
 {
   ifstream para_file;
@@ -177,7 +177,6 @@ Mussa::load_mupa_file(string para_file_path)
   bool parsing_path;
   string::size_type new_index, dir_index;
 
-
   // initialize values
   clear();
 
@@ -284,15 +283,11 @@ Mussa::load_mupa_file(string para_file_path)
     cout << "nway mupa: analysis_name = " << analysis_name 
          << " window = " << window 
          << " threshold = " << threshold << endl;
-
-    return "";
   }
-
   // no file was loaded, signal error
   else
   {
-    err_msg = "Config File: " + para_file_path + " not found";
-    return err_msg;
+    throw mussa_load_error("Config File: " + para_file_path + " not found");
   }
 }
 
@@ -316,12 +311,7 @@ Mussa::analyze(int w, int t, enum Mussa::analysis_modes the_ana_mode, double new
   }
 
   t1 = time(NULL);
-  try {
-    load_sequence_data();
-  } catch(sequence_load_error e) {
-    cerr << "Unable to load sequence" << endl;
-    cerr << e.what() << endl;
-  }
+  load_sequence_data();
         
   if (the_seqs.size() < 2) {
     throw mussa_analysis_error("you need to have at least 2 sequences to "
@@ -551,7 +541,7 @@ Mussa::save_muway(string save_path)
   the_paths.save(save_path);
 }
 
-string
+void
 Mussa::load(string ana_file)
 {
   int i, i2;
@@ -569,7 +559,6 @@ Mussa::load(string ana_file)
   parsing_path = true;
   end_index = ana_path.size()-1;
   if (ana_path[end_index] == '/') { 
-    cout << "found trailing /" << endl;
     --end_index;
   }
   start_index = ana_path.rfind('/', end_index);
@@ -582,62 +571,47 @@ Mussa::load(string ana_file)
   }
   analysis_name = ana_path.substr(start_index, end_index-start_index+1);
   cout << " ana_name " << analysis_name << endl;
-  file_path_base =  ana_path.substr(0, start_index) + analysis_name +"/" + analysis_name;
+  file_path_base =  ana_path.substr(0, start_index) + analysis_name 
+                    + "/" + analysis_name;
   a_file_path = file_path_base + ".muway";
   cout << " loading museq: " << a_file_path << endl;
-  err_msg = the_paths.load(a_file_path);
-
-  if (err_msg == "")
-  {
-    int seq_num = the_paths.sequence_count();
+  the_paths.load(a_file_path);
 
-    cout << "No BAM " << seq_num << endl; ;
+  int seq_num = the_paths.sequence_count();
 
-    a_file_path = file_path_base + ".museq";
+  a_file_path = file_path_base + ".museq";
 
-    // this is a bit of a hack due to C++ not acting like it should with files
-    for (i = 1; i <= seq_num; i++)
-    {
-      tmp_seq.clear();
-      cout << "mussa_class: loading museq frag... " << a_file_path << endl;
-      tmp_seq.load_museq(a_file_path, i);
-      the_seqs.push_back(tmp_seq);
-    }
-
-    empty_FLP_vector.clear();
-    for(i = 0; i < seq_num; i++)
-    {
-      all_comps.push_back(empty_FLP_vector); 
-      for(i2 = 0; i2 < seq_num; i2++)
-        all_comps[i].push_back(dummy_comp);
-    }
-
-    for(i = 0; i < seq_num; i++)
+  // this is a bit of a hack due to C++ not acting like it should with files
+  for (i = 1; i <= seq_num; i++)
+  {
+    tmp_seq.clear();
+    cout << "mussa_class: loading museq frag... " << a_file_path << endl;
+    tmp_seq.load_museq(a_file_path, i);
+    the_seqs.push_back(tmp_seq);
+  }
+  
+  empty_FLP_vector.clear();
+  for(i = 0; i < seq_num; i++)
+  {
+    all_comps.push_back(empty_FLP_vector); 
+    for(i2 = 0; i2 < seq_num; i2++)
+      all_comps[i].push_back(dummy_comp);
+  }
+  
+  for(i = 0; i < seq_num; i++)
+  {
+    for(i2 = i+1; i2 < seq_num; i2++)
     {
-      for(i2 = i+1; i2 < seq_num; i2++)
-      {
-        append_info.str("");
-        append_info <<  "_sp_" << i << "v" << i2;
-        cout << append_info.str() << endl;
-        a_file_path = file_path_base + append_info.str() + ".flp";
-        all_comps[i][i2].load(a_file_path);
-        cout << "real size = " << all_comps[i][i2].size() << endl;
-      }
+      append_info.str("");
+      append_info <<  "_sp_" << i << "v" << i2;
+      cout << append_info.str() << endl;
+      a_file_path = file_path_base + append_info.str() + ".flp";
+      all_comps[i][i2].load(a_file_path);
+      cout << "real size = " << all_comps[i][i2].size() << endl;
     }
-    return "";
   }
-  else
-    return err_msg;
 }
 
-/*
-      cout << "fee\n";
-      cout << "fie\n";
-      cout << "foe\n";
-      cout << "fum\n";
-*/
-
-
 
 void
 Mussa::save_old()
index 895018e6133ad9eabd328c40e127045dce515580..f0ed88426f2708cf60c05a5b6b6a0748c09b3ecd 100644 (file)
@@ -34,13 +34,14 @@ class Mussa
 
     void save();
     void save_muway(std::string save_path);
-    std::string load(std::string ana_file);
+    //! load a saved analysis directory
+    void load(std::string ana_path);
 
     //! clear parameters and initialize data lists
     void clear();
 
     // set parameters from a file - 'mupa' ~ mussa parameters
-    std::string load_mupa_file(std::string para_file_path);
+    void load_mupa_file(std::string para_file_path);
 
     // set parameters individually (eg from user input into gui classes)
     //! set analysis name
index f5a0e84b2dc9fb656d1fca74345042a2233bb85f..86dc577ab5316edf014948a9f85aaa815ad7b99c 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "alg/nway_paths.hh"
 #include "alg/conserved_path.h"
+#include "mussa_exceptions.hh"
 
 #include <fstream>
 #include <iostream>
@@ -125,7 +126,6 @@ NwayPaths::save(string save_file_path)
 {
   fstream save_file;
   list<ExtendedConservedPath >::iterator path_i, paths_end;
-  unsigned int i;
 
   save_file.open(save_file_path.c_str(), ios::out);
 
@@ -146,7 +146,7 @@ NwayPaths::save(string save_file_path)
     //cout << a_path.size() << endl;
     //first entry is the window length of the windows in the path
     save_file << a_path.window_size << ":";
-    for(i = 0; i != sequence_count(); ++i)
+    for(size_t i = 0; i != sequence_count(); ++i)
     {
       save_file << a_path[i];
       if (i != sequence_count())
@@ -161,7 +161,7 @@ NwayPaths::save(string save_file_path)
 }
 
 
-int
+size_t
 NwayPaths::sequence_count()
 {
   if (refined_pathz.begin() == refined_pathz.end() )
@@ -171,22 +171,19 @@ NwayPaths::sequence_count()
 }
 
 
-string
+void
 NwayPaths::load(string load_file_path)
 {
   fstream load_file;
   string file_data_line, header_data, data, path_node, path_width;
-  int i, space_split_i, equal_split_i, comma_split_i, colon_split_i;
+  int space_split_i, equal_split_i, comma_split_i, colon_split_i;
   vector<int> loaded_path;
-  string err_msg;
 
   load_file.open(load_file_path.c_str(), ios::in);
 
   if (!load_file)
   {
-    err_msg = "Sequence File: " + load_file_path + " not found"; 
-    cout << "BAM!!!!\n";
-    return err_msg;
+    throw mussa_load_error("Sequence File: " + load_file_path + " not found");
   }
   else
   {
@@ -238,7 +235,7 @@ NwayPaths::load(string load_file_path)
         // whats our window size?
         path_width = file_data_line.substr(0,colon_split_i); 
         file_data_line = file_data_line.substr(colon_split_i+1);
-        for(i = 0; i < species_num; i++)
+        for(size_t i = 0; i < species_num; i++)
         {
           comma_split_i = file_data_line.find(",");
           path_node = file_data_line.substr(0, comma_split_i); 
@@ -254,8 +251,6 @@ NwayPaths::load(string load_file_path)
       getline(load_file,file_data_line);
     }
     load_file.close();
-
-    return "";
   }
 }
 
index b75a3a4b932cfaf46d449fbcb9689cd5f61af337..38214057525780cfae648dbc7cdde4ddc0deb2ec 100644 (file)
@@ -52,11 +52,12 @@ class NwayPaths
 
     void simple_refine();
     void save(std::string save_file_path);
-    std::string load(std::string load_file_path);
+    //! load a muway file, \throws mussa_load_error
+    void load(std::string load_file_path);
     void add_path(int threshold, std::vector<int>& loaded_path);
     void add_path(ConservedPath loaded_path);
     //! how many sequences are in our comparison
-    int sequence_count();
+    size_t sequence_count();
 
     void find_paths(std::vector<std::vector<FLPs> > all_comparisons);
     void refine();
index b2b731bfd6e1321c9f9ee0646f5a8f4ba4d75c3a..2d44498775334dc5e4cd2e51c634697770a76471 100644 (file)
@@ -35,6 +35,9 @@ Mussa *initialize_mussa(int argc, char **argv)
   // running trumps viewing.
   if (vm.count("run-analysis")) {
     m->load_mupa_file( vm["run-analysis"].as< std::string >() );
+    std::cout << "I apologize for blocking the gui while running the analysis"
+              << std::endl;
+    m->analyze();
   }
   else if (vm.count("view-analysis")) {
     m->load( vm["view-analysis"].as< std::string >() );
index 5d150e3eb22d07144fd04fca4c4549924fa427dd..1b18d2adef3b7e1c9944fac3c5a3179983826bb6 100644 (file)
@@ -62,7 +62,7 @@ Sequence::load_fasta(string file_path, int seq_num,
 
   if (!data_file)
   {
-    throw sequence_load_error("Sequence File: " + file_path + " not found"); 
+    throw mussa_load_error("Sequence File: " + file_path + " not found"); 
   }
   // if file opened okay, read it
   else
@@ -161,7 +161,7 @@ Sequence::load_annot(string file_path, int start_index, int end_index)
 
   if (!data_file)
   {
-    throw sequence_load_error("Sequence File: " + file_path + " not found");
+    throw mussa_load_error("Sequence File: " + file_path + " not found");
   }
   // if file opened okay, read it
   else
index 5c6329617b02a7f45cfda172dafd35795c40a442..17c1b78840fc9ee4f9f1515ee579df2930f02057 100644 (file)
@@ -51,11 +51,11 @@ class Sequence
     //! assignment to constant sequences
     //Sequence &operator=(const Sequence&);
     //! load sequence AGCT from fasta file
-    //! throws sequence_load_error if something goes wrong
+    //! throws mussa_load_error if something goes wrong
     void load_fasta(const std::string file_path, int seq_num=1, 
                     int start_index=0, int end_index=0);
     //! load sequence annotations
-    //! throws sequence_load_error if something goes wrong
+    //! throws mussa_load_error if something goes wrong
     void load_annot(const std::string file_path, int start_index, int end_index);
     const std::list<annot> annotations() const;
     void set_seq(const std::string& a_seq);
index cc9a9a3256d4cc51517be2b218f026891bceb131..0ef0a41e0820a860342d131d62d35fc9a2fe39bc 100644 (file)
@@ -8,8 +8,8 @@ BOOST_AUTO_TEST_CASE( sequence_load_exception )
 {
   Sequence s;
   // there should be errors when we try to load something that doesn't exist
-  BOOST_CHECK_THROW( s.load_fasta("alkejralk", 1, 0, 0), sequence_load_error);
-  BOOST_CHECK_THROW( s.load_annot("alkejralk", 0, 0), sequence_load_error);
+  BOOST_CHECK_THROW( s.load_fasta("alkejralk", 1, 0, 0), mussa_load_error);
+  BOOST_CHECK_THROW( s.load_annot("alkejralk", 0, 0), mussa_load_error);
 }
 
 //! Do simple operations work correctly?
index 9f068fbe76583e6adb21ff12607522b20b0cb275..0f06beab80ff0fc13fab61ddf1a0211e3f72e0c3 100644 (file)
@@ -40,25 +40,22 @@ ConnWindow::real_load_ana_cb()
 
     // load the analysis
     an_analysis = new Mussa();
-    err_msg = an_analysis->load(a_file_path);
+    try {
+      an_analysis->load(a_file_path);
+    } catch (mussa_load_error e) {
+      fl_alert(e.what());
+      return;
+    }
     //.substr(0,a_file_path.find(".mu")));
 
-    if (err_msg == "")
-    {
-      // relabel window with the analysis name
-      window_name = "Mussa: " + an_analysis->get_name();
-      label((const char*)window_name.c_str());
-      // show the user the analysis
-      conn_box->setup(an_analysis->get_name(), an_analysis->size(), 
-                     an_analysis->get_window(), &(an_analysis->the_seqs), 
-                     &(an_analysis->the_paths));
-      conn_box->scale_paths();
-    }
-    else
-    {
-      fl_alert(err_msg.c_str());
-      cout << err_msg << endl;
-    }
+    // relabel window with the analysis name
+    window_name = "Mussa: " + an_analysis->get_name();
+    label((const char*)window_name.c_str());
+    // show the user the analysis
+    conn_box->setup(an_analysis->get_name(), an_analysis->size(), 
+                    an_analysis->get_window(), &(an_analysis->the_seqs), 
+                    &(an_analysis->the_paths));
+    conn_box->scale_paths();
   }
 }
 
@@ -84,7 +81,12 @@ ConnWindow::real_do_ana_cb()
     a_file_path = picked_file;
 
     an_analysis = new Mussa();
-    err_msg = an_analysis->load_mupa_file(a_file_path);
+    try {
+      an_analysis->load_mupa_file(a_file_path);
+    } catch (mussa_load_error e) {
+      fl_alert(e.what());
+      return;
+    }
 
     try {
       an_analysis->analyze(0, 0, Mussa::TransitiveNway, 0.0);
index 6a54d01c0a24e95425cc59161d07ef7b3127cb92..34ee3330ea92862535a8cbf9452bab52edb6e8e6 100644 (file)
--- a/mussa.cxx
+++ b/mussa.cxx
@@ -51,13 +51,13 @@ int main(int argc, char **argv)
   {
     if ((run_mode == 'f') || (run_mode == 'n'))
     {
-      err_msg = an_analysis.load_mupa_file(a_file_path);
+      an_analysis.load_mupa_file(a_file_path);
       an_analysis.analyze(window, threshold, ana_mode, ent_thres);
       //an_overlord.do_analysis();
     }
 
     if (run_mode == 'v')
-      err_msg = an_analysis.load(a_file_path);
+      an_analysis.load(a_file_path);
       //an_overlord.get_analysis();
 
     // no longer needed, but still semi-useful reality check...
index 2054f096f96852b5f2034e454f43563251a873e7..701c5e5d56f3bd96cc073bf4b9fc703d933d69d2 100644 (file)
@@ -9,11 +9,11 @@ public:
   explicit cmdline_error(const std::string& msg): std::runtime_error(msg) {};
 };
 
-//! Error loading sequence information
-class sequence_load_error : public std::runtime_error
+//! Error loading information
+class mussa_load_error : public std::runtime_error
 {
 public:
-  explicit sequence_load_error(const std::string& msg) : 
+  explicit mussa_load_error(const std::string& msg) : 
     std::runtime_error(msg) {};
 };
 
index 3b077e6670783144ba89eeb82af92045605d61a3..2974c9326a69d02ec3187588a8eaa1e4522a62d8 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <QDir>
 #include <QFileDialog>
+#include <QMessageBox>
 #include <QMouseEvent>
 #include <QRubberBand>
 #include <QRect>
@@ -33,8 +34,8 @@ PathScene::PathScene(Mussa* analysis, QWidget *parent) :
   else
   {
     mussaAnalysis = analysis;
-    updateAnalysis();
   }
+  updateScene();
 }
 
 QSize PathScene::sizeHint() const
@@ -106,18 +107,53 @@ void PathScene::loadMupa()
                                                    caption, 
                                                    QDir::currentPath(),
                                                    filter);
-  mussaAnalysis->load_mupa_file(mupa_path.toStdString());
-  updateAnalysis();
+  // user hit cancel?
+  if (mupa_path.isNull()) 
+    return;
+  // try to load safely
+  try {
+    Mussa *m = new Mussa;
+    m->load_mupa_file(mupa_path.toStdString());
+    m->analyze(0, 0, Mussa::TransitiveNway, 0.0);
+    // only switch mussas if we loaded without error
+    delete mussaAnalysis;
+    mussaAnalysis = m;
+    updateScene();
+  } catch (mussa_load_error e) {
+    QString msg("Unable to load ");
+    msg += mupa_path;
+    msg += "\n";
+    msg += e.what();
+    QMessageBox::warning(this, "Load Parameter", msg);
+  }
+  assert (mussaAnalysis != 0);
 }
 
 void PathScene::loadSavedAnalysis()
 {
   QString caption("Load a previously run analysis");
-  QString muway_path = QFileDialog::getExistingDirectory(this,
-                                                         caption, 
-                                                         QDir::currentPath());
-  mussaAnalysis->load(muway_path.toStdString());
-  updateAnalysis();
+  QString muway_dir = QFileDialog::getExistingDirectory(this,
+                                                        caption, 
+                                                        QDir::currentPath());
+  // user hit cancel?
+  if (muway_dir.isNull()) 
+    return;
+  // try to safely load
+  try {
+    Mussa *m = new Mussa;
+    m->load(muway_dir.toStdString());
+    // only switch mussas if we loaded without error
+    delete mussaAnalysis;
+    mussaAnalysis = m;
+    updateScene();
+  } catch (mussa_load_error e) {
+    QString msg("Unable to load ");
+    msg += muway_dir;
+    msg += "\n";
+    msg += e.what();
+    QMessageBox::warning(this, "Load Parameter", msg);
+  }
+  assert (mussaAnalysis != 0);
 }
 
 void PathScene::setSoftThreshold(int threshold)
@@ -176,39 +212,31 @@ void PathScene::paintGL()
   glFlush();
 }
 
-void PathScene::updateAnalysis()
+void PathScene::updateScene()
 {
   // Delete old glsequences
   // FIXME: does this actually free the memory from the new'ed GlSequences?
   tracks.clear();
 
-  // Run analysis
-  cout << "updateA:" << mussaAnalysis->size() //<< mussaAnalysis->paths().size()
-       << endl;
-  if (mussaAnalysis->size() >= 2) 
+  // save a reference to our GlSequences
+  GlSequence *gl_seq;
+  float y = mussaAnalysis->sequences().size() * 100 ;
+  float max_base_pairs = 0;
+  typedef vector<Sequence>::const_iterator seqs_itor_t;
+  for(seqs_itor_t seq_itor = mussaAnalysis->sequences().begin();
+      seq_itor != mussaAnalysis->sequences().end();
+      ++seq_itor)
   {
-    mussaAnalysis->analyze(0, 0, Mussa::TransitiveNway, 0.0);
-
-    // save a reference to our GlSequences
-    GlSequence *gl_seq;
-    float y = mussaAnalysis->sequences().size() * 100 ;
-    float max_base_pairs = 0;
-    typedef vector<Sequence>::const_iterator seqs_itor_t;
-    for(seqs_itor_t seq_itor = mussaAnalysis->sequences().begin();
-        seq_itor != mussaAnalysis->sequences().end();
-        ++seq_itor)
-    {
-      y = y - 100;
-      gl_seq = new GlSequence(*seq_itor);
-      gl_seq->setX(0);
-      gl_seq->setY(y);
-      if (gl_seq->width() > max_base_pairs ) max_base_pairs = gl_seq->width();
-      tracks.push_back( *gl_seq );
-    }
-    maxOrtho2d.setWidth(max_base_pairs + 100.0);
-    maxOrtho2d.setHeight((mussaAnalysis->sequences().size()) * 100 );
-    curOrtho2d = maxOrtho2d;
+    y = y - 100;
+    gl_seq = new GlSequence(*seq_itor);
+    gl_seq->setX(0);
+    gl_seq->setY(y);
+    if (gl_seq->width() > max_base_pairs ) max_base_pairs = gl_seq->width();
+    tracks.push_back( *gl_seq );
   }
+  maxOrtho2d.setWidth(max_base_pairs + 100.0);
+  maxOrtho2d.setHeight((mussaAnalysis->sequences().size()) * 100 );
+  curOrtho2d = maxOrtho2d;
 }
 
 static void processHits(GLint hits, GLuint buffer[])
index 7347cef178a30bd9cb18de00fdc12466011c5b37..3a0b657a87363bcf043ab7736072086f022d61fd 100644 (file)
@@ -36,8 +36,8 @@ public slots:
   void loadSavedAnalysis();
   //! set the soft threshold used by the Nway_Path algorithm
   void setSoftThreshold(int thres);
-  //! called when we've changed the analysis
-  void updateAnalysis();
+  //! indicate that we should update our scene
+  void updateScene();
 
 signals:
   //! emitted when our analysis has changed