Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

#include "workstation.h"
#include "daq.h"
#include "root_include.h"
#include "windowed_test.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include "daqscope.h"

//---------------------------------------------------------------
// Subwindow layout class

class TGMdiSubwindow
{
RQ_OBJECT("TGMdiSubwindow")

protected:
   TGMdiFrame       *fMdiFrame;

public:
   TGMdiSubwindow(TGMdiMainFrame *main, int w, int h);

   TGMdiFrame *GetMdiFrame() const { return fMdiFrame; }
   virtual Bool_t CloseWindow();
};

//---------------------------------------------------------------
// Main window class

class TGAppMainFrame
{
RQ_OBJECT("TGAppMainFrame")

protected:
   TGMainFrame     *fMain;
   TGMdiMainFrame  *fMainFrame;
   TGMdiMenuBar    *fMenuBar;
   TGLayoutHints   *fMenuBarItemLayout;
   TGPopupMenu     *fMenuFile, *fMenuAnalysis, *fMenuWindow, *fMenuHelp;
   TGPopupMenu     *fMenuHisttype;
   TGMdiSubwindow  *settingsPane, *mainSubwindow, *histogramPane, *histogramPaneFile, *histogramPaneCtr;

   void InitMenu();
   void MeasurementLayout();
   void CloseWindow();
   Bool_t About();
public:
   TGAppMainFrame(const TGWindow *p, int w, int h);

   void HandleMenu(Int_t id);

   void EnableVoltScan();
   void EnableSurfScan();
   void EnableZaxisScan();
   void VoltageLimit();
   void ChannelLimit();
   void CleanPlotToggle();
   void ConnectToScope();

   void SetVoltOut();
   void GetVoltOut();
   void ResetVoltOut();
   void SetPosition();
   void GetPosition();
   void HomePosition();
   void SaveFile();
   void StartAcq();

   void SelectDirectory();
   void ListMultiSelect();
   void ListSelectAll();
   void FileListNavigation(int pn);

   void DisplayHistogram(char *histfile, int histtype);
   void SetHistRange();
   void ChangeHisttype(int type);
   void ChangeChannel();
   void HistogramExport();
   void MakeSurfPlot(TList *files);
   void MakeBreakdownPlot(int nrp, double *volt, double *volterr, double *psep1, double *pseperr1, double *psep2, double *pseperr2, double *psep3, double *pseperr3, char *plotfile);

   void FitSpectrum(TList *files, int q);
   void EdgeDetection(TGraph *pdf, TGraph *cdf, char *outname, TCanvas *g1dCanvas, double pdfmax, int direction);
   void IntegSpectrum(TList *files, int direction);

   void RunMeas(void *ptr, int runCase, int zaxisscan);
};

const char *histExt = ".root";
const char *histExtAll = "*.root";
daq *gDaq;
daqscope *gScopeDaq;
int debugSig = 0;
int retTemp;
int gStop=0;
unsigned int gBuf[BSIZE];
int logchange = 0;
double tdctimeconversion = 45.0909;
double lenconversion = 0.3595;
int oscOn;

// ROOT file variable structure -----------
struct EventHeader {
  int nrch;
  int timestamp;
  double biasvolt;
  int xpos;
  int ypos;
  int zpos;
  double temperature;
  char laserinfo[256];
} evtheader;

struct EventData {
  int adcdata[8];
  int tdcdata[8];
} evtdata;

TFile *inroot;
TFile *outroot;

//---------------------------------------------------------------
// Global variables

TGCheckButton *voltscanOn;
TGCheckButton *surfscanOn;
TGCheckButton *zscanOn;
TGTextEntry   *oscIP;
TGTextButton  *oscConnect;
TGCheckButton *histogramOn;
TGNumberEntry *vHardlimit;
TGNumberEntry *NCH;
TGTextEntry   *laserInfo;
TGCheckButton *cleanOn;

TGTab         *setTab;
TGComboBox    *vOutCh;
TGNumberEntry *vOut;
TGCheckButton *vOutOnOff;
TGTextButton  *vOutSet;
TGTextButton  *vOutGet;
TGTextButton  *vOutReset;
TGNumberEntry *vOutStart;
TGNumberEntry *vOutStop;
TGNumberEntry *vOutStep;
TGNumberEntry *xPos;
TGNumberEntry *yPos;
TGNumberEntry *zPos;
TGTextButton  *positionSet;
TGTextButton  *positionGet;
TGTextButton  *positionHome;
TGNumberEntry *xPosMin;
TGNumberEntry *xPosMax;
TGNumberEntry *xPosStep;
TGNumberEntry *yPosMin;
TGNumberEntry *yPosMax;
TGNumberEntry *yPosStep;
TGNumberEntry *zPosMin;
TGNumberEntry *zPosMax;
TGNumberEntry *zPosStep;
TGNumberEntry *evtNum;
TGTextEntry   *timeStamp;
TGTextEntry   *fileName;
TGTextButton  *saveFile;
TGTextButton  *measStart;
TGLabel       *busyLabel;
TGHProgressBar *curProgress;

TRootEmbeddedCanvas *histCanvas;

TGTextButton  *selectDir;
TGListBox     *fileList;
TGCheckButton *multiSelect;
TGCheckButton *multiSelectAll;
TGTextButton  *prevFile;
TGTextButton  *nextFile;

TGNumberEntry *adcMinRange;
TGNumberEntry *adcMaxRange;
TGNumberEntry *tdcMinwindow;
TGNumberEntry *tdcMaxwindow;
TGNumberEntry *yMinRange;
TGNumberEntry *yMaxRange;
TGNumberEntry *selectCh;
TGTextButton  *changeADC;
TGTextButton  *changeTDC;
TGTextButton  *changeADCTDC;
TGTextButton  *change2Dsurf;
TGCheckButton *logscale;
TGTextButton  *exportHist;
TGNumberEntry *fitSigma;
TGNumberEntry *fitTresh;
TGNumberEntry *fitInter;
TGNumberEntry *accError;
TGCheckButton *exfitplots;

Bool_t firstrun = kTRUE;
Bool_t started;
Bool_t cleanPlots = kTRUE;

// Layout hints definitions
TGLayoutHints *f0 = new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2);
TGLayoutHints *f0centerx = new TGLayoutHints(kLHintsCenterX,2,2,2,2);
TGLayoutHints *f0centery = new TGLayoutHints(kLHintsLeft | kLHintsCenterY,2,2,2,2);
TGLayoutHints *f0center2d = new TGLayoutHints(kLHintsCenterX | kLHintsCenterY,2,2,2,2);
TGLayoutHints *f0right = new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2);
TGLayoutHints *f1 = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,2,2,2,2);
TGLayoutHints *f2 = new TGLayoutHints(kLHintsExpandX,2,2,2,2);
TGLayoutHints *f3 = new TGLayoutHints(kLHintsCenterY,2,2,20,2);
TGLayoutHints *f3notop = new TGLayoutHints(kLHintsCenterY,4,4,2,30);

// Separate functions -----------------------------------------
void GetTime(int intime, char *outtime)
{
   time_t rawtime;
   struct tm * timeinfo;
   if(intime < 0)
      time(&rawtime);
   else
      rawtime = (time_t)intime;
   timeinfo = localtime(&rawtime);
   sprintf(outtime, "%s", asctime(timeinfo));
   int len = strlen(outtime);
   if(len) outtime[len-1] = 0;
}

int MyTimer()
{
   char cmd[100];
   GetTime(-1, cmd);
   if (timeStamp) timeStamp->SetText(cmd);
   return 0;
}

int GetChannel()
{
   int selectedOutput;
   if(vOutCh->GetSelected() < 8) selectedOutput = (vOutCh->GetSelected())+1;
   else if( (vOutCh->GetSelected() >= 8) && (vOutCh->GetSelected() < 16) ) selectedOutput = (vOutCh->GetSelected())+93;
   else selectedOutput = 1;

   return selectedOutput;
}

void remove_ext(char *inname, char *outname)
{
  char ctemp[256];
  for(int i = 0; i < (int)strlen(inname); i++)
  {
    if( (inname[i] == '.') && (i > (int)(strlen(inname)-6)) )
    {
      ctemp[i] = '\0';
      sprintf(outname, "%s", ctemp);
      break;
    }
    else
      ctemp[i] = inname[i];
  }

  if(debugSig)
    printf("Outfile (remove_ext): %s\n", outname);
}

void remove_from_last(char *inname, char search, char *outname)
{
   char ctemp[256];
   int searchpos = -1;
   for(int i = (int)strlen(inname); i >= 0; i--)
   {
      if(inname[i] == search)
      {
         searchpos = i;
         break;
      }
   }

   for(int i = 0; i < searchpos; i++)
      ctemp[i] = inname[i];

   ctemp[searchpos] = '\0';
   sprintf(outname, "%s", ctemp);

   if(debugSig)
      printf("Outfile (remove_from_last): %s\n", outname);
}

// Peak detection function
int npeaks;
double FindPeaks(double *x, double *par)
{
   double result = 0;
   for(int i = 0; i < npeaks; i++)
   {
      double norm = par[3*i];
      double mean = par[3*i+1];
      double sigma = par[3*i+2];
      result += norm*TMath::Gaus(x[0], mean, sigma);
   }
   return result;
}

// Class related functions --------------------------------------

// Apply the upper voltage limit from settings pane to main window
void TGAppMainFrame::VoltageLimit()
{
   vOut->SetLimitValues(0, vHardlimit->GetNumber() );
}

// Apply the upper channel limit from settings pane to histogram settings
void TGAppMainFrame::ChannelLimit()
{
   selectCh->SetLimitValues(0, (NCH->GetNumber()-1) );
}

// Enable or disable voltage scan controls
void TGAppMainFrame::EnableVoltScan()
{
   if(voltscanOn->IsOn())
   {
      vOutStart->SetState(kTRUE);
      vOutStop->SetState(kTRUE);
      vOutStep->SetState(kTRUE);
   }
   else
   {
      vOutStart->SetState(kFALSE);
      vOutStop->SetState(kFALSE);
      vOutStep->SetState(kFALSE);
   }
}

// Enable or disable surface scan controls
void TGAppMainFrame::EnableSurfScan()
{
   if(surfscanOn->IsOn())
   {
      xPosMin->SetState(kTRUE);
      xPosMax->SetState(kTRUE);
      xPosStep->SetState(kTRUE);
      yPosMin->SetState(kTRUE);
      yPosMax->SetState(kTRUE);
      yPosStep->SetState(kTRUE);
   }
   else
   {
      xPosMin->SetState(kFALSE);
      xPosMax->SetState(kFALSE);
      xPosStep->SetState(kFALSE);
      yPosMin->SetState(kFALSE);
      yPosMax->SetState(kFALSE);
      yPosStep->SetState(kFALSE);
   }
}

// Enable or disable Z axis scan controls
void TGAppMainFrame::EnableZaxisScan()
{
   if(zscanOn->IsOn())
   {
      zPosMin->SetState(kTRUE);
      zPosMax->SetState(kTRUE);
      zPosStep->SetState(kTRUE);
   }
   else
   {
      zPosMin->SetState(kFALSE);
      zPosMax->SetState(kFALSE);
      zPosStep->SetState(kFALSE);
   }
}

// Toggle clean plots on/off
void TGAppMainFrame::CleanPlotToggle()
{
   cleanPlots = cleanOn->IsDown();
}

// Connect to oscilloscope
void TGAppMainFrame::ConnectToScope()
{
   int scopeState = -1;
   char *IPaddr = (char*)oscIP->GetText();
   int IPcorr = 0;
   char buf[BSIZE];

   if(oscOn == 0)
   {
      // Check if the IP address has the required three .
      for(int i = 0; i < (int)strlen(IPaddr); i++)
         if(IPaddr[i] == '.')
            IPcorr++;
    
      if( (IPaddr != NULL) && (IPcorr == 3) )
      {
#if WORKSTAT == 'I'
         printf("Connecting to oscilloscope.\n");
         retTemp = gScopeDaq->connect(IPaddr);
         scopeState = 1; // For testing instead of making a real connection
#else
         scopeState = 1;
#endif
      }
      else
      {
         scopeState = -1;
         printf("Please enter a valid scope IP address.\n");
      }
   }
   else if(oscOn == 1)
   {
#if WORKSTAT == 'I'
         printf("Disconnecting from oscilloscope.\n");
         retTemp = gScopeDaq->disconnect(IPaddr);
         scopeState = -1; // For testing instead of making a real disconnection
#else
         scopeState = -1;
#endif
   }

   if(scopeState >= 0)
   {
      setTab->SetEnabled(1, kTRUE);
      setTab->SetEnabled(2, kTRUE);
      oscIP->SetEnabled(kFALSE);
      oscConnect->SetText("Disconnect");
      oscConnect->SetTextJustify(36);
      oscConnect->SetWrapLength(-1);
      oscConnect->Resize(60,22);
      oscOn = 1;
   }
   else
   {
      setTab->SetEnabled(1, kFALSE);
      setTab->SetEnabled(2, kFALSE);
      oscIP->SetEnabled(kTRUE);
      oscConnect->SetText("Connect");
      oscConnect->SetTextJustify(36);
      oscConnect->SetWrapLength(-1);
      oscConnect->Resize(60,22);
      oscOn = 0;
   }
}

// Set the output voltage
void TGAppMainFrame::SetVoltOut()
{
   char cmd[256];
   int outOn;
   float outputVoltage;

   outputVoltage = vOut->GetNumber();

   if(vOutOnOff->IsOn()) outOn = 1;
   else outOn = 0;
  
   fflush(stdout);
   sprintf(cmd, "%s/mpod/mpod_voltage.sh -o %d -v %f -s %d", rootdir, GetChannel(), outputVoltage, outOn);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
   fflush(stdout);
}

// Get the output voltage
void TGAppMainFrame::GetVoltOut()
{
   char cmd[256];

   fflush(stdout);
   sprintf(cmd, "%s/mpod/mpod_voltage.sh -o %d -g > %s/curvolt.txt", rootdir, GetChannel(), rootdir);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
   fflush(stdout);

#if WORKSTAT == 'I'
   FILE* fvolt;
   double dtemp;
   char ctemp[24];
   sprintf(cmd, "%s/curvolt.txt", rootdir);
   fvolt = fopen(cmd, "r");
   
   if(fvolt != NULL)
   {
      sprintf(cmd, "WIENER-CRATE-MIB::outputVoltage.u%d = Opaque: Float: %s V\n", GetChannel()-1, "%lf" );
      retTemp = fscanf(fvolt, cmd, &dtemp);
      vOut->SetNumber(dtemp);
      sprintf(cmd, "WIENER-CRATE-MIB::outputSwitch.u%d = INTEGER: %s\n", GetChannel()-1, "%s" );
      retTemp = fscanf(fvolt, cmd, ctemp);
      if( strcmp(ctemp, "On(1)") == 0 )
         vOutOnOff->SetState(kButtonDown);
      else if( strcmp(ctemp, "Off(0)") == 0 )
         vOutOnOff->SetState(kButtonUp);
   }

   fclose(fvolt);
#endif
}

// Reset the output voltage
void TGAppMainFrame::ResetVoltOut()
{
   char cmd[256];

   vOut->SetNumber(0.000);
   vOutOnOff->SetState(kButtonUp);

   fflush(stdout);
   sprintf(cmd, "%s/mpod/mpod_voltage.sh -r %d", rootdir, GetChannel());
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
   fflush(stdout);
}

// Get the current table position
void TGAppMainFrame::GetPosition()
{
   char cmd[256];
  
   fflush(stdout);
   
   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 1 -p > %s/curpos.txt", rootdir, rootdir);  // X-axis
   fflush(stdout);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
   
   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 2 -p >> %s/curpos.txt", rootdir, rootdir); // Y-axis
   fflush(stdout);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
   
   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 3 -p >> %s/curpos.txt", rootdir, rootdir); // Z-axis
   fflush(stdout);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif

#if WORKSTAT == 'I'
   FILE* fpos;
   int itemp;
   sprintf(cmd, "%s/curpos.txt", rootdir);
   fpos = fopen(cmd, "r");
   
   if(fpos != NULL)
   {
      retTemp = fscanf(fpos, "%d\n", &itemp);
      xPos->SetNumber(itemp);
      retTemp = fscanf(fpos, "%d\n", &itemp);
      yPos->SetNumber(itemp);
      retTemp = fscanf(fpos, "%d\n", &itemp);
      zPos->SetNumber(itemp);
   }

   fclose(fpos);
#endif
}

