From d538d049654b1a23ed24f2ae0a59ba575a14b8fd Mon Sep 17 00:00:00 2001 From: Bea Cobo Date: Wed, 10 Mar 2021 15:46:12 +0100 Subject: [PATCH] Merged: Weird oscillations warning + Different preBuffers in the library + Adaptation to XIFUSIM081 (EXTEND and PH_ID columns) --- libsixt/advdet.c | 1643 +++++++++++++ libsixt/advdet.h | 671 ++++++ libsixt/integraSIRENA.cpp | 784 ++++-- libsixt/integraSIRENA.h | 47 +- libsixt/scheduler.cpp | 23 +- libsixt/tasksSIRENA.cpp | 2129 +++++++++++------ libsixt/tasksSIRENA.h | 8 +- libsixt/teseventlist.c | 827 +++++++ libsixt/teseventlist.h | 185 ++ libsixt/tesrecord.c | 202 ++ libsixt/tesrecord.h | 124 + libsixt/testriggerfile.c | 607 +++++ libsixt/testriggerfile.h | 103 + libsixt/versionSIRENA.h | 4 +- tools/tesreconstruction/tesreconstruction.c | 263 +- tools/tesreconstruction/tesreconstruction.par | 3 +- 16 files changed, 6514 insertions(+), 1109 deletions(-) create mode 100644 libsixt/advdet.c create mode 100644 libsixt/advdet.h create mode 100644 libsixt/teseventlist.c create mode 100644 libsixt/teseventlist.h create mode 100644 libsixt/tesrecord.c create mode 100644 libsixt/tesrecord.h create mode 100644 libsixt/testriggerfile.c create mode 100644 libsixt/testriggerfile.h diff --git a/libsixt/advdet.c b/libsixt/advdet.c new file mode 100644 index 0000000..6fd72b8 --- /dev/null +++ b/libsixt/advdet.c @@ -0,0 +1,1643 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2014-2016 Thorsten Brand, Thomas Dauser, Philippe Peille, FAU + Copyright 2015-2019 Remeis-Sternwarte, Friedrich-Alexander-Universitaet + Erlangen-Nuernberg +*/ + +#include "advdet.h" + +/** Data structure given to the XML handler to transfer data. */ +struct XMLParseData { + AdvDet* det; + int status; +}; + +//////////////////////////////////////////////////////////////////// +// Static function declarations. +//////////////////////////////////////////////////////////////////// + +/** Handler for the start of an XML element. */ +static void AdvDetXMLElementStart(void* parsedata, + const char* el, + const char** attr); +/** Handler for the end of an XML element. */ +static void AdvDetXMLElementEnd(void* parsedata, const char* el); + +//////////////////////////////////////////////////////////////////// +// Program Code +//////////////////////////////////////////////////////////////////// + +TESNoiseProperties* newTESNoise(int* const status){ + + // Allocate memory + TESNoiseProperties* noise=(TESNoiseProperties*)malloc(sizeof(TESNoiseProperties)); + if(NULL==noise){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TESNoiseProperties failed"); + return(noise); + } + + // Initialize values and pointers + noise->WhiteRMS=0.; + noise->H0=1.; + noise->Nz=0; + noise->Np=0; + noise->Zeros=NULL; + noise->Poles=NULL; + noise->OoFRMS=0.; + noise->OoFKnee=0.; + + return(noise); +} + +void destroyTESNoiseProperties(TESNoiseProperties* noise){ + if (NULL!=noise){ + if(noise->Zeros!=NULL){ + free(noise->Zeros); + } + if(noise->Poles!=NULL){ + free(noise->Poles); + } + noise->WhiteRMS=0.; + noise->H0=1.; + noise->Nz=0; + noise->Np=0; + noise->OoFRMS=0.; + noise->OoFKnee=0.; + } + free(noise); + noise=NULL; +} + +AdvPix* newAdvPix(int* const status){ + // Allocate memory + AdvPix* pix=(AdvPix*)malloc(sizeof(AdvPix)); + if(pix==NULL){ + *status=EXIT_FAILURE; + SIXT_ERROR("Unable to allocate memory for detector pixel"); + return(pix); + } + // Initialize values and pointers + pix->sx=0.; + pix->sy=0.; + pix->width=0.; + pix->height=0.; + pix->pindex=0; + //pix->version=NULL; + pix->profVersionID=0; + pix->ADCOffset=0; + pix->calfactor=0.; + pix->TESNoise=NULL; + pix->ngrades=0; + pix->grades=NULL; + pix->global_grading=0; + pix->arffile=NULL; + pix->arf=NULL; + pix->freq=0.; + pix->resfreq=0.; + pix->channel=NULL; + pix->electrical_cross_talk=NULL; + pix->thermal_cross_talk=NULL; + //pix->intermodulation_cross_talk=NULL; + pix->prop_cross_talk=NULL; + pix->der_cross_talk=NULL; + pix->tes_type=NULL; + pix->tes=NULL; + pix->row=0; + + return(pix); +} + +AdvRecons* newAdvRecons(int* const status){ //SIRENA + // Allocate memory + AdvRecons* recons=(AdvRecons*)malloc(sizeof(AdvRecons)); + if(recons==NULL){ + *status=EXIT_FAILURE; + SIXT_ERROR("Unable to allocate memory for reconstruction info"); + return(recons); + } + // Initialize values and pointers + recons->ngrades=0; + recons->grades=NULL; + + return(recons); +} + + +void freeAdvPix(AdvPix* pix){ + if(NULL!=pix){ + int g=pix->ngrades; + destroyTESNoiseProperties(pix->TESNoise); + freeGrading(pix); + freeMatrixCrossTalk(pix->thermal_cross_talk); + freeMatrixEnerdepCrossTalk(pix->electrical_cross_talk, g); + freeMatrixPropCrossTalk(pix->prop_cross_talk); + freeMatrixDerCrossTalk(pix->der_cross_talk); + } +} + +void freeAdvRecons(AdvRecons* recons){ //SIRENA + if(NULL!=recons){ + //int g=recons->ngrades; + freeGradingRecons(recons); + } +} + +void freeGrading(AdvPix* pix){ + for (int i=0;ingrades;i++){ + free(pix->grades[i].rmffile); + } + free(pix->grades); + pix->ngrades=0; + pix->grades=NULL; + pix->global_grading=0; +} + +void freeGradingRecons(AdvRecons* recons){ //SIRENA + free(recons->grades); + recons->ngrades=0; + recons->grades=NULL; +} + +/** Free the FDM System Structure */ +void freeFDMSystem(FDMSystem* fdmsys){ + int ii; + free(fdmsys->omega_array); + free(fdmsys->res_omega_array); + free(fdmsys->X_L); + free(fdmsys->capFac); + for (ii=0; iinum_pixels; ii++){ + free(fdmsys->Z_array[ii]); + } + free(fdmsys->Z_array); + free(fdmsys); +} + +void freeReadoutChannels(ReadoutChannels* rc){ + if ( rc != NULL ){ + // Free the FDM systems + for (int ii=0; iinum_channels; ii++){ + if (rc->channels[ii].fdmsys != NULL){ + freeFDMSystem(rc->channels[ii].fdmsys); + } + if (rc->channels[ii].pixels!=NULL){ + //Only release first pointer, the rest was released via destroyAdvDet (<-- Dangerous game here! Edoardo's comment) + free(rc->channels[ii].pixels); + } + } + free(rc->channels); + free(rc->df_information_band); + } + free(rc); +} + +void freeImodTab(ImodTab* tab, int gr){ + if (tab != NULL){ + for(int g=0; gchannel_file){ + free(det->channel_file); + det->channel_file=NULL; + } + if (NULL!=det->channel_resfreq_file){ + free(det->channel_resfreq_file); + det->channel_resfreq_file=NULL; + } + + freeReadoutChannels(det->readout_channels); + //Freeing tables for every grade + if(gr!=0){ + int len=det->xt_num_thermal; + + //Freeing electrical cross-talk + free(det->crosstalk_elec_timedep_file); + det->crosstalk_elec_timedep_file=NULL; + free(det->crosstalk_elec_file); + det->crosstalk_elec_file=NULL; + + freeElecTab(det->crosstalk_elec,gr); + det->crosstalk_elec=NULL; + freeCrosstalkTimedep(det->crosstalk_elec_timedep,gr); + free(det->crosstalk_elec_timedep); + det->crosstalk_elec_timedep=NULL; + + // Freeing intermodulation cross-talk + free(det->crosstalk_intermod_file); + det->crosstalk_intermod_file=NULL; + + freeImodTab(det->crosstalk_imod_table,gr); + det->crosstalk_imod_table=NULL; + + //Freeing thermal cross-talk + if(det->crosstalk_ther_timedep!=NULL){ + for(int i=0; icrosstalk_ther_timedep[i],gr); + free(det->crosstalk_ther_timedep[i]); + det->crosstalk_ther_timedep[i]=NULL; + free(det->crosstalk_thermal_timedep_file[i]); + det->crosstalk_thermal_timedep_file[i]=NULL; + } + free(det->crosstalk_thermal_timedep_file); + det->crosstalk_thermal_timedep_file=NULL; + free(det->crosstalk_ther_timedep); + det->crosstalk_ther_timedep=NULL; + } + free(det->xt_dist_thermal); + det->xt_dist_thermal=NULL; + free(det->xt_weight_thermal); + det->xt_weight_thermal=NULL; + + //Freeing Proportional Cross-talk + freeTDMTab(det->crosstalk_TDM_prop, gr); + det->crosstalk_TDM_prop=NULL; + + //Freeing Derivative Cross-talk + freeTDMTab(det->crosstalk_TDM_der, gr); + det->crosstalk_TDM_der=NULL; + } +} + +AdvDet* newAdvDet(int* const status){ + + // Allocate memory. + AdvDet* det=(AdvDet*)malloc(sizeof(AdvDet)); + if (NULL==det) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for AdvDet failed"); + return(det); + } + + // Initialize all pointers with NULL. + det->pix=NULL; + det->recons=NULL; //SIRENA + det->filename=NULL; + det->filepath=NULL; + det->sx=0.; + det->sy=0.; + det->npix=0; + det->nrecons=0; //SIRENA + det->cpix=0; + det->SampleFreq=-1.0; + det->tesnoisefilter=0; + det->inpixel=0; + det->oof_activated=0; + det->rmf_library=NULL; + det->arf_library=NULL; + det->tdm=0; + det->max_rows=0; + + det->xt_dist_thermal=NULL; + det->xt_weight_thermal=NULL; + det->xt_num_thermal=0; + + det->channel_file=NULL; + det->readout_channels=NULL; + det->channel_resfreq_file=NULL; + + det->crosstalk_intermod_file=NULL; + det->crosstalk_imod_table=NULL; + + det->crosstalk_thermal_timedep_file=NULL; + det->crosstalk_ther_timedep=NULL; + + det->crosstalk_elec_file=NULL; + det->crosstalk_elec_timedep_file=NULL; + det->crosstalk_elec_timedep=NULL; + det->crosstalk_elec=NULL; + det->scaling=1; + + det->TDM_prop_file=NULL; + det->crosstalk_TDM_prop=NULL; + det->prop_TDM_scaling_1=1; + det->prop_TDM_scaling_2=1; + + det->TDM_der_file=NULL; + det->crosstalk_TDM_der=NULL; + det->der_TDM_scaling=1; + + det->threshold_event_lo_keV=0.; + det->crosstalk_id=0; + + det->tes_type_file=NULL; + det->L_Common=0.; + det->C_Common=-1.; // default -1 means no common capacitance + + return(det); +} + +void destroyAdvDet(AdvDet **det){ + + if(NULL!=(*det)){ + int gr=0; + if(NULL!=(*det)->pix){ + gr =(*det)->pix[0].ngrades; + for(int i=0;i<(*det)->npix;i++){ + freeAdvPix(&(*det)->pix[i]); + } + free((*det)->pix); + } + //int grRecons=0; + if(NULL!=(*det)->recons){ //SIRENA + //grRecons =(*det)->recons[0].ngrades; + for(int i=0;i<(*det)->nrecons;i++){ + freeAdvRecons(&(*det)->recons[i]); + } + free((*det)->recons); + } + if(NULL!=(*det)->filename){ + free((*det)->filename); + } + if(NULL!=(*det)->filepath){ + free((*det)->filepath); + } + if(NULL!=(*det)->tes_type_file){ + free((*det)->tes_type_file); + } + freeRMFLibrary((*det)->rmf_library); + freeARFLibrary((*det)->arf_library); + + freeCrosstalk(*(det), gr); + free(*(det)); + } +} + +int CheckAdvPixImpact(AdvPix pix, Impact *imp){ + + // Calculate impact coordinates in respect to the + // pixel coordinate system + double u, v; + + u = imp->position.x - pix.sx; + v = imp->position.y - pix.sy; + + // Calculate half width and height of the rectangular pixel + double deltu, deltv; + deltu=pix.width/2.; + deltv=pix.height/2.; + + // Check if the impact lies in the rectangular pixel. + // Return 1 if yes, 0 if not. + if((u >= -deltu) && (u <= deltu) && (v >= -deltv) && (v <= deltv)){ + return 1; + }else{ + return 0; + } +} + +void CalcAdvPixImpact(AdvPix pix, Impact *imp, PixImpact *piximp){ + + // Calculate impact coordinates in respect to the + // pixel coordinate system + double u, v; + + u = imp->position.x - pix.sx; + v = imp->position.y - pix.sy; + + // Fill piximp fields + piximp->time = imp->time; + piximp->energy = imp->energy; + piximp->ph_id = imp->ph_id; + piximp->src_id = imp->src_id; + piximp->detposition.x = imp->position.x; + piximp->detposition.y = imp->position.y; + piximp->pixposition.x = u; + piximp->pixposition.y = v; +} + +int AdvImpactList(AdvDet *det, Impact *imp, PixImpact **piximp){ + + // Duplicate the impact but transform the coordinates into + // the detector coordinate system + Impact detimp; + + detimp.time = imp->time; + detimp.energy = imp->energy; + detimp.ph_id = imp->ph_id; + detimp.src_id = imp->src_id; + detimp.position.x = imp->position.x - det->sx; + detimp.position.y = imp->position.y - det->sy; + + int nimpacts=0; + + // loop over all pixels and check for hit + int ii; + + for(ii=0; iinpix; ii++){ + if(CheckAdvPixImpact(det->pix[ii], &detimp)!=0){ + nimpacts++; + *piximp=realloc(*piximp, nimpacts*sizeof(**piximp)); + (*piximp)[nimpacts-1].pixID=(long)ii; + CalcAdvPixImpact(det->pix[ii], &detimp, &((*piximp)[nimpacts-1])); + } + } + return nimpacts; +} + + +void parseAdvDetXML(AdvDet* const det, + const char* const filename, + int* const status){ + + headas_chat(5, "read advanced detector setup from XML file '%s' ...\n", filename); + + // Read the XML data from the file. + // Open the specified file. + printf("Read file %s\n", filename); + FILE* xmlfile=fopen(filename, "r"); + if (NULL==xmlfile) { + *status=EXIT_FAILURE; + char msg[MAXMSG]; + sprintf(msg, "failed opening XML " + "file '%s' for read access", filename); + SIXT_ERROR(msg); + return; + } + + // The data is read from the XML file and stored in xmlbuffer + // without any modifications. + struct XMLBuffer* xmlbuffer=newXMLBuffer(status); + CHECK_STATUS_VOID(*status); + + // Input buffer with an additional byte at the end for the + // termination of the string. + const int buffer_size=256; + char buffer[buffer_size+1]; + // Number of chars in buffer. + int len; + + // Read all data from the file. + do { + // Get a piece of input into the buffer. + len=fread(buffer, 1, buffer_size, xmlfile); + buffer[len]='\0'; // Terminate the string. + addString2XMLBuffer(xmlbuffer, buffer, status); + CHECK_STATUS_VOID(*status); + } while (!feof(xmlfile)); + + // Close the file handler to the XML file. + fclose(xmlfile); + + // Before expanding loops in the XML file, add the included code to it. + expandIncludesXML(xmlbuffer, filename, status); + CHECK_STATUS_VOID(*status); + + // Before actually parsing the XML code, expand the loops and + // arithmetic operations in the XML description. + // The expansion algorithm repeatetly scans the XML code and + // searches for loop tags. It replaces the loop tags by repeating + // the contained XML code. + expandXML(xmlbuffer, status); + CHECK_STATUS_VOID(*status); + + // Expand the eventual hexagonloop structure + expandHexagon(xmlbuffer,status); + CHECK_STATUS_VOID(*status); + + // Parse XML code in the xmlbuffer using the expat library. + // Get an XML_Parser object. + XML_Parser parser=XML_ParserCreate(NULL); + if (NULL==parser) { + *status=EXIT_FAILURE; + SIXT_ERROR("could not allocate memory for XML parser"); + return; + } + + // Set data that is passed to the handler functions. + struct XMLParseData xmlparsedata={ + .det =det, + .status=EXIT_SUCCESS + }; + XML_SetUserData(parser, &xmlparsedata); + + // Set the handler functions. + XML_SetElementHandler(parser, AdvDetXMLElementStart, AdvDetXMLElementEnd); + + // Parse all the data in the string buffer. + const int done=1; + if (!XML_Parse(parser, xmlbuffer->text, strlen(xmlbuffer->text), done)) { + // Parse error. + *status=EXIT_FAILURE; + char msg[MAXMSG]; + sprintf(msg, "failed parsing XML file '%s':\n%s\n", + filename, XML_ErrorString(XML_GetErrorCode(parser))); + printf("%s", xmlbuffer->text); + SIXT_ERROR(msg); + return; + } + + // Check that the correct number of pixels was found + if ((det->nrecons == 0) && (det->cpix!=det->npix)){ // SIRENA + //if(det->cpix!=det->npix){ + *status = EXIT_FAILURE; + SIXT_ERROR("Number of pixels given at pixdetector level does not match the number of pixel subelements"); + det->npix=det->cpix; + } + + // Check for errors. + if (EXIT_SUCCESS!=xmlparsedata.status) { + *status=xmlparsedata.status; + } + + // Release memory. + XML_ParserFree(parser); + + // Remove the XML string buffer. + freeXMLBuffer(&xmlbuffer); +} + +static void AdvDetXMLElementStart(void* parsedata, + const char* el, + const char** attr) +{ + struct XMLParseData* xmlparsedata=(struct XMLParseData*)parsedata; + + // Check if an error has occurred previously. + CHECK_STATUS_VOID(xmlparsedata->status); + + // Convert the element to an upper case string. + char Uelement[MAXMSG]; + strcpy(Uelement, el); + strtoupper(Uelement); + + // Check for advanced detector definition. + if (!strcmp(Uelement, "PIXDETECTOR")) { + // Determine npix + char npix[MAXMSG]; + char readout[MAXMSG]; + getXMLAttributeString(attr, "NPIX", npix); + + xmlparsedata->det->npix=atoi(npix); + if(xmlparsedata->det->npix<1){ + SIXT_ERROR("Number of pixels in advanced detector description less than 1."); + return; + } + xmlparsedata->det->pix=(AdvPix*)malloc(xmlparsedata->det->npix*sizeof(AdvPix)); + if(xmlparsedata->det->pix==NULL){ + SIXT_ERROR("Unable to allocate memory for advanced detector pixel array."); + return; + } + + xmlparsedata->det->sx=getXMLAttributeDouble(attr, "XOFF"); + xmlparsedata->det->sy=getXMLAttributeDouble(attr, "YOFF"); + getXMLAttributeString(attr, "READOUT", readout); + + if (!strcmp(readout,"fdm") || !strcmp(readout,"")){ + xmlparsedata->det->tdm=0; + printf("Readout type is FDM\n"); + } else if (!strcmp(readout,"tdm")){ + xmlparsedata->det->tdm=1; + printf("Readout type is TDM\n"); + } else { + SIXT_ERROR("Readout type is not understood"); + return; + } + + + for (int ii=0;iidet->npix;ii++){ + xmlparsedata->det->pix[ii].TESNoise=NULL; + xmlparsedata->det->pix[ii].grades=NULL; + xmlparsedata->det->pix[ii].ngrades=0; + xmlparsedata->det->pix[ii].global_grading=0; + xmlparsedata->det->pix[ii].channel=NULL; + xmlparsedata->det->pix[ii].thermal_cross_talk=NULL; + xmlparsedata->det->pix[ii].electrical_cross_talk=NULL; + xmlparsedata->det->pix[ii].prop_cross_talk=NULL; + xmlparsedata->det->pix[ii].der_cross_talk=NULL; + } + } else if (!strcmp(Uelement, "RECONSTRUCTION")) { //SIRENA + xmlparsedata->det->nrecons = 1; + xmlparsedata->det->recons=(AdvRecons*)malloc(xmlparsedata->det->nrecons*sizeof(AdvRecons)); + + for (int ii=0;iidet->nrecons;ii++){ + xmlparsedata->det->recons[ii].grades=NULL; + xmlparsedata->det->recons[ii].ngrades=0; + } + } else if (!strcmp(Uelement, "PIXEL")) { + //if ((xmlparsedata->det->cpix) >= (xmlparsedata->det->npix)) { + if ((xmlparsedata->det->cpix) > (xmlparsedata->det->npix)) { //SIRENA + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Number of pixels given at pixdetector level lower than the number of pixel subelements"); + return; + } + xmlparsedata->det->inpixel=1; + } else if (!strcmp(Uelement, "SHAPE")){ + double posx, posy; + posx=getXMLAttributeDouble(attr, "POSX"); + posy=getXMLAttributeDouble(attr, "POSY"); + if (xmlparsedata->det->inpixel){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].sx=posx*getXMLAttributeDouble(attr, "DELX"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].sy=posy*getXMLAttributeDouble(attr, "DELY"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].width=getXMLAttributeDouble(attr, "WIDTH"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].height=getXMLAttributeDouble(attr, "HEIGHT"); + } else { + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("XML syntax error: shape used outside of pixel"); + return; + } + } else if (!strcmp(Uelement,"PIXTES")) { + if (xmlparsedata->det->inpixel){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].tes_type=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->pix[xmlparsedata->det->cpix].tes_type); + getXMLAttributeString(attr, "TYPE", xmlparsedata->det->pix[xmlparsedata->det->cpix].tes_type); + if (strlen(xmlparsedata->det->pix[xmlparsedata->det->cpix].tes_type) == 0){ + free(xmlparsedata->det->pix[xmlparsedata->det->cpix].tes_type); + xmlparsedata->det->pix[xmlparsedata->det->cpix].tes_type=NULL; + } + } else { + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("XML syntax error: pixtes used outside of pixel"); + } + } else if (!strcmp(Uelement,"PULSESHAPE")){ + if (xmlparsedata->det->inpixel){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].calfactor=getXMLAttributeDouble(attr, "CALFACTOR"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].ADCOffset=getXMLAttributeInt(attr, "ADCOFFSET"); + getXMLAttributeString(attr, "TESPROFVER", xmlparsedata->det->pix[xmlparsedata->det->cpix].version); + xmlparsedata->det->pix[xmlparsedata->det->cpix].profVersionID=-1; + } else { + for (int i=0;idet->npix;i++){ + xmlparsedata->det->pix[i].calfactor=getXMLAttributeDouble(attr, "CALFACTOR"); + xmlparsedata->det->pix[i].ADCOffset=getXMLAttributeInt(attr, "ADCOFFSET"); + getXMLAttributeString(attr, "TESPROFVER", xmlparsedata->det->pix[i].version); + xmlparsedata->det->pix[i].profVersionID=-1; + } + } + } else if (!strcmp(Uelement, "TESWHITENOISE")) { + if (xmlparsedata->det->inpixel){ + if(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise==NULL){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise=newTESNoise(&(xmlparsedata->status)); + CHECK_STATUS_VOID(xmlparsedata->status); + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->WhiteRMS=getXMLAttributeDouble(attr, "RMS"); + } else { + for (int i=0;idet->npix;i++){ + if(xmlparsedata->det->pix[i].TESNoise==NULL){ + xmlparsedata->det->pix[i].TESNoise=newTESNoise(&(xmlparsedata->status)); + CHECK_STATUS_VOID(xmlparsedata->status); + } + xmlparsedata->det->pix[i].TESNoise->WhiteRMS=getXMLAttributeDouble(attr, "RMS"); + } + } + } else if (!strcmp(Uelement, "TESOOFNOISE")) { + if (xmlparsedata->det->inpixel){ + if(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise==NULL){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise=newTESNoise(&(xmlparsedata->status)); + CHECK_STATUS_VOID(xmlparsedata->status); + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->OoFRMS=getXMLAttributeDouble(attr, "RMS"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->OoFKnee=getXMLAttributeDouble(attr, "FKNEE"); + if (!xmlparsedata->det->oof_activated){ + xmlparsedata->det->oof_activated=1; + } + } else { + for (int i=0;idet->npix;i++){ + if(xmlparsedata->det->pix[i].TESNoise==NULL){ + xmlparsedata->det->pix[i].TESNoise=newTESNoise(&(xmlparsedata->status)); + CHECK_STATUS_VOID(xmlparsedata->status); + } + xmlparsedata->det->pix[i].TESNoise->OoFRMS=getXMLAttributeDouble(attr, "RMS"); + xmlparsedata->det->pix[i].TESNoise->OoFKnee=getXMLAttributeDouble(attr, "FKNEE"); + } + xmlparsedata->det->oof_activated=1; + } + } else if (!strcmp(Uelement, "TESNOISEFILTER")) { + if (xmlparsedata->det->inpixel){ + if(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise==NULL){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise=newTESNoise(&(xmlparsedata->status)); + CHECK_STATUS_VOID(xmlparsedata->status); + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->H0=getXMLAttributeDouble(attr, "NORM"); + xmlparsedata->det->tesnoisefilter=1; + } else { + for (int i=0;idet->npix;i++){ + if(xmlparsedata->det->pix[i].TESNoise==NULL){ + xmlparsedata->det->pix[i].TESNoise=newTESNoise(&(xmlparsedata->status)); + CHECK_STATUS_VOID(xmlparsedata->status); + } + xmlparsedata->det->pix[i].TESNoise->H0=getXMLAttributeDouble(attr, "NORM"); + xmlparsedata->det->tesnoisefilter=1; + xmlparsedata->det->pix[i].TESNoise->Np=0; + xmlparsedata->det->pix[i].TESNoise->Nz=0; + } + } + } else if (!strcmp(Uelement, "NOISEPOLE")) { + if(xmlparsedata->det->tesnoisefilter==1){ + if(xmlparsedata->det->inpixel){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Np++; + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Poles=(double*)realloc(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Poles, + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Np*sizeof(double)); + if(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Poles==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of noise poles array failed."); + return; + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Poles[xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Np-1]=getXMLAttributeDouble(attr, "POLE"); + } else { + for (int i=0;idet->npix;i++){ + xmlparsedata->det->pix[i].TESNoise->Np++; + xmlparsedata->det->pix[i].TESNoise->Poles=(double*)realloc(xmlparsedata->det->pix[i].TESNoise->Poles, + xmlparsedata->det->pix[i].TESNoise->Np*sizeof(double)); + if(xmlparsedata->det->pix[i].TESNoise->Poles==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of noise poles array failed."); + return; + } + xmlparsedata->det->pix[i].TESNoise->Poles[xmlparsedata->det->pix[i].TESNoise->Np-1]=getXMLAttributeDouble(attr, "POLE"); + } + } + }else{ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("XML syntax error: noisepole used outside of tesnoisefilter."); + return; + } + } else if (!strcmp(Uelement, "NOISEZERO")) { + if(xmlparsedata->det->tesnoisefilter==1){ + if(xmlparsedata->det->inpixel){ + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Nz++; + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Zeros=(double*)realloc(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Zeros, + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Nz*sizeof(double)); + if(xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Zeros==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of noise zeros array failed."); + return; + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Zeros[xmlparsedata->det->pix[xmlparsedata->det->cpix].TESNoise->Nz-1]=getXMLAttributeDouble(attr, "ZERO"); + } else { + for (int i=0;idet->npix;i++){ + xmlparsedata->det->pix[i].TESNoise->Nz++; + xmlparsedata->det->pix[i].TESNoise->Zeros=(double*)realloc(xmlparsedata->det->pix[i].TESNoise->Zeros, + xmlparsedata->det->pix[i].TESNoise->Nz*sizeof(double)); + if(xmlparsedata->det->pix[i].TESNoise->Zeros==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of noise zeros array failed."); + return; + } + xmlparsedata->det->pix[i].TESNoise->Zeros[xmlparsedata->det->pix[i].TESNoise->Nz-1]=getXMLAttributeDouble(attr, "ZERO"); + } + } + }else{ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("XML syntax error: noisezero used outside of tesnoisefilter."); + return; + } + } else if (!strcmp(Uelement, "PIXARF")) { + if (xmlparsedata->det->inpixel){ + char arffile[MAXFILENAME]; + getXMLAttributeString(attr, "FILENAME", arffile); + xmlparsedata->det->pix[xmlparsedata->det->cpix].arffile=strndup(arffile,MAXFILENAME); + xmlparsedata->det->pix[xmlparsedata->det->cpix].arf=NULL; + } else { + for (int i=0;idet->npix;i++){ + char arffile[MAXFILENAME]; + getXMLAttributeString(attr, "FILENAME", arffile); + xmlparsedata->det->pix[i].arffile=strndup(arffile,MAXFILENAME); + xmlparsedata->det->pix[i].arf=NULL; + } + } + } else if (!strcmp(Uelement,"GRADING")){ + if (xmlparsedata->det->nrecons == 1) //SIRENA + { + if (xmlparsedata->det->inpixel){ + xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades=realloc(xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades, + (xmlparsedata->det->recons[xmlparsedata->det->nrecons].ngrades+1)*sizeof(*(xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades))); + if (xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of grading array failed."); + return; + } + xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades[xmlparsedata->det->recons[xmlparsedata->det->nrecons].ngrades].value=getXMLAttributeInt(attr, "NUM"); + xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades[xmlparsedata->det->recons[xmlparsedata->det->nrecons].ngrades].gradelim_pre=getXMLAttributeLong(attr, "PRE"); + xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades[xmlparsedata->det->recons[xmlparsedata->det->nrecons].ngrades].gradelim_post=getXMLAttributeLong(attr, "POST"); + xmlparsedata->det->recons[xmlparsedata->det->nrecons].grades[xmlparsedata->det->recons[xmlparsedata->det->nrecons].ngrades].grade_preBuffer=getXMLAttributeLong(attr, "PB"); + + xmlparsedata->det->recons[xmlparsedata->det->nrecons].ngrades++; + } else { + for (int i=0;idet->nrecons;i++){ + xmlparsedata->det->recons[i].grades=realloc(xmlparsedata->det->recons[i].grades, + (xmlparsedata->det->recons[i].ngrades+1)*sizeof(*(xmlparsedata->det->recons[i].grades))); + if (xmlparsedata->det->recons[i].grades==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of grading array failed."); + return; + } + xmlparsedata->det->recons[i].grades[xmlparsedata->det->recons[i].ngrades].value=getXMLAttributeInt(attr, "NUM"); + xmlparsedata->det->recons[i].grades[xmlparsedata->det->recons[i].ngrades].gradelim_pre=getXMLAttributeLong(attr, "PRE"); + xmlparsedata->det->recons[i].grades[xmlparsedata->det->recons[i].ngrades].gradelim_post=getXMLAttributeLong(attr, "POST"); + xmlparsedata->det->recons[i].grades[xmlparsedata->det->recons[i].ngrades].grade_preBuffer=getXMLAttributeLong(attr, "PB"); + xmlparsedata->det->recons[i].grades[xmlparsedata->det->recons[i].ngrades].rmf=NULL; + + xmlparsedata->det->recons[i].ngrades++; + } + } + } + else + { + if (xmlparsedata->det->inpixel){ + if (xmlparsedata->det->pix[xmlparsedata->det->cpix].global_grading) { + freeGrading(&(xmlparsedata->det->pix[xmlparsedata->det->cpix])); + xmlparsedata->det->pix[xmlparsedata->det->cpix].global_grading=0; + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades=realloc(xmlparsedata->det->pix[xmlparsedata->det->cpix].grades, + (xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades+1)*sizeof(*(xmlparsedata->det->pix[xmlparsedata->det->cpix].grades))); + if (xmlparsedata->det->pix[xmlparsedata->det->cpix].grades==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of grading array failed."); + return; + } + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades[xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades].value=getXMLAttributeInt(attr, "NUM"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades[xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades].gradelim_pre=getXMLAttributeLong(attr, "PRE"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades[xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades].gradelim_post=getXMLAttributeLong(attr, "POST"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades[xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades].grade_preBuffer=getXMLAttributeLong(attr, "PB"); + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades[xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades].rmf=NULL; + + char rmffile[MAXFILENAME]; + getXMLAttributeString(attr, "RMF", rmffile); + xmlparsedata->det->pix[xmlparsedata->det->cpix].grades[xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades].rmffile=strndup(rmffile,MAXFILENAME); + xmlparsedata->det->pix[xmlparsedata->det->cpix].ngrades++; + } else { + for (int i=0;idet->npix;i++){ + xmlparsedata->det->pix[i].grades=realloc(xmlparsedata->det->pix[i].grades, + (xmlparsedata->det->pix[i].ngrades+1)*sizeof(*(xmlparsedata->det->pix[i].grades))); + if (xmlparsedata->det->pix[i].grades==NULL){ + xmlparsedata->status=EXIT_FAILURE; + SIXT_ERROR("Realloc of grading array failed."); + return; + } + xmlparsedata->det->pix[i].grades[xmlparsedata->det->pix[i].ngrades].value=getXMLAttributeInt(attr, "NUM"); + xmlparsedata->det->pix[i].grades[xmlparsedata->det->pix[i].ngrades].gradelim_pre=getXMLAttributeLong(attr, "PRE"); + xmlparsedata->det->pix[i].grades[xmlparsedata->det->pix[i].ngrades].gradelim_post=getXMLAttributeLong(attr, "POST"); + xmlparsedata->det->pix[i].grades[xmlparsedata->det->pix[i].ngrades].grade_preBuffer=getXMLAttributeLong(attr, "PB"); + xmlparsedata->det->pix[i].grades[xmlparsedata->det->pix[i].ngrades].rmf=NULL; + + char rmffile[MAXFILENAME]; + getXMLAttributeString(attr, "RMF", rmffile); + xmlparsedata->det->pix[i].grades[xmlparsedata->det->pix[i].ngrades].rmffile=strndup(rmffile,MAXFILENAME); + xmlparsedata->det->pix[i].ngrades++; + xmlparsedata->det->pix[i].global_grading=1; + } + } + } + } else if(!strcmp(Uelement, "TESPROFILE")){ + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->tesproffilename); + double new_samplefreq=getXMLAttributeDouble(attr, "SAMPLEFREQ"); + if ((xmlparsedata->det->SampleFreq!=-1) && (xmlparsedata->det->SampleFreq!=new_samplefreq)){ + SIXT_ERROR("Incompatible sampling frequency values encountered."); + return; + } + xmlparsedata->det->SampleFreq=new_samplefreq; + } else if(!strcmp(Uelement, "SAMPLEFREQ")){ + double new_samplefreq=getXMLAttributeDouble(attr, "VALUE"); + if ((xmlparsedata->det->SampleFreq!=-1) && (xmlparsedata->det->SampleFreq!=new_samplefreq)){ + SIXT_ERROR("Incompatible sampling frequency values encountered."); + return; + } + xmlparsedata->det->SampleFreq=new_samplefreq; + } else if (!strcmp(Uelement,"TESFILE")) { + xmlparsedata->det->tes_type_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->tes_type_file); + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->tes_type_file); + if (strlen(xmlparsedata->det->tes_type_file) == 0){ + free(xmlparsedata->det->tes_type_file); + xmlparsedata->det->tes_type_file=NULL; + } + + } else if(!strcmp(Uelement, "CHANNEL_FREQ_LIST")) { + xmlparsedata->det->channel_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->channel_file); + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->channel_file); + + xmlparsedata->det->channel_resfreq_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->channel_resfreq_file); + getXMLAttributeString(attr, "RESFILENAME", xmlparsedata->det->channel_resfreq_file); + + } else if(!strcmp(Uelement, "FDM_PARAMETERS")) { + xmlparsedata->det->L_Common=getXMLAttributeDouble(attr, "LCOMMON"); + // retrieval of common capacitance + // do it via getXMLAttributeString. If it's an empty string, do nothing (default value is -1) + // if it's not an empty string, do atof, as is done in getXMLAttributeDouble + char Cbuffer[MAXMSG]; // string buffer + getXMLAttributeString(attr,"CCOMMON", Cbuffer); + // an empty string starts with the terminator; this is faster than strcmp + if (Cbuffer[0] != '\0'){ + xmlparsedata->det->C_Common = atof(Cbuffer); + } + + } else if(!strcmp(Uelement, "CROSSTALK")) { + // Need to check if we have channels defined + if (xmlparsedata->det->channel_file == NULL){ + SIXT_ERROR("Trying to implement crosstalk, but no file defining the channels specified in the XML"); + return; + } + } else if(!strcmp(Uelement, "THERMALCROSSTALK")) { + xmlparsedata->det->xt_dist_thermal = realloc(xmlparsedata->det->xt_dist_thermal, + (xmlparsedata->det->xt_num_thermal+1)*sizeof(double)); + CHECK_MALLOC_VOID(xmlparsedata->det->xt_dist_thermal); + xmlparsedata->det->xt_dist_thermal[xmlparsedata->det->xt_num_thermal] = + getXMLAttributeDouble(attr, "DISTANCE"); + + xmlparsedata->det->crosstalk_thermal_timedep_file=(char**)realloc(xmlparsedata->det->crosstalk_thermal_timedep_file, (xmlparsedata->det->xt_num_thermal+1)*sizeof(char*)); + char* tmp=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp); + char* tmp_path=(char*)malloc(2*MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp_path); + getXMLAttributeString(attr, "TIMEDEPFILE", tmp); + xmlparsedata->det->crosstalk_thermal_timedep_file[xmlparsedata->det->xt_num_thermal]=tmp; + tmp_path=strcpy(tmp_path, xmlparsedata->det->filepath); + tmp_path=strcat(tmp_path, tmp); + if (strlen(tmp) == 0 || access(tmp_path, F_OK)==-1){ + xmlparsedata->status=EXIT_FAILURE; + printf("Warning: Thermal crosstalk time dependence file %s for neighbor %i is not given or does not exist\n", tmp_path, xmlparsedata->det->xt_num_thermal+1); + free(xmlparsedata->det->crosstalk_thermal_timedep_file[xmlparsedata->det->xt_num_thermal]); + xmlparsedata->det->crosstalk_thermal_timedep_file[xmlparsedata->det->xt_num_thermal]=NULL; + SIXT_ERROR("Themal crosstalk time dependence file not found\n"); + } + free(tmp_path); + + // check that distances are in increasing order + if((xmlparsedata->det->xt_num_thermal>0) && + (xmlparsedata->det->xt_dist_thermal[xmlparsedata->det->xt_num_thermal]det->xt_dist_thermal[xmlparsedata->det->xt_num_thermal-1])){ + xmlparsedata->status=EXIT_FAILURE; + free(xmlparsedata->det->crosstalk_thermal_timedep_file); + SIXT_ERROR("Thermal crosstalk distances are supposed to be given in increasing order\n"); + return; + } + + xmlparsedata->det->xt_weight_thermal = realloc(xmlparsedata->det->xt_weight_thermal, + (xmlparsedata->det->xt_num_thermal+1)*sizeof(double) ); + CHECK_MALLOC_VOID(xmlparsedata->det->xt_weight_thermal); + xmlparsedata->det->xt_weight_thermal[xmlparsedata->det->xt_num_thermal] = + getXMLAttributeDouble(attr, "WEIGHT"); + + xmlparsedata->det->xt_num_thermal++; + + } else if(!strcmp(Uelement, "ELECTRICALCROSSTALK")){ + xmlparsedata->det->crosstalk_elec_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->crosstalk_elec_file); + char* tmp_path=(char*)malloc(2*MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp_path); + tmp_path=strcpy(tmp_path, xmlparsedata->det->filepath); + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->crosstalk_elec_file); + tmp_path=strcat(tmp_path, xmlparsedata->det->crosstalk_elec_file); + if (strlen(xmlparsedata->det->crosstalk_elec_file) == 0 || access(tmp_path, F_OK)==-1){ + xmlparsedata->status=EXIT_FAILURE; + printf("Warning: Electrical crosstalk file %s is not given or does not exist\n", tmp_path); + free(xmlparsedata->det->crosstalk_elec_file); + xmlparsedata->det->crosstalk_elec_file=NULL; + SIXT_ERROR("Electrical crosstalk file not found"); + } + free(tmp_path); + + xmlparsedata->det->crosstalk_elec_timedep_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->crosstalk_elec_timedep_file); + char* tmp_path_2=(char*)malloc(2*MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp_path_2); + tmp_path_2=strcpy(tmp_path_2, xmlparsedata->det->filepath); + getXMLAttributeString(attr, "TIMEDEPFILE", xmlparsedata->det->crosstalk_elec_timedep_file); + tmp_path_2=strcat(tmp_path_2, xmlparsedata->det->crosstalk_elec_timedep_file); + if (strlen(xmlparsedata->det->crosstalk_elec_timedep_file) == 0 || access(tmp_path_2, F_OK)==-1){ + xmlparsedata->status=EXIT_FAILURE; + printf("Warning: Electrical cross-talk time dependence file %s is not given or does not exist\n", tmp_path_2); + free(xmlparsedata->det->crosstalk_elec_timedep_file); + xmlparsedata->det->crosstalk_elec_timedep_file=NULL; + SIXT_ERROR("Electrical cross-talk time dependence file not found"); + } + free(tmp_path_2); + + } else if(!strcmp(Uelement, "INTERMODULATION")) { + xmlparsedata->det->crosstalk_intermod_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->crosstalk_intermod_file); + char* tmp_path=(char*)malloc(2*MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp_path); + tmp_path=strcpy(tmp_path, xmlparsedata->det->filepath); + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->crosstalk_intermod_file); + tmp_path=strcat(tmp_path,xmlparsedata->det->crosstalk_intermod_file); + if (strlen(xmlparsedata->det->crosstalk_intermod_file) == 0 || access(tmp_path, F_OK)==-1){ + xmlparsedata->status=EXIT_FAILURE; + printf("Warning: Intermodulation cross-talk file %s is not given or does not exist\n", tmp_path); + free(xmlparsedata->det->crosstalk_intermod_file); + xmlparsedata->det->crosstalk_intermod_file=NULL; + SIXT_ERROR("Intermodulation cross-talk file not found"); + } + free(tmp_path); + + } else if(!strcmp(Uelement, "PROPCROSSTALK")){ + xmlparsedata->det->TDM_prop_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->TDM_prop_file); + char* tmp_path=(char*)malloc(2*MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp_path); + tmp_path=strcpy(tmp_path, xmlparsedata->det->filepath); + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->TDM_prop_file); + tmp_path=strcat(tmp_path, xmlparsedata->det->TDM_prop_file); + if (strlen(xmlparsedata->det->TDM_prop_file) == 0 || access(tmp_path, F_OK)==-1){ + xmlparsedata->status=EXIT_FAILURE; + printf("Warning: Proportional cross-talk file %s is not given or does not exist\n", tmp_path); + free(xmlparsedata->det->TDM_prop_file); + xmlparsedata->det->TDM_prop_file=NULL; + SIXT_ERROR("Proportional cross-talk file not found"); + } + free(tmp_path); + + xmlparsedata->det->prop_TDM_scaling_1=getXMLAttributeDouble(attr,"SCALING1"); + xmlparsedata->det->prop_TDM_scaling_2=getXMLAttributeDouble(attr,"SCALING2"); + + } else if(!strcmp(Uelement, "DERCROSSTALK")){ + xmlparsedata->det->TDM_der_file=(char*)malloc(MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(xmlparsedata->det->TDM_der_file); + char* tmp_path=(char*)malloc(2*MAXFILENAME*sizeof(char)); + CHECK_MALLOC_VOID(tmp_path); + tmp_path=strcpy(tmp_path, xmlparsedata->det->filepath); + getXMLAttributeString(attr, "FILENAME", xmlparsedata->det->TDM_der_file); + tmp_path=strcat(tmp_path, xmlparsedata->det->TDM_der_file); + if (strlen(xmlparsedata->det->TDM_der_file) == 0 || access(tmp_path, F_OK)==-1){ + xmlparsedata->status=EXIT_FAILURE; + printf("Warning: Derivative cross-talk file %s is not given or does not exist\n", tmp_path); + free(xmlparsedata->det->TDM_der_file); + xmlparsedata->det->TDM_der_file=NULL; + SIXT_ERROR("Derivative cross-talk file not found"); + } + free(tmp_path); + + xmlparsedata->det->der_TDM_scaling=getXMLAttributeDouble(attr,"SCALING"); + + } else if (!strcmp(Uelement,"THRESHOLD_EVENT_LO_KEV")){ + xmlparsedata->det->threshold_event_lo_keV = getXMLAttributeDouble(attr,"VALUE"); + } else { + // Unknown tag, display warning. + char msg[MAXMSG]; + sprintf(msg, "unknown XML tag: <%s>", el); + SIXT_WARNING(msg); + } +} + +static void AdvDetXMLElementEnd(void* parsedata, const char* el) +{ + struct XMLParseData* xmlparsedata=(struct XMLParseData*)parsedata; + + // Check if an error has occurred previously. + CHECK_STATUS_VOID(xmlparsedata->status); + + // Convert the element to an upper case string. + char Uelement[MAXMSG]; + strcpy(Uelement, el); + strtoupper(Uelement); + + if (!strcmp(Uelement, "TESNOISEFILTER")) { + xmlparsedata->det->tesnoisefilter=0; + } else if(!strcmp(Uelement, "PIXEL")){ + xmlparsedata->det->inpixel=0; + xmlparsedata->det->cpix++; + } + + // Check if an error has occurred previously. + CHECK_STATUS_VOID(xmlparsedata->status); +} + +AdvDet* loadAdvDet(const char* const filename, + int* const status) +{ + // Get a new and empty data structure. + AdvDet* det=newAdvDet(status); + CHECK_STATUS_RET(*status, det); + + // Split the reference to the XML detector definition file + // into path and filename. This has to be done before + // calling the parser routine for the XML file. + char filename2[MAXFILENAME]; + char rootname[MAXFILENAME]; + // Make a local copy of the filename variable in order to avoid + // compiler warnings due to discarded const qualifier at the + // subsequent function call. + strcpy(filename2, filename); + fits_parse_rootname(filename2, rootname, status); + CHECK_STATUS_RET(*status, det); + + // Split rootname into the file path and the file name. + char* lastslash=strrchr(rootname, '/'); + if (NULL==lastslash) { + det->filepath=(char*)malloc(sizeof(char)); + CHECK_NULL_RET(det->filepath, *status, + "memory allocation for filepath failed", det); + det->filename=(char*)malloc((strlen(rootname)+1)*sizeof(char)); + CHECK_NULL_RET(det->filename, *status, + "memory allocation for filename failed", det); + strcpy(det->filepath, ""); + strcpy(det->filename, rootname); + } else { + lastslash++; + det->filename=(char*)malloc((strlen(lastslash)+1)*sizeof(char)); + CHECK_NULL_RET(det->filename, *status, + "memory allocation for filename failed", det); + strcpy(det->filename, lastslash); + + *lastslash='\0'; + det->filepath=(char*)malloc((strlen(rootname)+1)*sizeof(char)); + CHECK_NULL_RET(det->filepath, *status, + "memory allocation for filepath failed", det); + strcpy(det->filepath, rootname); + } + // END of storing the filename and filepath. + + // Read in the XML definition of the detector. + parseAdvDetXML(det, filename, status); + CHECK_STATUS_RET(*status, det); + + // Remove overlapping pixels with the rule newest survives + removeOverlapping(det,status); + + return(det); +} + + +/** Iterates the different pixels and loads the necessary RMFLibrary */ +void loadRMFLibrary(AdvDet* det, int* const status){ + det->rmf_library = malloc(sizeof(*(det->rmf_library))); + if (NULL == det->rmf_library){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation for rmf library failed"); + return; + } + det->rmf_library->rmf_array = malloc(RMFLIBRARYSIZE*sizeof(*(det->rmf_library->rmf_array))); + if (NULL == det->rmf_library->rmf_array){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation for rmf library failed"); + return; + } + det->rmf_library->filenames = malloc(RMFLIBRARYSIZE*sizeof(*(det->rmf_library->filenames))); + if (NULL == det->rmf_library->filenames){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation for rmf library failed"); + return; + } + + det->rmf_library->size = RMFLIBRARYSIZE; + det->rmf_library->n_rmf = 0; + + for (int i=0;irmf_library->rmf_array[i]=NULL; + det->rmf_library->filenames[i]=NULL; + } + + for (int i=0;inpix;i++){ + for (int j=0;jpix[i].ngrades;j++){ + addRMF(det,&(det->pix[i]),j,status); + CHECK_STATUS_VOID(*status); + } + } +} + +/** Adds the RMF corresponding to the jth index in the pixel rmffiles array to the RMF library. The RMF will only be added if it is not already in the library */ +void addRMF(AdvDet* det,AdvPix* pixel,int rmf_index,int* const status){ + if(NULL==pixel->grades){ + *status=EXIT_FAILURE; + SIXT_ERROR("Tried to load pixel RMF whereas no RMF file was given in XML. Abort"); + return; + } + for (int i=0;irmf_library->n_rmf;i++){ + if(!strcmp(det->rmf_library->filenames[i],pixel->grades[rmf_index].rmffile)){ + pixel->grades[rmf_index].rmf=det->rmf_library->rmf_array[i]; + return; //If the rmf is already in there, just update the rmfID and return + } + } + + // Update size if necessary + if (det->rmf_library->n_rmf>=det->rmf_library->size){ + det->rmf_library->size *=2; + struct RMF** new_rmf_array = realloc(det->rmf_library->rmf_array,det->rmf_library->size*sizeof(*(det->rmf_library->rmf_array))); + if (NULL==new_rmf_array){ + *status = EXIT_FAILURE; + SIXT_ERROR("Size update of RMF library failed"); + return; + } + char** new_filenames = realloc(det->rmf_library->filenames,det->rmf_library->size*sizeof(*(det->rmf_library->filenames))); + if (NULL==new_filenames){ + *status = EXIT_FAILURE; + SIXT_ERROR("Size update of RMF library failed"); + return; + } + + det->rmf_library->rmf_array=new_rmf_array; + det->rmf_library->filenames=new_filenames; + } + + //Add RMF to the library + char filepathname[MAXFILENAME]; + strncpy(filepathname,det->filepath,MAXFILENAME); + int maxch=strlen(filepathname); + if (maxchgrades[rmf_index].rmffile,MAXFILENAME-maxch); + filepathname[MAXFILENAME-1]='\0'; + } else { + *status=EXIT_FAILURE; + SIXT_ERROR("RMF path and filename are too long"); + return; + } + det->rmf_library->rmf_array[det->rmf_library->n_rmf] = loadNormalizedRMF(filepathname,status); + det->rmf_library->filenames[det->rmf_library->n_rmf] = strndup(pixel->grades[rmf_index].rmffile,MAXFILENAME); + pixel->grades[rmf_index].rmf=det->rmf_library->rmf_array[det->rmf_library->n_rmf]; + det->rmf_library->n_rmf++; +} + +/** Destructor of the RMF library structure */ +void freeRMFLibrary(RMFLibrary* library){ + if (NULL!=library){ + for(int i=0;isize;i++){ + freeRMF(library->rmf_array[i]); + free(library->filenames[i]); + } + free(library->rmf_array); + free(library->filenames); + free(library); + } + library=NULL; +} + +/** Iterates the different pixels and loads the necessary ARFLibrary */ +void loadARFLibrary(AdvDet* det, int* const status){ + det->arf_library = malloc(sizeof(*(det->arf_library))); + if (NULL == det->arf_library){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation for arf library failed"); + return; + } + det->arf_library->arf_array = malloc(RMFLIBRARYSIZE*sizeof(*(det->arf_library->arf_array))); + if (NULL == det->arf_library->arf_array){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation for arf library failed"); + return; + } + det->arf_library->filenames = malloc(RMFLIBRARYSIZE*sizeof(*(det->arf_library->filenames))); + if (NULL == det->arf_library->filenames){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation for arf library failed"); + return; + } + + det->arf_library->size = RMFLIBRARYSIZE; + det->arf_library->n_arf = 0; + + for (int i=0;iarf_library->arf_array[i]=NULL; + det->arf_library->filenames[i]=NULL; + } + + for (int i=0;inpix;i++){ + addARF(det,&(det->pix[i]),status); + CHECK_STATUS_VOID(*status); + } +} + +/** Adds an ARF to the ARF library. The ARF will only be added if it is not already in the library */ +void addARF(AdvDet* det,AdvPix* pixel,int* const status){ + if(NULL==pixel->arffile){ + *status=EXIT_FAILURE; + SIXT_ERROR("Tried to load pixel ARF whereas no ARF file was given in XML. Abort"); + return; + } + for (int i=0;iarf_library->n_arf;i++){ + if(!strcmp(det->arf_library->filenames[i],pixel->arffile)){ + pixel->arf=det->arf_library->arf_array[i]; + return; //If the arf is already in there, just update the arfID and return + } + } + + // Update size if necessary + if (det->arf_library->n_arf>=det->arf_library->size){ + det->arf_library->size = det->arf_library->size*2; + struct ARF** new_arf_array = realloc(det->arf_library->arf_array,det->arf_library->size*sizeof(*(det->arf_library->arf_array))); + if (NULL==new_arf_array){ + *status = EXIT_FAILURE; + SIXT_ERROR("Size update of ARF library failed"); + return; + } + char** new_filenames = realloc(det->arf_library->filenames,det->arf_library->size*sizeof(*(det->arf_library->filenames))); + if (NULL==new_filenames){ + *status = EXIT_FAILURE; + SIXT_ERROR("Size update of ARF library failed"); + return; + } + + det->arf_library->arf_array=new_arf_array; + det->arf_library->filenames=new_filenames; + } + + //Add ARF to the library + char filepathname[MAXFILENAME]; + strcpy(filepathname,det->filepath); + strcat(filepathname,pixel->arffile); + det->arf_library->arf_array[det->arf_library->n_arf] = loadARF(filepathname,status); + det->arf_library->filenames[det->arf_library->n_arf] = strdup(pixel->arffile); + pixel->arf=det->arf_library->arf_array[det->arf_library->n_arf]; + det->arf_library->n_arf++; +} + +/** Destructor of the ARF library structure */ +void freeARFLibrary(ARFLibrary* library){ + if (NULL!=library){ + for(int i=0;isize;i++){ + freeARF(library->arf_array[i]); + free(library->filenames[i]); + } + free(library->arf_array); + free(library->filenames); + free(library); + } + library=NULL; +} + +/** Function to remove overlapping pixels from the detector */ +void removeOverlapping(AdvDet* det,int* const status){ + char * active_pixels = malloc(det->npix*sizeof(*active_pixels)); + if (NULL==active_pixels){ + *status = EXIT_FAILURE; + SIXT_ERROR("Memory allocation failed for active_pixels in removeOverlapping"); + return; + } + + AdvPix* current_pixel=NULL; + AdvPix* pixel_to_compare=NULL; + int number_active_pixels=0; + for (int i=0;inpix;i++){ + active_pixels[i]=1; + current_pixel = &(det->pix[i]); + number_active_pixels++; + for (int j=0;jpix[j]); + if(!(current_pixel->sx-.5*current_pixel->width > pixel_to_compare->sx + .5*pixel_to_compare->width || current_pixel->sx+.5*current_pixel->width < pixel_to_compare->sx-.5*pixel_to_compare->width || + current_pixel->sy -.5*current_pixel->height > pixel_to_compare->sy+.5*pixel_to_compare->height || current_pixel->sy+.5*current_pixel->heightsy-.5*pixel_to_compare->height)){ + if (active_pixels[j]) number_active_pixels--; + active_pixels[j]=0; + } + } + } + + AdvPix* new_pix_array=malloc(number_active_pixels*sizeof(*(new_pix_array))); + if(NULL==new_pix_array){ + *status=EXIT_FAILURE; + SIXT_ERROR("Memory allocation failed for new pixel array in removeOverlapping"); + return; + } + + det->cpix=0; + for (int i=0;inpix;i++){ + if(active_pixels[i]){ + new_pix_array[det->cpix]=det->pix[i]; + new_pix_array[det->cpix].pindex=det->cpix; + det->cpix++; + } else{ + freeAdvPix(&(det->pix[i])); + } + } + free(det->pix); + det->pix = new_pix_array; + det->npix=number_active_pixels; + free(active_pixels); + headas_chat(0,"Number of pixels after removing overlaps: %d\n \n",number_active_pixels); +} + +/** Constructor for MatrixCrossTalk structure */ +IntermodulationCrossTalk* newImodCrossTalk(int* const status){ + IntermodulationCrossTalk* matrix = (IntermodulationCrossTalk*) malloc(sizeof(IntermodulationCrossTalk)); + CHECK_MALLOC_RET_NULL_STATUS(matrix,*status); + + matrix->num_cross_talk_pixels=0; + + matrix->cross_talk_pixels = NULL; + matrix->cross_talk_info = NULL; + + return matrix; +} + +/** Destructor for MatrixCrossTalk structure */ +void freeMatrixCrossTalk(MatrixCrossTalk* matrix){ + if (matrix!=NULL){ + free(matrix->cross_talk_pixels); + free(matrix->cross_talk_weights); + free(matrix->cross_talk_index); + } + free(matrix); + matrix=NULL; +} + +/** Destructor for MatrixCrossTalk structure */ +void freeMatrixEnerdepCrossTalk(MatrixEnerdepCrossTalk* matrix, int gr){ + if (matrix!=NULL){ + for(int k=0;kcross_talk_pixels_1); + free(matrix->cross_talk_pixels_2); + matrix->type_1_pix=0; + matrix->type_2_pix=0; + } + free(matrix); + matrix=NULL; +} + +/** Destructor for MatrixDerCrossTalk structure */ +void freeMatrixDerCrossTalk(MatrixDerCrossTalk* matrix){ + if (matrix!=NULL){ + free(matrix->cross_talk_pixels); + matrix->num_cross_talk_pixels=0; + } + free(matrix); + matrix=NULL; +} + +/** Destructor for MatrixCrossTalk structure */ +void freeImodCrossTalk(IntermodulationCrossTalk** matrix){ + if (*matrix!=NULL){ + for (int ii=0; ii < (*matrix)->num_cross_talk_pixels; ii++){ + free((*matrix)->cross_talk_pixels[ii]); + } + free((*matrix)->cross_talk_info); +/* for (int ii=0; ii < (*matrix)->num_cross_talk_pixels; ii++){ + free((*matrix)->cross_talk_pixels[ii]); + free((*matrix)->cross_talk_info[ii]); + } + free((*matrix)->num_pixel_combinations); */ + } + free(*matrix); +} + + +/** Constructor for MatrixCrossTalk structure */ +MatrixCrossTalk* newMatrixCrossTalk(int* const status){ + MatrixCrossTalk* matrix = (MatrixCrossTalk*) malloc(sizeof(*matrix)); + CHECK_MALLOC_RET_NULL_STATUS(matrix,*status); + + matrix->num_cross_talk_pixels=0; + matrix->cross_talk_index = NULL; + matrix->cross_talk_pixels = NULL; + matrix->cross_talk_weights = NULL; + + return matrix; +} + +/** Constructor for MatrixEnerdepCrossTalk structure */ +MatrixEnerdepCrossTalk* newMatrixEnerdepCrossTalk(int grade, int* const status){ + MatrixEnerdepCrossTalk* matrix = (MatrixEnerdepCrossTalk*) malloc(grade*sizeof(MatrixEnerdepCrossTalk)); + CHECK_MALLOC_RET_NULL_STATUS(matrix,*status); + + for(int l=0;ltype_1_pix=0; + matrix->type_2_pix=0; + matrix->cross_talk_pixels_1 = NULL; + matrix->cross_talk_pixels_2 = NULL; + + return matrix; +} + +/** Constructor for MatrixPropCrossTalk structure */ +MatrixDerCrossTalk* newMatrixDerCrossTalk(int* const status){ + MatrixDerCrossTalk* matrix = (MatrixDerCrossTalk*) malloc(sizeof(MatrixPropCrossTalk)); + CHECK_MALLOC_RET_NULL_STATUS(matrix,*status); + + matrix->num_cross_talk_pixels=0; + matrix->cross_talk_pixels = NULL; + + return matrix; +} + +/** Constructor for CrosstalkTimdep structure */ +CrosstalkTimedep* newCrossTalkTimedep(int* const status){ + CrosstalkTimedep* crosstalk_timedep = (CrosstalkTimedep*)malloc(sizeof(CrosstalkTimedep)); + CHECK_MALLOC_RET_NULL_STATUS(crosstalk_timedep,*status); + crosstalk_timedep->length=0; + crosstalk_timedep->name_type=NULL; // Useless for the moment + crosstalk_timedep->time=NULL; + crosstalk_timedep->weight=NULL; + crosstalk_timedep->weight_t0 = 1.0; + return crosstalk_timedep; +} + +/** Destructor for CrosstalkTimdep structure */ +void freeCrosstalkTimedep(CrosstalkTimedep* timedep, int gr){ + if(timedep!=NULL){ + for(int k=0; k<2*gr;k++){ + timedep[k].length=0; + free(timedep[k].name_type); + free(timedep[k].time); + free(timedep[k].weight); + timedep[k].weight_t0=0; + } + } +} diff --git a/libsixt/advdet.h b/libsixt/advdet.h new file mode 100644 index 0000000..7172020 --- /dev/null +++ b/libsixt/advdet.h @@ -0,0 +1,671 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2014 Thorsten Brand, FAU + Copyright 2015-2019 Remeis-Sternwarte, Friedrich-Alexander-Universitaet + Erlangen-Nuernberg +*/ + +#ifndef ADVDET_H +#define ADVDET_H 1 + +#include "sixt.h" +#include "impact.h" +#include "pixelimpact.h" +#include "point.h" +#include "xmlbuffer.h" +#include "teseventlist.h" +#include "pixelimpactfile.h" +#include "tespixel.h" + +// For FDM calculations in tessim +#include +#include +#include + +//////////////////////////////////////////////////////////////////////// +// Constants. +//////////////////////////////////////////////////////////////////////// + +/** Initial size of RMFLibrary. */ +#define RMFLIBRARYSIZE (10) + +#define DEFAULTGOODSAMPLE 32768 // TODO : check whether we do want to leave that as a macro + +//////////////////////////////////////////////////////////////////////// +// Type Declarations. +//////////////////////////////////////////////////////////////////////// + + +typedef struct MatrixCrossTalk MatrixCrossTalk; +typedef struct MatrixEnerdepCrossTalk MatrixEnerdepCrossTalk; +typedef struct MatrixPropCrossTalk MatrixPropCrossTalk; +typedef struct MatrixDerCrossTalk MatrixDerCrossTalk; +typedef struct Channel Channel; +typedef struct IntermodulationCrossTalk IntermodulationCrossTalk; +typedef struct ReadoutChannels ReadoutChannels; +typedef struct FDMSystem FDMSystem; + +/** Data structure describing the noise properties of calorimeter + pixels */ +typedef struct{ + + /** White noise RMS value */ + double WhiteRMS; + + /** Normalisation of the filter function */ + double H0; + + /** Number of zeros */ + int Nz; + + /** Zeros */ + double *Zeros; + + /** Number of poles */ + int Np; + + /** Poles */ + double *Poles; + + /** 1/f noise properties */ + /** 1/f rms value */ + double OoFRMS; + + /** 1/f knee frequency (e.g. the pole where the flat power spectrum + turns into a 1/f curve) */ + double OoFKnee; + +}TESNoiseProperties; + +/** Data structure defining a grading */ + +typedef struct{ + + /** Response matrix file */ + char* rmffile; + + /** ID of the rmf */ + struct RMF* rmf; + + /** The grade values */ + int value; + + /** Size in samples before and after one pulse defining the grade */ + long gradelim_pre; + long gradelim_post; + + /** Size in samples before one pulse defining the preBuffer */ + long grade_preBuffer; + +}TESGrade; + +/** Data structure describing a pixel with arbitrary geometry. + Current implementation: only rectangulars, parallel to detector + coordinate system. */ +struct AdvPix{ + + /** x-shift of pixel in respect to the detector reference point */ + double sx; + + /** y-shift of pixel in respect to the detector reference point */ + double sy; + + /** Width of the pixel [m], centered around pixel reference point. */ + double width; + + /** Height of the pixel [m], centered around pixel reference point. */ + double height; + + /** Index of pixel in detector structure. */ + int pindex; + + /** Version of pulse template. */ + char version[10]; + + /** Version index of pulse template */ + int profVersionID; + + /** Sampling frequency */ + int ADCOffset; + + /** Sampling frequency */ + double calfactor; + + /** Noise properties of pixel noise */ + TESNoiseProperties* TESNoise; + + /** Number of grades for this pixel */ + int ngrades; + + /** Different grades for this pixel */ + TESGrade* grades; + + /** Signal if grading has already been defined globally */ + int global_grading; + + /** Ancillary response file */ + char* arffile; + + /** ID of the arf inside general detector (to avoid loading one arf per pixel) */ + struct ARF* arf; + + /** Frequency of the pixel */ + double freq; + + /** Resonance frequency of the pixel */ + /** equals freq unless specified otherwise (i.e. in case of detuned pixels) */ + double resfreq; + + /** Read-out channel to which it belongs */ + Channel* channel; + + /** Cross-talk structures */ + MatrixCrossTalk* thermal_cross_talk; + + /**Electrical cross_talk */ + MatrixEnerdepCrossTalk* electrical_cross_talk; + + /** Proportional cross talk */ + MatrixPropCrossTalk* prop_cross_talk; + + /** Derivative cross talk */ + MatrixDerCrossTalk* der_cross_talk; + + /** tessim struct */ + char* tes_type; + tesparams *tes; + + /** TDM parameters */ + int row; + +}; typedef struct AdvPix AdvPix; + +struct AdvRecons{ //SIRENA + + /** Number of grades for this pixel */ + int ngrades; + + /** Different grades for this pixel */ + TESGrade* grades; + +}; typedef struct AdvRecons AdvRecons; + +/** Data structure containing a library of different RMFs */ +typedef struct{ + + /** Current size of the allocated library */ + int size; + + /** Number of RMFs in the library */ + int n_rmf; + + /** Array containing the filenames of the loaded rmfs */ + char** filenames; + + /** Array containing the rmf structures */ + struct RMF** rmf_array; + +}RMFLibrary; + +/** Data structure containing a library of different ARFs */ +typedef struct{ + + /** Current size of the allocated library */ + int size; + + /** Number of ARFs in the library */ + int n_arf; + + /** Array containing the filenames of the loaded arfs */ + char** filenames; + + /** Array containing the arf structures */ + struct ARF** arf_array; + +}ARFLibrary; + +/** structure defining the time dependent weights for the crosstalk*/ +typedef struct{ + int length; + char* name_type; // Useless for the moment + double* time; + double* weight; + double weight_t0; // weight at time t=0 (simultaneous) +} CrosstalkTimedep; + +/** structure containing one of the intermodulation crosstalk table*/ +typedef struct{ + + double**** matrix; // 4d table containing the frequency weights + + double* ampl; + double* dt; // in seconds + double* freq; + + int n_ampl; + int n_dt; + int n_freq; + + // an event is defined to extent and cause crosstalk from [dt_min,dt_max] + double dt_min; // in seconds + double dt_max; // in seconds + +}ImodTab; + +/** structure containing one of the electrical crosstalk */ +typedef struct{ + + double*** matrix; // 3d table containing the frequency weights + + double* freq_s; + double* freq_p; + double* ener_p; + + int n_freq_s; + int n_freq_p; + int n_ener_p; + +}ElecTab; + +/** structure containing the TDM cross-talk */ +typedef struct{ + + double*** matrix; // 3d table containing the weights + + double* ener_p; + double* ener_v; + double* samples; + + int n_samples; + int n_ener_p; + int n_ener_v; + +}TDMTab; + +/** Data structure describing the geometry of a pixel detector with + arbitrary pixel geometry. */ +typedef struct{ + + /** x-shift of detector in respect to the focal point */ + double sx; + + /** y-shift of detector in respect to the focal point */ + double sy; + + /** Number of pixels. */ + int npix; + + /** 1 if 'reconstruction' node exits (0 if not) */ //SIRENA + int nrecons; + + /** Counter for operations on pixels */ + int cpix; + + /** array of pixels. */ + AdvPix *pix; + + /** reconstruction info. */ //SIRENA + AdvRecons *recons; + + /** File name (without path contributions) of the FITS file + containing the XML detector definition. */ + char* filename; + + /** Path to the FITS file containing the XML detector definition. */ + char* filepath; + + /** Name of file of pulse templates. */ + char tesproffilename[MAXFILENAME]; + + /** Sampling frequency */ + double SampleFreq; + + /** Signal if being inside the 'tesnoisefilter' tag of xml */ + int tesnoisefilter; + + /** Signal if being inside the 'pixel' tag of xml */ + int inpixel; + + /** Signal if the OofNoise is requested in at least one pixel */ + int oof_activated; + + /** RMF library */ + RMFLibrary* rmf_library; + + /** ARF library */ + ARFLibrary* arf_library; + + /** TDM or not TDM */ + int tdm; + int max_rows; + + /** File listing for each pixel the channel and frequency */ + char* channel_file; + + /** File listing for each pixel the channel and resonance frequency */ + /** Same format as channel_file */ + char* channel_resfreq_file; + + /** List of all readout channels */ + ReadoutChannels* readout_channels; + + /** Structure containing the intermodulation crosstalk table and the time dependence crosstalk table */ + + char* crosstalk_intermod_file; + ImodTab* crosstalk_imod_table; + + /** Structure containing the thermal crosstalk informations */ + + char** crosstalk_thermal_timedep_file; + CrosstalkTimedep** crosstalk_ther_timedep; + int xt_num_thermal; + double* xt_dist_thermal; + double* xt_weight_thermal; + + /** Structure containing the electrical crosstalk table and the dependence crosstalk table */ + char* crosstalk_elec_file; + char* crosstalk_elec_timedep_file; + ElecTab* crosstalk_elec; + CrosstalkTimedep* crosstalk_elec_timedep; + float scaling; + + /** Structure containing the proportional TDM cross-talk tables */ + char* TDM_prop_file; + TDMTab* crosstalk_TDM_prop; + float prop_TDM_scaling_1; + float prop_TDM_scaling_2; + + /** Structure containing the derivative TDM cross-talk tables */ + char* TDM_der_file; + TDMTab* crosstalk_TDM_der; + float der_TDM_scaling; + + /** Trigger threshold */ + double threshold_event_lo_keV; + + /** Crosstalk ID (which effects should be included */ + int crosstalk_id; + + /** File containing TES pixel definitions */ + char* tes_type_file; + + /** Common impedance and capacitance for FDM Crosstalk */ + double L_Common; + double C_Common; + +}AdvDet; + + +///////////////////////////////////////////////////////////////////// +// Structures for the Crosstalk +///////////////////////////////////////////////////////////////////// + +/** Structure defining the cross talk between pixels, which can be approximated + by a simple matrix containing weights */ +struct MatrixCrossTalk{ + /** number of cross-talk pixels */ + int num_cross_talk_pixels; + + /** Distance to neighbour type*/ + int* cross_talk_index; + + /** Array containing cross-talk pixels */ + AdvPix** cross_talk_pixels; + + /** Cross-talk weights*/ + double* cross_talk_weights; + +}; + +/** Structure defining the cross talk between pixels, which can be approximated + by a simple matrix containing weights */ +struct MatrixEnerdepCrossTalk{ + /** number of cross-talk pixels */ + int num_cross_talk_pixels; + + /** Array containing cross-talk pixels */ + AdvPix** cross_talk_pixels; + + /** Cross-talk weights*/ + double** cross_talk_weights; + + int n_ener; + +}; + +/** Structure defining the proporitonal cross talk between pixels, which can be approximated + by a simple matrix containing weights */ +struct MatrixPropCrossTalk{ + + /** Number of cross-talk pixel for type 1 cross-talk */ + int type_1_pix; + + /** Number of cross-talk pixel for type 2 cross-talk */ + int type_2_pix; + + /** Array containing the cross talk pixels */ + int* cross_talk_pixels_1; + int* cross_talk_pixels_2; + +}; + +/** Structure defining the proporitonal cross talk between pixels, which can be approximated + by a simple matrix containing weights */ +struct MatrixDerCrossTalk{ + + /** Number of cross-talk pixel for type 3 cross-talk */ + int num_cross_talk_pixels; + + /** Array containing the cross talk pixels */ + int* cross_talk_pixels; +}; + + +/** Structure defining the cross talk between pixels, which can be approximated + by a simple matrix containing weights */ +struct IntermodulationCrossTalk{ + /** number of cross-talk pixels */ + int num_cross_talk_pixels; + + /** numbrer of combiniations for each pixel */ + // int* num_pixel_combinations; + + /** Array containing cross-talk pixels */ + AdvPix*** cross_talk_pixels; + + /** Cross-talk weights*/ + ImodTab** cross_talk_info; + +}; + +/** Structure containing linear equations system for FDM Crosstalk **/ +struct FDMSystem{ + int num_pixels; + double* omega_array; // angular frequencies for pixels, length = num_pixels + double* res_omega_array; // angular resonance frequencies for pixels, length = num_pixels + double** Z_array; // complex impedances (saved as doubles, since they are imaginary), size = num_pixels x num_pixels + double L_Common; // common impedance [H] + double C_Common; // common capacitance [F] + double* X_L; // imaginary impedance term that's constant and used a lot + double* capFac; // extra factor due to common capacitance - only for n = 2! + }; + + +/** Structure of a single channel, including all its contained pixels*/ +struct Channel{ + AdvPix** pixels; + int num_pixels; + int channel_id; + FDMSystem* fdmsys; +}; + +/** Structure containing a certain amount of Impacts, which are not written + to the output file yet, as further modifications due to additional + (crosstalk) events might happen or that these events directly influence + other events */ +typedef struct channelImpacts{ + double time_diff_criteria; + Impact** impacts_saved; // length = num_pixels + Channel* channel; +} channelImpacts; + +/** Structure combining all readout channels */ +struct ReadoutChannels{ + Channel* channels; + double* df_information_band; //in [Hz]; + int num_channels; +}; + +///////////////////////////////////////////////////////////////////// +// Function Declarations. +///////////////////////////////////////////////////////////////////// + +/** Constructor. Allocates memory for a new TESNoiseProperties data + structure. */ +TESNoiseProperties* newTESNoise(int* const status); + +/** Allocates zeros and poles arrays. */ +void allocateZerosPoles(TESNoiseProperties* noise,int nzeros,int npoles,int* const status); + +/** Duplicates a TESNoiseProperties structure into another. If given structure is NULL, allocate new one. */ +TESNoiseProperties* duplicateTESNoise(TESNoiseProperties* noise,int nzeros,int npoles,int* const status); + +/** Destructor. Releases all allocated memory. */ +void destroyTESNoiseProperties(TESNoiseProperties* noise); + +/** Constructor for an empty AdvPix structure */ +AdvPix* newAdvPix(int* const status); + +/** Destructor of the AdvPix structure */ +void freeAdvPix(AdvPix* pix); + +/** Constructor for an empty AdvRecons structure */ +AdvRecons* newAdvRecons(int* const status); //SIRENA + +/** Destructor of the AdvRecons structure */ +void freeAdvRecons(AdvRecons* recons); //SIRENA + +/** Remove the existing grading scheme from the pixel */ +void freeGrading(AdvPix* pix); + +/** Remove the existing grading scheme from the pixel */ +void freeGradingRecons(AdvRecons* recons); //SIRENA + +/** Frees electrical table*/ +void freeElecTab(ElecTab* tab, int gr); + +/** Free the Readout Channel Structure */ +void freeReadoutChannels(ReadoutChannels* rc); + +/** Free the FDM System Structure */ +void freeFDMSystem(FDMSystem* fdm_sys); + +/** Read the advanced detector syntax from the specified XML */ +void parseAdvDetXML(AdvDet* const det, + const char* const filename, + int* const status); + +/** Constructor. Allocates memory for a new AdvDet data structure. */ +AdvDet* newAdvDet(int* const status); + +/** Loads AdvDet information from XML file */ +AdvDet* loadAdvDet(const char* const filename, + int* const status); + +/** Destructor. Releases all allocated memory and resets the pointer + to the AdvDet data structure to NULL. */ +void destroyAdvDet(AdvDet **det); + +/** Function testing if an impact lies inside a pixel. */ +int CheckAdvPixImpact(AdvPix pix, Impact *imp); + +/** Function calculating the exact impact position and time in + pixel coordinates. */ +void CalcAdvPixImpact(AdvPix pix, Impact *imp, PixImpact *piximp); + +/** Function determining the pixel indices which have an impact from one + event. Gives the number of pixels that were hit.*/ +int AdvImpactList(AdvDet *det, Impact *imp, PixImpact **piximp); + +/** Iterates the different pixels and loads the necessary RMFLibrary */ +void loadRMFLibrary(AdvDet* det, int* const status); + +/** Adds an RMF to the RMF library. The RMF will only be added if it is not already in the library */ +void addRMF(AdvDet* det,AdvPix* pixel,int rmf_index,int* const status); + +/** Destructor of the RMF library structure */ +void freeRMFLibrary(RMFLibrary* library); + +/** Iterates the different pixels and loads the necessary ARFLibrary */ +void loadARFLibrary(AdvDet* det, int* const status); + +/** Adds an ARF to the ARF library. The ARF will only be added if it is not already in the library */ +void addARF(AdvDet* det,AdvPix* pixel,int* const status); + +/** Destructor of the ARF library structure */ +void freeARFLibrary(ARFLibrary* library); + +/** Function to remove overlapping pixels from the detector */ +void removeOverlapping(AdvDet* det,int* const status); + +/** Constructor for MatrixCrossTalk structure */ +MatrixCrossTalk* newMatrixCrossTalk(int* const status); + +/** Constructor for MatrixEnerdepCrossTalk structure */ +MatrixEnerdepCrossTalk* newMatrixEnerdepCrossTalk(int grade, int* const status); + +/** Constructor for MatrixPropCrossTalk structure */ +MatrixPropCrossTalk* newMatrixPropCrossTalk(int* const status); + +/** Constructor for MatrixDerCrossTalk structure */ +MatrixDerCrossTalk* newMatrixDerCrossTalk(int* const status); + +/** Destructor for MatrixCrossTalk structure */ +void freeMatrixCrossTalk(MatrixCrossTalk* matrix); + +/** Destructor for MatrixEnerdepCrossTalk structure */ +void freeMatrixEnerdepCrossTalk(MatrixEnerdepCrossTalk* matrix, int gr); + +/** Destructor for MatrixPropCrossTalk structure */ +void freeMatrixPropCrossTalk(MatrixPropCrossTalk* matrix); + +/** Destructor for MatrixDerCrossTalk structure */ +void freeMatrixDerCrossTalk(MatrixDerCrossTalk* matrix); + +/** Constructor for IntermodulationCrossTalk structure */ +IntermodulationCrossTalk* newImodCrossTalk(int* const status); + +/** Destructor for IntermodulationCrossTalk structure */ +void freeImodCrossTalk(IntermodulationCrossTalk** matrix); + +/** Constructor for CrosstalkTimdep structure */ +CrosstalkTimedep* newCrossTalkTimedep(int* const status); + +/** Destructor for CrosstalkTimdep structure */ +void freeCrosstalkTimedep(CrosstalkTimedep* timedep, int gr); + +/** free Intermod Table and Strcture */ +void freeImodTab(ImodTab* tab, int gr); + +/** free TDM Table and Structures */ +void freeTDMTab(TDMTab* tab, int gr); + +/** free the crosstalk structures */ +void freeCrosstalk(AdvDet* det, int gr); + +#endif /* ADVDET_H */ diff --git a/libsixt/integraSIRENA.cpp b/libsixt/integraSIRENA.cpp index 8611120..9928e1d 100755 --- a/libsixt/integraSIRENA.cpp +++ b/libsixt/integraSIRENA.cpp @@ -116,7 +116,7 @@ * It has been fixed in 'tesreconstruction' as 'DAB' * - oflength_strategy: Optimal Filter length Strategy: FREE, BASE2, BYGRADE or FIXED * - oflength: Optimal Filter length (taken into account if :option:`OFStrategy`=FIXED) - * - preBuffer: Some samples added before the starting time of a pulse + * - preBuffer: Some samples added or not before the starting time of a pulse (number of added samples read from the xml file) * - monoenergy: Monochromatic energy of input file in eV (only for library creation) * - hduPRECALWN: Add or not the PRECALWN HDU in the library file (1/0) (only for library creation) * - hduPRCLOFWM: Add or not the PRCLOFWM HDU in the library file (1/0) (only for library creation) @@ -143,12 +143,13 @@ char* const library_file, char* const event_file, int pulse_length, double scaleFactor, int samplesUp, int samplesDown, double nSgms, int detectSP, int opmode, char *detectionMode, double LrsT, double LbT, char* const noise_file, char* filter_domain, char* filter_method, char* energy_method, double filtEev, double Ifit, char *ofnoise, int lagsornot, int nLags, int Fitting35, int ofiter, char oflib, char *ofinterp, - char* oflength_strategy, int oflength, int preBuffer, + char* oflength_strategy, int oflength, char preBuffer, double monoenergy, char hduPRECALWN, char hduPRCLOFWM, int largeFilter, int interm, char* const detectFile, int errorT, int Sum0Filt, char clobber, int maxPulsesPerRecord, double SaturationValue, char* const tstartPulse1, int tstartPulse2, int tstartPulse3, double energyPCA1, double energyPCA2, char * const XMLFile, int* const status) { + //gsl_set_error_handler_off(); /*string message = ""; * char valERROR[256];*/ @@ -169,11 +170,23 @@ //EP_PRINT_ERROR("Pulse length not provided => Fixed as the base-2 value equal or lower than largeFilter",-999); // Only a warning } + // Loading in the reconstruct_init structure values related to grading and preBuffer values from the XML file + if (0 != preBuffer) reconstruct_init->preBuffer = 1; + else reconstruct_init->preBuffer = 0; + gsl_vector *pBi = gsl_vector_alloc(reconstruct_init->grading->ngrades); + gsl_matrix_get_col(pBi,reconstruct_init->grading->gradeData,2); + reconstruct_init->preBuffer_max_value = gsl_vector_max(pBi); + reconstruct_init->preBuffer_min_value = gsl_vector_min(pBi); + gsl_vector *posti = gsl_vector_alloc(reconstruct_init->grading->ngrades); + gsl_matrix_get_col(posti,reconstruct_init->grading->gradeData,1); + reconstruct_init->post_max_value = gsl_vector_max(posti); + reconstruct_init->post_min_value = gsl_vector_min(posti); if (exists) - { + { if (opmode == 1) { + /*if (pulse_length == -999) { pulse_length = oflength; @@ -182,15 +195,23 @@ if ((pulse_length < oflength) && ((strcmp(energy_method,"OPTFILT") == 0) || (strcmp(energy_method,"I2R") == 0) || (strcmp(energy_method,"I2RFITTED") == 0))) { EP_PRINT_ERROR("0-padding is going to be used)",-999); // Only a warning + /*if (preBuffer > pulse_length) + { + EP_EXIT_ERROR("It has no sense preBuffer>PulseLength",EPFAIL); + }*/ } else if ((pulse_length > oflength) && ((strcmp(energy_method,"OPTFILT") == 0) || (strcmp(energy_method,"I2R") == 0) || (strcmp(energy_method,"I2RFITTED") == 0))) { + /*if (preBuffer > oflength) + { + EP_EXIT_ERROR("It has no sense preBuffer>OFLength",EPFAIL); + }*/ pulse_length = oflength; } largeFilter = pulse_length; } - reconstruct_init->library_collection = getLibraryCollection(library_file, opmode, hduPRECALWN, hduPRCLOFWM, largeFilter, filter_domain, pulse_length, energy_method, ofnoise, filter_method, oflib, &ofinterp, filtEev, lagsornot, preBuffer, status); + reconstruct_init->library_collection = getLibraryCollection(library_file, opmode, hduPRECALWN, hduPRCLOFWM, largeFilter, filter_domain, pulse_length, energy_method, ofnoise, filter_method, oflib, &ofinterp, filtEev, lagsornot, reconstruct_init->preBuffer, pBi, posti, status); if (*status) { EP_EXIT_ERROR((char*)"Error in getLibraryCollection",EPFAIL); @@ -229,6 +250,9 @@ EP_EXIT_ERROR((char*)"Error accessing library file: it does not exists ",EPFAIL); } + gsl_vector_free(pBi); pBi = 0; + gsl_vector_free(posti); posti = 0; + // Load NoiseSpec structure reconstruct_init->noise_spectrum = NULL; bool baselineReadFromLibrary = true; @@ -384,7 +408,6 @@ strcpy(reconstruct_init->OFInterp,ofinterp); strcpy(reconstruct_init->OFStrategy,oflength_strategy); reconstruct_init->OFLength = oflength; - reconstruct_init->preBuffer = preBuffer; reconstruct_init->errorT = errorT; reconstruct_init->Sum0Filt = Sum0Filt; reconstruct_init->intermediate = interm; @@ -453,8 +476,7 @@ { EP_EXIT_ERROR("Record size is <= 0",EPFAIL); } - //log_debug("Pulse length: %d",reconstruct_init->pulse_length); - //log_debug("Record size: %d",record->trigger_size); + if(reconstruct_init->pulse_length > record->trigger_size) { //EP_EXIT_ERROR("Warning: pulse length is larger than record size. Pulse length set to maximum value (record size)",EPFAIL); @@ -688,7 +710,7 @@ } // Detect pulses in record - //log_trace("Before runDetect"); + log_trace("Before runDetect"); runDetect(record, trig_reclength,lastRecord, nRecord, *pulsesAll, &reconstruct_init, &pulsesInRecord); log_trace("After runDetect"); @@ -701,7 +723,7 @@ if ((reconstruct_init->opmode == 1) && (strcmp(reconstruct_init->EnergyMethod,"PCA") != 0)) { // Filter and calculates energy - runEnergy(record, trig_reclength, &reconstruct_init, &pulsesInRecord, optimalFilter,*pulsesAll); + runEnergy(record, nRecord, trig_reclength, &reconstruct_init, &pulsesInRecord, optimalFilter,*pulsesAll); } log_trace("After runEnergy"); @@ -742,6 +764,8 @@ if (event_list->grades2 != NULL) delete [] event_list->grades2; if (event_list->pulse_heights != NULL) delete [] event_list->pulse_heights; if (event_list->ph_ids != NULL) delete [] event_list->ph_ids; + if (event_list->ph_ids2 != NULL) delete [] event_list->ph_ids2; + if (event_list->ph_ids3 != NULL) delete [] event_list->ph_ids3; if (event_list->pix_ids != NULL) delete [] event_list->pix_ids; if (event_list->tstarts != NULL) delete [] event_list->tstarts; if (event_list->tends != NULL) delete [] event_list->tends; @@ -786,7 +810,7 @@ } } - log_debug("pulsesAll: %i",(*pulsesAll)->ndetpulses); + log_trace("pulsesAll: %i",(*pulsesAll)->ndetpulses); //cout<<"pulsesAll: "<<(*pulsesAll)->ndetpulses<ndetpulses<grades2 = new int[event_list->index]; event_list->pulse_heights = new double[event_list->index]; event_list->ph_ids = new long[event_list->index]; + event_list->ph_ids2 = new long[event_list->index]; + event_list->ph_ids3 = new long[event_list->index]; event_list->pix_ids = new long[event_list->index]; event_list->tends = new double[event_list->index]; event_list->tstarts = new double[event_list->index]; @@ -839,6 +865,8 @@ event_list->pulse_heights[ip] = pulsesInRecord->pulses_detected[ip].pulse_height; event_list->pix_ids[ip] = pulsesInRecord->pulses_detected[ip].pixid; event_list->ph_ids[ip] = pulsesInRecord->pulses_detected[ip].phid; + event_list->ph_ids2[ip] = pulsesInRecord->pulses_detected[ip].phid2; + event_list->ph_ids3[ip] = pulsesInRecord->pulses_detected[ip].phid3; event_list->tstarts[ip] = pulsesInRecord->pulses_detected[ip].Tstart; event_list->tends[ip] = pulsesInRecord->pulses_detected[ip].Tend; event_list->risetimes[ip] = pulsesInRecord->pulses_detected[ip].riseTime; @@ -861,7 +889,7 @@ } gsl_vector_free(numLagsUsed_vector); - } + } } else { @@ -1063,9 +1091,12 @@ * It has been fixed in 'tesreconstruction' as 'DAB' (but it would be possible to work with 'MF') * - filtEeV: Energy of the filters of the library to be used to calculate energy * - lagsornot: Lags (1) or no lags (0) + * - preBuffer: Using preBuffer (1) or not using preBuffer (0) + * - pBi: Vector with the preBuffer values read from the XML file + * - posti: Vector with the post values read from the XML file * - status: Input/output status ******************************************************************************/ - LibraryCollection* getLibraryCollection(const char* const filename, int opmode, int hduPRECALWN, int hduPRCLOFWM, int largeFilter, char* filter_domain, int pulse_length, char *energy_method, char *ofnoise, char *filter_method, char oflib, char **ofinterp, double filtEev, int lagsornot, int preBuffer, int* const status) + LibraryCollection* getLibraryCollection(const char* const filename, int opmode, int hduPRECALWN, int hduPRCLOFWM, int largeFilter, char* filter_domain, int pulse_length, char *energy_method, char *ofnoise, char *filter_method, char oflib, char **ofinterp, double filtEev, int lagsornot, int preBuffer, gsl_vector *pBi, gsl_vector *posti, int* const status) { // Create LibraryCollection structure LibraryCollection* library_collection = new LibraryCollection; @@ -1193,10 +1224,21 @@ *status = EPFAIL; return(library_collection); } - if ((opmode == 0) && (pulse_length != template_duration)) + if (preBuffer == 0) { - EP_PRINT_ERROR("It is not possible the PulseLength provided because it does not match with the PulseLength (PULSE_column_length) of the existing library",EPFAIL); - *status=EPFAIL; return(library_collection); + if ((opmode == 0) && (pulse_length != template_duration)) + { + EP_PRINT_ERROR("It is not possible the PulseLength provided because it does not match with the PulseLength (PULSE_column_length) of the existing library",EPFAIL); + *status=EPFAIL; return(library_collection); + } + } + else // preBuffer = 1 + { + if ((opmode == 0) && (gsl_vector_max(posti) != template_duration)) + { + EP_PRINT_ERROR("It is not possible the post and pB values provided in the XML file because it does not match with the template duration of the existing library",EPFAIL); + *status=EPFAIL; return(library_collection); + } } int template_durationPLSMXLFF = -999; @@ -1674,7 +1716,7 @@ gsl_matrix_set_row(library_collection->W,it,vectorAux_W); } - if ((opmode == 1) && (it < ntemplates-1) && (strcmp(energy_method,"WEIGHT") == 0) || + if (((opmode == 1) && (it < ntemplates-1) && (strcmp(energy_method,"WEIGHT") == 0)) || ((opmode == 0) && (hduPRECALWN == 1) && (ntemplates > 1) && (it < ntemplates-1))) { gsl_matrix_get_row(vectorAux_T,matrixAux_T,it); @@ -1694,14 +1736,14 @@ gsl_vector_set(library_collection->r,it,gsl_vector_get(vectorAux_r,it)); } - if ((opmode == 1) && (it < ntemplates-1) &&(strcmp(energy_method,"WEIGHTN") == 0) || + if (((opmode == 1) && (it < ntemplates-1) && (strcmp(energy_method,"WEIGHTN") == 0)) || ((opmode == 0) && (hduPRECALWN == 1) && (ntemplates > 1) && (it < ntemplates-1))) { gsl_matrix_get_row(vectorAux_WAB,matrixAux_WAB,it); gsl_matrix_set_row(library_collection->WAB,it,vectorAux_WAB); } - if ((opmode == 1) && (it < ntemplates-1) &&(strcmp(energy_method,"WEIGHTN") == 0) || + if (((opmode == 1) && (it < ntemplates-1) &&(strcmp(energy_method,"WEIGHTN") == 0)) || ((opmode == 0) && (ntemplates > 1) && (it < ntemplates-1))) { @@ -1750,7 +1792,8 @@ if (vectorAux_DAB != NULL) gsl_vector_free(vectorAux_DAB); // Added new code to handle the new HDUs FIXFILTF, FIXFILTT, PRECALWN and PRCLOFWM - if (opmode == 0) + //if (opmode == 0) + if ((opmode == 0) && (preBuffer == 0)) { // FIXFILTF HDU strcpy(HDUname,"FIXFILTF"); @@ -1768,7 +1811,7 @@ return(library_collection); } if (ntemplates == 1) nOFs = nOFs-1; // -1 because the ENERGYcolumn - else nOFs = (nOFs-1)/2; // -1 because the ENERGYcolumn and /2 because the AB column + else nOFs = (nOFs-1)/2; // -1 because the ENERGYcolumn and /2 because the AB column if (nOFs == 0) { @@ -1803,7 +1846,7 @@ } } if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) lengthALL_PRCLWN = lengthALL_F-largeFilter*2; - else lengthALL_PRCLWN = lengthALL_F; + else lengthALL_PRCLWN = lengthALL_F; lengthALL_PRCLOFWM = lengthALL_F; @@ -2157,6 +2200,149 @@ } gsl_matrix_free(matrixALL_PRCLOFWMx); } + else if ((opmode == 0) && (preBuffer == 1)) + { + // FIXFILTF HDU + strcpy(HDUname,"FIXFILTF"); + if (fits_movnam_hdu(fptr, ANY_HDU,HDUname, extver, status)) + { + EP_PRINT_ERROR("Error moving to HDU FIXFILTF in library file",*status); + return(library_collection); + } + + library_collection->nfixedfilters = posti->size; + + int lengthALL_F = 0; + int lengthALL_T = 0; + + for (int i=0;isize;i++) + { + lengthALL_T = lengthALL_T + gsl_vector_get(posti,i); + } + + lengthALL_F = lengthALL_T*2; + + gsl_matrix *matrixALL_OFFx = gsl_matrix_alloc(ntemplates,lengthALL_F); + gsl_matrix *matrixALL_OFTx = gsl_matrix_alloc(ntemplates,lengthALL_T); + gsl_matrix *matrixALLab_OFFx = gsl_matrix_alloc(ntemplates,lengthALL_F); + gsl_matrix *matrixALLab_OFTx = gsl_matrix_alloc(ntemplates,lengthALL_T); + + char str_length[125]; + + gsl_matrix *matrixAux_OFFx = NULL; + gsl_matrix *matrixAuxab_OFFx = NULL; + int index = 0; + strcpy(obj.nameTable,"FIXFILTF"); + obj.iniRow = 1; + obj.endRow = ntemplates; + for (int i=0;isize;i++) + { + snprintf(str_length,125,"%d",(int) gsl_vector_get(posti,i)); + matrixAux_OFFx = gsl_matrix_alloc(ntemplates,gsl_vector_get(posti,i)*2); + + strcpy(obj.nameCol,(string("F")+string(str_length)).c_str()); + if (readFitsComplex (obj,&matrixAux_OFFx)) + { + EP_PRINT_ERROR("Cannot run readFitsComplex in integraSIRENA.cpp",*status); + *status=EPFAIL; return(library_collection); + } + for (int j=0;jsize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALL_OFFx,j,k+index,gsl_matrix_get(matrixAux_OFFx,j,k)); + } + } + + index = index + gsl_vector_get(posti,i)*2; + + if (ntemplates > 1) + { + EP_PRINT_ERROR("Code not prepared for ntemplates>1 and preBuffer=yes",*status); + return(library_collection); + } + + gsl_matrix_free(matrixAux_OFFx); + gsl_matrix_free(matrixAuxab_OFFx); + } + + // FIXFILTT HDU + strcpy(HDUname,"FIXFILTT"); + if (fits_movnam_hdu(fptr, ANY_HDU,HDUname, extver, status)) + { + EP_PRINT_ERROR("Error moving to HDU FIXFILTT in library file",*status); + return(library_collection); + } + + gsl_matrix *matrixAux_OFTx = NULL; + gsl_matrix *matrixAuxab_OFTx = NULL; + index = 0; + strcpy(obj.nameTable,"FIXFILTT"); + for (int i=0;isize;i++) + { + snprintf(str_length,125,"%d",(int) gsl_vector_get(posti,i)); + matrixAux_OFTx = gsl_matrix_alloc(ntemplates,gsl_vector_get(posti,i)); + + strcpy(obj.nameCol,(string("T")+string(str_length)).c_str()); + if (readFitsComplex (obj,&matrixAux_OFTx)) + { + EP_PRINT_ERROR("Cannot run readFitsComplex in integraSIRENA.cpp",*status); + *status=EPFAIL; return(library_collection); + } + for (int j=0;jsize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALL_OFTx,j,k+index,gsl_matrix_get(matrixAux_OFTx,j,k)); + } + } + + if (ntemplates > 1) + { + EP_PRINT_ERROR("Code not prepared for ntemplates>1 and preBuffer=yes",*status); + return(library_collection); + } + + index = index + gsl_vector_get(posti,i); + + gsl_matrix_free(matrixAux_OFTx); + gsl_matrix_free(matrixAuxab_OFTx); + } + for (int it=0;itoptimal_filtersFREQ[it].energy = gsl_vector_get(library_collection->energies,it); + library_collection->optimal_filtersFREQ[it].ofilter_duration = lengthALL_F; + library_collection->optimal_filtersFREQ[it].ofilter = gsl_vector_alloc(lengthALL_F); + + gsl_matrix_get_row(library_collection->optimal_filtersFREQ[it].ofilter,matrixALL_OFFx,it); + + library_collection->optimal_filtersTIME[it].energy = gsl_vector_get(library_collection->energies,it); + library_collection->optimal_filtersTIME[it].ofilter_duration = lengthALL_T; + library_collection->optimal_filtersTIME[it].ofilter = gsl_vector_alloc(lengthALL_T); + + gsl_matrix_get_row(library_collection->optimal_filtersTIME[it].ofilter,matrixALL_OFTx,it); + + if (it < ntemplates-1) + { + library_collection->optimal_filtersabFREQ[it].energy = gsl_vector_get(library_collection->energies,it); + library_collection->optimal_filtersabFREQ[it].ofilter_duration = lengthALL_F; + library_collection->optimal_filtersabFREQ[it].ofilter = gsl_vector_alloc(lengthALL_F); + + gsl_matrix_get_row(library_collection->optimal_filtersabFREQ[it].ofilter,matrixALLab_OFFx,it); + + library_collection->optimal_filtersabTIME[it].energy = gsl_vector_get(library_collection->energies,it); + library_collection->optimal_filtersabTIME[it].ofilter_duration = lengthALL_F; + library_collection->optimal_filtersabTIME[it].ofilter = gsl_vector_alloc(lengthALL_T); + + gsl_matrix_get_row(library_collection->optimal_filtersabTIME[it].ofilter,matrixALLab_OFTx,it); + } + } + + gsl_matrix_free(matrixALL_OFFx); + gsl_matrix_free(matrixALL_OFTx); + gsl_matrix_free(matrixALLab_OFFx); + gsl_matrix_free(matrixALLab_OFTx); + } if ((opmode == 1) && (oflib == 1)) { @@ -2183,14 +2369,24 @@ return(library_collection); } - if (ntemplates == 1) + if (preBuffer == 0) { - int nOFs_aux; - nOFs_aux = nOFs-1; // -1 because the ENERGYcolumn - if ((nOFs_aux == floor(log2(template_duration))) || (nOFs_aux == 1 + floor(log2(template_duration)))) nOFs = nOFs-1; // -1 because the ENERGYcolumn - else nOFs = (nOFs-1)/2; // /2 because the AB column + if (ntemplates == 1) + { + int nOFs_aux; + nOFs_aux = nOFs-1; // -1 because the ENERGYcolumn + if ((nOFs_aux == floor(log2(template_duration))) || (nOFs_aux == 1 + floor(log2(template_duration)))) nOFs = nOFs-1; // -1 because the ENERGYcolumn + else nOFs = (nOFs-1)/2; // /2 because the AB column + } + else nOFs = (nOFs-1)/2; // /2 because the AB column } - else nOFs = (nOFs-1)/2; // /2 because the AB column + else // preBuffer =1 + { + if (ntemplates == 1) nOFs = nOFs-1; // -1 because the ENERGYcolumn + else nOFs = (nOFs-1)/2; // /2 because the AB column + + } + if (nOFs == 0) { EP_PRINT_ERROR("The library has no fixed optimal filters",EPFAIL); @@ -2199,16 +2395,34 @@ library_collection->nfixedfilters = nOFs; int lengthALL_F = 0; - for (int i=0;isize) + { + EP_PRINT_ERROR("The number of optimal filters in the library does not match the grading info in the XML file",EPFAIL); + *status=EPFAIL; return(library_collection); + } + for (int i=0;isize;i++) + { + lengthALL_T = lengthALL_T + gsl_vector_get(posti,i) + gsl_vector_get(pBi,i); + } + + lengthALL_F = lengthALL_T*2; + } + strcpy(obj.nameTable,"FIXFILTF"); if (strcmp(*ofinterp,"MF") == 0) @@ -2216,53 +2430,82 @@ gsl_matrix *matrixALL_OFFx = gsl_matrix_alloc(ntemplates,lengthALL_F); gsl_matrix *matrixAux_OFFx = NULL; - for (int i=0;isize1;j++) - { - for (int k=0;ksize2;k++) - { - gsl_matrix_set(matrixALL_OFFx,j,k+index,gsl_matrix_get(matrixAux_OFFx,j,k)); - } - } - - if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) - { - if (i==0) index = index + template_durationPLSMXLFF*2; - else index = index + pow(2,floor(log2(template_duration))-i+1)*2; - } - else index = index + pow(2,floor(log2(template_duration))-i)*2; - - gsl_matrix_free(matrixAux_OFFx); + for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALL_OFFx,j,k+index,gsl_matrix_get(matrixAux_OFFx,j,k)); + } + } + + if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) + { + if (i==0) index = index + template_durationPLSMXLFF*2; + else index = index + pow(2,floor(log2(template_duration))-i+1)*2; + } + else index = index + pow(2,floor(log2(template_duration))-i)*2; + + gsl_matrix_free(matrixAux_OFFx); + } + } + else // preBuffer=1 + { + for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALL_OFFx,j,k+index,gsl_matrix_get(matrixAux_OFFx,j,k)); + } + } + + index = index + gsl_vector_get(posti,i)*2; + + gsl_matrix_free(matrixAux_OFFx); + } } for (int it=0;itoptimal_filters[it].energy = gsl_vector_get(library_collection->energies,it); + library_collection->optimal_filters[it].energy = gsl_vector_get(library_collection->energies,it); library_collection->optimal_filters[it].ofilter_duration = lengthALL_F; library_collection->optimal_filters[it].ofilter = gsl_vector_alloc(lengthALL_F); @@ -2276,48 +2519,77 @@ gsl_matrix *matrixALLab_OFFx = gsl_matrix_alloc(ntemplates,lengthALL_F); gsl_matrix *matrixAuxab_OFFx = NULL; - for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALLab_OFFx,j,k+index,gsl_matrix_get(matrixAuxab_OFFx,j,k)); + } + } + + if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) + { + if (i==0) index = index + template_durationPLSMXLFF*2; + else index = index + pow(2,floor(log2(template_duration))-i+1)*2; + } + else index = index + pow(2,floor(log2(template_duration))-i)*2; + + gsl_matrix_free(matrixAuxab_OFFx); + } + } + else //preBuffer = 1 { - if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) + for (int i=0;isize1;j++) - { - for (int k=0;ksize2;k++) + for (int j=0;jsize1;j++) { - gsl_matrix_set(matrixALLab_OFFx,j,k+index,gsl_matrix_get(matrixAuxab_OFFx,j,k)); + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALLab_OFFx,j,k+index,gsl_matrix_get(matrixAuxab_OFFx,j,k)); + } } + + index = index + gsl_vector_get(posti,i)*2; + + gsl_matrix_free(matrixAuxab_OFFx); } - - if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) - { - if (i==0) index = index + template_durationPLSMXLFF*2; - else index = index + pow(2,floor(log2(template_duration))-i+1)*2; - } - else index = index + pow(2,floor(log2(template_duration))-i)*2; - - gsl_matrix_free(matrixAuxab_OFFx); } for (int it=0;itnfixedfilters = nOFs; int lengthALL_T = 0; - for (int i=0;isize) + { + EP_PRINT_ERROR("The number of optimal filters in the library does not match the grading info in the XML file",EPFAIL); + *status=EPFAIL; return(library_collection); + } + for (int i=0;isize1;j++) - { - for (int k=0;ksize2;k++) - { - gsl_matrix_set(matrixALL_OFTx,j,k+index,gsl_matrix_get(matrixAux_OFTx,j,k)); - } - } - - if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) - { - if (i==0) index = index + template_durationPLSMXLFF; - else index = index + pow(2,floor(log2(template_duration))-i+1); - } - else index = index + pow(2,floor(log2(template_duration))-i); - - gsl_matrix_free(matrixAux_OFTx); + for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALL_OFTx,j,k+index,gsl_matrix_get(matrixAux_OFTx,j,k)); + } + } + + if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) + { + if (i==0) index = index + template_durationPLSMXLFF; + else index = index + pow(2,floor(log2(template_duration))-i+1); + } + else index = index + pow(2,floor(log2(template_duration))-i); + + gsl_matrix_free(matrixAux_OFTx); + } + } + else // preBuffer =1 + { + for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALL_OFTx,j,k+index,gsl_matrix_get(matrixAux_OFTx,j,k)); + } + } + + index = index + gsl_vector_get(posti,i); + + gsl_matrix_free(matrixAux_OFTx); + } } for (int it=0;itsize1;j++) - { - for (int k=0;ksize2;k++) - { - gsl_matrix_set(matrixALLab_OFTx,j,k+index,gsl_matrix_get(matrixAuxab_OFTx,j,k)); - } - } - - if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) - { - if (i==0) index = index + template_durationPLSMXLFF; - else index = index + pow(2,floor(log2(template_duration))-i+1); - } - else index = index + pow(2,floor(log2(template_duration))-i); - - gsl_matrix_free(matrixAuxab_OFTx); - } + for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALLab_OFTx,j,k+index,gsl_matrix_get(matrixAuxab_OFTx,j,k)); + } + } + + if ((ncols == 7) || (ncols == 9) || (ncols == 10) || (ncols == 19)) + { + if (i==0) index = index + template_durationPLSMXLFF; + else index = index + pow(2,floor(log2(template_duration))-i+1); + } + else index = index + pow(2,floor(log2(template_duration))-i); + + gsl_matrix_free(matrixAuxab_OFTx); + } + } + else // preBuffer = 1 + { + for (int i=0;isize1;j++) + { + for (int k=0;ksize2;k++) + { + gsl_matrix_set(matrixALLab_OFTx,j,k+index,gsl_matrix_get(matrixAuxab_OFTx,j,k)); + } + } + + index = index + gsl_vector_get(posti,i); + + gsl_matrix_free(matrixAuxab_OFTx); + } + } for (int it=0;itn_record); - th_runEnergy(data->rec, data->trig_reclength, + th_runEnergy(data->rec, data->n_record, data->trig_reclength, &(data->rec_init), &(data->record_pulses), //&(data->optimal_filter)); @@ -89,7 +89,7 @@ void energy_worker_v2() if(detected_queue.wait_and_pop(data)){ //log_trace("Extracting energy data from queue..."); //log_debug("Energy data in record %i",data->n_record); - th_runEnergy(data->rec, data->trig_reclength, + th_runEnergy(data->rec, data->n_record, data->trig_reclength, &(data->rec_init), &(data->record_pulses), //&(data->optimal_filter); @@ -156,12 +156,13 @@ void scheduler::push_detection(TesRecord* record, int trig_reclength, input->event_list->grades2 = new int[event_list->size]; input->event_list->pulse_heights = new double[event_list->size]; input->event_list->ph_ids = new long[event_list->size]; + input->event_list->ph_ids2 = new long[event_list->size]; + input->event_list->ph_ids3 = new long[event_list->size]; input->event_list->grading = new int[event_list->size]; input->event_list->phis = new double[event_list->size]; input->event_list->lagsShifts = new int[event_list->size]; input->event_list->bsln = new double[event_list->size]; input->event_list->pix_ids = new long[event_list->size]; - input->event_list->ph_ids = new long[event_list->size]; log_trace("push_detection 3"); detection_queue.push(input); log_trace("push_detection 4"); @@ -316,12 +317,14 @@ void scheduler::finish_reconstruction(ReconstructInitSIRENA* reconstruct_init, event_list->grades1[ip] = record_pulses->pulses_detected[ip].grade1; event_list->grades2[ip] = record_pulses->pulses_detected[ip].grade2; event_list->pulse_heights[ip] = record_pulses->pulses_detected[ip].pulse_height; - event_list->ph_ids[ip] = 0; + //event_list->ph_ids[ip] = 0; event_list->phis[ip] = record_pulses->pulses_detected[ip].phi; event_list->lagsShifts[ip] = record_pulses->pulses_detected[ip].lagsShift; event_list->bsln[ip] = record_pulses->pulses_detected[ip].bsln; event_list->pix_ids[ip] = record_pulses->pulses_detected[ip].pixid; event_list->ph_ids[ip] = record_pulses->pulses_detected[ip].phid; + event_list->ph_ids2[ip] = record_pulses->pulses_detected[ip].phid2; + event_list->ph_ids3[ip] = record_pulses->pulses_detected[ip].phid3; } if (data_array[i]->last_record == 1) { //log_debug("eventlist last record"); @@ -362,12 +365,14 @@ void scheduler::finish_reconstruction(ReconstructInitSIRENA* reconstruct_init, event_list->grades1[ip] = (*pulsesAll)->pulses_detected[ip].grade1; event_list->grades2[ip] = (*pulsesAll)->pulses_detected[ip].grade2; event_list->pulse_heights[ip] = (*pulsesAll)->pulses_detected[ip].pulse_height; - event_list->ph_ids[ip] = 0; + //event_list->ph_ids[ip] = 0; event_list->phis[ip] = record_pulses->pulses_detected[ip].phi; event_list->lagsShifts[ip] = record_pulses->pulses_detected[ip].lagsShift; event_list->bsln[ip] = record_pulses->pulses_detected[ip].bsln; event_list->pix_ids[ip] = record_pulses->pulses_detected[ip].pixid; event_list->ph_ids[ip] = record_pulses->pulses_detected[ip].phid; + event_list->ph_ids2[ip] = record_pulses->pulses_detected[ip].phid2; + event_list->ph_ids3[ip] = record_pulses->pulses_detected[ip].phid3; } } } @@ -538,12 +543,14 @@ void scheduler::finish_reconstruction_v2(ReconstructInitSIRENA* reconstruct_init event_list->grades1[ip] = record_pulses->pulses_detected[ip].grade1; event_list->grades2[ip] = record_pulses->pulses_detected[ip].grade2; event_list->pulse_heights[ip] = record_pulses->pulses_detected[ip].pulse_height; - event_list->ph_ids[ip] = 0; + //event_list->ph_ids[ip] = 0; event_list->phis[ip] = record_pulses->pulses_detected[ip].phi; event_list->lagsShifts[ip] = record_pulses->pulses_detected[ip].lagsShift; event_list->bsln[ip] = record_pulses->pulses_detected[ip].bsln; event_list->pix_ids[ip] = record_pulses->pulses_detected[ip].pixid; event_list->ph_ids[ip] = record_pulses->pulses_detected[ip].phid; + event_list->ph_ids2[ip] = record_pulses->pulses_detected[ip].phid2; + event_list->ph_ids3[ip] = record_pulses->pulses_detected[ip].phid3; } if (data_array[i]->last_record == 1) { //log_debug("eventlist last record"); @@ -584,12 +591,14 @@ void scheduler::finish_reconstruction_v2(ReconstructInitSIRENA* reconstruct_init event_list->grades1[ip] = (*pulsesAll)->pulses_detected[ip].grade1; event_list->grades2[ip] = (*pulsesAll)->pulses_detected[ip].grade2; event_list->pulse_heights[ip] = (*pulsesAll)->pulses_detected[ip].pulse_height; - event_list->ph_ids[ip] = 0; + //event_list->ph_ids[ip] = 0; event_list->phis[ip] = record_pulses->pulses_detected[ip].phi; event_list->lagsShifts[ip] = record_pulses->pulses_detected[ip].lagsShift; event_list->bsln[ip] = record_pulses->pulses_detected[ip].bsln; event_list->pix_ids[ip] = record_pulses->pulses_detected[ip].pixid; event_list->ph_ids[ip] = record_pulses->pulses_detected[ip].phid; + event_list->ph_ids2[ip] = record_pulses->pulses_detected[ip].phid2; + event_list->ph_ids3[ip] = record_pulses->pulses_detected[ip].phid3; } } } diff --git a/libsixt/tasksSIRENA.cpp b/libsixt/tasksSIRENA.cpp index a439f98..33ecb46 100755 --- a/libsixt/tasksSIRENA.cpp +++ b/libsixt/tasksSIRENA.cpp @@ -1,4 +1,3 @@ - /*********************************************************************** * This file is part of SIXTE/SIRENA software. * @@ -106,7 +105,7 @@ * - Create intermediate output FITS file if required ('createDetectFile') * - (Filter and) differentiate the 'models' of the library (only for the first record in PRODUCTION 'opmode=1') ('filderLibrary') * - Store the input record in 'invector' ('loadRecord') - * - Detect weird oscillations in some GSFC records + * - Detect weird oscillations in some GSFC records providing a warning (no pulses detected in that record) * - Convert I into R if 'EnergyMethod' = I2R or I2RFITTED ('convertI2R') * - Process each record ('proceRecord') * - (Low-pass filter and) differentiate @@ -136,7 +135,7 @@ * - record: Member of TesRecord' structure that contains the input record * - trig_reclength: Record size (just in case threading and input files with different 'ADC' lengths but the same record size indeed) * - lastRecord: Integer to verify whether record is the last one (=1) to be read (and thus if library file will be created) - * - nrecord: Current record index (to know the particular record where there is a weird oscillation) + * - nrecord: Current record index (to know the particular record where there is a weird oscillation) * - pulsesAll: Member of 'PulsesCollection' structure to successively store all the pulses used to create the library. Re-populated after each processed record * - reconstruct_init: Member of 'ReconstructInitSIRENA' structure to initialize the reconstruction parameters (pointer and values) * - pulsesInRecord: Member of 'PulsesCollection' structure to store all the pulses found in the input record @@ -216,6 +215,10 @@ void runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nrecor message = "Cannot run routine loadRecord"; EP_EXIT_ERROR(message,EPFAIL); } + /*for (int i=0;isize;i++) + { + cout<trigger_size > trig_reclength) @@ -267,6 +270,7 @@ void runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nrecor message = "Cannot run routine convertI2R"; EP_EXIT_ERROR(message,EPFAIL); } + //gsl_vector_scale(invector,100000); } for (int i=0;isize;i++) // Because in 'runEnergy' the record (TesRecord) is used => The I2R or I2RFITTED transformed record has to be used @@ -276,12 +280,17 @@ void runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nrecor log_trace("Detecting..."); // Process each record - if (procRecord(reconstruct_init, tstartRecord, 1/record->delta_t, dtcObject, invector, invectorOriginal,*pulsesInRecord, pulsesAll->ndetpulses, record->pixid,record->phid_list->phid_array[0], oscillations)) + //if (procRecord(reconstruct_init, tstartRecord, 1/record->delta_t, dtcObject, invector, invectorOriginal,*pulsesInRecord, pulsesAll->ndetpulses, record->pixid,record->phid_list->phid_array[0], oscillations)) + gsl_vector *phid = gsl_vector_alloc(3); + for (int i=0;isize;i++) gsl_vector_set(phid,i,record->phid_list->phid_array[i]); + if (procRecord(reconstruct_init, tstartRecord, 1/record->delta_t, dtcObject, invector, invectorOriginal,*pulsesInRecord, pulsesAll->ndetpulses, record->pixid, phid, oscillations)) { message = "Cannot run routine procRecord for record processing"; EP_EXIT_ERROR(message,EPFAIL); } gsl_vector_free(invectorOriginal); invectorOriginal = 0; + gsl_vector_free(phid); phid = 0; + log_trace("After detecting..."); // From this point forward, I2R and I2RFITTED are completely equivalent to OPTFILT if ((strcmp((*reconstruct_init)->EnergyMethod,"I2R") == 0) || (strcmp((*reconstruct_init)->EnergyMethod,"I2RFITTED") == 0)) @@ -332,15 +341,24 @@ void runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nrecor // Calculate an average record // It is not necessary to check the allocation because 'PulseLength' (input parameter) has been checked previously - gsl_vector *pulsetemplateMaxLengthFixedFilter = gsl_vector_alloc((*reconstruct_init)->largeFilter); - gsl_vector *pulsetemplate = gsl_vector_alloc((*reconstruct_init)->pulse_length); + gsl_vector *pulsetemplateMaxLengthFixedFilter; + gsl_vector *pulsetemplate; + if ((*reconstruct_init)->preBuffer == 0) + { + pulsetemplateMaxLengthFixedFilter = gsl_vector_alloc((*reconstruct_init)->largeFilter); + pulsetemplate = gsl_vector_alloc((*reconstruct_init)->pulse_length); + } + else if ((*reconstruct_init)->preBuffer == 1) + { + pulsetemplateMaxLengthFixedFilter = gsl_vector_alloc((*reconstruct_init)->post_max_value); + pulsetemplate = gsl_vector_alloc((*reconstruct_init)->post_max_value); + } double pulseheighttemplate = 0; gsl_matrix *weight = gsl_matrix_alloc(inputPulseLength,inputPulseLength); gsl_matrix *covariance = gsl_matrix_alloc(inputPulseLength,inputPulseLength); gsl_matrix_set_zero(weight); gsl_matrix_set_zero(covariance); - log_trace("Before calculateTemplate..."); if (calculateTemplate (*reconstruct_init, pulsesAll, *pulsesInRecord, 1/record->delta_t, &pulsetemplate, &pulseheighttemplate, &covariance, &weight, &pulsetemplateMaxLengthFixedFilter)) { message = "Cannot run routine calculateTemplate in CALIBRATION mode"; @@ -865,7 +883,7 @@ void th_runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nre gsl_vector *invectorOriginal = gsl_vector_alloc(invector->size); gsl_vector_memcpy(invectorOriginal,invector); - // To detect weird oscillations in some GSFC records + // To detect weird oscillations in some GSFC records double meanTEST=0; double sgTEST=0; if (findMeanSigma (invector, &meanTEST, &sgTEST)) @@ -892,6 +910,7 @@ void th_runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nre message = "Cannot run routine convertI2R"; EP_EXIT_ERROR(message,EPFAIL); } + //gsl_vector_scale(invector,100000); } // Convert I into R if 'EnergyMethod' = I2R or I2RFITTED @@ -914,6 +933,7 @@ void th_runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nre message = "Cannot run routine convertI2R"; EP_EXIT_ERROR(message,EPFAIL); } + //gsl_vector_scale(invector,100000); for (int i=0;isize;i++) // Because in 'runEnergy' the record (TesRecord) is used => The I2R or I2RFITTED transformed record has to be used { @@ -929,6 +949,7 @@ void th_runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nre message = "Cannot run routine convertI2R"; EP_EXIT_ERROR(message,EPFAIL); } + // gsl_vector_scale(invector,100000); for (int i=0;isize;i++) // Because in 'runEnergy' the record (TesRecord) is used => The I2R or I2RFITTED transformed record has to be used { @@ -939,13 +960,18 @@ void th_runDetect(TesRecord* record, int trig_reclength, int lastRecord, int nre // Process each record // thread safe + gsl_vector *phid = gsl_vector_alloc(3); + for (int i=0;isize;i++) gsl_vector_set(phid,i,record->phid_list->phid_array[i]); + //if (procRecord(reconstruct_init, tstartRecord, 1/record->delta_t, dtcObject, + // invector, invectorOriginal, *pulsesInRecord, pulsesAll->ndetpulses,record->pixid,record->phid_list->phid_array[0], oscillations)) if (procRecord(reconstruct_init, tstartRecord, 1/record->delta_t, dtcObject, - invector, invectorOriginal, *pulsesInRecord, pulsesAll->ndetpulses,record->pixid,record->phid_list->phid_array[0],oscillations)) + invector, invectorOriginal, *pulsesInRecord, pulsesAll->ndetpulses,record->pixid,phid, oscillations)) { message = "Cannot run routine procRecord for record processing"; EP_EXIT_ERROR(message,EPFAIL); } gsl_vector_free(invectorOriginal); invectorOriginal = 0; + gsl_vector_free(phid); phid = 0; if ((strcmp((*reconstruct_init)->EnergyMethod,"I2R") == 0) || (strcmp((*reconstruct_init)->EnergyMethod,"I2RFITTED") == 0)) { @@ -2188,17 +2214,15 @@ int loadRecord(TesRecord* record, double *time_record, gsl_vector **adc_double) * - foundPulses: Input/output structure where the found pulses info is stored * - num_previousDetectedPulses: Number of previous detected pulses (to know the index to get the proper element from tstartPulse1_i in case tstartPulse1=nameFile) * - pixid: Pixel ID (from the input file) to be propagated - * - phid: Photon ID (from the input file) to be propagated + * - phid: Photon ID (from the input file) to be propagated * - oscillations: 1 (there are weird oscillations in the record) or 0 (record without weird oscillations) ****************************************************************************/ -int procRecord(ReconstructInitSIRENA** reconstruct_init, double tstartRecord, double samprate, fitsfile *dtcObject, gsl_vector *record, gsl_vector *recordWithoutConvert2R, PulsesCollection *foundPulses, long num_previousDetectedPulses, int pixid, int phid, int oscillations) +int procRecord(ReconstructInitSIRENA** reconstruct_init, double tstartRecord, double samprate, fitsfile *dtcObject, gsl_vector *record, gsl_vector *recordWithoutConvert2R, PulsesCollection *foundPulses, long num_previousDetectedPulses, int pixid, gsl_vector *phid, int oscillations) { int status = EPOK; string message = ""; char valERROR[256]; - int preBuffer = (*reconstruct_init)-> preBuffer; - // Declare and initialize variables int numPulses = 0; double threshold = 0.0; @@ -2211,10 +2235,17 @@ int procRecord(ReconstructInitSIRENA** reconstruct_init, double tstartRecord, do gsl_vector_view temp; double scaleFactor = (*reconstruct_init)->scaleFactor; - //int sizePulse_b = (*reconstruct_init)->pulse_length; - //cout<<"(*reconstruct_init)->pulse_length: "<<(*reconstruct_init)->pulse_length<largeFilter: "<<(*reconstruct_init)->largeFilter<pulse_length,(*reconstruct_init)->largeFilter); + int preBuffer_value; + + int sizePulse_b; + if ((*reconstruct_init)->preBuffer == 1) + { + sizePulse_b = (*reconstruct_init)->post_max_value; + } + else + { + sizePulse_b = ((*reconstruct_init)->pulse_length,(*reconstruct_init)->largeFilter); + } int samplesUp = (*reconstruct_init)->samplesUp; double nSgms = (*reconstruct_init)->nSgms; double Lrs = (int) ((*reconstruct_init)->LrsT*samprate); // Running sum length (in the RS filter case): 'LrsT' in samples @@ -2391,6 +2422,7 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ numPulses = 0; (*reconstruct_init)->threshold = -999.0; } + log_debug("procRecord: After finding pulses"); // Write test info if ((*reconstruct_init)->intermediate == 1) @@ -2404,8 +2436,8 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ gsl_vector_free(recordDERIVATIVEOriginal); recordDERIVATIVEOriginal = 0; //cout<<"numPulses: "< Standard (good) pulses // 1 => Truncated pulses at the beginning (when detecting: 'findTstartCAL', 'InitialTriggering', 'FindSecondaries' and 'FindSecondaries') @@ -2413,6 +2445,7 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ // 10 => Saturated pulses ('procRecord') // 11 => Truncated at the beginning and saturated pulses ('procRecord') // 12 => Truncated at the end and saturated pulses ('procRecord') + //cout<<"sizePulse_b: "<opmode == 1) gsl_vector_set(tstartgsl,i,gsl_vector_get(tstartgsl,i) + (*reconstruct_init)->errorT); @@ -2423,7 +2456,14 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ } else { - gsl_vector_set(tendgsl,i,gsl_vector_get(tstartgsl,i)-preBuffer+sizePulse_b); //tend_i = tstart_i + Pulse_Length + if ((*reconstruct_init)->preBuffer == 1) + { + gsl_vector_set(tendgsl,i,gsl_vector_get(tstartgsl,i)-(*reconstruct_init)->preBuffer_min_value+sizePulse_b); //tend_i = tstart_i + Pulse_Length + } + else + { + gsl_vector_set(tendgsl,i,gsl_vector_get(tstartgsl,i)+sizePulse_b); //tend_i = tstart_i + Pulse_Length + } } if (gsl_vector_get(tendgsl,i) > recordDERIVATIVE->size) // Truncated pulses at the end of the record @@ -2461,6 +2501,7 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ } }*/ } + log_debug("procRecord: After calculating tend"); // Calculate the baseline before a pulse (in general 'before') => To be written in BSLN column in the output FITS file gsl_vector *Lbgsl = gsl_vector_alloc((*reconstruct_init)->maxPulsesPerRecord); // If there is no free-pulses segments longer than Lb=> @@ -2469,23 +2510,13 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ gsl_vector *rmsBgsl; if (numPulses != 0) { - //if ((Lb == 0.0) || ((*reconstruct_init)->opmode == 0)) - /*if ((*reconstruct_init)->opmode == 0) - * { - * Bgsl = gsl_vector_alloc(numPulses); - * gsl_vector_set_all(Bgsl,-999.0); - * rmsBgsl = gsl_vector_alloc(numPulses); - * gsl_vector_set_all(rmsBgsl,-999.0); - } - else - {*/ if (getB(recordNOTFILTERED, tstartgsl, numPulses, &Lbgsl, (*reconstruct_init)->pulse_length, &Bgsl, &rmsBgsl)) { message = "Cannot run getB"; EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } - //} } + log_debug("procRecord: After calculating the baseline"); // Obtain the approximate rise and fall times of each pulse // It is not necessary to check the allocation because '(*reconstruct_init)->maxPulsesPerRecord'='EventListSize'(input parameter) must already be > 0 @@ -2498,16 +2529,47 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ message = "Cannot run routine obtainRiseFallTimes to calculate rise and fall times"; EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } + log_debug("procRecord: After obtaining rise and fall times"); // Load the found pulses data in the input/output 'foundPulses' structure foundPulses->ndetpulses = numPulses; foundPulses->pulses_detected = new PulseDetected[numPulses]; - log_debug("**numPulses: %i",numPulses); //cout<<"numPulses : "<pulses_detected[i].pulse_duration = floor(gsl_vector_get(tendgsl,i)-gsl_vector_get(tstartgsl,i)); - foundPulses->pulses_detected[i].pulse_duration = floor(gsl_vector_get(tendgsl,i)-(gsl_vector_get(tstartgsl,i)-preBuffer)); + foundPulses->pulses_detected[i].pulse_duration = floor(gsl_vector_get(tendgsl,i)-(gsl_vector_get(tstartgsl,i)-(*reconstruct_init)->preBuffer_min_value)); + if (((*reconstruct_init)->preBuffer == 1) && ((*reconstruct_init)->opmode == 1)) + { + if (((*reconstruct_init)->OFLength > foundPulses->pulses_detected[i].pulse_duration) && ((*reconstruct_init)->pulse_length >= (*reconstruct_init)->OFLength)) + { + resize_mf = (*reconstruct_init)->OFLength; + } + else if ((*reconstruct_init)->pulse_length < (*reconstruct_init)->OFLength) + { + resize_mf = (*reconstruct_init)->pulse_length; + } + else + { + resize_mf = (*reconstruct_init)->OFLength; + } + for (int j=0; j<(*reconstruct_init)->grading->gradeData->size1;j++) + { + if (gsl_matrix_get((*reconstruct_init)->grading->gradeData,j,1) == resize_mf) + { + preBuffer_value = gsl_matrix_get((*reconstruct_init)->grading->gradeData,j,2); + resize_mfvsposti = 1; + break; + } + } + if (resize_mfvsposti == 0) + { + message = "The grading/preBuffer info of the XML file does not match the filter length"; + EP_EXIT_ERROR(message,EPFAIL); + } + } //cout<<"foundPulses->pulses_detected[i].pulse_duration: "<pulses_detected[i].pulse_duration<pulses_detected[i].avg_4samplesDerivative = gsl_vector_get(samp1DERgsl,i); @@ -2556,6 +2618,7 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ str.clear(); EP_PRINT_ERROR(message,EPFAIL); return(EPFAIL); } + //temp = gsl_vector_subvector(recordNOTFILTERED,gsl_vector_get(tstartgsl,i),foundPulses->pulses_detected[i].pulse_duration); temp = gsl_vector_subvector(recordNOTFILTERED,gsl_vector_get(tstartgsl,i),floor(gsl_vector_get(tendgsl,i)-gsl_vector_get(tstartgsl,i))); if (gsl_vector_memcpy(foundPulses->pulses_detected[i].pulse_adc,&temp.vector) != 0) @@ -2576,7 +2639,7 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ EP_PRINT_ERROR(message,EPFAIL); return(EPFAIL); } - if (preBuffer == 0) + if ((*reconstruct_init)->preBuffer == 0) { if (gsl_vector_get(tstartgsl,i)< 0) { @@ -2588,18 +2651,33 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ } temp = gsl_vector_subvector(recordNOTFILTERED,gsl_vector_get(tstartgsl,i),foundPulses->pulses_detected[i].pulse_duration); } - else if (preBuffer != 0) + else if ((*reconstruct_init)->preBuffer == 1) { - if (gsl_vector_get(tstartgsl,i)-preBuffer >= 0) + if ((*reconstruct_init)->opmode == 0) { - temp = gsl_vector_subvector(recordNOTFILTERED,gsl_vector_get(tstartgsl,i) - preBuffer,foundPulses->pulses_detected[i].pulse_duration); + if (gsl_vector_get(tstartgsl,i)-(*reconstruct_init)->preBuffer_max_value >= 0) + { + temp = gsl_vector_subvector(recordNOTFILTERED,gsl_vector_get(tstartgsl,i)-(*reconstruct_init)->preBuffer_max_value,foundPulses->pulses_detected[i].pulse_duration); + } + else if (gsl_vector_get(tstartgsl,i)-(*reconstruct_init)->preBuffer_max_value < 0) + { + temp = gsl_vector_subvector(recordNOTFILTERED,0,foundPulses->pulses_detected[i].pulse_duration+(*reconstruct_init)->preBuffer_max_value); + } } - else if (gsl_vector_get(tstartgsl,i)-preBuffer < 0) + else { - temp = gsl_vector_subvector(recordNOTFILTERED,0,foundPulses->pulses_detected[i].pulse_duration); + + if (gsl_vector_get(tstartgsl,i)-preBuffer_value >= 0) + { + temp = gsl_vector_subvector(recordNOTFILTERED,gsl_vector_get(tstartgsl,i) - preBuffer_value,foundPulses->pulses_detected[i].pulse_duration); + } + else if (gsl_vector_get(tstartgsl,i)-preBuffer_value < 0) + { + temp = gsl_vector_subvector(recordNOTFILTERED,0,foundPulses->pulses_detected[i].pulse_duration); + } } } - + if (gsl_vector_memcpy(foundPulses->pulses_detected[i].pulse_adc_preBuffer,&temp.vector) != 0) { sprintf(valERROR,"%d",__LINE__-2); @@ -2619,14 +2697,33 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ foundPulses->pulses_detected[i].maxDER = gsl_vector_get(maxDERgsl,i); foundPulses->pulses_detected[i].samp1DER = gsl_vector_get(samp1DERgsl,i); // 'energy' will be known after running 'runEnergy' - if ((preBuffer != 0) && (gsl_vector_get(tstartgsl,i)-preBuffer < 0)) + if (((*reconstruct_init)->preBuffer == 1) && ((*reconstruct_init)->opmode == 0)) + { + if (gsl_vector_get(tstartgsl,i)-(*reconstruct_init)->preBuffer_max_value < 0) + { + gsl_vector_set(qualitygsl,i, 1); + } + } + else if (((*reconstruct_init)->preBuffer == 1) && ((*reconstruct_init)->opmode == 1)) + { + if (gsl_vector_get(tstartgsl,i)-preBuffer_value < 0) + { + gsl_vector_set(qualitygsl,i, 1); + } + } + else if ((*reconstruct_init)->preBuffer == 0) { - gsl_vector_set(qualitygsl,i, 1); + if (gsl_vector_get(tstartgsl,i) < 0) + { + gsl_vector_set(qualitygsl,i, 1); + } } foundPulses->pulses_detected[i].quality = gsl_vector_get(qualitygsl,i); foundPulses->pulses_detected[i].numLagsUsed = gsl_vector_get(lagsgsl,i); foundPulses->pulses_detected[i].pixid = pixid; - foundPulses->pulses_detected[i].phid = phid; + foundPulses->pulses_detected[i].phid = gsl_vector_get(phid,0); + foundPulses->pulses_detected[i].phid2 = gsl_vector_get(phid,1); + foundPulses->pulses_detected[i].phid3 = gsl_vector_get(phid,2); if (gsl_vector_get(Bgsl,i) != -999.0) { foundPulses->pulses_detected[i].bsln = gsl_vector_get(Bgsl,i)/gsl_vector_get(Lbgsl,i); @@ -2640,14 +2737,13 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ //log_debug("Pulse %i tstart=%f maxDER=%f samp1DER=%f pulse_duration=%i quality=%f lags=%f",i,gsl_vector_get(tstartgsl,i),foundPulses->pulses_detected[i].maxDER,gsl_vector_get(samp1DERgsl,i),foundPulses->pulses_detected[i].pulse_duration,foundPulses->pulses_detected[i].quality,gsl_vector_get(lagsgsl,i)); //cout<<"Bgsl = "<pulses_detected[i].bsln<pulses_detected[i].pulse_duration, foundPulses->pulses_detected[i].quality); log_debug("tstart= %f", gsl_vector_get(tstartgsl,i)); log_debug("tend= %f", gsl_vector_get(tendgsl,i)); log_debug("pulse duration %d", foundPulses->pulses_detected[i].pulse_duration); log_debug("quality %f", foundPulses->pulses_detected[i].quality); } - // Write pulses info in intermediate output FITS file if ((*reconstruct_init)->intermediate == 1) { @@ -2678,7 +2774,7 @@ gsl_vector_memcpy(recordDERIVATIVE,record);*/ if (Lbgsl != NULL) {gsl_vector_free(Lbgsl); Lbgsl = 0;} if (Bgsl != NULL) {gsl_vector_free(Bgsl); Bgsl = 0;} } - + message.clear(); return EPOK; @@ -2993,7 +3089,18 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection string message = ""; char valERROR[256]; - int preBuffer = reconstruct_init-> preBuffer; + int pulseLengthCT; + int preBuffer_value; + if (reconstruct_init->preBuffer == 0) + { + preBuffer_value = 0; + pulseLengthCT = max(reconstruct_init->pulse_length,reconstruct_init->largeFilter); + } + else if (reconstruct_init->preBuffer == 1) + { + preBuffer_value = reconstruct_init->preBuffer_max_value; + pulseLengthCT = reconstruct_init->post_max_value; + } int totalPulses = pulsesAll->ndetpulses + pulsesInRecord->ndetpulses; @@ -3001,20 +3108,17 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection gsl_vector *tstart = gsl_vector_alloc(totalPulses); gsl_vector *pulseheight = gsl_vector_alloc(totalPulses); gsl_vector *quality = gsl_vector_alloc(totalPulses); - //gsl_vector *bslnpulse = = gsl_vector_alloc(totalPulses); for (int i=0;indetpulses;i++) { gsl_vector_set(tstart,i,pulsesAll->pulses_detected[i].Tstart); gsl_vector_set(pulseheight,i,pulsesAll->pulses_detected[i].pulse_height); gsl_vector_set(quality,i,pulsesAll->pulses_detected[i].quality); - //gsl_vector_set(bslnpulse,i,pulsesAll->pulses_detected[i].bsln); } for (int i=0;indetpulses;i++) { gsl_vector_set(tstart,i+pulsesAll->ndetpulses,pulsesInRecord->pulses_detected[i].Tstart); gsl_vector_set(pulseheight,i+pulsesAll->ndetpulses,pulsesInRecord->pulses_detected[i].pulse_height); gsl_vector_set(quality,i+pulsesAll->ndetpulses,pulsesInRecord->pulses_detected[i].quality); - //gsl_vector_set(bslnpulse,i+pulsesAll->ndetpulses,pulsesInRecord->pulses_detected[i].bsln); } // It is not necessary because 'pulsesAll->ndetpulses + pulsesInRecord->ndetpulses' has been checked previously @@ -3023,15 +3127,14 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection gsl_vector_set_all(nonpileup,1); int nBins; // Square-root choice (used by Excel and many others) - gsl_vector *xhisto; // X-axis of the pulseheights histogram - gsl_vector *yhisto; // Y-axis of the pulseheights histogram - int index_maximumpulseheight; // Index where the maximum of the pulseheights histogram is - double maximumpulseheight; // Maximum of the pulseheights histogram + gsl_vector *xhisto; // X-axis of the pulseheights histogram + gsl_vector *yhisto; // Y-axis of the pulseheights histogram + int index_maximumpulseheight; // Index where the maximum of the pulseheights histogram is + double maximumpulseheight; // Maximum of the pulseheights histogram bool firstnonpileupPulse = true; + // It is not necessary because 'reconstruct_init->pulse_length'='PulseLength' (input parameter) has been checked previously - //gsl_vector *pulse = gsl_vector_alloc(reconstruct_init->pulse_length); - int pulseLengthCT = max(reconstruct_init->pulse_length,reconstruct_init->largeFilter); gsl_vector *pulse = gsl_vector_alloc(pulseLengthCT); gsl_vector *pulseaverageCT = gsl_vector_alloc(pulseLengthCT); @@ -3045,19 +3148,19 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection // It is not necessary because 'totalPulses'='pulsesAll->ndetpulses + pulsesInRecord->ndetpulses' has been checked previously gsl_vector *pulseheightAUX = gsl_vector_alloc(totalPulses); int cnt = 0; - //cout<<"totalpulses: "<pulse_length; + //if (i == totalPulses-1) tstartnext = gsl_vector_get(tstart,i)+2*reconstruct_init->pulse_length; + if (i == totalPulses-1) tstartnext = gsl_vector_get(tstart,i)+2*pulseLengthCT; else tstartnext = gsl_vector_get(tstart,i+1); - if ((tstartnext-gsl_vector_get(tstart,i) > reconstruct_init->pulse_length) && ((gsl_vector_get(quality,i) == 0) || (gsl_vector_get(quality,i) == 10))) + //if ((tstartnext-gsl_vector_get(tstart,i) > reconstruct_init->pulse_length) && ((gsl_vector_get(quality,i) == 0) || (gsl_vector_get(quality,i) == 10))) + if ((tstartnext-gsl_vector_get(tstart,i) > pulseLengthCT) && ((gsl_vector_get(quality,i) == 0) || (gsl_vector_get(quality,i) == 10))) { gsl_vector_set(pulseheightAUX,cnt,gsl_vector_get(pulseheight,i)); cnt = cnt +1; } } - //cout<<"cnt: "<pulse_length; + //if (i == totalPulses-1) tstartnext = gsl_vector_get(tstart,i)+2*reconstruct_init->pulse_length; + if (i == totalPulses-1) tstartnext = gsl_vector_get(tstart,i)+2*pulseLengthCT; else tstartnext = gsl_vector_get(tstart,i+1); // Check if the pulse is piled-up or not - //if ((gsl_vector_get(pulseheight,i) < maximumpulseheight-0.1*maximumpulseheight) || (gsl_vector_get(pulseheight,i) > maximumpulseheight+0.1*maximumpulseheight) || (tstartnext-gsl_vector_get(tstart,i) <= reconstruct_init->pulse_length) || ((gsl_vector_get(quality,i) != 0) && (gsl_vector_get(quality,i) != 10))) - if ((gsl_vector_get(pulseheight,i) < maximumpulseheight-0.1*maximumpulseheight) || (gsl_vector_get(pulseheight,i) > maximumpulseheight+0.1*maximumpulseheight) || (gsl_vector_get(tstart,i)-preBuffer+pulseLengthCT >= tstartnext) || ((gsl_vector_get(quality,i) != 0) && (gsl_vector_get(quality,i) != 10))) + //if ((gsl_vector_get(pulseheight,i) < maximumpulseheight-0.1*maximumpulseheight) || (gsl_vector_get(pulseheight,i) > maximumpulseheight+0.1*maximumpulseheight) || (tstartnext-gsl_vector_get(tstart,i) <= pulseLengthCT) || ((gsl_vector_get(quality,i) != 0) && (gsl_vector_get(quality,i) != 10))) + if ((gsl_vector_get(pulseheight,i) < maximumpulseheight-0.1*maximumpulseheight) || (gsl_vector_get(pulseheight,i) > maximumpulseheight+0.1*maximumpulseheight) || (gsl_vector_get(tstart,i)-preBuffer_value+pulseLengthCT >= tstartnext) || ((gsl_vector_get(quality,i) != 0) && (gsl_vector_get(quality,i) != 10))) { gsl_vector_set(nonpileup,i,0); nonpileupPulses --; - //cout< Align and average them if (firstnonpileupPulse == true) { - //gsl_vector_memcpy(*pulseaverage,pulse); gsl_vector_memcpy(pulseaverageCT,pulse); } else @@ -3148,7 +3250,6 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection // message = "Cannot run align for pulse " + boost::lexical_cast(i) + " when 1st pulse is piled-up"; // EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); //} - //gsl_vector_add(*pulseaverage,pulse); gsl_vector_add(pulseaverageCT,pulse); } *pulseaverageHeight = *pulseaverageHeight + gsl_vector_get(pulseheight,i); @@ -3157,11 +3258,17 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection } //cout<<"Number of pulses to average: "<pulse_length); + if ((reconstruct_init)->preBuffer == 0) + { + temp = gsl_vector_subvector(pulseaverageCT,0,reconstruct_init->pulse_length); + } + else + { + temp = gsl_vector_subvector(pulseaverageCT,0,pulseLengthCT); + } gsl_vector_memcpy(*pulseaverage,&temp.vector); if (reconstruct_init->hduPRECALWN == 1) @@ -3177,6 +3284,8 @@ int calculateTemplate(ReconstructInitSIRENA *reconstruct_init, PulsesCollection } *pulseaverageHeight = *pulseaverageHeight/nonpileupPulses; + //for (int i=0;i<(*pulseaverage)->size;i++) + // cout<pulse_length'=PulseLength(input parameter) has been checked previously - gsl_matrix *pulsetemplates_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); - gsl_matrix *pulsetemplatesMaxLengthFixedFilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->largeFilter); - gsl_matrix *pulsetemplatesb0_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); - gsl_matrix *matchedfilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); - gsl_matrix *matchedfiltersb0_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); + //gsl_matrix *pulsetemplates_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); + //gsl_matrix *pulsetemplatesMaxLengthFixedFilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->largeFilter); + gsl_matrix *pulsetemplates_matrix; + gsl_matrix *pulsetemplatesMaxLengthFixedFilters_matrix; + gsl_matrix *pulsetemplatesb0_matrix; + gsl_matrix *matchedfilters_matrix; + gsl_matrix *matchedfiltersb0_matrix; + if ((*reconstruct_init)->preBuffer == 1) + { + pulsetemplates_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->post_max_value); + pulsetemplatesMaxLengthFixedFilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->post_max_value); + pulsetemplatesb0_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->post_max_value); + matchedfilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->post_max_value); + matchedfiltersb0_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->post_max_value); + } + else + { + pulsetemplates_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); + pulsetemplatesMaxLengthFixedFilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->largeFilter); + pulsetemplatesb0_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); + matchedfilters_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); + matchedfiltersb0_matrix = gsl_matrix_alloc(1,(*reconstruct_init)->pulse_length); + } strcpy(keyname,"CREADATE"); time_t rawtime; @@ -4348,7 +4475,6 @@ int writeLibrary(ReconstructInitSIRENA **reconstruct_init, double samprate, doub message = "Cannot run addFirstRow in writeLibrary"; EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } - // Free allocated GSL vectors and matrices gsl_vector_free(energyoutgsl); energyoutgsl = 0; gsl_vector_free(estenergyoutgsl); estenergyoutgsl = 0; @@ -4429,7 +4555,7 @@ int addFirstRow(ReconstructInitSIRENA *reconstruct_init, fitsfile **inLibObject, string message = ""; char valERROR[256]; - int preBuffer = reconstruct_init-> preBuffer; + //int preBuffer = reconstruct_init-> preBuffer; gsl_vector *optimalfilter = NULL; gsl_vector *optimalfilter_f = NULL; @@ -4550,15 +4676,21 @@ int addFirstRow(ReconstructInitSIRENA *reconstruct_init, fitsfile **inLibObject, } // It is not necessary to check the allocation because 'reconstruct_init->pulse_length'=PulseLength(input parameter) has been checked previously - gsl_vector *matchedfilters_row = gsl_vector_alloc(reconstruct_init->pulse_length); + gsl_vector *matchedfilters_row; + if (reconstruct_init->preBuffer == 0) + { + matchedfilters_row = gsl_vector_alloc(reconstruct_init->pulse_length); + } + else + { + matchedfilters_row = gsl_vector_alloc(reconstruct_init->post_max_value); + } if (runF0orB0val == 0) gsl_matrix_get_row(matchedfilters_row,MF,0); else if (runF0orB0val == 1) gsl_matrix_get_row(matchedfilters_row,MFB0,0); - //for (int i=0;isize;i++) cout<opmode, matchedfilters_row, matchedfilters_row->size, samprate, runF0orB0val, reconstruct_init->noise_spectrum->noisefreqs, reconstruct_init->noise_spectrum->noisespec, &optimalfilter, &optimalfilter_f, &optimalfilter_FFT, &optimalfilter_FFT_complex)) { @@ -4651,26 +4783,99 @@ int addFirstRow(ReconstructInitSIRENA *reconstruct_init, fitsfile **inLibObject, gsl_vector_view(temp); gsl_matrix *optimalfiltersT_matrix; gsl_matrix *optimalfiltersF_matrix; - for (int j=0;jsize;j++) + if (reconstruct_init->preBuffer == 0) { - if (gsl_vector_get(fixedlengths,j) == optimalfilter_FFT_complex->size) + for (int j=0;jsize;j++) { - if ((optimalfilter_x = gsl_vector_alloc(optimalfilter_FFT_complex->size)) == 0) + if (gsl_vector_get(fixedlengths,j) == optimalfilter_FFT_complex->size) { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; - EP_PRINT_ERROR(message,EPFAIL); + if ((optimalfilter_x = gsl_vector_alloc(optimalfilter_FFT_complex->size)) == 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_vector_memcpy(optimalfilter_x,optimalfilter); + + optimalfilter_FFT_complex_x = gsl_vector_complex_alloc(optimalfilter_FFT_complex->size); + gsl_vector_complex_memcpy(optimalfilter_FFT_complex_x,optimalfilter_FFT_complex); + } + else + { + // It will enter this 'else' for fixedlengths_i=largeFilter and fixedlengths_isize + if ((matchedfiltersSHORT = gsl_vector_alloc(gsl_vector_get(fixedlengths,j))) == 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + if (gsl_vector_get(fixedlengths,j) == reconstruct_init->largeFilter) + { + //gsl_vector *matchedfiltersMaxLengthFixedFilter_row = gsl_vector_alloc(reconstruct_init->largeFilter); + gsl_vector *matchedfiltersMaxLengthFixedFilter_row = gsl_vector_alloc(PULSEMaxLengthFixedFilter->size2); + gsl_matrix_get_row(matchedfiltersMaxLengthFixedFilter_row,PULSEMaxLengthFixedFilter,0); //Matched filter + gsl_vector_scale(matchedfiltersMaxLengthFixedFilter_row,1.0/reconstruct_init->monoenergy); + if ((gsl_vector_get(fixedlengths,j) < 0) || (gsl_vector_get(fixedlengths,j) > matchedfiltersMaxLengthFixedFilter_row->size)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "View goes out of scope the original vector in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); + } + temp = gsl_vector_subvector(matchedfiltersMaxLengthFixedFilter_row,0,gsl_vector_get(fixedlengths,j)); + if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); + } + cout<<"matchedfiltersSHORT->size: "<size<size: "<size< matchedfilters_row->size)) + if ((gsl_vector_get(fixedlengths,j) < 0) || (gsl_vector_get(fixedlengths,j) > matchedfilters_row->size)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "View goes out of scope the original vector in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); + } + temp = gsl_vector_subvector(matchedfilters_row,0,gsl_vector_get(fixedlengths,j)); + if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); + } + gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector); + } + + // Calculate the optimal filter + if (calculus_optimalFilter (0, 0, reconstruct_init->opmode, matchedfiltersSHORT, matchedfiltersSHORT->size, samprate, runF0orB0val, reconstruct_init->noise_spectrum->noisefreqs, reconstruct_init->noise_spectrum->noisespec, &optimalfilter_x, &optimalfilter_f_x, &optimalfilter_FFT_x, &optimalfilter_FFT_complex_x)) + { + message = "Cannot run routine calculus_optimalFilter in writeLibrary"; + EP_PRINT_ERROR(message,EPFAIL); return(EPFAIL); + } + + gsl_vector_free(matchedfiltersSHORT); matchedfiltersSHORT = 0; + gsl_vector_free(optimalfilter_f_x); optimalfilter_f_x = 0; + gsl_vector_free(optimalfilter_FFT_x); optimalfilter_FFT_x = 0; } - gsl_vector_memcpy(optimalfilter_x,optimalfilter); - optimalfilter_FFT_complex_x = gsl_vector_complex_alloc(optimalfilter_FFT_complex->size); - gsl_vector_complex_memcpy(optimalfilter_FFT_complex_x,optimalfilter_FFT_complex); - } - else - { - // It will enter this 'else' for fixedlengths_i=largeFilter and fixedlengths_isize - if ((matchedfiltersSHORT = gsl_vector_alloc(gsl_vector_get(fixedlengths,j))) == 0) + if ((optimalfilter_FFT_RI = gsl_vector_alloc(optimalfilter_FFT_complex_x->size*2)) == 0) { sprintf(valERROR,"%d",__LINE__-2); string str(valERROR); @@ -4678,54 +4883,73 @@ int addFirstRow(ReconstructInitSIRENA *reconstruct_init, fitsfile **inLibObject, str.clear(); EP_PRINT_ERROR(message,EPFAIL); } - if (gsl_vector_get(fixedlengths,j) == reconstruct_init->largeFilter) + for (int i=0;isize;i++) { - gsl_vector *matchedfiltersMaxLengthFixedFilter_row = gsl_vector_alloc(reconstruct_init->largeFilter); - gsl_matrix_get_row(matchedfiltersMaxLengthFixedFilter_row,PULSEMaxLengthFixedFilter,0); //Matched filter - gsl_vector_scale(matchedfiltersMaxLengthFixedFilter_row,1.0/reconstruct_init->monoenergy); - if ((gsl_vector_get(fixedlengths,j) < 0) || (gsl_vector_get(fixedlengths,j) > matchedfiltersMaxLengthFixedFilter_row->size)) + gsl_vector_set(optimalfilter_FFT_RI,i,GSL_REAL(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); + if ((i+optimalfilter_FFT_complex_x->size < 0) || (i+optimalfilter_FFT_complex_x->size > optimalfilter_FFT_RI->size-1)) { sprintf(valERROR,"%d",__LINE__+5); string str(valERROR); - message = "View goes out of scope the original vector in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_EXIT_ERROR(message,EPFAIL); - } - temp = gsl_vector_subvector(matchedfiltersMaxLengthFixedFilter_row,0,gsl_vector_get(fixedlengths,j)); - if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) - { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; str.clear(); - EP_EXIT_ERROR(message,EPFAIL); + EP_PRINT_ERROR(message,EPFAIL); } - gsl_vector_free(matchedfiltersMaxLengthFixedFilter_row); matchedfiltersMaxLengthFixedFilter_row = 0; + gsl_vector_set(optimalfilter_FFT_RI,i+optimalfilter_FFT_complex_x->size,GSL_IMAG(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); } - else + gsl_vector_complex_free(optimalfilter_FFT_complex_x); optimalfilter_FFT_complex_x = 0; + + strcpy(extname,"FIXFILTF"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) { - //cout<<"matchedfilters_row->size: "<size< matchedfilters_row->size)) - if ((gsl_vector_get(fixedlengths,j) < 0) || (gsl_vector_get(fixedlengths,j) > matchedfilters_row->size)) - { - sprintf(valERROR,"%d",__LINE__+5); - string str(valERROR); - message = "View goes out of scope the original vector in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_EXIT_ERROR(message,EPFAIL); - } - temp = gsl_vector_subvector(matchedfilters_row,0,gsl_vector_get(fixedlengths,j)); - if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) - { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_EXIT_ERROR(message,EPFAIL); - } - gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector); + message = "Cannot move to HDU " + string(extname) + " in library"; + EP_PRINT_ERROR(message,status);return(EPFAIL); + } + snprintf(str_length,125,"%ld",optimalfilter_FFT_RI->size/2); + strcpy(objFREQ.nameCol,(string("F")+string(str_length)).c_str()); + strcpy(objFREQ.unit," "); + optimalfiltersF_matrix = gsl_matrix_alloc(1,optimalfilter_FFT_RI->size); + gsl_matrix_set_row(optimalfiltersF_matrix,0,optimalfilter_FFT_RI); + if (writeFitsComplex(objFREQ,optimalfiltersF_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_vector_free(optimalfilter_FFT_RI); optimalfilter_FFT_RI = 0; + + strcpy(extname,"FIXFILTT"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + message = "Cannot move to HDU " + string(extname) + " in library"; + EP_PRINT_ERROR(message,status);return(EPFAIL); + } + strcpy(objTIME.nameCol,(string("T")+string(str_length)).c_str()); + optimalfiltersT_matrix = gsl_matrix_alloc(1,optimalfilter_x->size); + gsl_matrix_set_row(optimalfiltersT_matrix,0,optimalfilter_x); + if (writeFitsComplex(objTIME,optimalfiltersT_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_vector_free(optimalfilter_x); optimalfilter_x = 0; + + gsl_matrix_free(optimalfiltersT_matrix); optimalfiltersT_matrix = 0; + gsl_matrix_free(optimalfiltersF_matrix); optimalfiltersF_matrix = 0; + } + } + else // preBuffer + { + for (int j=0;jgrading->gradeData->size1;j++) + { + temp = gsl_vector_subvector(matchedfilters_row,reconstruct_init->preBuffer_max_value-gsl_matrix_get(reconstruct_init->grading->gradeData,j,2),gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + + if ((matchedfiltersSHORT = gsl_vector_alloc(gsl_matrix_get(reconstruct_init->grading->gradeData,j,1))) == 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; + EP_PRINT_ERROR(message,EPFAIL); } + gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector); // Calculate the optimal filter if (calculus_optimalFilter (0, 0, reconstruct_init->opmode, matchedfiltersSHORT, matchedfiltersSHORT->size, samprate, runF0orB0val, reconstruct_init->noise_spectrum->noisefreqs, reconstruct_init->noise_spectrum->noisespec, &optimalfilter_x, &optimalfilter_f_x, &optimalfilter_FFT_x, &optimalfilter_FFT_complex_x)) @@ -4734,70 +4958,66 @@ int addFirstRow(ReconstructInitSIRENA *reconstruct_init, fitsfile **inLibObject, EP_PRINT_ERROR(message,EPFAIL); return(EPFAIL); } - gsl_vector_free(matchedfiltersSHORT); matchedfiltersSHORT = 0; - gsl_vector_free(optimalfilter_f_x); optimalfilter_f_x = 0; - gsl_vector_free(optimalfilter_FFT_x); optimalfilter_FFT_x = 0; - } - - if ((optimalfilter_FFT_RI = gsl_vector_alloc(optimalfilter_FFT_complex_x->size*2)) == 0) - { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_PRINT_ERROR(message,EPFAIL); - } - for (int i=0;isize;i++) - { - gsl_vector_set(optimalfilter_FFT_RI,i,GSL_REAL(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); - if ((i+optimalfilter_FFT_complex_x->size < 0) || (i+optimalfilter_FFT_complex_x->size > optimalfilter_FFT_RI->size-1)) + if ((optimalfilter_FFT_RI = gsl_vector_alloc(optimalfilter_FFT_complex_x->size*2)) == 0) { - sprintf(valERROR,"%d",__LINE__+5); + sprintf(valERROR,"%d",__LINE__-2); string str(valERROR); - message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; str.clear(); EP_PRINT_ERROR(message,EPFAIL); } - gsl_vector_set(optimalfilter_FFT_RI,i+optimalfilter_FFT_complex_x->size,GSL_IMAG(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); - } - gsl_vector_complex_free(optimalfilter_FFT_complex_x); optimalfilter_FFT_complex_x = 0; - - strcpy(extname,"FIXFILTF"); - if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) - { - message = "Cannot move to HDU " + string(extname) + " in library"; - EP_PRINT_ERROR(message,status);return(EPFAIL); - } - snprintf(str_length,125,"%ld",optimalfilter_FFT_RI->size/2); - strcpy(objFREQ.nameCol,(string("F")+string(str_length)).c_str()); - strcpy(objFREQ.unit," "); - optimalfiltersF_matrix = gsl_matrix_alloc(1,optimalfilter_FFT_RI->size); - gsl_matrix_set_row(optimalfiltersF_matrix,0,optimalfilter_FFT_RI); - if (writeFitsComplex(objFREQ,optimalfiltersF_matrix)) - { - message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); - EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); - } - gsl_vector_free(optimalfilter_FFT_RI); optimalfilter_FFT_RI = 0; - - strcpy(extname,"FIXFILTT"); - if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) - { - message = "Cannot move to HDU " + string(extname) + " in library"; - EP_PRINT_ERROR(message,status);return(EPFAIL); - } - strcpy(objTIME.nameCol,(string("T")+string(str_length)).c_str()); - optimalfiltersT_matrix = gsl_matrix_alloc(1,optimalfilter_x->size); - gsl_matrix_set_row(optimalfiltersT_matrix,0,optimalfilter_x); - if (writeFitsComplex(objTIME,optimalfiltersT_matrix)) - { - message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); - EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + for (int i=0;isize;i++) + { + gsl_vector_set(optimalfilter_FFT_RI,i,GSL_REAL(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); + if ((i+optimalfilter_FFT_complex_x->size < 0) || (i+optimalfilter_FFT_complex_x->size > optimalfilter_FFT_RI->size-1)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_vector_set(optimalfilter_FFT_RI,i+optimalfilter_FFT_complex_x->size,GSL_IMAG(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); + } + gsl_vector_complex_free(optimalfilter_FFT_complex_x); optimalfilter_FFT_complex_x = 0; + + strcpy(extname,"FIXFILTF"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + message = "Cannot move to HDU " + string(extname) + " in library"; + EP_PRINT_ERROR(message,status);return(EPFAIL); + } + snprintf(str_length,125,"%ld",optimalfilter_FFT_RI->size/2); + strcpy(objFREQ.nameCol,(string("F")+string(str_length)).c_str()); + strcpy(objFREQ.unit," "); + optimalfiltersF_matrix = gsl_matrix_alloc(1,optimalfilter_FFT_RI->size); + gsl_matrix_set_row(optimalfiltersF_matrix,0,optimalfilter_FFT_RI); + if (writeFitsComplex(objFREQ,optimalfiltersF_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_vector_free(optimalfilter_FFT_RI); optimalfilter_FFT_RI = 0; + + strcpy(extname,"FIXFILTT"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + message = "Cannot move to HDU " + string(extname) + " in library"; + EP_PRINT_ERROR(message,status);return(EPFAIL); + } + strcpy(objTIME.nameCol,(string("T")+string(str_length)).c_str()); + optimalfiltersT_matrix = gsl_matrix_alloc(1,optimalfilter_x->size); + gsl_matrix_set_row(optimalfiltersT_matrix,0,optimalfilter_x); + if (writeFitsComplex(objTIME,optimalfiltersT_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_vector_free(optimalfilter_x); optimalfilter_x = 0; + + gsl_matrix_free(optimalfiltersT_matrix); optimalfiltersT_matrix = 0; + gsl_matrix_free(optimalfiltersF_matrix); optimalfiltersF_matrix = 0; } - gsl_vector_free(optimalfilter_x); optimalfilter_x = 0; - - gsl_matrix_free(optimalfiltersT_matrix); optimalfiltersT_matrix = 0; - gsl_matrix_free(optimalfiltersF_matrix); optimalfiltersF_matrix = 0; } gsl_vector_complex_free(optimalfilter_FFT_complex); optimalfilter_FFT_complex = 0; @@ -5094,13 +5314,44 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb gsl_vector *energycolumn = gsl_vector_alloc(eventcntLib+1); gsl_vector *energycolumnORIGINAL = gsl_vector_alloc(eventcntLib); gsl_vector *estenergycolumn = gsl_vector_alloc(eventcntLib+1); - gsl_matrix *modelsMaxLengthFixedFilteraux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->largeFilter); - gsl_matrix *modelsaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_matrix *modelsb0aux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_matrix *matchedfiltersaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_matrix *matchedfiltersb0aux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_matrix *weightaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); - gsl_matrix *covarianceaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + + gsl_matrix *modelsMaxLengthFixedFilteraux; + gsl_matrix *modelsaux; + gsl_matrix *modelsb0aux; + gsl_matrix *matchedfiltersaux; + gsl_matrix *matchedfiltersb0aux; + gsl_matrix *weightaux; + gsl_matrix *covarianceaux; + gsl_matrix *Pabaux; + gsl_matrix *PabMaxLengthFixedFilteraux; + gsl_matrix *Dabaux; + + if (reconstruct_init-> preBuffer ==0) + { + modelsMaxLengthFixedFilteraux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->largeFilter); + modelsaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + modelsb0aux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + matchedfiltersaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + matchedfiltersb0aux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + weightaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + covarianceaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + Pabaux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->pulse_length); + PabMaxLengthFixedFilteraux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->largeFilter); + Dabaux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->pulse_length); + } + else + { + modelsMaxLengthFixedFilteraux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + modelsaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + modelsb0aux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + matchedfiltersaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + matchedfiltersb0aux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + weightaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + covarianceaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + Pabaux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->post_max_value); + PabMaxLengthFixedFilteraux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->post_max_value); + Dabaux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->post_max_value); + } gsl_matrix *Wabaux = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); gsl_matrix_set_zero(Wabaux); @@ -5116,11 +5367,9 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb gsl_matrix_set_zero(ZVaux); gsl_vector *rEaux = gsl_vector_alloc(eventcntLib+1); gsl_vector_set_zero(rEaux); - gsl_matrix *Pabaux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->pulse_length); + gsl_matrix_set_zero(Pabaux); - gsl_matrix *PabMaxLengthFixedFilteraux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->largeFilter); gsl_matrix_set_zero(PabMaxLengthFixedFilteraux); - gsl_matrix *Dabaux = gsl_matrix_alloc(eventcntLib+1, reconstruct_init->pulse_length); gsl_matrix_set_zero(Dabaux); gsl_matrix *optimalfiltersFREQaux; @@ -5144,16 +5393,29 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb int lengthALL_F = 0; int lengthALL_T = 0; - for (int i=0;ipulse_length));i++) + if (reconstruct_init->preBuffer == 0) { - lengthALL_F = lengthALL_F + pow(2,floor(log2(reconstruct_init->pulse_length))-i)*2; - lengthALL_T = lengthALL_T + pow(2,floor(log2(reconstruct_init->pulse_length))-i); + for (int i=0;ipulse_length));i++) + { + lengthALL_F = lengthALL_F + pow(2,floor(log2(reconstruct_init->pulse_length))-i)*2; + lengthALL_T = lengthALL_T + pow(2,floor(log2(reconstruct_init->pulse_length))-i); + } + if (reconstruct_init->largeFilter != reconstruct_init->pulse_length) + { + lengthALL_F = lengthALL_F + reconstruct_init->largeFilter*2; + lengthALL_T = lengthALL_T + reconstruct_init->largeFilter; + } } - if (reconstruct_init->largeFilter != reconstruct_init->pulse_length) + else if (reconstruct_init->preBuffer == 1) { - lengthALL_F = lengthALL_F + reconstruct_init->largeFilter*2; - lengthALL_T = lengthALL_T + reconstruct_init->largeFilter; + for (int i=0;igrading->gradeData->size1;i++) + { + lengthALL_T = lengthALL_T + gsl_matrix_get(reconstruct_init->grading->gradeData,i,1); + } + + lengthALL_F = lengthALL_T*2; } + gsl_matrix *optimalfiltersabFREQaux; if ((optimalfiltersabFREQaux = gsl_matrix_alloc(eventcntLib+1,lengthALL_F)) == 0) { @@ -5175,7 +5437,7 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb int lengthALL_PRCLWN; if (reconstruct_init->largeFilter != reconstruct_init->pulse_length) lengthALL_PRCLWN = lengthALL_F-reconstruct_init->largeFilter*2; - else lengthALL_PRCLWN = lengthALL_F; + else lengthALL_PRCLWN = lengthALL_F; gsl_matrix *PRCLWNaux; if ((PRCLWNaux = gsl_matrix_alloc(eventcntLib+1,lengthALL_PRCLWN)) == 0) { @@ -5283,7 +5545,15 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb } gsl_matrix_set_row(modelsaux,eventcntLib,pulsetemplate); - vectoraux1 = gsl_vector_alloc(reconstruct_init->pulse_length); + if (reconstruct_init->preBuffer == 0) + { + vectoraux1 = gsl_vector_alloc(reconstruct_init->pulse_length); + } + else + { + vectoraux1 = gsl_vector_alloc(reconstruct_init->post_max_value); + } + gsl_vector_memcpy(vectoraux1,pulsetemplate); gsl_vector *baselinegslaux = gsl_vector_alloc(pulsetemplate->size); @@ -5336,59 +5606,142 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb int indexT = 0; int indexF = 0; - for (int j=0;jsize;j++) + if (reconstruct_init->preBuffer == 0) { - if (gsl_vector_get(fixedlengths,j) == optimalfilter_FFT_complex->size) + for (int j=0;jsize;j++) { - if ((optimalfilter_x = gsl_vector_alloc(optimalfilter->size)) == 0) + if (gsl_vector_get(fixedlengths,j) == optimalfilter_FFT_complex->size) { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_PRINT_ERROR(message,EPFAIL); + if ((optimalfilter_x = gsl_vector_alloc(optimalfilter->size)) == 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_vector_memcpy(optimalfilter_x,optimalfilter); + + optimalfilter_FFT_complex_x = gsl_vector_complex_alloc(optimalfilter_FFT_complex->size); + gsl_vector_complex_memcpy(optimalfilter_FFT_complex_x,optimalfilter_FFT_complex); + + gsl_vector_free(optimalfilter_f); optimalfilter_f = 0; + gsl_vector_free(optimalfilter_FFT); optimalfilter_FFT = 0; + } + else + { + if ((matchedfiltersSHORT = gsl_vector_alloc(gsl_vector_get(fixedlengths,j))) == 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + if (gsl_vector_get(fixedlengths,j) == reconstruct_init->largeFilter) + { + gsl_vector_scale(pulsetemplateMaxLengthFixedFilter,1/reconstruct_init->monoenergy); + if (gsl_vector_memcpy(matchedfiltersSHORT,pulsetemplateMaxLengthFixedFilter) != 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); + } + } + else + { + temp = gsl_vector_subvector(vectoraux1,0,gsl_vector_get(fixedlengths,j)); + if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); + } + } + + // Calculate the optimal filter + if (calculus_optimalFilter (0, 0, reconstruct_init->opmode, matchedfiltersSHORT, matchedfiltersSHORT->size, samprate, runF0orB0val, reconstruct_init->noise_spectrum->noisefreqs, reconstruct_init->noise_spectrum->noisespec, &optimalfilter_x, &optimalfilter_f_x, &optimalfilter_FFT_x, &optimalfilter_FFT_complex_x)) + { + message = "Cannot run routine calculus_optimalFilter in writeLibrary"; + EP_PRINT_ERROR(message,EPFAIL); return(EPFAIL); + } + gsl_vector_free(matchedfiltersSHORT); matchedfiltersSHORT = 0; + gsl_vector_free(optimalfilter_f_x); optimalfilter_f_x = 0; + gsl_vector_free(optimalfilter_FFT_x); optimalfilter_FFT_x = 0; } - gsl_vector_memcpy(optimalfilter_x,optimalfilter); - - optimalfilter_FFT_complex_x = gsl_vector_complex_alloc(optimalfilter_FFT_complex->size); - gsl_vector_complex_memcpy(optimalfilter_FFT_complex_x,optimalfilter_FFT_complex); - gsl_vector_free(optimalfilter_f); optimalfilter_f = 0; - gsl_vector_free(optimalfilter_FFT); optimalfilter_FFT = 0; - } - else - { - if ((matchedfiltersSHORT = gsl_vector_alloc(gsl_vector_get(fixedlengths,j))) == 0) + optimalfilter_FFT_RI = gsl_vector_alloc(optimalfilter_FFT_complex_x->size*2); + for (int i=0;isize;i++) { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_PRINT_ERROR(message,EPFAIL); + gsl_vector_set(optimalfilter_FFT_RI,i,GSL_REAL(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); + if ((i+optimalfilter_FFT_complex_x->size < 0) || (i+optimalfilter_FFT_complex_x->size > optimalfilter_FFT_RI->size-1)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_vector_set(optimalfilter_FFT_RI,i+optimalfilter_FFT_complex_x->size,GSL_IMAG(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); } - if (gsl_vector_get(fixedlengths,j) == reconstruct_init->largeFilter) + gsl_vector_complex_free(optimalfilter_FFT_complex_x); optimalfilter_FFT_complex_x = 0; + + for (int i=0;isize;i++) { - gsl_vector_scale(pulsetemplateMaxLengthFixedFilter,1/reconstruct_init->monoenergy); - if (gsl_vector_memcpy(matchedfiltersSHORT,pulsetemplateMaxLengthFixedFilter) != 0) + if ((i+indexF < 0) || (i+indexF > optimalfiltersFREQaux->size2-1)) { - sprintf(valERROR,"%d",__LINE__-2); + sprintf(valERROR,"%d",__LINE__+5); string str(valERROR); - message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; str.clear(); - EP_EXIT_ERROR(message,EPFAIL); - } + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_matrix_set(optimalfiltersFREQaux,eventcntLib,i+indexF,gsl_vector_get(optimalfilter_FFT_RI,i)); } - else + indexF = indexF + optimalfilter_FFT_RI->size; + + for (int i=0;isize;i++) { - temp = gsl_vector_subvector(vectoraux1,0,gsl_vector_get(fixedlengths,j)); - if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) + if ((i+indexT < 0) || (i+indexT > optimalfiltersTIMEaux->size2-1)) { - sprintf(valERROR,"%d",__LINE__-2); + sprintf(valERROR,"%d",__LINE__+5); string str(valERROR); - message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; str.clear(); - EP_EXIT_ERROR(message,EPFAIL); + EP_PRINT_ERROR(message,EPFAIL); } + gsl_matrix_set(optimalfiltersTIMEaux,eventcntLib,i+indexT,gsl_vector_get(optimalfilter_x,i)); + } + indexT = indexT + optimalfilter_x->size; + + gsl_vector_free(optimalfilter_x); optimalfilter_x = 0; + gsl_vector_free(optimalfilter_FFT_RI); optimalfilter_FFT_RI = 0; + } + } + else + { + for (int j=0;jgrading->gradeData->size1;j++) + { + if ((matchedfiltersSHORT = gsl_vector_alloc(gsl_matrix_get(reconstruct_init->grading->gradeData,j,1))) == 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Allocating with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + temp = gsl_vector_subvector(vectoraux1,0,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + if (gsl_vector_memcpy(matchedfiltersSHORT,&temp.vector) != 0) + { + sprintf(valERROR,"%d",__LINE__-2); + string str(valERROR); + message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_EXIT_ERROR(message,EPFAIL); } // Calculate the optimal filter @@ -5400,54 +5753,54 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb gsl_vector_free(matchedfiltersSHORT); matchedfiltersSHORT = 0; gsl_vector_free(optimalfilter_f_x); optimalfilter_f_x = 0; gsl_vector_free(optimalfilter_FFT_x); optimalfilter_FFT_x = 0; - } - - optimalfilter_FFT_RI = gsl_vector_alloc(optimalfilter_FFT_complex_x->size*2); - for (int i=0;isize;i++) - { - gsl_vector_set(optimalfilter_FFT_RI,i,GSL_REAL(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); - if ((i+optimalfilter_FFT_complex_x->size < 0) || (i+optimalfilter_FFT_complex_x->size > optimalfilter_FFT_RI->size-1)) + + optimalfilter_FFT_RI = gsl_vector_alloc(optimalfilter_FFT_complex_x->size*2); + for (int i=0;isize;i++) { - sprintf(valERROR,"%d",__LINE__+5); - string str(valERROR); - message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_PRINT_ERROR(message,EPFAIL); + gsl_vector_set(optimalfilter_FFT_RI,i,GSL_REAL(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); + if ((i+optimalfilter_FFT_complex_x->size < 0) || (i+optimalfilter_FFT_complex_x->size > optimalfilter_FFT_RI->size-1)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_vector_set(optimalfilter_FFT_RI,i+optimalfilter_FFT_complex_x->size,GSL_IMAG(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); } - gsl_vector_set(optimalfilter_FFT_RI,i+optimalfilter_FFT_complex_x->size,GSL_IMAG(gsl_vector_complex_get(optimalfilter_FFT_complex_x,i))); - } - gsl_vector_complex_free(optimalfilter_FFT_complex_x); optimalfilter_FFT_complex_x = 0; - - for (int i=0;isize;i++) - { - if ((i+indexF < 0) || (i+indexF > optimalfiltersFREQaux->size2-1)) + gsl_vector_complex_free(optimalfilter_FFT_complex_x); optimalfilter_FFT_complex_x = 0; + + for (int i=0;isize;i++) { - sprintf(valERROR,"%d",__LINE__+5); - string str(valERROR); - message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_PRINT_ERROR(message,EPFAIL); + if ((i+indexF < 0) || (i+indexF > optimalfiltersFREQaux->size2-1)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_matrix_set(optimalfiltersFREQaux,eventcntLib,i+indexF,gsl_vector_get(optimalfilter_FFT_RI,i)); } - gsl_matrix_set(optimalfiltersFREQaux,eventcntLib,i+indexF,gsl_vector_get(optimalfilter_FFT_RI,i)); - } - indexF = indexF + optimalfilter_FFT_RI->size; - - for (int i=0;isize;i++) - { - if ((i+indexT < 0) || (i+indexT > optimalfiltersTIMEaux->size2-1)) + indexF = indexF + optimalfilter_FFT_RI->size; + + for (int i=0;isize;i++) { - sprintf(valERROR,"%d",__LINE__+5); - string str(valERROR); - message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_PRINT_ERROR(message,EPFAIL); + if ((i+indexT < 0) || (i+indexT > optimalfiltersTIMEaux->size2-1)) + { + sprintf(valERROR,"%d",__LINE__+5); + string str(valERROR); + message = "Setting with <= 0 size in line " + str + " (" + __FILE__ + ")"; + str.clear(); + EP_PRINT_ERROR(message,EPFAIL); + } + gsl_matrix_set(optimalfiltersTIMEaux,eventcntLib,i+indexT,gsl_vector_get(optimalfilter_x,i)); } - gsl_matrix_set(optimalfiltersTIMEaux,eventcntLib,i+indexT,gsl_vector_get(optimalfilter_x,i)); + indexT = indexT + optimalfilter_x->size; + + gsl_vector_free(optimalfilter_x); optimalfilter_x = 0; + gsl_vector_free(optimalfilter_FFT_RI); optimalfilter_FFT_RI = 0; } - indexT = indexT + optimalfilter_x->size; - - gsl_vector_free(optimalfilter_x); optimalfilter_x = 0; - gsl_vector_free(optimalfilter_FFT_RI); optimalfilter_FFT_RI = 0; } gsl_vector_complex_free(optimalfilter_FFT_complex); optimalfilter_FFT_complex = 0; @@ -5607,24 +5960,81 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb gsl_matrix_free(aux); aux = 0; gsl_matrix_free(inv); inv = 0; } - + // Realign // It is not necessary to check the allocation because 'eventcntLib' is already >= 1 and 'reconstruct_init->pulse_length'=PulseLength(input parameter) // and 'reconstruct_init->library_collection->optimal_filters->ofilter_duration' have been checked previously gsl_vector *energycolumnaux = gsl_vector_alloc(eventcntLib+1); gsl_vector *estenergycolumnaux = gsl_vector_alloc(eventcntLib+1); - gsl_vector *modelsMaxLengthFixedFilterrow = gsl_vector_alloc(reconstruct_init->largeFilter); - gsl_matrix *modelsMaxLengthFixedFilteraux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->largeFilter); - gsl_vector *modelsrow = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_matrix *modelsaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_vector *modelsrowb0 = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_matrix *modelsb0aux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_vector *matchedfiltersrow = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_matrix *matchedfiltersaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_vector *matchedfiltersrowb0 = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_matrix *matchedfiltersb0aux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); - gsl_matrix *weightaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); - gsl_matrix *covarianceaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + + gsl_vector *modelsMaxLengthFixedFilterrow ; + gsl_matrix *modelsMaxLengthFixedFilteraux1; + gsl_vector *modelsrow; + gsl_matrix *modelsaux1; + gsl_vector *modelsrowb0; + gsl_matrix *modelsb0aux1; + gsl_vector *matchedfiltersrow; + gsl_matrix *matchedfiltersaux1; + gsl_vector *matchedfiltersrowb0; + gsl_matrix *matchedfiltersb0aux1; + + gsl_matrix *weightaux1; + gsl_matrix *covarianceaux1; + + gsl_matrix *Pabaux1; + gsl_vector *PabMaxLengthFixedFilterrow; + gsl_matrix *PabMaxLengthFixedFilteraux1; + gsl_vector *Pabrow; + gsl_vector *Dabrow; + gsl_matrix *Dabaux1; + + if (reconstruct_init->preBuffer == 0) + { + modelsMaxLengthFixedFilterrow = gsl_vector_alloc(reconstruct_init->largeFilter); + modelsMaxLengthFixedFilteraux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->largeFilter); + modelsrow = gsl_vector_alloc(reconstruct_init->pulse_length); + modelsaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + modelsrowb0 = gsl_vector_alloc(reconstruct_init->pulse_length); + modelsb0aux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + matchedfiltersrow = gsl_vector_alloc(reconstruct_init->pulse_length); + matchedfiltersaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + matchedfiltersrowb0 = gsl_vector_alloc(reconstruct_init->pulse_length); + matchedfiltersb0aux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + + weightaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + covarianceaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + + Pabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + PabMaxLengthFixedFilterrow = gsl_vector_alloc(reconstruct_init->largeFilter); + PabMaxLengthFixedFilteraux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->largeFilter); + Pabrow = gsl_vector_alloc(reconstruct_init->pulse_length); + Dabrow = gsl_vector_alloc(reconstruct_init->pulse_length); + Dabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); + } + else + { + modelsMaxLengthFixedFilterrow = gsl_vector_alloc(reconstruct_init->post_max_value); + modelsMaxLengthFixedFilteraux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + modelsrow = gsl_vector_alloc(reconstruct_init->post_max_value); + modelsaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + modelsrowb0 = gsl_vector_alloc(reconstruct_init->post_max_value); + modelsb0aux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + matchedfiltersrow = gsl_vector_alloc(reconstruct_init->post_max_value); + matchedfiltersaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + matchedfiltersrowb0 = gsl_vector_alloc(reconstruct_init->post_max_value); + matchedfiltersb0aux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + + weightaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + covarianceaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + + Pabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + PabMaxLengthFixedFilterrow = gsl_vector_alloc(reconstruct_init->post_max_value); + PabMaxLengthFixedFilteraux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + Pabrow = gsl_vector_alloc(reconstruct_init->post_max_value); + Dabrow = gsl_vector_alloc(reconstruct_init->post_max_value); + Dabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->post_max_value); + } + gsl_vector *Wabrow = gsl_vector_alloc(reconstruct_init->pulse_length*reconstruct_init->pulse_length); gsl_matrix *Wabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); gsl_vector *TVrow = gsl_vector_alloc(reconstruct_init->pulse_length); @@ -5644,14 +6054,8 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb gsl_vector *rEcolumn = gsl_vector_alloc(eventcntLib+1); gsl_vector *rEcolumnaux = gsl_vector_alloc(eventcntLib+1); gsl_vector_set_zero(rEcolumnaux); - gsl_vector *Pabrow = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_matrix *Pabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); gsl_matrix_set_zero(Pabaux1); - gsl_vector *PabMaxLengthFixedFilterrow = gsl_vector_alloc(reconstruct_init->largeFilter); - gsl_matrix *PabMaxLengthFixedFilteraux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->largeFilter); gsl_matrix_set_zero(PabMaxLengthFixedFilteraux1); - gsl_vector *Dabrow = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_matrix *Dabaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->pulse_length); gsl_matrix_set_zero(Dabaux1); gsl_vector *optimalfiltersFREQrow = gsl_vector_alloc(reconstruct_init->library_collection->optimal_filtersFREQ->ofilter_duration); gsl_matrix *optimalfiltersFREQaux1 = gsl_matrix_alloc(eventcntLib+1,reconstruct_init->library_collection->optimal_filtersFREQ->ofilter_duration); @@ -5878,9 +6282,21 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb // Write values // It is not necessary to check the allocation because 'reconstruct_init->pulse_length'=PulseLength(input parameter) has been checked previously - gsl_matrix *matrixaux = gsl_matrix_alloc(1,reconstruct_init->pulse_length); - gsl_matrix *matrixaux2 = gsl_matrix_alloc(1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); - gsl_matrix *matrixaux_2 = gsl_matrix_alloc(1,reconstruct_init->pulse_length*2); + gsl_matrix *matrixaux; + gsl_matrix *matrixaux2; + gsl_matrix *matrixaux_2; + if (reconstruct_init->preBuffer == 0) + { + matrixaux = gsl_matrix_alloc(1,reconstruct_init->pulse_length); + matrixaux2 = gsl_matrix_alloc(1,reconstruct_init->pulse_length*reconstruct_init->pulse_length); + matrixaux_2 = gsl_matrix_alloc(1,reconstruct_init->pulse_length*2); + } + else + { + matrixaux = gsl_matrix_alloc(1,reconstruct_init->post_max_value); + matrixaux2 = gsl_matrix_alloc(1,(reconstruct_init->post_max_value)*(reconstruct_init->post_max_value)); + matrixaux_2 = gsl_matrix_alloc(1,(reconstruct_init->post_max_value)*2); + } obj.inObject = *inLibObject; obj.nameTable = new char [255]; @@ -6219,87 +6635,118 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb strcpy(objFREQ.unit," "); strcpy(objWN.unit," "); strcpy(objOFWM.unit," "); - for (int j=0;jlibrary_collection->nfixedfilters;j++) + + if (reconstruct_init-> preBuffer == 0) { - strcpy(extname,"FIXFILTT"); - if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) - { - EP_PRINT_ERROR("Error moving to HDU FIXFILTT in library file",status); - return(EPFAIL); - } - - snprintf(str_length,125,"%d",(int) gsl_vector_get(fixedlengths,j)); - strcpy(objTIME.nameCol,(string("T")+string(str_length)).c_str()); - gsl_matrix_get_row(optimalfiltersTIMErow,optimalfiltersTIMEaux,i); - gsl_matrix *optimalfiltersTIME_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)); - temp = gsl_vector_subvector(optimalfiltersTIMErow,indexT,gsl_vector_get(fixedlengths,j)); - gsl_matrix_set_row(optimalfiltersTIME_matrix,0,&temp.vector); - if (writeFitsComplex(objTIME,optimalfiltersTIME_matrix)) - { - message = "Cannot run writeFitsComplex routine for column " + string(objTIME.nameCol); - EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); - } - gsl_matrix_free(optimalfiltersTIME_matrix); optimalfiltersTIME_matrix = 0; - - if (i < eventcntLib) + for (int j=0;jlibrary_collection->nfixedfilters;j++) { - strcpy(objTIME.nameCol,(string("ABT")+string(str_length)).c_str()); - gsl_matrix_get_row(optimalfiltersabTIMErow,optimalfiltersabTIMEaux,i); - gsl_matrix *optimalfiltersabTIME_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)); - temp = gsl_vector_subvector(optimalfiltersabTIMErow,indexT,gsl_vector_get(fixedlengths,j)); - gsl_matrix_set_row(optimalfiltersabTIME_matrix,0,&temp.vector); - if (writeFitsComplex(objTIME, optimalfiltersabTIME_matrix)) + strcpy(extname,"FIXFILTT"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + EP_PRINT_ERROR("Error moving to HDU FIXFILTT in library file",status); + return(EPFAIL); + } + + snprintf(str_length,125,"%d",(int) gsl_vector_get(fixedlengths,j)); + strcpy(objTIME.nameCol,(string("T")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersTIMErow,optimalfiltersTIMEaux,i); + gsl_matrix *optimalfiltersTIME_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)); + temp = gsl_vector_subvector(optimalfiltersTIMErow,indexT,gsl_vector_get(fixedlengths,j)); + gsl_matrix_set_row(optimalfiltersTIME_matrix,0,&temp.vector); + if (writeFitsComplex(objTIME,optimalfiltersTIME_matrix)) { message = "Cannot run writeFitsComplex routine for column " + string(objTIME.nameCol); EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } - gsl_matrix_free(optimalfiltersabTIME_matrix); optimalfiltersabTIME_matrix = 0; - } - - indexT = indexT + gsl_vector_get(fixedlengths,j); - - strcpy(extname,"FIXFILTF"); - if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) - { - EP_PRINT_ERROR("Error moving to HDU FIXFILTF in library file",status); - return(EPFAIL); - } - - strcpy(objFREQ.nameCol,(string("F")+string(str_length)).c_str()); - gsl_matrix_get_row(optimalfiltersFREQrow,optimalfiltersFREQaux,i); - gsl_matrix *optimalfiltersFREQ_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); - temp = gsl_vector_subvector(optimalfiltersFREQrow,indexF,gsl_vector_get(fixedlengths,j)*2); - gsl_matrix_set_row(optimalfiltersFREQ_matrix,0,&temp.vector); - if (writeFitsComplex(objFREQ,optimalfiltersFREQ_matrix)) - { - message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); - EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); - } - gsl_matrix_free(optimalfiltersFREQ_matrix); optimalfiltersFREQ_matrix = 0; - - if (i < eventcntLib) - { - strcpy(objFREQ.nameCol,(string("ABF")+string(str_length)).c_str()); - gsl_matrix_get_row(optimalfiltersabFREQrow,optimalfiltersabFREQaux,i); - gsl_matrix *optimalfiltersabFREQ_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); - temp = gsl_vector_subvector(optimalfiltersabFREQrow,indexF,gsl_vector_get(fixedlengths,j)*2); - gsl_matrix_set_row(optimalfiltersabFREQ_matrix,0,&temp.vector); - if (writeFitsComplex(objFREQ, optimalfiltersabFREQ_matrix)) + gsl_matrix_free(optimalfiltersTIME_matrix); optimalfiltersTIME_matrix = 0; + + if (i < eventcntLib) + { + strcpy(objTIME.nameCol,(string("ABT")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersabTIMErow,optimalfiltersabTIMEaux,i); + gsl_matrix *optimalfiltersabTIME_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)); + temp = gsl_vector_subvector(optimalfiltersabTIMErow,indexT,gsl_vector_get(fixedlengths,j)); + gsl_matrix_set_row(optimalfiltersabTIME_matrix,0,&temp.vector); + if (writeFitsComplex(objTIME, optimalfiltersabTIME_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objTIME.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_matrix_free(optimalfiltersabTIME_matrix); optimalfiltersabTIME_matrix = 0; + } + + indexT = indexT + gsl_vector_get(fixedlengths,j); + + strcpy(extname,"FIXFILTF"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + EP_PRINT_ERROR("Error moving to HDU FIXFILTF in library file",status); + return(EPFAIL); + } + + strcpy(objFREQ.nameCol,(string("F")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersFREQrow,optimalfiltersFREQaux,i); + gsl_matrix *optimalfiltersFREQ_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); + temp = gsl_vector_subvector(optimalfiltersFREQrow,indexF,gsl_vector_get(fixedlengths,j)*2); + gsl_matrix_set_row(optimalfiltersFREQ_matrix,0,&temp.vector); + if (writeFitsComplex(objFREQ,optimalfiltersFREQ_matrix)) { message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } - gsl_matrix_free(optimalfiltersabFREQ_matrix); optimalfiltersabFREQ_matrix = 0; - } - - indexF = indexF + gsl_vector_get(fixedlengths,j)*2; - - if (reconstruct_init->hduPRECALWN == 1) - { - if (reconstruct_init->largeFilter != reconstruct_init->pulse_length) + gsl_matrix_free(optimalfiltersFREQ_matrix); optimalfiltersFREQ_matrix = 0; + + if (i < eventcntLib) { - if (j >= 1) - { + strcpy(objFREQ.nameCol,(string("ABF")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersabFREQrow,optimalfiltersabFREQaux,i); + gsl_matrix *optimalfiltersabFREQ_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); + temp = gsl_vector_subvector(optimalfiltersabFREQrow,indexF,gsl_vector_get(fixedlengths,j)*2); + gsl_matrix_set_row(optimalfiltersabFREQ_matrix,0,&temp.vector); + if (writeFitsComplex(objFREQ, optimalfiltersabFREQ_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_matrix_free(optimalfiltersabFREQ_matrix); optimalfiltersabFREQ_matrix = 0; + } + + indexF = indexF + gsl_vector_get(fixedlengths,j)*2; + + if (reconstruct_init->hduPRECALWN == 1) + { + if (reconstruct_init->largeFilter != reconstruct_init->pulse_length) + { + if (j >= 1) + { + if (i < eventcntLib) + { + strcpy(extname,"PRECALWN"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + EP_PRINT_ERROR("Error moving to HDU PRECALWN in library file",status); + return(EPFAIL); + } + + strcpy(objWN.nameCol,(string("PCL")+string(str_length)).c_str()); + gsl_matrix_get_row(PRCLWNrow,PRCLWNaux,i); + gsl_matrix *PRCLWN_matrix; + PRCLWN_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); + temp = gsl_vector_subvector(PRCLWNrow,indexPRCLWN,gsl_vector_get(fixedlengths,j)*2); + gsl_matrix_set_row(PRCLWN_matrix,0,&temp.vector); + if (writeFitsComplex(objWN,PRCLWN_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objWN.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_matrix_free(PRCLWN_matrix); PRCLWN_matrix = 0; + } + + indexPRCLWN = indexPRCLWN + gsl_vector_get(fixedlengths,j)*2; + } + } + else + { if (i < eventcntLib) { strcpy(extname,"PRECALWN"); @@ -6326,61 +6773,112 @@ int readAddSortParams(ReconstructInitSIRENA *reconstruct_init,fitsfile **inLibOb indexPRCLWN = indexPRCLWN + gsl_vector_get(fixedlengths,j)*2; } } - else + + if (reconstruct_init->hduPRCLOFWM == 1) { - if (i < eventcntLib) + strcpy(extname,"PRCLOFWM"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) { - strcpy(extname,"PRECALWN"); - if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) - { - EP_PRINT_ERROR("Error moving to HDU PRECALWN in library file",status); - return(EPFAIL); - } - - strcpy(objWN.nameCol,(string("PCL")+string(str_length)).c_str()); - gsl_matrix_get_row(PRCLWNrow,PRCLWNaux,i); - gsl_matrix *PRCLWN_matrix; - PRCLWN_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); - temp = gsl_vector_subvector(PRCLWNrow,indexPRCLWN,gsl_vector_get(fixedlengths,j)*2); - gsl_matrix_set_row(PRCLWN_matrix,0,&temp.vector); - if (writeFitsComplex(objWN,PRCLWN_matrix)) - { - message = "Cannot run writeFitsComplex routine for column " + string(objWN.nameCol); - EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); - } - gsl_matrix_free(PRCLWN_matrix); PRCLWN_matrix = 0; + EP_PRINT_ERROR("Error moving to HDU PRCLOFWM in library file",status); + return(EPFAIL); + } + + strcpy(objOFWM.nameCol,(string("OFW")+string(str_length)).c_str()); + gsl_matrix_get_row(PRCLOFWMrow,PRCLOFWMaux,i); + gsl_matrix *PRCLOFWM_matrix; + PRCLOFWM_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); + temp = gsl_vector_subvector(PRCLOFWMrow,indexPRCLOFWM,gsl_vector_get(fixedlengths,j)*2); + gsl_matrix_set_row(PRCLOFWM_matrix,0,&temp.vector); + if (writeFitsComplex(objOFWM,PRCLOFWM_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objOFWM.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } + gsl_matrix_free(PRCLOFWM_matrix); PRCLOFWM_matrix = 0; - indexPRCLWN = indexPRCLWN + gsl_vector_get(fixedlengths,j)*2; + indexPRCLOFWM = indexPRCLOFWM + gsl_vector_get(fixedlengths,j)*2; } } - - if (reconstruct_init->hduPRCLOFWM == 1) + } + else + { + for (int j=0;jgrading->gradeData->size1;j++) { - strcpy(extname,"PRCLOFWM"); + strcpy(extname,"FIXFILTT"); + if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) + { + EP_PRINT_ERROR("Error moving to HDU FIXFILTT in library file",status); + return(EPFAIL); + } + + snprintf(str_length,125,"%d",(int) gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + strcpy(objTIME.nameCol,(string("T")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersTIMErow,optimalfiltersTIMEaux,i); + gsl_matrix *optimalfiltersTIME_matrix = gsl_matrix_alloc(1,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + temp = gsl_vector_subvector(optimalfiltersTIMErow,indexT,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + gsl_matrix_set_row(optimalfiltersTIME_matrix,0,&temp.vector); + if (writeFitsComplex(objTIME,optimalfiltersTIME_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objTIME.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_matrix_free(optimalfiltersTIME_matrix); optimalfiltersTIME_matrix = 0; + + if (i < eventcntLib) + { + strcpy(objTIME.nameCol,(string("ABT")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersabTIMErow,optimalfiltersabTIMEaux,i); + gsl_matrix *optimalfiltersabTIME_matrix = gsl_matrix_alloc(1,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + temp = gsl_vector_subvector(optimalfiltersabTIMErow,indexT,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)); + gsl_matrix_set_row(optimalfiltersabTIME_matrix,0,&temp.vector); + if (writeFitsComplex(objTIME, optimalfiltersabTIME_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objTIME.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_matrix_free(optimalfiltersabTIME_matrix); optimalfiltersabTIME_matrix = 0; + } + + indexT = indexT + gsl_matrix_get(reconstruct_init->grading->gradeData,j,1); + + strcpy(extname,"FIXFILTF"); if (fits_movnam_hdu(*inLibObject, ANY_HDU,extname, 0, &status)) { - EP_PRINT_ERROR("Error moving to HDU PRCLOFWM in library file",status); + EP_PRINT_ERROR("Error moving to HDU FIXFILTF in library file",status); return(EPFAIL); } - strcpy(objOFWM.nameCol,(string("OFW")+string(str_length)).c_str()); - gsl_matrix_get_row(PRCLOFWMrow,PRCLOFWMaux,i); - gsl_matrix *PRCLOFWM_matrix; - PRCLOFWM_matrix = gsl_matrix_alloc(1,gsl_vector_get(fixedlengths,j)*2); - temp = gsl_vector_subvector(PRCLOFWMrow,indexPRCLOFWM,gsl_vector_get(fixedlengths,j)*2); - gsl_matrix_set_row(PRCLOFWM_matrix,0,&temp.vector); - if (writeFitsComplex(objOFWM,PRCLOFWM_matrix)) + strcpy(objFREQ.nameCol,(string("F")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersFREQrow,optimalfiltersFREQaux,i); + gsl_matrix *optimalfiltersFREQ_matrix = gsl_matrix_alloc(1,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)*2); + temp = gsl_vector_subvector(optimalfiltersFREQrow,indexF,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)*2); + gsl_matrix_set_row(optimalfiltersFREQ_matrix,0,&temp.vector); + if (writeFitsComplex(objFREQ,optimalfiltersFREQ_matrix)) { - message = "Cannot run writeFitsComplex routine for column " + string(objOFWM.nameCol); + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); } - gsl_matrix_free(PRCLOFWM_matrix); PRCLOFWM_matrix = 0; + gsl_matrix_free(optimalfiltersFREQ_matrix); optimalfiltersFREQ_matrix = 0; - indexPRCLOFWM = indexPRCLOFWM + gsl_vector_get(fixedlengths,j)*2; + if (i < eventcntLib) + { + strcpy(objFREQ.nameCol,(string("ABF")+string(str_length)).c_str()); + gsl_matrix_get_row(optimalfiltersabFREQrow,optimalfiltersabFREQaux,i); + gsl_matrix *optimalfiltersabFREQ_matrix = gsl_matrix_alloc(1,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)*2); + temp = gsl_vector_subvector(optimalfiltersabFREQrow,indexF,gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)*2); + gsl_matrix_set_row(optimalfiltersabFREQ_matrix,0,&temp.vector); + if (writeFitsComplex(objFREQ, optimalfiltersabFREQ_matrix)) + { + message = "Cannot run writeFitsComplex routine for column " + string(objFREQ.nameCol); + EP_PRINT_ERROR(message,EPFAIL);return(EPFAIL); + } + gsl_matrix_free(optimalfiltersabFREQ_matrix); optimalfiltersabFREQ_matrix = 0; + } + + indexF = indexF + gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)*2; } } - } + } // Free allocated GSL vectors gsl_vector_free(optimalfilter); optimalfilter = 0; @@ -6506,10 +7004,10 @@ int calculateIntParams(ReconstructInitSIRENA *reconstruct_init, int indexa, int gsl_vector *Y; gsl_vector *Z; double r; - gsl_vector *Pab = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_vector *PabMaxLengthFixedFilter = gsl_vector_alloc(reconstruct_init->largeFilter); - gsl_vector *Dab = gsl_vector_alloc(reconstruct_init->pulse_length); - gsl_vector *DabMaxLengthFixedFilter = gsl_vector_alloc(reconstruct_init->largeFilter); + gsl_vector *Pab; + gsl_vector *PabMaxLengthFixedFilter; + gsl_vector *Dab; + gsl_vector *DabMaxLengthFixedFilter; gsl_vector *Wabvector; gsl_matrix *Walpha; gsl_vector *Walphavector; @@ -6519,7 +7017,27 @@ int calculateIntParams(ReconstructInitSIRENA *reconstruct_init, int indexa, int double Ea,Eb; gsl_vector *vectoraux = gsl_vector_alloc(1); - gsl_vector *vectoraux1 = gsl_vector_alloc(reconstruct_init->pulse_length); + gsl_vector *vectoraux1; + gsl_vector *vectorMaxLengthFixedFilteraux1; + if (reconstruct_init->preBuffer == 0) + { + Pab = gsl_vector_alloc(reconstruct_init->pulse_length); + PabMaxLengthFixedFilter = gsl_vector_alloc(reconstruct_init->largeFilter); + Dab = gsl_vector_alloc(reconstruct_init->pulse_length); + DabMaxLengthFixedFilter = gsl_vector_alloc(reconstruct_init->largeFilter); + vectoraux1 = gsl_vector_alloc(reconstruct_init->pulse_length); + vectorMaxLengthFixedFilteraux1 = gsl_vector_alloc(reconstruct_init->largeFilter); + } + else + { + Pab = gsl_vector_alloc(reconstruct_init->post_max_value); + PabMaxLengthFixedFilter = gsl_vector_alloc(reconstruct_init->post_max_value); + Dab = gsl_vector_alloc(reconstruct_init->post_max_value); + DabMaxLengthFixedFilter = gsl_vector_alloc(reconstruct_init->post_max_value); + vectoraux1 = gsl_vector_alloc(reconstruct_init->post_max_value); + vectorMaxLengthFixedFilteraux1 = gsl_vector_alloc(reconstruct_init->post_max_value); + } + gsl_vector *vectoraux2 = gsl_vector_alloc(reconstruct_init->pulse_length*reconstruct_init->pulse_length); gsl_matrix *matrixaux = gsl_matrix_alloc(reconstruct_init->pulse_length,reconstruct_init->pulse_length); @@ -6531,8 +7049,6 @@ int calculateIntParams(ReconstructInitSIRENA *reconstruct_init, int indexa, int gsl_vector *optimalfilter_FFT = NULL; gsl_vector_complex *optimalfilter_FFT_complex = NULL; - gsl_vector *vectorMaxLengthFixedFilteraux1 = gsl_vector_alloc(reconstruct_init->largeFilter); - // Calculate if (reconstruct_init->hduPRECALWN == 1) { @@ -7014,7 +7530,7 @@ int vector2matrix (gsl_vector *vectorin, gsl_matrix **matrixout) * R/R0 = 1 - (abs(DeltaI)/I_BIAS)/(1+abs(DeltaI)/I_BIAS) (I_BIAS is a keyword in the events file) * * - Conversion according to 'EnergyMethod'=I2RFITTED: - * R/V0 = -1/(Ifit+ADC) being Ifit=ADU_BIAS + * R/V0 = -1/(Ifit+ADC) being Ifit an input parameter * * If the ADU_CNV keyword is not in the events file and 'invector' contains tha ADC column data: * @@ -7027,7 +7543,7 @@ int vector2matrix (gsl_vector *vectorin, gsl_matrix **matrixout) * R/R0 = 1 - 1*(abs(DeltaI)/I0_START)/(1+abs(DeltaI)/I0_START) * * - Conversion according to 'EnergyMethod'=I2RFITTED: - * R/V0 = -1/(Ifit+ADC) being Ifit=I0_START(adu)=I0_START(A)/aducnv(A/adu) + * R/V0 = -1/(Ifit+ADC) being Ifit an input parameter * * Parameters: * - Ibias: Initial bias current (I0_START column) @@ -7155,6 +7671,7 @@ int convertI2R (char* EnergyMethod,double Ibias, double Imin, double Imax, doubl gsl_vector_free(invector_modified); invector_modified = 0;*/ } + gsl_vector_scale(*invector,100000); message.clear(); @@ -7495,14 +8012,9 @@ int obtainRiseFallTimes (gsl_vector *recordNOTFILTERED, double samprate, gsl_vec gsl_vector_view(temp); - /*cout<<"numPulses: "<size;k++) - { - //cout<<"gsl_vector_get(&temp.vector,k): "< threshold10) && (index10 == -999)) index10 = k; - if (gsl_vector_get(&temp.vector,k) > threshold50) - { - index50 = k; - break; - } - } - //cout<<"providingRiseTime: "<size: "<<(&temp.vector)->size<size;k++) - { - //cout<<"gsl_vector_get(&temp.vector,k): "<size;k++) + { + //cout<<"gsl_vector_get(&temp.vector,k): "< threshold10) && (index10 == -999)) index10 = k; + if (gsl_vector_get(&temp.vector,k) > threshold50) + { + index50 = k; + break; + } } - } - //cout<<"providingFallTime: "<size;k++) + { + //cout<<"gsl_vector_get(&temp.vector,k): "<pulse_length <= (*reconstruct_init)->OFLength) - * { - * resize_mf_lowres = 4; -} -else -{ -resize_mf_lowres = 4; -}*/ - resize_mf_lowres = 4; + resize_mf_lowres = 8; pulse_lowres = gsl_vector_alloc(resize_mf_lowres); gsl_vector *filtergsl_lowres = NULL; if (strcmp((*reconstruct_init)->FilterDomain,"T") == 0) filtergsl_lowres= gsl_vector_alloc(resize_mf_lowres); @@ -7797,9 +8308,23 @@ resize_mf_lowres = 4; double Ealpha_lowres, Ebeta_lowres; gsl_vector *optimalfilter_lowres = gsl_vector_alloc(filtergsl_lowres->size); // Resized optimal filter expressed in the time domain (optimalfilter(t)) gsl_vector_complex *optimalfilter_FFT_complex_lowres = gsl_vector_complex_alloc(filtergsl_lowres->size/2); + int filter8_exist = 0; + for (int i=0; i<(*reconstruct_init)->grading->gradeData->size1;i++) + { + if (gsl_matrix_get((*reconstruct_init)->grading->gradeData,i,1) == 8) + { + filter8_exist = 1; + break; + } + } + if (filter8_exist == 0) + { + message = "There is not a 8-length filter in the library to calculate the low energy resolution estimator => Not calculated (ELOWRES=-999)"; + EP_PRINT_ERROR(message,-999); // Only a warning + } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - int pulseGrade; // Pileup=-2, Rejected=-1, HighRes=1, MidRes=2, LimRes=3, LowRes=4 + int pulseGrade; // Pileup=-2, Rejected=-1, VeryHighRes=1, HighRes=2, IntRes=3, MidRes=4, LimRes=5, LowRes=6 // Store the record in 'invector' // It is not necessary to check the allocation because 'record->trigger_size' has been checked previously @@ -7846,28 +8371,57 @@ resize_mf_lowres = 4; double sumfilt; + int preBuffer_value = 0; + int resize_mfvsposti = 0; + int extraSizeDueToLags = 0; for (int i=0; i<(*pulsesInRecord)->ndetpulses ;i++) { tstartSamplesRecord = (*pulsesInRecord)->pulses_detected[i].TstartSamples; tstartSamplesRecordStartDOUBLE = tstartSamplesRecord-numlags2; //Si no pongo numlags2, los LAGS no salen bien (empieza desde muy atras a calcular energias)*/ if (tstartSamplesRecordStartDOUBLE < 0) (*pulsesInRecord)->pulses_detected[i].quality = 1; - - //if ((*pulsesInRecord)->pulses_detected[i].quality != 1) + if ((*pulsesInRecord)->pulses_detected[i].quality == 0) { - tooshortPulse_NoLags = 0; - - // Establish the pulse grade (HighRes=1, MidRes=2, LimRes=3, LowRes=4, Rejected=-1, Pileup=-2) and the optimal filter length - if ((*pulsesInRecord)->pulses_detected[i].quality == 1) (*pulsesInRecord)->pulses_detected[i].grade1 = -999; - else (*pulsesInRecord)->pulses_detected[i].grade1 = (*pulsesInRecord)->pulses_detected[i].pulse_duration; - + // Establish the pulse grade and the optimal filter length pulseGrade = 0; - if (pulseGrading(*reconstruct_init,(*pulsesInRecord)->pulses_detected[i].grade1,(*pulsesInRecord)->pulses_detected[i].grade2,OFlength_strategy,&pulseGrade,&resize_mf)) + if (pulseGrading(*reconstruct_init,(*pulsesInRecord)->pulses_detected[i].pulse_duration,(*pulsesInRecord)->pulses_detected[i].grade2,OFlength_strategy,&pulseGrade,&resize_mf,nrecord)) { message = "Cannot run routine pulseGrading"; EP_EXIT_ERROR(message,EPFAIL); } + + if (preBuffer == 1) + { + for (int j=0; j<(*reconstruct_init)->grading->gradeData->size1;j++) + { + if (gsl_matrix_get((*reconstruct_init)->grading->gradeData,j,1) == resize_mf) + { + preBuffer_value = gsl_matrix_get((*reconstruct_init)->grading->gradeData,j,2); + resize_mfvsposti = 1; + break; + } + } + if (resize_mfvsposti == 0) + { + message = "The grading/preBuffer info of the XML file does not match the filter length"; + EP_EXIT_ERROR(message,EPFAIL); + } + } + + if (tstartSamplesRecordStartDOUBLE-preBuffer_value+resize_mf+numlags > recordAux->size) + { + (*pulsesInRecord)->pulses_detected[i].quality = 1; + + message = "tstart-preBuffer+filterSize+numlags/2>recordSize for pulse i=" + boost::lexical_cast(i+1) + " in record " + boost::lexical_cast(nrecord); + EP_PRINT_ERROR(message,-999); + } + } + + if ((*pulsesInRecord)->pulses_detected[i].quality == 0) + { + tooshortPulse_NoLags = 0; + (*pulsesInRecord)->pulses_detected[i].grade1 = resize_mf; //resize_mf = resize_mf + preBuffer; log_debug("resize_mf (after pulseGrading): %i",resize_mf); @@ -7881,7 +8435,8 @@ resize_mf_lowres = 4; str.clear(); EP_EXIT_ERROR(message,EPFAIL); } - if ((tstartSamplesRecord-preBuffer < 0) ||(tstartSamplesRecord-preBuffer+resize_mf > recordAux->size-1)) + //if ((tstartSamplesRecord-preBuffer < 0) ||(tstartSamplesRecord-preBuffer+resize_mf > recordAux->size-1)) + if ((tstartSamplesRecord-preBuffer_value < 0) ||(tstartSamplesRecord-preBuffer_value+resize_mf > recordAux->size)) { sprintf(valERROR,"%d",__LINE__+6); string str(valERROR); @@ -7889,7 +8444,7 @@ resize_mf_lowres = 4; str.clear(); EP_EXIT_ERROR(message,EPFAIL); } - temp = gsl_vector_subvector(recordAux,tstartSamplesRecord-preBuffer,resize_mf); + temp = gsl_vector_subvector(recordAux,tstartSamplesRecord-preBuffer_value,resize_mf); if (gsl_vector_memcpy(pulse, &temp.vector) != 0) { sprintf(valERROR,"%d",__LINE__-2); @@ -7905,20 +8460,11 @@ resize_mf_lowres = 4; //////////// In order to get the low resolution energy estimator by filtering with a 4-samples-length filter /////////////////// log_trace("Calculating the low energy estimator..."); energy_lowres = -999; - // Pulse - if ((resize_mf_lowres <= recordAux->size-tstartSamplesRecord) && ((*reconstruct_init)->OFLib == 1)) - { - /*if (resize_mf_lowres > recordAux->size-tstartSamplesRecord) - * { - * sprintf(valERROR,"%d",__LINE__+5); - * string str(valERROR); - * message = "View goes out of scope the original vector in line " + str + " (" + __FILE__ + ")"; - * str.clear(); - * EP_EXIT_ERROR(message,EPFAIL); - }*/ - - if (preBuffer == 0) - { + if (filter8_exist == 1) + { + // Pulse + if ((resize_mf_lowres <= recordAux->size-tstartSamplesRecord) && ((*reconstruct_init)->OFLib == 1)) + { temp = gsl_vector_subvector(recordAux,tstartSamplesRecord,length_lowres); gsl_vector *vectoraux = gsl_vector_alloc(length_lowres); @@ -7932,58 +8478,45 @@ resize_mf_lowres = 4; } gsl_vector_free(vectoraux); vectoraux = 0; - } - else - { - temp = gsl_vector_subvector(recordAux,tstartSamplesRecord-preBuffer,resize_mf_lowres); - if (gsl_vector_memcpy(pulse_lowres, &temp.vector) != 0) + // Get the filter + if (strcmp((*reconstruct_init)->OFInterp,"MF") == 0) { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_EXIT_ERROR(message,EPFAIL); + if (find_optimalfilter((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Ealpha_lowres, &Ebeta_lowres)) + { + message = "Cannot run routine find_optimalfilter for filter interpolation"; + EP_EXIT_ERROR(message,EPFAIL); + } } - } - - // Get the filter - if (strcmp((*reconstruct_init)->OFInterp,"MF") == 0) - { - if (find_optimalfilter((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Ealpha_lowres, &Ebeta_lowres)) + else { - message = "Cannot run routine find_optimalfilter for filter interpolation"; - EP_EXIT_ERROR(message,EPFAIL); + if (find_optimalfilterDAB((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Pab_lowres,&Ealpha_lowres, &Ebeta_lowres)) + { + message = "Cannot run routine find_optimalfilterDAB for filter interpolation"; + EP_EXIT_ERROR(message,EPFAIL); + } } - } - else - { - if (find_optimalfilterDAB((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Pab_lowres,&Ealpha_lowres, &Ebeta_lowres)) + gsl_vector_set_all(optimalfilter_lowres,0); + for (int k=0;ksize/2;k++) { - message = "Cannot run routine find_optimalfilterDAB for filter interpolation"; - EP_EXIT_ERROR(message,EPFAIL); + gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(0.0,0.0)); } - } - gsl_vector_set_all(optimalfilter_lowres,0); - for (int k=0;ksize/2;k++) - { - gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(0.0,0.0)); - } - if (TorF == 0) gsl_vector_memcpy(optimalfilter_lowres,filtergsl_lowres); - else if (TorF == 1) - { - // It is not necessary to check the allocation because 'filtergsl' size has been checked previously - for (int k=0;ksize/2;k++) + if (TorF == 0) gsl_vector_memcpy(optimalfilter_lowres,filtergsl_lowres); + else if (TorF == 1) { - gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(gsl_vector_get(filtergsl_lowres,k),gsl_vector_get(filtergsl_lowres,k+filtergsl_lowres->size/2))); + // It is not necessary to check the allocation because 'filtergsl' size has been checked previously + for (int k=0;ksize/2;k++) + { + gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(gsl_vector_get(filtergsl_lowres,k),gsl_vector_get(filtergsl_lowres,k+filtergsl_lowres->size/2))); + } + } + + // Calculate the low resolution estimator + if (calculateEnergy(pulse_lowres,1,optimalfilter_lowres,optimalfilter_FFT_complex_lowres,0,0,0,(*reconstruct_init),TorF,1/record->delta_t,Pab_lowres,PRCLWN_lowres,PRCLOFWM_lowres,&energy_lowres,&tstartNewDev,&lagsShift,1,resize_mf_lowres,1)) + { + message = "Cannot run calculateEnergy routine for pulse i=" + boost::lexical_cast(i); + EP_EXIT_ERROR(message,EPFAIL); } - } - - // Calculate the low resolution estimator - if (calculateEnergy(pulse_lowres,1,optimalfilter_lowres,optimalfilter_FFT_complex_lowres,0,0,0,(*reconstruct_init),TorF,1/record->delta_t,Pab_lowres,PRCLWN_lowres,PRCLOFWM_lowres,&energy_lowres,&tstartNewDev,&lagsShift,1,resize_mf_lowres,1)) - { - message = "Cannot run calculateEnergy routine for pulse i=" + boost::lexical_cast(i); - EP_EXIT_ERROR(message,EPFAIL); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -7999,41 +8532,34 @@ resize_mf_lowres = 4; { if (strcmp((*reconstruct_init)->OFNoise,"NSD") == 0) { - if (tstartSamplesRecordStartDOUBLE-preBuffer+resize_mf+numlags-1 <= recordAux->size) - { - resize_mfNEW = resize_mf + numlags -1; - } - else + resize_mfNEW = resize_mf + numlags -1; + //} + /*else { //resize_mfNEW = resize_mf + numlags/2; - message = "tstart-preBuffer+filterSize-1>recordSize for pulse i=" + boost::lexical_cast(i); + message = "tstart-preBuffer+filterSize>recordSize for pulse i=" + boost::lexical_cast(i+1) + " in record " + boost::lexical_cast(nrecord); EP_EXIT_ERROR(message,EPFAIL); - } - + }*/ /*if ((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) // 0-padding { - if (tstartSamplesRecordStartDOUBLE-preBuffer+numlags-1 <= recordAux->size) + if (tstartSamplesRecordStartDOUBLE+resize_mf+numlags -1 <= recordAux->size) { resize_mfNEW = resize_mf + numlags -1; } else { - //resize_mfNEW = resize_mf + numlags/2; - message = "tstart-preBuffer+numlags-1>recordSize for pulse i=" + boost::lexical_cast(i); - EP_EXIT_ERROR(message,EPFAIL); + resize_mfNEW = resize_mf + numlags/2; } } else // NO 0-padding (or preBuffer or short filter) { - if (tstartSamplesRecordStartDOUBLE-preBuffer+resize_mf+numlags-1 <= recordAux->size) + if (tstartSamplesRecordStartDOUBLE+resize_mf+numlags -1 <= recordAux->size) { resize_mfNEW = resize_mf + numlags -1; } else { - //resize_mfNEW = resize_mf + numlags/2; - message = "tstart-preBuffer+filterSize+numlags-1>recordSize for pulse i=" + boost::lexical_cast(i); - EP_EXIT_ERROR(message,EPFAIL); + resize_mfNEW = resize_mf + numlags/2; } }*/ } @@ -8041,7 +8567,7 @@ resize_mf_lowres = 4; { resize_mfNEW = resize_mf; } - log_debug("resize_mfNEW: %i",resize_mfNEW); + //log_debug("resize_mfNEW: %i",resize_mfNEW); if ((pulseToCalculateEnergy = gsl_vector_alloc(resize_mfNEW)) == 0) { @@ -8053,7 +8579,7 @@ resize_mf_lowres = 4; } gsl_vector_set_all(pulseToCalculateEnergy,-999); - if ((tstartSamplesRecordStartDOUBLE-preBuffer < 0) || (tstartSamplesRecordStartDOUBLE-preBuffer > recordAux->size-2) + if ((tstartSamplesRecordStartDOUBLE-preBuffer_value < 0) || (tstartSamplesRecordStartDOUBLE-preBuffer_value > recordAux->size-2) || (resize_mfNEW < 1)) { sprintf(valERROR,"%d",__LINE__+5); @@ -8062,7 +8588,7 @@ resize_mf_lowres = 4; str.clear(); EP_EXIT_ERROR(message,EPFAIL); } - temp = gsl_vector_subvector(recordAux,tstartSamplesRecordStartDOUBLE-preBuffer,resize_mfNEW); + temp = gsl_vector_subvector(recordAux,tstartSamplesRecordStartDOUBLE-preBuffer_value,resize_mfNEW); if (gsl_vector_memcpy(pulseToCalculateEnergy, &temp.vector) != 0) { @@ -8144,7 +8670,8 @@ resize_mf_lowres = 4; log_debug("resize_mf1: %i",resize_mf); // If it is necessary, choose the base-2 system value closest (lower than or equal) to the pulse length if (((*reconstruct_init)->pulse_length > (*reconstruct_init)->OFLength) //No 0-padding - || (((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) && (preBuffer != 0)) + //|| (((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) && (preBuffer != 0)) + || (((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) && (preBuffer == 1)) || (resize_mf < (*reconstruct_init)->OFLength)) { //log_debug("Entra (no 0-padding)",resize_mf); @@ -8171,17 +8698,29 @@ resize_mf_lowres = 4; tooshortPulse_NoLags = 1; } + if (filtergsl != NULL) gsl_vector_free(filtergsl); filtergsl = 0; // It is not necessary to check the allocation because '(*reconstruct_init)->pulse_length'='PulseLength'(input parameter) has been checked previously if (strcmp((*reconstruct_init)->FilterDomain,"T") == 0) filtergsl= gsl_vector_alloc(resize_mf); else if (strcmp((*reconstruct_init)->FilterDomain,"F") == 0) filtergsl= gsl_vector_alloc(resize_mf*2); if ((strcmp((*reconstruct_init)->FilterDomain,"T") == 0) && ((*reconstruct_init)->pulse_length < (*reconstruct_init)->OFLength)) // 0-padding { - if ((*reconstruct_init)->library_collection->pulse_templates[0].template_duration < (*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration) - filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); - else - filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templates[0].template_duration); + //if (preBuffer == 0) + //{ + if ((*reconstruct_init)->library_collection->pulse_templates[0].template_duration < (*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration) + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); + else + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templates[0].template_duration); + /*} + else // preBuffer = 1 + { + if ((*reconstruct_init)->library_collection->pulse_templates[0].template_duration < (*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration) + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration-(*reconstruct_init)->preBuffer_max_value); + else + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templates[0].template_duration-(*reconstruct_init)->preBuffer_max_value); + }*/ } + gsl_vector_set_all(filtergsl,-999.0); Pab = gsl_vector_alloc(resize_mf); if (numiteration == 0) @@ -8201,7 +8740,6 @@ resize_mf_lowres = 4; message = "Cannot run routine find_optimalfilterDAB for filter interpolation"; EP_EXIT_ERROR(message,EPFAIL); } - } } else @@ -8458,6 +8996,9 @@ resize_mf_lowres = 4; cout<<"sumfilt1="<size;j++) + // cout<delta_t,Pab,PRCLWN,PRCLOFWM,&energy,&tstartNewDev,&lagsShift,0,resize_mf,tooshortPulse_NoLags)) { @@ -8642,7 +9183,7 @@ resize_mf_lowres = 4; /***** SECTION BB ************************************************************ * th_runEenergy: Run energy calculation only in multithread mode *****************************************************************************/ -void th_runEnergy(TesRecord* record, int trig_reclength, +void th_runEnergy(TesRecord* record, int nrecord, int trig_reclength, ReconstructInitSIRENA** reconstruct_init, PulsesCollection** pulsesInRecord, OptimalFilterSIRENA **optimalFilter, PulsesCollection *pulsesAll) @@ -8764,19 +9305,11 @@ void th_runEnergy(TesRecord* record, int trig_reclength, double minimum; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - int length_lowres = 4; + int length_lowres = 8; double energy_lowres; long resize_mf_lowres; gsl_vector *pulse_lowres; - /*if ((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) - * { - * resize_mf_lowres = 4; -} -else -{ -resize_mf_lowres = 4; -}*/ - resize_mf_lowres = 4; + resize_mf_lowres = 8; pulse_lowres = gsl_vector_alloc(resize_mf_lowres); gsl_vector *filtergsl_lowres = NULL; if (strcmp((*reconstruct_init)->FilterDomain,"T") == 0) filtergsl_lowres= gsl_vector_alloc(resize_mf_lowres); @@ -8787,6 +9320,20 @@ resize_mf_lowres = 4; double Ealpha_lowres, Ebeta_lowres; gsl_vector *optimalfilter_lowres = gsl_vector_alloc(filtergsl_lowres->size); // Resized optimal filter expressed in the time domain (optimalfilter(t)) gsl_vector_complex *optimalfilter_FFT_complex_lowres = gsl_vector_complex_alloc(filtergsl_lowres->size/2); + int filter8_exist = 0; + for (int i=0; i<(*reconstruct_init)->grading->gradeData->size1;i++) + { + if (gsl_matrix_get((*reconstruct_init)->grading->gradeData,i,1) == 8) + { + filter8_exist = 1; + break; + } + } + if (filter8_exist == 0) + { + message = "There is not a 8-length filter in the library to calculate the low energy resolution estimator => Not calculated (ELOWRES=-999)"; + EP_PRINT_ERROR(message,-999); // Only a warning + } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int pulseGrade; // Pileup=-2, Rejected=-1, HighRes=1, MidRes=2, LimRes=3, LowRes=4 @@ -8836,6 +9383,9 @@ resize_mf_lowres = 4; double sumfilt; + int preBuffer_value = 0; + int resize_mfvsposti = 0; + int extraSizeDueToLags = 0; for (int i=0; i<(*pulsesInRecord)->ndetpulses ;i++) { @@ -8843,22 +9393,48 @@ resize_mf_lowres = 4; tstartSamplesRecordStartDOUBLE = tstartSamplesRecord-numlags2; if (tstartSamplesRecordStartDOUBLE < 0) (*pulsesInRecord)->pulses_detected[i].quality = 1; - //if ((*pulsesInRecord)->pulses_detected[i].quality != 1) if ((*pulsesInRecord)->pulses_detected[i].quality == 0) { - tooshortPulse_NoLags = 0; - - // Establish the pulse grade (HighRes=1, MidRes=2, LimRes=3, LowRes=4, Rejected=-1, Pileup=-2) and the optimal filter length - if ((*pulsesInRecord)->pulses_detected[i].quality == 1) (*pulsesInRecord)->pulses_detected[i].grade1 = -1; - else (*pulsesInRecord)->pulses_detected[i].grade1 = (*pulsesInRecord)->pulses_detected[i].pulse_duration; + // Establish the pulse grade and the optimal filter length pulseGrade = 0; - if (pulseGrading(*reconstruct_init,(*pulsesInRecord)->pulses_detected[i].grade1,(*pulsesInRecord)->pulses_detected[i].grade2,OFlength_strategy,&pulseGrade,&resize_mf)) + if (pulseGrading(*reconstruct_init,(*pulsesInRecord)->pulses_detected[i].pulse_duration,(*pulsesInRecord)->pulses_detected[i].grade2,OFlength_strategy,&pulseGrade,&resize_mf,nrecord)) { message = "Cannot run routine pulseGrading"; EP_EXIT_ERROR(message,EPFAIL); } + + if (preBuffer == 1) + { + for (int j=0; j<(*reconstruct_init)->grading->gradeData->size1;j++) + { + if (gsl_matrix_get((*reconstruct_init)->grading->gradeData,j,1) == resize_mf) + { + preBuffer_value = gsl_matrix_get((*reconstruct_init)->grading->gradeData,j,2); + resize_mfvsposti = 1; + break; + } + } + if (resize_mfvsposti == 0) + { + message = "The grading/preBuffer info of the XML file does not match the filter length"; + EP_EXIT_ERROR(message,EPFAIL); + } + } + + if (tstartSamplesRecordStartDOUBLE-preBuffer_value+resize_mf+numlags > recordAux->size) + { + (*pulsesInRecord)->pulses_detected[i].quality = 1; + + message = "tstart-preBuffer+filterSize+numlags/2>recordSize for pulse i=" + boost::lexical_cast(i+1) + " in record " + boost::lexical_cast(nrecord); + EP_PRINT_ERROR(message,-999); + } + } + + if ((*pulsesInRecord)->pulses_detected[i].quality == 0) + { + tooshortPulse_NoLags = 0; + (*pulsesInRecord)->pulses_detected[i].grade1 = resize_mf; - //resize_mf = resize_mf + preBuffer; // Pulse: Load the proper piece of the record in 'pulse' if ((pulse = gsl_vector_alloc(resize_mf)) == 0) @@ -8869,7 +9445,7 @@ resize_mf_lowres = 4; str.clear(); EP_EXIT_ERROR(message,EPFAIL); } - if ((tstartSamplesRecord-preBuffer < 0) ||(tstartSamplesRecord-preBuffer+resize_mf > recordAux->size-1)) + if ((tstartSamplesRecord-preBuffer_value < 0) ||(tstartSamplesRecord-preBuffer_value+resize_mf > recordAux->size)) { sprintf(valERROR,"%d",__LINE__+6); string str(valERROR); @@ -8877,7 +9453,7 @@ resize_mf_lowres = 4; str.clear(); EP_EXIT_ERROR(message,EPFAIL); } - temp = gsl_vector_subvector(recordAux,tstartSamplesRecord-preBuffer,resize_mf); + temp = gsl_vector_subvector(recordAux,tstartSamplesRecord-preBuffer_value,resize_mf); if (gsl_vector_memcpy(pulse, &temp.vector) != 0) { sprintf(valERROR,"%d",__LINE__-2); @@ -8893,19 +9469,10 @@ resize_mf_lowres = 4; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////// In order to get the low resolution energy estimator by filtering with a 4-samples-length filter /////////////////// energy_lowres = -999; - // Pulse - if (resize_mf_lowres <= recordAux->size-tstartSamplesRecord) + if (filter8_exist == 1) { - /*if (resize_mf_lowres > recordAux->size-tstartSamplesRecord) - * { - * sprintf(valERROR,"%d",__LINE__+5); - * string str(valERROR); - * message = "View goes out of scope the original vector in line " + str + " (" + __FILE__ + ")"; - * str.clear(); - * EP_EXIT_ERROR(message,EPFAIL); - }*/ - - if (preBuffer == 0) + // Pulse + if (resize_mf_lowres <= recordAux->size-tstartSamplesRecord) { temp = gsl_vector_subvector(recordAux,tstartSamplesRecord,length_lowres); @@ -8920,57 +9487,44 @@ resize_mf_lowres = 4; } gsl_vector_free(vectoraux); vectoraux = 0; - } - else - { - temp = gsl_vector_subvector(recordAux,tstartSamplesRecord-preBuffer,resize_mf_lowres); - if (gsl_vector_memcpy(pulse_lowres, &temp.vector) != 0) + // Filter + if (strcmp((*reconstruct_init)->OFInterp,"MF") == 0) { - sprintf(valERROR,"%d",__LINE__-2); - string str(valERROR); - message = "Copying vectors of different length in line " + str + " (" + __FILE__ + ")"; - str.clear(); - EP_EXIT_ERROR(message,EPFAIL); + if (find_optimalfilter((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Ealpha_lowres, &Ebeta_lowres)) + { + message = "Cannot run routine find_optimalfilter for filter interpolation"; + EP_EXIT_ERROR(message,EPFAIL); + } } - } - - // Filter - if (strcmp((*reconstruct_init)->OFInterp,"MF") == 0) - { - if (find_optimalfilter((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Ealpha_lowres, &Ebeta_lowres)) + else { - message = "Cannot run routine find_optimalfilter for filter interpolation"; - EP_EXIT_ERROR(message,EPFAIL); + if (find_optimalfilterDAB((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Pab_lowres,&Ealpha_lowres, &Ebeta_lowres)) + { + message = "Cannot run routine find_optimalfilterDAB for filter interpolation"; + EP_EXIT_ERROR(message,EPFAIL); + } } - } - else - { - if (find_optimalfilterDAB((*pulsesInRecord)->pulses_detected[i].maxDER, (*reconstruct_init)->library_collection->maxDERs, (*reconstruct_init), &filtergsl_lowres, &Pab_lowres,&Ealpha_lowres, &Ebeta_lowres)) + gsl_vector_set_all(optimalfilter_lowres,0); + for (int k=0;ksize/2;k++) { - message = "Cannot run routine find_optimalfilterDAB for filter interpolation"; - EP_EXIT_ERROR(message,EPFAIL); + gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(0.0,0.0)); } - } - gsl_vector_set_all(optimalfilter_lowres,0); - for (int k=0;ksize/2;k++) - { - gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(0.0,0.0)); - } - if (TorF == 0) gsl_vector_memcpy(optimalfilter_lowres,filtergsl_lowres); - else if (TorF == 1) - { - // It is not necessary to check the allocation because 'filtergsl' size has been checked previously - for (int k=0;ksize/2;k++) + if (TorF == 0) gsl_vector_memcpy(optimalfilter_lowres,filtergsl_lowres); + else if (TorF == 1) { - gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(gsl_vector_get(filtergsl_lowres,k),gsl_vector_get(filtergsl_lowres,k+filtergsl_lowres->size/2))); + // It is not necessary to check the allocation because 'filtergsl' size has been checked previously + for (int k=0;ksize/2;k++) + { + gsl_vector_complex_set(optimalfilter_FFT_complex_lowres,k,gsl_complex_rect(gsl_vector_get(filtergsl_lowres,k),gsl_vector_get(filtergsl_lowres,k+filtergsl_lowres->size/2))); + } + } + // Calculate the low resolution estimator + if (calculateEnergy(pulse_lowres,1,optimalfilter_lowres,optimalfilter_FFT_complex_lowres,0,0,0,(*reconstruct_init),TorF,1/record->delta_t,Pab_lowres,PRCLWN_lowres,PRCLOFWM_lowres,&energy_lowres,&tstartNewDev,&lagsShift,1,resize_mf_lowres,1)) + { + message = "Cannot run calculateEnergy routine for pulse i=" + boost::lexical_cast(i); + EP_EXIT_ERROR(message,EPFAIL); } - } - // Calculate the low resolution estimator - if (calculateEnergy(pulse_lowres,1,optimalfilter_lowres,optimalfilter_FFT_complex_lowres,0,0,0,(*reconstruct_init),TorF,1/record->delta_t,Pab_lowres,PRCLWN_lowres,PRCLOFWM_lowres,&energy_lowres,&tstartNewDev,&lagsShift,1,resize_mf_lowres,1)) - { - message = "Cannot run calculateEnergy routine for pulse i=" + boost::lexical_cast(i); - EP_EXIT_ERROR(message,EPFAIL); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -8984,7 +9538,7 @@ resize_mf_lowres = 4; { if (strcmp((*reconstruct_init)->OFNoise,"NSD") == 0) { - if (tstartSamplesRecordStartDOUBLE-preBuffer+resize_mf+numlags-1 <= recordAux->size) + if (tstartSamplesRecordStartDOUBLE-preBuffer_value+resize_mf+numlags-1 <= recordAux->size) { resize_mfNEW = resize_mf + numlags -1; } @@ -8996,7 +9550,7 @@ resize_mf_lowres = 4; } /*if ((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) // 0-padding { - if (tstartSamplesRecordStartDOUBLE-preBuffer+numlags -1 <= recordAux->size) + if (tstartSamplesRecordStartDOUBLE+resize_mf+numlags -1 <= recordAux->size) { resize_mfNEW = resize_mf + numlags -1; } @@ -9005,9 +9559,9 @@ resize_mf_lowres = 4; resize_mfNEW = resize_mf + numlags/2; } } - else // NO 0-padding (or preBuffer or short filter) + else // NO 0-padding (or preBuffer or normal) { - if (tstartSamplesRecordStartDOUBLE-preBuffer+resize_mf+numlags -1 <= recordAux->size) + if (tstartSamplesRecordStartDOUBLE+resize_mf+numlags -1 <= recordAux->size) { resize_mfNEW = resize_mf + numlags -1; } @@ -9041,7 +9595,7 @@ resize_mf_lowres = 4; EP_EXIT_ERROR(message,EPFAIL); } - temp = gsl_vector_subvector(recordAux,tstartSamplesRecordStartDOUBLE-preBuffer,resize_mfNEW); + temp = gsl_vector_subvector(recordAux,tstartSamplesRecordStartDOUBLE-preBuffer_value,resize_mfNEW); if (strcmp((*reconstruct_init)->OFNoise,"NSD") == 0) { @@ -9134,10 +9688,10 @@ resize_mf_lowres = 4; if ((*reconstruct_init)->LagsOrNot == 1) resize_mf= resize_mfNEW-numlags+1; // Choose the base-2 system value closest (lower than or equal) to the pulse length if (((*reconstruct_init)->pulse_length > (*reconstruct_init)->OFLength) //No 0-padding - || (((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) && (preBuffer != 0)) + //|| (((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) && (preBuffer != 0)) + || (((*reconstruct_init)->pulse_length <= (*reconstruct_init)->OFLength) && (preBuffer == 1)) || (resize_mf < (*reconstruct_init)->OFLength)) { - //resize_mf = pow(2,floor(log2(resize_mf))); double double_oflength = (double)(*reconstruct_init)->OFLength; double log2_double_oflength = log2(double_oflength); if ((log2_double_oflength - (int) log2_double_oflength) == 0) //oflength is a power of 2 @@ -9165,10 +9719,20 @@ resize_mf_lowres = 4; if ((strcmp((*reconstruct_init)->FilterDomain,"T") == 0) && ((*reconstruct_init)->pulse_length < (*reconstruct_init)->OFLength)) // 0-padding { - if ((*reconstruct_init)->library_collection->pulse_templates[0].template_duration < (*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration) - filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); - else - filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templates[0].template_duration); + if (preBuffer == 0) + { + if ((*reconstruct_init)->library_collection->pulse_templates[0].template_duration < (*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration) + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); + else + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templates[0].template_duration); + } + else // preBuffer = 1 + { + if ((*reconstruct_init)->library_collection->pulse_templates[0].template_duration < (*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration) + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration-(*reconstruct_init)->preBuffer_max_value); + else + filtergsl = gsl_vector_alloc((*reconstruct_init)->library_collection->pulse_templates[0].template_duration-(*reconstruct_init)->preBuffer_max_value); + } } Pab = gsl_vector_alloc(resize_mf); @@ -10455,25 +11019,35 @@ int find_optimalfilter(double maxDER, gsl_vector *maxDERs, ReconstructInitSIRENA } gsl_vector *fixedlengths = gsl_vector_alloc(reconstruct_init->library_collection->nfixedfilters); - if ((reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != reconstruct_init->library_collection->pulse_templates[0].template_duration) && - (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != -999) - && (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != 999)) - + if (reconstruct_init->preBuffer == 0) { - for (int i=0;ilibrary_collection->nfixedfilters-1;i++) + if ((reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != reconstruct_init->library_collection->pulse_templates[0].template_duration) && + (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != -999) + && (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != 999)) + { - gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + for (int i=0;ilibrary_collection->nfixedfilters-1;i++) + { + gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + } + gsl_vector_set(fixedlengths,0,reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); + } + else + { + for (int i=0;ilibrary_collection->nfixedfilters;i++) + { + gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + } } - gsl_vector_set(fixedlengths,0,reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); } - else + else // preBuffer = 1 { - for (int i=0;ilibrary_collection->nfixedfilters;i++) + for (int i=0;igrading->gradeData->size1;i++) { - gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + gsl_vector_set(fixedlengths,i,gsl_matrix_get(reconstruct_init->grading->gradeData,i,1)); } } - + int index = 0; gsl_vector_view temp; for (int i=0;ilibrary_collection->nfixedfilters;i++) @@ -10489,7 +11063,7 @@ int find_optimalfilter(double maxDER, gsl_vector *maxDERs, ReconstructInitSIRENA } if (strcmp(reconstruct_init->FilterDomain,"F") == 0) index = index + gsl_vector_get(fixedlengths,i)*2; - else if (strcmp(reconstruct_init->FilterDomain,"T") == 0) index = index + gsl_vector_get(fixedlengths,i); + else if (strcmp(reconstruct_init->FilterDomain,"T") == 0) index = index + gsl_vector_get(fixedlengths,i); } gsl_vector_free(optimalfilterFound_Aux); optimalfilterFound_Aux = 0; @@ -10630,21 +11204,31 @@ int find_optimalfilterDAB(double maxDER, gsl_vector *maxDERs, ReconstructInitSIR } gsl_vector *fixedlengths = gsl_vector_alloc(reconstruct_init->library_collection->nfixedfilters); - if ((reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != reconstruct_init->library_collection->pulse_templates[0].template_duration) - && (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != -999) - && (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != 999)) + if (reconstruct_init->preBuffer == 0) { - for (int i=0;ilibrary_collection->nfixedfilters-1;i++) + if ((reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != reconstruct_init->library_collection->pulse_templates[0].template_duration) + && (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != -999) + && (reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration != 999)) { - gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + for (int i=0;ilibrary_collection->nfixedfilters-1;i++) + { + gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + } + gsl_vector_set(fixedlengths,0,reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); + } + else + { + for (int i=0;ilibrary_collection->nfixedfilters;i++) + { + gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + } } - gsl_vector_set(fixedlengths,0,reconstruct_init->library_collection->pulse_templatesMaxLengthFixedFilter[0].template_duration); } - else + else // preBuffer = 1 { - for (int i=0;ilibrary_collection->nfixedfilters;i++) + for (int i=0;igrading->gradeData->size1;i++) { - gsl_vector_set(fixedlengths,reconstruct_init->library_collection->nfixedfilters-1-i,pow(2,1+i)); + gsl_vector_set(fixedlengths,i,gsl_matrix_get(reconstruct_init->grading->gradeData,i,1)); } } @@ -11050,18 +11634,27 @@ int find_Esboundary(double maxDER, gsl_vector *maxDERs, ReconstructInitSIRENA *r * - OFlength_strategy: 'OFStrategy' (input) * - pulseGrade: Pulse grade (output) * - OFlength: Optimal filter length (='OFLength' only if 'OFStrategy'=FIXED and 'OFLength' <= grade1) (output) + * - nrecord: Current record index (to know the particular record where there could be more than one pulse => message) ****************************************/ -int pulseGrading (ReconstructInitSIRENA *reconstruct_init, int grade1, int grade2, int OFlength_strategy, int *pulseGrade, long *OFlength) +int pulseGrading (ReconstructInitSIRENA *reconstruct_init, int grade1, int grade2, int OFlength_strategy, int *pulseGrade, long *OFlength, int nrecord) { string message = ""; char valERROR[256]; // For the moment, in the 'xifu_detector_hex_baseline.xml' there is not info about all the pixels (SPA, LPA1, LPA2 or LPA3) // It works with the current structure in the .xml file (maybe NOT with a different structure) - int L2 = gsl_matrix_get(reconstruct_init->grading->gradeData,3,1); // 'gradelim_post' if 'value'(grading num) = 4 + /*int L2 = gsl_matrix_get(reconstruct_init->grading->gradeData,3,1); // 'gradelim_post' if 'value'(grading num) = 4 int LIMITED = gsl_matrix_get(reconstruct_init->grading->gradeData,2,1); // 'gradelim_post' if 'value'(grading num) = 3 int M1 = gsl_matrix_get(reconstruct_init->grading->gradeData,1,1); // 'gradelim_post' if 'value'(grading num) = 2 - int H1 = gsl_matrix_get(reconstruct_init->grading->gradeData,0,1); // 'gradelim_post' if 'value'(grading num) = 1 + int H1 = gsl_matrix_get(reconstruct_init->grading->gradeData,0,1); // 'gradelim_post' if 'value'(grading num) = 1*/ + + /*int vhigh = gsl_matrix_get(reconstruct_init->grading->gradeData,0,1); // 'gradelim_post' if 'value'(grading num) = 1 + int high = gsl_matrix_get(reconstruct_init->grading->gradeData,1,1); // 'gradelim_post' if 'value'(grading num) = 2 + int inter = gsl_matrix_get(reconstruct_init->grading->gradeData,2,1); // 'gradelim_post' if 'value'(grading num) = 3 + int mid = gsl_matrix_get(reconstruct_init->grading->gradeData,3,1); // 'gradelim_post' if 'value'(grading num) = 4 + int lim = gsl_matrix_get(reconstruct_init->grading->gradeData,4,1); // 'gradelim_post' if 'value'(grading num) = 5 + int low = gsl_matrix_get(reconstruct_init->grading->gradeData,5,1); // 'gradelim_post' if 'value'(grading num) = 6*/ + gsl_vector *gradelim; if ((gradelim = gsl_vector_alloc(reconstruct_init->grading->ngrades)) == 0) { @@ -11088,15 +11681,33 @@ int pulseGrading (ReconstructInitSIRENA *reconstruct_init, int grade1, int grade if (OFlength_strategy == 0) *OFlength = grade1; else if (OFlength_strategy == 3) { - *OFlength = min(reconstruct_init->OFLength,grade1); + //*OFlength = min(reconstruct_init->OFLength,grade1); /*if (reconstruct_init->OFLength > grade1) { message = "OFLength provided as input parameter > Pulse duration (there can be a pulse in its tail) => OFLength=Pulse duration"; EP_PRINT_ERROR(message,-999); // Only a warning }*/ + + //*OFlength = reconstruct_init->OFLength; + if ((reconstruct_init->OFLength > grade1) && (reconstruct_init->pulse_length >= reconstruct_init->OFLength)) + { + *OFlength = reconstruct_init->OFLength; + + char str_nrecord[125]; snprintf(str_nrecord,125,"%d",nrecord); + message = "OFLength provided as input parameter > Pulse duration (there can be a pulse in its tail) => Pulse duration = OFLength " + string(str_nrecord); + EP_PRINT_ERROR(message,-999); // Only a warning + } + else if (reconstruct_init->pulse_length < reconstruct_init->OFLength) + { + *OFlength = reconstruct_init->pulse_length; + } + else + { + *OFlength = reconstruct_init->OFLength; + } } - if (grade1 >= H1) // High res + /*if (grade1 >= H1) // High res { *pulseGrade = 1; if (OFlength_strategy == 2) *OFlength = H1; @@ -11120,7 +11731,83 @@ int pulseGrading (ReconstructInitSIRENA *reconstruct_init, int grade1, int grade { *pulseGrade = -2; if (OFlength_strategy == 2) *OFlength = grade1; - } + }*/ + /*if (grade1 >= vhigh) // Very High res + { + *pulseGrade = 1; + if (OFlength_strategy == 2) *OFlength = vhigh; + } + else if (grade1 >= high) // High res + { + *pulseGrade = 2; + if (OFlength_strategy == 2) *OFlength = high; + } + else if (grade1 >= inter) // Inter res + { + *pulseGrade = 3; + if (OFlength_strategy == 2) *OFlength = inter; + } + else if (grade1 > mid) // Mid res + { + *pulseGrade = 4; + if (OFlength_strategy == 2) *OFlength = mid; + } + else if (grade1 > lim) // Lim res + { + *pulseGrade = 5; + if (OFlength_strategy == 2) *OFlength = lim; + } + else if (grade1 > low) // Low res + { + *pulseGrade = 6; + if (OFlength_strategy == 2) *OFlength = low; + } + else if (grade1 <= low) //Pileup + { + *pulseGrade = -2; + if (OFlength_strategy == 2) *OFlength = grade1; + }*/ + + *pulseGrade = 0; + int nopower2 = 0; + for (int i=0;igrading->ngrades;i++) + { + if (grade1 >= gsl_matrix_get(reconstruct_init->grading->gradeData,i,1)) + { + *pulseGrade = i+1; + if (OFlength_strategy == 2) + { + if (log2(gsl_matrix_get(reconstruct_init->grading->gradeData,i,1))-(int)log2(gsl_matrix_get(reconstruct_init->grading->gradeData,i,1)) != 0) + { + for (int j=i+1;jgrading->ngrades;j++) + { + if (log2(gsl_matrix_get(reconstruct_init->grading->gradeData,j,1))-(int)log2(gsl_matrix_get(reconstruct_init->grading->gradeData,j,1)) == 0) + { + *OFlength = gsl_matrix_get(reconstruct_init->grading->gradeData,j,1); + nopower2 = 1; + break; + } + } + } + else + { + *OFlength = gsl_matrix_get(reconstruct_init->grading->gradeData,i,1); + nopower2 = 1; + } + } + break; + } + } + if ((OFlength_strategy == 2) && (nopower2 == 0)) + { + message = "No grade being a power of 2 in the XML file"; + EP_PRINT_ERROR(message,EPFAIL); return(EPFAIL); + } + if (*pulseGrade == 0) + { + *pulseGrade = -2; + if (OFlength_strategy == 2) *OFlength = grade1; + } if ((grade2 < gradelim_pre) || (grade1 == -1)) // Rejected: It is distinguished by the grade but currently its energy is also calculated (by using the info of the next pulse to establish the OFLength) { @@ -11259,10 +11946,10 @@ int calculateEnergy (gsl_vector *vector, int pulseGrade, gsl_vector *filter, gsl log_debug("filterFFT->size: %i",filterFFT->size); log_debug("vector->size: %i",vector->size); log_debug("productSize: %i",productSize); - int minimo; + /*int minimo; if (vector->size < filter->size) minimo = vector->size; else minimo = filter->size; - /*if (LowRes== 0) + if (LowRes== 0) { for (int i=0;i. + + + Copyright 2015 Philippe Peille, IRAP +*/ + +#include "teseventlist.h" + +/** TesEventList constructor. Returns a pointer to an empty TesEventList data + structure. */ +TesEventList* newTesEventList(int* const status){ + TesEventList* event_list= malloc(sizeof*event_list); + if (NULL==event_list) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TesEventList failed"); + return(event_list); + } + // Initialize pointers with NULL + event_list->event_indexes=NULL; + event_list->pulse_heights=NULL; + event_list->energies=NULL; + event_list->grades1=NULL; + event_list->grades2=NULL; + event_list->ph_ids=NULL; + + // Initialize values + event_list->size=0; + event_list->size_energy=0; + event_list->index=0; + + return(event_list); +} + +TesEventList* newTesEventListSIRENA(int* const status){ + TesEventList* event_list= malloc(sizeof*event_list); + if (NULL==event_list) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TesEventList failed"); + return(event_list); + } + // Initialize pointers with NULL + event_list->event_indexes=NULL; + event_list->pulse_heights=NULL; + event_list->avgs_4samplesDerivative=NULL; + event_list->Es_lowres=NULL; + event_list->grading=NULL; + event_list->phis=NULL; + event_list->lagsShifts=NULL; + event_list->bsln=NULL; + event_list->rmsbsln=NULL; + event_list->energies=NULL; + event_list->grades1=NULL; + event_list->grades2=NULL; + event_list->ph_ids=NULL; + event_list->ph_ids2=NULL; + event_list->ph_ids3=NULL; + event_list->pix_ids=NULL; + event_list->risetimes=NULL; + event_list->falltimes=NULL; + + // Initialize values + event_list->size=0; + event_list->size_energy=0; + event_list->index=0; + + return(event_list); +} + +/** TesEventList Destructor. */ +void freeTesEventList(TesEventList* event_list){ + if (NULL!=event_list){ + free(event_list->event_indexes); + free(event_list->pulse_heights); + free(event_list->energies); + free(event_list->grades1); + free(event_list->grades2); + free(event_list->ph_ids); + free(event_list); + event_list=NULL; + } +} + +void freeTesEventListSIRENA(TesEventList* event_list){ + if (NULL!=event_list){ + free(event_list->event_indexes); + free(event_list->pulse_heights); + free(event_list->energies); + free(event_list->avgs_4samplesDerivative); + free(event_list->Es_lowres); + free(event_list->grading); + free(event_list->phis); + free(event_list->lagsShifts); + free(event_list->bsln); + free(event_list->rmsbsln); + free(event_list->grades1); + free(event_list->grades2); + free(event_list->ph_ids); + free(event_list->ph_ids2); + free(event_list->ph_ids3); + free(event_list->pix_ids); + free(event_list->risetimes); + free(event_list->falltimes); + free(event_list); + event_list=NULL; + } +} + +/** Allocates memory for a TesEventList structure for the triggering stage: + * only event_index, pulse_height */ +void allocateTesEventListTrigger(TesEventList* event_list,int size,int* const status){ + event_list->event_indexes = malloc(size*sizeof*(event_list->event_indexes)); + if (NULL == event_list->event_indexes){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for event_index array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + + event_list->pulse_heights = malloc(size*sizeof*(event_list->pulse_heights)); + if (NULL == event_list->pulse_heights){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for pulse_height array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + + event_list->grades1 = malloc(size*sizeof*(event_list->grades1)); + if (NULL == event_list->grades1){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for grade1 array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + + event_list->size = size; +} + +/** Allocates memory for the energy, grade1, and grade2 arrays according to + * current size */ +void allocateWholeTesEventList(TesEventList* event_list,unsigned char allocate_ph,int* const status){ + //Only allocate if necessary + if (event_list->size_energy < event_list->size) { + //Free previous lists if they were already used + if (NULL != event_list->energies) { + free(event_list->energies); + //free(event_list->grading); + //free(event_list->phis); + free(event_list->grades2); + if(NULL!= event_list->ph_ids){ + free(event_list->ph_ids); + } + } + event_list->energies = malloc(event_list->size*sizeof*(event_list->energies)); + if (NULL == event_list->energies){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for energy array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + + /*event_list->grading = malloc(event_list->size*sizeof*(event_list->grading)); //SIRENA + if (NULL == event_list->grading){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for energy array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + }*/ + + /*event_list->phis = malloc(event_list->size*sizeof*(event_list->phis)); //SIRENA + if (NULL == event_list->phis){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for energy array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + }*/ + + event_list->grades2 = malloc(event_list->size*sizeof*(event_list->grades2)); + if (NULL == event_list->grades2){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for grade2 array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + + if (allocate_ph){ + event_list->ph_ids = malloc(event_list->size*sizeof*(event_list->ph_ids)); + if (NULL == event_list->ph_ids){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for ph_ids array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + } + + /*event_list->pix_ids = malloc(event_list->size*sizeof*(event_list->pix_ids)); + if (NULL == event_list->pix_ids){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for pix_ids array in TesEventList failed"); + CHECK_STATUS_VOID(*status); + }*/ + + event_list->size_energy = event_list->size; + } +} + +/** Appends the index and pulse_height lists to the list */ +void addEventToList(TesEventList* event_list,int index,double pulse_height,int grade1,int* const status) { + //If the list is not big enough, increase size + if (event_list->index >= event_list->size) { + //Increase size value + event_list->size = event_list->size * 2; + + //Allocate new arrays + int * new_event_index_array = realloc(event_list->event_indexes,(event_list->size)*sizeof(*(event_list->event_indexes))); + if (!new_event_index_array){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation during size update of TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + double * new_pulse_height_array = realloc(event_list->pulse_heights,(event_list->size)*sizeof(*(event_list->pulse_heights))); + if (!new_pulse_height_array){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation during size update of TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + int * new_grades1 = realloc(event_list->grades1,(event_list->size)*sizeof(*(event_list->grades1))); + if (!new_grades1){ + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation during size update of TesEventList failed"); + CHECK_STATUS_VOID(*status); + } + + //Assign Struct arrays to the new ones + event_list->event_indexes = new_event_index_array; + event_list->pulse_heights = new_pulse_height_array; + event_list->grades1 = new_grades1; + } + //Add data to lists + event_list->event_indexes[event_list->index] = index; + event_list->pulse_heights[event_list->index] = pulse_height; + event_list->grades1[event_list->index] = grade1; + + + event_list->index++; +} + + +/** TesEventFile constructor. Returns a pointer to an empty TesEventFile data + structure. */ +TesEventFile* newTesEventFile(int* const status){ + TesEventFile* file=malloc(sizeof(*file)); + if (NULL==file) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TesEventFile failed"); + return(file); + } + + // Initialize pointers with NULL. + file->fptr =NULL; + + // Initialize values. + file->row =1; + file->nrows =0; + file->timeCol =1; + file->energyCol =2; + + file->grade1Col =3; + file->grade2Col =4; + file->pixIDCol =5; + file->phIDCol =6; + file->raCol =7; + file->decCol =8; + file->detxCol =9; + file->detyCol =10; + file->gradingCol=11; + file->srcIDCol =12; + file->nxtCol =13; + file->extCol =14; + + return(file); +} + +TesEventFile* newTesEventFileSIRENA(int* const status){ + TesEventFile* file=malloc(sizeof(*file)); + if (NULL==file) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TesEventFile failed"); + return(file); + } + + // Initialize pointers with NULL. + file->fptr =NULL; + + // Initialize values. + file->row =1; + file->nrows =0; + file->timeCol =1; + file->energyCol =2; + file->avg_4samplesDerivativeCol =3; + file->E_lowresCol =4; + file->grade1Col =5; + file->grade2Col =6; + file->phiCol =7; + file->lagsShiftCol =8; + file->bslnCol =9; + file->rmsbslnCol =10; + file->pixIDCol =11; + file->phIDCol =12; + file->riseCol =13; + file->fallCol =14; + file->raCol =15; + file->decCol =16; + file->detxCol =17; + file->detyCol =18; + file->gradingCol=19; + file->srcIDCol =20; + file->nxtCol =21; + file->extCol =22; + + return(file); +} + +/** TesEventFile Destructor. */ +void freeTesEventFile(TesEventFile* file, int* const status){ + if (NULL!=file) { + if (NULL!=file->fptr) { + fits_close_file(file->fptr, status); + CHECK_STATUS_VOID(*status); + headas_chat(5, "closed TesEventFile list file\n"); + } + free(file); + file=NULL; + } +} + +/** Create and open a new TesEventFile. */ +TesEventFile* opennewTesEventFile(const char* const filename, + SixtStdKeywords* keywords, + const char clobber, + int* const status){ + TesEventFile* file = newTesEventFile(status); + CHECK_STATUS_RET(*status, file); + + int exists; + char buffer[MAXFILENAME]; + sprintf(buffer,"%s",filename); + fits_file_exists(buffer, &exists, status); + CHECK_STATUS_RET(*status,file); + if (0!=exists) { + if (0!=clobber) { + // Delete the file. + remove(buffer); + } else { + // Throw an error. + char msg[MAXMSG]; + sprintf(msg, "file '%s' already exists", buffer); + SIXT_ERROR(msg); + *status=EXIT_FAILURE; + CHECK_STATUS_RET(*status,file); + } + } + fits_create_file(&file->fptr,buffer, status); + CHECK_STATUS_RET(*status,file); + int logic=(int)'T'; + int bitpix=8; + int naxis=0; + fits_update_key(file->fptr, TLOGICAL, "SIMPLE", &(logic), NULL, status); + fits_update_key(file->fptr, TINT, "BITPIX", &(bitpix), NULL, status); + fits_update_key(file->fptr, TINT, "NAXIS", &(naxis), NULL, status); + sixt_add_fits_stdkeywords(file->fptr,1,keywords,status); + CHECK_STATUS_RET(*status,file); + + time_t rawtime; + struct tm * timeinfo; + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); + const char * chardate = asctime (timeinfo); + char keyvalstr[1000]; + strcpy(keyvalstr,chardate); + fits_write_key(file->fptr,TSTRING,"CREADATE",keyvalstr,NULL,status); + CHECK_STATUS_RET(*status,file); + + // Create table + + //first column TIME + char *ttype[]={"TIME","SIGNAL","GRADE1","GRADE2","PIXID","PH_ID","RA","DEC","DETX","DETY","GRADING","SRC_ID","N_XT","E_XT"}; + char *tform[]={"1D", "1D", "1J", "1J", "1J", "1J", "1D", "1D", "1E", "1E", "1I", "1J", "1I", "1D"}; + char *tunit[]={"s", "keV", "", "", "", "", "deg", "deg", "m", "m", "", "", "", "keV"}; + + fits_create_tbl(file->fptr, BINARY_TBL, 0, 14, ttype, tform, tunit,"EVENTS", status); + sixt_add_fits_stdkeywords(file->fptr,2,keywords,status); + CHECK_STATUS_RET(*status,file); + + int firstpix=0,lastpix=0,numberpix=0; + float monoen=-1.; + long nes_tot=0,net_tot=0; + fits_update_key(file->fptr, TINT, "FIRSTPIX", &firstpix, "First pixel in record file", status); + fits_update_key(file->fptr, TINT, "LASTPIX", &lastpix, "Last pixel in record file", status); + fits_update_key(file->fptr, TINT, "NPIX", &numberpix, "Number of pixels in record file", status); + fits_update_key(file->fptr, TFLOAT, "MONOEN", &monoen, "Monochromatic energy of photons [keV]", status); + fits_update_key(file->fptr, TLONG, "NESTOT", &nes_tot, "Total number of events simulated", status); + fits_update_key(file->fptr, TLONG, "NETTOT", &net_tot, "Total number of events actually triggered", status); + CHECK_STATUS_RET(*status,file); + + return(file); + +} + +TesEventFile* opennewTesEventFileSIRENA(const char* const filename, + SixtStdKeywords* keywords, + const char* const sirenaVersion, + const char clobber, + int* const status){ + TesEventFile* file = newTesEventFileSIRENA(status); + CHECK_STATUS_RET(*status, file); + + int exists; + char buffer[MAXFILENAME]; + sprintf(buffer,"%s",filename); + fits_file_exists(buffer, &exists, status); + CHECK_STATUS_RET(*status,file); + if (0!=exists) { + if (0!=clobber) { + // Delete the file. + remove(buffer); + } else { + // Throw an error. + char msg[MAXMSG]; + sprintf(msg, "file '%s' already exists", buffer); + SIXT_ERROR(msg); + *status=EXIT_FAILURE; + CHECK_STATUS_RET(*status,file); + } + } + fits_create_file(&file->fptr,buffer, status); + CHECK_STATUS_RET(*status,file); + int logic=(int)'T'; + int bitpix=8; + int naxis=0; + fits_update_key(file->fptr, TLOGICAL, "SIMPLE", &(logic), NULL, status); + fits_update_key(file->fptr, TINT, "BITPIX", &(bitpix), NULL, status); + fits_update_key(file->fptr, TINT, "NAXIS", &(naxis), NULL, status); + sixt_add_fits_stdkeywords(file->fptr,1,keywords,status); + CHECK_STATUS_RET(*status,file); + + time_t rawtime; + struct tm * timeinfo; + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); + const char * chardate = asctime (timeinfo); + char keyvalstr[1000]; + strcpy(keyvalstr,chardate); + fits_write_key(file->fptr,TSTRING,"CREADATE",keyvalstr,NULL,status); + CHECK_STATUS_RET(*status,file); + + fits_write_key(file->fptr,TSTRING,"SIRENAV",sirenaVersion,NULL,status); + CHECK_STATUS_RET(*status,file); + + // Create table + + //first column TIME + char *ttype[]={"TIME","SIGNAL","AVG4SD","ELOWRES","GRADE1","GRADE2","PHI","LAGS","BSLN","RMSBSLN","PIXID","PH_ID","RISETIME","FALLTIME","RA","DEC","DETX","DETY","GRADING","SRC_ID","N_XT","E_XT"}; + char *tform[]={"1D", "1D", "1D", "1D", "1J", "1J", "1D", "1J", "1D", "1D", "1J", "3J", "1D", "1D", "1D", "1D", "1E", "1E", "1I", "1J", "1I", "1D"}; + char *tunit[]={"s", "keV", "", "keV", "", "", "", "", "", "", "", "", "s", "s", "deg", "deg", "m", "m", "", "", "", "keV"}; + + fits_create_tbl(file->fptr, BINARY_TBL, 0, 22, ttype, tform, tunit,"EVENTS", status); + sixt_add_fits_stdkeywords(file->fptr,2,keywords,status); + CHECK_STATUS_RET(*status,file); + + int firstpix=0,lastpix=0,numberpix=0; + float monoen=-1.; + long nes_tot=0,net_tot=0; + fits_update_key(file->fptr, TINT, "FIRSTPIX", &firstpix, "First pixel in record file", status); + fits_update_key(file->fptr, TINT, "LASTPIX", &lastpix, "Last pixel in record file", status); + fits_update_key(file->fptr, TINT, "NPIX", &numberpix, "Number of pixels in record file", status); + fits_update_key(file->fptr, TFLOAT, "MONOEN", &monoen, "Monochromatic energy of photons [keV]", status); + fits_update_key(file->fptr, TLONG, "NESTOT", &nes_tot, "Total number of events simulated", status); + fits_update_key(file->fptr, TLONG, "NETTOT", &net_tot, "Total number of events actually triggered", status); + CHECK_STATUS_RET(*status,file); + + return(file); + +} + +static int getColnumIfExists(fitsfile *fptr, int casesen, char* template, int* const status) { + int colnum = 0; + fits_get_colnum(fptr, casesen, template, &colnum, status); + if (*status == COL_NOT_FOUND) { + *status = 0; + return -1; + } + + return colnum; +} + +/** Opens a TES event file with the given mode */ +TesEventFile* openTesEventFile(const char* const filename,const int mode, int* const status){ + TesEventFile * file = newTesEventFile(status); + headas_chat(3, "open TES event file '%s' ...\n", filename); + fits_open_table(&file->fptr, filename, mode, status); + CHECK_STATUS_RET(*status, NULL); + + // Determine the row numbers. + fits_get_num_rows(file->fptr, &(file->nrows), status); + + // Determine the column numbers. + file->timeCol = getColnumIfExists(file->fptr, CASEINSEN, "TIME", status); + file->energyCol = getColnumIfExists(file->fptr, CASEINSEN, "SIGNAL", status); + file->grade1Col = getColnumIfExists(file->fptr, CASEINSEN, "GRADE1", status); + file->grade2Col = getColnumIfExists(file->fptr, CASEINSEN, "GRADE2", status); + file->pixIDCol = getColnumIfExists(file->fptr, CASEINSEN, "PIXID", status); + file->phIDCol = getColnumIfExists(file->fptr, CASEINSEN, "PH_ID", status); + file->raCol = getColnumIfExists(file->fptr, CASEINSEN, "RA", status); + file->decCol = getColnumIfExists(file->fptr, CASEINSEN, "DEC", status); + file->detxCol = getColnumIfExists(file->fptr, CASEINSEN, "DETX", status); + file->detyCol = getColnumIfExists(file->fptr, CASEINSEN, "DETY", status); + file->gradingCol = getColnumIfExists(file->fptr, CASEINSEN, "GRADING", status); + file->srcIDCol = getColnumIfExists(file->fptr, CASEINSEN, "SRC_ID", status); + file->nxtCol = getColnumIfExists(file->fptr, CASEINSEN, "N_XT", status); + file->extCol = getColnumIfExists(file->fptr, CASEINSEN, "E_XT", status); + + CHECK_STATUS_RET(*status, NULL); + + return(file); +} + +/** Adds the data contained in the event list to the given file */ +void saveEventListToFile(TesEventFile* file,TesEventList * event_list, + double start_time,double delta_t,long pixID,int* const status){ + //Save time, PIXID and dummy grading column + double time; + int dummy_grading = 0; + for (int i = 0 ; iindex ; i++){ + time = start_time + delta_t*event_list->event_indexes[i]; + fits_write_col(file->fptr, TDOUBLE, file->timeCol, + file->row, 1, 1, &time, status); + //fits_write_col(file->fptr, TLONG, file->pixIDCol, + // file->row, 1, 1, &pixID, status); + fits_write_col(file->fptr, TINT, file->pixIDCol, + file->row, 1, 1, &event_list->pix_ids[i], status); + fits_write_col(file->fptr, TINT, file->gradingCol, + file->row, 1, 1, &dummy_grading, status); + CHECK_STATUS_VOID(*status); + file->row++; + } + file->row = file->row - event_list->index; + CHECK_STATUS_VOID(*status); + + //Save energy column + fits_write_col(file->fptr, TDOUBLE, file->energyCol, + file->row, 1, event_list->index, event_list->energies, status); + CHECK_STATUS_VOID(*status); + + /*//Save grading (GRADING) column + fits_write_col(file->fptr, TINT, file->gradingCol, + file->row, 1, event_list->index, event_list->grading, status); + CHECK_STATUS_VOID(*status);*/ + + //Save grade1 column + fits_write_col(file->fptr, TINT, file->grade1Col, + file->row, 1, event_list->index, event_list->grades1, status); + CHECK_STATUS_VOID(*status); + + //Save grade2 column + fits_write_col(file->fptr, TINT, file->grade2Col, + file->row, 1, event_list->index, event_list->grades2, status); + CHECK_STATUS_VOID(*status); + + //If PH_ID was computed, save it + if(NULL!=event_list->ph_ids){ + fits_write_col(file->fptr, TLONG, file->phIDCol, + file->row, 1, event_list->index, event_list->ph_ids, status); + CHECK_STATUS_VOID(*status); + } + + file->row = file->row + event_list->index; + file->nrows+= event_list->index; +} + +/** Adds the data contained in the event list to the given file */ +void saveEventListToFileSIRENA(TesEventFile* file,TesEventList * event_list, + double start_time,double delta_t,long pixID,int* const status){ + //Save time, PIXID and dummy grading column + double time; + int dummy_grading = 0; + for (int i = 0 ; iindex ; i++){ + time = start_time + delta_t*event_list->event_indexes[i]; + fits_write_col(file->fptr, TDOUBLE, file->timeCol, + file->row, 1, 1, &time, status); + //fits_write_col(file->fptr, TLONG, file->pixIDCol, + // file->row, 1, 1, &pixID, status); + fits_write_col(file->fptr, TINT, file->pixIDCol, + file->row, 1, 1, &event_list->pix_ids[i], status); + fits_write_col(file->fptr, TINT, file->gradingCol, + file->row, 1, 1, &dummy_grading, status); + CHECK_STATUS_VOID(*status); + file->row++; + } + file->row = file->row - event_list->index; + CHECK_STATUS_VOID(*status); + + //Save energy column + fits_write_col(file->fptr, TDOUBLE, file->energyCol, + file->row, 1, event_list->index, event_list->energies, status); + CHECK_STATUS_VOID(*status); + + //Save avgs_4samplesDerivative (AVG4SD) column + fits_write_col(file->fptr, TDOUBLE, file->avg_4samplesDerivativeCol, + file->row, 1, event_list->index, event_list->avgs_4samplesDerivative, status); + CHECK_STATUS_VOID(*status); + + //Save Es_lowres (ELOWRES) column + fits_write_col(file->fptr, TDOUBLE, file->E_lowresCol, + file->row, 1, event_list->index, event_list->Es_lowres, status); + CHECK_STATUS_VOID(*status); + + //Save phis (PHI) column + fits_write_col(file->fptr, TDOUBLE, file->phiCol, + file->row, 1, event_list->index, event_list->phis, status); + CHECK_STATUS_VOID(*status); + + //Save lagsShifts (LAGS) column + fits_write_col(file->fptr, TINT, file->lagsShiftCol, + file->row, 1, event_list->index, event_list->lagsShifts, status); + CHECK_STATUS_VOID(*status); + + //Save bsln (BSLN) column + fits_write_col(file->fptr, TDOUBLE, file->bslnCol, + file->row, 1, event_list->index, event_list->bsln, status); + CHECK_STATUS_VOID(*status); + + //Save rmsbsln (RMSBSLN) column + fits_write_col(file->fptr, TDOUBLE, file->rmsbslnCol, + file->row, 1, event_list->index, event_list->rmsbsln, status); + CHECK_STATUS_VOID(*status); + + //Save grading (GRADING) column + fits_write_col(file->fptr, TINT, file->gradingCol, + file->row, 1, event_list->index, event_list->grading, status); + CHECK_STATUS_VOID(*status); + + //Save grade1 column + fits_write_col(file->fptr, TINT, file->grade1Col, + file->row, 1, event_list->index, event_list->grades1, status); + CHECK_STATUS_VOID(*status); + + //Save grade2 column + fits_write_col(file->fptr, TINT, file->grade2Col, + file->row, 1, event_list->index, event_list->grades2, status); + CHECK_STATUS_VOID(*status); + + //If PH_ID was computed, save it + /*if(NULL!=event_list->ph_ids){ + fits_write_col(file->fptr, TLONG, file->phIDCol, + file->row, 1, event_list->index, event_list->ph_ids, status); + CHECK_STATUS_VOID(*status); + }*/ + //If PH_ID was computed, save it + if((NULL!=event_list->ph_ids) && (event_list->ph_ids == 0)){ + fits_write_col(file->fptr, TLONG, file->phIDCol, + file->row, 1, event_list->index, event_list->ph_ids, status); + CHECK_STATUS_VOID(*status); + } + else if ((NULL!=event_list->ph_ids) && (event_list->ph_ids != 0)){ + int dimPH_ID = 3; // Length of the PH_ID column + int *buffer = (int *) malloc(event_list->index*dimPH_ID*sizeof(int)); + for (int i=0;iindex;i++) + { + buffer[0+i*dimPH_ID] = event_list->ph_ids[i]; + buffer[1+i*dimPH_ID] = event_list->ph_ids2[i]; + buffer[2+i*dimPH_ID] = event_list->ph_ids3[i]; + } + + fits_write_col(file->fptr, TINT, file->phIDCol, + file->row, 1,event_list->index*3, buffer, status); // Be careful TINT or TLONG!!! + free(buffer); + } + + file->row = file->row + event_list->index; + file->nrows+= event_list->index; +} + +/** Updates the RA, DEC and DETX/Y columns with the given coordinates */ +void updateRaDecDetXY(TesEventFile* file,double ra, double dec, float detx,float dety,int* const status){ + double dbuffer=ra*180./M_PI; + fits_write_col(file->fptr, TDOUBLE, file->raCol, + file->row, 1, 1,&dbuffer, status); + CHECK_STATUS_VOID(*status); + dbuffer=dec*180./M_PI; + fits_write_col(file->fptr, TDOUBLE, file->decCol, + file->row, 1, 1,&dbuffer, status); + CHECK_STATUS_VOID(*status); + fits_write_col(file->fptr, TFLOAT, file->detxCol, + file->row, 1, 1,&detx, status); + CHECK_STATUS_VOID(*status); + fits_write_col(file->fptr, TFLOAT, file->detyCol, + file->row, 1, 1,&dety, status); + CHECK_STATUS_VOID(*status); +} + +/** Add event as reconstructed with the RMF method */ +void addRMFImpact(TesEventFile* file,PixImpact * impact,int grade1,int grade2,int grading,int n_xt,double e_xt,int* const status){ + //Save time column + fits_write_col(file->fptr, TDOUBLE, file->timeCol, + file->row, 1, 1, &(impact->time), status); + CHECK_STATUS_VOID(*status); + + //Save energy column + double energy = (double)impact->energy; + fits_write_col(file->fptr, TDOUBLE, file->energyCol, + file->row, 1, 1, &energy, status); + CHECK_STATUS_VOID(*status); + + //Save grade1 column + if (file->grade1Col!=-1) { + fits_write_col(file->fptr, TLONG, file->grade1Col, + file->row, 1, 1, &grade1, status); + CHECK_STATUS_VOID(*status); + } + + //Save grade2 column + if (file->grade2Col!=-1) { + fits_write_col(file->fptr, TLONG, file->grade2Col, + file->row, 1, 1, &grade2, status); + CHECK_STATUS_VOID(*status); + } + + //Save grading column + if (file->gradingCol!=-1) { + fits_write_col(file->fptr, TINT, file->gradingCol, + file->row, 1, 1, &grading, status); + CHECK_STATUS_VOID(*status); + } + + //Save PIXID column + long pixID = impact->pixID+1; + fits_write_col(file->fptr, TLONG, file->pixIDCol, + file->row, 1, 1, &pixID, status); + CHECK_STATUS_VOID(*status); + + //Save PH_ID column + fits_write_col(file->fptr, TLONG, file->phIDCol, + file->row, 1, 1, &(impact->ph_id), status); + CHECK_STATUS_VOID(*status); + + //Save SRC_ID column + if (file->srcIDCol!=-1) { + fits_write_col(file->fptr, TINT, file->srcIDCol, + file->row, 1, 1, &(impact->src_id), status); + CHECK_STATUS_VOID(*status); + } + + //Save N_XT and E_XT columns + fits_write_col(file->fptr, TINT, file->nxtCol, + file->row, 1, 1, &n_xt, status); + fits_write_col(file->fptr, TDOUBLE, file->extCol, + file->row, 1, 1, &e_xt, status); + CHECK_STATUS_VOID(*status); + + + file->row++; + file->nrows++; +} + +/** Adds an event whose signal as not been evaluated yet (necessity in order to keep causality in event file) */ +void addEmptyEvent(TesEventFile* file,PixImpact* impact, int* const status){ + //Save time column + fits_write_col(file->fptr, TDOUBLE, file->timeCol, + file->row, 1, 1, &(impact->time), status); + CHECK_STATUS_VOID(*status); + + //Save PIXID column + long pixID = impact->pixID+1; + fits_write_col(file->fptr, TLONG, file->pixIDCol, + file->row, 1, 1, &pixID, status); + CHECK_STATUS_VOID(*status); + + //Save PH_ID column + fits_write_col(file->fptr, TLONG, file->phIDCol, + file->row, 1, 1, &(impact->ph_id), status); + CHECK_STATUS_VOID(*status); + + //Save SRC_ID column + fits_write_col(file->fptr, TINT, file->srcIDCol, + file->row, 1, 1, &(impact->src_id), status); + CHECK_STATUS_VOID(*status); + file->row++; + file->nrows++; +} + +/** Update signal and grading columns of an event */ +void updateSignal(TesEventFile* file,long row,double energy,long grade1,long grade2,int grading,int n_xt,double e_xt,int* const status){ + //Save energy column + fits_write_col(file->fptr, TDOUBLE, file->energyCol, + row, 1, 1, &energy, status); + CHECK_STATUS_VOID(*status); + + //Save grade1 column + fits_write_col(file->fptr, TLONG, file->grade1Col, + row, 1, 1, &grade1, status); + CHECK_STATUS_VOID(*status); + + //Save grade2 column + fits_write_col(file->fptr, TLONG, file->grade2Col, + row, 1, 1, &grade2, status); + CHECK_STATUS_VOID(*status); + + //Save grading column + fits_write_col(file->fptr, TINT, file->gradingCol, + row, 1, 1, &grading, status); + CHECK_STATUS_VOID(*status); + + //Save N_XT and E_XT columns + fits_write_col(file->fptr, TINT, file->nxtCol, + row, 1, 1, &n_xt, status); + CHECK_STATUS_VOID(*status); + + fits_write_col(file->fptr, TDOUBLE, file->extCol, + row, 1, 1, &e_xt, status); + CHECK_STATUS_VOID(*status); +} diff --git a/libsixt/teseventlist.h b/libsixt/teseventlist.h new file mode 100644 index 0000000..c12f517 --- /dev/null +++ b/libsixt/teseventlist.h @@ -0,0 +1,185 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2015 Philippe Peille, IRAP +*/ + +#ifndef TESEVENTLIST_H +#define TESEVENTLIST_H 1 + +#include "sixt.h" +#include "pixelimpact.h" + +//////////////////////////////////////////////////////////////////////// +// Type declarations. +//////////////////////////////////////////////////////////////////////// + +typedef struct { + /** Current size of the list */ + int size; + + /** Current size of the energy/grade lists */ + int size_energy; + + /** Current end index of the list */ + int index; + + /** Index arrival time of the photons inside a record */ + + //int * event_indexes; + double * event_indexes; //SIRENA + + /** Pulse height of the photons */ + double * pulse_heights; + + /** Average of the first 4 samples of the derivative of the event (pulse) */ + double * avgs_4samplesDerivative; //SIRENA + + /** Low resolution energy estimator (4 samples-long filter) */ + double * Es_lowres; //SIRENA + + /** Offset relative to the central point of the parabola */ + double * phis; //SIRENA + + /** Number of samples shifted to find the maximum of the parabola */ + int * lagsShifts; //SIRENA + + /** Baseline calculated just previously to the pulse (in general)(see 'getB') */ + double * bsln; //SIRENA + + /** Rms of the baseline calculated just previously to the pulse (in general)(see 'getB') */ + double * rmsbsln; //SIRENA + + /** Pulse grade */ + int * grading; //SIRENA + + /** Energy of the photons */ + double * energies; + + /** Grade 1: length of the filter used during the reconstruction */ + int * grades1; + + /** Grade 2: distance in samples to the previous pulse */ + int * grades2; + + /** PH_ID of the reconstructed photons */ + long * ph_ids; + long * ph_ids2; + long * ph_ids3; + + /** PIX_ID of the reconstructed photons */ + long * pix_ids; + + /** Tstart of the reconstructed photons (in time) */ + double * tstarts; + + /** Tend of the reconstructed photons (in time) */ + double * tends; + + /** Rise time of the reconstructed photons (in time) */ + double * risetimes; + + /** Fall time of the reconstructed photons (in time) */ + double * falltimes; + +} TesEventList; + +typedef struct { + /** Pointer to the FITS file. */ + fitsfile* fptr; + + /** Number of the current row in the FITS file. The numbering + starts at 1 for the first line. If row is equal to 0, no row + has been read or written so far. */ + long row; + + /** Total number of rows */ + long nrows; + + /** Column numbers for time, energy, grade1, grade2, pixID, RA and DEC columns */ + int timeCol,energyCol,avg_4samplesDerivativeCol,E_lowresCol,grade1Col,grade2Col,phiCol,lagsShiftCol,bslnCol,rmsbslnCol,pixIDCol,riseCol,fallCol,phIDCol,raCol,decCol,detxCol,detyCol,gradingCol,srcIDCol,nxtCol,extCol; //SIRENA + +} TesEventFile; + +//////////////////////////////////////////////////////////////////////// +// Function declarations. +//////////////////////////////////////////////////////////////////////// + +/** TesEventList constructor. Returns a pointer to an empty TesEventList data + structure. */ +TesEventList* newTesEventList(int* const status); +TesEventList* newTesEventListSIRENA(int* const status); + +/** TesEventList Destructor. */ +void freeTesEventList(TesEventList* event_list); +void freeTesEventListSIRENA(TesEventList* event_list); + +/** Allocates memory for a TesEventList structure for the triggering stage: + * only event_index, pulse_height and grades1 */ +void allocateTesEventListTrigger(TesEventList* event_list,int size,int* const status); + +/** Allocates memory for the energy and grade2 arrays according to + * current size if necessary. Only allocate ph_id if specified */ +void allocateWholeTesEventList(TesEventList* event_list,unsigned char allocate_ph,int* const status); + +/** Appends the index and pulse_height lists to the list */ +void addEventToList(TesEventList* event_list,int index,double pulse_height,int grade1,int* const status); + + +/** TesEventFile constructor. Returns a pointer to an empty TesEventFile data + structure. */ +TesEventFile* newTesEventFile(int* const status); +TesEventFile* newTesEventFileSIRENA(int* const status); + +/** Create and open a new TesEventFile. */ +TesEventFile* opennewTesEventFile(const char* const filename, + SixtStdKeywords* keywords, + const char clobber, + int* const status); + +TesEventFile* opennewTesEventFileSIRENA(const char* const filename, + SixtStdKeywords* keywords, + const char* const sirenaVersion, + const char clobber, + int* const status); + +/** Opens a TES event file with the given mode */ +TesEventFile* openTesEventFile(const char* const filename,const int mode, int* const status); + +/** TesEventFile Destructor. */ +void freeTesEventFile(TesEventFile* file, int* const status); + +/** Adds the data contained in the event list to the given file */ +void saveEventListToFile(TesEventFile* file,TesEventList * event_list, + double start_time,double delta_t,long pixID,int* const status); +void saveEventListToFileSIRENA(TesEventFile* file,TesEventList * event_list, + double start_time,double delta_t,long pixID,int* const status); + +/** Updates the RA, DEC and DETX/Y columns with the given coordinates */ +void updateRaDecDetXY(TesEventFile* file,double ra, double dec, float detx,float dety,int* const status); + +/** Add event as reconstructed with the RMF method */ +void addRMFImpact(TesEventFile* file,PixImpact * impact,int grade1,int grade2,int grading,int n_xt,double e_xt,int* const status); + +/** Adds an event whose signal as not been evaluated yet (necessity in order to keep causality in event file) */ +void addEmptyEvent(TesEventFile* file,PixImpact* impact, int* const status); + +/** Update signal and grading columns of an event */ +//void updateSignal(TesEventFile* file,long row,double energy,double avg_4samplesDerivative,long grade1,long grade2,int grading,int n_xt,double e_xt,int* const status); +void updateSignal(TesEventFile* file,long row,double energy,long grade1,long grade2,int grading,int n_xt,double e_xt,int* const status); + +#endif /* TESEVENTLIST_H */ diff --git a/libsixt/tesrecord.c b/libsixt/tesrecord.c new file mode 100644 index 0000000..287bf8f --- /dev/null +++ b/libsixt/tesrecord.c @@ -0,0 +1,202 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2015 Philippe Peille, IRAP + Copyright 2016-2019 Remeis-Sternwarte, Friedrich-Alexander-Universitaet + Erlangen-Nuernberg +*/ + +#include "tesrecord.h" + +/** Constructor. Returns a pointer to an empty RecordStruct data + structure. */ +TesRecord* newTesRecord(int* const status){ + CHECK_STATUS_RET(*status,NULL); + TesRecord* record=malloc(sizeof(TesRecord)); + if (NULL==record) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TesRecord failed"); + return(NULL); // yes, we could return record here, but best be obvious + } + // Initialize pointers with NULL. + record->adc_array = NULL; + record->adc_double = NULL; + record->phid_list = NULL; + record->error_double = NULL; + + // Initialize values. + record->trigger_size =0; + record->time =0; + record->pixid =0; + + return(record); +} + +/** Allocate memory for a RecordStruct data */ +void allocateTesRecord(TesRecord * record,unsigned long triggerSize,double delta_t,unsigned char wait_list,int* const status){ + record->trigger_size = triggerSize; + record->delta_t = delta_t; + + //Allocate adc_array + record->adc_array = malloc(triggerSize*sizeof(*(record->adc_array))); + CHECK_NULL_VOID(record->adc_array,*status,"allocateTesRecord: adc_array: memory allocation failed"); + //Allocate adc_double + record->adc_double = malloc(triggerSize*sizeof(*(record->adc_double))); + CHECK_NULL_VOID(record->adc_array,*status,"allocateTesRecord: adc_double: memory allocation failed"); + + //Allocate error_double + record->error_double = malloc(triggerSize*sizeof(*(record->error_double))); + CHECK_NULL_VOID(record->adc_array,*status,"allocateTesRecord: error_double: memory allocation failed"); + + //Allocate phid_list + record->phid_list = newAllocatedPhIDList(MAXIMPACTNUMBER,wait_list,status); + CHECK_STATUS_VOID(*status); + +} + +// useful routine to generate a new tes record in one step +TesRecord *createTesRecord(unsigned long triggerSize,double delta_t,unsigned char wait_list,int* const status){ + TesRecord *record=newTesRecord(status); + CHECK_STATUS_RET(*status,NULL); + allocateTesRecord(record,triggerSize,delta_t,wait_list,status); + CHECK_STATUS_RET(*status,NULL); + return record; +} + + +/** Change the record length of a tes record **/ +void resizeTesRecord(TesRecord *record,unsigned long triggerSize, int* const status) { + CHECK_STATUS_VOID(*status); + + // reallocate the buffers + // note: since a tes record has no concept of how full it is, + // this can destroy data! + uint16_t* new_adc=realloc(record->adc_array,triggerSize*sizeof(uint16_t)); + CHECK_NULL_VOID(new_adc,*status,"Cannot reallocate ADC array"); + double *new_doub=realloc(record->adc_double,triggerSize*sizeof(double)); + CHECK_NULL_VOID(new_doub,*status,"Cannot reallocate ADC double array"); + double *new_err=realloc(record->error_double,triggerSize*sizeof(double)); + CHECK_NULL_VOID(new_err,*status,"Cannot reallocate ADC double array"); + + record->adc_array=new_adc; + record->adc_double=new_doub; + record->error_double=new_err; + record->trigger_size=triggerSize; +} + + +/** Destructor of the RecordStruct data structure. */ +void freeTesRecord(TesRecord** const record){ + if (*record!=NULL){ + free((*record)->adc_double); + free((*record)->adc_array); + free((*record)->error_double); + freePhIDList((*record)->phid_list); + free(*record); + *record = NULL; + } +} + +/** Constructor and allocater. Returns a pointer to an allocated PHIDList data + structure. */ +PhIDList* newAllocatedPhIDList(int size,unsigned char wait_list,int* const status){ + PhIDList* phid_list=malloc(sizeof(*phid_list)); + if (NULL==phid_list) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for PhIDList failed"); + return(phid_list); + } + + // Allocate phid_list. + phid_list->phid_array = malloc(size*sizeof(*(phid_list->phid_array))); + if (NULL==phid_list->phid_array) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for PhIDList failed"); + return(phid_list); + } + + //Allocate time array if this is a wait_list + if(wait_list){ + phid_list->times = malloc(size*sizeof(*(phid_list->times))); + if (NULL==phid_list->times) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for PhIDList failed"); + return(phid_list); + } + } + + // Initialize values. + phid_list->size =size; + phid_list->index =0; + phid_list->wait_list = wait_list; + phid_list->n_elements=0; + + return(phid_list); +} + +/** Destructor of the RecordStruct data structure. */ +void freePhIDList(PhIDList * list){ + if(NULL!=list){ + free(list->phid_array); + if(list->wait_list){ + free(list->times); + } + } + free(list); + list=NULL; +} + +/** Append ph_id to list */ +void appendPhID(PhIDList * const list,long ph_id,double time,int* const status){ + if(list->wait_list){ + if(list->n_elements >= list->size){ + *status=EXIT_FAILURE; + SIXT_ERROR("Number of impacts in record greater than the maximum allocated number -> abort.\nCheck your count rate or MAXIMPACTNUMBER in testriggerfile.h"); + CHECK_STATUS_VOID(*status); + } else { + list->phid_array[list->index % list->size] = ph_id; + list->times[list->index % list->size] = time; + list->index++; + list->n_elements++; + } + } else { + if(list->index >= list->size){ + *status=EXIT_FAILURE; + SIXT_ERROR("Number of impacts in record greater than the maximum allocated number -> abort.\nCheck your count rate or MAXIMPACTNUMBER in testriggerfile.h"); + CHECK_STATUS_VOID(*status); + } else { + list->phid_array[list->index] = ph_id; + list->index++; + } + } +} + +/** Get first element in wait list */ +int popPhID(PhIDList * const list,long* ph_id,double* time,int* const status){ + if(!(list->wait_list)){ + *status=EXIT_FAILURE; + SIXT_ERROR("Pop function only defined for wait list"); + CHECK_STATUS_RET(*status,0); + } + if(list->n_elements==0){ + return(0); + } + *ph_id = list->phid_array[(list->index-list->n_elements) % list->size]; + *time = list->times[(list->index-list->n_elements) % list->size]; + list->n_elements--; + return(1); +} diff --git a/libsixt/tesrecord.h b/libsixt/tesrecord.h new file mode 100644 index 0000000..928f915 --- /dev/null +++ b/libsixt/tesrecord.h @@ -0,0 +1,124 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2015 Philippe Peille, IRAP + Copyright 2016-2019 Remeis-Sternwarte, Friedrich-Alexander-Universitaet + Erlangen-Nuernberg +*/ + +#ifndef TESRECORD_H +#define TESRECORD_H 1 + +#include "sixt.h" + +//////////////////////////////////////////////////////////////////////// +// Constants. +//////////////////////////////////////////////////////////////////////// + +/** Maximum number of impacts per trigger. */ +#define MAXIMPACTNUMBER (50000) + +//////////////////////////////////////////////////////////////////////// +// Type declarations. +//////////////////////////////////////////////////////////////////////// + +typedef struct{ + /** Array containing the phIDs */ + long* phid_array; + + /** Array containing the corresponding impact times (only relevant in case of wait list) */ + double* times; + + /** Boolean to state if this should be a wait list */ + unsigned char wait_list; + + /** Number of elements in the wait list */ + int n_elements; + + /** Current index in the list */ + int index; + + /** Size of the list */ + int size; +}PhIDList; + +typedef struct{ + /** Number of ADC values in the record */ + unsigned long trigger_size; + + /** Start time of the record */ + double time; + + /** Time difference between two samples */ + double delta_t; + + /** Buffer to read a record of ADC values */ + uint16_t* adc_array; + + /** Double version of the record */ + double* adc_double; + + /** Error signal */ + double* error_double; + + /** EXTEND of the record */ + long extend; + + /** PIXID of the record */ + long pixid; + + /** Array of the PH_ID in the record */ + PhIDList* phid_list; + +}TesRecord; + + +//////////////////////////////////////////////////////////////////////// +// Function declarations. +//////////////////////////////////////////////////////////////////////// + +/** Constructor. Returns a pointer to an empty RecordStruct data + structure. */ +TesRecord* newTesRecord(int* const status); + +/** Allocates memory for a RecordStruct data */ +void allocateTesRecord(TesRecord * record,unsigned long triggerSize,double delta_t,unsigned char wait_list,int* const status); + +TesRecord *createTesRecord(unsigned long triggerSize,double delta_t,unsigned char wait_list,int* const status); + +/** resizes the TesRecord **/ +void resizeTesRecord(TesRecord *record,unsigned long triggerSize, int* const status); + +/** Destructor of the RecordStruct data structure. */ +void freeTesRecord(TesRecord** const record); + + +/** Constructor and allocater. Returns a pointer to an allocated PHIDList data + structure. */ +PhIDList* newAllocatedPhIDList(int size,unsigned char wait_list,int* const status); + +/** Destructor of the RecordStruct data structure. */ +void freePhIDList(PhIDList * list); + +/** Append ph_id to list */ +void appendPhID(PhIDList * const list,long ph_id,double time,int* const status); + +/** Get first element in wait list */ +int popPhID(PhIDList * const list,long* ph_id,double* time,int* const status); + + +#endif /* TESRECORD_H */ diff --git a/libsixt/testriggerfile.c b/libsixt/testriggerfile.c new file mode 100644 index 0000000..1679547 --- /dev/null +++ b/libsixt/testriggerfile.c @@ -0,0 +1,607 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2014 Philippe Peille, IRAP +*/ + +#include "testriggerfile.h" + +/** Constructor. Returns a pointer to an empty TesTriggerFile data + structure. */ +TesTriggerFile* newTesTriggerFile(unsigned long triggerSize,int write_doubles, int* const status) { + TesTriggerFile* file=(TesTriggerFile*)malloc(sizeof(TesTriggerFile)); + if (NULL==file) { + *status=EXIT_FAILURE; + SIXT_ERROR("memory allocation for TesTriggerFile failed"); + return(file); + } + + // Initialize pointers with NULL. + file->fptr =NULL; + + // Initialize values. + file->nrows =0; + file->row =1; + file->rowbuffer =0; + file->timeCol =1; + file->trigCol =2; + file->extendCol =3; + file->pixIDCol =4; + file->ph_idCol =5; + file->trigger_size =triggerSize; + file->delta_t=0; + file->write_doubles = write_doubles; + + return(file); +} + +/** Destructor. */ +void freeTesTriggerFile(TesTriggerFile** const file, int* const status){ + if (NULL!=*file) { + if (NULL!=(*file)->fptr) { + // delete superfluous rows + if ((*file)->rowbuffer!=0){ + if ((*file)->nrows==0){ + // TODO Understand why this works + // deleting all rows without writing at least once leads to error code 107, + // which is "tried to move past end of file" + int garbage = 1; + fits_write_col((*file)->fptr, TLONG, (*file)->pixIDCol, (*file)->row, 1, 1, &garbage, status); + + fits_delete_rows((*file)->fptr, 1, TESTRIGGERFILE_ROWBUFFERSIZE, status); + } else { + fits_delete_rows((*file)->fptr, (*file)->nrows+1, (*file)->rowbuffer, status); + } + } + + fits_close_file_chksum((*file)->fptr, status); + headas_chat(5, "closed TesStream list file (containing %ld rows).\n", + (*file)->nrows); + } + + (*file)->nrows =0; + (*file)->row =0; + (*file)->rowbuffer =0; + (*file)->timeCol =0; + (*file)->trigCol =0; + (*file)->extendCol =0; + (*file)->ph_idCol =0; + (*file)->pixIDCol =0; + + free(*file); + *file=NULL; + } +} + +/** Create and open a new TesTriggerFile. */ +TesTriggerFile* opennewTesTriggerFile(const char* const filename, + SixtStdKeywords * keywords, + char* const xmlfile, + char* const impactlist, + unsigned long triggerSize, + int preBufferSize, + double sampleFreq, + int write_doubles, + const char clobber, + int* const status){ + + TesTriggerFile* file = newTesTriggerFile(triggerSize,write_doubles,status); + CHECK_STATUS_RET(*status, NULL); + + char buffer[FLEN_FILENAME]; + strncpy(buffer,filename,FLEN_FILENAME); + buffer[FLEN_FILENAME-1]='\0'; + + fits_create_file_clobber(&file->fptr,buffer,clobber,status); + CHECK_STATUS_RET(*status,NULL); + + int logic=TRUE; + int bitpix=8; + int naxis=0; + fits_update_key(file->fptr, TLOGICAL, "SIMPLE", &logic, NULL, status); + fits_update_key(file->fptr, TINT, "BITPIX", &bitpix, NULL, status); + fits_update_key(file->fptr, TINT, "NAXIS", &naxis, NULL, status); + + + sixt_add_fits_stdkeywords(file->fptr, 1,keywords, status); + fits_update_key(file->fptr, TULONG, "TRIGGSZ", &triggerSize, "Number of samples in triggers", status); + fits_update_key(file->fptr, TINT, "PREBUFF", &preBufferSize, "Number of samples before start of pulse", status); + double deltat = 1./sampleFreq; + fits_update_key(file->fptr, TDOUBLE, "DELTAT", &deltat, "Time resolution of data stream", status); + + //Write XML and pixel impact filenames into header + fits_update_key(file->fptr,TSTRING,"XMLFILE",xmlfile,NULL,status); + fits_update_key(file->fptr,TSTRING,"PIXFILE",impactlist,NULL,status); + CHECK_STATUS_RET(*status,NULL); + + // Create table + char *ttype[]={"TIME","ADC","EXTEND","PIXID","PH_ID"}; + char *tunit[]={"s","ADU","SAMPLES","",""}; + //char *tform[]={"1D",NULL,"1J","1PJ"}; + char *tform[]={"1D",NULL,"1J","1J","3PJ"}; + + tform[1]=malloc(FLEN_KEYWORD*sizeof(char)); + if (write_doubles){ + sprintf(tform[1], "%ldD",triggerSize); + CHECK_NULL_RET(tform[1],*status,"Memory allocation failed",NULL); + } else { + sprintf(tform[1], "%ldU",triggerSize); + CHECK_NULL_RET(tform[1],*status,"Memory allocation failed",NULL); + } + + // Include allocate a buffer of rows ahead of time + file->rowbuffer = TESTRIGGERFILE_ROWBUFFERSIZE; + + fits_create_tbl(file->fptr, BINARY_TBL, file->rowbuffer, 4, ttype, tform, tunit,"RECORDS", status); + //Add keywords to other extension + fits_update_key(file->fptr, TULONG, "TRIGGSZ", &triggerSize, "Number of samples in a standard trigger", status); + fits_update_key(file->fptr, TINT, "PREBUFF", &preBufferSize, "Number of samples before start of pulse", status); + fits_update_key(file->fptr, TDOUBLE, "DELTAT", &deltat, "Time resolution of data stream", status); + + sixt_add_fits_stdkeywords(file->fptr, 2,keywords, status); + CHECK_STATUS_RET(*status,NULL); + + int firstpix=0,lastpix=0,numberpix=0; + float monoen=-1.; + long nes_tot=0,net_tot=0; + fits_update_key(file->fptr, TINT, "FIRSTPIX", &firstpix, "First pixel in record file", status); + fits_update_key(file->fptr, TINT, "LASTPIX", &lastpix, "Last pixel in record file", status); + fits_update_key(file->fptr, TINT, "NPIX", &numberpix, "Number of pixels in record file", status); + fits_update_key(file->fptr, TFLOAT, "MONOEN", &monoen, "Monochromatic energy of photons [keV]", status); + fits_update_key(file->fptr, TLONG, "NESTOT", &nes_tot, "Total number of events simulated", status); + fits_update_key(file->fptr, TLONG, "NETTOT", &net_tot, "Total number of events actually triggered", status); + CHECK_STATUS_RET(*status,NULL); + + return(file); + +} + +/** Open an existing TesTriggerFile. */ +TesTriggerFile* openexistingTesTriggerFile(const char* const filename,SixtStdKeywords* keywords,int* const status){ + TesTriggerFile* file = newTesTriggerFile(0,0,status); + + char comment[FLEN_COMMENT]; + + //Open record file in READONLY mode + fits_open_file(&(file->fptr), filename, READONLY, status); + + int hdunum; + fits_get_num_hdus(file->fptr, &hdunum,status); + + // Check if input FITS file have been simulated with TESSIM or XIFUSIM + int tessimOrxifusim = -999; + fits_movnam_hdu(file->fptr, ANY_HDU,"RECORDS", 0, status); + if (*status != 0) + { + *status = 0; + fits_movnam_hdu(file->fptr, ANY_HDU,"TESRECORDS", 0, status); + if (*status != 0) + { + printf("%s","Cannot move to TESRECORDS HDU in input FITS file\n"); + CHECK_STATUS_RET(*status, NULL); + } + else + { + tessimOrxifusim = 1; + } + } + else + { + tessimOrxifusim = 0; + } + if (tessimOrxifusim == -999) + { + printf("%s","Neither the 'RECORDS' nor 'TESRECORDS' HDUs are in the input FITS file\n"); + CHECK_STATUS_RET(*status, NULL); + } + + //Read standard keywords + //(shouldn't we read these from the record extension?) + sixt_read_fits_stdkeywords(file->fptr,keywords,status); + + //Get number of rows + fits_read_key(file->fptr, TINT, "NAXIS2", &(file->nrows), comment, status); + + //Associate column numbers + fits_get_colnum(file->fptr, CASEINSEN,"TIME", &(file->timeCol), status); + fits_get_colnum(file->fptr, CASEINSEN,"ADC", &(file->trigCol), status); + int colnum = file->trigCol; + fits_get_colnum(file->fptr, CASEINSEN,"EXTEND", &(file->extendCol), status); + //printf("%s %d %s","statusEXTEND: ",*status,"\n"); + if (*status != 0) *status = 0; // status!=0 if no EXTEND column + + fits_get_colnum(file->fptr, CASEINSEN,"PIXID", &(file->pixIDCol), status); + fits_get_colnum(file->fptr, CASEINSEN,"PH_ID", &(file->ph_idCol), status); + CHECK_STATUS_RET(*status, NULL); + + file->delta_t = -999; + int deltat_exists = 0; + int dec_fac_exists = 0; + int tclock_exists = 0; + int numrow_exists = 0; + int p_row_exists = 0; + // To get the sampling rate no matter the origin of the file + for (int i=0;ifptr, i+1, NULL, status); + fits_read_key(file->fptr,TDOUBLE,"DELTAT", &(file->delta_t),comment,status); + if (*status == 0) + { + deltat_exists = 1; + break; + } + else if ((*status != 0) && (i <= hdunum-1)) + { + *status = 0; + } + } + //printf("%s %d %s","deltat_exists: ",deltat_exists,"\n"); + //printf("%s %f %s","file->delta_t: ",file->delta_t,"\n"); + double tclock; + if (deltat_exists == 0) + { + double dec_fac; + for (int i=0;ifptr, i+1, NULL, status); + fits_read_key(file->fptr,TDOUBLE,"DEC_FAC", &dec_fac,comment,status); + if (*status == 0) + { + dec_fac_exists = 1; + break; + } + else if ((*status != 0) && (i <= hdunum-1)) + { + *status = 0; + } + } + for (int i=0;ifptr, i+1, NULL, status); + fits_read_key(file->fptr,TDOUBLE,"TCLOCK", &tclock,comment,status); + if (*status == 0) + { + tclock_exists = 1; + break; + } + else if ((*status != 0) && (i <= hdunum-1)) + { + *status = 0; + } + } + file->delta_t = tclock*dec_fac; + //printf("%s %d %s","tclock_exists: ",tclock_exists,"\n"); + //printf("%s %d %s","dec_fac_exists: ",dec_fac_exists,"\n"); + //printf("%s %f %s","file->delta_t: ",file->delta_t,"\n"); + } + if ((deltat_exists == 0) && ((tclock_exists == 0) || (dec_fac_exists == 0))) + { + int numrow; + for (int i=0;ifptr, i+1, NULL, status); + fits_read_key(file->fptr,TINT,"NUMROW", &numrow,comment,status); + if (*status == 0) + { + numrow_exists = 1; + break; + } + else if ((*status != 0) && (i <= hdunum-1)) + { + *status = 0; + } + } + int p_row; + for (int i=0;ifptr, i+1, NULL, status); + fits_read_key(file->fptr,TINT,"P_ROW", &p_row,comment,status); + if (*status == 0) + { + p_row_exists = 1; + break; + } + else if ((*status != 0) && (i <= hdunum-1)) + { + *status = 0; + } + } + file->delta_t = tclock*numrow*p_row; + //printf("%s %d %s","numrow_exists: ",numrow_exists,"\n"); + //printf("%s %d %s","p_row_exists: ",p_row_exists,"\n"); + //printf("%s %f %s","file->delta_t: ",file->delta_t,"\n"); + } + /*if ((deltat_exists == 0) && ((dec_fac_exists == 0) || (tclock_exists == 0)) && ((numrow_exists == 0) || (p_row_exists == 0))) + { + printf("%s","Cannot read or get the sampling rate from the input file. Please, include the DELTAT keyword (inverse of sampling rate) in the input FITS file before running GENNOISESPEC again\n"); + CHECK_STATUS_RET(*status, NULL); + }*/ + + if (tessimOrxifusim == 0) //TESSIM + { + fits_movnam_hdu(file->fptr, ANY_HDU,"RECORDS", 0, status); + } + else //XIFUSIM + { + fits_movnam_hdu(file->fptr, ANY_HDU,"TESRECORDS", 0, status); + + if ((deltat_exists == 0) && ((dec_fac_exists == 0) || (tclock_exists == 0)) && ((numrow_exists == 0) || (p_row_exists == 0))) + { + file->delta_t = -999; + } + } + + // Get the trigger size + char keyname[10] = "TFORM"; + + char colnumchar[10]; + snprintf(colnumchar,10,"%d",colnum); + strcat(keyname,colnumchar); + + char readTFORMADC [10]; + fits_read_key(file->fptr,TSTRING,keyname,readTFORMADC,comment,status); + //printf("%s %s %s","TFORM2: ",readTFORMADC,"\n"); + + char * pointerTFORM; + + pointerTFORM = strstr(readTFORMADC,"("); + + if (pointerTFORM) // There is a parenthesis + { + //printf("%s","YES (\n"); + char each_character_after_paren[125]; + char characters_after_paren[125]; + + pointerTFORM = pointerTFORM + 1; // Pointer to the next character to "(" + snprintf(each_character_after_paren,125,"%c",*pointerTFORM); + snprintf(characters_after_paren,125,"%c",*pointerTFORM); + while (*pointerTFORM != ')') + { + pointerTFORM = pointerTFORM + 1; + snprintf(each_character_after_paren,125,"%c",*pointerTFORM); + strcat(characters_after_paren,each_character_after_paren); + } + file->trigger_size = atoi(characters_after_paren); + //printf("%s %d %s","eventsz: ",file->trigger_size,"\n"); + } + else // There is not a parenthesis + { + //printf("%s","NO (\n"); + + char *ptr; + long ret; + + ret = strtol(readTFORMADC, &ptr, 10); + file->trigger_size = ret; + //printf("%s %d %s","eventsz: ",file->trigger_size,"\n"); + } + + return(file); +} + +/** Populates a TesRecord structure with the next record */ +int getNextRecord(TesTriggerFile* const file,TesRecord* record,int *lastRecord,int *startRecordGroup,int* const status){ + int anynul=0; + char tform2ADC[20]; + LONGLONG rec_trigsize; + + (*lastRecord) = 0; + (*startRecordGroup) = 0; + + if (NULL==file || NULL==file->fptr) { + *status=EXIT_FAILURE; + SIXT_ERROR("No opened trigger file to read from"); + CHECK_STATUS_RET(*status,0); + } + + if (file->row<=file->nrows) { + // get length of this record + // (although unlikely, we might have a very large file, so we best + // use the LONGLONG interface to the descriptor + + // read TFORM for ADC to know if it is FIXED or VARIABLE length + fits_read_key(file->fptr,TSTRING, "TFORM2", &tform2ADC, NULL, status); + if(strstr(tform2ADC, "(") != NULL){ + LONGLONG offset; + fits_read_descriptll(file->fptr,file->trigCol,file->row,&rec_trigsize,&offset,status); + CHECK_STATUS_RET(*status,0); + + }else{ + LONGLONG col_width; + int adc_col_typecode; + fits_get_coltypell(file->fptr,file->trigCol,&adc_col_typecode, + &rec_trigsize,&col_width,status); + CHECK_STATUS_RET(*status,0); + } + + fits_read_col(file->fptr, TLONG, file->pixIDCol, + file->row,1,1,0,&(record->pixid), &anynul,status); + CHECK_STATUS_RET(*status,0); + fits_read_col(file->fptr, TDOUBLE, file->timeCol, + file->row,1,1,0,&(record->time), &anynul,status); + CHECK_STATUS_RET(*status,0); + + fits_read_col(file->fptr, TLONG, file->extendCol, + file->row,1,1,0,&(record->extend), &anynul,status); + //CHECK_STATUS_RET(*status,0); + if (*status != 0) // No EXTEND column + { + *status = 0; + //// when ADC is integer + ////fits_read_col(file->fptr, TUSHORT, file->trigCol, + //// file->row,1,record->trigger_size,0,record->adc_array, &anynul,status); + //// when ADC is DOUBLE + fits_read_col(file->fptr, TDOUBLE, file->trigCol, + file->row,1,record->trigger_size,0,record->adc_double, &anynul,status); + CHECK_STATUS_RET(*status,0); + + //// fits_read_col(file->fptr, TLONG, file->ph_idCol, + //// file->row,1,MAXIMPACTNUMBER,0,record->phid_array, &anynul,status); + //// CHECK_STATUS_RET(*status,0); + + //fits_read_col(file->fptr, TLONG, file->pixIDCol, + // file->row,1,1,0,&(record->pixid), &anynul,status); + //CHECK_STATUS_RET(*status,0); + //fits_read_col(file->fptr, TDOUBLE, file->timeCol, + // file->row,1,1,0,&(record->time), &anynul,status); + //CHECK_STATUS_RET(*status,0); + ////Changed below by MTC// for (unsigned long i=0 ; i < file->trigger_size ; i++) { + ///* Comment again because now ADC is double + // * for (unsigned long i=0 ; i < record->trigger_size ; i++) { + // * + // * record->adc_double[i]= (double) (record->adc_array[i]);} + //*/ + + fits_read_col(file->fptr, TLONG, file->ph_idCol, + file->row,1,1,0,&(record->phid_list->phid_array[0]), &anynul,status); + if (*status != 0) // Simulated files have the PH_ID column but empty + { + record->phid_list->phid_array[0] = 0; + *status = 0; + } + //CHECK_STATUS_RET(*status,0); + + (*startRecordGroup) = file->row; + + file->row++; + } + else // EXTEND column + { + // resize buffers if that is necessary + int nrowsTogether = 0; + if (record->extend == 0) + { + if (record->trigger_size!=(unsigned long) rec_trigsize) { + resizeTesRecord(record,(unsigned long) rec_trigsize,status); + CHECK_STATUS_RET(*status,0); + } + // when ADC is integer + //fits_read_col(file->fptr, TUSHORT, file->trigCol, + // file->row,1,record->trigger_size,0,record->adc_array, &anynul,status); + // when ADC is DOUBLE + fits_read_col(file->fptr, TDOUBLE, file->trigCol, + file->row,1,record->trigger_size,0,record->adc_double, &anynul,status); + CHECK_STATUS_RET(*status,0); + (*startRecordGroup) = file->row; + } + else + { + int sizeADC = record->trigger_size; + int sizeToWrite; + + int sizeLastRow = 0; + div_t nrowsTogether_div_t = div(record->trigger_size+record->extend,record->trigger_size); + nrowsTogether = nrowsTogether_div_t.quot +1; + sizeLastRow = nrowsTogether_div_t.rem; + resizeTesRecord(record,(unsigned long) record->extend + record->trigger_size,status); + double *singleRecord = NULL; + int rowToRead = file->row; + int index = 0; + (*startRecordGroup) = file->row; + for (int i=0;ifptr, TUSHORT, file->trigCol, + // file->row,1,record->trigger_size,0,record->adc_array, &anynul,status); + // when ADC is DOUBLE + fits_read_col(file->fptr, TDOUBLE, file->trigCol, + rowToRead,1,sizeADC,0,singleRecord, &anynul,status); + CHECK_STATUS_RET(*status,0); + + if (i != nrowsTogether-1) + { + sizeToWrite = sizeADC; + } + else + { + sizeToWrite = sizeLastRow; + } + for (int j=0;jadc_double[j+index] = singleRecord[j]; + } + free(singleRecord); + index = index + sizeADC; + rowToRead++; + } + } + + + /*fits_read_col(file->fptr, TDOUBLE, file->timeCol, + file->row,1,1,0,&(record->time), &anynul,status); + CHECK_STATUS_RET(*status,0); + //Changed below by MTC// for (unsigned long i=0 ; i < file->trigger_size ; i++) { + //Comment again because now ADC is double + // for (unsigned long i=0 ; i < record->trigger_size ; i++) { + // + // record->adc_double[i]= (double) (record->adc_array[i]);} + // + */ + + free(record->phid_list->phid_array); + record->phid_list->phid_array = malloc(3*sizeof(*(record->phid_list->phid_array))); + fits_read_col(file->fptr, TLONG, file->ph_idCol, + file->row,1,3,0,record->phid_list->phid_array, &anynul,status); + CHECK_STATUS_RET(*status,0); + + if (record->extend == 0) + { + file->row++; + } + else + { + file->row = file->row + nrowsTogether; + } + } + + if (file->row>file->nrows) (*lastRecord) = 1; + + return(1); + } else { + return(0); + } +} + +/** Writes a record to a file */ +void writeRecord(TesTriggerFile* outputFile,TesRecord* record,int* const status){ + // if we've run out of buffer, extend the table + if (outputFile->rowbuffer==0){ + // extend to 1.5 of previous length + outputFile->rowbuffer = (long) outputFile->nrows/2; + fits_insert_rows(outputFile->fptr, outputFile->nrows, outputFile->rowbuffer, status); + } + + // write values + fits_write_col(outputFile->fptr, TDOUBLE, outputFile->timeCol, + outputFile->row, 1, 1, &(record->time), status); + if (outputFile->write_doubles){ + fits_write_col(outputFile->fptr, TDOUBLE, outputFile->trigCol, + outputFile->row, 1, record->trigger_size,record->adc_double, status); + } else { + fits_write_col(outputFile->fptr, TUSHORT, outputFile->trigCol, + outputFile->row, 1, record->trigger_size,record->adc_array, status); + } + fits_write_col(outputFile->fptr, TLONG, outputFile->pixIDCol, + outputFile->row, 1, 1, &(record->pixid), status); + fits_write_col(outputFile->fptr, TLONG, outputFile->ph_idCol, + outputFile->row, 1,record->phid_list->index,record->phid_list->phid_array, status); + + outputFile->rowbuffer--; + outputFile->nrows++; + outputFile->row++; +} diff --git a/libsixt/testriggerfile.h b/libsixt/testriggerfile.h new file mode 100644 index 0000000..46cbc39 --- /dev/null +++ b/libsixt/testriggerfile.h @@ -0,0 +1,103 @@ +/* + This file is part of SIXTE. + + SIXTE 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 + any later version. + + SIXTE 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. + + For a copy of the GNU General Public License see + . + + + Copyright 2015 Philippe Peille, IRAP + Copyright 2016-2019 Remeis-Sternwarte, Friedrich-Alexander-Universitaet + Erlangen-Nuernberg +*/ + +#ifndef TESTRIGGERFILE_H +#define TESTRIGGERFILE_H 1 + +#include "sixt.h" +#include "tesdatastream.h" +#include "pixelimpactfile.h" +#include "tesrecord.h" +#include "optimalfilters.h" + + + +//////////////////////////////////////////////////////////////////////// +// Type declarations. +//////////////////////////////////////////////////////////////////////// + +typedef struct{ + /** Pointer to the FITS file. */ + fitsfile* fptr; + + /** Total number of rows in the FITS file. */ + long nrows; + + /** Number of the current row in the FITS file. The numbering + starts at 1 for the first line. If row is equal to 0, no row + has been read or written so far. */ + long row; + + /** The amount of rows that have been reserved as a buffer but + not written yet. */ + long rowbuffer; + + /** Number of ADC values per record */ + unsigned long trigger_size; + + /** Time interval between two ADC values in the file */ + double delta_t; + + /** Column numbers for time, trigger, impact, and pixID columns */ + int timeCol,trigCol,extendCol,ph_idCol,pixIDCol; + + /** Option to write the records in doubles */ + int write_doubles; + +}TesTriggerFile; + +#define TESTRIGGERFILE_ROWBUFFERSIZE 100 // initial default value of rowbuffer + +//////////////////////////////////////////////////////////////////////// +// Function declarations. +//////////////////////////////////////////////////////////////////////// + + +/** Constructor. Returns a pointer to an empty TesTriggerFile data + structure. */ +TesTriggerFile* newTesTriggerFile(unsigned long triggerSize,int write_doubles,int* const status); + +/** Destructor. */ +void freeTesTriggerFile(TesTriggerFile** const file, int* const status); + +/** Create and open a new TesTriggerFile. */ +TesTriggerFile* opennewTesTriggerFile(const char* const filename, + SixtStdKeywords * keywords, + char* const xmlfile, + char* const impactlist, + unsigned long triggerSize, + int preBufferSize, + double sampleFreq, + int write_doubles, + const char clobber, + int* const status); + +/** Create and open a new TesTriggerFile. */ +TesTriggerFile* openexistingTesTriggerFile(const char* const filename,SixtStdKeywords* keywords,int* const status); + +/** Populates a TesRecord structure with the next record */ +int getNextRecord(TesTriggerFile* const file,TesRecord* record,int *lastRecord,int *startRecordGroup,int* const status); + +/** Writes a record to a file */ +void writeRecord(TesTriggerFile* outputFile,TesRecord* record,int* const status); + +#endif /* TESTRIGGERFILE_H */ diff --git a/libsixt/versionSIRENA.h b/libsixt/versionSIRENA.h index d0746e4..af41b58 100644 --- a/libsixt/versionSIRENA.h +++ b/libsixt/versionSIRENA.h @@ -22,11 +22,11 @@ // CANTABRIA (CSIC-UC) with funding from the Spanish Ministry of Science and // Innovation (MICINN) // -// DATE: 2021/02/18, 08:57:15 +// DATE: 2021/03/10, 15:46:12 #ifndef SIRENA_VERSION_H #define SIRENA_VERSION_H -#define SIRENA_VERSION "3.8.6" +#define SIRENA_VERSION "3.8.7" #endif diff --git a/tools/tesreconstruction/tesreconstruction.c b/tools/tesreconstruction/tesreconstruction.c index b485c41..c28fe91 100644 --- a/tools/tesreconstruction/tesreconstruction.c +++ b/tools/tesreconstruction/tesreconstruction.c @@ -78,7 +78,7 @@ * - OFLib: Work or not with a library with optimal filters (1/0) * - OFStrategy: Optimal Filter length Strategy: FREE, BYGRADE or FIXED * - OFLength: Optimal Filter length (taken into account if OFStrategy=FIXED) -* - preBuffer: Some samples added before the starting time of a pulse +* - preBuffer: Some samples added before the starting time of a pulse (number of samples added read from the xml file) * - intermediate: Write or not intermediate files (1/0) * - detectFile: Intermediate detections file (if intermediate=1) * - errorT: Additional error (in samples) added to the detected time (Logically, it changes the reconstructed energies ) @@ -95,7 +95,11 @@ * - Register HEATOOL * - Reading all programm parameters by using PIL * - Read XML info -* - Read the grading info from the input XML file +* - Sixt standard keywords structure +* - Open output FITS file +* - Initialize PP data structures needed for pulse filtering +* - Initialize SIRENA data structures needed for pulse filtering +* - Read the grading data from the XML file and store it in 'reconstruct_init_sirena->grading' * - Obtain the 'trig_reclength' and the sampling rate: * - If Rcmethod starts with '@' => List of record input FITS files. For every FITS file: * - Open FITS file @@ -109,11 +113,6 @@ * - Get the sampling rate from the HISTORY keyword from the input FITS file * - If it is a xifusim simulated file * - Obtain 'trig_reclength' from the HISTORY block -* - Sixt standard keywords structure -* - Open output FITS file -* - Initialize PP data structures needed for pulse filtering -* - Initialize SIRENA data structures needed for pulse filtering -* - Read the grading data from the XML file and store it in 'reconstruct_init_sirena->grading' * - Build up TesEventList to recover the results of the reconstruction * - Reconstruct the input record FITS file: * - If Rcmethod starts with '@' => List of record input FITS files. For every FITS file: @@ -164,20 +163,112 @@ int tesreconstruction_main() { return(EXIT_FAILURE); } + // Sixt standard keywords structure + //---------------------------------- + SixtStdKeywords* keywords = newSixtStdKeywords(&status); + CHECK_STATUS_BREAK(status); + + //Open outfile + //------------ + TesEventFile * outfile = opennewTesEventFileSIRENA(par.TesEventFile, + keywords, + SIRENA_VERSION, + par.clobber, + &status); + CHECK_STATUS_BREAK(status); + + // Initialize PP data structures needed for pulse filtering + //--------------------------------------------------------- + ReconstructInit* reconstruct_init = newReconstructInit(&status); + CHECK_STATUS_BREAK(status); + + // Initialize SIRENA data structures needed for pulse filtering + //------------------------------------------------------------- + ReconstructInitSIRENA* reconstruct_init_sirena = newReconstructInitSIRENA(&status); + CHECK_STATUS_BREAK(status); + PulsesCollection* pulsesAll = newPulsesCollection(&status); + CHECK_STATUS_BREAK(status); + OptimalFilterSIRENA* optimalFilter = newOptimalFilterSIRENA(&status); + CHECK_STATUS_BREAK(status);// define a second structure for calibration + double sf = -999.; double sampling_rate = -999.0; AdvDet *det = newAdvDet(&status); - if (par.opmode != 0) + + // Read XML info + //-------------- + CHECK_STATUS_BREAK(status); + det = loadAdvDet(par.XMLFile, &status); + CHECK_STATUS_BREAK(status); + + sf = det->SampleFreq; + + // Read the grading data from the XML file and store it in 'reconstruct_init_sirena->grading' + reconstruct_init_sirena->grading = NULL; + reconstruct_init_sirena->grading = (Grading*)malloc(sizeof(Grading)); + + reconstruct_init_sirena->grading->ngrades = 0; + reconstruct_init_sirena->grading->value = NULL; + reconstruct_init_sirena->grading->gradeData = NULL; + + if ((det->nrecons == 0) && (det->npix == 0)) { - // Read XML info - //-------------- - CHECK_STATUS_BREAK(status); - det = loadAdvDet(par.XMLFile, &status); - CHECK_STATUS_BREAK(status); - - sf = det->SampleFreq; + SIXT_ERROR("The provided XMLFile does not have the grading info"); + return(EXIT_FAILURE); + } + else if ((det->nrecons == 0) && (det->npix != 0)) + { + if (det->pix->grades == NULL) + { + SIXT_ERROR("The provided XMLFile does not have the grading info"); + return(EXIT_FAILURE); + } + reconstruct_init_sirena->grading->ngrades=det->pix->ngrades; + reconstruct_init_sirena->grading->gradeData = gsl_matrix_alloc(det->pix->ngrades,3); + for (int i=0;ipix->ngrades;i++) + { + gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,0,(int) (det->pix->grades[i].gradelim_pre)); + gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,1,(int) (det->pix->grades[i].gradelim_post)); + gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,2,(int) (det->pix->grades[i].grade_preBuffer)); + } + } + else if(((det->nrecons != 0) && (det->npix == 0)) || ((det->nrecons == 1) && (det->npix == 1))) + { + if (det->recons->grades == NULL) + { + SIXT_ERROR("The provided XMLFile does not have the grading info"); + return(EXIT_FAILURE); + } + reconstruct_init_sirena->grading->ngrades=det->recons->ngrades; + reconstruct_init_sirena->grading->gradeData = gsl_matrix_alloc(det->recons->ngrades,3); + for (int i=0;irecons->ngrades;i++) + { + gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,0,(int) (det->recons->grades[i].gradelim_pre)); + gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,1,(int) (det->recons->grades[i].gradelim_post)); + gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,2,(int) (det->recons->grades[i].grade_preBuffer)); + } + } + + int OFlengthvsposti = 0; + if ((par.preBuffer == 1) && (par.opmode == 1)) + { + for (int i=0;igrading->ngrades;i++) + { + if (par.OFLength == gsl_matrix_get(reconstruct_init_sirena->grading->gradeData,i,1)) + { + OFlengthvsposti = 1; + break; + } + } + if (OFlengthvsposti == 0) + { + SIXT_ERROR("The grading/preBuffer info of the XML file does not match the OFLength input parameter"); + return(EXIT_FAILURE); + } } + destroyAdvDet(&det); + int trig_reclength = -999; char* firstchar = strndup(par.RecordFile, 1); @@ -454,84 +545,7 @@ int tesreconstruction_main() { fits_close_file(fptr,&status); CHECK_STATUS_BREAK(status); } - - // Sixt standard keywords structure - //---------------------------------- - SixtStdKeywords* keywords = newSixtStdKeywords(&status); - CHECK_STATUS_BREAK(status); - - //Open outfile - //------------ - TesEventFile * outfile = opennewTesEventFileSIRENA(par.TesEventFile, - keywords, - SIRENA_VERSION, - par.clobber, - &status); - CHECK_STATUS_BREAK(status); - - // Initialize PP data structures needed for pulse filtering - //--------------------------------------------------------- - ReconstructInit* reconstruct_init = newReconstructInit(&status); - CHECK_STATUS_BREAK(status); - - // Initialize SIRENA data structures needed for pulse filtering - //------------------------------------------------------------- - ReconstructInitSIRENA* reconstruct_init_sirena = newReconstructInitSIRENA(&status); - CHECK_STATUS_BREAK(status); - PulsesCollection* pulsesAll = newPulsesCollection(&status); - CHECK_STATUS_BREAK(status); - OptimalFilterSIRENA* optimalFilter = newOptimalFilterSIRENA(&status); - CHECK_STATUS_BREAK(status);// define a second structure for calibration - - if (par.opmode != 0) // Grading info is not necessary when building the library - { - // Read the grading data from the XML file and store it in 'reconstruct_init_sirena->grading' - reconstruct_init_sirena->grading = NULL; - //reconstruct_init_sirena->grading = (Grading*)malloc(sizeof(Grading)); - reconstruct_init_sirena->grading = (Grading*)malloc(sizeof(Grading)); - - reconstruct_init_sirena->grading->ngrades = 0; - reconstruct_init_sirena->grading->value = NULL; - reconstruct_init_sirena->grading->gradeData = NULL; - - if ((det->nrecons == 0) && (det->npix == 0)) - { - SIXT_ERROR("The provided XMLFile does not have the grading info"); - return(EXIT_FAILURE); - } - else if ((det->nrecons == 0) && (det->npix != 0)) - { - if (det->pix->grades == NULL) - { - SIXT_ERROR("The provided XMLFile does not have the grading info"); - return(EXIT_FAILURE); - } - reconstruct_init_sirena->grading->ngrades=det->pix->ngrades; - reconstruct_init_sirena->grading->gradeData = gsl_matrix_alloc(det->pix->ngrades,2); - for (int i=0;ipix->ngrades;i++) - { - gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,0,(int) (det->pix->grades[i].gradelim_pre)); - gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,1,(int) (det->pix->grades[i].gradelim_post)); - } - } - else if(((det->nrecons != 0) && (det->npix == 0)) || ((det->nrecons == 1) && (det->npix == 1))) - { - if (det->recons->grades == NULL) - { - SIXT_ERROR("The provided XMLFile does not have the grading info"); - return(EXIT_FAILURE); - } - reconstruct_init_sirena->grading->ngrades=det->recons->ngrades; - reconstruct_init_sirena->grading->gradeData = gsl_matrix_alloc(det->recons->ngrades,2); - for (int i=0;irecons->ngrades;i++) - { - gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,0,(int) (det->recons->grades[i].gradelim_pre)); - gsl_matrix_set(reconstruct_init_sirena->grading->gradeData,i,1,(int) (det->recons->grades[i].gradelim_post)); - } - } - } - destroyAdvDet(&det); - + // Build up TesEventList to recover the results of the reconstruction // SIRENA method TesEventList* event_list = newTesEventListSIRENA(&status); @@ -544,7 +558,7 @@ int tesreconstruction_main() { TesTriggerFile* record_file; TesRecord* record; - int lastRecord = 0, nrecord = 0, nrecord_filei = 0; //last record required for SIRENA library creation + int lastRecord = 0, nrecord = 0, startRecordGroup = 0,nrecord_filei = 0; //last record required for SIRENA library creation if (strcmp(firstchar2,"@") == 0) { @@ -597,7 +611,7 @@ int tesreconstruction_main() { // Iterate of records and do the reconstruction //int lastRecord = 0, nrecord = 0; //last record required for SIRENA library creation nrecord_filei = 0; - while(getNextRecord(record_file,record,&status)) + while(getNextRecord(record_file,record,&lastRecord,&startRecordGroup,&status)) { if(!strcmp(par.Rcmethod,"PP")) { @@ -617,7 +631,7 @@ int tesreconstruction_main() { //printf("%s %d %s","**TESRECONSTRUCTION nrecord = ",nrecord,"\n"); reconstructRecordSIRENA(record,trig_reclength,event_list,reconstruct_init_sirena, - lastRecord, nrecord, &pulsesAll, &optimalFilter, &status); + lastRecord, startRecordGroup, &pulsesAll, &optimalFilter, &status); } CHECK_STATUS_BREAK(status); @@ -626,9 +640,6 @@ int tesreconstruction_main() { // In THREADING mode, saveEventListToFileSIRENA is not called until finishing with calculus // (ordering is necessary previously) if(!is_threading()){ - //printf("\n %p - %f", outfile, record_file->delta_t); - //printf("\nRecord single"); - //printf("\n%f - %ld", record->time, record->pixid); saveEventListToFileSIRENA(outfile,event_list,record->time,record_file->delta_t,record->pixid,&status); CHECK_STATUS_BREAK(status); //Reinitialize event list @@ -640,21 +651,12 @@ int tesreconstruction_main() { } // while getNextRecord if(is_threading()) { - //printf("%s","**Threading...waiting \n"); th_end(&reconstruct_init_sirena, &pulsesAll, &optimalFilter); - //printf("%s %d %s","**Threading...after th_end: pulsesAll->ndetpulses", pulsesAll->ndetpulses,"\n"); - //printf("%s %d %s","**Threading...after th_end: pulsesAll->size", pulsesAll->size,"\n"); int i = 1; int aux = 1; while((aux = th_get_event_list(&event_list, &record)) == 1) { - //printf("%s %d %s","**Threading...i: ", i,"\n"); - //printf("%s %d %s","**Threading...event_list->size_energy: ", event_list->size_energy,"\n"); Always 0 - //printf("%s %e %s","**Threading...event_list->energies[0]: ", event_list->energies[0],"\n"); Energy value - //printf("%s %e %s","**Threading...event_list->energies[1]: ", event_list->energies[1],"\n"); Not error but non relevant value - //printf("%s %e %s","**Threading...event_list->energies[100000]: ", event_list->energies[100000],"\n"); Not error but non relevant value saveEventListToFileSIRENA(outfile,event_list,record->time,record_file->delta_t,record->pixid,&status); - //printf("%s","**Threading...after de saveEventListToFileSIRENA \n"); CHECK_STATUS_BREAK(status); ++i; } @@ -729,12 +731,6 @@ int tesreconstruction_main() { } CHECK_STATUS_BREAK(status); - //printf("%s %d %s","record_file->trigger_size0: ", record_file->trigger_size,"\n"); - //printf("%s %d %s","trig_reclength: ", trig_reclength,"\n"); - //if (record_file->trigger_size > trig_reclength) - //{ - // record_file->trigger_size = trig_reclength; - //} // Build up TesRecord to read the file record = newTesRecord(&status); if ((record_file->delta_t == -999) && (sampling_rate == -999)) @@ -747,12 +743,10 @@ int tesreconstruction_main() { //allocateTesRecord(record,record_file->trigger_size,record_file->delta_t,0,&status); allocateTesRecord(record,trig_reclength,record_file->delta_t,0,&status); CHECK_STATUS_BREAK(status); - //printf("%s %f %s","record_file->delta_t = ",record_file->delta_t,"\n"); - //printf("%s %f %s","samprate = ",1.0/(record_file->delta_t),"\n"); // Iterate of records and do the reconstruction lastRecord = 0, nrecord = 0; //last record required for SIRENA library creation - while(getNextRecord(record_file,record,&status)) + while(getNextRecord(record_file,record,&lastRecord,&startRecordGroup,&status)) { if(!strcmp(par.Rcmethod,"PP")) { @@ -761,12 +755,12 @@ int tesreconstruction_main() { else { nrecord = nrecord + 1; - if(nrecord == record_file->nrows) lastRecord=1; - /*if(nrecord < 7) + //if(nrecord == record_file->nrows) lastRecord=1; + /*if(nrecord < 116) { continue; } - else if(nrecord > 7) + else if(nrecord > 117) { status=1; CHECK_STATUS_BREAK(status); @@ -783,10 +777,9 @@ int tesreconstruction_main() { } //printf("%s %d %s","**TESRECONSTRUCTION nrecord = ",nrecord,"\n"); - //printf("%s %d %s", "pixid: ",record->pixid,"\n"); - //printf("%s %d %s","ph_id: ",record->phid_list->phid_array[0],"\n"); + //printf("%s %d %s","startRecordGroup = ",startRecordGroup,"\n"); reconstructRecordSIRENA(record,trig_reclength, event_list,reconstruct_init_sirena, - lastRecord, nrecord, &pulsesAll, &optimalFilter, &status); + lastRecord, startRecordGroup, &pulsesAll, &optimalFilter, &status); } CHECK_STATUS_BREAK(status); @@ -795,14 +788,7 @@ int tesreconstruction_main() { // In THREADING mode, saveEventListToFileSIRENA is not called until finishing with calculus // (ordering is necessary previously) if(!is_threading()){ - //printf("\n %p - %f", outfile, record_file->delta_t); - //printf("\nRecord single"); - //printf("\n%f - %ld", record->time, record->pixid); - //printf("%s %d %s","**Before saveEventListToFileSIRENA \n"); - //printf("%s %d %s","status2 = ",status,"\n"); saveEventListToFileSIRENA(outfile,event_list,record->time,record_file->delta_t,record->pixid,&status); - //printf("%s %d %s","**After saveEventListToFileSIRENA \n"); - //printf("%s %d %s","status3 = ",status,"\n"); CHECK_STATUS_BREAK(status); //Reinitialize event list event_list->index=0; @@ -814,18 +800,11 @@ int tesreconstruction_main() { { //printf("%s","**Threading...waiting \n"); th_end(&reconstruct_init_sirena, &pulsesAll, &optimalFilter); - //printf("%s %d %s","**Threading...after th_end: pulsesAll->ndetpulses", pulsesAll->ndetpulses,"\n"); - //printf("%s %d %s","**Threading...after th_end: pulsesAll->size", pulsesAll->size,"\n"); int i = 1; int aux = 1; while((aux = th_get_event_list(&event_list, &record)) == 1) { - //printf("%s %d %s","**Threading...event_list->size_energy: ", event_list->size_energy,"\n"); //Always 0 - //printf("%s %e %s","**Threading...event_list->energies[0]: ", event_list->energies[0],"\n"); //Energy value - //printf("%s %e %s","**Threading...event_list->energies[1]: ", event_list->energies[1],"\n"); //Not error but non relevant value - //printf("%s %e %s","**Threading...event_list->energies[100000]: ", event_list->energies[100000],"\n"); Not error but non relevant value saveEventListToFileSIRENA(outfile,event_list,record->time,record_file->delta_t,record->pixid,&status); - //printf("%s","**Threading...after saveEventListToFileSIRENA \n"); CHECK_STATUS_BREAK(status); ++i; } @@ -1095,7 +1074,7 @@ int getpar(struct Parameters* const par) status=ape_trad_query_int("OFLength", &par->OFLength); - status=ape_trad_query_int("preBuffer", &par->preBuffer); + status=ape_trad_query_bool("preBuffer", &par->preBuffer); status=ape_trad_query_int("errorT", &par->errorT); @@ -1222,14 +1201,14 @@ int getpar(struct Parameters* const par) MyAssert((strcmp(par->OFStrategy,"FREE") == 0) || (strcmp(par->OFStrategy,"BYGRADE") == 0) || (strcmp(par->OFStrategy,"FIXED") == 0), "OFStrategy must be FREE, BYGRADE or FIXED"); - MyAssert(par->OFLength > 0, "OFLength must be greater than 0"); + MyAssert(par->OFLength > 0, "OFLength must be greater than 0"); - MyAssert(par->preBuffer >= 0, "preBuffer must be 0 or greater than 0"); + //MyAssert(par->preBuffer >= 0, "preBuffer must be 0 or greater than 0"); MyAssert(par->energyPCA1 > 0, "energyPCA1 must be greater than 0"); - MyAssert(par->energyPCA2 > 0, "energyPCA2 must be greater than 0"); + MyAssert(par->energyPCA2 > 0, "energyPCA2 must be greater than 0"); - MyAssert(par->LbT > 0, "LbT must be greater than 0"); + MyAssert(par->LbT > 0, "LbT must be greater than 0"); } else { SIXT_ERROR("failed reading the Rcmethod parameter"); diff --git a/tools/tesreconstruction/tesreconstruction.par b/tools/tesreconstruction/tesreconstruction.par index 616e430..b0c30a7 100755 --- a/tools/tesreconstruction/tesreconstruction.par +++ b/tools/tesreconstruction/tesreconstruction.par @@ -46,7 +46,8 @@ OFIter,i,h,0,,,"Iterate or not iterate (1/0)" OFLib,b,h,yes,,,"Work or not with a library with optimal filters (yes/no)" OFStrategy,s,h,"BYGRADE",,,"Optimal Filter length Strategy: FREE, BYGRADE or FIXED" OFLength,i,h,8192,,,"Optimal Filter length (taken into account if OFStrategy=FIXED)" -preBuffer,i,h,0,,,"Some samples added before the starting time of a pulse" +#preBuffer,i,h,0,,,"Some samples added before the starting time of a pulse" +preBuffer,b,h,no,,,"Some samples added or not before the starting time of a pulse (number of added samples read from the xml file)" intermediate,i,h,0,,,"Write or not intermediate files (1/0)" detectFile,s,h,"detections.fits",,,"Intermediate detections file (if intermediate=1)" errorT,i,h,0,,,"Additional error (in samples) added to the detected time" # Logically, it changes the reconstructed energies