Skip to content
Snippets Groups Projects
raw.cc 24.98 KiB
/*
 * raw.cc  --  analyze "raw" (L0) data and produce the preprocessed "preliminary" (L1) data set.
 *
 *  Copyright (C) 2012-TODAY The LAGO Project, http://lagoproject.org, lago-pi@lagoproject.org
 *
 *  Original authors: Hernán Asorey, Xavier Bertou
 *  e-mail: asoreyh@cab.cnea.gov.ar  (asoreyh@gmail.com)
 *  Laboratorio de Detección de Partículas y Radiación (LabDPR)
 *  Centro Atómico Bariloche - San Carlos de Bariloche, Argentina
 */

/*
 *  LICENSE GPLv3
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. */

/*  -*- coding: utf8 -*-
 *  try to preserve encoding  */
/************************************************************************/
#define _FILE_OFFSET_BITS 64

#include <string.h>
#include <string.h>
#include <vector>
#include <fstream>
using namespace std;

#include "lago_data.h"
#include "lago_file.h"

#define MAXPULSEPERSEC 1000000
#define MAXTIMEINVECTOR 40000

#define SCL_LEVELS 4
#define SCL_BINS 200
#define SCL_TIME (1./SCL_BINS)
#define SCL_CLOCK (SCL_TIME/25e-9)

// action flags. Should be improved with a class
int ical=0, itim=0, isol=0, iall=0, imon=0, force=0, ivalid=0;
int izip=0, iscl=0, isclg=0, itrg=0, irte=0, iflx=0, ineg[3]= {0,0,0};

// OLD SCALER ANALYSIS
// levels should be given above baseline or threshold (-lt modifier).
// With the new electronics there is no undershoot analysis
int scl_level[CHANNELS][SCL_LEVELS];
int scl_scalers[CHANNELS][SCL_LEVELS][SCL_BINS];
int scl_default[SCL_LEVELS] = { 30, 50, 100, 300};
int scl_prv_trigger = 0;
int scl_flux[CHANNELS];

// FLUX ANALYSIS
int flx_default = 60, flx_time = 0;
int flx_tots_sum = 0, flx_tots_sum_2 = 0;
int flx_sum[CHANNELS], flx_sum_2[CHANNELS];
double flx_aux = 0.;
double flx_temp_sum = 0., flx_temp_sum_2 = 0.;
double flx_pres_sum = 0., flx_pres_sum_2 = 0.;
double flx_temp_avg = 0., flx_temp_dev = 0.;
double flx_pres_avg = 0., flx_pres_dev = 0.;
double flx_tots_avg = 0., flx_tots_dev = 0.;
double flx_avg[CHANNELS], flx_dev[CHANNELS];

// OFFLINE TRIGGER
int trg_level[CHANNELS];
int trg_default = 85;

// TIME DIFFERENCE (AND ALSO ALL PULSE DATA) ANALYSIS
int tim_pc = 0, tim_pt = 0, tim_dc = 0, tim_dt = 0;
double tim_ap = 0., tim_map = 0.;

// ALL PULSE DATA ANALYSIS
int all_trg = 0;

ofstream cal, tim, mon;
FILE *scl, *sol, *all, *rte, *flx;

int Peak[CHANNELS][1024];
int Base[CHANNELS][1024];
int Charge[CHANNELS][4096];
int ECharge[CHANNELS][4096];
int Time[CHANNELS][MAXTIMEINVECTOR];

int Peak_minute[CHANNELS][1024];
int Charge_minute[CHANNELS][4096];