// Set the current table position
void TGAppMainFrame::SetPosition()
{
   char cmd[256];
   int positX, positY, positZ;
  
   positX = xPos->GetNumber();
   positY = yPos->GetNumber();
   positZ = zPos->GetNumber();
  
   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 1 -v %d -s la && %s/MIKRO/mikro_ctrl -n 1 -c m", rootdir, positX, rootdir);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
  
   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 2 -v %d -s la && %s/MIKRO/mikro_ctrl -n 2 -c m", rootdir, positY, rootdir);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
  
   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 3 -v %d -s la && %s/MIKRO/mikro_ctrl -n 3 -c m", rootdir, positZ, rootdir);
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
}

// Set the current table position to a predetermined HOME position
void TGAppMainFrame::HomePosition()
{
   char cmd[256];

   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 1 -h", rootdir);   // X-axis
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif

   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 2 -h", rootdir);   // Y-axis
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif

   sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 3 -h", rootdir);   // Z-axis
#if WORKSTAT == 'I'
   retTemp = system(cmd);
#else
   printf("Cmd: %s\n",cmd);
#endif
}

// Make breakdown voltage plot
void TGAppMainFrame::MakeBreakdownPlot(int nrp, double *volt, double *volterr, double *psep1, double *pseperr1, double *psep2, double *pseperr2, double *psep3, double *pseperr3, char *plotfile)
{
   double fparam[2], fparamerr[2], meanval;
   TLatex *latex;
   char ctemp[256];
   int sortindex[nrp];

   TCanvas *canvas = new TCanvas("canv","canv",900,1200);
   canvas->Divide(1,3);
  
   TGraphErrors *gr1 = new TGraphErrors(nrp, volt, psep1, volterr, pseperr1);
   TGraphErrors *gr2 = new TGraphErrors(nrp, volt, psep2, volterr, pseperr2);
   TGraphErrors *gr3 = new TGraphErrors(nrp, volt, psep3, volterr, pseperr3);
  
   if(!cleanPlots)
      gr1->SetTitle("1st - 2nd peak separation");
   else
      gr1->SetTitle();
   gr1->SetLineColor(kBlue);
   gr1->SetMarkerColor(kBlue);
   gr1->SetMarkerStyle(20);
   gr1->SetMarkerSize(0.6);
  
  
   if(!cleanPlots)
      gr2->SetTitle("2nd - 3rd peak separation");
   else
      gr2->SetTitle();
   gr2->SetLineColor(kMagenta);
   gr2->SetMarkerColor(kMagenta);
   gr2->SetMarkerStyle(21);
   gr2->SetMarkerSize(0.4);
  
   if(!cleanPlots)
      gr3->SetTitle("3rd - 4th peak separation");
   else
      gr3->SetTitle();
   gr3->SetLineColor(kGreen);
   gr3->SetMarkerColor(kGreen);
   gr3->SetMarkerStyle(22);
   gr3->SetMarkerSize(0.6);
 
   // Plotting the first breakdown voltage plot
   canvas->cd(1);
   gPad->SetGridx(1);
   gPad->SetGridy(1);

   gr1->Draw("AP");
   gr1->GetXaxis()->SetTitle("Bias voltage (V)");
   gr1->GetYaxis()->SetTitle("Peak separation");
   gr1->GetYaxis()->CenterTitle();
   gr1->Fit("pol1","Q");
  
   TF1 *fit1 = gr1->GetFunction("pol1");
   fparam[0] = fit1->GetParameter(0);
   fparamerr[0] = fit1->GetParError(0); 
   fparam[1] = fit1->GetParameter(1);
   fparamerr[1] = fit1->GetParError(1);

   TMath::Sort(nrp, psep1, sortindex, kFALSE);

   meanval = -fparam[0]/fparam[1];
   if(!cleanPlots)
   {
      sprintf(ctemp, "#splitline{#Delta_{p}(U) = (%.2lf #pm %.2lf)#timesU + (%.2lf #pm %.3lf)}{U_{0} = %.2lf #pm %.3lf}", fparam[0], fparamerr[0], fparam[1], fparamerr[1], meanval, meanval*(TMath::Abs(fparamerr[0]/fparam[0]) + TMath::Abs(fparamerr[1]/fparam[1])) );
      latex = new TLatex();
      latex->SetTextSize(0.039);
      latex->DrawLatex(volt[0]-(volt[1]-volt[0]), 0.97*psep1[sortindex[nrp-1]], ctemp);
   }
   else
      printf("#Delta_p(U) = (%.2lf #pm %.2lf)*U + (%.2lf #pm %.3lf)\nU_0 = %.2lf #pm %.3lf", fparam[0], fparamerr[0], fparam[1], fparamerr[1], meanval, meanval*(TMath::Abs(fparamerr[0]/fparam[0]) + TMath::Abs(fparamerr[1]/fparam[1])) );

   // Plotting the second breakdown voltage plot
   canvas->cd(2);
   gPad->SetGridx(1);
   gPad->SetGridy(1);

   gr2->Draw("AP");
   gr2->GetXaxis()->SetTitle("Bias voltage (V)");
   gr2->GetYaxis()->SetTitle("Peak separation");
   gr2->GetYaxis()->CenterTitle();
   gr2->Fit("pol1","Q");
  
   TF1 *fit2 = gr2->GetFunction("pol1");
   fparam[0] = fit2->GetParameter(0);
   fparamerr[0] = fit2->GetParError(0); 
   fparam[1] = fit2->GetParameter(1);
   fparamerr[1] = fit2->GetParError(1);

   meanval = -fparam[0]/fparam[1];
   if(!cleanPlots)
   {
      sprintf(ctemp, "#splitline{#Delta_{p}(U) = (%.2lf #pm %.2lf)#timesU + (%.2lf #pm %.3lf)}{U_{0} = %.2lf #pm %.3lf}", fparam[0], fparamerr[0], fparam[1], fparamerr[1], meanval, meanval*(TMath::Abs(fparamerr[0]/fparam[0]) + TMath::Abs(fparamerr[1]/fparam[1])) );
      latex = new TLatex();
      latex->SetTextSize(0.039);
      latex->DrawLatex(volt[0]-(volt[1]-volt[0]), 0.97*psep2[sortindex[nrp-1]], ctemp);
   }
   else
      printf("#Delta_p(U) = (%.2lf #pm %.2lf)*U + (%.2lf #pm %.3lf)\nU_0 = %.2lf #pm %.3lf", fparam[0], fparamerr[0], fparam[1], fparamerr[1], meanval, meanval*(TMath::Abs(fparamerr[0]/fparam[0]) + TMath::Abs(fparamerr[1]/fparam[1])) );

   // Plotting the third breakdown voltage plot
   canvas->cd(3);
   gPad->SetGridx(1);
   gPad->SetGridy(1);

   gr3->Draw("AP");
   gr3->GetXaxis()->SetTitle("Bias voltage (V)");
   gr3->GetYaxis()->SetTitle("Peak separation");
   gr3->GetYaxis()->CenterTitle();
   gr3->Fit("pol1","Q");
  
   TF1 *fit3 = gr3->GetFunction("pol1");
   fparam[0] = fit3->GetParameter(0);
   fparamerr[0] = fit3->GetParError(0); 
   fparam[1] = fit3->GetParameter(1);
   fparamerr[1] = fit3->GetParError(1);

   meanval = -fparam[0]/fparam[1];
   if(!cleanPlots)
   {
      sprintf(ctemp, "#splitline{#Delta_{p}(U) = (%.2lf #pm %.2lf)#timesU + (%.2lf #pm %.3lf)}{U_{0} = %.2lf #pm %.3lf}", fparam[0], fparamerr[0], fparam[1], fparamerr[1], meanval, meanval*(TMath::Abs(fparamerr[0]/fparam[0]) + TMath::Abs(fparamerr[1]/fparam[1])) );
      latex = new TLatex();
      latex->SetTextSize(0.039);
      latex->DrawLatex(volt[0]-(volt[1]-volt[0]), 0.97*psep3[sortindex[nrp-1]], ctemp);
   }
   else
      printf("#Delta_p(U) = (%.2lf #pm %.2lf)*U + (%.2lf #pm %.3lf)\nU_0 = %.2lf #pm %.3lf", fparam[0], fparamerr[0], fparam[1], fparamerr[1], meanval, meanval*(TMath::Abs(fparamerr[0]/fparam[0]) + TMath::Abs(fparamerr[1]/fparam[1])) );

   canvas->SaveAs(plotfile);
}

// Fit the ADC spectrum peaks and make a breakdown voltage plot
void TGAppMainFrame::FitSpectrum(TList *files, int q)
{
   TCanvas *gCanvas = histCanvas->GetCanvas();
   gCanvas->cd();
   TH1F *histtemp;
   TSpectrum *spec;
   TH1 *histback;
   TH1F *h2;
   float *xpeaks;
   TF1 *fit;
   TF1 *fittingfunc;
   double *fparam;
   double *fparamerr;
   double meanparam[20], meanparamerr[20];
   int sortindex[20];
   char exportname[256];
   char paramname[256];
   char ctemp[256];

   FILE *fp;
   remove_from_last((char*)files->At(0)->GetTitle(), '_', ctemp);
   sprintf(paramname, "%s_fitresult.txt", ctemp);
   fp = fopen(paramname, "w");
   fclose(fp);

   int peaklimit = 5;
   int p = 0;
   double dtemp;
   double volt[files->GetSize()], volterr[files->GetSize()], sep[3][files->GetSize()], seperr[3][files->GetSize()]; 
   for(int m = 0; m < files->GetSize(); m++)
   {
      volt[m] = 0; volterr[m] = 0;
      for(int i = 0; i < 3; i++)
      { sep[i][m] = 0; seperr[i][m] = 0; }
   }

   for(int m = 0; m < files->GetSize(); m++)
   {
      for(int i = 0; i < 20; i++) { meanparam[20] = 0; meanparamerr[20] = 0; }

      DisplayHistogram( (char*)(files->At(m)->GetTitle()), 0);
      dtemp = evtheader.biasvolt;
      gCanvas->Modified();
      gCanvas->Update();

      histtemp = (TH1F*)gCanvas->GetPrimitive(histname);
      npeaks = 20;
      double par[3000];
      spec = new TSpectrum(npeaks);
      // Find spectrum background
      histback = spec->Background(histtemp, (int)fitInter->GetNumber(), "same");
      // Clone histogram and subtract background from it
      h2 = (TH1F*)histtemp->Clone("h2");
      h2->Add(histback, -1);
      // Search for the peaks
      int found = spec->Search(h2, fitSigma->GetNumber(), "goff", fitTresh->GetNumber() );
      printf("Found %d candidates to fit.\n",found);
      npeaks = found;
    
      xpeaks = spec->GetPositionX();
      for(int i = 0; i < found; i++)
      {
         float xp = xpeaks[i];
         int bin = h2->GetXaxis()->FindBin(xp);
         float yp = h2->GetBinContent(bin);
         par[3*i] = yp;
         par[3*i+1] = xp;
    //      par[3*i+2] = 3;
         par[3*i+2] = (double)fitSigma->GetNumber();
    //      printf("Peak %d: %f\n", i+1, xp);
      }
    
      // Fit the histogram
      fit = new TF1("fit", FindPeaks, 0, 400, 3*npeaks);
      TVirtualFitter::Fitter(histtemp, 3*npeaks);
      fit->SetParameters(par);
      fit->SetNpx(300);
      h2->Fit("fit","Q");  // for quiet mode, add Q
      fittingfunc = h2->GetFunction("fit");
      fparam = fittingfunc->GetParameters();
      fparamerr = fittingfunc->GetParErrors();
    
      // Gather the parameters (mean peak value for now)
      int j = 1;
      int nrfit = 0;
      while(1)
      {
         if( (fparam[j] < 1.E-30) || (fparamerr[j] < 1.E-10) )
            break;
         else
         {
            if(fparam[j] > 0)
            {
               meanparam[nrfit] = fparam[j];
               meanparamerr[nrfit] = fparamerr[j];
               nrfit++;
            }
         }
    
         j+=3;
      }

      // Write out parameters to a file
      fp = fopen(paramname, "a");
    
      fprintf(fp, "%d\t", nrfit);
      TMath::Sort(nrfit, meanparam, sortindex, kFALSE);
      for(int i = 0; i < nrfit; i++)
      {
         if(debugSig)
            printf("Peak %d: %lf\t%lf\n", i+1, meanparam[sortindex[i]], meanparamerr[sortindex[i]]);
         fprintf(fp, "%le\t%le\t", meanparam[sortindex[i]], meanparamerr[sortindex[i]]);
      }
      printf("\n");
      fprintf(fp, "\n");

      fclose(fp);

      h2->SetStats(0);
      
      gCanvas->Modified();
      gCanvas->Update();

      // Save each fitting plot
      if(exfitplots->IsDown())
      {
         remove_ext((char*)files->At(m)->GetTitle(), ctemp);
         sprintf(exportname, "%s_fit.pdf", ctemp);
         gCanvas->SaveAs(exportname);
      }

      // Get points for mean peak values and create a breakdown voltage plot
      if(nrfit >= peaklimit)
      {
         sep[0][p] = meanparam[sortindex[2]] - meanparam[sortindex[1]];
         sep[1][p] = meanparam[sortindex[3]] - meanparam[sortindex[2]];
         sep[2][p] = meanparam[sortindex[4]] - meanparam[sortindex[3]];
     
         seperr[0][p] = TMath::Abs(meanparamerr[sortindex[2]]) + TMath::Abs(meanparamerr[sortindex[1]]);
         seperr[1][p] = TMath::Abs(meanparamerr[sortindex[3]]) + TMath::Abs(meanparamerr[sortindex[2]]);
         seperr[2][p] = TMath::Abs(meanparamerr[sortindex[4]]) + TMath::Abs(meanparamerr[sortindex[3]]);
     
         volt[p] = dtemp;
         volterr[p] = 1.e-4;
     
         if(debugSig)
            printf("p=%d:\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\n", p, volt[p], sep[0][p], seperr[0][p], sep[1][p], seperr[1][p], sep[2][p], seperr[2][p]);
    
         // Accept only the points with a small enough error
         if( (seperr[0][p]/sep[0][p] < accError->GetNumber()) && (seperr[1][p]/sep[1][p] < accError->GetNumber()) && (seperr[2][p]/sep[2][p] < accError->GetNumber()) )
            p++;
         else
            printf("Point (at %.2lfV) rejected due to errors: %lf, %lf, %lf\n", volt[p], seperr[0][p]/sep[0][p], seperr[1][p]/sep[1][p], seperr[2][p]/sep[2][p]);
      }

      if(q == 1) break;
   }

   // Plot & fit breakdown voltage plots
   if(q > 1)
   {
      remove_from_last((char*)files->At(0)->GetTitle(), '_', ctemp);
      sprintf(paramname, "%s_breakdown.pdf", ctemp);
      MakeBreakdownPlot(p, volt, volterr, sep[0], seperr[0], sep[1], seperr[1], sep[2], seperr[2], paramname);
   }
}

