// generated by Fast Light User Interface Designer (fluid) version 1.0300

#include "/home/ddong/COSM_Source_Base/build/est/gui/estGUI.h"
#include "FL/Fl_Native_File_Chooser.H"
#include "estAbout.h"
#include "wu/wuImage.h"
#include "estAlgo.h"
#include "xml/estXml.h"
#include "est/estimate.h"
#include "est/estimateIterative.h"
#include <blitz/timer.h>
#include <FL/Fl_Sys_Menu_Bar.H>
#include <FL/fl_ask.H>
#include <stdlib.h>
#include <iostream>
#include <fstream>

void EstGUI::cb_Quit_i(Fl_Menu_*, void*) {
  exit(0);
}
void EstGUI::cb_Quit(Fl_Menu_* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Quit_i(o,v);
}

void EstGUI::cb_About_i(Fl_Menu_*, void*) {
  if (!aboutDialog) {
    make_about();
}
aboutDialog->show();
}
void EstGUI::cb_About(Fl_Menu_* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_About_i(o,v);
}

Fl_Menu_Item EstGUI::menu_[] = {
 {"File", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Quit", 0,  (Fl_Callback*)EstGUI::cb_Quit, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Help", 0,  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"About...", 0,  (Fl_Callback*)EstGUI::cb_About, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {0,0,0,0,0,0,0,0,0}
};

void EstGUI::cb_Browse_i(Fl_Button*, void*) {
  Fl_Native_File_Chooser native;

native.title("Select Filename to Read");
native.type(Fl_Native_File_Chooser::BROWSE_FILE);
native.filter("*.wu");
native.show();
estImgInput->value(native.filename());
}
void EstGUI::cb_Browse(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Browse_i(o,v);
}

void EstGUI::cb_Browse1_i(Fl_Button*, void*) {
  Fl_Native_File_Chooser native;

native.title("Select Filename to Read");
native.type(Fl_Native_File_Chooser::BROWSE_FILE);
native.filter("*.wu");
native.show();
estPsfInput->value(native.filename());
}
void EstGUI::cb_Browse1(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Browse1_i(o,v);
}

void EstGUI::cb_Browse2_i(Fl_Button*, void*) {
  Fl_Native_File_Chooser native;

native.title("Select Filename to Write");
native.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
native.filter("*.wu");
native.show();
estEstInput->value(native.filename());
}
void EstGUI::cb_Browse2(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Browse2_i(o,v);
}

void EstGUI::cb_estLlsCheck_i(Fl_Round_Button*, void*) {
  if ( estLlsCheck->value() )
{
    estMapCheck->value(false);
    estEmCheck->value(false);
    estJvcCheck->value(false);
    estSiCheck->value(false);
    estSvCheck->value(false);
    estOsCheck->value(false);
    estDvCheck->value(false);
};
}
void EstGUI::cb_estLlsCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_estLlsCheck_i(o,v);
}

void EstGUI::cb_estMapCheck_i(Fl_Round_Button*, void*) {
  if ( estMapCheck->value() )
{
    estLlsCheck->value(false);
    estEmCheck->value(false);
    estJvcCheck->value(false);
    estSiCheck->value(false);
    estSvCheck->value(false);
    estOsCheck->value(false);
    estDvCheck->value(false);
};
}
void EstGUI::cb_estMapCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_estMapCheck_i(o,v);
}

void EstGUI::cb_Run_i(Fl_Button*, void*) {
  estProgress->value(0);
processing();
}
void EstGUI::cb_Run(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->user_data()))->cb_Run_i(o,v);
}

void EstGUI::cb_Run1_i(Fl_Button*, void*) {
  estProgress->value(0);
if ( tableDialog == 0 )
{
    make_table_dialog();
}
estTable->clear();
Fl::wait(0.0);
gStop = false;
estXAxis->maximum(estIterationsInput->value());
processing();
}
void EstGUI::cb_Run1(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->user_data()))->cb_Run1_i(o,v);
}

void EstGUI::cb_Stop_i(Fl_Button*, void*) {
  gStop = true;
}
void EstGUI::cb_Stop(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->user_data()))->cb_Stop_i(o,v);
}

void EstGUI::cb_estEmCheck_i(Fl_Round_Button*, void*) {
  if ( estEmCheck->value() )
{
    estLlsCheck->value(false);
    estMapCheck->value(false);
    estJvcCheck->value(false);
    estSiCheck->value(false);
    estSvCheck->value(false);
    estOsCheck->value(false);
    estDvCheck->value(false);
    
    estInvariantDoubleInput->activate();
};
}
void EstGUI::cb_estEmCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estEmCheck_i(o,v);
}

void EstGUI::cb_estJvcCheck_i(Fl_Round_Button*, void*) {
  if ( estJvcCheck->value() )
{
    estLlsCheck->value(false);
    estMapCheck->value(false);
    estEmCheck->value(false);
    estSiCheck->value(false);
    estSvCheck->value(false);
    estOsCheck->value(false);
    estDvCheck->value(false);
    
    estInvariantDoubleInput->activate();
};
}
void EstGUI::cb_estJvcCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estJvcCheck_i(o,v);
}

void EstGUI::cb_estSiCheck_i(Fl_Round_Button*, void*) {
  if ( estSiCheck->value() )
{
    estLlsCheck->value(false);
    estMapCheck->value(false);
    estEmCheck->value(false);
    estJvcCheck->value(false);
    estSvCheck->value(false);
    estOsCheck->value(false);
    estDvCheck->value(false);
    
    estInvariantDoubleInput->value(0);
    estInvariantDoubleInput->deactivate();
};
}
void EstGUI::cb_estSiCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estSiCheck_i(o,v);
}

Fl_Menu_Item EstGUI::menu_estInvariantPenaltyInput[] = {
 {"None", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Intensity", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Roughness", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

void EstGUI::cb_estSvCheck_i(Fl_Round_Button*, void*) {
  if ( estSvCheck->value() )
{
    estLlsCheck->value(false);
    estMapCheck->value(false);
    estEmCheck->value(false);
    estJvcCheck->value(false);
    estSiCheck->value(false);
    estOsCheck->value(false);
    estDvCheck->value(false);
    estVariantModelInput->value(0);
    estVariantModelInput->activate();
    
    estVariantStrataStartInput->activate();
    estVariantStrataSizeInput->activate();
    estVariantStrataNumberInput->activate();
    estVariantPCAComponentsInput->deactivate();
    estVariantPCAStartInput->deactivate();
    estVariantPCANumberInput->deactivate();
    estVariantDoubleInput->activate();
    estVariantBigInput->activate();
    estOtfInput->activate();
};
}
void EstGUI::cb_estSvCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estSvCheck_i(o,v);
}

void EstGUI::cb_estOsCheck_i(Fl_Round_Button*, void*) {
  if ( estOsCheck->value() )
{
    estLlsCheck->value(false);
    estMapCheck->value(false);
    estEmCheck->value(false);
    estJvcCheck->value(false);
    estSiCheck->value(false);
    estSvCheck->value(false);
    estDvCheck->value(false);
    estVariantModelInput->value(0);
    estVariantModelInput->deactivate();
    
    estVariantStrataStartInput->activate();
    estVariantStrataSizeInput->activate();
    estVariantStrataNumberInput->activate();
    estVariantPCAComponentsInput->deactivate();
    estVariantPCAStartInput->deactivate();
    estVariantPCANumberInput->deactivate();
    estVariantDoubleInput->activate();
    estVariantBigInput->activate();
    estOtfInput->activate();
};
}
void EstGUI::cb_estOsCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estOsCheck_i(o,v);
}