void TreatSecond(LagoGeneric *Data, LagoEvent*Pulse, int NbPulses) {
	if (((Data->second)%36)==0)
		cerr << "Done " << ((Data->second)%3600)/36 << "%\r";
	if (!NbPulses) {
		if (iscl)
			fprintf(scl, "# s %d %d %.2f %.2f\n", Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
		return;
	}
	if (iall)
		fprintf(all, "# %d %d %.2f %.2f\n", Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
	if (imon)
		mon << Data->second << " " << Data->clockfrequency << " " << Data->temperature << " " << Data->pressure << " " << endl;

	for (int j=0; j<CHANNELS; j++)
		scl_flux[j] = 0;

	int scl_idx = 0;
	int scl_peak = 0;
	for (int i=0; i<NbPulses; i++) {
		int trg_drop = 0;
		if (itrg)
			for (int j=0; j<CHANNELS; j++)
				if (Pulse[i].IsTriggered(j))
					if (Pulse[i].GetValAtTrigger(j) < trg_level[j])
						trg_drop++;
		if (itrg && trg_drop)
			continue;
		for (int j=0; j<CHANNELS; j++) { //count all channels, not only those triggered
			Peak[j][Pulse[i].GetPeak(j)]++;
			Charge[j][Pulse[i].GetCharge(j,ineg[j])]++;
			Base[j][Pulse[i].GetBase(j)]++;
			scl_flux[j]++;
			if (iscl) {
				scl_idx = (int)(Pulse[i].clockcount / SCL_CLOCK);
				scl_peak = Pulse[i].GetPeak(j);
				if (isclg)
					scl_peak += BASELINE;
				for (int k=0; k<SCL_LEVELS; k++) {
					if (scl_peak >= scl_level[j][k]) {
						scl_scalers[j][k][scl_idx]++;
					}
				}
			}
		}

		if (iall || itim) {			
			// for both cases we need to calculate time difference between consecutive pulses...
			tim_dc = Pulse[i].counter - tim_pc;
			if (tim_dc < 0)
				tim_dc += 40000000;
			tim_dt = Pulse[i].clockcount - tim_pt;
			if (tim_dt < 0)
				tim_dt += 40000000;

			if (itim) {// Time difference analysis
				if (tim_dc == 1) { // use this pulse for time analysis
					if (tim_dt < MAXTIMEINVECTOR) { // this pulse could fit in the times array
						for (int j=0; j<CHANNELS; j++) {
							if (Pulse[i].IsTriggered(j)) { // only use triggered channel
								if (tim_map) { //aop filter is enabled
									tim_ap = Pulse[i].GetCharge(j,ineg[j]) / Pulse[i].GetPeak(j);
									if (tim_ap > tim_map) // that's ok
										Time[j][tim_dt]++; //Finally
								}
								else {
									Time[j][tim_dt]++; //Finally
								}
							}
						}
					}
				}
			}
			if (iall) {
				fprintf(all, "%d %d %d", tim_dt * 25, tim_dc, Pulse[i].trigger);
				for (int j=0; j<CHANNELS; j++)
					if (Pulse[i].IsTriggered(j)) fprintf(all, " %d %d", Pulse[i].GetCharge(j,ineg[j]), Pulse[i].GetPeak(j));
				fprintf(all, "\n");
			}
			tim_pc = Pulse[i].counter;
			tim_pt = Pulse[i].clockcount;
		} // end of tim and all sector
	} // close loop for all pulses

	if (iflx) {
		if (flx_time == flx_default) {
			// averages
			flx_temp_avg = flx_temp_sum / flx_time;
			flx_pres_avg = flx_pres_sum / flx_time;
			flx_tots_avg = flx_tots_sum / flx_time;
			for (int j=0; j<CHANNELS; j++)
				flx_avg[j] = flx_sum[j] / flx_time;

			// devs
			if (flx_time > 1)
				flx_aux = flx_time / (flx_time - 1);
			else
				flx_aux = 1.;
			flx_temp_dev = sqrt(flx_aux * ( flx_temp_sum_2 / flx_time - flx_temp_avg * flx_temp_avg));
			flx_pres_dev = sqrt(flx_aux * ( flx_pres_sum_2 / flx_time - flx_pres_avg * flx_pres_avg));
			flx_tots_dev = sqrt(flx_aux * ( flx_tots_sum_2 / flx_time - flx_tots_avg * flx_tots_avg));
			for (int j=0; j<CHANNELS; j++)
				flx_dev[j] = sqrt(flx_aux * ( flx_sum_2[j] / flx_time -  flx_avg[j] *  flx_avg[j]));

			// print
			fprintf (flx, "%d %.2f %.2f %.2f", Data->second - int(flx_time / 2.), flx_temp_avg, flx_pres_avg, flx_tots_avg);
			for (int j=0; j<CHANNELS; j++)
				fprintf (flx, " %.2f", flx_avg[j]);
			fprintf (flx, " %.2f %.2f %.2f", flx_temp_dev, flx_pres_dev, flx_tots_dev);
			for (int j=0; j<CHANNELS; j++)
				fprintf (flx, " %.2f", flx_dev[j]);
			fprintf (flx, "\n");
			// clean
			flx_time = 0;
			flx_temp_sum = flx_pres_sum = flx_temp_sum_2 = flx_pres_sum_2 = 0.;
			flx_tots_sum = flx_tots_sum_2 = 0;
			for (int j=0; j<CHANNELS; j++)
				flx_sum[j] = flx_sum_2[j] = 0;
		}
		flx_time++;
		flx_temp_sum += Data->temperature;
		flx_pres_sum += Data->pressure;
		flx_tots_sum  += NbPulses;
		flx_temp_sum_2 += Data->temperature * Data->temperature;
		flx_pres_sum_2 += Data->pressure * Data->pressure;
		flx_tots_sum_2  += NbPulses * NbPulses;
		for (int j=0; j<CHANNELS; j++) {
			flx_sum[j] += scl_flux[j];
			flx_sum_2[j] += scl_flux[j] * scl_flux[j];
		}
	}

	if (isol) {
		if (((Data->second)%60)==0) { // every minute, histograms
			fprintf(sol, "# q %d %d %.2f %.2f\n", Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
			for (int i=0; i<CHANNELS; i++) {
				fprintf(sol, "0 %d %d %d %.2f %.2f", i, Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
				for (int j=0; j<4096; j++) {
					fprintf(sol, " %d", Charge[i][j]-Charge_minute[i][j]);
					Charge_minute[i][j]=Charge[i][j];
				}
				fprintf(sol, "\n");
			}
			fprintf(sol, "# p %d %d %.2f %.2f\n", Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
			for (int i=0; i<CHANNELS; i++) {
				fprintf(sol, "1 %d %d %d %.2f %.2f", i, Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
				for (int j=0; j<1024; j++) {
					fprintf(sol, " %d", Peak[i][j]-Peak_minute[i][j]);
					Peak_minute[i][j]=Peak[i][j];
				}
				fprintf(sol, "\n");
			}
		}
	}

	if (irte) {
		fprintf(rte, "%d %.2f %.2f", Data->second, Data->temperature, Data->pressure);
		fprintf(rte, " %d",NbPulses);
		for (int j=0; j<CHANNELS; j++)
			fprintf(rte, " %d", scl_flux[j]);
		fprintf(rte, "\n");
	}

	if (iscl) {
		fprintf(scl, "# s %d %d %.2f %.2f", Data->second, Data->clockfrequency, Data->temperature, Data->pressure);
		fprintf(scl, " %d",NbPulses);
		for (int j=0; j<CHANNELS; j++) {
			fprintf(scl, " %d", scl_flux[j]);
		}
		fprintf(scl, "\n");
		for (int l=0; l<SCL_BINS; l++) {
			for (int j=0; j<CHANNELS; j++) {
				for (int k=0; k<SCL_LEVELS; k++) {
					fprintf(scl,"%d ", scl_scalers[j][k][l]);
					scl_scalers[j][k][l] = 0;
				}
			}
			fprintf(scl,"\n");
		}
	}
}

void Usage(char *prog, int verbose=0)
{
	cout << endl << PROJECT << " " << VERSION << endl;
	cout << endl << "LAGO raw data analysis (L0 -> L1)" << endl << endl;
	cout << "Usage: " << prog << " [flags] raw_file" << endl;
	cout << "  Options (note they are case sensitive!):"<<endl;
	cout << "          -h: prints help and exits"<<endl;
	cout << "          -c: produces .cal calibration file"<<endl;
	cout << "          -s: produces .sol solar physics file"<<endl;
	cout << "          -t <a/p>: produces .tim time difference histogram file,"  << endl  << "              filtering by a/p is a value is given (default = no)"<<endl;
	cout << "          -r: produces .raw " << raw_limit << " second raw file copy"<<endl;
	cout << "          -a: produces .all.bz2 compressed file containing charge," << endl << "              peak, dc and dt for all pulses"<<endl;
	cout << "          -m: produces .mon monitoring file"<<endl;
	cout << "          -n <time>: produces .rte scaler file with total number of pulses" << endl << "              per second. It is enabled by default when -l option is used."<< endl << "              If time (in seconds) is given, it also produces a .flx (flux)" << endl << "              file with averaged rates over <time> seconds."<<endl;
	cout << "          -l: produces .scl scaler data file (old lago analysis)"<<endl;
	cout << "          -g: produces .scl scaler data file (old lago analysis), with" << endl << "              absolute thresholds (should be used with -l)"<<endl;
	cout << "          -v <channel (1-3)>: checks channel is correct (bits and baseline)"<<endl;
	cout << endl << "  Flags and modifiers:"<<endl;
	cout << "          -f: force analysis"<<endl;
	cout << "          -z: produces bzip2 compressed files (solar and scaler data)"<<endl;
	cout << "          -N <channel mask 1-7>: channels having negative undershoots"<<endl;
	cout << "          -l <ch>";
	for (int i=0; i<SCL_LEVELS; i++)
		cout << " <l" << i+1 << ">";
	cout << ": Define the " << SCL_LEVELS << " thresholds for" << endl << "              old-lago-like analysis on channel <ch>"<<endl;
	cout << "              Default thresholds: ";
	for (int i=0; i<SCL_LEVELS; i++)
		cout << scl_default[i] << " ";
	cout << endl;
	cout << "          -u <trigger ch1> <trigger ch2> <trigger ch3>: impose an offline" << endl << "              trigger level for each channel (default value: " << trg_default << " ADC)" << endl;
	cout << endl;
	if (verbose) {
		// verbose help
	}
	exit(1);
}

int main (int argc, char *argv[])
{
	LagoFile Input;

	char nfi[256];
	char *ifiname=NULL;
	int NbPulses=0;
	int scl_ch_set=0;

	// setting scaler levels (same for all channels)
	for (int i = 0; i < CHANNELS; i++)
		for (int j = 0; j < SCL_LEVELS; j++)
			scl_level[i][j] =  scl_default[j];

	// setting scaler counters to 0
	for (unsigned int i = 0; i < CHANNELS; i++)
		for (unsigned int j = 0; j < SCL_LEVELS; j++)
			for (unsigned int l = 0; l < SCL_LEVELS; l++)
				scl_scalers[i][j][l]=0;
	for (int i = 0; i < CHANNELS; i++)
		scl_flux[i] = 0;
	for (int i = 0; i < CHANNELS; i++)
		trg_level[i] = trg_default;

	LagoGeneric Data;
	LagoEvent *Pulse;
	Pulse=(LagoEvent*)malloc(MAXPULSEPERSEC*sizeof(LagoEvent));

	for (int i=0; i<MAXPULSEPERSEC; i++)
		Pulse[i].Init();

	for (int i=1; i<argc; i++) {
		char *tmparg=argv[i];
		if (*tmparg=='-')
			switch (*(tmparg+1)) {
			case 'f':
				force++;
				Input.SetForce(force);
				break;
			case 'c':
				ical=1;
				break;
			case 's':
				isol=1;
				break;
			case 'z':
				izip=1;
				break;
			case 't':
				itim=1;
				if (atof(argv[i+1])) { // false if not a/p value was given
					i++;
					tim_map = atof(argv[i]);
				}
				break;
			case 'r':
				iraw=1;
				break;
			case 'a':
				iall=1;
				break;
			case 'u':
				itrg=1;
				if (atoi(argv[i+1])) { // false if not trigger value was given. Use default levels
					for (int j = 0; j < CHANNELS; j++) {
						i++;
						if (atoi(argv[i])) {
							trg_level[j] = atoi(argv[i]);
						}
						else { // user didn't set the four levels (mandatory): try again.
							cerr << " Error: you must set one trigger level per channel" << endl;
							Usage(argv[0]);
							break;
						}
					}
				}
				break;
			case 'm':
				imon=1;
				break;
			case 'n':
				irte=1;
				if (atof(argv[i+1])) {
					i++;
					flx_default = atof(argv[i]);
					iflx = 1;
				}
				break;
			case 'g':
				isclg=1;
				break;
			case 'l':
				iscl=1;
				irte=1;
				if (atoi(argv[i+1])) { // false if not levels present. Use default levels
					i++;
					scl_ch_set = atoi(argv[i]);
					if (scl_ch_set > 0 && scl_ch_set <= CHANNELS) {
						scl_ch_set -= 1;
						for (int j = 0; j < SCL_LEVELS; j++) {
							i++;
							if (atoi(argv[i])) {
								scl_level[scl_ch_set][j] = atoi(argv[i]);
							}
							else { // user didn't set the four levels (mandatory): try again.
								cerr << " Error: you must set the four levels for channel " << scl_ch_set + 1 << endl << endl;
								Usage(argv[0]);
								break;
							}
						}
					}
					else {
						cerr << " Error: channel number not valid " << endl << endl;
						Usage(argv[0]);
						break;
					}
				}
				break;
			case 'N':
				i++;
				for (int j=0; j<CHANNELS; j++)
					ineg[j] = (atoi(argv[i]) & (1<<j));
				if (atoi(argv[i])<1 || atoi(argv[i])>7) {
					cerr << " Error: channel mask not valid " << endl << endl;
					Usage(argv[0]);
				}
				break;
			case 'v':
				i++;
				ivalid=atoi(argv[i]);
				if (ivalid<1 || ivalid>CHANNELS) {
					cerr << "Error: channel should be within 1-3" << endl;
					return 1;
				}
				break;
			case 'h':
			default:
				Usage(argv[0]);
				break;
			}
		else ifiname=argv[i];
	}
	if (!ifiname) {
		cerr << endl << "Error: Missing filename" << endl << endl;
		Usage(argv[0]);
	}
	snprintf(nfi,256,"%s",ifiname);
	if (isclg && !iscl) {
		cerr << endl << "Error: Try using -g -l" << endl << endl;
		Usage(argv[0]);
	}

	Input.Open(nfi);

	for (int j = 0; j < CHANNELS; j++)
		trg_level[j] -= BASELINE;

	char *ifile2;
	char ifile[256];
	ifile2=ifiname;
	if (strrchr(ifile2,'/')!=NULL) {
		ifile2=strrchr(ifile2,'/')+1;
	}
	snprintf(ifile, 256,"l1_%s_%s",VERSION,ifile2);
	if (strrchr(ifile,'.')!=NULL) {
		if (strncmp(strrchr(ifile,'.'),".bz2",4)==0) { // remove .bz2 if present
			*(strrchr(ifile,'.'))='\0';
		}
	}
	if (strrchr(ifile,'.')!=NULL) {
		if (strncmp(strrchr(ifile,'.'),".dat",4)==0) { // remove .dat if present
			*(strrchr(ifile,'.'))='\0';
		}
	}

	for (int i=0; i<CHANNELS; i++) {
		for (int j=0; j<1024; j++)
			Peak[i][j]=Peak_minute[i][j]=Base[i][j]=0;
		for (int j=0; j<4096; j++)
			ECharge[i][j]=Charge[i][j]=Charge_minute[i][j]=0;
		for (int j=0; j<MAXTIMEINVECTOR; j++)
			Time[i][j]=0;
	}

	if (ivalid)
		fprintf(stderr,"Validating channel %d\n",ivalid);

	if (ical) {
		snprintf(nfi,256,"%s.cal",ifile);
		cal.open(nfi);
	}

	if (itim) {
		snprintf(nfi,256,"%s.tim",ifile);
		tim.open(nfi);
	}

	if (iraw) {
		snprintf(nfi,256,"%s.raw",ifile);
		raw.open(nfi);
	}

	if (iall) {
		snprintf(nfi,256,"bzip2 -9z > %s.all.bz2",ifile);
		if ((all = popen(nfi,"w"))==NULL) {
			fprintf(stderr,"Failed to open compressed all particles file. Abort.\n");
			exit(1);
		}
	}

	if (imon) {
		snprintf(nfi,256,"%s.mon",ifile);
		mon.open(nfi);
	}
	if (irte) {
		snprintf(nfi,256,"%s.rte",ifile);
		if ((rte = fopen(nfi,"w"))==NULL) {
			fprintf(stderr,"Failed to open rate file. Abort.\n");
			exit(1);
		}
	}

	if (iflx) {
		snprintf(nfi,256,"%s.flx",ifile);
		if ((flx = fopen(nfi,"w"))==NULL) {
			fprintf(stderr,"Failed to open flux file. Abort.\n");
			exit(1);
		}
	}

	if (isol) {
		if (izip) {
			snprintf(nfi,256,"bzip2 -9z > %s.sol.bz2",ifile);
			if ((sol = popen(nfi,"w"))==NULL) {
				fprintf(stderr,"Failed to open compressed solar file. Abort.\n");
				exit(1);
			}
		}
		else {
			snprintf(nfi,256,"%s.sol",ifile);
			if ((sol = fopen(nfi,"w"))==NULL) {
				fprintf(stderr,"Failed to open scaler file. Abort.\n");
				exit(1);
			}
		}
	}

	if (iscl) {
		if (izip) {
			snprintf(nfi,256,"bzip2 -9z > %s.scl.bz2",ifile);
			if ((scl = popen(nfi,"w"))==NULL) {
				fprintf(stderr,"Failed to open compressed scaler file. Abort.\n");
				exit(1);
			}
		}
		else {
			snprintf(nfi,256,"%s.scl",ifile);
			if ((scl = fopen(nfi,"w"))==NULL) {
				fprintf(stderr,"Failed to open scaler file. Abort.\n");
				exit(1);
			}
		}
	}

	if (ical) {
		cal << "# # # p 1 cal " << PROJECT << " " << VERSION << endl;
		cal << "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)" << endl;
		cal << "# # This is a file containing the charge and peak calibration histograms" << endl;
		cal << "# # Format is ch1 ch2 ch3 pk1 pk2 pk3" << endl;
		if (itrg)
			cal << "# # An offline trigger of " << trg_level[0] << " " << trg_level[1] << " " << trg_level[2] << " ADC above baseline has been used for each channel respectively." << endl;
	}

	if (itim) {
		tim << "# # # p 1 tim " << PROJECT << " " << VERSION << endl;
		tim << "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)" << endl;
		tim << "# # This is a file containing the time difference histogram" << endl;
		tim << "# # Format is #time_difference(ns) #count for each channel" << endl;
		if (tim_map)
			tim << "# # Pulses were discarded if (a/p < " << tim_map << ")"<< endl;
		if (itrg)
			tim << "# # An offline trigger of " << trg_level[0] << " " << trg_level[1] << " " << trg_level[2] << " ADC above baseline has been used for each channel respectively." << endl;
	}

	if (iraw) {
		raw << "# # # p 1 raw " << PROJECT << " " << VERSION << endl;
		raw << "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)" << endl;
		raw << "# # This is a RAW file containing the first 10 seconds of data" << endl;
	}

	if (isol) {
		fprintf(sol, "# # # p 1 sol %s %s\n", PROJECT, VERSION);
		fprintf(sol, "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)\n");
		fprintf(sol, "# # This is a Solar data file.\n");
		fprintf(sol, "# # These are one minute charge and peak histograms, with monitoring information\n");
		fprintf(sol, "# # Format is # q/p second frequency temperature pressure\n");
		fprintf(sol, "# # (q for charge and p for peak)\n");
		fprintf(sol, "# # followed by 0/1 0/1/2 second frequency temperature pressure and 1024 or 4096 values\n");
		fprintf(sol, "# # where 0/1 stands for charge (0) or peak (1) and 0/1/2 is the channel\n");
		if (itrg)
			fprintf(sol, "# # An offline trigger of %d %d %d ADC above baseline has been used for each channel respectively.\n", trg_level[0], trg_level[1], trg_level[2]);
	}

	if (iall) {
		fprintf(all, "# # # p 1 all %s %s\n", PROJECT, VERSION);
		fprintf(all, "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)\n");
		fprintf(all, "# # This is a file containing all processed data\n");
		fprintf(all, "# # Format is # second frequency temperature pressure\n");
		fprintf(all, "# #   time_to_prev_pulse counts_to_prev_pulse channels_triggered_mask ch_ch1 pk_ch1 ch_ch2 pk_ch2 ch_ch3 pk_ch3 (channel <i> is printed only if it triggered)\n");
		fprintf(all, "# # note: time_to_prev_pulse is in clock cycle, and reset to 0 every second\n");
		if (itrg)
			fprintf(all, "# # An offline trigger of %d %d %d ADC above baseline has been used for each channel respectively.\n", trg_level[0], trg_level[1], trg_level[2]);
	}

	if (imon) {
		mon << "# # # p 1 mon " << PROJECT << " " << VERSION << endl;
		mon << "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)" << endl;
		mon << "# # This is a monitoring file." << endl;
		mon << "# # Format is second frequency temperature pressure" << endl;
	}

	if (iscl) {
		fprintf(scl, "# # # p 1 scl %s %s\n", PROJECT, VERSION);
		fprintf(scl, "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)\n");
		fprintf(scl, "# # This is the old-lago-like scaler file.\n");
		fprintf(scl, "# # Format is:\n");
		fprintf(scl, "# # # s second frequency temperature pressure Total_Rate Rate_per_channel:_(%d)_columns\n",CHANNELS);
		fprintf(scl, "# # followed by %d lines (%.1e s) containing %d counting levels for each channel\n", SCL_BINS, SCL_TIME, SCL_LEVELS);
		fprintf(scl, "# # These are the thresholds used:\n");
		for (int i = 0; i < CHANNELS; i++) {
			fprintf(scl, "# # Channel %d : ", i+1);
			for (int j = 0; j < SCL_LEVELS; j++)
				fprintf(scl, "l%d = %d ", j+1, scl_level[i][j]);
			fprintf(scl,"\n");
		}
		fprintf(scl,"# # Scalers thresholds are ");
		if (isclg)
			fprintf(scl, "considered as absolute levels.\n");
		else
			fprintf(scl, "compared with the baseline level for each channel (%d adc)\n", BASELINE);
		if (itrg)
			fprintf(scl, "# # An offline trigger of %d %d %d ADC above baseline has been used for each channel respectively.\n", trg_level[0], trg_level[1], trg_level[2]);
	}
	if (irte) {
		fprintf(rte, "# # # p 1 rte %s %s\n", PROJECT, VERSION);
		fprintf(rte, "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)\n");
		fprintf(rte, "# # This is the rate (pulse per second) file.\n");
		fprintf(rte, "# # Format is:\n");
		fprintf(rte, "# # second temperature pressure Total_Rate Rate_per_channel:_(%d)_columns\n",CHANNELS);
	}
	if (iflx) {
		fprintf(flx, "# # # p 1 flx %s %s\n", PROJECT, VERSION);
		fprintf(flx, "# # L1 level file (processed raw data, use at your own risk or contact lago@lagoproject.org)\n");
		fprintf(flx, "# # This is the flux file.\n");
		fprintf(flx, "# # Format is:\n");
		fprintf(flx, "# # second_at_half_interval avg_temp avg_press avg_rate avg_rate_per_channel sigma_temp sigma_press sigma_rate sigma_rate_per_channel\n");
		fprintf(flx, "# # Average interval used: %d seconds\n", flx_default);
	}

	/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
	//
	// File reading and processing
	//
	cerr << "Reading file" << endl;
	while(NbPulses!=-1) {
		NbPulses=Input.ReadOneSecond(&Data,Pulse,MAXPULSEPERSEC);
		if (NbPulses>0) TreatSecond(&Data,Pulse,NbPulses);
	}


	// Filling calibration histograms
	for (int j=0; j<4096; j++) {
		for (int i=0; i<CHANNELS; i++)  {
			cal << Charge[i][j] << " ";
		}
		if (j<1024) for (int i=0; i<CHANNELS; i++)
				cal << Peak[i][j] << " ";
		cal << endl;
	}

	//
	// Channel validation code
	//
	if (ivalid) {
		printf("Validation of channel %d:\n",ivalid);
		// validity checks...
		ivalid=ivalid-1; // 0 to 2
		// baseline
		double b=0,b2=0,n=0;
		for (int j=0; j<1024; j++) {
			b+=Base[ivalid][j]*1.*j;
			b2+=Base[ivalid][j]*1.*j*j;
			n+=Base[ivalid][j];
		}
		if (n<1000) {
			printf("@ Problem: not enough events on this channel (%d)\n",int(n));
		}
		else {
			//printf("%lf %lf %lf\n",b,b2,n);
			float m=b*1./n;
			float v=sqrt(b2*1./n-m*m);
			int bb=0;
			for (int j=0; j<1024; j++)
				if (j<m-5*v || j>m+5*v) bb+=Base[ivalid][j];
			printf("  Baseline: %lf +- %lf, %lf%% at more than 5 sigmas\n",m,v,bb*100./n);
			if (m-v>BASELINE || m+v<BASELINE) printf("@ Problem: Baseline is not within 1 sigma of %d\n",BASELINE);
			if (v>2) printf("@ Problem: Baseline fluctuation is high, more than 2 ADC\n");
			// peak histogram
			int BitHist[10][10];
			for (int i=0; i<10; i++)
				for (int j=0; j<10; j++) BitHist[i][j]=0;
			int tv=0;
			for (int j=BASELINE; j<1024; j++) {
				tv+=Peak[ivalid][j-BASELINE];
				for (int i=0; i<10; i++)
					for (int k=0; k<10; k++)
						if (int(pow(2,i))==(j&(int(pow(2,i)))))
							if (int(pow(2,k))==(j&(int(pow(2,k)))))
								BitHist[i][k]+=Peak[ivalid][j-BASELINE];
			}
			for (int i=0; i<10; i++)
				for (int j=i; j<10; j++)
					if (BitHist[i][j]==0) printf("@ Problem: bit combination %d %d never happenning\n",i,j);
			//for (int j=0; j<1024; j++)
			//printf("%d %d %d\n",j,Peak[ivalid][j],Base[ivalid][j]);
		}
	}
	//
	// Time difference vector
	//
	if (itim) {
		for (int i=0; i<MAXTIMEINVECTOR; i++) {
			tim << i * 25 << " ";
			for (int j=0; j<CHANNELS; j++)
				tim << Time[j][i] << " ";
			tim << endl;
		}
	}
	//
	// Closing files
	//
	if (ical)
		cal.close();
	if (itim)
		tim.close();
	if (iall)
		pclose(all);
	if (iraw)
		raw.close();
	if (imon)
		mon.close();
	if (irte)
		fclose(rte);
	if (iflx)
		fclose(flx);
	if (izip) {
		if (isol)
			pclose(sol);
		if (iscl)
			pclose(scl);
	}
	else {
		if (isol)
			fclose(sol);
		if (iscl)
			fclose(scl);
	}
}