// Plotting of PDF and CDF functions for the edge (with the added fit)
void TGAppMainFrame::EdgeDetection(TGraph *pdf, TGraph *cdf, char *outname, TCanvas *g1dCanvas, double pdfmax, int direction)
{
//   double x, y;

   pdf->Fit("gaus","Q");
   pdf->GetFunction("gaus")->SetNpx(400);
/*
   for(int i = 0; i < nrpoints; i++)
   {
      pdf->GetPoint(i, x, y);
      pdf->SetPoint(i, x, (y/pdfmax) );
   }
*/
   gStyle->SetOptFit(1);

   cdf->Draw("AL");
   gPad->Update();
   pdf->Draw("LP");

   g1dCanvas->Modified();
   g1dCanvas->Update();

   TPaveStats *stats = (TPaveStats*)pdf->FindObject("stats");
   if(!cleanPlots)
   {
//      stats->SetX1NDC(0.14); stats->SetX2NDC(0.28);
//      stats->SetY1NDC(0.83); stats->SetY2NDC(0.96);
      stats->SetX1NDC(0.86); stats->SetX2NDC(1.0);
      stats->SetY1NDC(0.87); stats->SetY2NDC(1.0);
   }
   else
   {
      stats->SetX1NDC(1.1); stats->SetX2NDC(1.3);
      stats->SetY1NDC(1.1); stats->SetY2NDC(1.3);
   }

   g1dCanvas->SetGridx(1);
   g1dCanvas->SetGridy(1);
   if(direction == 1)
      cdf->GetXaxis()->SetTitle("X [#mum]");
   else if(direction == 2)
      cdf->GetXaxis()->SetTitle("Y [#mum]");
   cdf->GetXaxis()->CenterTitle(kTRUE);
   cdf->GetXaxis()->SetLabelSize(0.022);
   cdf->GetYaxis()->SetTitle("Normalized ADC integral");
//   cdf->GetYaxis()->SetTitle("Normalized ADC integral (CDF)");
//   cdf->GetYaxis()->SetTitleColor(kBlue);
   cdf->GetYaxis()->CenterTitle(kTRUE);
   cdf->GetYaxis()->SetLabelSize(0.022);
   cdf->GetYaxis()->SetRangeUser(0,1);
   cdf->GetYaxis()->SetTitleSize(0.030);
//   cdf->GetYaxis()->SetLabelColor(kBlue);
   if(!cleanPlots)
      cdf->SetTitle("SiPM edge detection");
   else
      cdf->SetTitle();
   cdf->SetLineColor(kBlue);
   pdf->SetLineWidth(2);
   cdf->SetLineWidth(2);

/*   TGaxis *axis = new TGaxis(gPad->GetUxmax(), 0, gPad->GetUxmax(), 1, 0, pdfmax, 510, "+L");
   axis->Draw();
   axis->SetTitle("Normalized ADC integral (PDF)");
   axis->SetTitleSize(0.035);
   axis->CenterTitle();
   axis->SetTitleColor(kBlack);
   axis->SetTitleFont(42);
   axis->SetLabelSize(0.022);
   axis->SetLabelColor(kBlack);*/

   g1dCanvas->Modified();
   g1dCanvas->Update();

   g1dCanvas->SaveAs(outname);
}

// Integrate the spectrum
void TGAppMainFrame::IntegSpectrum(TList *files, int direction)
{
   unsigned int nrfiles = fileList->GetNumberOfEntries();
   char ctemp[256];
   int j, k = 0, m = 0, n = 0;

   TCanvas *gCanvas = new TCanvas("canv","canv",900,900);
   TCanvas *g1dCanvas = new TCanvas("canv1d","canv1d",1200,900);
   TTree *header_data, *meas_data;
   double *integralCount, *integralAcc;
   integralCount = new double[nrfiles];
   integralAcc = new double[nrfiles];
//   double xsurfmin, ysurfmin, zsurfmin;
   double *surfx, *surfy, *surfz;
   surfx = new double[nrfiles];
   surfy = new double[nrfiles];
   surfz = new double[nrfiles];
   for(int i = 0; i < (int)nrfiles; i++) {integralCount[i] = 0; integralAcc[i] = 0; }

   TGraph *gScan[2];    // graphs for PDF and CDF functions
   double pdfmax = -1;
   TGraph2D *gScan2D;
   gScan2D = new TGraph2D();
   int nrentries;
   double minInteg, maxInteg;

   char exportname[256];

   if(files->GetSize() > 0)
   {
      for(int i = 0; i < (int)files->GetSize(); i++)
      {
         n++;
         if(files->At(i))
         {
            sprintf(ctemp, "%s", files->At(i)->GetTitle());
            inroot = new TFile(ctemp, "READ");
          
            inroot->GetObject("header_data", header_data);
            inroot->GetObject("meas_data", meas_data);
          
            // Reading the header
            header_data->SetBranchAddress("xpos", &evtheader.xpos);
            header_data->GetEntry(0);
            header_data->SetBranchAddress("ypos", &evtheader.ypos);
            header_data->GetEntry(0);
            header_data->SetBranchAddress("zpos", &evtheader.zpos);
            header_data->GetEntry(0);
    
            char rdc[256];
            j = selectCh->GetNumber();
            double rangetdc[2];
            rangetdc[0] = tdcMinwindow->GetNumber();
            rangetdc[1] = tdcMaxwindow->GetNumber();
    
            k = 0;
            m = 0;
          
            // Reading the data
            for(int e = 0; e < meas_data->GetEntries(); e++)
            {
               sprintf(rdc, "ADC%d", j);
               meas_data->SetBranchAddress(rdc, &evtdata.adcdata[j]);
               meas_data->GetEntry(e);
          
               sprintf(rdc, "TDC%d", j);
               meas_data->SetBranchAddress(rdc, &evtdata.tdcdata[j]);
               meas_data->GetEntry(e);
    
               // If our data point is inside the TDC window
               if( ((double)evtdata.tdcdata[j]/tdctimeconversion >= rangetdc[0]) && ((double)evtdata.tdcdata[j]/tdctimeconversion <= rangetdc[1]) )
               {
                  k++;
                  m += evtdata.adcdata[j];
               }
            }

/*          if(n == 1)  // these values can be used to set 0 value at first X, Y and Z positions
            {
               xsurfmin = evtheader.xpos;
               ysurfmin = evtheader.ypos;
               zsurfmin = evtheader.zpos;
            }
            surfx[i] = (double)(evtheader.xpos-xsurfmin)*lenconversion;
            surfy[i] = (double)(evtheader.ypos-ysurfmin)*lenconversion;
            surfz[i] = (double)(evtheader.zpos-zsurfmin)*lenconversion;*/
            surfx[i] = (double)(evtheader.xpos*lenconversion);
            surfy[i] = (double)(evtheader.ypos*lenconversion);
            surfz[i] = (double)(evtheader.zpos*lenconversion);

/*            surfx[i] = evtheader.xpos;
            surfy[i] = evtheader.ypos;
            surfz[i] = evtheader.zpos;
*/
            integralCount[i] += ((double)m)/((double)k);
            
            delete inroot;
         }
      }

      nrentries = n;
      printf("%d files were selected.\n", nrentries);

      double curzval = surfz[0];
      j = 0;
      int acc = 0;
      int zb;
      for(int i = 0; i <= nrentries; i++)
      {  
         if(acc == nrentries)
         {
            minInteg = TMath::MinElement(j, integralAcc);

            for(int za = 0; za < j; za++)
               integralAcc[za] = integralAcc[za] - minInteg;

            maxInteg = TMath::MaxElement(j, integralAcc);

            for(int za = 0; za < j; za++)
            {
               zb = i-j+za;
               integralCount[zb] = integralAcc[za]/maxInteg;
               if(debugSig)
                  printf("Integral check 2 (i=%d,j=%d,za=%d,z=%.2lf,zb=%d): %lf\t%lf\n", i, j, za, surfz[i-j], zb, integralCount[zb], integralAcc[za]/maxInteg);
            }

            // Plotting of PDF and CDF functions for the edge (with the added fit)
            gScan[1] = new TGraph();
            for(int za = 0; za < j; za++)
            {
               zb = i-j+za;
               if(direction == 1)
                  gScan[1]->SetPoint(za, (double)surfx[zb], (double)integralAcc[za]/maxInteg);
               else if(direction == 2)
                  gScan[1]->SetPoint(za, (double)surfy[zb], (double)integralAcc[za]/maxInteg);

               if( ((integralAcc[za+1]-integralAcc[za])/maxInteg > pdfmax) && (za < j-1) )
                  pdfmax = (integralAcc[za+1]-integralAcc[za])/maxInteg;
            }

            pdfmax = (TMath::Ceil(pdfmax*10))/10.;
     
            gScan[0] = new TGraph();
            for(int za = j-1; za >= 0; za--)
            {
               zb = (i-1)-(j-1)+za;
               if((integralAcc[za]-integralAcc[za-1])/(maxInteg) < 0)
               {
                  if(direction == 1)
                     gScan[0]->SetPoint(za, (double)surfx[zb], 0);
                  else if(direction == 2)
                     gScan[0]->SetPoint(za, (double)surfy[zb], 0);
               }
               else
               {
                  if(direction == 1)
                     gScan[0]->SetPoint(za, (double)surfx[zb], (integralAcc[za]-integralAcc[za-1])/(maxInteg));
                  else if(direction == 2)
                     gScan[0]->SetPoint(za, (double)surfy[zb], (integralAcc[za]-integralAcc[za-1])/(maxInteg));
//               gScan[0]->SetPoint(za, (double)surfx[zb], (integralAcc[za]-integralAcc[za-1])/(pdfmax*maxInteg));
               }
            }
     
            remove_from_last((char*)files->At(i-1)->GetTitle(), '_', ctemp);
            sprintf(exportname, "%s_edge.pdf", ctemp);
            EdgeDetection(gScan[0], gScan[1], exportname, g1dCanvas, pdfmax, direction);
     
//            delete gScan[0];
//            delete gScan[1];

            i--;
            pdfmax = 0;
            break;
         }       
         else
         {
            if(surfz[i] == curzval)
            {
               integralAcc[j] = integralCount[i];
               if(debugSig)
                  printf("Integral check 1 (i=%d,j=%d,z=%.2lf): %lf\t%lf\n", i, j, surfz[i], integralCount[i], integralAcc[j]);
               j++;
               acc++;
            }
            else
            {
               minInteg = TMath::MinElement(j, integralAcc);
           
               for(int za = 0; za < j; za++)
                  integralAcc[za] = integralAcc[za] - minInteg;
           
               maxInteg = TMath::MaxElement(j, integralAcc);
           
               for(int za = 0; za < j; za++)
               {
                  zb = i-j+za;
                  integralCount[zb] = integralAcc[za]/maxInteg;
                  if(debugSig)
                     printf("Integral check 2 (i=%d,j=%d,za=%d,z=%.2lf,zb=%d): %lf\t%lf\n", i, j, za, surfz[i-j], zb, integralCount[zb], integralAcc[za]/maxInteg);
               }
               
               curzval = surfz[i];
               i--;

               // Plotting of PDF and CDF functions for the edge (with the added fit)
               gScan[1] = new TGraph();
               for(int za = 0; za < j; za++)
               {
                  zb = i-(j-1)+za;
                  if(direction == 1)
                     gScan[1]->SetPoint(za, (double)surfx[zb], (double)integralAcc[za]/maxInteg);
                  else if(direction == 2)
                     gScan[1]->SetPoint(za, (double)surfy[zb], (double)integralAcc[za]/maxInteg);

                  if( ((integralAcc[za+1]-integralAcc[za])/maxInteg > pdfmax) && (za < j-1) )
                     pdfmax = (integralAcc[za+1]-integralAcc[za])/maxInteg;
               }

               pdfmax = (TMath::Ceil(pdfmax*10))/10.;

               gScan[0] = new TGraph();
               for(int za = j-1; za >= 0; za--)
               {
                  zb = i-(j-1)+za;
                  if((integralAcc[za]-integralAcc[za-1])/(maxInteg) < 0)
                  {
                     if(direction == 1)
                        gScan[0]->SetPoint(za, (double)surfx[zb], 0);
                     else if(direction == 2)
                        gScan[0]->SetPoint(za, (double)surfy[zb], 0);
                  }
                  else
                  {
                     if(direction == 1)
                        gScan[0]->SetPoint(za, (double)surfx[zb], (integralAcc[za]-integralAcc[za-1])/(maxInteg));
                     else if(direction == 2)
                        gScan[0]->SetPoint(za, (double)surfy[zb], (integralAcc[za]-integralAcc[za-1])/(maxInteg));
//                  gScan[0]->SetPoint(za, (double)surfx[zb], (integralAcc[za]-integralAcc[za-1])/(pdfmax*maxInteg));
                  }
               }

               remove_from_last((char*)files->At(i)->GetTitle(), '_', ctemp);
               sprintf(exportname, "%s_edge.pdf", ctemp);
               EdgeDetection(gScan[0], gScan[1], exportname, g1dCanvas, pdfmax, direction);
     
               delete gScan[0];
               delete gScan[1];

               j = 0;
               pdfmax = 0;
            }
         }
      }

//      delete g1dCanvas;
    
      double range[4];
      if(direction == 1)
      {
         range[0] = TMath::MinElement(nrentries, surfx);
         range[1] = TMath::MaxElement(nrentries, surfx);
      }
      else if(direction == 2)
      {
         range[0] = TMath::MinElement(nrentries, surfy);
         range[1] = TMath::MaxElement(nrentries, surfy);
      }
      else
      {
         range[0] = TMath::MinElement(nrentries, surfx);
         range[1] = TMath::MaxElement(nrentries, surfx);
      }
      range[2] = TMath::MinElement(nrentries, surfz);
      range[3] = TMath::MaxElement(nrentries, surfz);
    
      // Plotting of 2D edge plot
      for(int i = 0; i < nrentries; i++)
      {
         if(direction == 1)
         {
            if(debugSig)
               printf("%.2lf\t%.2lf\t%lf\n", surfx[i], surfz[i], integralCount[i]);
            gScan2D->SetPoint(i, surfx[i], surfz[i], integralCount[i]);
         }
         else if(direction == 2)
         {
            if(debugSig)
               printf("%.2lf\t%.2lf\t%lf\n", surfy[i], surfz[i], integralCount[i]);
            gScan2D->SetPoint(i, surfy[i], surfz[i], integralCount[i]);
         }
      }

      gCanvas->cd();
      gStyle->SetPalette(1);
      gScan2D->Draw("COLZ");
     
      gCanvas->Modified();
      gCanvas->Update();
     
      if(direction == 1)
         gScan2D->GetXaxis()->SetTitle("X [#mum]");
      else if(direction == 2)
         gScan2D->GetXaxis()->SetTitle("Y [#mum]");
      gScan2D->GetXaxis()->CenterTitle(kTRUE);
      gScan2D->GetXaxis()->SetLabelSize(0.022);
      gScan2D->GetXaxis()->SetRangeUser(range[0], range[1]);
      gScan2D->GetXaxis()->SetNoExponent();
      gScan2D->GetYaxis()->SetTitle("Z [#mum]");
      gScan2D->GetYaxis()->SetTitleOffset(1.3);
      gScan2D->GetYaxis()->CenterTitle(kTRUE);
      gScan2D->GetYaxis()->SetLabelSize(0.022);
      gScan2D->GetYaxis()->SetRangeUser(range[2], range[3]);
      TGaxis *yax = (TGaxis*)gScan2D->GetYaxis();
      yax->SetMaxDigits(4);
      if(!cleanPlots)
         gScan2D->SetTitle("Laser focal point");
      else
         gScan2D->SetTitle();
  
      gCanvas->Modified();
      gCanvas->Update();

      remove_from_last((char*)files->At(0)->GetTitle(), '_', ctemp);
      sprintf(exportname, "%s", ctemp);
      remove_from_last(exportname, '_', ctemp);
      if(direction == 1)
         sprintf(exportname, "%s_xdir_focalpoint.pdf", ctemp);
      else if(direction == 2)
         sprintf(exportname, "%s_ydir_focalpoint.pdf", ctemp);
      gCanvas->SaveAs(exportname);
   }
}