void EstGUI::cb_estDvCheck_i(Fl_Round_Button*, void*) {
  if ( estDvCheck->value() )
{
    estLlsCheck->value(false);
    estMapCheck->value(false);
    estEmCheck->value(false);
    estJvcCheck->value(false);
    estSiCheck->value(false);
    estSvCheck->value(false);
    estOsCheck->value(false);
    estVariantModelInput->value(0);
    estVariantModelInput->deactivate();
    
    estVariantStrataStartInput->deactivate();
    estVariantStrataSizeInput->deactivate();
    estVariantPCAComponentsInput->deactivate();
    estVariantPCAStartInput->deactivate();
    estVariantPCANumberInput->deactivate();
    estVariantDoubleInput->deactivate();
    estVariantBigInput->deactivate();
    estOtfInput->deactivate();
                      
};
}
void EstGUI::cb_estDvCheck(Fl_Round_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estDvCheck_i(o,v);
}

void EstGUI::cb_OTF_i(Fl_Menu_*, void*) {
  estOtfInput->deactivate();
}
void EstGUI::cb_OTF(Fl_Menu_* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_OTF_i(o,v);
}

void EstGUI::cb_OTF1_i(Fl_Menu_*, void*) {
  estOtfInput->activate();
}
void EstGUI::cb_OTF1(Fl_Menu_* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_OTF1_i(o,v);
}

