#include <stdlib.h>
 
#include <stdio.h>
 
#include <stdint.h>
 
#include "daq.h"
 
#include "H1D.h"
 
#include "H2D.h"
 
#include "PETProjDataMgr.h"
 
 
 
double gAdc[MAXCH];  // raw ADC ji
 
float  gNtdata[MAXCH*3];
 
int m_write=0;
 
 
 
double gData[MAXCH]; // korigirani ADC ji
 
 
 
float gSum[MAXPMT];
 
float gRawSum[MAXPMT];
 
float gMax[MAXPMT];
 
float gSumCluster[MAXPMT];
 
int   gNabove[MAXPMT];
 
 
 
 
 
 
 
 
 
 
 
double GetEnergy(int ch, int adc) {
 
        return (adc-conf.apedestals[ch])/(conf.apeak[ch]-conf.apedestals[ch])*conf.peakscaling;
 
}
 
 
 
 
 
 
 
int  GetGlobalPosition(int ipmt, double angle, float cx, float cy, float *gposition) {
 
 
 
        double phi = angle + conf.module[ipmt].phi;
 
        double r   = conf.module[ipmt].r;
 
        double sinphi 
= sin(phi
);  
        double cosphi 
= cos(phi
);  
 
 
        gposition[0]= cosphi* r + sinphi * cx ;
 
        gposition[1]= sinphi* r - cosphi * cx ;
 
        gposition[2]= cy;
 
 
 
        //if (m_debug) printf(  "[%d] phi=%f %f global ( %f , %f , %f )\n" ,ipmt,  module[ipmt].phi,angle, rv.x(), rv.y(), rv.z());
 
        return  0;
 
}
 
 
 
 
 
int GetRealPosition(int ipmt, float px,float py,float *cx,float *cy) {
 
        // iz CoG izracuna pozicijo na kristalu
 
 
 
        int binx = 0; //####m_crystalid[ipmt]->GetXaxis()->FindBin(px);
 
        int biny = 0; //####m_crystalid[ipmt]->GetYaxis()->FindBin(py);
 
        int crystalid  = 0;//####m_crystalid[ipmt]->GetBinContent(binx,biny);
 
        *cx= ( crystalid % conf.nofcrystalsx - conf.nofcrystalsy/2. + 0.5 ) * conf.crystalpitchx;
 
        *cy= ( crystalid / conf.nofcrystalsx - conf.nofcrystalsx/2. + 0.5 ) * conf.crystalpitchy;
 
 
 
 
 
        // razmazi pozicijo po povrsini kristala
 
        double rndx = Random(-0.5,0.5)* conf.crystalpitchx;
 
        double rndy = Random(-0.5,0.5)* conf.crystalpitchy;
 
        *cx+= rndx;
 
        *cy+= rndy;
 
        return crystalid;
 
}
 
 
 
 
 