void TGAppMainFrame::RunMeas(void *ptr, int runCase, int zaxisscan)
{
   printf("Start of Run, run case %d\n", runCase);
   float progVal;

   char ctemp[256];
   char fname[256];

   remove_ext((char*)fileName->GetText(), ctemp);
//   printf("Save name: %s\nNo extension: %s\n", fileName->GetText(), ctemp);

   // Open file for writing
/*   if(runCase == 0)
   {
      sprintf(fname, "rm %s_%s", ctemp, histExtAll);
      retTemp = system(fname);
   }*/  // deleting might not be necesary due to RECREATE in root file open

   if( voltscanOn->IsOn() || surfscanOn->IsOn() )
   {
      if(zaxisscan == 0)
      {
         if(runCase < 10)
            sprintf(fname, "%s_0000%d%s", ctemp, runCase, histExt);
         else if( (runCase >= 10) && (runCase < 100) )
            sprintf(fname, "%s_000%d%s", ctemp, runCase, histExt);
         else if( (runCase >= 100) && (runCase < 1000) )
            sprintf(fname, "%s_00%d%s", ctemp, runCase, histExt);
         else if( (runCase >= 1000) && (runCase < 10000) )
            sprintf(fname, "%s_0%d%s", ctemp, runCase, histExt);
         else if( (runCase >= 10000) && (runCase < 100000) )
            sprintf(fname, "%s_%d%s", ctemp, runCase, histExt);
      }
      else if(zaxisscan == 1)
      {
         if(runCase < 10)
            sprintf(fname, "%s_z%d_0000%d%s", ctemp, (int)zPos->GetNumber(), runCase, histExt);
         else if( (runCase >= 10) && (runCase < 100) )
            sprintf(fname, "%s_z%d_000%d%s", ctemp, (int)zPos->GetNumber(), runCase, histExt);
         else if( (runCase >= 100) && (runCase < 1000) )
            sprintf(fname, "%s_z%d_00%d%s", ctemp, (int)zPos->GetNumber(), runCase, histExt);
         else if( (runCase >= 1000) && (runCase < 10000) )
            sprintf(fname, "%s_z%d_0%d%s", ctemp, (int)zPos->GetNumber(), runCase, histExt);
         else if( (runCase >= 10000) && (runCase < 100000) )
            sprintf(fname, "%s_z%d_0%d%s", ctemp, (int)zPos->GetNumber(), runCase, histExt);
      }
   }
   else if( !voltscanOn->IsOn() && !surfscanOn->IsOn() )
      sprintf(fname, "%s%s", ctemp, histExt);
//   printf("Rootfile: %s\n", fname);

   // Check if set voltage is below the hard limit
   if( vOut->GetNumber() > vHardlimit->GetNumber() )
   {
      printf("Voltage hard limit triggered (%lf > %lf)!\n", vOut->GetNumber(), vHardlimit->GetNumber() );
      vOut->SetNumber( vHardlimit->GetNumber() );
   }

   outroot = new TFile(fname, "RECREATE");

   TTree *header_data = new TTree("header_data", "Header information for the measurement.");
   TTree *meas_data = new TTree("meas_data", "Saved measurement data.");

   // Branches for the header
   header_data->Branch("nrch", &evtheader.nrch, "nrch/I");
   header_data->Branch("timestamp", &evtheader.timestamp, "timestamp/I");
   header_data->Branch("biasvolt", &evtheader.biasvolt, "biasvolt/D");
   header_data->Branch("xpos", &evtheader.xpos, "xpos/I");
   header_data->Branch("ypos", &evtheader.ypos, "ypos/I");
   header_data->Branch("zpos", &evtheader.zpos, "zpos/I");
   header_data->Branch("temperature", &evtheader.temperature, "temperature/D");
   header_data->Branch("laserinfo", &evtheader.laserinfo, "laserinfo/C");

   evtheader.nrch = (int)NCH->GetNumber()*2;
   evtheader.timestamp = (int)time(NULL);
   evtheader.biasvolt = (double)vOut->GetNumber();
   evtheader.xpos = (int)xPos->GetNumber();
   evtheader.ypos = (int)yPos->GetNumber();
   evtheader.zpos = (int)zPos->GetNumber();
   evtheader.temperature = 25.0;        // Still to do!!!
   sprintf(evtheader.laserinfo, "%s", laserInfo->GetText());

   char histtime[256];
   GetTime(evtheader.timestamp, histtime);

   printf("Save file header information:\n");
   printf("- Number of channels: %d\n", evtheader.nrch);
   printf("- Timestamp: %d (%s)\n", evtheader.timestamp, histtime);
   printf("- Bias voltage: %lf\n", evtheader.biasvolt);
   printf("- Table position (X,Y,Z): %d, %d, %d\n", evtheader.xpos, evtheader.ypos, evtheader.zpos);
   printf("- Temperature: %lf\n", evtheader.temperature);
   printf("- Laser and filter settings: %s\n", evtheader.laserinfo);

   header_data->Fill();

   // Branches for ADC and TDC data
   for(int i = 0; i < evtheader.nrch/2; i++)
   {
      sprintf(ctemp, "ADC%d", i);
      sprintf(fname, "ADC%d/I", i);
      meas_data->Branch(ctemp, &evtdata.adcdata[i], fname);

      sprintf(ctemp, "TDC%d", i);
      sprintf(fname, "TDC%d/I", i);
      meas_data->Branch(ctemp, &evtdata.tdcdata[i], fname);
   }

   int neve  = (int) evtNum->GetNumber();
   int allEvt, zProg;
   zProg = 1;

#if WORKSTAT == 'I'
#else
// ONLY FOR TESTING!
   TRandom *randNum = new TRandom();
   randNum->SetSeed(0);
// ONLY FOR TESTING!
#endif

   if (gDaq)
   {
      gDaq->fStop=0;
      // Start gathering
      gDaq->start();

      busyLabel->Enable();

      for (int n=0;n<neve && !gDaq->fStop ;/*n++*/)
      {
         int nb = gDaq->event(gBuf,BSIZE);

#if WORKSTAT == 'I'
#else
// ONLY FOR TESTING!
         for(int i=0; i < evtheader.nrch; i++)
         {
            if(i == 1)
               gBuf[i] = randNum->Gaus(1500,300);
            else if(i == 0)
               gBuf[i] = randNum->Poisson(2500);
         }
// ONLY FOR TESTING!
#endif
         if (nb<=0) n--;

         int nc=0;

         while ( (nb>0) && (n<neve) )
         {
            for(int i = 0; i < evtheader.nrch; i++)
            {
               unsigned short adc = gBuf[i+nc]&0xFFFF;
               if(i % 2 == 0)           // TDC
                  evtdata.tdcdata[i/2] = (int)adc;
               else if(i % 2 == 1)      // ADC
                  evtdata.adcdata[i/2] = (int)adc;
            }
            meas_data->Fill();
            
            n++;
            nc += evtheader.nrch;
            nb -= evtheader.nrch;
         }

         MyTimer();
         allEvt = n;
         if (gSystem->ProcessEvents()) printf("Run Interrupted\n");

         if( (started) && (n == (neve*zProg)/10) )
         {
            progVal = (float)zProg*10;
            curProgress->SetPosition(progVal);
            zProg++;
         }
      }

      printf("Number of gathered events: %d\n", allEvt);
      measStart->SetText("Start acquisition");
      started = kFALSE;

      gDaq->stop();
   }

   busyLabel->Disable();
   printf("End of Run neve=%d\n",neve);

   header_data->Write();
   meas_data->Write();
   delete header_data;
   delete meas_data;

   outroot->Close();
}

// Start the acquisition
void TGAppMainFrame::StartAcq()
{
   // Determine the type of measurement to perform
   int vscan = 0, pscan = 0, zscan = 0;
   if(voltscanOn->IsOn()) vscan = 1;
   if(surfscanOn->IsOn()) pscan = 1;
   if(zscanOn->IsOn()) zscan = 1;

   char cmd[256];
   int i, j, k;
   float progVal;
   FILE *pfin;

   // Variables for voltage scan
   float currentVoltage, minVoltage, maxVoltage, stepVoltage;
   int repetition;

   // Variables for surface scan
   int minXpos, maxXpos, stepXpos;
   int minYpos, maxYpos, stepYpos;
   int minZpos, maxZpos, stepZpos;
   int repetX, repetY, repetZ;

   // Voltage scan
   if( (vscan == 1) && (pscan == 0) )
   {
      if(started)
      {
         printf("Stopping current voltage scan...\n");
         gROOT->SetInterrupt();
         measStart->SetText("Start acquisition");
         started = kFALSE;

         pfin = fopen("finish_sig.txt","w");
         fprintf(pfin, "%s: Voltage scan stopped.", timeStamp->GetText());
         fclose(pfin);
      }
      else if(!started)
      {
         measStart->SetText("Stop acquisition");
         started = kTRUE;

         printf("Running a voltage scan...\n");
      
         minVoltage = vOutStart->GetNumber();
         maxVoltage = vOutStop->GetNumber();
         stepVoltage = vOutStep->GetNumber();
    
         if(stepVoltage == 0.)
            repetition = 1;
         else
            repetition = ((maxVoltage - minVoltage)/stepVoltage)+1;
    
         for(i=0; i < repetition; i++)
         {
            progVal = (float)(100.00/repetition)*i;
            curProgress->SetPosition(progVal);
        
            fflush(stdout);
            currentVoltage = minVoltage + stepVoltage*i;
            sprintf(cmd, "%s/mpod/mpod_voltage.sh -o %d -v %f -s 1", rootdir, GetChannel(), currentVoltage);
#if WORKSTAT == 'I'
            retTemp = system(cmd);
#else
            printf("Cmd: %s\n",cmd);
#endif
            fflush(stdout);
        
            printf("Waiting for voltage change...\n");
            sleep(5);
            vOut->SetNumber(currentVoltage);
            printf("Continuing...\n");
        
            // Here comes function to start histogramming <<<<<<<<<<<<<<<<<<<<<<<<
            RunMeas((void*)0, i, 0);
            fflush(stdout);
         }
        
         // Set output back to off
         fflush(stdout);
         printf("Measurement finished, returning to starting voltage...\n");
         sprintf(cmd, "%s/mpod/mpod_voltage.sh -o %d -v %f -s 1", rootdir, GetChannel(), minVoltage);
         vOut->SetNumber(minVoltage);
#if WORKSTAT == 'I'
         retTemp = system(cmd);
#else
         printf("Cmd: %s\n",cmd);
#endif
         fflush(stdout);
        
         progVal = 100.00;
         curProgress->SetPosition(progVal);
         printf("\n");

         pfin = fopen("finish_sig.txt","w");
         fprintf(pfin, "%s: Voltage scan finished.", timeStamp->GetText());
         fclose(pfin);
      }
   }
   // Surface scan
   else if( (pscan == 1) && (vscan == 0) )
   {
      minXpos = xPosMin->GetNumber();
      maxXpos = xPosMax->GetNumber();
      stepXpos = xPosStep->GetNumber();
      minYpos = yPosMin->GetNumber();
      maxYpos = yPosMax->GetNumber();
      stepYpos = yPosStep->GetNumber();
      minZpos = zPosMin->GetNumber();
      maxZpos = zPosMax->GetNumber();
      stepZpos = zPosStep->GetNumber();

      if(zscan == 1)
      {
         if(stepZpos == 0.) repetZ = 1;
         else repetZ = ((maxZpos - minZpos)/stepZpos)+1;
      }
      else
      {
         minZpos = zPos->GetNumber();
         repetZ = 1;
      }

      if(stepXpos == 0.) repetX = 1;
      else repetX = ((maxXpos - minXpos)/stepXpos)+1;
      if(stepYpos == 0.) repetY = 1;
      else repetY = ((maxYpos - minYpos)/stepYpos)+1;

      for(k=0; k < repetZ; k++)
      {
         fflush(stdout);
         // Y-axis change
         sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 3 -v %d -s la && %s/MIKRO/mikro_ctrl -n 3 -c m", rootdir, minZpos + stepZpos*k, rootdir);
#if WORKSTAT == 'I'
         retTemp = system(cmd);
#else
         printf("Cmd: %s\n",cmd);
#endif
         fflush(stdout);
     
         printf("Next Z position...\n");
         zPos->SetNumber(minZpos + stepZpos*k);
         fflush(stdout);
     
         for(j=0; j < repetY; j++)
         {
            fflush(stdout);
            // Y-axis change
            sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 2 -v %d -s la && %s/MIKRO/mikro_ctrl -n 2 -c m", rootdir, minYpos + stepYpos*j, rootdir);
#if WORKSTAT == 'I'
            retTemp = system(cmd);
#else
            printf("Cmd: %s\n",cmd);
#endif
            fflush(stdout);
     
            sleep(4);
            printf("Next Y position...\n");
            yPos->SetNumber(minYpos + stepYpos*j);
            fflush(stdout);
     
            for(i=0; i < repetX; i++)
            {
               progVal = (float)(100.00/(repetX*repetY))*(j*repetX+i);
               curProgress->SetPosition(progVal);
     
               // X-axis change
               sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 1 -v %d -s la && %s/MIKRO/mikro_ctrl -n 1 -c m", rootdir, minXpos + stepXpos*i, rootdir);
#if WORKSTAT == 'I'
               retTemp = system(cmd);
#else
               printf("Cmd: %s\n",cmd);
#endif
               fflush(stdout);
        
               printf("Next X position...\n");
               fflush(stdout);
     
               printf("Waiting for position change...\n");
               sleep(2);
               xPos->SetNumber(minXpos + stepXpos*i);
               printf("Continuing...\n");
     
//               for (k=0;k<(NTDCCH+NADCCH);k++) gHisto1D[k]->Reset();
//               for (k=0;k<(NTDCCH+NADCCH)/2;k++) gHisto2D[k]->Reset();
     
               // Here comes function to start histogramming <<<<<<<<<<<<<<<<<<<<<<<<
               RunMeas((void*)0, (j*repetX + i), zscan );
     
               fflush(stdout);
            }
     
            printf("\n");
         }
      }

      fflush(stdout);
      printf("Measurement finished, returning to starting position...\n");
      // X-axis return
      sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 1 -v %d -s la && %s/MIKRO/mikro_ctrl -n 1 -c m", rootdir, minXpos, rootdir);
#if WORKSTAT == 'I'
      retTemp = system(cmd);
#else
      printf("Cmd: %s\n",cmd);
#endif
      fflush(stdout);

      // Y-axis return
      sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 2 -v %d -s la && %s/MIKRO/mikro_ctrl -n 2 -c m", rootdir, minYpos, rootdir);
#if WORKSTAT == 'I'
      retTemp = system(cmd);
#else
      printf("Cmd: %s\n",cmd);
#endif

      // Z-axis return
      sprintf(cmd, "sudo %s/MIKRO/mikro_ctrl -n 3 -v %d -s la && %s/MIKRO/mikro_ctrl -n 3 -c m", rootdir, minZpos, rootdir);
#if WORKSTAT == 'I'
      retTemp = system(cmd);
#else
      printf("Cmd: %s\n",cmd);
#endif
      xPos->SetNumber(minXpos);
      yPos->SetNumber(minYpos);
      zPos->SetNumber(minZpos);

      progVal = 100.00;
      curProgress->SetPosition(progVal);
      printf("\n");

      pfin = fopen("finish_sig.txt","w");
      fprintf(pfin, "%s: Surface scan finished.", timeStamp->GetText());
      fclose(pfin);
   }
   // Normal single measurement
   else if( (vscan == 0) && (pscan == 0) )
   {
      // Set the start button to stop and enable stopping of measurement
      if(started)
      {
         printf("Stopping current single scan...\n");
         gROOT->SetInterrupt();
//         gDaq->fStop=1;
         measStart->SetText("Start acquisition");
         started = kFALSE;
      }
      else if(!started)
      {
         measStart->SetText("Stop acquisition");
         started = kTRUE;

         printf("Running a single scan...\n");
         RunMeas((void*)0, 0, 0);
         printf("Measurement finished...\n");
         printf("\n");
      }
   }
}

// File browser for opening histograms
void TGAppMainFrame::SelectDirectory()
{
   int i = fileList->GetNumberOfEntries();

   TGFileInfo file_info;
   const char *filetypes[] = {"Histograms",histExtAll,0,0};
   file_info.fFileTypes = filetypes;
   file_info.fIniDir = StrDup("./results");
   file_info.fMultipleSelection = kTRUE;
   new TGFileDialog(gClient->GetDefaultRoot(), fMain, kFDOpen, &file_info);

   TList *files = file_info.fFileNamesList;
   if(files)
   {
      TSystemFile *file;
      TString fname;
      TIter next(files);
      while(file=(TSystemFile*)next())
      {
         fname = file->GetName();
         fileList->AddEntry(fname.Data(), i);
         i++;
      }
   }
   fileList->Layout();
}

// File browser for selecting the save file
void TGAppMainFrame::SaveFile()
{
   TGFileInfo file_info;
   const char *filetypes[] = {"Histograms",histExtAll,0,0};
   file_info.fFileTypes = filetypes;
   file_info.fIniDir = StrDup("./results");
   new TGFileDialog(gClient->GetDefaultRoot(), fMain, kFDSave, &file_info);

   fileName->SetText(file_info.fFilename);
}

// Toggle multiple selection in filelist
void TGAppMainFrame::ListMultiSelect()
{
   fileList->SetMultipleSelections((multiSelect->IsOn()));

   if(multiSelectAll->IsDown())
      multiSelectAll->SetState(kButtonUp);
}

