/**
 *  FTrkScanQlook_EXPERT.cxx
 *
 * autor: D.Fedele
 * version v2r08
 * Parameters:
 * 	file - the path to the root file to analyze
 *      outdir - total path of output file 
 *      event - the number of the single event to analyze
 *      va1 - the number of the single va1 to analyze (dsp*100+va1)
 *      value - the number of events to store in the .dat file with va1 values*10 + # of calibration (if #of cal = 0, select every calibration)
 *      outfile - extension of output file (pdf,ps,gif,jpg)
 *               
 */
//
#include <iostream>
#include <sstream>
#include <fstream>
//
#include <TPaveText.h>
#include <TLatex.h>
#include <TCanvas.h>
#include <TGraph.h>
#include <TFile.h>
#include <TTree.h>
#include <TStyle.h>
#include <TString.h>
//
#include <physics/tracker/TrackerEvent.h>
#include <PscuHeader.h>
#include <EventHeader.h>
#include <CalibTrk1Event.h>
#include <CalibTrk2Event.h>
#include <RunHeaderEvent.h>
//

using namespace std;

typedef struct trkword{
  int type;
  int decode;
};

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
 *
 |   The function "datadecode" decodes the tracker words.
 *   
 |   Tracker words are of three types:
 *   - ADC data 
 |   - strip address
 *   - end of ladder
 |   
 *   The function returns a struct variable (trkword) 
 |   that contains two quantities, type and decode, which are assigned 
 *   the following values:
 |   
 *   type                     decode              
 |   ----------------------------------------------------
 *   -1     error             0          
 |    0     data              0-4095   ADC values
 *    1     address           0-1023   strip address (relative to ladder)
 |    2     end-of-ladder     1,2,3    ladder number     (compressed acq mode)      
 *                            4,5,6    ladder number + 3 (full acq mode)
 |       
 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
trkword datadecode(int word){
  int type =0;
  int data =0;
  int nodata = word&0xf000;
  int zero = 0;

  trkword thisword;
    
  switch (nodata>>12){

  case 0:      
	
    thisword.decode = word;
    thisword.type = 0;
    //	cout << thisword.decode << "\n";
    return (thisword);              //>>>>> ADC data (0)

  case 1:       

    type = word&0xC00;
    data = word&0x3ff;

    switch(type>>10){

    case 0:   
      thisword.decode = data;
      thisword.type = 1; //>>> address (1)
      return (thisword);          

    case 2:  
      //	    if(data>=4)data = data-3;
      if(data>6){
	printf("Error on data \n");
	thisword.decode = zero;
	thisword.type = -1;
	return (thisword);     //>>>>> error (-1)
      }
      thisword.decode = data;	    
      thisword.type = 2;
      return (thisword);       //>>> end-of-ladder 

    default:
      printf("Error on data \n");
      thisword.decode = zero;
      thisword.type = -1;
      return (thisword);              //>>>>> error (-1)
	    
    }

  default:

    printf("Error on data \n");
    thisword.decode = zero;
    thisword.type = -1;
    return (thisword);              //>>>>> error (-1)
  }
}