int HistogramsInit() {
 
 
 
        if (conf.write) {
 
                char varlist[1024], tmplist[1024];
 
                sprintf( varlist
,"sum0:sum1:sum2:sum3:nh0:nh1:nh2:nh3:c0:c1:c2:c3:px0:px1:px2:px3:py0:py1:py2:py3:rx0:rx1:rx2:rx3:ry0:ry1:ry2:ry3:max0:max1:max2:max3");  
                for (int i=0; i<MAXCH; i++) {
 
                        sprintf(varlist
,"%s:a%d",tmplist
,i
);  
                }
 
                /*
 
                        energija .. (adc -pedestal) * scaling
 
 
 
                        sum0 .. sum3 vsota energij po vseh kanalih fotopomnozevalke
 
                        nh0  .. nh4   stevilo zadetkov na fotopomnozevalki (adc nad thresholdom)
 
                        c0   .. c4 vsota energij za kanale nad thresholdom
 
                        px0  .. px4 x koordinata COG na fotopomnozevalki
 
                        py0  .. py4 y koordinata COG na fotopomnozevalki
 
                        max0 .. max3 maximalna energija na kanalu na fotopomnozevalki
 
                        a0   .. a63 energija na i-tem kanalu
 
                */
 
                //gNtuple = new TNtuple("nt","Pet RAW data",varlist);
 
        }
 
        m_Nhits = H2D_Init(301,"hnabove","Stevilo zadetkov nad nivojem diskriminacije",4,-0.5,3.5, 16,+0.5,16.5 );  // stevilo hitov nad thresholdom
 
        m_GlobalPosition =H2D_Init(302,"globalxy","Rekonstruirana koordinata zadetka",200,-80,80,200,-80,80);  // reconstruirana koordinata v globalnem sistemu
 
 
 
 
 
        char hname[0xFF];
 
        char hn[0xFF];
 
        int i;
 
        for (i=0; i<MAXCH; i++) {
 
                sprintf(hname
,"Raw ADC Ch. %d ;ADC;N",i
);  
                //m_Adc[i]   = H1D_Init(i,hn,hname,4000,-0.5,3999.5);       // osnovni adcji
 
                m_Adc[i]   = H1D_Init(i,hn,hname,400,500-0.5,899.5);       // osnovni adcji
 
                sprintf(hname
,"cADC za dogodke z manj kot x hitov na pmtju Ch. %d ;ADC;N",i
);  
                m_AdcCut[i]   = H1D_Init(i+MAXCH, hn,hname,4000,-0.5,3999.5);    // adcji za zadetke z manj kot 7 hiti na PMTju
 
                sprintf(hname
,"cADC proti stevilu zadetkov na pmtju Ch. %d ;ADC;N",i
);  
                m_Adc_vs_Nhits[i]   = H2D_Init(i,hn,hname,200,0,4000, 17,-0.5,16.5); // adc proti stevilu zadetkov na PMTju
 
                sprintf(hname
,"cADC proti vsoti kanalov na pmtju,  Ch. %d ;ADC;ADCsum",i
);  
                m_Adc_vs_Sum[i]   = H2D_Init(i+MAXCH,hn,hname,200,0,4000, 200,0,12000 );  // raw adc proti vsoti kanalov na PMTju
 
                sprintf(hname
,"Raw ADC proti vsoti kanalov na pmtju,  Ch. %d ;ADC;ADCsum",i
);  
                m_Adc_vs_Sum_Uncorected[i]   =H2D_Init(i+MAXCH*2,hn,hname,100,0,3500, 100,5000,12000 );  // adc proti vsoti kanalov na PMTju
 
        }
 
 
 
        for (i=0; i<MAXPMT; i++) {
 
                sprintf(hname
,"Vsota cADC na PMTju %d ;ADC;N",i
);  
                m_AdcSum[i]   =H1D_Init(200+i,hn,hname,200,0,20000); // vsota adcjev na PMTju
 
                sprintf(hname
,"Vsota cADC na PMTju za dogodke z manj kot x zadetki %d ;ADC;N",i
);  
                m_AdcSumCluster[i]   = H1D_Init(216+i,hn,hname,200,0,20000);  // vsota adcjev na pmtju, ki so nad threshholdom,  za dogodke z manj kot 5 zadetki na PMTju
 
 
 
                sprintf(hname
,"Center naboja CoG PMT %d ;x;y",i
);  
                m_CenterOfGravity[i]   =H2D_Init(200+i,hn,hname,200,-1.25,4.25,200,-1.25,4.25); // center naboja na PMTju
 
 
 
                sprintf(hname
,"Center naboja CoG za zadetke nad thresholdom PMT %d ;x;y",i
);  
                m_CenterOfGravityforChAboveThreshold[i] = H2D_Init(216+i,hn,hname,200,0,3,200,0,3);  // center naboja za zadetke nad thresholdom
 
 
 
                sprintf(hname
,"Rekonstruirana koordinata PMT %d ;x(mm);y(mm)",i
);  
                m_ReconstructedPosition[i]   = H2D_Init(232+i,hn,hname,200,-12,12,200,-12,12); // korigirana koordinata na pmtju
 
 
 
                sprintf(hname
,"SumAdc PMT %d ;SumAdc(a.u.);crystal ID",i
);  
                m_SumAdc[i]   =H2D_Init(248+i,hn,hname,200,0,12000,81,-0.5,80.5); // SumADC spekter za razlicne kristale
 
        }
 
 
 
        // store mapping
 
        //TH1I *hx= new TH1I("mapping", "ch mapping", 16, -0.5,15.5);
 
        //for (int j=0;j<16;j++) hx->Fill(j,m_geo->ch[j].idx);
 
 
 
        return 0;
 
};
 
 
 
int HistogramsWrite(const char *fname){
 
        FILE 
*fp 
= fopen(fname
, "wb"); 
        
 
        if (fp){
 
          int i; 
 
                for (i=0;i<H1DMAX;i++){ if (H1D_Exist(i)) H1D_Write2File(i, fp); }
 
                for (i=0;i<H2DMAX;i++){ if (H2D_Exist(i)) H2D_Write2File(i, fp); } 
 
                for (i=0;i<H3DMAX;i++){ if (H3D_Exist(i)) H3D_Write2File(i, fp); } 
 
        
 
        }
 
 
 
        return 0;
 
}
 
 
 
 
 