// Select all entries in filelist
void TGAppMainFrame::ListSelectAll()
{
   if(multiSelectAll->IsDown())
   {
      multiSelect->SetState(kButtonDown);
      fileList->SetMultipleSelections((multiSelect->IsOn()));
      for(int i = 0; i < fileList->GetNumberOfEntries(); i++) 
         fileList->Select(i,kTRUE);
   }
   else if(!multiSelectAll->IsDown())
   {
      multiSelect->SetState(kButtonUp);
      fileList->SetMultipleSelections((multiSelect->IsOn()));
      for(int i = 0; i < fileList->GetNumberOfEntries(); i++) 
         fileList->Select(i,kFALSE);
   }
}

// Navigation buttons for the filelist (<<, >>) and double click
void TGAppMainFrame::FileListNavigation(int pn)
{
   unsigned int nrfiles = fileList->GetNumberOfEntries();
   int curSel;
   TList *files;
   if( nrfiles > 0 )
   {
      if(pn < -1)
      {
         if(multiSelect->IsOn())
         {
            // turn off multiple selection and select first file on list
            fileList->SetMultipleSelections(kFALSE);
            multiSelect->SetState(kButtonUp);
            multiSelectAll->SetState(kButtonUp);

            fileList->Select(0,kTRUE);
         }
         else
         {
            // if nothing is selected, curSel will be -1
            curSel = fileList->GetSelected();
            // go to next file on list
            if(pn == -3)
            {
               if( (curSel == (int)(nrfiles-1)) || (curSel == -1) )
                  fileList->Select(0);
               else
                  fileList->Select(curSel+1);
            }
            // go to previous file on list
            else if(pn == -2)
            {
               if( (curSel == 0) || (curSel == -1) )
                  fileList->Select(nrfiles-1);
               else
                  fileList->Select(curSel-1);
            }
         }
      }

      // check the newly selected file/files and return its name/their names
      files = new TList();
      fileList->GetSelectedEntries(files);
      if(files)
      {
         for(int i = 0; i < (int)nrfiles; i++)
         {
            if(files->At(i))
            {
               if(debugSig)
                  printf("Filename: %s\n", files->At(i)->GetTitle());
               if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DADC) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 0);
               else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DTDC) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 1);
               else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_2D) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 2);
            }
         }
      }

      // Still need to include drawing of histograms we move to!!!
   }
}

// Display the currently selected histogram in file list
void TGAppMainFrame::DisplayHistogram(char* histfile, int histtype)
{
   if(debugSig)
      printf("Selected file: %s\n", histfile);

   TCanvas *gCanvas = histCanvas->GetCanvas();

   inroot = new TFile(histfile, "READ");

   TTree *header_data, *meas_data;
   inroot->GetObject("header_data", header_data);
   inroot->GetObject("meas_data", meas_data);

   // Reading the header
   header_data->SetBranchAddress("nrch", &evtheader.nrch);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("timestamp", &evtheader.timestamp);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("biasvolt", &evtheader.biasvolt);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("xpos", &evtheader.xpos);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("ypos", &evtheader.ypos);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("zpos", &evtheader.zpos);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("temperature", &evtheader.temperature);
   header_data->GetEntry(0);
   header_data->SetBranchAddress("laserinfo", &evtheader.laserinfo);
   header_data->GetEntry(0);

   char histtime[256];
   GetTime(evtheader.timestamp, histtime);

   if(debugSig)
   {
      printf("Opened file header information:\n");
      printf("- Number of channels: %d\n", evtheader.nrch);
      printf("- Timestamp: %d (%s)\n", evtheader.timestamp, histtime);
      printf("- Bias voltage: %lf\n", evtheader.biasvolt);
      printf("- Table position (X,Y,Z): %d, %d, %d\n", evtheader.xpos, evtheader.ypos, evtheader.zpos);
      printf("- Temperature: %lf\n", evtheader.temperature);
      printf("- Laser and filter settings: %s\n", evtheader.laserinfo);
   }

   int j;
   char rdc[256];
   char rdcsel[256];

   j = selectCh->GetNumber();

   printf("Found %d data points.\n", (int)meas_data->GetEntries());

   gCanvas->cd();
   double range[4];
   range[0] = adcMinRange->GetNumber();
   range[1] = adcMaxRange->GetNumber();
   range[2] = tdcMinwindow->GetNumber();
   range[3] = tdcMaxwindow->GetNumber();

   if(histtype == 0)
   {
      if( range[0] == range[1] )
         sprintf(rdc, "ADC%d>>%s", j, histname);
      else
         sprintf(rdc, "ADC%d>>%s(%d,%lf,%lf)", j, histname, (int)(range[1]-range[0]), range[0]-0.5, range[1]-0.5);

      sprintf(rdcsel, "(TDC%d>%lf)&&(TDC%d<%lf)", j, range[2]*tdctimeconversion, j, range[3]*tdctimeconversion);
      meas_data->Draw(rdc, rdcsel);

      sprintf(rdc, "ADC%d, Vbias=%.3lf, TDC=(%.2lf,%.2lf);ADC;", j, evtheader.biasvolt, range[2], range[3]);
      TH1F *histtemp = (TH1F*)gCanvas->GetPrimitive(histname);
      if(!cleanPlots)
         histtemp->SetTitle(rdc);
      else
         histtemp->SetTitle(";ADC;");
      histtemp->GetXaxis()->SetLabelSize(0.025);
      histtemp->GetXaxis()->CenterTitle(kTRUE);
      histtemp->GetYaxis()->SetLabelSize(0.025);
      if(cleanPlots)
      {
         TGaxis *yax = (TGaxis*)histtemp->GetYaxis();
         yax->SetMaxDigits(4);
      }

      gCanvas->Modified();
      gCanvas->Update();

      if( yMinRange->GetNumber() != yMaxRange->GetNumber() )
      {
         if( (logscale->IsDown()) && (yMinRange->GetNumber() <= 0) )
         {
            histtemp->GetYaxis()->SetRangeUser(0.5, yMaxRange->GetNumber());
            yMinRange->SetNumber(0.5);
            logchange = 1;
         }
         else
         {
            gCanvas->SetLogy(kFALSE);
            if(logchange == 1)
            {
               yMinRange->SetNumber(0.0);
               logchange = 0;
            }
            histtemp->GetYaxis()->SetRangeUser(yMinRange->GetNumber(), yMaxRange->GetNumber());
         }
      }

      TPaveStats *stats = (TPaveStats*)histtemp->FindObject("stats");
      if(!cleanPlots)
      {
         stats->SetX1NDC(0.84); stats->SetX2NDC(0.97);
         stats->SetY1NDC(0.87); stats->SetY2NDC(0.97);
      }
      else
      {
         stats->SetX1NDC(1.1); stats->SetX2NDC(1.3);
         stats->SetY1NDC(1.1); stats->SetY2NDC(1.3);
      }
   }
   else if(histtype == 1)
   {
      if( range[0] == range[1] )
         sprintf(rdc, "(TDC%d/%lf)>>%s", j, tdctimeconversion, histname);
      else
         sprintf(rdc, "(TDC%d/%lf)>>%s(%d,%lf,%lf)", j, tdctimeconversion, histname, (int)((range[3]-range[2])*tdctimeconversion), range[2], range[3]);
      sprintf(rdcsel, "(TDC%d>%lf)&&(TDC%d<%lf)", j, range[2]*tdctimeconversion, j, range[3]*tdctimeconversion);
      meas_data->Draw(rdc, rdcsel);

      sprintf(rdc, "TDC%d, Vbias=%.3lf, TDC=(%.2lf,%.2lf);Time (TDC channel) [ns];", j, evtheader.biasvolt, range[2], range[3]);
      TH1F *histtemp = (TH1F*)gCanvas->GetPrimitive(histname);
      if(!cleanPlots)
         histtemp->SetTitle(rdc);
      else
         histtemp->SetTitle(";Time (TDC channel) [ns];");
      histtemp->GetXaxis()->SetLabelSize(0.025);
      histtemp->GetXaxis()->CenterTitle(kTRUE);
      histtemp->GetYaxis()->SetLabelSize(0.025);
      if(cleanPlots)
      {
         TGaxis *yax = (TGaxis*)histtemp->GetYaxis();
         yax->SetMaxDigits(4);
      }

      gCanvas->Modified();
      gCanvas->Update();

      if( yMinRange->GetNumber() != yMaxRange->GetNumber() )
      {
         if( (logscale->IsDown()) && (yMinRange->GetNumber() <= 0) )
         {
            histtemp->GetYaxis()->SetRangeUser(0.5, yMaxRange->GetNumber());
            yMinRange->SetNumber(0.5);
            logchange = 1;
         }
         else
         {
            gCanvas->SetLogy(kFALSE);
            if(logchange == 1)
            {
               yMinRange->SetNumber(0.0);
               logchange = 0;
            }
            histtemp->GetYaxis()->SetRangeUser(yMinRange->GetNumber(), yMaxRange->GetNumber());
         }
      }

      TPaveStats *stats = (TPaveStats*)histtemp->FindObject("stats");
      if(!cleanPlots)
      {
         stats->SetX1NDC(0.84); stats->SetX2NDC(0.97);
         stats->SetY1NDC(0.87); stats->SetY2NDC(0.97);
      }
      else
      {
         stats->SetX1NDC(1.1); stats->SetX2NDC(1.3);
         stats->SetY1NDC(1.1); stats->SetY2NDC(1.3);
      }
   }
   else if(histtype == 2)
   {
      if( ((range[0] == range[1]) && (range[2] == range[3])) || (range[2] == range[3]) || (range[0] == range[1]) )
         sprintf(rdc, "(TDC%d/%lf):ADC%d>>%s", j, tdctimeconversion, j, histname);
      else
         sprintf(rdc, "(TDC%d/%lf):ADC%d>>%s(%d,%lf,%lf,%d,%lf,%lf)", j, tdctimeconversion, j, histname, (int)(range[1]-range[0])/2, range[0]-0.5, range[1]-0.5, (int)((range[3]-range[2])*tdctimeconversion)/2, range[2], range[3]);
      meas_data->Draw(rdc,"","COLZ");

      sprintf(rdc, "ADC/TDC%d, Vbias=%.3lf, TDC=(%.2lf,%.2lf);ADC;TDC", j, evtheader.biasvolt, range[2], range[3]);
      TH2F *histtemp = (TH2F*)gCanvas->GetPrimitive(histname);
      if(!cleanPlots)
         histtemp->SetTitle(rdc);
      else
         histtemp->SetTitle(";ADC;Time (TDC channel) [ns]");
      histtemp->GetXaxis()->SetLabelSize(0.025);
      histtemp->GetXaxis()->CenterTitle(kTRUE);
      histtemp->GetYaxis()->SetLabelSize(0.025);
      histtemp->GetYaxis()->CenterTitle(kTRUE);
      histtemp->GetYaxis()->SetTitleOffset(1.35);
      if(cleanPlots)
      {
         TGaxis *yax = (TGaxis*)histtemp->GetYaxis();
         yax->SetMaxDigits(4);
      }

      gCanvas->Modified();
      gCanvas->Update();

      TPaveStats *stats = (TPaveStats*)histtemp->FindObject("stats");
//      stats->SetOptStat(0);
      stats->SetX1NDC(1.1); stats->SetX2NDC(1.3);
      stats->SetY1NDC(1.1); stats->SetY2NDC(1.3);

      TPaletteAxis *gpalette = (TPaletteAxis*)histtemp->GetListOfFunctions()->FindObject("palette");
      gpalette->SetLabelSize(0.022);
   }

   if(histtype < 2)
   {
      if( logscale->IsDown() )
         gCanvas->SetLogy(kTRUE);
      else if( !logscale->IsDown() )
         gCanvas->SetLogy(kFALSE);
   }
   else
      gCanvas->SetLogy(kFALSE);

   gCanvas->Modified();
   gCanvas->Update();

   // If you close the opened file, the data can't be accessed by other functions
}

// Create a 2D surface plot and plot it
void TGAppMainFrame::MakeSurfPlot(TList *files)
{
   unsigned int nrfiles = fileList->GetNumberOfEntries();
   int j, k = 0, m = 0, n = 0;
   char ctemp[256];
   TCanvas *gCanvas = histCanvas->GetCanvas();
   TTree *header_data, *meas_data;
   double *integralCount;
   double *surfx, *surfy;
   double xsurfmin = 0, ysurfmin = 0;
   integralCount = new double[nrfiles];
   for(int i = 0; i < (int)nrfiles; i++) integralCount[i] = 0;
   surfx = new double[nrfiles];
   surfy = new double[nrfiles];
   int nrentries;
   TGraph2D *gScan2D;
   gScan2D = new TGraph2D();

/*   int zProg = 0;
   float progVal;
   curProgress->SetPosition(zProg);*/

   char exportname[256];
   
   if(multiSelect->IsOn())
   {
      printf("Creating a surface plot. Please wait...\n");
      fileList->GetSelectedEntries(files);
      if(files)
      {
         busyLabel->Enable();

         for(int i = 0; i < (int)nrfiles; i++)
         {
            if(files->At(i))
            {
               n++;
//               printf("Filename: %s\n", files->At(i)->GetTitle());
             
               sprintf(ctemp, "%s", files->At(i)->GetTitle());
               inroot = new TFile(ctemp, "READ");
             
               inroot->GetObject("header_data", header_data);
               inroot->GetObject("meas_data", meas_data);
             
               // Reading the header
               header_data->SetBranchAddress("xpos", &evtheader.xpos);
               header_data->GetEntry(0);
               header_data->SetBranchAddress("ypos", &evtheader.ypos);
               header_data->GetEntry(0);

               char rdc[256];
               j = selectCh->GetNumber();
               double rangetdc[2];
               rangetdc[0] = tdcMinwindow->GetNumber();
               rangetdc[1] = tdcMaxwindow->GetNumber();

               k = 0;
               m = 0;
             
               // Reading the data
               for(int i = 0; i < meas_data->GetEntries(); i++)
               {
                  sprintf(rdc, "ADC%d", j);
                  meas_data->SetBranchAddress(rdc, &evtdata.adcdata[j]);
                  meas_data->GetEntry(i);
             
                  sprintf(rdc, "TDC%d", j);
                  meas_data->SetBranchAddress(rdc, &evtdata.tdcdata[j]);
                  meas_data->GetEntry(i);

                  // If our data point is inside the TDC window
                  if( ((double)evtdata.tdcdata[j]/tdctimeconversion >= rangetdc[0]) && ((double)evtdata.tdcdata[j]/tdctimeconversion <= rangetdc[1]) )
                  {
                     k++;
                     m += evtdata.adcdata[j];
                  }
               }

               integralCount[n-1] += ((double)m)/((double)k);
               if(n == 1)
               {
                  xsurfmin = evtheader.xpos;
                  ysurfmin = evtheader.ypos;
               }
               surfx[n-1] = (double)(evtheader.xpos-xsurfmin)*lenconversion;
               surfy[n-1] = (double)(evtheader.ypos-ysurfmin)*lenconversion;

/*             if( n == (((files->GetSize())*zProg)/20)+1 ) // divide by 20 because files->GetSize() gives a double value of the files selected
               {
                  progVal = (float)n;
                  curProgress->SetPosition(progVal);
                  zProg++;
                  printf("Progress = %lf\n", progVal);
               }*/

               delete inroot;
            }
         }

         busyLabel->Disable();

         nrentries = n;
         printf("%d files were selected.\n", nrentries);

         for(int i = 0; i < nrentries; i++)
         {
//            printf("At position (%d,%d), the ADC integral is: %lf.\n", surfx[i], surfy[i], integralCount[i]);
            gScan2D->SetPoint(i, surfx[i], surfy[i], integralCount[i]);
         }
         gCanvas->cd();
         gScan2D->Draw("COLZ");

         gCanvas->Modified();
         gCanvas->Update();

         gScan2D->GetXaxis()->SetTitle("X [#mum]");
         gScan2D->GetXaxis()->CenterTitle(kTRUE);
         gScan2D->GetXaxis()->SetLabelSize(0.022);
         gScan2D->GetXaxis()->SetRangeUser(surfx[0], surfx[nrentries-1]);
//       j = 500+(int)((surfx[nrentries-1]-surfx[0])/(surfx[1]-surfx[0]));
//       if(j > 510) j = 510;
         gScan2D->GetXaxis()->SetNdivisions(510, kTRUE);
         gScan2D->GetYaxis()->SetTitle("Y [#mum]");
         gScan2D->GetYaxis()->SetTitleOffset(1.3);
         gScan2D->GetYaxis()->CenterTitle(kTRUE);
         gScan2D->GetYaxis()->SetLabelSize(0.022);
         gScan2D->GetYaxis()->SetRangeUser(surfy[0], surfy[nrentries-1]);
//       j = 500+(int)((surfy[nrentries-1]-surfy[0])/(surfy[(int)((surfx[nrentries-1]-surfx[0])/(surfx[1]-surfx[0])+1)]-surfy[0]));
//       if(j > 510) j = 510;
         gScan2D->GetYaxis()->SetNdivisions(510, kTRUE);

         TGaxis *yax = (TGaxis*)gScan2D->GetYaxis();
         yax->SetMaxDigits(4);

         if(!cleanPlots)
            gScan2D->SetTitle("Surface scan");
         else
            gScan2D->SetTitle();

//         TPaletteAxis *gpalette = (TPaletteAxis*)gScan2D->GetListOfFunctions()->FindObject("palette");
//         gpalette->SetLabelSize(0.022);

         gCanvas->Modified();
         gCanvas->Update();

         remove_from_last((char*)files->At(0)->GetTitle(), '_', ctemp);
         sprintf(exportname, "%s_surfscan.pdf", ctemp);
         gCanvas->SaveAs(exportname);
      }
   }
   else
   {
      printf("To make a 2D surface scan plot, select multiple root files.\n");
      change2Dsurf->SetDown(kFALSE);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_SURF);
   }

   delete[] surfx;
   delete[] surfy;
   delete[] integralCount;
}