void FTrkScanQLook_EXPERT(TString file, TString outdir,Int_t event, Int_t va1, Int_t value, TString outfile)
{

  // 
  //   obtain information about the data file and select the output file
  Int_t dwpos = file.Last('/');
  Int_t dwpos1 = file.Last('.');
  TString base,ffile ;
  ffile=file(dwpos+1,dwpos1-(dwpos+1));
  if(dwpos>0) base=file(0,dwpos);

  TString out;
  if(outdir.Length()==0){
    out = base;
  }else{
    out = outdir;
  }
  if(out.Last('/')+1<out.Length()) out+="/";
    
  pamela::tracker::TrackerEvent *trk=0;
  pamela::EventHeader *eh=0,*eH=0;
  pamela::PscuHeader *ph=0,*pH=0;
  pamela::RunHeaderEvent *reh=0;
  pamela::CalibTrk1Event *trk1 = 0;
  pamela::CalibTrk2Event *trk2 = 0;
  pamela::EventCounter *cod=0;

  pamela::PacketType *pctp=0;
  // open files
  TFile *trackerFile = new TFile(file);
  if ( !trackerFile ){
    trackerFile->Close();
    printf("No tracker file! \n");
    return;
  }

  //Takes the tree and branches
  TTree *tr = (TTree*)trackerFile->Get("Physics");
  tr->SetBranchAddress("Tracker",&trk);
  tr->SetBranchAddress("Header",&eh);

  TTree *otr  = (TTree*)trackerFile->Get("RunHeader");
  otr->SetBranchAddress("Header",&eH);
  otr->SetBranchAddress("RunHeader",&reh);

  TTree *otr1 = (TTree*)trackerFile->Get("CalibTrk1");
  otr1->SetBranchAddress("CalibTrk1", &trk1);
  TTree *otr2 = (TTree*)trackerFile->Get("CalibTrk2");
  otr2->SetBranchAddress("CalibTrk2", &trk2);

  // Define variables 
  Int_t nevents = tr->GetEntries();
  Int_t neventH = otr->GetEntries();
  Int_t cevents=0;
      
  if(otr1->GetEntries()==otr2->GetEntries())
    cevents = otr1->GetEntries();
  else printf("\nWARNING: CalibTrk1 entries is different from CalibTrk2 entries\n\n");
  
  
  if ( nevents <= 0 ) {
    trackerFile->Close();
    printf("The file is empty, exiting...\n");
    return;
  }

  //
  // open the output text files for the alarms
  TString fname = out+ffile;
  int slen=fname.Length();
  int last=fname.Last('_');
  if(last<(slen-1))fname.Append('_');   
  fname.Append("FTrk-DSP-values.dat");
  ofstream values(fname,ios::out);

  //
  printf("\n Number of Entries: %d\n",nevents);
  printf(" Number of Header Entries: %d\n",neventH);
  printf(" Number of Calibration: %d\n",cevents);
   
  ULong_t obt=0,hobt[neventH];  
  Int_t eve,cin=0,cins=0,br=0,olrun[neventH];
  TString cal="";
  
  eve=3;
  for(Int_t i=0;i<neventH;i++){
    otr->GetEntry(i);
    pH = eH->GetPscuHeader();
    hobt[i]= pH->GetOrbitalTime();
    olrun[i]=reh->TRK_CALIB_USED;
    if(reh->TRK_CALIB_USED!=104 && br==0){
      obt = pH->GetOrbitalTime();
      cal="Event with online calibration";
      br=1;
    }
    if(i==neventH-1 && br==0){
      cal="*****  ONLINE CALIBRATION NOT FOUND IN THIS FILE  *****";
      eve=2;
    }
  }

  int tot=2,totvalues=0,TOT=0,totsum=0;
  if(event<0) tot=abs(event);
  if(value>0) totvalues=value/10;
    
  TOT= tot > totvalues ? tot : totvalues;
  if(value>0) totsum= (value/10) > 100 ? (value/10) : 100;
  else totsum=100;

  Int_t calev=cevents;

  TH1F *histomax[12][tot];           //histos of max signals
  TH1F *histocomp[12][tot];          //histos of compressed data
  TH1F *histofull[12][tot];          //histos of full data
  TCanvas *c1[tot],*csum[calev];
  TH1F *histova[tot];
  TGraph*sum[12][calev][totsum/2];                  
  TCanvas *cva[tot];
  
  TPad *trkpad[12];          //pad for histos

  stringstream fromfile,isfile,title,hid,message;
  TString figsa="",figsav="",figsava="";
  Int_t canvasx=1200;
  Int_t canvasy=900;
  
  TLatex *t=new TLatex();
  t->SetTextFont(32);
  t->SetTextColor(1);
  t->SetTextAlign(12);
  t->SetTextSize(0.02);

  gStyle->SetLabelSize(0.06,"x");
  gStyle->SetLabelSize(0.06,"y");
  gStyle->SetTitleFontSize(0.1);
  gStyle->SetFillColor(10);  
  gStyle->SetTitleFillColor(10);
  gStyle->SetOptStat(0);
    
  Int_t p[12],psum=0;
  Int_t whistostrip[3072];
  for(int s=0;s<3072;s++) whistostrip[s]=s+1;

  if(eve==3){
    for(Int_t i=0;i<nevents;i++){
      tr->GetEntry(i); 
      ph = eh->GetPscuHeader();
      cod = eh->GetCounter();
      if(olrun[cod->Get(pctp->RunHeader)-1]==104) continue;
      if(value%10!=0){
	if(i==0) cin=cod->Get(pctp->CalibTrk1)+((value%10)-1);
	if(cod->Get(pctp->CalibTrk1)==cin+1){
	  eve=i+3;
	  cin=100;
	}
      }
      else {
	if(i==0) cin=cod->Get(pctp->CalibTrk1);
	if(event<0 && cod->Get(pctp->CalibTrk1)==cin+1){
	  eve=i+3;
	  cin=100;
	}
	else if(event>=0 && (ULong_t)ph->GetOrbitalTime()>obt && obt>0){
	  eve=i+3;
	  obt=0;
	} 
      }
      if(i==0) cins=cod->Get(pctp->CalibTrk1);
      if(cod->Get(pctp->CalibTrk1)>cins){
	psum=1;
	cins=cod->Get(pctp->CalibTrk1);
      }
      if(psum==1){
	figsa=out+ffile+"_FTrkScanQLook_EXPERT_sumof";
	figsa+=totsum;
	figsa+="events_cal";
	figsa+=cins;
	csum[cins-1] = new TCanvas(figsa.Data(),"FTrkQLookSCAN",canvasx,canvasy);
	csum[cins-1]->SetFillColor(10);
	csum[cins-1]->Range(0,0,1,1);
	fromfile.str("");
	fromfile<<"FTrkScanQLook_EXPERT      File: "<<ffile<<"   ---->  Sum of "<<totsum<<" events after the "<<cins<<"  calibration  at OBT= "<<hobt[(cod->Get(pctp->RunHeader))-1];
	t->SetTextSize(0.02);
	t->DrawLatex(0.02,0.98,fromfile.str().c_str());
	
	//  draw pads
	Double_t posy = 0.95;    // up y-coord - top pads
	Double_t hpad = 0.15;   // pad height
	Double_t posx1=0;          // left  x-coord - pad column 
	Double_t posx0=0;          //       x-coord - column division
	Double_t wrel = 0.6;     // relative x size of first sub-column
	Double_t marg = 0.004;   // margin among pads
	
	hpad = (posy-marg*11)/6;
	wrel = (1-marg*4)/2;
	for(Int_t n = 0; n<12; n++){
	  if ( (n+1)%2 ) {
	    if(n>1)posy = posy-(marg*2+hpad);
	    posx1 = marg;
	    posx0 = posx1 + wrel;
	  } else {
	    posx1 = posx0 + 2*marg;
	    posx0 = posx1 + wrel;
	  };
	  
	  /* -----------> pad for histograms  */
	  trkpad[n] = new TPad("pad"," ",posx1,posy-hpad,posx0,posy,18,0,0);
	  trkpad[n]->SetFillColor(19);
	  trkpad[n]->SetFrameFillColor(10);

	  p[n]=0;
	} 
      }
      if(psum>0 && psum<=totsum){
	// = = = = = = = = = = = = = = = = = = = = = = = = =
	//  create header dump retrieving event info
	// = = = = = = = = = = = = = = = = = = = = = = = = =
	Int_t ndsp=0;
	
	Int_t whistomax[3072];
	Int_t whisto[3072];
	Int_t whistocomp[3072];
	Int_t whistofull[3072];
	
	//	//      transmitted words
	Int_t word = 0;
	Int_t iword = 0;   
	Int_t ii=0,ifull[12],icomp[12],imax[12],nn=0;    
	trkword thisword;
	
	Int_t address,ladder;
	
	
	for(Int_t n = 0; n<12; n++){
	  ndsp = trk->DSPnumber[n];
	  nn = ndsp-1;
	  ifull[nn]=0;
	  icomp[nn]=0;
	  imax[nn]=0;
	  
	  for(Int_t vi = 0; vi< 3072; vi++){
	    whistomax[vi] = -200;
	    whistocomp[vi] = -200;
	    whistofull[vi] = -200;
	    whisto[vi] = -200;
	  }
	  
	  //      	  //      trasmitted data
	  //      	  
	  address = 0;
	  ladder = 1;
	  for(Int_t vi = 0; vi < trk->DATAlength[n] ; vi++){
	    word = trk->TrackerData.At(iword);	    
	    thisword = datadecode(word);
	    iword++;
	    switch (thisword.type){
	      
	    case 0:  //ADC value
	      whisto[address] = thisword.decode;
	      address++;    
	      //	cout << "    adr " << address << "\n"; 
	      break;
	      
	    case 1:  //address
	      address = 1024*(ladder-1) + thisword.decode;
	      //	cout << "    adr " << address << "\n";
	      break;
	      
	    case 2:  //end-of-ladder
	      ladder = thisword.decode;
	      //		cout << "Ladder " << ladder << "\n"; 
	      if(ladder==3){
		//                  end of compressed data - FILL HISTO
		//cout << ">>> COMPRESSED data" << "\n";
		for(ii = 0; ii < 3072; ii++){
		  whistocomp[ii]=whisto[ii];
		  whisto[ii] = -200;
		}
		address = 0;
		ladder = 1;		    
	      }else if(ladder==6){
		//                  end of full data - FILL HISTO
		//cout << ">>> FULL data" << "\n";
		for(ii = 0; ii < 3072; ii++){
		  whistofull[ii]=whisto[ii];
		  whisto[ii] = -200;
		}
		address = 0;
		ladder = 1;
	      }else{		
		if(ladder>3)	ladder=ladder-3;
		address= ladder*1024;		
		ladder = ladder + 1;	
	      }
	    }    
	  }     
	  
	  for(Int_t vi = 0; vi < 3072; vi++){
	    if(whistofull[vi]>-200){
	      if(vi==3071){
		sum[nn][cins-1][p[nn]] = new TGraph(3072,whistostrip,whistofull);
		p[nn]++;
	      }	  	     
	      if(value%10==0 && value>0){
		if(whistofull[vi]>0){
		  if(vi==0) values << (short int)ndsp << " ";
		  values <<(short int) whistofull[vi] <<" ";
		  if(vi==3071) values << endl;
		}
	      }
	    }
	  }
	}
	psum++;
	if(value%10==0 && value>0) values << (short int)0 << endl << endl;
      }
      if(psum==totsum+1){
	if(value%10==0 && value>0) values << (short int)(-cins) << endl << endl;
	psum=0;
	for(Int_t vi = 0; vi < 12; vi++){	  
	  if(p[vi]>0){

	    TLine li,liva1;
	    li.SetLineColor(38);
	    li.SetLineStyle(4);
	    li.SetLineWidth(2);
	    liva1.SetLineColor(42);
	    liva1.SetLineStyle(3);
	    liva1.SetLineWidth(1);
	  
	    Float_t va1x=0;
	    csum[cins-1]->cd(); 
	    trkpad[vi]->Draw();
	    trkpad[vi]->cd();
	    trkpad[vi]->SetFillColor(10);
	  
	    stringstream tit,hid;
	    tit.str("");
	    hid.str("");
	    tit<<"DSP "<<vi+1;
	    sum[vi][cins-1][0]->SetTitle(tit.str().c_str());
	    sum[vi][cins-1][0]->GetXaxis()->SetTitle("channel id");
	    sum[vi][cins-1][0]->GetXaxis()->CenterTitle();
	    sum[vi][cins-1][0]->GetXaxis()->SetRangeUser(0,3073);
	    sum[vi][cins-1][0]->GetXaxis()->SetTitleSize(0.06);
	    sum[vi][cins-1][0]->GetXaxis()->SetTitleOffset(0.8);
	    sum[vi][cins-1][0]->GetYaxis()->SetTitle("ADC value");
	    sum[vi][cins-1][0]->GetYaxis()->SetTitleSize(0.09);
	    sum[vi][cins-1][0]->GetYaxis()->SetTitleOffset(0.4);
	    sum[vi][cins-1][0]->GetYaxis()->CenterTitle();
	    sum[vi][cins-1][0]->GetYaxis()->SetRangeUser(0,4500);
	    sum[vi][cins-1][0]->SetMarkerStyle(20);
	    sum[vi][cins-1][0]->SetMarkerSize(0.1);
	    sum[vi][cins-1][0]->SetMarkerColor(4);
	    sum[vi][cins-1][0]->Draw("ap");
	    hid<<p[vi]<<" events";
	    t->SetTextSize(0.11);
	    t->DrawLatex(2400,4250,hid.str().c_str());
	    for(int pi=1; pi<p[vi];pi++){
	      sum[vi][cins-1][pi]->SetMarkerStyle(21);
	      sum[vi][cins-1][pi]->SetMarkerSize(0.1);
	      sum[vi][cins-1][pi]->SetMarkerColor(4);
	      sum[vi][cins-1][pi]->Draw("p");
	    }
	    for(int va=1; va<24; va++){
	      va1x=128*va;
	      liva1.DrawLine(va1x,0.,va1x,4500.);
	    }
	    li.DrawLine(1024.5,0.,1024.5,4500.);
	    li.DrawLine(2048.5,0.,2048.5,4500.);
	    csum[cins-1]->Update();
	    hid.str("");
	  }
	}
	if(strcmp(outfile.Data(),"ps") && strcmp(outfile.Data(),"pdf")){
	  figsa+="."+outfile;
	  csum[cins-1]->Print(figsa.Data());
	}
       	if(cod->Get(pctp->CalibTrk1)==cevents) break;
      } 
    }
  }

  if(!strcmp(outfile.Data(),"ps") || !strcmp(outfile.Data(),"pdf")){
    stringstream nom1,nom2,nom3;
    nom1<<out<<ffile<<"_FTrkScanQLook_EXPERT_sumof"<<totsum<<"event.ps(";
    nom2<<out<<ffile<<"_FTrkScanQLook_EXPERT_sumof"<<totsum<<"event.ps";
    nom3<<out<<ffile<<"_FTrkScanQLook_EXPERT_sumof"<<totsum<<"event.ps)";
    
    for(int va=0; va<cevents; va++){
      if(cevents==1) csum[va]->Print(nom2.str().c_str(),"Landscape");
      if(cevents>2){
	if(va==0) csum[va]->Print(nom1.str().c_str(),"Landscape");
	if(va>0 && va<cevents-1) csum[va]->Print(nom2.str().c_str(),"Landscape");
	if(va>0 && va==cevents-1) csum[va]->Print(nom3.str().c_str(),"Landscape");
      }
    }
  }  
  //
  // Convert ps to pdf if required
  if(!strcmp(outfile.Data(),"pdf")){
    stringstream com;
    com<<"ps2pdf13 "<<out<<ffile<<"_FTrkScanQLook_EXPERT_sumof"<<totsum<<"event.ps "<<out<<ffile<<"_FTrkScanQLook_EXPERT_sumof"<<totsum<<"event.pdf";
    system(com.str().c_str());
    printf("\n---> ps file converted in pdf format!\n");
    com.str("");
    com<<"rm -f "<<out<<ffile<<"_FTrkScanQLook_EXPERT_sumof"<<totsum<<"event.ps ";
    system(com.str().c_str());
    printf("---> ps file removed!\n\n");
    com.str("");
  }



  for(Int_t e=0;e<TOT;e++){
    if(event<=0 || (value%10!=0 && e==0))
      event=eve;
    else {
      event=event+1;
      if(event>eve-3 && eve>2)
	cal="Event with online calibration";
      else 
	cal="*****  ONLINE CALIBRATION NOT FOUND IN THIS FILE  *****";
    }
    printf("Scan of Entry %d\n",event); 
	    
    tr->GetEntry(event);    
    //============================================================================  

    //  draw display area	

    TPad *trkpad[12],*pad=0;          //pad for histos
    TPaveText *trkpadtext[12]; //pad for header
    Int_t ndsp=0;

    if((tot<TOT && e<tot) || tot==TOT){
      figsav=out+ffile+"_FTrkScanQLook_EXPERT_ev";
      figsav+=event+1;
      c1[e] = new TCanvas(figsav.Data(),"FTrkQLookSCAN",canvasx,canvasy);
      c1[e]->SetFillColor(10);
      c1[e]->Range(0,0,1,1);
      fromfile.str("");
      fromfile<<"FTrkScanQLook_EXPERT      File: "<<ffile<<"            ---->  Entry  "<<event;
      t->SetTextSize(0.02);
      t->DrawLatex(0.02,0.98,fromfile.str().c_str());
      t->DrawLatex(0.60,0.98,cal.Data());
  
      isfile<<"Chips with white line at least once showed anomalous behaviour";
      t->SetTextColor(1);
      t->SetTextSize(0.018);
      t->DrawLatex(.05,.96,isfile.str().c_str());
      isfile.str("");
      
      isfile<<"Boxes so colored point out anomalous chips (not necessarily broken)";
      t->SetTextColor(107);
      //      t->DrawLatex(.5,.96,isfile.str().c_str());
      isfile.str("");
      t->SetTextColor(1);

      if(va1!=0){
	figsava=out+ffile+"_FTrkScanQLook_EXPERT_ev";
	figsava+=event+1;
	figsava+="_DSP";
	figsava+=(int)(va1/100);
	figsava+="_VA1-";
	figsava+=va1%100;
	cva[e] = new TCanvas(figsava.Data(),"TrkQLookSCAN VA1",canvasx,canvasy);
	cva[e]->SetFillColor(10);
	cva[e]->Range(0,0,1,1);
	fromfile.str("");
	fromfile<<"FTrkScanQLook_EXPERT      File: "<<ffile<<"      ---->  Entry  "<<event<<"      --> DSP "<<(int)(va1/100)<<"     --> va1 "<<va1%100;
	t->DrawLatex(0.02,0.98,fromfile.str().c_str());
	//      t->DrawLatex(0.65,0.98,cal.Data());
      }

      //  draw pads
      Double_t posy = 0.95;    // up y-coord - top pads
      Double_t hpad = 0.15;   // pad height
      Double_t posx1=0;          // left  x-coord - pad column 
      Double_t posx2=0;          // right x-coord - pad olumn
      Double_t posx0=0;          //       x-coord - column division
      Double_t wrel = 0.6;     // relative x size of first sub-column
      Double_t marg = 0.004;   // margin among pads

      for(Int_t n = 0; n<12; n++){
	if ( (n+1)%2 ) {
	  if(n>1)posy = posy-(marg*2+hpad);
	  posx1 = marg;
	  posx2 = 0.5 - marg;
	  posx0 = 0.5*wrel;
	} else {
	  posx1 = posx1 + 0.5;
	  posx2 = posx2 + 0.5;
	  posx0 = posx0 + 0.5;
	};
    
	/* -----------> pad for histograms  */
	trkpad[n] = new TPad("pad"," ",posx1,posy-hpad,posx0-marg,posy,18,0,0);
	trkpad[n]->SetFillColor(19);
	trkpad[n]->SetFrameFillColor(10);
	/* -----------> pad for header dump */
	trkpadtext[n] = new TPaveText((posx0+marg),(posy-hpad),posx2,posy);
	/* -----------> HISTOGRAMS          */
	
	title.str("");
	title<<"DSP "<<n+1;
	hid<<"h"<<n+e*100;
	histomax[n][e] = new TH1F(hid.str().c_str(),title.str().c_str(),3073,-0.5,3072.5);
	hid<<"hh"<<n+e*100;
	histocomp[n][e] = new TH1F(hid.str().c_str(),title.str().c_str(),3073,-0.5,3072.5);
	hid<<"hhh"<<n+e*100;
	histofull[n][e] = new TH1F(hid.str().c_str(),title.str().c_str(),3073,-0.5,3072.5);
	title.str("");
	hid.str("");
      } 
      if(va1!=0){
	title.str("");
	title<<"DSP "<<(int)(va1/100)<<" -- va1 "<<va1%100;
	hid<<"va"<<e;
	histova[e] = new TH1F(hid.str().c_str(),title.str().c_str(),130,0,129);
      }               //end loop on views
    
      /* -----------> pad for histograms  */
      pad = new TPad("padva"," ",0,0,1,0.97,18,0,0);
      pad->SetFillColor(19);
      pad->SetFrameFillColor(10);
    } 
    // = = = = = = = = = = = = = = = = = = = = = = = = =
    //  create header dump retrieving event info
    // = = = = = = = = = = = = = = = = = = = = = = = = =
    

    Double_t whistomax[3072];
    Double_t whisto[3072];
    Double_t whistocomp[3072];
    Double_t whistofull[3072];

    //=============================================
    //      transmitted words
    Int_t word = 0;
    Int_t iword = 0;
    Int_t TOTDATAlength_check = 0;    
    Int_t ii=0,ifull[12],icomp[12],imax[12],nn=0;    
    trkword thisword;

    Int_t address,ladder;
    
    
    for(Int_t n = 0; n<12; n++){
    
      ndsp = trk->DSPnumber[n];
      nn = ndsp-1;
      ifull[nn]=0;
      icomp[nn]=0;
      imax[nn]=0;
      if(ndsp>0){
	if(ndsp<13){
	  if((tot<TOT && e<tot) || tot==TOT){
	
	    /*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*
	     *
	     * Write event LEVEL0 report
	     *
	     *.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*/

	    trkpadtext[nn]->SetTextFont(40);
	    trkpadtext[nn]->SetFillColor(33);
	    trkpadtext[nn]->SetTextSize(0.012);
	    trkpadtext[nn]->SetTextAlign(13);

	    trkpadtext[nn]->AddText(" ");
	    message<<"DAQ mode  --------> "<<trk->DAQmode[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    message<<"Event number  --------> "<<trk->eventn[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    message<<"13-bit words --------> "<<trk->DATAlength[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    if (!(nn%2)&&trk->signcluster[n][0]!=0) message<<"L1  add:  "<<trk->addrcluster[n][0]<<" - sign: "<<1024-(trk->signcluster[n][0]);
	    else message<<"L1  add:  "<<trk->addrcluster[n][0]<<" - sign: "<<(trk->signcluster[n][0]);
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    if (!(nn%2)&&trk->signcluster[n][1]!=0) message<<"L2  add:  "<<trk->addrcluster[n][1]<<" - sign: "<<1024-(trk->signcluster[n][1]);
	    else message<<"L2  add:  "<<trk->addrcluster[n][1]<<" - sign: "<<trk->signcluster[n][1];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    if (!(nn%2)&&trk->signcluster[n][2]!=0) message<<"L3  add:  "<<trk->addrcluster[n][2]<<" - sign: "<<1024-(trk->signcluster[n][2]);
	    else message<<"L3  add:  "<<trk->addrcluster[n][2]<<" - sign: "<<trk->signcluster[n][2];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    message<<"NCLUST "<<trk->nclust[n]<<"    CUTC "<<trk->cutc[n]<<"   CUTCL "<<trk->cutcl[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    message<<"Comp. time "<<trk->compressiontime[n]<<" x 0.051ms = "<<0.051*trk->compressiontime[n]<<" ms";
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    trkpadtext[nn]->AddText(" ");
	    message<<"CRC -->  "<<trk->crc[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    message<<"FL1-6 -->  "<<trk->fl1[n]<<" "<<trk->fl2[n]<<" "<<trk->fl3[n]<<" "<<trk->fl4[n]<<" "<<trk->fl5[n]<<" "<<trk->fl6[n]<<" FC "<<trk->fc[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str(""); 
	    trkpadtext[nn]->AddText(" ");
	    trkpadtext[nn]->AddLine(0,0,0,0);
	    message<<"PNum "<<trk->pnum[n]<<" - BId "<<trk->bid[n]<<"       ALARM  "<<trk->alarm[n];
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    message<<"Cmd "<<trk->cmdnum[n]<<" --- Answer length "<<trk->aswr[n]<<" byte";
	    trkpadtext[nn]->AddText(message.str().c_str());
	    message.str("");
	    trkpadtext[nn]->AddText(" ");
	
	    TOTDATAlength_check = TOTDATAlength_check + trk->DATAlength[n];
	  }
	  /*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*
	   *
	   * Plot event LEVEL0 histo
	   *
	   *.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*/

	  //=============================================
	}
	for(Int_t i = 0; i< 3072; i++){
	  whistomax[i] = -200;
	  whistocomp[i] = -200;
	  whistofull[i] = -200;
	  whisto[i] = -200;
	}

	//      ===============
	//      trasmitted data
	//      ===============

	address = 0;
	ladder = 1;
	for(Int_t i = 0; i < trk->DATAlength[n] ; i++){
	  word = trk->TrackerData.At(iword);	    
	  thisword = datadecode(word);
	  iword++;
	  switch (thisword.type){
	    
	  case 0:  //ADC value
	    whisto[address] = thisword.decode;
	    address++;    
	    //	cout << "    adr " << address << "\n"; 
	    break;

	  case 1:  //address
	    address = 1024*(ladder-1) + thisword.decode;
	    //	cout << "    adr " << address << "\n";
	    break;

	  case 2:  //end-of-ladder
	    ladder = thisword.decode;
	    //		cout << "Ladder " << ladder << "\n"; 
	    if(ladder==3){
	      //                  end of compressed data - FILL HISTO
	      //cout << ">>> COMPRESSED data" << "\n";
	      for(ii = 0; ii < 3072; ii++){
		whistocomp[ii]=whisto[ii];
		whisto[ii] = -200;
	      }
	      address = 0;
	      ladder = 1;		    
	    }else if(ladder==6){
	      //                  end of full data - FILL HISTO
	      //cout << ">>> FULL data" << "\n";
	      for(ii = 0; ii < 3072; ii++){
		whistofull[ii]=whisto[ii];
		whisto[ii] = -200;
	      }
	      address = 0;
	      ladder = 1;
	    }else{		
	      if(ladder>3)	ladder=ladder-3;
	      address= ladder*1024;		
	      ladder = ladder + 1;	
	    }
	  }    
	}    
	

	//      ===============
	//      maximum signals
	//      ===============
	if(trk->signcluster[nn][0]!=0) whistomax[   0+(int)trk->addrcluster[nn][0]] = whistocomp[   0+(int)trk->addrcluster[nn][0]];
	if(trk->signcluster[nn][1]!=0) whistomax[1024+(int)trk->addrcluster[nn][1]] = whistocomp[1024+(int)trk->addrcluster[nn][1]];
	if(trk->signcluster[nn][2]!=0) whistomax[2048+(int)trk->addrcluster[nn][2]] = whistocomp[2048+(int)trk->addrcluster[nn][2]];

	for(Int_t i = 0; i < 3072; i++){
	  if(whistomax[i]>-200) imax[nn]=1;
	  if(whistocomp[i]>-200) icomp[nn]=1;
	  if(whistofull[i]>-200) ifull[nn]=1;
	  if(value%10!=0){
	    if((totvalues<TOT && e<totvalues) || totvalues==TOT){
	      if(whistofull[i]>0){
		if(i==0) values << (short int)ndsp << " ";
		values <<(short int) whistofull[i] <<" ";
		if(i==3071) values << endl;
	      }
	    }
	  }
	  if((tot<TOT && e<tot) || tot==TOT){
	    histomax[nn][e]->Fill((Float_t)i,whistomax[i]);
	    histocomp[nn][e]->Fill((Float_t)i,whistocomp[i]);
	    histofull[nn][e]->Fill((Float_t)i,whistofull[i]);
	    if(va1!=0 && ndsp==(int)(va1/100) && i>=128*((va1%100)-1)){
	      if(i<128*(va1%100))
		histova[e]->Fill((Float_t)(i-128*((va1%100)-1)+1),whistofull[i]);
	    }
	  }
	}
    
	if((tot<TOT && e<tot) || tot==TOT){
	  TBox b;
	  TLine li,liva1;
	  li.SetLineColor(38);
	  li.SetLineStyle(4);
	  li.SetLineWidth(2);
	  liva1.SetLineColor(42);
	  liva1.SetLineStyle(3);
	  liva1.SetLineWidth(1);

	  Float_t va1x=0,maxhist=4500.,minhist=-500.;

	  if(va1!=0){
	    cva[e]->cd();
	    pad->Draw();
	    pad->cd();
	    pad->SetFillColor(10);
	    histova[e]->SetTitleSize(0.01);
	    histova[e]->GetYaxis()->SetRangeUser(1500,4500);
	    histova[e]->SetLineColor(40);
	    histova[e]->SetFillColor(40);
	    histova[e]->SetLineWidth(1);
	    histova[e]->SetLineStyle(2);
	    //	    histova[e]->GetYaxis()->SetLabelSize(0.03);
	    histova[e]->Draw("");
	    cva[e]->Update();
	  }

	  c1[e]->cd();           
	  trkpadtext[nn]->Draw();
	  trkpad[nn]->Draw();
	  trkpad[nn]->cd();
	  trkpad[nn]->SetFillColor(10);

	  histocomp[nn][e]->SetTitleSize(0.1);
	  histocomp[nn][e]->GetYaxis()->SetRangeUser(-500,4500);
	  histocomp[nn][e]->SetLineStyle(1);
	  histocomp[nn][e]->SetLineColor(38);
	  histocomp[nn][e]->SetFillColor(38);
	  histocomp[nn][e]->SetLineWidth(1);
	  histocomp[nn][e]->Draw("");

	  histofull[nn][e]->SetLineColor(40);
	  histofull[nn][e]->SetFillColor(40);
	  histofull[nn][e]->SetLineWidth(1);
	  histofull[nn][e]->SetLineStyle(2);

	  histomax[nn][e]->SetLineColor(2);
	  histomax[nn][e]->SetLineWidth(1);
	  histomax[nn][e]->SetLineStyle(3);

	  if(ifull[nn]==1) histofull[nn][e]->Draw("9bsame][");
	  if(icomp[nn]==1) histocomp[nn][e]->Draw("9bsame][");
	  if(imax[nn]==1) histomax[nn][e]->Draw("same][");
	  histocomp[nn][e]->Draw("axis same");
	  
	  b.SetFillColor(19);
	  b.SetFillStyle(3945);
	  if(nn==0){
	    b.DrawBox(0.,minhist,2047.,maxhist);
	  }
	  else if(nn==1){
	    b.DrawBox(128.,minhist,256.,maxhist);
	    b.DrawBox(384.,minhist,512.,maxhist);
	    b.DrawBox(896.,minhist,1024.,maxhist);
	    b.DrawBox(2048.,minhist,2432.,maxhist);
	    b.DrawBox(2816.,minhist,2944.,maxhist);
	    b.DrawBox(2944.,minhist,3070.,maxhist);
	  }
	  else if(nn==3){
	    b.DrawBox(0.,minhist,256.,maxhist);
	    b.DrawBox(2816.,minhist,3070.,maxhist);
	  }
	  else if(nn==4){
	    b.DrawBox(256.,minhist,512.,maxhist);
	    b.DrawBox(1792.,minhist,1920.,maxhist);
	    b.DrawBox(2816.,minhist,3070.,maxhist);
	  }
	  else if(nn==5){
	    b.DrawBox(0.,minhist,256.,maxhist);
	    b.DrawBox(896.,minhist,1024.,maxhist); 
	    b.DrawBox(1664.,minhist,1792.,maxhist);      
	  }
	  else if(nn==6){
	    b.DrawBox(512.,minhist,768.,maxhist);
	    b.DrawBox(1024.,minhist,1280.,maxhist);
	    b.DrawBox(1280.,minhist,1792.,maxhist); 
	    b.DrawBox(2560.,minhist,2816.,maxhist);
	  }
	  else if(nn==7){
	    b.DrawBox(0.,minhist,1535.,maxhist);
	    b.DrawBox(2024.,minhist,2280.,maxhist);
	  }
	  else if(nn==8){
	    b.DrawBox(512.,minhist,768.,maxhist);
	  }
	  else if(nn==9){
	    b.DrawBox(0.,minhist,128.,maxhist);
	    b.DrawBox(256.,minhist,384.,maxhist);
	    b.DrawBox(512.,minhist,640.,maxhist);
	    b.DrawBox(896.,minhist,1152.,maxhist);
	    b.DrawBox(1280.,minhist,1535.,maxhist);
	    b.DrawBox(1664.,minhist,1920.,maxhist);
	    b.DrawBox(2048.,minhist,2304.,maxhist);
	  }
	  else if(nn==10){
	    b.DrawBox(0.,minhist,512.,maxhist);
	    b.DrawBox(1024.,minhist,3070.,maxhist);
	  }
	  else if(nn==11){
	    b.DrawBox(0.,minhist,512.,maxhist);
	    b.DrawBox(768.,minhist,1024.,maxhist);
	    b.DrawBox(1536.,minhist,1664.,maxhist);
	    b.DrawBox(1920.,minhist,2560.,maxhist);
	    b.DrawBox(2816.,minhist,3070.,maxhist);
	  }                    
	  for(int va=1; va<24; va++){
	    va1x=128*va;
	    liva1.DrawLine(va1x,minhist,va1x,maxhist);
	  }
	  li.DrawLine(1024.5,minhist,1024.5,maxhist);
	  li.DrawLine(2048.5,minhist,2048.5,maxhist);
	  c1[e]->Update();
	}
	
      }
    }//end loop on views
    
    if((tot<TOT && e<tot) || tot==TOT){
      stringstream nom1,nom2,nom3;
      nom1<<out<<ffile<<"_FTrkScanQLook_EXPERT.ps(";
      nom2<<out<<ffile<<"_FTrkScanQLook_EXPERT.ps";
      nom3<<out<<ffile<<"_FTrkScanQLook_EXPERT.ps)";
      
      if(!strcmp(outfile.Data(),"ps")||!strcmp(outfile.Data(),"pdf")){
	if(e==0){
	  c1[e]->Print(nom1.str().c_str(),"Landscape");
	  if(va1!=0) cva[e]->Print(nom2.str().c_str(),"Landscape");
	}
	if(e>0 && tot>2){
	  c1[e]->Print(nom2.str().c_str(),"Landscape");
	  if(va1!=0) cva[e]->Print(nom2.str().c_str(),"Landscape");
	}
	if(e==tot-1){
	  c1[e]->Print(nom2.str().c_str(),"Landscape");
	  if(va1!=0) cva[e]->Print(nom3.str().c_str(),"Landscape");
	}
      }
      else{
	figsav+="."+outfile;
	c1[e]->Print(figsav.Data());
	if(va1!=0){
	  figsava+="."+outfile;
	  cva[e]->Print(figsava.Data());
	}
      }
    }
    if(value%10!=0){
      if(totvalues==TOT || (totvalues<TOT && e<totvalues))
	values << (short int)0 << endl << endl;
    }
  }
  stringstream com;
  
  values.close();
  if(value==0){
    com<<"rm -f "<<fname;
    system(com.str().c_str());
  }
  //
  // Convert ps to pdf if required
  if(!strcmp(outfile.Data(),"pdf")){
    com<<"ps2pdf13 "<<out<<ffile<<"_FTrkScanQLook_EXPERT.ps "<<out<<ffile<<"_FTrkScanQLook_EXPERT.pdf";
    system(com.str().c_str());
    printf("\n---> ps file converted in pdf format!\n");
    com.str("");
    com<<"rm -f "<<out<<ffile<<"_FTrkScanQLook_EXPERT.ps ";
    system(com.str().c_str());
    printf("---> ps file removed!\n\n");
    com.str("");
  }
  
  return;
}