int HistogramsFill() {
 
        int i=0, ipmt;
 
        for (i=0; i<MAXCH; i++) { // zanka cez vse elektronske kanale;
 
                float x=gData[i];
 
                int ipmt= i/16;
 
                float s=gSum[ipmt];
 
                // int idx= 2*(ipmt)+64;
 
                // const  float fSlope1=2;
 
                // const  float fSlope2=3;
 
                //  if ( ((s-gSumPedestals[ipmt] ) > fSlope1*(x-gPedestals[i])) && ((s-gSumPedestals[ipmt] ) < fSlope2*(x-gPedestals[ipmt])) ) {
 
                if (gNabove[ipmt]<7) {
 
                        H2D_Fill(m_Adc_vs_Sum[i],x,s,1);
 
                        H2D_Fill(m_Adc_vs_Sum_Uncorected[i], gAdc[i],gRawSum[ipmt],1);
 
                        H1D_Fill(m_AdcCut[i],x,1);
 
                }
 
        }
 
 
 
        HVector3 r_coincidence[2];
 
        for (int k=0; k<2; k++) for (int i1=0; i1<3; i1++)  r_coincidence[k].x[i1]=0;
 
        int  f_coincidence[2]= {0,0};
 
 
 
        for (ipmt=0; ipmt<4; ipmt++) { // zanka preko pmtjev
 
                int j2= (ipmt/2)*2+1-ipmt%2;  // sosednja fotopomnozevalka
 
 
 
                float posx[2]= {0,0};
 
                float posy[2]= {0,0};
 
                float sum[2]= {0,0};
 
                for (int ich=0; ich<16; ich++) { // zanka preko elektronskih kanalov na fotopomnozevalki
 
                        int ch= ich+ipmt*16;
 
                        if (gMax[ipmt]>conf.adcthreshold) {
 
                                posx[0]+= gData[ch]*conf.channel[ich].ix;
 
                                posy[0]+= gData[ch]*conf.channel[ich].iy;
 
                                sum[0] += gData[ch];
 
 
 
                                if (gData[ch]> 0.1*gMax[ipmt]) { // pri racunanju pozicije upostevaj le kanale, ki imajo vrednost vecjo od ratio*maksimalna na tisti fotopomnozevalki ********
 
                                        posx[1]+= gData[ch]*conf.channel[ich].ix;
 
                                        posy[1]+= gData[ch]*conf.channel[ich].iy;
 
                                        sum[1] += gData[ch];
 
                                }
 
                        }
 
                }
 
 
 
                if (m_write) {
 
                        gNtdata[12+ipmt]=posx[0]/sum[0];
 
                        gNtdata[16+ipmt]=posy[0]/sum[0];
 
                        gNtdata[20+ipmt]=(sum[1]>0)?posx[1]/sum[1]:-10;
 
                        gNtdata[24+ipmt]=(sum[1]>0)?posy[1]/sum[1]:-10;
 
                        gNtdata[28+ipmt]=sum[0];
 
                }
 
                if (gMax[ipmt]>gMax[j2]) { // izberi fotopomnozevalko, ki ima vec zadetkov kot soseda TRG= (P1|P2) & (P3|P4)
 
 
 
                        if ( sum[0] > 0  ) {
 
                                float px=posx[0]/sum[0];
 
                                float py=posy[0]/sum[0];
 
 
 
                                H2D_Fill(m_CenterOfGravity[ipmt],px,py,1);
 
 
 
                                float cx=0; //koordinata na pmtju
 
                                float cy=0;
 
                                int crystalID = GetRealPosition(ipmt,px,py,&cx,&cy);
 
                                H2D_Fill(m_ReconstructedPosition[ipmt],cx,cy,1);
 
                                H2D_Fill(m_SumAdc[ipmt],gSum[ipmt], crystalID,1 );
 
                                if (debug 
> 2) printf("ipmt=%d cx=%f cy=%f\n",ipmt
,cx
,cy
);  
                                GetGlobalPosition(ipmt, conf.rotation, cx, cy,r_coincidence[ipmt/2].x) ;
 
                                f_coincidence[ipmt/2] =1;
 
                                H2D_Fill(m_GlobalPosition,r_coincidence[ipmt/2].x[0],r_coincidence[ipmt/2].x[1],1);
 
 
 
                        }
 
                        if ( sum[1] > 0  ) {
 
 
 
                                float px=posx[1]/sum[1];
 
                                float py=posy[1]/sum[1];
 
                                // float px0=posx[0]/sum[0];
 
                                // float py0=posy[0]/sum[0];
 
                                // if (px0<0.25 || px0>2.75 ||  py0< 0.25 || py0> 2.75)
 
                                // if  (((py0>0.75 && py0<1.25) || (py0>1.75 && py0<2.25))  &&  (px0< 0.25 || px0>2.75 ) )
 
                                H2D_Fill(m_CenterOfGravityforChAboveThreshold[ipmt],px,py,1);
 
                        }
 
 
 
                }
 
        }
 
 
 
        for (i=0; i<MAXCH; i++) if (gData[i]>conf.adcthreshold) {
 
                        H2D_Fill(m_Adc_vs_Nhits[i],gData[i],gNabove[i/16],1);
 
                }
 
        for (i=0; i<MAXCH; i++) if (gData[i]>conf.adcthreshold && gNabove[i/16]<5 ) {
 
                        gSumCluster[i/16]+=gData[i];
 
                }
 
        for (ipmt=0; ipmt<4; ipmt++) {
 
                H1D_Fill(m_AdcSum[ipmt],gSum[ipmt],1);
 
                H1D_Fill(m_AdcSumCluster[ipmt],gSumCluster[ipmt],1);
 
        }
 
 
 
        for (i=0; i<4; i++) H1D_Fill(m_Nhits,i,gNabove[i]);
 
 
 
        if (m_write) {
 
                for (i=0; i<4; i++) {
 
                        gNtdata[i]=gSum[i];
 
                        gNtdata[4+i]=gNabove[i];
 
                        gNtdata[8+i]=gSumCluster[i];
 
                }
 
                for (i=0; i<MAXCH; i++) gNtdata[32+i]=gData[i];
 
                //gNtuple->Fill(gNtdata);
 
        }
 
        //
 
        // coincidences
 
        //
 
        if (f_coincidence[0]&&f_coincidence[1]) {
 
                conf.coincidences++;
 
                if (debug > 1) {
 
                        printf(  "Coincidence ( %f , %f , %f ) ( %f , %f , %f )\n" ,  
                                                         r_coincidence[0].x[0], r_coincidence[0].x[1], r_coincidence[0].x[2],
 
                                                         r_coincidence[1].x[0], r_coincidence[1].x[1], r_coincidence[1].x[2] );
 
                }
 
                AddEvent( r_coincidence[0] , r_coincidence[1]);
 
        }
 
        return 0;
 
};
 
 
 
 
 
 
 