// Change histogram when changing the channel
void TGAppMainFrame::ChangeChannel()
{
   unsigned int nrfiles = fileList->GetNumberOfEntries();
   TList *files;

   if( nrfiles > 0 )
   {
      // check the newly selected file/files and return its name/their names
      files = new TList();
      fileList->GetSelectedEntries(files);
      if(files)
      {
         for(int i = 0; i < (int)nrfiles; i++)
         {
            if(files->At(i))
            {
               if(debugSig)
                  printf("Filename: %s\n", files->At(i)->GetTitle());
               if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DADC) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 0);
               else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DTDC) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 1);
               else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_2D) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 2);
            }
         }
      }
   }
}

// Setting a predetermined X range
void TGAppMainFrame::SetHistRange()
{
   unsigned int nrfiles = fileList->GetNumberOfEntries();

   if(nrfiles > 0)
   {
      TList *files;
      files = new TList();
      fileList->GetSelectedEntries(files);
      if(files)
      {
         for(int i = 0; i < (int)nrfiles; i++)
         {
            if(files->At(i))
            {
               if(debugSig)
                  printf("Filename: %s\n", files->At(i)->GetTitle());
               if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DADC) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 0);
               else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DTDC) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 1);
               else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_2D) )
                  DisplayHistogram( (char*)(files->At(i)->GetTitle()), 2);
            }
         }
      }
   }
}

// Changing the histogram type to display
void TGAppMainFrame::ChangeHisttype(int type)
{
   TGTextButton *pressedB = new TGTextButton();
   int menuID = 0;
   unsigned int nrfiles = fileList->GetNumberOfEntries();

   // ADC histogram
   if(type == 0)
   {
      pressedB = changeADC;
      menuID = M_ANALYSIS_HISTTYPE_1DADC;

      changeTDC->SetDown(kFALSE);
      changeADCTDC->SetDown(kFALSE);
      change2Dsurf->SetDown(kFALSE);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_1DTDC);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_2D);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_SURF);
   }
   // TDC histogram
   else if(type == 1)
   {
      pressedB = changeTDC;
      menuID = M_ANALYSIS_HISTTYPE_1DTDC;

      changeADC->SetDown(kFALSE);
      changeADCTDC->SetDown(kFALSE);
      change2Dsurf->SetDown(kFALSE);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_1DADC);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_2D);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_SURF);
   }
   // ADC vs. TDC histogram
   else if(type == 2)
   {
      pressedB = changeADCTDC;
      menuID = M_ANALYSIS_HISTTYPE_2D;

      changeADC->SetDown(kFALSE);
      changeTDC->SetDown(kFALSE);
      change2Dsurf->SetDown(kFALSE);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_1DADC);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_1DTDC);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_SURF);
   }
   // Surface scan plot
   else if(type == 3)
   {
      pressedB = change2Dsurf;
      menuID = M_ANALYSIS_HISTTYPE_SURF;

      changeADC->SetDown(kFALSE);
      changeTDC->SetDown(kFALSE);
      changeADCTDC->SetDown(kFALSE);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_1DADC);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_1DTDC);
      fMenuHisttype->UnCheckEntry(M_ANALYSIS_HISTTYPE_2D);
   }

   if( fMenuHisttype->IsEntryChecked(menuID) )
   {
      pressedB->SetDown(kFALSE);
      fMenuHisttype->UnCheckEntry(menuID);
   }
   else if( !fMenuHisttype->IsEntryChecked(menuID) )
   {
      pressedB->SetDown(kTRUE);
      fMenuHisttype->CheckEntry(menuID);
   }

   if(nrfiles > 0)
   {
      // Still need to add the switch!!!
      TList *files;
      files = new TList();
      fileList->GetSelectedEntries(files);

      if(type < 3)
         DisplayHistogram( (char*)(files->At(0)->GetTitle()), type);
      else if(type == 3)
         MakeSurfPlot( files );
   }
}

// Changing the histogram type to display
void TGAppMainFrame::HistogramExport()
{
   unsigned int nrfiles = fileList->GetNumberOfEntries();
   TList *files;
   TCanvas *gCanvas = histCanvas->GetCanvas();
   
   char exportname[256];
   char ctemp[256];

   if(nrfiles > 0)
   {
      files = new TList();
      fileList->GetSelectedEntries(files);
      if(files)
      {
         if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_SURF) ) // for the surface scan, the plot from all selected files is already created
         {
            remove_from_last((char*)files->At(0)->GetTitle(), '_', ctemp);
            sprintf(exportname, "%s_surfscan.pdf", ctemp);
            gCanvas->SaveAs(exportname);
         }
         else
         {
            for(int i = 0; i < (int)nrfiles; i++)
            {
               if(files->At(i))
               {
                  remove_ext((char*)files->At(i)->GetTitle(), ctemp);
     
                  if(debugSig)
                     printf("Filename: %s\n", files->At(i)->GetTitle());
                  if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DADC) )
                  {
                     sprintf(exportname, "%s_adc%d.pdf", ctemp, (int)selectCh->GetNumber());
                     DisplayHistogram( (char*)(files->At(i)->GetTitle()), 0);
                  }
                  else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DTDC) )
                  {
                     sprintf(exportname, "%s_tdc%d.pdf", ctemp, (int)selectCh->GetNumber());
                     DisplayHistogram( (char*)(files->At(i)->GetTitle()), 1);
                  }
                  else if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_2D) )
                  {
                     sprintf(exportname, "%s_adctdc%d.pdf", ctemp, (int)selectCh->GetNumber());
                     DisplayHistogram( (char*)(files->At(i)->GetTitle()), 2);
                  }
     
                  gCanvas->SaveAs(exportname);
               }
            }
         }
      }
   }
}

//---------------------------------------------------------------
// Main window constructor definition (& layout)

TGAppMainFrame::TGAppMainFrame(const TGWindow *p, int w, int h)
{
   gDaq = new daq();
   gScopeDaq = new daqscope();

   // Define the main window and menubar
   fMain = new TGMainFrame(p, w, h, kVerticalFrame);    // vertical frame split into menubar and main frame
   fMenuBar = new TGMdiMenuBar(fMain, 10, 10);          // just prepare menubar, draw it with InitMenu()
   fMain->AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX));

   // Define the main frame where opened subwindows will appear
   fMainFrame = new TGMdiMainFrame(fMain, fMenuBar, 300, 300);
   fMain->AddFrame(fMainFrame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));

   // Initialize the menubar the initial measurement layout subwindows and display the main window
   InitMenu();
   MeasurementLayout();
   fMain->SetWindowName(WINDOW_NAME);
   fMain->MapSubwindows();
   fMain->MapWindow();
   fMain->Layout();
   GetPosition();
   GetVoltOut();
}

//---------------------------------------------------------------
// Event handler for menubar actions

void TGAppMainFrame::HandleMenu(Int_t id)
{
   TList *files;

   switch (id) {
      case M_FILE_NEW:
         // Clear any values and histogram
         break;

      case M_FILE_EXIT:
         CloseWindow();
         break;

      case M_ANALYSIS_HISTTYPE_1DADC:
         // Toggles the ADC button
         ChangeHisttype(0);
         break;

      case M_ANALYSIS_HISTTYPE_1DTDC:
         ChangeHisttype(1);
         break;

      case M_ANALYSIS_HISTTYPE_2D:
         ChangeHisttype(2);
         break;

      case M_ANALYSIS_HISTTYPE_SURF:
         ChangeHisttype(3);
         break;

      case M_ANALYSIS_FIT:
         // Fit spectrum
         files = new TList();
         fileList->GetSelectedEntries(files);

         if( fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DADC) && (files->GetSize() > 0) )
            FitSpectrum(files, 1);
         break;

      case M_ANALYSIS_FITSEL:
         // Fit all spectra
         files = new TList();
         fileList->GetSelectedEntries(files);

         if( (fMenuHisttype->IsEntryChecked(M_ANALYSIS_HISTTYPE_1DADC)) && (files->GetSize() > 1) )
            FitSpectrum(files, files->GetSize());
         break;

      case M_ANALYSIS_INTEGX:
         // Integrate the current spectra
         files = new TList();
         fileList->GetSelectedEntries(files);

         IntegSpectrum(files, 1);
         break;

      case M_ANALYSIS_INTEGY:
         // Integrate the current spectra
         files = new TList();
         fileList->GetSelectedEntries(files);

         IntegSpectrum(files, 2);
         break;

      case M_WINDOW_HOR:
         fMainFrame->TileHorizontal();
         break;

      case M_WINDOW_VERT:
         fMainFrame->TileVertical();
         break;

      case M_HELP_ABOUT:
         About();
         break;

      default:
         fMainFrame->SetCurrent(id);
         break;
   }
}

//---------------------------------------------------------------
// Initialize the main window menu

void TGAppMainFrame::InitMenu()
{
   fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0);

   // Popup menu in menubar for File controls
   fMenuFile = new TGPopupMenu(gClient->GetRoot());     // adds a new popup menu to the menubar
   fMenuFile->AddEntry(new TGHotString("&New Measurement"), M_FILE_NEW);
   fMenuFile->AddSeparator();
   fMenuFile->AddEntry(new TGHotString("E&xit"), M_FILE_EXIT);

   // Popup menu in menubar for Analysis controls
   fMenuHisttype = new TGPopupMenu(gClient->GetRoot()); // adds a cascade menu that will be incorporated into analysis controls
   fMenuHisttype->AddEntry(new TGHotString("1D &ADC histogram"), M_ANALYSIS_HISTTYPE_1DADC);
   fMenuHisttype->AddEntry(new TGHotString("1D &TDC histogram"), M_ANALYSIS_HISTTYPE_1DTDC);
   fMenuHisttype->AddEntry(new TGHotString("&2D ADC vs. TDC histogram"), M_ANALYSIS_HISTTYPE_2D);
   fMenuHisttype->AddEntry(new TGHotString("2D &surface scan plot"), M_ANALYSIS_HISTTYPE_SURF);

   fMenuAnalysis = new TGPopupMenu(gClient->GetRoot()); // adds a new popup menu to the menubar
   fMenuAnalysis->AddPopup(new TGHotString("&Histogram type"), fMenuHisttype);

   fMenuAnalysis->AddEntry(new TGHotString("&Fit spectrum"), M_ANALYSIS_FIT);
   fMenuAnalysis->AddEntry(new TGHotString("Fit &all selected"), M_ANALYSIS_FITSEL);
   fMenuAnalysis->AddEntry(new TGHotString("Integrate spectrum (&X direction)"), M_ANALYSIS_INTEGX);
   fMenuAnalysis->AddEntry(new TGHotString("Integrate spectrum (&Y direction)"), M_ANALYSIS_INTEGY);

   // Popup menu in menubar for Window controls
   fMenuWindow = new TGPopupMenu(gClient->GetRoot());   // adds a new popup menu to the menubar
   fMenuWindow->AddEntry(new TGHotString("Tile &Horizontally"), M_WINDOW_HOR);
   fMenuWindow->AddEntry(new TGHotString("Tile &Vertically"), M_WINDOW_VERT);
   fMenuWindow->AddPopup(new TGHotString("&Windows"), fMainFrame->GetWinListMenu());

   // Popup menu in menubar for Help controls
   fMenuHelp = new TGPopupMenu(gClient->GetRoot());
   fMenuHelp->AddEntry(new TGHotString("&About"), M_HELP_ABOUT);

   // Connect all menu items with actions - handled by HandleMenu()
   fMenuFile->Connect("Activated(Int_t)", "TGAppMainFrame", this, "HandleMenu(Int_t)");
   fMenuAnalysis->Connect("Activated(Int_t)", "TGAppMainFrame", this, "HandleMenu(Int_t)");
   fMenuWindow->Connect("Activated(Int_t)", "TGAppMainFrame", this, "HandleMenu(Int_t)");
   fMenuHelp->Connect("Activated(Int_t)", "TGAppMainFrame", this, "HandleMenu(Int_t)");

   // Draw the created popup menus on the menubar
   fMenuBar->AddPopup(new TGHotString("&File"), fMenuFile, fMenuBarItemLayout);
   fMenuBar->AddPopup(new TGHotString("&Analysis"),fMenuAnalysis,fMenuBarItemLayout);
   fMenuBar->AddPopup(new TGHotString("&Windows"),fMenuWindow,fMenuBarItemLayout);
   fMenuBar->AddPopup(new TGHotString("&Help"), fMenuHelp, fMenuBarItemLayout);
}

//---------------------------------------------------------------
// Set the measurement subwindow layout