Fl_Menu_Item EstGUI::menu_estVariantBigInput[] = {
 {"OTF in Memory", 0,  (Fl_Callback*)EstGUI::cb_OTF, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"OTF on Disk", 0,  (Fl_Callback*)EstGUI::cb_OTF1, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

void EstGUI::cb_Strata_i(Fl_Menu_*, void*) {
  estVariantStrataStartInput->activate();
                      estVariantStrataSizeInput->activate();
                      estVariantStrataNumberInput->activate();
                      estVariantPCAComponentsInput->deactivate();
                      estVariantPCAStartInput->deactivate();
                      estVariantPCANumberInput->deactivate();
                      estVariantDoubleInput->activate();
                      estVariantBigInput->activate();
                      estOtfInput->activate();
}
void EstGUI::cb_Strata(Fl_Menu_* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Strata_i(o,v);
}

void EstGUI::cb_PCA_i(Fl_Menu_*, void*) {
  estVariantStrataStartInput->deactivate();
                      estVariantStrataSizeInput->deactivate();
                      estVariantStrataNumberInput->deactivate();
                      estVariantPCAComponentsInput->activate();
                      estVariantPCAStartInput->activate();
                      estVariantPCANumberInput->activate();
                      estVariantDoubleInput->value(0);
                      estVariantDoubleInput->deactivate();
                      estVariantBigInput->value(0);
                      estVariantBigInput->deactivate();
                      estOtfInput->deactivate();
}
void EstGUI::cb_PCA(Fl_Menu_* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_PCA_i(o,v);
}

Fl_Menu_Item EstGUI::menu_estVariantModelInput[] = {
 {"Strata mode", 0,  (Fl_Callback*)EstGUI::cb_Strata, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"PCA mode", 0,  (Fl_Callback*)EstGUI::cb_PCA, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

Fl_Menu_Item EstGUI::menu_estVariantPenaltyInput[] = {
 {"None", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Intensity", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Roughness", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

void EstGUI::cb_Browse3_i(Fl_Button*, void*) {
  Fl_Native_File_Chooser native;

native.title("Select Filename to Write");
native.type(Fl_Native_File_Chooser::BROWSE_FILE);
native.filter("*.wu");
native.show();
estPhaInput->value(native.filename());
}
void EstGUI::cb_Browse3(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Browse3_i(o,v);
}

void EstGUI::cb_Clear_i(Fl_Button*, void*) {
  estCanvas->clear();
}
void EstGUI::cb_Clear(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Clear_i(o,v);
}

void EstGUI::cb_estConvergenceMinimumChoice_i(Fl_Input_Choice* o, void*) {
  double value = 1;
sscanf(o->value(), "%lf", &value);
estYAxis->minimum(value);
}
void EstGUI::cb_estConvergenceMinimumChoice(Fl_Input_Choice* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estConvergenceMinimumChoice_i(o,v);
}

Fl_Menu_Item EstGUI::menu_estConvergenceMinimumChoice[] = {
 {"1", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.1", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.01", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.0001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.00001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.000001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.0000001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.00000001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.000000001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

void EstGUI::cb_estConvergenceMaximumChoice_i(Fl_Input_Choice* o, void*) {
  double value = 1;
sscanf(o->value(), "%lf", &value);
estYAxis->maximum(value);
}
void EstGUI::cb_estConvergenceMaximumChoice(Fl_Input_Choice* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_estConvergenceMaximumChoice_i(o,v);
}

Fl_Menu_Item EstGUI::menu_estConvergenceMaximumChoice[] = {
 {"10000", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"1000", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"100", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"10", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"1", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.1", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.01", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"0.0001", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

Fl_Menu_Item EstGUI::menu_estConvergenceMeasureMenu[] = {
 {"Maximum", 0,  0, 0, 2, FL_NORMAL_LABEL, 0, 14, 0},
 {"Mean", 0,  0, 0, 2, FL_NORMAL_LABEL, 0, 14, 0},
 {"Mean Square", 0,  0, 0, 2, FL_NORMAL_LABEL, 0, 14, 0},
 {"Log Likelihood", 0,  0, 0, 2, FL_NORMAL_LABEL, 0, 14, 0},
 {"I-Divergence", 0,  0, 0, 2, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

void EstGUI::cb_Table_i(Fl_Button*, void*) {
  if (!tableDialog) {
    make_table_dialog();
}
tableDialog->show();
}
void EstGUI::cb_Table(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_Table_i(o,v);
}

void EstGUI::cb_Browse4_i(Fl_Button*, void*) {
  Fl_Native_File_Chooser native;

native.title("Select Filename to Read");
native.type(Fl_Native_File_Chooser::BROWSE_FILE);
native.filter("*.xml");
native.show();
estXmlInput->value(native.filename());
}
void EstGUI::cb_Browse4(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Browse4_i(o,v);
}

void EstGUI::cb_Open_i(Fl_Button*, void*) {
  readXml(estXmlInput->value());
}
void EstGUI::cb_Open(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Open_i(o,v);
}

void EstGUI::cb_Close_i(Fl_Return_Button*, void*) {
  tableDialog->hide();
}
void EstGUI::cb_Close(Fl_Return_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Close_i(o,v);
}

void EstGUI::cb_Save_i(Fl_Button*, void*) {
  Fl_Native_File_Chooser native;

native.title("Select Filename to Write");
native.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
native.filter("*.csv");
native.show();
if ( native.filename() )
{
    make_save_csv(native.filename());
};
}
void EstGUI::cb_Save(Fl_Button* o, void* v) {
  ((EstGUI*)(o->parent()->user_data()))->cb_Save_i(o,v);
}

EstGUI::EstGUI() {
  { estWindow = new Fl_Double_Window(716, 744, "COSM Estimation");
    estWindow->labelsize(12);
    estWindow->user_data((void*)(this));
    { Fl_Sys_Menu_Bar* o = new Fl_Sys_Menu_Bar(0, 0, 725, 25);
      o->box(FL_UP_BOX);
      o->color(FL_BACKGROUND_COLOR);
      o->selection_color(FL_SELECTION_COLOR);
      o->labeltype(FL_NORMAL_LABEL);
      o->labelfont(0);
      o->labelsize(14);
      o->labelcolor(FL_FOREGROUND_COLOR);
      o->align(Fl_Align(FL_ALIGN_CENTER));
      o->when(FL_WHEN_RELEASE_ALWAYS);
      Fl_Group::current()->resizable(o);
      o->menu(menu_);
    } // Fl_Sys_Menu_Bar* o
    { estImgInput = new Fl_File_Input(175, 125, 390, 30, "Data Input File:");
      estImgInput->tooltip("Path and filename for input data image");
    } // Fl_File_Input* estImgInput
    { Fl_Button* o = new Fl_Button(595, 130, 90, 25, "Browse...");
      o->callback((Fl_Callback*)cb_Browse);
    } // Fl_Button* o
    { estPsfInput = new Fl_File_Input(180, 160, 385, 30, "PSF Input File:");
      estPsfInput->tooltip("Path and filename for PSF image");
    } // Fl_File_Input* estPsfInput
    { Fl_Button* o = new Fl_Button(595, 165, 90, 25, "Browse...");
      o->callback((Fl_Callback*)cb_Browse1);
    } // Fl_Button* o
    { estEstInput = new Fl_File_Input(180, 215, 385, 30, "Estimation Output File:");
      estEstInput->tooltip("Path and filename for estimation output image");
    } // Fl_File_Input* estEstInput
    { Fl_Button* o = new Fl_Button(595, 220, 90, 25, "Browse...");
      o->callback((Fl_Callback*)cb_Browse2);
    } // Fl_Button* o
    { estProgress = new Fl_Progress(35, 695, 650, 25, "Progress");
      estProgress->tooltip("Algorithm progress");
      estProgress->selection_color((Fl_Color)230);
    } // Fl_Progress* estProgress
    { Fl_Tabs* o = new Fl_Tabs(35, 260, 650, 420);
      o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
      { estLinearGroup = new Fl_Group(35, 285, 650, 395, "Linear");
        estLinearGroup->hide();
        { Fl_Group* o = new Fl_Group(90, 345, 505, 130, "Algorithm:");
          o->box(FL_ENGRAVED_BOX);
          o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
          { estLlsCheck = new Fl_Round_Button(115, 380, 205, 25, "Linear Least Squares (LLS)");
            estLlsCheck->tooltip("Select LLS algorithm");
            estLlsCheck->down_box(FL_ROUND_DOWN_BOX);
            estLlsCheck->callback((Fl_Callback*)cb_estLlsCheck);
          } // Fl_Round_Button* estLlsCheck
          { estMapCheck = new Fl_Round_Button(115, 420, 205, 25, "Linear Maximum a Posteriori (MAP)");
            estMapCheck->tooltip("Select MAP algorithm");
            estMapCheck->down_box(FL_ROUND_DOWN_BOX);
            estMapCheck->callback((Fl_Callback*)cb_estMapCheck);
          } // Fl_Round_Button* estMapCheck
          o->end();
        } // Fl_Group* o
        { estLinearParameterInput = new Fl_Value_Input(170, 485, 80, 20, "Parameter: ");
          estLinearParameterInput->tooltip("Linear algorithm parameter used for regularization");
        } // Fl_Value_Input* estLinearParameterInput
        { Fl_Button* o = new Fl_Button(85, 600, 95, 25, "Run");
          o->tooltip("Run  selected estimation algorithm");
          o->callback((Fl_Callback*)cb_Run);
        } // Fl_Button* o
        estLinearGroup->end();
      } // Fl_Group* estLinearGroup
      { estIterativeGroup = new Fl_Group(35, 285, 650, 380, "Iterative");
        { Fl_Button* o = new Fl_Button(85, 640, 95, 25, "Run");
          o->tooltip("Run selected estimation algorithm");
          o->callback((Fl_Callback*)cb_Run1);
        } // Fl_Button* o
        { Fl_Button* o = new Fl_Button(185, 640, 95, 25, "Stop");
          o->tooltip("Stop estimation algorithm at next update interval");
          o->callback((Fl_Callback*)cb_Stop);
        } // Fl_Button* o
        { estIterationsInput = new Fl_Value_Input(505, 605, 120, 20, "Iterations:");
          estIterationsInput->tooltip("Number of iterations to perform");
          estIterationsInput->value(100);
        } // Fl_Value_Input* estIterationsInput
        { estUpdateInput = new Fl_Value_Input(505, 625, 120, 20, "Update:");
          estUpdateInput->tooltip("Number of iterations between measurment updates");
          estUpdateInput->value(10);
        } // Fl_Value_Input* estUpdateInput
        { estWriteInput = new Fl_Value_Input(505, 645, 120, 20, "Write:");
          estWriteInput->tooltip("Minumum value in the estimation image at every iteration");
          estWriteInput->value(100);
        } // Fl_Value_Input* estWriteInput
        { Fl_Tabs* o = new Fl_Tabs(60, 300, 565, 290);
          { estInvariantGroup = new Fl_Group(60, 320, 565, 225, "Invariant");
            estInvariantGroup->hide();
            { Fl_Group* o = new Fl_Group(90, 345, 505, 130, "Algorithm:");
              o->box(FL_ENGRAVED_BOX);
              o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
              { estEmCheck = new Fl_Round_Button(115, 380, 225, 25, "Expectation Maximization (EM)");
                estEmCheck->tooltip("Select EM algorithm");
                estEmCheck->down_box(FL_ROUND_DOWN_BOX);
                estEmCheck->callback((Fl_Callback*)cb_estEmCheck);
              } // Fl_Round_Button* estEmCheck
              { estJvcCheck = new Fl_Round_Button(115, 420, 205, 25, "Jansson-van Cittert (JVC)");
                estJvcCheck->tooltip("Select JVC algorithm");
                estJvcCheck->down_box(FL_ROUND_DOWN_BOX);
                estJvcCheck->callback((Fl_Callback*)cb_estJvcCheck);
              } // Fl_Round_Button* estJvcCheck
              { estSiCheck = new Fl_Round_Button(365, 380, 225, 25, "SI Conjugate Gradient (SICG)");
                estSiCheck->tooltip("Select Space Invariant Conjugate Gradient algorithm");
                estSiCheck->down_box(FL_ROUND_DOWN_BOX);
                estSiCheck->callback((Fl_Callback*)cb_estSiCheck);
              } // Fl_Round_Button* estSiCheck
              o->end();
            } // Fl_Group* o
            { estInvariantParameterInput = new Fl_Value_Input(170, 485, 80, 20, "Penalty:      ");
              estInvariantParameterInput->tooltip("Intensity penalty for EM algorithm");
            } // Fl_Value_Input* estInvariantParameterInput
            { estInvariantDoubleInput = new Fl_Check_Button(390, 485, 90, 20, "Double Z");
              estInvariantDoubleInput->tooltip("Use double  pixel size in z dimension in EM algorithm");
              estInvariantDoubleInput->down_box(FL_DOWN_BOX);
            } // Fl_Check_Button* estInvariantDoubleInput
            { estInvariantPenaltyInput = new Fl_Choice(280, 485, 100, 20);
              estInvariantPenaltyInput->down_box(FL_BORDER_BOX);
              estInvariantPenaltyInput->menu(menu_estInvariantPenaltyInput);
            } // Fl_Choice* estInvariantPenaltyInput
            estInvariantGroup->end();
          } // Fl_Group* estInvariantGroup
          { estVariantGroup = new Fl_Group(60, 325, 565, 265, "Variant");
            estVariantGroup->hide();
            { Fl_Group* o = new Fl_Group(90, 345, 505, 130, "Algorithm:");
              o->box(FL_ENGRAVED_BOX);
              o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
              { estSvCheck = new Fl_Round_Button(115, 380, 205, 25, "Space-Variant EM (EMSV)");
                estSvCheck->tooltip("Select Space-Variant EM algorithm");
                estSvCheck->down_box(FL_ROUND_DOWN_BOX);
                estSvCheck->callback((Fl_Callback*)cb_estSvCheck);
              } // Fl_Round_Button* estSvCheck
              { estOsCheck = new Fl_Round_Button(115, 420, 205, 25, "Ordered Subsets EM (EMOS)");
                estOsCheck->tooltip("Select Ordered Subset EM algorithm");
                estOsCheck->down_box(FL_ROUND_DOWN_BOX);
                estOsCheck->callback((Fl_Callback*)cb_estOsCheck);
              } // Fl_Round_Button* estOsCheck
              { estDvCheck = new Fl_Round_Button(365, 380, 225, 25, "DV Conjugate Gradient (DVCG)");
                estDvCheck->tooltip("Select Depth Variant Conjugate Gradient algorithm");
                estDvCheck->down_box(FL_ROUND_DOWN_BOX);
                estDvCheck->callback((Fl_Callback*)cb_estDvCheck);
              } // Fl_Round_Button* estDvCheck
              o->end();
            } // Fl_Group* o
            { estVariantParameterInput = new Fl_Value_Input(170, 485, 80, 20, "Penalty:      ");
              estVariantParameterInput->tooltip("Intensity penalty value");
            } // Fl_Value_Input* estVariantParameterInput
            { estVariantDoubleInput = new Fl_Check_Button(390, 485, 85, 20, "Double Z");
              estVariantDoubleInput->tooltip("Use double z dimension in algorithms");
              estVariantDoubleInput->down_box(FL_DOWN_BOX);
            } // Fl_Check_Button* estVariantDoubleInput
            { estVariantBigInput = new Fl_Choice(470, 485, 125, 20);
              estVariantBigInput->tooltip("Keep PSF in memory or read from disk each iteration.");
              estVariantBigInput->down_box(FL_BORDER_BOX);
              estVariantBigInput->menu(menu_estVariantBigInput);
            } // Fl_Choice* estVariantBigInput
            { estVariantStrataStartInput = new Fl_Value_Input(240, 515, 45, 20, "Start: ");
              estVariantStrataStartInput->tooltip("Start of strata in pixel");
              estVariantStrataStartInput->minimum(1);
              estVariantStrataStartInput->maximum(128);
              estVariantStrataStartInput->value(1);
            } // Fl_Value_Input* estVariantStrataStartInput
            { estOtfInput = new Fl_File_Input(470, 510, 125, 35, "OTF Name:");
              estOtfInput->tooltip("Optical transfer function image file name");
            } // Fl_File_Input* estOtfInput
            { estVariantStrataSizeInput = new Fl_Value_Input(335, 515, 45, 20, "Size: ");
              estVariantStrataSizeInput->tooltip("Size of strata in pixel");
              estVariantStrataSizeInput->minimum(1);
              estVariantStrataSizeInput->maximum(128);
              estVariantStrataSizeInput->value(1);
            } // Fl_Value_Input* estVariantStrataSizeInput
            { estVariantStrataNumberInput = new Fl_Value_Input(140, 515, 45, 20, "Strata: ");
              estVariantStrataNumberInput->tooltip("Number of strata");
              estVariantStrataNumberInput->minimum(1);
              estVariantStrataNumberInput->maximum(128);
              estVariantStrataNumberInput->value(1);
            } // Fl_Value_Input* estVariantStrataNumberInput
            { estVariantPCAComponentsInput = new Fl_Value_Input(165, 545, 45, 20, "Components: ");
              estVariantPCAComponentsInput->tooltip("Number of components");
              estVariantPCAComponentsInput->minimum(1);
              estVariantPCAComponentsInput->maximum(128);
              estVariantPCAComponentsInput->value(1);
              estVariantPCAComponentsInput->deactivate();
            } // Fl_Value_Input* estVariantPCAComponentsInput
            { estVariantPCAStartInput = new Fl_Value_Input(265, 545, 45, 20, "Start: ");
              estVariantPCAStartInput->tooltip("Start PCA in pixel");
              estVariantPCAStartInput->minimum(1);
              estVariantPCAStartInput->maximum(128);
              estVariantPCAStartInput->value(1);
              estVariantPCAStartInput->deactivate();
            } // Fl_Value_Input* estVariantPCAStartInput
            { estVariantPCANumberInput = new Fl_Value_Input(380, 545, 45, 20, "Number: ");
              estVariantPCANumberInput->tooltip("Number of PCA PSFs in pixel");
              estVariantPCANumberInput->minimum(1);
              estVariantPCANumberInput->maximum(128);
              estVariantPCANumberInput->value(1);
              estVariantPCANumberInput->deactivate();
            } // Fl_Value_Input* estVariantPCANumberInput
            { estVariantModelInput = new Fl_Choice(470, 555, 125, 20);
              estVariantModelInput->tooltip("Model of variant algorithm.");
              estVariantModelInput->down_box(FL_BORDER_BOX);
              estVariantModelInput->menu(menu_estVariantModelInput);
            } // Fl_Choice* estVariantModelInput
            { estVariantPenaltyInput = new Fl_Choice(280, 485, 100, 20);
              estVariantPenaltyInput->down_box(FL_BORDER_BOX);
              estVariantPenaltyInput->menu(menu_estVariantPenaltyInput);
            } // Fl_Choice* estVariantPenaltyInput
            estVariantGroup->end();
          } // Fl_Group* estVariantGroup
          { Fl_Group* o = new Fl_Group(65, 324, 560, 265, "Convergence");
            { estPhaInput = new Fl_File_Input(175, 335, 330, 30, "Reference File:");
              estPhaInput->tooltip("Reference image file name  to compare with ( if blank, previous estimate will\
 be used)");
            } // Fl_File_Input* estPhaInput
            { Fl_Button* o = new Fl_Button(515, 340, 95, 25, "Browse...");
              o->callback((Fl_Callback*)cb_Browse3);
            } // Fl_Button* o
            { estCanvas = new Ca_Canvas(130, 382, 255, 154);
              estCanvas->box(FL_ENGRAVED_BOX);
              estCanvas->color(FL_BACKGROUND2_COLOR);
              estCanvas->selection_color(FL_BACKGROUND_COLOR);
              estCanvas->labeltype(FL_NORMAL_LABEL);
              estCanvas->labelfont(0);
              estCanvas->labelsize(14);
              estCanvas->labelcolor(FL_FOREGROUND_COLOR);
              estCanvas->align(Fl_Align(FL_ALIGN_CENTER));
              estCanvas->when(FL_WHEN_RELEASE);
              estCanvas->current();
            } // Ca_Canvas* estCanvas
            { estXAxis = new Ca_X_Axis(120, 536, 275, 34, "Iterations");
              estXAxis->box(FL_NO_BOX);
              estXAxis->color(FL_BACKGROUND_COLOR);
              estXAxis->selection_color(FL_BACKGROUND_COLOR);
              estXAxis->labeltype(FL_NORMAL_LABEL);
              estXAxis->labelfont(0);
              estXAxis->labelsize(10);
              estXAxis->labelcolor(FL_FOREGROUND_COLOR);
              estXAxis->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT));
              estXAxis->when(FL_WHEN_RELEASE);
              estXAxis->grid_visible(CA_MINOR_TICK|CA_MAJOR_TICK|CA_LABEL_GRID|CA_ALWAYS_VISIBLE);
              estXAxis->minor_grid_color(FL_RED); estXAxis->major_grid_color(FL_RED); estXAxis->label_grid_color(FL_RED); estXAxis->label_size(10);
              estXAxis->minimum(0); estXAxis->maximum(100);
              estXAxis->current();
            } // Ca_X_Axis* estXAxis
            { estYAxis = new Ca_Y_Axis(70, 382, 60, 162, "Error");
              estYAxis->box(FL_NO_BOX);
              estYAxis->color(FL_BACKGROUND_COLOR);
              estYAxis->selection_color(FL_BACKGROUND_COLOR);
              estYAxis->labeltype(FL_NORMAL_LABEL);
              estYAxis->labelfont(0);
              estYAxis->labelsize(11);
              estYAxis->labelcolor(FL_FOREGROUND_COLOR);
              estYAxis->align(Fl_Align(FL_ALIGN_TOP));
              estYAxis->when(FL_WHEN_RELEASE);
              estYAxis->grid_visible(CA_MINOR_TICK|CA_MAJOR_TICK|CA_LABEL_GRID|CA_ALWAYS_VISIBLE);
              estYAxis->minor_grid_color(FL_RED); estYAxis->major_grid_color(FL_RED); estYAxis->label_grid_color(FL_RED);estYAxis->label_size(10); estYAxis->label_format("%3.1e");
              estYAxis->minimum(1e-9); estYAxis->maximum(1);
              estYAxis->scale(CA_LOG); estYAxis->current();
            } // Ca_Y_Axis* estYAxis
            { Fl_Button* o = new Fl_Button(515, 460, 95, 25, "Clear");
              o->tooltip("Clear plots in measurement graph area");
              o->callback((Fl_Callback*)cb_Clear);
            } // Fl_Button* o
            { Fl_Input_Choice* o = estConvergenceMinimumChoice = new Fl_Input_Choice(515, 549, 95, 22, "minimum: ");
              estConvergenceMinimumChoice->labelsize(12);
              estConvergenceMinimumChoice->textsize(12);
              estConvergenceMinimumChoice->callback((Fl_Callback*)cb_estConvergenceMinimumChoice);
              estConvergenceMinimumChoice->menu(menu_estConvergenceMinimumChoice);
              o->value("0.000000001");
            } // Fl_Input_Choice* estConvergenceMinimumChoice
            { Fl_Input_Choice* o = estConvergenceMaximumChoice = new Fl_Input_Choice(515, 518, 95, 22, "maximum:");
              estConvergenceMaximumChoice->labelsize(12);
              estConvergenceMaximumChoice->textsize(12);
              estConvergenceMaximumChoice->callback((Fl_Callback*)cb_estConvergenceMaximumChoice);
              estConvergenceMaximumChoice->menu(menu_estConvergenceMaximumChoice);
              o->value("1");
            } // Fl_Input_Choice* estConvergenceMaximumChoice
            { estConvergenceMeasureMenu = new Fl_Menu_Button(515, 390, 95, 25, "Measure");
              { Fl_Menu_Item* o = &menu_estConvergenceMeasureMenu[0];
                o->set();
              }
              { Fl_Menu_Item* o = &menu_estConvergenceMeasureMenu[1];
                o->set();
              }
              { Fl_Menu_Item* o = &menu_estConvergenceMeasureMenu[2];
                o->set();
              }
              { Fl_Menu_Item* o = &menu_estConvergenceMeasureMenu[3];
                o->set();
              }
              { Fl_Menu_Item* o = &menu_estConvergenceMeasureMenu[4];
                o->set();
              }
              estConvergenceMeasureMenu->menu(menu_estConvergenceMeasureMenu);
            } // Fl_Menu_Button* estConvergenceMeasureMenu
            { Fl_Button* o = new Fl_Button(515, 425, 95, 25, "Table...");
              o->callback((Fl_Callback*)cb_Table);
            } // Fl_Button* o
            o->end();
          } // Fl_Group* o
          o->end();
        } // Fl_Tabs* o
        estIterativeGroup->end();
      } // Fl_Group* estIterativeGroup
      o->end();
    } // Fl_Tabs* o
    { estXmlInput = new Fl_File_Input(175, 50, 390, 30, "XML File:");
      estXmlInput->tooltip("Path and filename for input data image");
    } // Fl_File_Input* estXmlInput
    { Fl_Button* o = new Fl_Button(595, 50, 90, 25, "Browse...");
      o->callback((Fl_Callback*)cb_Browse4);
    } // Fl_Button* o
    { Fl_Button* o = new Fl_Button(595, 80, 90, 25, "Open");
      o->callback((Fl_Callback*)cb_Open);
    } // Fl_Button* o
    { Fl_Check_Button* o = estCenteredPsfCheck = new Fl_Check_Button(550, 190, 20, 15, " Centered PSF");
      estCenteredPsfCheck->down_box(FL_DOWN_BOX);
      estCenteredPsfCheck->labelsize(12);
      estCenteredPsfCheck->align(Fl_Align(FL_ALIGN_LEFT));
      o->value(true);
    } // Fl_Check_Button* estCenteredPsfCheck
    estWindow->end();
  } // Fl_Double_Window* estWindow
  tableDialog = 0;
}

void EstGUI::show(int argc, char* argv[]) {
  this->estWindow->show(argc, argv);
}

void EstGUI::processing() {
  const int N = 3;
  
      std::string estname = estEstInput->value();
      std::string psfname = estPsfInput->value();
      std::string otfname = estOtfInput->value();
      std::string imgname = estImgInput->value();
      std::string phaname = estPhaInput->value();
      
      if ( estname.empty() )
      {
          fl_alert("Unknown Output Estimation Filename");
          return;
      }
      if ( psfname.empty() ) 
      {
          fl_alert("Unknown Input PSF Filename");
          return;
      }
      if ( imgname.empty() )
      {
          fl_alert("Unknown Input Image Filename");
          return;
      }
      
      std::string psfprefix;
      std::string psfsuffix;
      std::string otfprefix;
      std::string otfsuffix;
      std::string estprefix;
      std::string estsuffix;
      
   
      size_t i = estname.rfind('.', estname.length( ));
      if (i != std::string::npos) {
          estprefix = estname.substr(0,i);
          estsuffix = estname.substr(i+1, estname.length());
      }
      std::cout << "Estimage Prefix: "<<estprefix<<", Estimage Suffix: "<<estsuffix<<", iter: "<<estWriteInput->value()<<std::endl;
   
      i = psfname.rfind('.', psfname.length( ));
      if (i != std::string::npos) {
          psfprefix = psfname.substr(0,i);
          psfsuffix = psfname.substr(i+1, psfname.length());
      }
      std::cout << "PSF Prefix: "<<psfprefix<<", PSF Suffix: "<<psfsuffix<<std::endl;
      
      if ( !otfname.empty() ) {
          i = otfname.rfind('.', otfname.length( ));
          if (i != std::string::npos) {
              otfprefix = otfname.substr(0,i);
              otfsuffix = otfname.substr(i+1, otfname.length());
          }
          std::cout << "OTF Prefix: "<<otfprefix<<", OTF Suffix: "<<otfsuffix<<std::endl;
      }
      std::string xmlname = estprefix + ".xml";
      std::cout << "Xml file: "<<xmlname<< std::endl;
      writeXml(xmlname);
                                                                                  
      // read in img file
      cosm::WUImage imgData;
      if (imgData.ReadData(imgname) == false) return;
                                                                                  
      // read phantom file
      bool usePhantom = false;
      cosm::WUImage phantomData;
      if ( phaname != "" )
      {
          if (phantomData.ReadData(phaname) == false) return;
          usePhantom = true;
      }
                                                                                  
      // read in psf file
      cosm::WUImage psfData;
      if ( estLlsCheck->value() || estMapCheck->value() || 
            estEmCheck->value() || estJvcCheck->value() || 
            estSiCheck->value() )
      { 
          if (psfData.ReadData(psfname) == false) return;
      }
      bool centeredPsf = estCenteredPsfCheck->value();
                                                                                  
      // command line parameters
      int iterations = (int)estIterationsInput->value();
      int update = (int)estUpdateInput->value();
      int writeUpdate = estWriteInput->value();
      double error = 1e-4;
      
      unsigned short err = 0;
      Fl_Menu_Item* menu_item = (Fl_Menu_Item*)estConvergenceMeasureMenu->menu();
      for ( int i = 0; i < estConvergenceMeasureMenu->size(); i++ )
      {
          if ( menu_item[i].value() )
          {
              err |= (1 << i);
          }
      }
      double value = 0;
      bool intensity = false;
      bool roughness = false;
      
      int numberOfStrata;
      int startOfStrata;
      int sizeOfStrata;
  
      if (estVariantModelInput->value() == 0)
      {
          numberOfStrata = (int)estVariantStrataNumberInput->value();
          startOfStrata = (int)estVariantStrataStartInput->value();
          sizeOfStrata = (int)estVariantStrataSizeInput->value();
      } else if (estVariantModelInput->value() == 1)
      {
          // Use kind of Strata variables to pass PCA values
          numberOfStrata = (int)estVariantPCAComponentsInput->value();
          startOfStrata = (int)estVariantPCAStartInput->value();
          sizeOfStrata = (int)estVariantPCANumberInput->value();
      }
  
      // determin the algorithm
      int algo = 0;
      if ( estLlsCheck->value() )
      {
          algo = EST_LLS;
          value = estLinearParameterInput->value();
      }
      else if ( estMapCheck->value() )
      {
          algo = EST_MAP;
          value = estLinearParameterInput->value();
      }
      else if ( estJvcCheck->value() )
      {
          algo = EST_JVC;
          value = estInvariantParameterInput->value();
      }
      else if ( estEmCheck->value() )
      {
          algo = EST_EM;
          value = estInvariantParameterInput->value(); 
          intensity = estInvariantPenaltyInput->value() == 1;
          roughness = estInvariantPenaltyInput->value() == 2;                                                                     
          if ( estInvariantDoubleInput->value() )
          {
              algo |= EST_DOUBLE;
          }
      }else if ( estSiCheck->value() )
      {
          algo = EST_EMSICG;
          value = estInvariantParameterInput->value();
      }
      else if ( estSvCheck->value() )
      {
          algo = EST_EMSV;
          value = estVariantParameterInput->value();
          intensity = estVariantPenaltyInput->value() == 1;
          roughness = estVariantPenaltyInput->value() == 2;
          if ( estVariantDoubleInput->value() )
          {
              algo |= EST_DOUBLE;
          }
          if ( estVariantBigInput->value() == 1 )
          {
              algo |= EST_IO;
          }
          if ( estVariantModelInput->value() == 1 )
          {
              algo |= EST_PCA;
          }
          
      }
      else if ( estOsCheck->value() )
      {
          algo = EST_EMOS;
          value = estVariantParameterInput->value();
          intensity = estVariantPenaltyInput->value() == 1;
          roughness = estVariantPenaltyInput->value() == 2;
          if ( estVariantDoubleInput->value() )
          {
              algo |= EST_DOUBLE;
          }
          if ( estVariantBigInput->value() == 1 )
          {
              algo |= EST_IO;
          }
      }
      else if ( estDvCheck->value() )
      {
          algo = EST_EMDVCG;
          value = estVariantParameterInput->value();
          intensity = estVariantPenaltyInput->value() == 1;
          roughness = estVariantPenaltyInput->value() == 2;
      }
      if ( algo == 0 ) return;
      
      estProgress->value(0);
      // convert to same data type and do estimation
      if ( imgData.IsFloat() )
      {
          blitz::Array<float,N> img = imgData.GetFloatArray();
          psfData.ConvertToFloat();
          blitz::Array<float,N> psf = psfData.GetFloatArray();
          if ( !larger(img.shape(), psf.shape()) )
          {
              fl_alert("PSF Larger Than Image");
              return;
          }
          phantomData.ConvertToFloat();
          blitz::Array<float, N> phantom = phantomData.GetFloatArray();
          cosm::EstimatePenalty<float,N>* penalty = 
              (intensity ? (cosm::EstimatePenalty<float,N>*)(new cosm::IntensityPenalty<float,N>(value)) :
              (roughness ? (cosm::EstimatePenalty<float,N>*)(new cosm::RoughnessPenalty<float,N>(value)) : NULL));
          float regularization = static_cast<float> (value);
          blitz::Array<float,N> est = performEstimation(algo, img, psf, phantom, usePhantom, iterations, update, writeUpdate, numberOfStrata, startOfStrata, sizeOfStrata,(float)value, err, psfprefix, psfsuffix, otfprefix, otfsuffix, estprefix, estsuffix, centeredPsf, penalty, estProgress, estTable, regularization);
          estProgress->value(100);
          cosm::wuDataWrite(est, estname);
      }
      else if ( imgData.IsDouble() )
      {
          blitz::Array<double,N> img = imgData.GetDoubleArray();
          psfData.ConvertToDouble();
          blitz::Array<double,N> psf = psfData.GetDoubleArray();
          if ( !larger(img.shape(), psf.shape()) )
          {
              fl_alert("PSF Larger Than Image");
              return;
          }
          phantomData.ConvertToDouble();
          blitz::Array<double, N> phantom = phantomData.GetDoubleArray();
          cosm::EstimatePenalty<double,N>* penalty =  
              (intensity ? (cosm::EstimatePenalty<double,N>*)(new cosm::IntensityPenalty<double,N>(value)) :
              (roughness ? (cosm::EstimatePenalty<double,N>*)(new cosm::RoughnessPenalty<double,N>(value)) : NULL));
          double regularization = static_cast<double> (value);
          blitz::Array<double,N> est = performEstimation(algo, img, psf, phantom, usePhantom, iterations, update, writeUpdate, numberOfStrata, startOfStrata, sizeOfStrata, (double)value, err, psfprefix, psfsuffix, otfprefix, otfsuffix, estprefix, estsuffix, centeredPsf, penalty, estProgress, estTable, regularization);
          estProgress->value(100);
          cosm::wuDataWrite(est, estname);
      }
      else if ( imgData.IsLongDouble() )
      {
          blitz::Array<long double,N> img = imgData.GetLongDoubleArray();
          psfData.ConvertToLongDouble();
          blitz::Array<long double,N> psf = psfData.GetLongDoubleArray();
          if ( !larger(img.shape(), psf.shape()) )
          {
              fl_alert("PSF Larger Than Image");    
              return;
          }
          phantomData.ConvertToLongDouble();
          blitz::Array<long double, N> phantom = phantomData.GetLongDoubleArray();
          cosm::EstimatePenalty<long double,N>* penalty = 
              (intensity ? (cosm::EstimatePenalty<long double,N>*)(new cosm::IntensityPenalty<long double,N>(value)) :
              (roughness ? (cosm::EstimatePenalty<long double,N>*)(new cosm::RoughnessPenalty<long double,N>(value)) : NULL));
          long double regularization = static_cast<long double> (value);
          blitz::Array<long double,N> est = performEstimation(algo, img, psf, phantom, usePhantom, iterations, update, writeUpdate, numberOfStrata, startOfStrata, sizeOfStrata, (long double)value, err, psfprefix, psfsuffix, otfprefix, otfsuffix, estprefix, estsuffix, centeredPsf, penalty, estProgress, estTable, regularization);
          estProgress->value(100);
          cosm::wuDataWrite(est, estname);
      }
}

void EstGUI::readXml( const std::string& filename ) {
  cosm::EstXml<double> estXml;
  if ( !estXml.open( filename ) ) return;
  
  estLlsCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_LLS);
  estMapCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_MAP); 
  estEmCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_EM);
  estJvcCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_JVC);
  estSiCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_SICG);
  estSvCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_EMSV); 
  estOsCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_EMOS);
  estDvCheck->value(estXml.algorithm() == EstXml<double>::ALGORITHM_DVCG);
  
  estImgInput->value(estXml.imgFile().c_str());
  estPsfInput->value(estXml.psfFile().c_str());
  estEstInput->value(estXml.estFile().c_str());
  
  estCenteredPsfCheck->value(estXml.centeredPSF());
  
  estLinearParameterInput->value(estXml.linearParameter());
  estIterationsInput->value(estXml.iterationNumber());
  estUpdateInput->value(estXml.iterationUpdate());
  estWriteInput->value(estXml.iterationWrite());
  
  estInvariantDoubleInput->value(estXml.invariantDoubleZ());
  estInvariantParameterInput->value(estXml.invariantPenaltyValue());
  estInvariantPenaltyInput->value(estXml.invariantPenaltyType());
  
  estVariantDoubleInput->value(estXml.variantDoubleZ());
  estVariantParameterInput->value(estXml.variantPenaltyValue());
  estVariantPenaltyInput->value(estXml.variantPenaltyType());
  estVariantStrataNumberInput->value(estXml.variantStrataValue());
  estVariantStrataStartInput->value(estXml.variantStrataStart());
  estVariantStrataSizeInput->value(estXml.variantStrataSize());
  estVariantBigInput->value(estXml.variantOtfType());
  estOtfInput->value(estXml.variantOtfName().c_str());
  
  estVariantPCAComponentsInput->value(estXml.variantPCAValue());
  estVariantPCAStartInput->value(estXml.variantPCAStart());
  estVariantPCANumberInput->value(estXml.variantPCASize());
  estVariantModelInput->value(estXml.variantModeType());
  
  if (estSvCheck->value()){
  	if ( estVariantModelInput->value() == 0 )
  	{
  		  estVariantStrataStartInput->activate();
  		  estVariantStrataSizeInput->activate();
  		  estVariantStrataNumberInput->activate();
  		  estVariantPCAComponentsInput->deactivate();
  		  estVariantPCAStartInput->deactivate();
  		  estVariantPCANumberInput->deactivate();
  		  estVariantDoubleInput->activate();
  		  estVariantBigInput->activate();
  	} else if (estVariantModelInput->value() == 1)
  	{
  		  estVariantStrataStartInput->deactivate();
  		  estVariantStrataSizeInput->deactivate();
  		  estVariantStrataNumberInput->deactivate();
  		  estVariantPCAComponentsInput->activate();
  		  estVariantPCAStartInput->activate();
  		  estVariantPCANumberInput->activate();
  		  estVariantDoubleInput->value(0);
  		  estVariantDoubleInput->deactivate();
  		  estVariantBigInput->value(0);
  		  estVariantBigInput->deactivate();
  	}
  }else if (estOsCheck->value()){
  	estVariantModelInput->deactivate();
  	estVariantStrataStartInput->activate();
  	estVariantStrataSizeInput->activate();
  	estVariantStrataNumberInput->activate();
  	estVariantPCAComponentsInput->deactivate();
  	estVariantPCAStartInput->deactivate();
  	estVariantPCANumberInput->deactivate();
  	estVariantDoubleInput->activate();
  	estVariantBigInput->activate();
  }else if (estDvCheck->value()){
      estVariantModelInput->deactivate();
      
      estVariantStrataStartInput->deactivate();
      estVariantStrataSizeInput->deactivate();
      estVariantPCAComponentsInput->deactivate();
      estVariantPCAStartInput->deactivate();
      estVariantPCANumberInput->deactivate();
      estVariantDoubleInput->deactivate();
      estVariantBigInput->deactivate();
      estOtfInput->deactivate();
  
  }
  
  Fl_Menu_Item* menu_item = (Fl_Menu_Item*)estConvergenceMeasureMenu->menu();
  for ( int i = 0; i < estConvergenceMeasureMenu->size(); i++ )
  {
      if ( (int(estXml.convergenceType()) >> i) && 0x1 )
      {
          menu_item[i].set();
      }
      else
      {
          menu_item[i].clear();
      }
  }
  estPhaInput->value(estXml.convergenceName().c_str());
}

void EstGUI::writeXml( const std::string& filename ) {
  cosm::EstXml<double> estXml;
  if ( estLlsCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_LLS);
  if ( estMapCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_MAP);
  if ( estEmCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_EM);
  if ( estJvcCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_JVC);
  if ( estSiCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_SICG);
  if ( estSvCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_EMSV);
  if ( estOsCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_EMOS);
  if ( estDvCheck->value() ) estXml.algorithm(EstXml<double>::ALGORITHM_DVCG);
  
  
  estXml.imgFile(estImgInput->value());
  estXml.psfFile(estPsfInput->value());
  estXml.estFile(estEstInput->value());
  
  estXml.centeredPSF(estCenteredPsfCheck->value());
  
  estXml.linearParameter(estLinearParameterInput->value());
  estXml.iterationNumber(estIterationsInput->value());
  estXml.iterationUpdate(estUpdateInput->value());
  estXml.iterationWrite(estWriteInput->value());
  
  estXml.invariantDoubleZ(estInvariantDoubleInput->value());
  estXml.invariantPenaltyValue(estInvariantParameterInput->value());
  estXml.invariantPenaltyType(EstXml<double>::PenaltyType(estInvariantPenaltyInput->value()));
  
  estXml.variantDoubleZ(estVariantDoubleInput->value());
  estXml.variantPenaltyValue(estVariantParameterInput->value());
  estXml.variantPenaltyType(EstXml<double>::PenaltyType(estVariantPenaltyInput->value()));
  estXml.variantStrataValue(estVariantStrataNumberInput->value());
  estXml.variantStrataStart(estVariantStrataStartInput->value());
  estXml.variantStrataSize(estVariantStrataSizeInput->value());
  estXml.variantOtfType(EstXml<double>::OTFType(estVariantBigInput->value()));
  estXml.variantOtfName(estOtfInput->value());
  
  estXml.variantPCAValue(estVariantPCAComponentsInput->value());
  estXml.variantPCAStart(estVariantPCAStartInput->value());
  estXml.variantPCASize(estVariantPCANumberInput->value());
  estXml.variantModeType(EstXml<double>::ModeType(estVariantModelInput->value()));
  
  int value = 0;
  Fl_Menu_Item* menu_item = (Fl_Menu_Item*)estConvergenceMeasureMenu->menu();
  for ( int i = 0; i < estConvergenceMeasureMenu->size(); i++ )
  {
      if ( menu_item[i].value() )
      {
          value |= (1 << i);
      }
  }
  estXml.convergenceType(value);
  estXml.convergenceName(estPhaInput->value());
  
  estXml.save( filename );
}

void EstGUI::make_table_dialog( void ) {
  { tableDialog = new Fl_Double_Window(513, 656);
    tableDialog->user_data((void*)(this));
    { estTable = new Table(30, 28, 455, 553, "Error Measure Table:");
      estTable->box(FL_ENGRAVED_BOX);
      estTable->color(FL_BACKGROUND_COLOR);
      estTable->selection_color(FL_BACKGROUND_COLOR);
      estTable->labeltype(FL_NORMAL_LABEL);
      estTable->labelfont(0);
      estTable->labelsize(14);
      estTable->labelcolor(FL_FOREGROUND_COLOR);
      estTable->align(Fl_Align(FL_ALIGN_TOP_LEFT));
      estTable->when(FL_WHEN_RELEASE);
      make_table_entries();
    } // Table* estTable
    { Fl_Return_Button* o = new Fl_Return_Button(395, 605, 86, 25, "Close");
      o->callback((Fl_Callback*)cb_Close);
    } // Fl_Return_Button* o
    { Fl_Button* o = new Fl_Button(305, 605, 84, 25, "Save...");
      o->callback((Fl_Callback*)cb_Save);
    } // Fl_Button* o
    tableDialog->end();
  } // Fl_Double_Window* tableDialog
}

void EstGUI::make_table_entries(void) {
  estTable->addColumn("Iteration", 65);
  estTable->addColumn("Maximum", 70);
  estTable->addColumn("Mean", 50);
  estTable->addColumn("Mean Square", 85);
  estTable->addColumn("Log Likelihood", 100);
  estTable->addColumn("I-Divergence", 80);
}

void EstGUI::make_save_csv( const char* filename) {
  std::filebuf file;
  file.open(filename, ios::out);
  
  std::ostream out(&file);
  out << "Iterations, Maximum, Mean, Mean Square, Log Likelihood, I-Divergence" << std::endl;
  int i = 0, j = 0;
  for ( i = 0; i < estTable->rows(); i++ )
  {
      for ( j = 0; j < estTable->columns()-1; j++ )
      {
          out << estTable->valueAt(i,j) <<", ";
      }
      out << estTable->valueAt(i,j) << std::endl;
  }
}