int analyse(int nb, uint32_t *buf) {
 
 
 
        int idx=1;
 
        int neve=buf[0]/2;
 
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
        for (int nev=0; nev<neve; nev++) {
 
                int len=buf[idx];
 
                int sb =buf[idx+1];
 
                unsigned int *pbuf=&buf[idx+2];
 
                if (sb!=0xffab) {
 
                        printf("0x%04x!0xffab len=%d\n",sb
,len
);  
                        break;
 
                }
 
                // postavi na nic
 
#define InitArrayWithAValue(arr,n,x) {for (int i=0;i<n;i++) arr[i]=x;}
 
 
 
                //------------------------------------------------------------
 
                // postavi na nic
 
 
 
                InitArrayWithAValue( gSum       , MAXPMT    , 0);
 
                InitArrayWithAValue( gRawSum    , MAXPMT    , 0);
 
                InitArrayWithAValue( gMax       , MAXPMT    , 0);
 
                InitArrayWithAValue( gSumCluster, MAXPMT    , 0);
 
                InitArrayWithAValue( gNabove    , MAXPMT    , 0);
 
                InitArrayWithAValue( gData      , MAXCH, 0);
 
                InitArrayWithAValue( gAdc       , MAXCH, 0);
 
                for (int i0=0; i0<len-2; i0+=2) {
 
 
 
                        int data0  = pbuf[i0];
 
                        int data1  = pbuf[i0+1];
 
                        int geo    = (data1 >> 11) & 0x1f;
 
                        int ch     = (data1&0x1f)  | (geo<<5);
 
                        int dtype  = (data1>>9)&0x3;
 
                        int adc    =  data0&0xfff;
 
                        if (dtype == 0 & ch<MAXCH) {
 
                                if (debug
)      printf("%d ADC %d %d\n", geo
, ch
, adc
);  
                                if (ch<MAXCH) H1D_Fill(ch, adc,1);
 
                                int ipmt = ch/16;
 
 
 
                                gAdc[ch]=adc;
 
                                gRawSum[ipmt]+=adc;
 
 
 
                                gData[ch]=GetEnergy(ch,adc);
 
 
 
                                gSum[ipmt]+=gData[ch];
 
                                if (gData[ch]   >gMax[ipmt] )     gMax[ipmt]= gData[ch];
 
                                if (gData[ch]   >conf.adcthreshold )    gNabove[ipmt]++;
 
                                //#### m_Adc[ch]->Fill(adc);
 
                        }
 
                };// for (int i0=0;i0<len-2;i0+=2)
 
                //------------------------------------------------------------
 
 
 
                idx+=len+1;
 
                HistogramsFill();
 
                if (m_write) {
 
                        gNtdata[0]=0;
 
                        for (int i=0; i<MAXCH; i++) gNtdata[i+1]=gAdc[i];
 
                        //####gNtuple->Fill(gNtdata);
 
                }
 
 
 
        } // for (int nev=0;nev<neve;nev++)
 
 
 
 
 
 
 
 
 
        return 0;
 
}