void TGAppMainFrame::MeasurementLayout()
{
   TGMdiFrame *mdiFrame;

   // Generic horizontal and vertical frames
   TGHorizontalFrame *fH1, *fH2, *fH3;
   TGVerticalFrame *fV1;
   TGGroupFrame *fG1;
   TGLabel *lab;
   TGCompositeFrame *fT1;

   // Sizes of internal group and subwindow structures
   int subwin[2];
   int subgroup[2];

// Settings pane ---------------------------------------------------------------------------
   subwin[0] = (winWidth/6)-5; subwin[1] = 3*((winHeight/5)-5)-10;
   settingsPane = new TGMdiSubwindow(fMainFrame, subwin[0], subwin[1]);
   mdiFrame = settingsPane->GetMdiFrame();

   // Check button to toggle voltage scan
   voltscanOn = new TGCheckButton(mdiFrame, "Voltage scan ON/OFF");
   voltscanOn->Resize(50,22);
   voltscanOn->SetState(kButtonUp);
   mdiFrame->AddFrame(voltscanOn, f0centerx);

   // Check button to toggle surface scan
   surfscanOn = new TGCheckButton(mdiFrame, "Surface scan ON/OFF");
   surfscanOn->Resize(50,22);
   surfscanOn->SetState(kButtonUp);
   mdiFrame->AddFrame(surfscanOn, f0centerx);

   // Check button to toggle Z direction scan
   zscanOn = new TGCheckButton(mdiFrame, "Z-axis scan ON/OFF");
   zscanOn->Resize(50,22);
   zscanOn->SetState(kButtonUp);
   mdiFrame->AddFrame(zscanOn, f0centerx);

   // Check button to toggle (open) the histogram window
//   histogramOn = new TGCheckButton(mdiFrame, "Histogram display ON/OFF");
//   histogramOn->Resize(50,22);
//   histogramOn->SetState(kButtonUp);
//   mdiFrame->AddFrame(histogramOn, f0centerx);

   subgroup[0] = subwin[0]-10;
   // Hard limit for maximum voltage we can set
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   lab = new TGLabel(fH1, "Voltage limit:");
   fH1->AddFrame(lab, f0center2d);
   vHardlimit = new TGNumberEntry(fH1, 70.00, 4, 999, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber);
   vHardlimit->Resize(80,22);
   fH1->AddFrame(vHardlimit, f0center2d);
   mdiFrame->AddFrame(fH1, f2);

   // Number of used channels
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   lab = new TGLabel(fH1, "Nr. of channels:");
   fH1->AddFrame(lab, f0center2d);
   NCH = new TGNumberEntry(fH1, 1, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 1, 8);
   NCH->Resize(40,22);
   fH1->AddFrame(NCH, f0center2d);
   mdiFrame->AddFrame(fH1, f2);

   // Check button to toggle plots with additional information or clean plots
   cleanOn = new TGCheckButton(mdiFrame, "Clean plots ON/OFF");
   cleanOn->Resize(50,22);
   cleanOn->SetState(kButtonDown);
   cleanPlots = 1;
   mdiFrame->AddFrame(cleanOn, f0centerx);

   // Button and textbox to enter the oscilloscope IP address
   lab = new TGLabel(mdiFrame, "Scope IP:");
   mdiFrame->AddFrame(lab, f0);
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   oscIP = new TGTextEntry(fH1, "178.172.43.157");
   oscIP->Resize(110,22);
   fH1->AddFrame(oscIP, f0);
   oscConnect = new TGTextButton(fH1, "Connect");
   oscConnect->SetTextJustify(36);
   oscConnect->SetWrapLength(-1);
   oscConnect->Resize(60,22);
   fH1->AddFrame(oscConnect, f0);
   oscOn = 0;
   mdiFrame->AddFrame(fH1, f2);

   // Laser settings (freq., tune, ND filter)
   lab = new TGLabel(mdiFrame, "Laser settings:");
   mdiFrame->AddFrame(lab, f0);
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   laserInfo = new TGTextEntry(fH1, "kHz, tune, ND");
   fH1->AddFrame(laserInfo, f2);
   mdiFrame->AddFrame(fH1, f2);

   mdiFrame->SetMdiHints(kMdiMinimize);
   mdiFrame->SetWindowName("Settings pane");
   mdiFrame->MapSubwindows();
   mdiFrame->Layout();
   mdiFrame->Move(0,0);
// Settings pane ---------------------------------------------------------------------------

// Main window -----------------------------------------------------------------------------
   subwin[0] = 3*((winWidth/6)-5); subwin[1] = 3*((winHeight/5)-5)-10;
   mainSubwindow = new TGMdiSubwindow(fMainFrame, subwin[0], subwin[1]);
   mdiFrame = mainSubwindow->GetMdiFrame();

   // Voltage and position tab
   subgroup[0] = 2*subwin[0]/5-12;
   subgroup[1] = (subwin[1]+15)/2+5;
   setTab = new TGTab(mdiFrame, subgroup[0], subgroup[1]);
   
   fT1 = setTab->AddTab("Voltage + Position");

   fH1 = new TGHorizontalFrame(fT1, subwin[0], subgroup[1], kFixedHeight);
   // Left pane (Bias voltage controls)
   fV1 = new TGVerticalFrame(fH1, subgroup[0], subgroup[1], kFixedWidth | kFixedHeight);
   fG1 = new TGGroupFrame(fV1, "Bias voltage controls");

   // Output voltage supply channel
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "Output channel:");
   fH2->AddFrame(lab, f0center2d);
   vOutCh = new TGComboBox(fH2, 200);
   vOutCh->AddEntry("1", 0);
   vOutCh->AddEntry("2", 1);
   vOutCh->AddEntry("3", 2);
   vOutCh->AddEntry("4", 3);
   vOutCh->AddEntry("5", 4);
   vOutCh->AddEntry("6", 5);
   vOutCh->AddEntry("7", 6);
   vOutCh->AddEntry("8", 7);
   vOutCh->AddEntry("101", 8);
   vOutCh->AddEntry("102", 9);
   vOutCh->AddEntry("103", 10);
   vOutCh->AddEntry("104", 11);
   vOutCh->AddEntry("105", 12);
   vOutCh->AddEntry("106", 13);
   vOutCh->AddEntry("107", 14);
   vOutCh->AddEntry("108", 15);
   vOutCh->Resize(50,22);
   vOutCh->Select(0);
   fH2->AddFrame(vOutCh, f0center2d);
   fG1->AddFrame(fH2, f2);

   // Output voltage setting
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "Output voltage:");
   fH2->AddFrame(lab, f0center2d);
   vOut = new TGNumberEntry(fH2, 0.00, 4, 999, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, 0, vHardlimit->GetNumber());
   vOut->Resize(80,22);
   fH2->AddFrame(vOut, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   vOutOnOff = new TGCheckButton(fH2, "Output ON/OFF");
   vOutOnOff->Resize(subgroup[0]-10,22);
   vOutOnOff->SetState(kButtonUp);
   fH2->AddFrame(vOutOnOff, f0centerx);
   fG1->AddFrame(fH2, f2);

   // Set, get and reset voltage buttons
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   fH3 = new TGHorizontalFrame(fH2, subgroup[0], 30);
   vOutSet = new TGTextButton(fH3, "Set");
   vOutSet->SetTextJustify(36);
   vOutSet->SetWrapLength(-1);
   vOutSet->Resize(60,22);
   fH3->AddFrame(vOutSet, f0);
   vOutGet = new TGTextButton(fH3, "Get");
   vOutGet->SetTextJustify(36);
   vOutGet->SetWrapLength(-1);
   vOutGet->Resize(60,22);
   fH3->AddFrame(vOutGet, f0);
   vOutReset = new TGTextButton(fH3, "Reset");
   vOutReset->SetTextJustify(36);
   vOutReset->SetWrapLength(-1);
   vOutReset->Resize(60,22);
   fH3->AddFrame(vOutReset, f0);
   fH2->AddFrame(fH3, f0centerx);
   fG1->AddFrame(fH2, f2);

   // Voltage scan controls
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "V (min):");
   fH2->AddFrame(lab, f0center2d);
   vOutStart = new TGNumberEntry(fH2, 0.00, 4, 999, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber);
   vOutStart->Resize(80,22);
   fH2->AddFrame(vOutStart, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "V (max):");
   fH2->AddFrame(lab, f0center2d);
   vOutStop = new TGNumberEntry(fH2, 0.00, 4, 999, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber);
   vOutStop->Resize(80,22);
   fH2->AddFrame(vOutStop, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "V (step):");
   fH2->AddFrame(lab, f0center2d);
   vOutStep = new TGNumberEntry(fH2, 0.00, 4, 999, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEAAnyNumber);
   vOutStep->Resize(80,22);
   fH2->AddFrame(vOutStep, f0center2d);
   fG1->AddFrame(fH2, f2);

   fV1->AddFrame(fG1, f1);
   // Left pane (Bias voltage controls)
   fH1->AddFrame(fV1, f0);
   
   // Right pane (Table position controls)
   subgroup[0] = 3*subwin[0]/5-12;
   fV1 = new TGVerticalFrame(fH1, subgroup[0], subgroup[1], kFixedWidth | kFixedHeight);
   fG1 = new TGGroupFrame(fV1, "Table position controls");

   // X, Y and Z positions
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "X:");
   fH2->AddFrame(lab, f0center2d);
   xPos = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 215000);
   xPos->Resize(80,22);
   fH2->AddFrame(xPos, f0center2d);

   lab = new TGLabel(fH2, "Z (min):");
   fH2->AddFrame(lab, f0center2d);
   zPosMin = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 375000);
   zPosMin->Resize(80,22);
   fH2->AddFrame(zPosMin, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "Y:");
   fH2->AddFrame(lab, f0center2d);
   yPos = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 215000);
   yPos->Resize(80,22);
   fH2->AddFrame(yPos, f0center2d);

   lab = new TGLabel(fH2, "Z (max):");
   fH2->AddFrame(lab, f0center2d);
   zPosMax = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 375000);
   zPosMax->Resize(80,22);
   fH2->AddFrame(zPosMax, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0] ,30);
   lab = new TGLabel(fH2, "Z:");
   fH2->AddFrame(lab, f0center2d);
   zPos = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 375000);
   zPos->Resize(80,22);
   fH2->AddFrame(zPos, f0center2d);

   lab = new TGLabel(fH2, "Z (step):");
   fH2->AddFrame(lab, f0center2d);
   zPosStep = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative);
   zPosStep->Resize(80,22);
   fH2->AddFrame(zPosStep, f0center2d);
   fG1->AddFrame(fH2, f2);

   // Set, Get and Home the table position
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   fH3 = new TGHorizontalFrame(fH2, subgroup[0], 30);
   positionSet = new TGTextButton(fH3, "Set");
   positionSet->SetTextJustify(36);
   positionSet->SetWrapLength(-1);
   positionSet->Resize(60,22);
   fH3->AddFrame(positionSet, f0);
   positionGet = new TGTextButton(fH3, "Get");
   positionGet->SetTextJustify(36);
   positionGet->SetWrapLength(-1);
   positionGet->Resize(60,22);
   fH3->AddFrame(positionGet, f0);
   positionHome = new TGTextButton(fH3, "Home");
   positionHome->SetTextJustify(36);
   positionHome->SetWrapLength(-1);
   positionHome->Resize(60,22);
   fH3->AddFrame(positionHome, f0);
   fH2->AddFrame(fH3, f0centerx);
   fG1->AddFrame(fH2, f2);

   // Position scan controls
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "X (min):");
   fH2->AddFrame(lab, f0center2d);
   xPosMin = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 215000);
   xPosMin->Resize(80,22);
   fH2->AddFrame(xPosMin, f0center2d);

   lab = new TGLabel(fH2, "Y (min):");
   fH2->AddFrame(lab, f0center2d);
   yPosMin = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 215000);
   yPosMin->Resize(80,22);
   fH2->AddFrame(yPosMin, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "X (max):");
   fH2->AddFrame(lab, f0center2d);
   xPosMax = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 215000);
   xPosMax->Resize(80,22);
   fH2->AddFrame(xPosMax, f0center2d);

   lab = new TGLabel(fH2, "Y (max):");
   fH2->AddFrame(lab, f0center2d);
   yPosMax = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber, TGNumberFormat::kNELLimitMinMax, -100, 215000);
   yPosMax->Resize(80,22);
   fH2->AddFrame(yPosMax, f0center2d);
   fG1->AddFrame(fH2, f2);

   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "X (step):");
   fH2->AddFrame(lab, f0center2d);
   xPosStep = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative);
   xPosStep->Resize(80,22);
   fH2->AddFrame(xPosStep, f0center2d);

   lab = new TGLabel(fH2, "Y (step):");
   fH2->AddFrame(lab, f0center2d);
   yPosStep = new TGNumberEntry(fH2, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative);
   yPosStep->Resize(80,22);
   fH2->AddFrame(yPosStep, f0center2d);
   fG1->AddFrame(fH2, f2);
   
   fV1->AddFrame(fG1, f1);
   // Right pane (Table position controls)
   fH1->AddFrame(fV1, f0);
   fT1->AddFrame(fH1, f1);

   // Waveform tab
   fT1 = setTab->AddTab("Waveform");
   fH1 = new TGHorizontalFrame(fT1, subwin[0], subgroup[1], kFixedHeight);
   lab = new TGLabel(fH1, "Waveform controls");
   fH1->AddFrame(lab, f0center2d);
   fT1->AddFrame(fH1, f0);

   // Wave measurements tab
   fT1 = setTab->AddTab("Measurement");
   fH1 = new TGHorizontalFrame(fT1, subwin[0], subgroup[1], kFixedHeight);
   lab = new TGLabel(fH1, "Waveform measurement controls");
   fH1->AddFrame(lab, f0center2d);
   fT1->AddFrame(fH1, f0);

   mdiFrame->AddFrame(setTab, f0);
   // Disable the two tabs regarding the Scope if not connected to one
   setTab->SetEnabled(1,kFALSE);
   setTab->SetEnabled(2,kFALSE);

   // Bottom pane (File controls)
   subgroup[0] = subwin[0]-20;
   subgroup[1] = subwin[1]/3-30; //2*(3*((winWidth/6)-5))/5+10;
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], subgroup[1] /*1*(3*((winWidth/6)-5))/5+15*/ , kFixedWidth | kFixedHeight);
   fG1 = new TGGroupFrame(fH1, "Event/Data file controls");

   // Number of events
   fH2 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH2, "Number of events:");
   fH2->AddFrame(lab, f0centery);
   evtNum = new TGNumberEntry(fH2, 10000, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative);
   evtNum->Resize(80,22);
   fH2->AddFrame(evtNum, f0centery);
   fG1->AddFrame(fH2, f2);

   // Time stamp display
   fH2 = new TGHorizontalFrame(fG1,600,200);
   lab = new TGLabel(fH2, "Time stamp:");
   fH2->AddFrame(lab, f0centery);
   timeStamp = new TGTextEntry(fH2, "");
   timeStamp->Resize(440,22);
   timeStamp->SetState(kFALSE); // time stamp is read-only
   fH2->AddFrame(timeStamp, f0centery);
   fG1->AddFrame(fH2, f2);

   // Save to file
   fH2 = new TGHorizontalFrame(fG1,600,200);
   lab = new TGLabel(fH2, "Save to file:");
   fH2->AddFrame(lab, f0centery);
   char *cTemp;
   cTemp = new char[256];
   sprintf(cTemp, "./results/test%s", histExt);
   fileName = new TGTextEntry(fH2, cTemp);
   delete[] cTemp;
   fileName->Resize(400,22);
   fileName->SetState(kFALSE);
   fH2->AddFrame(fileName, f0centery);
   saveFile = new TGTextButton(fH2, "...");
   saveFile->SetTextJustify(36);
   saveFile->SetWrapLength(-1);
   saveFile->Resize(80,22);
   fH2->AddFrame(saveFile, f0centery);
//   mdiFrame->AddFrame(fH2, f0);
   fG1->AddFrame(fH2, f2);
   fH1->AddFrame(fG1, f1);
   // Bottom pane (File controls)
   mdiFrame->AddFrame(fH1, f0);

   subgroup[0] = subwin[0]-70;
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   fH2 = new TGHorizontalFrame(fH1, 3*subgroup[0]/4, 30, kFixedWidth);
   measStart = new TGTextButton(fH2, "Start acquisition");
   measStart->SetTextJustify(36);
   measStart->SetWrapLength(-1);
   measStart->Resize(80,22);
   fH2->AddFrame(measStart, f0center2d);

   ULong_t fcolor;
   gClient->GetColorByName("red", fcolor);

   busyLabel = new TGLabel(fH2, "Busy"); //, fTextGC->GetGC(), labelfont, kChildFrame);
   busyLabel->SetTextJustify(36);
   busyLabel->Resize(80,22);
   busyLabel->Disable();
   busyLabel->SetTextColor(fcolor);
   fH2->AddFrame(busyLabel, f0center2d);

   curProgress = new TGHProgressBar(fH2, TGProgressBar::kStandard, 150);
   curProgress->ShowPosition();
   curProgress->SetRange(0,100);
   curProgress->SetBarColor("green");
   fH2->AddFrame(curProgress, f0center2d);
   fH1->AddFrame(fH2, f0centerx);
   mdiFrame->AddFrame(fH1, f2);

   mdiFrame->SetMdiHints(kMdiMinimize | kMdiMaximize);
   mdiFrame->SetWindowName("Main measurement window");
   mdiFrame->MapSubwindows();
   mdiFrame->Layout();
   mdiFrame->Move((winWidth/6),0);
// Main window -----------------------------------------------------------------------------

// Histogram pane --------------------------------------------------------------------------
   subwin[0] = 2*((winWidth/6)-5); subwin[1] = (int)(2.5*((winHeight/5)-5))-5;
   histogramPane = new TGMdiSubwindow(fMainFrame, subwin[0], subwin[1]);
   mdiFrame = histogramPane->GetMdiFrame();

   histCanvas = new TRootEmbeddedCanvas("histCanvas",mdiFrame,900,900);
   mdiFrame->AddFrame(histCanvas, f1);
   TCanvas *gCanvas = histCanvas->GetCanvas();
   gCanvas->SetGridx();
   gCanvas->SetGridy();

   mdiFrame->SetMdiHints(kMdiMinimize | kMdiMaximize);
   mdiFrame->SetWindowName("Histogram");
   mdiFrame->MapSubwindows();
   mdiFrame->Layout();
   mdiFrame->Move(4*((winWidth/6)-5)+10,0);
// Histogram pane --------------------------------------------------------------------------

// Histogram file selection pane -----------------------------------------------------------
   subwin[0] = 4*((winWidth/6)-5); subwin[1] = 2*((winHeight/5)-5)+15;
   histogramPaneFile = new TGMdiSubwindow(fMainFrame, subwin[0]+5, subwin[1]);
   mdiFrame = histogramPaneFile->GetMdiFrame();

   // Open browser for file selection 
   subgroup[0] = subwin[0]-10;
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   lab = new TGLabel(fH1, "File selection:");
   fH1->AddFrame(lab, f0centery);

   selectDir = new TGTextButton(fH1, "...");
   selectDir->SetTextJustify(36);
   selectDir->SetWrapLength(-1);
   selectDir->Resize(80,22);
   fH1->AddFrame(selectDir, f0centery);
   mdiFrame->AddFrame(fH1, f2);

   // List view of the opened files
   fileList = new TGListBox(mdiFrame,1);
   fileList->GetVScrollbar();
   fileList->Resize(300, (subwin[1]/2)-10 );
   mdiFrame->AddFrame(fileList, f2);

   // Multiple file selection toggle, previous/next controls and clear list
   fH1 = new TGHorizontalFrame(mdiFrame, subgroup[0], 30);
   multiSelect = new TGCheckButton(fH1, "Multiple file select");
   multiSelect->Resize(50,22);
   multiSelect->SetState(kButtonUp);
   fH1->AddFrame(multiSelect, f0);

   multiSelectAll = new TGCheckButton(fH1, "Select all listed files");
   multiSelectAll->Resize(50,22);
   multiSelectAll->SetState(kButtonUp);
   fH1->AddFrame(multiSelectAll, f0);

   TGTextButton *clearList = new TGTextButton(fH1, "Clear list");
   clearList->SetTextJustify(36);
   clearList->SetWrapLength(-1);
   clearList->Resize(80,22);
   fH1->AddFrame(clearList, f0right);

   nextFile = new TGTextButton(fH1, ">>");
   nextFile->SetTextJustify(36);
   nextFile->SetWrapLength(-1);
   nextFile->Resize(80,22);
   fH1->AddFrame(nextFile, f0right);

   prevFile = new TGTextButton(fH1, "<<");
   prevFile->SetTextJustify(36);
   prevFile->SetWrapLength(-1);
   prevFile->Resize(80,22);
   fH1->AddFrame(prevFile, f0right);
   mdiFrame->AddFrame(fH1, f2);

   mdiFrame->SetMdiHints(kMdiMinimize);
   mdiFrame->SetWindowName("Histogram file selection");
   mdiFrame->MapSubwindows();
   mdiFrame->Layout();
   mdiFrame->Move(0,3*((winHeight/5)-5)-5);
// Histogram file selection pane -----------------------------------------------------------

// Histogram controls pane -----------------------------------------------------------------
   subwin[0] = 2*((winWidth/6)-5); subwin[1] = (int)(2.5*((winHeight/5)-5))+10;
   histogramPaneCtr = new TGMdiSubwindow(fMainFrame, subwin[0], subwin[1]);
   mdiFrame = histogramPaneCtr->GetMdiFrame();

   // Control for histogram X range
   subgroup[0] = subwin[0]-10;
   fG1 = new TGGroupFrame(mdiFrame, "Histogram display");
   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "ADC range (min, max):");
   fH1->AddFrame(lab, f0centery);
   adcMinRange = new TGNumberEntry(fH1, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber);
   adcMinRange->Resize(80,22);
   fH1->AddFrame(adcMinRange, f0centery);
   adcMaxRange = new TGNumberEntry(fH1, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEAAnyNumber);
   adcMaxRange->Resize(80,22);
   fH1->AddFrame(adcMaxRange, f0centery);
   fG1->AddFrame(fH1, f2);

   // TDC window for getting data
   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "TDC range (min, max):");
   fH1->AddFrame(lab, f0centery);
   tdcMinwindow = new TGNumberEntry(fH1, 0.0, 6, 999, TGNumberFormat::kNESRealTwo, TGNumberFormat::kNEAAnyNumber);
   tdcMinwindow->Resize(80,22);
   fH1->AddFrame(tdcMinwindow, f0centery);
   tdcMaxwindow = new TGNumberEntry(fH1, 221.8, 6, 999, TGNumberFormat::kNESRealTwo, TGNumberFormat::kNEAAnyNumber);
   tdcMaxwindow->Resize(80,22);
   fH1->AddFrame(tdcMaxwindow, f0centery);
   fG1->AddFrame(fH1, f2);

   // Y axis range settings
   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "Y range (min, max):");
   fH1->AddFrame(lab, f0centery);
   yMinRange = new TGNumberEntry(fH1, 0, 6, 999, TGNumberFormat::kNESRealOne, TGNumberFormat::kNEAAnyNumber);
   yMinRange->Resize(80,22);
   fH1->AddFrame(yMinRange, f0centery);
   yMaxRange = new TGNumberEntry(fH1, 0, 6, 999, TGNumberFormat::kNESRealOne, TGNumberFormat::kNEAAnyNumber);
   yMaxRange->Resize(80,22);
   fH1->AddFrame(yMaxRange, f0centery);
   fG1->AddFrame(fH1, f2);

   // Select the channel to display
   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "Display channel:");
   fH1->AddFrame(lab, f0centery);
   selectCh = new TGNumberEntry(fH1, 0, 6, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, (NCH->GetNumber())-1);
   selectCh->Resize(40,22);
   fH1->AddFrame(selectCh, f0centery);

   changeADC = new TGTextButton(fH1, "ADC");
   changeADC->AllowStayDown(kTRUE);
   changeADC->SetDown(kTRUE);
   fMenuHisttype->CheckEntry(M_ANALYSIS_HISTTYPE_1DADC);
   changeADC->SetTextJustify(36);
   changeADC->SetWrapLength(-1);
   changeADC->Resize(60,22);
   fH1->AddFrame(changeADC, f0centery);

   changeTDC = new TGTextButton(fH1, "TDC");
   changeTDC->AllowStayDown(kTRUE);
   changeTDC->SetTextJustify(36);
   changeTDC->SetWrapLength(-1);
   changeTDC->Resize(60,22);
   fH1->AddFrame(changeTDC, f0centery);

   changeADCTDC = new TGTextButton(fH1, "ADC/TDC");
   changeADCTDC->AllowStayDown(kTRUE);
   changeADCTDC->SetTextJustify(36);
   changeADCTDC->SetWrapLength(-1);
   changeADCTDC->Resize(60,22);
   fH1->AddFrame(changeADCTDC, f0centery);
   
   change2Dsurf = new TGTextButton(fH1, "Surf 2D");
   change2Dsurf->AllowStayDown(kTRUE);
   change2Dsurf->SetTextJustify(36);
   change2Dsurf->SetWrapLength(-1);
   change2Dsurf->Resize(60,22);
   fH1->AddFrame(change2Dsurf, f0);
   fG1->AddFrame(fH1, f2);

   logscale = new TGCheckButton(fG1, "Logarithmic scale ON/OFF");
   logscale->Resize(50,22);
   logscale->SetState(kButtonUp);
   fG1->AddFrame(logscale, f0centerx);

   // Export the selected files
   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 100);
   fH2 = new TGHorizontalFrame(fH1, subgroup[0], 100);
   lab = new TGLabel(fH2, "Export selected histograms:");
   fH2->AddFrame(lab, f0centery);

   exportHist = new TGTextButton(fH2, "Export");
   exportHist->SetTextJustify(36);
   exportHist->SetWrapLength(-1);
   exportHist->Resize(80,22);
   fH2->AddFrame(exportHist, f0centery);
   fH1->AddFrame(fH2, f0centerx);
   fG1->AddFrame(fH1, f2);
   mdiFrame->AddFrame(fG1, f2);

   // Fitting controls for ADC spectrum
   fG1 = new TGGroupFrame(mdiFrame, "Fit Settings");
   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "Peak sigma:");
   fH1->AddFrame(lab, f0centery);
   fitSigma = new TGNumberEntry(fH1, 1.5, 3, 999, TGNumberFormat::kNESRealThree, TGNumberFormat::kNEANonNegative);
   fitSigma->Resize(60,22);
   fH1->AddFrame(fitSigma, f0centery);
   fG1->AddFrame(fH1, f2);

   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "Signal/Noise treshold:");
   fH1->AddFrame(lab, f0centery);
   fitTresh = new TGNumberEntry(fH1, 5.0E-3, 3, 999, TGNumberFormat::kNESReal, TGNumberFormat::kNEANonNegative);
   fitTresh->Resize(60,22);
   fH1->AddFrame(fitTresh, f0centery);
   fG1->AddFrame(fH1, f2);

   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "Background interpolation:");
   fH1->AddFrame(lab, f0centery);
   fitInter = new TGNumberEntry(fH1, 8, 3, 999, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative);
   fitInter->Resize(60,22);
   fH1->AddFrame(fitInter, f0centery);
   fG1->AddFrame(fH1, f2);

   fH1 = new TGHorizontalFrame(fG1, subgroup[0], 30);
   lab = new TGLabel(fH1, "Peak fit max. acceptable error:");
   fH1->AddFrame(lab, f0centery);
   accError = new TGNumberEntry(fH1, 0.15, 3, 999, TGNumberFormat::kNESRealTwo, TGNumberFormat::kNEANonNegative);
   accError->Resize(60,22);
   fH1->AddFrame(accError, f0centery);
   fG1->AddFrame(fH1, f2);

   exfitplots = new TGCheckButton(fG1, "Export fitting plots ON/OFF");
   exfitplots->Resize(50,22);
   exfitplots->SetState(kButtonDown);
   fG1->AddFrame(exfitplots, f0centerx);
   mdiFrame->AddFrame(fG1, f2);

   mdiFrame->SetMdiHints(kMdiMinimize);
   mdiFrame->SetWindowName("Histogram controls");
   mdiFrame->MapSubwindows();
   mdiFrame->Layout();
   mdiFrame->Move(4*((winWidth/6)-5)+10,(int)(2.5*((winHeight/5)-5)));
// Histogram controls pane -----------------------------------------------------------------

   // Action connections
   voltscanOn->Connect("Clicked()", "TGAppMainFrame", this, "EnableVoltScan()");
   surfscanOn->Connect("Clicked()", "TGAppMainFrame", this, "EnableSurfScan()");
   zscanOn->Connect("Clicked()", "TGAppMainFrame", this, "EnableZaxisScan()");
//   histogramOn->Connect("Clicked()", "TGAppMainFrame", this, "HistogramToggle()");
   vHardlimit->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "VoltageLimit()");
   (vHardlimit->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "VoltageLimit()");
   NCH->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "ChannelLimit()");
   (NCH->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "ChannelLimit()");
   cleanOn->Connect("Clicked()", "TGAppMainFrame", this, "CleanPlotToggle()");
   oscConnect->Connect("Clicked()", "TGAppMainFrame", this, "ConnectToScope()");
   vOutSet->Connect("Clicked()", "TGAppMainFrame", this, "SetVoltOut()");
   vOutGet->Connect("Clicked()", "TGAppMainFrame", this, "GetVoltOut()");
   vOutReset->Connect("Clicked()", "TGAppMainFrame", this, "ResetVoltOut()");
   positionSet->Connect("Clicked()", "TGAppMainFrame", this, "SetPosition()");
   positionGet->Connect("Clicked()", "TGAppMainFrame", this, "GetPosition()");
   positionHome->Connect("Clicked()", "TGAppMainFrame", this, "HomePosition()");
   saveFile->Connect("Clicked()", "TGAppMainFrame", this, "SaveFile()");
   measStart->Connect("Clicked()", "TGAppMainFrame", this, "StartAcq()");
   selectDir->Connect("Clicked()", "TGAppMainFrame", this, "SelectDirectory()");
   multiSelect->Connect("Clicked()", "TGAppMainFrame", this, "ListMultiSelect()");
   multiSelectAll->Connect("Clicked()", "TGAppMainFrame", this, "ListSelectAll()");
   prevFile->Connect("Clicked()", "TGAppMainFrame", this, "FileListNavigation(=-2)");
   nextFile->Connect("Clicked()", "TGAppMainFrame", this, "FileListNavigation(=-3)");
   fileList->Connect("DoubleClicked(Int_t)", "TGAppMainFrame", this, "FileListNavigation(Int_t)");
   clearList->Connect("Clicked()", "TGListBox", fileList, "RemoveAll()");

   adcMinRange->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "SetHistRange()");
   (adcMinRange->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "SetHistRange()");
   adcMaxRange->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "SetHistRange()");
   (adcMaxRange->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "SetHistRange()");
   yMinRange->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "SetHistRange()");
   (yMinRange->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "SetHistRange()");
   yMaxRange->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "SetHistRange()");
   (yMaxRange->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "SetHistRange()");
   tdcMinwindow->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "SetHistRange()");
   (tdcMinwindow->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "SetHistRange()");
   tdcMaxwindow->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "SetHistRange()");
   (tdcMaxwindow->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "SetHistRange()");
   changeADC->Connect("Clicked()", "TGAppMainFrame", this, "ChangeHisttype(=0)");
   changeTDC->Connect("Clicked()", "TGAppMainFrame", this, "ChangeHisttype(=1)");
   changeADCTDC->Connect("Clicked()", "TGAppMainFrame", this, "ChangeHisttype(=2)");
   change2Dsurf->Connect("Clicked()", "TGAppMainFrame", this, "ChangeHisttype(=3)");
   selectCh->Connect("ValueSet(Long_t)", "TGAppMainFrame", this, "ChangeChannel()");
   (selectCh->GetNumberEntry())->Connect("ReturnPressed()", "TGAppMainFrame", this, "ChangeChannel()");
   logscale->Connect("Clicked()", "TGAppMainFrame", this, "SetHistRange()");
   exportHist->Connect("Clicked()", "TGAppMainFrame", this, "HistogramExport()");

   started = kFALSE;
   EnableVoltScan();
   EnableSurfScan();
   EnableZaxisScan();
}

//---------------------------------------------------------------
// Closing the main application window and checking the about information

void TGAppMainFrame::CloseWindow()
{
   gApplication->Terminate(0);
}

Bool_t TGAppMainFrame::About()
{
   int ret = 0;

   new TGMsgBox(gClient->GetRoot(), fMain,
                fMain->GetWindowName(), "This is an application.",
                kMBIconQuestion, kMBClose, &ret);

   if(debug == 1)
      if(ret == kMBClose)
         printf("Closing the About window (%d).\n", ret);

   return kFALSE;
}

//---------------------------------------------------------------
// Subwindow constructor definition (& layout) and close subwindow action

TGMdiSubwindow::TGMdiSubwindow(TGMdiMainFrame *main, int w, int h)
{
   // Create a new subwindow
   fMdiFrame = new TGMdiFrame(main, w, h);
   fMdiFrame->Connect("CloseWindow()", "TGMdiSubwindow", this, "CloseWindow()");  // setting here to =0 -> will always ask before closing window
   fMdiFrame->DontCallClose();          // only let this window close if Yes is pressed when closing window

}

Bool_t TGMdiSubwindow::CloseWindow()
{
   int ret = 0;

//   if(noq == 0)
//   {
      new TGMsgBox(gClient->GetRoot(), fMdiFrame,
                fMdiFrame->GetWindowName(), "Really want to close the window?",
                kMBIconExclamation, kMBYes | kMBNo, &ret);
      if (ret == kMBYes) return fMdiFrame->CloseWindow();

      return kFALSE;
//   }
//   else
//      return fMdiFrame->CloseWindow();
}

//---------------------------------------------------------------
// Main function

void windowed_test()
{
   new TGAppMainFrame(gClient->GetRoot(), winWidth, winHeight);
}

//#ifdef STANDALONE
int main(int argc, char **argv)
{
   TApplication theApp("MdiTest", &argc, argv);

   windowed_test();

   theApp.Run();

   return 0;
}
//#endif