/*----- PROTECTED REGION ID(CCDSpectrometer.cpp) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        CCDSpectrometer.cpp
//
// description : C++ source for the CCDSpectrometer class and its commands.
//               The class is derived from Device. It represents the
//               CORBA servant object which will be accessed from the
//               network. All commands which can be executed on the
//               CCDSpectrometer are implemented in this file.
//
// project :     CCDSpectrometer
//
// This file is part of Tango device class.
//
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Tango is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#include "CCDSpectrometer.h"
#include "CCDSpectrometerClass.h"
#include <readthread.h>
#include "tcheck_get_rt_buffer.hpp"
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer.cpp

/**
 *  CCDSpectrometer class description:
 *    Laser Spectrometer based on Basler CCD Tango Device
 */

//================================================================
//  The following table gives the correspondence
//  between command and method names.
//
//  Command name       |  Method name
//================================================================
//  State              |  Inherited (no method)
//  Status             |  Inherited (no method)
//  Start              |  start
//  Stop               |  stop
//  Reset              |  reset
//  StartSingle        |  start_single
//  StartContinuous    |  start_continuous
//  GetLastData        |  get_last_data
//  AcquireNoise       |  acquire_noise
//  SaveReferenceData  |  save_reference_data
//  GetData            |  get_data
//  GetGaussFitCenter  |  get_gauss_fit_center
//  GetGaussFitWidth   |  get_gauss_fit_width
//  GetFWHMCenter      |  get_fwhmcenter
//  GetFWHMWidth       |  get_fwhmwidth
//  ExportWavelength   |  export_wavelength
//  GetArea            |  get_area
//  GetWave            |  get_wave
//  GetLambda          |  get_lambda
//================================================================

//================================================================
//  Attributes managed are:
//================================================================
//  SyncMode                    |  Tango::DevLong	Scalar
//  ExposureTime                |  Tango::DevDouble	Scalar
//  NoiseSubtraction            |  Tango::DevBoolean	Scalar
//  GaussFitEnable              |  Tango::DevBoolean	Scalar
//  FWHMEnable                  |  Tango::DevBoolean	Scalar
//  GaussFitCenter              |  Tango::DevDouble	Scalar
//  GaussFitWidth               |  Tango::DevDouble	Scalar
//  FWHMCenter                  |  Tango::DevDouble	Scalar
//  FWHMWidth                   |  Tango::DevDouble	Scalar
//  Center                      |  Tango::DevDouble	Scalar
//  Width                       |  Tango::DevDouble	Scalar
//  FitType                     |  Tango::DevLong	Scalar
//  FWHMAvg                     |  Tango::DevLong	Scalar
//  NoiseLevel                  |  Tango::DevLong	Scalar
//  DataReferenceFile           |  Tango::DevString	Scalar
//  AutoExposure                |  Tango::DevBoolean	Scalar
//  RtMode                      |  Tango::DevBoolean	Scalar
//  IntensityCalibrationEnable  |  Tango::DevBoolean	Scalar
//  Area                        |  Tango::DevDouble	Scalar
//  AreaRegion                  |  Tango::DevDouble	Scalar
//  AreaEnable                  |  Tango::DevBoolean	Scalar
//  WidthCorrectionEnable       |  Tango::DevBoolean	Scalar
//  IncrSensitivity             |  Tango::DevBoolean	Scalar
//  Data                        |  Tango::DevDouble	Spectrum  ( max = 4100)
//  NumPixels                   |  Tango::DevLong	Spectrum  ( max = 2)
//  RegionOfInterest            |  Tango::DevDouble	Spectrum  ( max = 2)
//  AnalysisRegion              |  Tango::DevDouble	Spectrum  ( max = 2)
//  GaussFit                    |  Tango::DevDouble	Spectrum  ( max = 4)
//  FWHM                        |  Tango::DevDouble	Spectrum  ( max = 3)
//  GaussReference              |  Tango::DevDouble	Spectrum  ( max = 4)
//  DataReference               |  Tango::DevDouble	Spectrum  ( max = 5000)
//  IntensityCalibration        |  Tango::DevDouble	Spectrum  ( max = 5000)
//  NoiseProfile                |  Tango::DevDouble	Spectrum  ( max = 5000)
//  Wave                        |  Tango::DevDouble	Spectrum  ( max = 5000)
//  Lambda                      |  Tango::DevDouble	Spectrum  ( max = 5000)
//================================================================

namespace CCDSpectrometer_ns
{
/*----- PROTECTED REGION ID(CCDSpectrometer::namespace_starting) ENABLED START -----*/
/* clang-format on */
//	static initializations
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::namespace_starting

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::CCDSpectrometer()
 *	Description: Constructors for a Tango device
 *                implementing the classCCDSpectrometer
 */
//--------------------------------------------------------
CCDSpectrometer::CCDSpectrometer(Tango::DeviceClass *cl, std::string &s)
 : TANGO_BASE_CLASS(cl, s.c_str())
{
	/*----- PROTECTED REGION ID(CCDSpectrometer::constructor_1) ENABLED START -----*/
	/* clang-format on */
	init_device();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::constructor_1
}
//--------------------------------------------------------
CCDSpectrometer::CCDSpectrometer(Tango::DeviceClass *cl, const char *s)
 : TANGO_BASE_CLASS(cl, s)
{
	/*----- PROTECTED REGION ID(CCDSpectrometer::constructor_2) ENABLED START -----*/
	/* clang-format on */
	init_device();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::constructor_2
}
//--------------------------------------------------------
CCDSpectrometer::CCDSpectrometer(Tango::DeviceClass *cl, const char *s, const char *d)
 : TANGO_BASE_CLASS(cl, s, d)
{
	/*----- PROTECTED REGION ID(CCDSpectrometer::constructor_3) ENABLED START -----*/
	/* clang-format on */
	init_device();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::constructor_3
}
//--------------------------------------------------------
CCDSpectrometer::~CCDSpectrometer()
{
	delete_device();
}

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::delete_device()
 *	Description: will be called at device destruction or at init command
 */
//--------------------------------------------------------
void CCDSpectrometer::delete_device()
{
	DEBUG_STREAM << "CCDSpectrometer::delete_device() " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::delete_device) ENABLED START -----*/
	/* clang-format on */
	//	Delete device allocated objects
	loop->abortflag = true;
	abortflag = true;
	sleep(1);

	Tango::DbDatum gr("DefaultGaussRef");
	vector<double> gref;
	gref.push_back(attr_GaussReference_read[0]);
	gref.push_back(attr_GaussReference_read[1]);
	gref.push_back(attr_GaussReference_read[2]);
	gref.push_back(attr_GaussReference_read[3]);
	gr << gref;
	Tango::DbDatum ar("AnalysisRegion");
	vector<double> anre;
	anre.push_back(attr_AnalysisRegion_read[0]);
	anre.push_back(attr_AnalysisRegion_read[1]);
	ar << anre;
	Tango::DbDatum ri("RegionOfInterest");
	vector<double> rein;
	rein.push_back(attr_RegionOfInterest_read[0]);
	rein.push_back(attr_RegionOfInterest_read[1]);
	ri << rein;
	Tango::DbDatum et("ExposureTime");
	et << *attr_ExposureTime_read;
	Tango::DbDatum sm("SyncMode");
	sm << *attr_SyncMode_read;
	Tango::DbData data;
	data.push_back(gr);
	data.push_back(ar);
	data.push_back(ri);
	data.push_back(et);
	data.push_back(sm);
	Tango::Database *db = new Tango::Database();
	try
	{
		db->set_timeout_millis(15000);
		db->put_device_property(get_name(), data);
	}
	catch(Tango::DevFailed &e)
	{
		stringstream o;
		o << " Error saving properties='" << e.errors[0].desc << "'";
		WARN_STREAM << __FUNCTION__<< o.str();
	}
	delete db;

	delete [] x_values;
	if(pLiveData_avg)
	{
		delete [] pLiveData_avg;
		pLiveData_avg = NULL;
	}
	if(pLiveData)
	{
		delete [] pLiveData;
		pLiveData = NULL;
	}
	if(pNoiseMask_avg)
	{
		delete [] pNoiseMask_avg;
		pNoiseMask_avg = NULL;
	}
	if(pReferenceData)
	{
		delete [] pReferenceData;
		pReferenceData = NULL;
	}
	/*if(pMeasData)
	{
		delete [] pMeasData;
		pMeasData = NULL;
	}*/
	if(pFrameBuffer)
	{
		delete [] pFrameBuffer;
		pFrameBuffer = NULL;
	}
	delete m_gaussfit;
	delete m_asyngaussfit;
	delete m_confiteorfit;

	for(int i=0; i<NUM_BUF; i++)
	{
		tbuf[i].delete_rt_buffer();
	}
	tbuf_array.delete_rt_buffer();
	tbuf_array_w.delete_rt_buffer();
	tbuf_array_l.delete_rt_buffer();

	delete dpmutex;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::delete_device
	delete[] attr_SyncMode_read;
	delete[] attr_ExposureTime_read;
	delete[] attr_NoiseSubtraction_read;
	delete[] attr_GaussFitEnable_read;
	delete[] attr_FWHMEnable_read;
	delete[] attr_GaussFitCenter_read;
	delete[] attr_GaussFitWidth_read;
	delete[] attr_FWHMCenter_read;
	delete[] attr_FWHMWidth_read;
	delete[] attr_Center_read;
	delete[] attr_Width_read;
	delete[] attr_FitType_read;
	delete[] attr_FWHMAvg_read;
	delete[] attr_NoiseLevel_read;
	delete[] attr_AutoExposure_read;
	delete[] attr_RtMode_read;
	delete[] attr_IntensityCalibrationEnable_read;
	delete[] attr_Area_read;
	delete[] attr_AreaRegion_read;
	delete[] attr_AreaEnable_read;
	delete[] attr_WidthCorrectionEnable_read;
	delete[] attr_IncrSensitivity_read;
	delete[] attr_NumPixels_read;
	delete[] attr_RegionOfInterest_read;
	delete[] attr_AnalysisRegion_read;
	delete[] attr_GaussFit_read;
	delete[] attr_FWHM_read;
	delete[] attr_GaussReference_read;
	delete[] attr_IntensityCalibration_read;
}

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::init_device()
 *	Description: will be called at device initialization.
 */
//--------------------------------------------------------
void CCDSpectrometer::init_device()
{
	DEBUG_STREAM << "CCDSpectrometer::init_device() create device " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::init_device_before) ENABLED START -----*/
	/* clang-format on */
	//	Initialization before get_device_property() call
	abortflag = false;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::init_device_before


	//	Get the device properties from database
	get_device_property();

	attr_SyncMode_read = new Tango::DevLong[1];
	attr_ExposureTime_read = new Tango::DevDouble[1];
	attr_NoiseSubtraction_read = new Tango::DevBoolean[1];
	attr_GaussFitEnable_read = new Tango::DevBoolean[1];
	attr_FWHMEnable_read = new Tango::DevBoolean[1];
	attr_GaussFitCenter_read = new Tango::DevDouble[1];
	attr_GaussFitWidth_read = new Tango::DevDouble[1];
	attr_FWHMCenter_read = new Tango::DevDouble[1];
	attr_FWHMWidth_read = new Tango::DevDouble[1];
	attr_Center_read = new Tango::DevDouble[1];
	attr_Width_read = new Tango::DevDouble[1];
	attr_FitType_read = new Tango::DevLong[1];
	attr_FWHMAvg_read = new Tango::DevLong[1];
	attr_NoiseLevel_read = new Tango::DevLong[1];
	attr_AutoExposure_read = new Tango::DevBoolean[1];
	attr_RtMode_read = new Tango::DevBoolean[1];
	attr_IntensityCalibrationEnable_read = new Tango::DevBoolean[1];
	attr_Area_read = new Tango::DevDouble[1];
	attr_AreaRegion_read = new Tango::DevDouble[1];
	attr_AreaEnable_read = new Tango::DevBoolean[1];
	attr_WidthCorrectionEnable_read = new Tango::DevBoolean[1];
	attr_IncrSensitivity_read = new Tango::DevBoolean[1];
	attr_NumPixels_read = new Tango::DevLong[2];
	attr_RegionOfInterest_read = new Tango::DevDouble[2];
	attr_AnalysisRegion_read = new Tango::DevDouble[2];
	attr_GaussFit_read = new Tango::DevDouble[4];
	attr_FWHM_read = new Tango::DevDouble[3];
	attr_GaussReference_read = new Tango::DevDouble[4];
	attr_IntensityCalibration_read = new Tango::DevDouble[5000];
	/*----- PROTECTED REGION ID(CCDSpectrometer::init_device) ENABLED START -----*/
	/* clang-format on */
	//	Initialize device
	*attr_FitType_read = GAUSS_FIT;
	*attr_FWHMAvg_read = 3;
	defaultStartRegion = floor(defaultStartRegion*1000.0)*0.001;
	defaultEndRegion = floor(defaultEndRegion*1000.0)*0.001;
	for(int i=0; i<5000; i++)
		attr_IntensityCalibration_read[i] = 1.0;
	*attr_IntensityCalibrationEnable_read = false;

	attr_GaussFit_read[0]=attr_GaussFit_read[1]=attr_GaussFit_read[2]=attr_GaussFit_read[3]=0;
	*attr_ExposureTime_read = exposureTime;
	*attr_SyncMode_read = syncMode;
	attr_AnalysisRegion_read[0] = attr_RegionOfInterest_read[0] = defaultStartRegion;
	attr_AnalysisRegion_read[1] = attr_RegionOfInterest_read[1] = defaultEndRegion;
	if(regionOfInterest.size() >= 2)
	{
		attr_RegionOfInterest_read[0] = regionOfInterest[0];
		attr_RegionOfInterest_read[1] = regionOfInterest[1];
	}
	if(analysisRegion.size() >= 2)
	{
		attr_AnalysisRegion_read[0] = analysisRegion[0];
		attr_AnalysisRegion_read[1] = analysisRegion[1];
	}
	if(defaultGaussRef.size() == 4)
	{
		int i=0;
		for(vector<double>::iterator it = defaultGaussRef.begin(); it != defaultGaussRef.end(); it++)
			attr_GaussReference_read[i++] = *it;
		/*attr_GaussReference_read[0] = defaultGaussRef[0];
		attr_GaussReference_read[1] = defaultGaussRef[1];
		attr_GaussReference_read[2] = defaultGaussRef[2];
		attr_GaussReference_read[3] = defaultGaussRef[3];*/
	}
	else
		attr_GaussReference_read[0] = attr_GaussReference_read[1] = attr_GaussReference_read[2] = attr_GaussReference_read[3]= 0;
	
	FrameBufferIndex = 0;

	pLiveData = NULL;
	pReferenceData = NULL;
	pFrameBuffer = NULL;
	x_values = NULL;
	pLiveData_avg = NULL;
	pNoiseMask_avg = NULL;

	ostringstream tempstr;
	tempstr << dataReferenceFile << ends;
	if(tempstr.str().length() < sizeof(attr_strchar))
		strcpy(attr_strchar,tempstr.str().c_str());

	live_mode = false;
	init_live_mode = false;
	measure_mode = false;
	init_measure_mode = false;
	acquire_noise_mode = false;
	init_acquire_noise_mode = false;
	stop_mode = false;
	noise_level = 0;
	GaussFit_valid = false;

	y_max_mean = 0;
	memset(exposures, 0, sizeof(int)*AUTO_EXPOSURE_MEAN);
	exposure_idx = 0;

//	m_gaussfit = new GaussFit(NUM_GAUSS_PARAMETER, gauss_f, gauss_df, gauss_fdf);
//	m_gaussfit = new Fit(NUM_GAUSS_PARAMETER, gauss_f, gauss_df, gauss_fdf);
	m_gaussfit = new Fit(GAUSS_FIT, GAUSS_FIT_NUM_PARAM, 1);
	m_asyngaussfit = new Fit(GAUSS_FIT_ASYMM, GAUSS_FIT_ASYMM_NUM_PARAM, 1);
	m_confiteorfit = new Fit(CONFITEOR2_FIT, CONFITEOR_FIT_NUM_PARAM, 1);

	for(int i=0; i<NUM_BUF; i++)
	{
		tbuf[i].init_rt_buffer(BUF_SIZE);
		tbuf[i].set_mode(tbuffer::BUF_RT_CIRCULAR);
		//set_fill_hole(BUF_RT_FILL_0, buf[i]);
		//set_fill_hole(BUF_RT_NO_FILL, buf[i]);
		tbuf[i].set_fill_hole(BUF_RT_FILL_1);
	}
	tbuf_array.init_rt_buffer(BUF_SIZE);
	tbuf_array.set_mode(tbuffer::BUF_RT_CIRCULAR);
	tbuf_array.set_fill_hole(BUF_RT_FILL_1);

	tbuf_array_w.init_rt_buffer(BUF_SIZE);
	tbuf_array_w.set_mode(tbuffer::BUF_RT_CIRCULAR);
	tbuf_array_w.set_fill_hole(BUF_RT_FILL_1);

	tbuf_array_l.init_rt_buffer(BUF_SIZE);
	tbuf_array_l.set_mode(tbuffer::BUF_RT_CIRCULAR);
	tbuf_array_l.set_fill_hole(BUF_RT_FILL_1);

	//	Initialize device
	set_state(Tango::ON);

	if(intensityCalibrationFile.length() > 0)
		load_intensity_cal_file(intensityCalibrationFile);

	init_data(false);
	dpmutex = new omni_mutex();
	dp = new Tango::DeviceProxy(deviceName);
	loop = new readthread(this);
	loop->start();

	if(autoStart && conn_status)
	{
		try
		{
			start();
		}
		catch(Tango::DevFailed &e)
		{
			INFO_STREAM << __func__ << ": error autostarting=" << e.errors[0].desc;
		}
	}

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::init_device
}

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::get_device_property()
 *	Description: Read database to initialize property data members.
 */
//--------------------------------------------------------
void CCDSpectrometer::get_device_property()
{
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_device_property_before) ENABLED START -----*/
	/* clang-format on */
	//	Initialize property data members
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_device_property_before


	//	Read device properties from database.
	Tango::DbData	dev_prop;
	dev_prop.push_back(Tango::DbDatum("DeviceName"));
	dev_prop.push_back(Tango::DbDatum("DefaultGaussRef"));
	dev_prop.push_back(Tango::DbDatum("DataReferenceFile"));
	dev_prop.push_back(Tango::DbDatum("DefaultStartRegion"));
	dev_prop.push_back(Tango::DbDatum("DefaultEndRegion"));
	dev_prop.push_back(Tango::DbDatum("PreferFWHM"));
	dev_prop.push_back(Tango::DbDatum("AutoExposureRange"));
	dev_prop.push_back(Tango::DbDatum("AutoExposureStep"));
	dev_prop.push_back(Tango::DbDatum("AutoExposureAmpRange"));
	dev_prop.push_back(Tango::DbDatum("IntensityCalibrationFile"));
	dev_prop.push_back(Tango::DbDatum("NoiseProfileFile"));
	dev_prop.push_back(Tango::DbDatum("WavelengthAttr"));
	dev_prop.push_back(Tango::DbDatum("AreaInAnalysisRegion"));
	dev_prop.push_back(Tango::DbDatum("WidthCorrection"));
	dev_prop.push_back(Tango::DbDatum("NFramesBuffered"));
	dev_prop.push_back(Tango::DbDatum("AnalysisRegion"));
	dev_prop.push_back(Tango::DbDatum("RegionOfInterest"));
	dev_prop.push_back(Tango::DbDatum("ExposureTime"));
	dev_prop.push_back(Tango::DbDatum("SyncMode"));
	dev_prop.push_back(Tango::DbDatum("AutoStart"));
	dev_prop.push_back(Tango::DbDatum("NumPixel"));
	dev_prop.push_back(Tango::DbDatum("CameraLabel"));

	//	is there at least one property to be read ?
	if (dev_prop.size()>0)
	{
		//	Call database and extract values
		if (Tango::Util::instance()->_UseDb==true)
			get_db_device()->get_property(dev_prop);

		//	get instance on CCDSpectrometerClass to get class property
		Tango::DbDatum	def_prop, cl_prop;
		CCDSpectrometerClass	*ds_class =
			(static_cast<CCDSpectrometerClass *>(get_device_class()));
		int	i = -1;

		//	Try to initialize DeviceName from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  deviceName;
		else {
			//	Try to initialize DeviceName from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  deviceName;
		}
		//	And try to extract DeviceName value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  deviceName;

		//	Try to initialize DefaultGaussRef from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  defaultGaussRef;
		else {
			//	Try to initialize DefaultGaussRef from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  defaultGaussRef;
		}
		//	And try to extract DefaultGaussRef value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  defaultGaussRef;

		//	Try to initialize DataReferenceFile from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  dataReferenceFile;
		else {
			//	Try to initialize DataReferenceFile from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  dataReferenceFile;
		}
		//	And try to extract DataReferenceFile value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  dataReferenceFile;

		//	Try to initialize DefaultStartRegion from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  defaultStartRegion;
		else {
			//	Try to initialize DefaultStartRegion from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  defaultStartRegion;
		}
		//	And try to extract DefaultStartRegion value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  defaultStartRegion;

		//	Try to initialize DefaultEndRegion from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  defaultEndRegion;
		else {
			//	Try to initialize DefaultEndRegion from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  defaultEndRegion;
		}
		//	And try to extract DefaultEndRegion value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  defaultEndRegion;

		//	Try to initialize PreferFWHM from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  preferFWHM;
		else {
			//	Try to initialize PreferFWHM from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  preferFWHM;
		}
		//	And try to extract PreferFWHM value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  preferFWHM;

		//	Try to initialize AutoExposureRange from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  autoExposureRange;
		else {
			//	Try to initialize AutoExposureRange from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  autoExposureRange;
		}
		//	And try to extract AutoExposureRange value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  autoExposureRange;

		//	Try to initialize AutoExposureStep from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  autoExposureStep;
		else {
			//	Try to initialize AutoExposureStep from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  autoExposureStep;
		}
		//	And try to extract AutoExposureStep value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  autoExposureStep;

		//	Try to initialize AutoExposureAmpRange from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  autoExposureAmpRange;
		else {
			//	Try to initialize AutoExposureAmpRange from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  autoExposureAmpRange;
		}
		//	And try to extract AutoExposureAmpRange value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  autoExposureAmpRange;

		//	Try to initialize IntensityCalibrationFile from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  intensityCalibrationFile;
		else {
			//	Try to initialize IntensityCalibrationFile from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  intensityCalibrationFile;
		}
		//	And try to extract IntensityCalibrationFile value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  intensityCalibrationFile;

		//	Try to initialize NoiseProfileFile from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  noiseProfileFile;
		else {
			//	Try to initialize NoiseProfileFile from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  noiseProfileFile;
		}
		//	And try to extract NoiseProfileFile value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  noiseProfileFile;

		//	Try to initialize WavelengthAttr from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  wavelengthAttr;
		else {
			//	Try to initialize WavelengthAttr from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  wavelengthAttr;
		}
		//	And try to extract WavelengthAttr value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  wavelengthAttr;

		//	Try to initialize AreaInAnalysisRegion from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  areaInAnalysisRegion;
		else {
			//	Try to initialize AreaInAnalysisRegion from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  areaInAnalysisRegion;
		}
		//	And try to extract AreaInAnalysisRegion value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  areaInAnalysisRegion;

		//	Try to initialize WidthCorrection from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  widthCorrection;
		else {
			//	Try to initialize WidthCorrection from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  widthCorrection;
		}
		//	And try to extract WidthCorrection value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  widthCorrection;

		//	Try to initialize NFramesBuffered from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  nFramesBuffered;
		else {
			//	Try to initialize NFramesBuffered from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  nFramesBuffered;
		}
		//	And try to extract NFramesBuffered value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  nFramesBuffered;

		//	Try to initialize AnalysisRegion from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  analysisRegion;
		else {
			//	Try to initialize AnalysisRegion from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  analysisRegion;
		}
		//	And try to extract AnalysisRegion value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  analysisRegion;

		//	Try to initialize RegionOfInterest from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  regionOfInterest;
		else {
			//	Try to initialize RegionOfInterest from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  regionOfInterest;
		}
		//	And try to extract RegionOfInterest value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  regionOfInterest;

		//	Try to initialize ExposureTime from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  exposureTime;
		else {
			//	Try to initialize ExposureTime from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  exposureTime;
		}
		//	And try to extract ExposureTime value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  exposureTime;

		//	Try to initialize SyncMode from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  syncMode;
		else {
			//	Try to initialize SyncMode from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  syncMode;
		}
		//	And try to extract SyncMode value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  syncMode;

		//	Try to initialize AutoStart from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  autoStart;
		else {
			//	Try to initialize AutoStart from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  autoStart;
		}
		//	And try to extract AutoStart value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  autoStart;

		//	Try to initialize NumPixel from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  numPixel;
		else {
			//	Try to initialize NumPixel from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  numPixel;
		}
		//	And try to extract NumPixel value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  numPixel;

		//	Try to initialize CameraLabel from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  cameraLabel;
		else {
			//	Try to initialize CameraLabel from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  cameraLabel;
		}
		//	And try to extract CameraLabel value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  cameraLabel;

	}

	/*----- PROTECTED REGION ID(CCDSpectrometer::get_device_property_after) ENABLED START -----*/
	/* clang-format on */
	//	Check device property data members init
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_device_property_after
}

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::always_executed_hook()
 *	Description: method always executed before any command is executed
 */
//--------------------------------------------------------
void CCDSpectrometer::always_executed_hook()
{
	DEBUG_STREAM << "CCDSpectrometer::always_executed_hook()  " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::always_executed_hook) ENABLED START -----*/
	/* clang-format on */
	//	code always executed before all requests
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::always_executed_hook
}

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::read_attr_hardware()
 *	Description: Hardware acquisition for attributes
 */
//--------------------------------------------------------
void CCDSpectrometer::read_attr_hardware(TANGO_UNUSED(std::vector<long> &attr_list))
{
	DEBUG_STREAM << "CCDSpectrometer::read_attr_hardware(std::vector<long> &attr_list) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_attr_hardware) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_attr_hardware
}
//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::write_attr_hardware()
 *	Description: Hardware writing for attributes
 */
//--------------------------------------------------------
void CCDSpectrometer::write_attr_hardware(TANGO_UNUSED(std::vector<long> &attr_list))
{
	DEBUG_STREAM << "CCDSpectrometer::write_attr_hardware(std::vector<long> &attr_list) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_attr_hardware) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_attr_hardware
}

//--------------------------------------------------------
/**
 *	Read attribute SyncMode related method
 *	Description: 0=SW
 *               1=HW Sync input
 *               2=HW external trigger
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_SyncMode(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_SyncMode(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_SyncMode) ENABLED START -----*/
	/* clang-format on */
	Tango::DevBoolean syncmode;
	try {
		dpmutex->lock();
		dp->read_attribute(TRIGGER_ATTR)>>(syncmode);
		dpmutex->unlock();
		*attr_SyncMode_read = syncmode ? 1 : 0;
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error reading =" << e.errors[0].desc;
	}
	//	Set the attribute value
	attr.set_value(attr_SyncMode_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_SyncMode
}
//--------------------------------------------------------
/**
 *	Write attribute SyncMode related method
 *	Description: 0=SW
 *               1=HW Sync input
 *               2=HW external trigger
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_SyncMode(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_SyncMode(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevLong	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_SyncMode) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	if(w_val < 0 || w_val > 1)
	{
		stringstream tmp;
		tmp << "Allowed values: 0=No Trigger, 1=HW Trigger";
		Tango::Except::throw_exception(
					(const char *) "OutOfRange",
					tmp.str(),
					(const char *) __func__, Tango::ERR);
	}
	Tango::DevBoolean syncmode = w_val==1;
	try {
		Tango::DeviceAttribute Din(TRIGGER_ATTR,syncmode);
		dpmutex->lock();
		dp->write_attribute(Din);
		dpmutex->unlock();
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error writing =" << e.errors[0].desc;
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_SyncMode
}
//--------------------------------------------------------
/**
 *	Read attribute ExposureTime related method
 *	Description: Exposure time in milliseconds
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_ExposureTime(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_ExposureTime(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_ExposureTime) ENABLED START -----*/
	/* clang-format on */
	Tango::DevLong exposure;
	try {
		dpmutex->lock();
		dp->read_attribute(EXPOSURE_ATTR)>>(exposure);
		dpmutex->unlock();
		*attr_ExposureTime_read = (double)exposure/1000.0;
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error reading =" << e.errors[0].desc;
	}
	//	Set the attribute value
	attr.set_value(attr_ExposureTime_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_ExposureTime
}
//--------------------------------------------------------
/**
 *	Write attribute ExposureTime related method
 *	Description: Exposure time in milliseconds
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_ExposureTime(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_ExposureTime(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevDouble	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_ExposureTime) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	Tango::DevLong exposure = (Tango::DevLong)(w_val*1000);
	try {
		Tango::DeviceAttribute Din(EXPOSURE_ATTR,exposure);
		dpmutex->lock();
		dp->write_attribute(Din);
		dpmutex->unlock();
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error writing =" << e.errors[0].desc;
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_ExposureTime
}
//--------------------------------------------------------
/**
 *	Read attribute NoiseSubtraction related method
 *	Description: Enable/Disable subtraction of background noise profile 
 *               acquired with the AcquireNoise command
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_NoiseSubtraction(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_NoiseSubtraction(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_NoiseSubtraction) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_NoiseSubtraction_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_NoiseSubtraction
}
//--------------------------------------------------------
/**
 *	Write attribute NoiseSubtraction related method
 *	Description: Enable/Disable subtraction of background noise profile 
 *               acquired with the AcquireNoise command
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_NoiseSubtraction(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_NoiseSubtraction(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_NoiseSubtraction) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_NoiseSubtraction_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_NoiseSubtraction
}
//--------------------------------------------------------
/**
 *	Read attribute GaussFitEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_GaussFitEnable(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_GaussFitEnable(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_GaussFitEnable) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_GaussFitEnable_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_GaussFitEnable
}
//--------------------------------------------------------
/**
 *	Write attribute GaussFitEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_GaussFitEnable(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_GaussFitEnable(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_GaussFitEnable) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_GaussFitEnable_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_GaussFitEnable
}
//--------------------------------------------------------
/**
 *	Read attribute FWHMEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_FWHMEnable(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_FWHMEnable(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_FWHMEnable) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_FWHMEnable_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_FWHMEnable
}
//--------------------------------------------------------
/**
 *	Write attribute FWHMEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_FWHMEnable(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_FWHMEnable(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_FWHMEnable) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_FWHMEnable_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_FWHMEnable
}
//--------------------------------------------------------
/**
 *	Read attribute GaussFitCenter related method
 *	Description: wavelength of peak of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_GaussFitCenter(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_GaussFitCenter(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_GaussFitCenter) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	if(GaussFit_valid)
	{
		attr.set_value(attr_GaussFitCenter_read);
	}
	else
	{
		attr.set_quality(Tango::ATTR_INVALID);
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_GaussFitCenter
}
//--------------------------------------------------------
/**
 *	Read attribute GaussFitWidth related method
 *	Description: width of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_GaussFitWidth(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_GaussFitWidth(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_GaussFitWidth) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	if(GaussFit_valid)
	{
		attr.set_value(attr_GaussFitWidth_read);
	}
	else
	{
		attr.set_quality(Tango::ATTR_INVALID);
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_GaussFitWidth
}
//--------------------------------------------------------
/**
 *	Read attribute FWHMCenter related method
 *	Description: wavelength of peak of FWHM
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_FWHMCenter(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_FWHMCenter(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_FWHMCenter) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_FWHMCenter_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_FWHMCenter
}
//--------------------------------------------------------
/**
 *	Read attribute FWHMWidth related method
 *	Description: width of FWHM
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_FWHMWidth(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_FWHMWidth(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_FWHMWidth) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_FWHMWidth_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_FWHMWidth
}
//--------------------------------------------------------
/**
 *	Read attribute Center related method
 *	Description: wavelength of peak of FWHM or of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_Center(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_Center(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_Center) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	if(*attr_FWHMEnable_read || (*attr_GaussFitEnable_read && GaussFit_valid))
		attr.set_value(attr_Center_read);
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_Center
}
//--------------------------------------------------------
/**
 *	Read attribute Width related method
 *	Description: width of FWHM or of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_Width(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_Width(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_Width) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	if(*attr_FWHMEnable_read || (*attr_GaussFitEnable_read && GaussFit_valid))
		attr.set_value(attr_Width_read);
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_Width
}
//--------------------------------------------------------
/**
 *	Read attribute FitType related method
 *	Description: 1=Gaussian 2=Gaussian Asymm 3=Confiteor
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_FitType(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_FitType(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_FitType) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_FitType_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_FitType
}
//--------------------------------------------------------
/**
 *	Write attribute FitType related method
 *	Description: 1=Gaussian 2=Gaussian Asymm 3=Confiteor
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_FitType(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_FitType(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevLong	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_FitType) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_FitType_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_FitType
}
//--------------------------------------------------------
/**
 *	Read attribute FWHMAvg related method
 *
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_FWHMAvg(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_FWHMAvg(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_FWHMAvg) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_FWHMAvg_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_FWHMAvg
}
//--------------------------------------------------------
/**
 *	Write attribute FWHMAvg related method
 *
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_FWHMAvg(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_FWHMAvg(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevLong	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_FWHMAvg) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_FWHMAvg_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_FWHMAvg
}
//--------------------------------------------------------
/**
 *	Read attribute NoiseLevel related method
 *
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_NoiseLevel(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_NoiseLevel(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_NoiseLevel) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	*attr_NoiseLevel_read = noise_level;
	attr.set_value(attr_NoiseLevel_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_NoiseLevel
}
//--------------------------------------------------------
/**
 *	Write attribute NoiseLevel related method
 *
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_NoiseLevel(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_NoiseLevel(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevLong	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_NoiseLevel) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	noise_level = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_NoiseLevel
}
//--------------------------------------------------------
/**
 *	Read attribute DataReferenceFile related method
 *
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_DataReferenceFile(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_DataReferenceFile(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_DataReferenceFile) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr_tmp_ptr = attr_strchar;
	attr_DataReferenceFile_read = &attr_tmp_ptr;
	attr.set_value(attr_DataReferenceFile_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_DataReferenceFile
}
//--------------------------------------------------------
/**
 *	Write attribute DataReferenceFile related method
 *
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_DataReferenceFile(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_DataReferenceFile(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevString	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_DataReferenceFile) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	ostringstream tempstr;

	tempstr << w_val << ends;
	if(tempstr.str().length() < sizeof(attr_strchar))
	{
		strcpy(attr_strchar,tempstr.str().c_str());
		if(strlen(attr_strchar) > 0)
		{
			dataReferenceFile  = tempstr.str();

			ifstream  fd;		//startup file
			fd.open(dataReferenceFile.c_str());
			if (!fd)
			{
				stringstream tmp;
				tmp << "Cannot open Data Reference file:" << strerror(errno) << endl;
				INFO_STREAM << "CCDSpectrometer::write_DataReferenceFile(): " << tmp.str();
				Tango::Except::throw_exception(
					(const char *) "Error opening file",
					tmp.str(),
					(const char *) "CCDSpectrometer::write_DataReferenceFile()", Tango::ERR);
			}
			else{
				DEBUG_STREAM << "CCDSpectrometer::write_DataReferenceFile(): file opened successfully" << endl;
				string lineread;
				int i=0;
				double val;
				while(std::getline(fd, lineread, '\n'))
				{ // Read line by line
					if(lineread.length() > 0 && i < numPixel)
					{
						sscanf(lineread.c_str(),"%lf",&val);
						pReferenceData[i++] = val;
					}
				}
				fd.close();
			}
		}
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_DataReferenceFile
}
//--------------------------------------------------------
/**
 *	Read attribute AutoExposure related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_AutoExposure(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_AutoExposure(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_AutoExposure) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_AutoExposure_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_AutoExposure
}
//--------------------------------------------------------
/**
 *	Write attribute AutoExposure related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_AutoExposure(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_AutoExposure(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_AutoExposure) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_AutoExposure_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_AutoExposure
}
//--------------------------------------------------------
/**
 *	Read attribute RtMode related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_RtMode(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_RtMode(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_RtMode) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_RtMode_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_RtMode
}
//--------------------------------------------------------
/**
 *	Write attribute RtMode related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_RtMode(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_RtMode(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_RtMode) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_RtMode_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_RtMode
}
//--------------------------------------------------------
/**
 *	Read attribute IntensityCalibrationEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_IntensityCalibrationEnable(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_IntensityCalibrationEnable(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_IntensityCalibrationEnable) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_IntensityCalibrationEnable_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_IntensityCalibrationEnable
}
//--------------------------------------------------------
/**
 *	Write attribute IntensityCalibrationEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_IntensityCalibrationEnable(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_IntensityCalibrationEnable(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_IntensityCalibrationEnable) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_IntensityCalibrationEnable_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_IntensityCalibrationEnable
}
//--------------------------------------------------------
/**
 *	Read attribute Area related method
 *
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_Area(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_Area(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_Area) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_Area_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_Area
}
//--------------------------------------------------------
/**
 *	Read attribute AreaRegion related method
 *
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_AreaRegion(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_AreaRegion(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_AreaRegion) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_AreaRegion_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_AreaRegion
}
//--------------------------------------------------------
/**
 *	Write attribute AreaRegion related method
 *
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_AreaRegion(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_AreaRegion(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevDouble	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_AreaRegion) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_AreaRegion_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_AreaRegion
}
//--------------------------------------------------------
/**
 *	Read attribute AreaEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_AreaEnable(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_AreaEnable(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_AreaEnable) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_AreaEnable_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_AreaEnable
}
//--------------------------------------------------------
/**
 *	Write attribute AreaEnable related method
 *
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_AreaEnable(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_AreaEnable(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_AreaEnable) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_AreaEnable_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_AreaEnable
}
//--------------------------------------------------------
/**
 *	Read attribute WidthCorrectionEnable related method
 *	Description: enable widht correction
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_WidthCorrectionEnable(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_WidthCorrectionEnable(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_WidthCorrectionEnable) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_WidthCorrectionEnable_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_WidthCorrectionEnable
}
//--------------------------------------------------------
/**
 *	Write attribute WidthCorrectionEnable related method
 *	Description: enable widht correction
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_WidthCorrectionEnable(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_WidthCorrectionEnable(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_WidthCorrectionEnable) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_WidthCorrectionEnable_read = w_val;
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_WidthCorrectionEnable
}
//--------------------------------------------------------
/**
 *	Read attribute IncrSensitivity related method
 *	Description: false: use standard sensitivity
 *               true: use increased sensitivity
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::read_IncrSensitivity(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_IncrSensitivity(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_IncrSensitivity) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_IncrSensitivity_read);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_IncrSensitivity
}
//--------------------------------------------------------
/**
 *	Write attribute IncrSensitivity related method
 *	Description: false: use standard sensitivity
 *               true: use increased sensitivity
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void CCDSpectrometer::write_IncrSensitivity(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_IncrSensitivity(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve write value
	Tango::DevBoolean	w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_IncrSensitivity) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	*attr_IncrSensitivity_read = w_val;//TODO: SUPPORTED?
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_IncrSensitivity
}
//--------------------------------------------------------
/**
 *	Read attribute Data related method
 *
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 4100
 */
//--------------------------------------------------------
void CCDSpectrometer::read_Data(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_Data(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_Data) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	//attr.set_value(attr_Data_read, DataAttrib::X_DATA_SIZE);
#ifdef _NON_AVERAGE
	if(pLiveData)
	{
		attr_Data_read = (Tango::DevLong *)&(pLiveData[0 + attr_RegionOfInterest_read[0]]);
		attr.set_value(attr_Data_read,attr_RegionOfInterest_read[1] - attr_RegionOfInterest_read[0]);
	}
#else
	if(pLiveData_avg)
	{
		//DEBUG_STREAM << "CCDSpectrometer::read_Data() ROIStartPix"<<RegionOfInterestStartPix<<" ROIEndPix="<<RegionOfInterestEndPix<<" size="<<RegionOfInterestEndPix - RegionOfInterestStartPix + 1<< endl;
		//attr_Data_read = (Tango::DevLong *)&(pLiveData_avg[0 + WaveLenght2Pix(attr_RegionOfInterest_read[0])]);
		attr_Data_read = (Tango::DevDouble *)&(pLiveData_avg[0 + RegionOfInterestStartPix]);
		//attr.set_value(attr_Data_read,WaveLenght2Pix(attr_RegionOfInterest_read[1]) - WaveLenght2Pix(attr_RegionOfInterest_read[0]));
		attr.set_value(attr_Data_read,RegionOfInterestEndPix - RegionOfInterestStartPix + 1);
	}
#endif
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_Data
}
//--------------------------------------------------------
/**
 *	Read attribute NumPixels related method
 *	Description: long[0]: number of pixels horizontally (number of CCD-array columns)
 *               long[1]: number of pixels vertically (number of CCD-array lines)
 *
 *	Data type:	Tango::DevLong
 *	Attr type:	Spectrum max = 2
 */
//--------------------------------------------------------
void CCDSpectrometer::read_NumPixels(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_NumPixels(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_NumPixels) ENABLED START -----*/
	/* clang-format on */
	attr_NumPixels_read[0] = numPixel;
	attr_NumPixels_read[1] = 1;
	//	Set the attribute value
	attr.set_value(attr_NumPixels_read, NumPixelsAttrib::X_DATA_SIZE);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_NumPixels
}
//--------------------------------------------------------
/**
 *	Read attribute RegionOfInterest related method
 *	Description: Region of interest returned by the Data attribute
 *               double[0]=start of the region
 *               double[1]=end of the region
 *               
 *               Values are in nm according with the conversion factor in x_values
 *               Data attribute property
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 2
 */
//--------------------------------------------------------
void CCDSpectrometer::read_RegionOfInterest(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_RegionOfInterest(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_RegionOfInterest) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	vector<Tango::DevLong> hwroi;
	try {
		dpmutex->lock();
		dp->read_attribute(ROI_ATTR)>>(hwroi);
		dpmutex->unlock();
		DEBUG_STREAM << __func__ << ": read hwroi.size=" << hwroi.size();
		if(hwroi.size() >= 4)
		{
			if(hwroi[0] > 0 && hwroi[0] < numPixel)
			{
				attr_RegionOfInterest_read[0] = x_values[hwroi[0]];
				RegionOfInterestStartPix = hwroi[0];
				
			}
			if(hwroi[2] > 0 && hwroi[2] < numPixel)
			{
				attr_RegionOfInterest_read[1] = x_values[hwroi[2]];
				RegionOfInterestEndPix =  hwroi[2];
			}
		}
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error reading =" << e.errors[0].desc;
		Tango::Except::re_throw_exception(e,
			(const char *) "Error",
			(const char *) "Read Error",
			(const char *) __func__, Tango::ERR);
	}


	attr.set_value(attr_RegionOfInterest_read, RegionOfInterestAttrib::X_DATA_SIZE);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_RegionOfInterest
}
//--------------------------------------------------------
/**
 *	Write attribute RegionOfInterest related method
 *	Description: Region of interest returned by the Data attribute
 *               double[0]=start of the region
 *               double[1]=end of the region
 *               
 *               Values are in nm according with the conversion factor in x_values
 *               Data attribute property
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 2
 */
//--------------------------------------------------------
void CCDSpectrometer::write_RegionOfInterest(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_RegionOfInterest(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve number of write values
	int	w_length = attr.get_write_value_length();

	//	Retrieve pointer on write values (Do not delete !)
	const Tango::DevDouble	*w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_RegionOfInterest) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	if(get_state()==Tango::FAULT)
	{
		Tango::Except::throw_exception(
			(const char *) "CCD not communicating",
			(const char *) "CCD not communicating",
			(const char *) __func__, Tango::ERR);
	}
	if(w_length != 2)
	{
		Tango::Except::throw_exception(
			(const char *) "Wrong parameters",
			(const char *) "Expected 2 parameters",
			(const char *) __func__, Tango::ERR);
	}
	Tango::DevDouble	w_val_[2];
	w_val_[0] = floor(w_val[0]*1000.0)*0.001;
	w_val_[1] = floor(w_val[1]*1000.0)*0.001;
	if(w_val_[0] < x_values[0] || w_val_[0] > x_values[numPixel-1] ||
			w_val_[1] < x_values[0] || w_val_[1] > x_values[numPixel-1] ||
			w_val_[0] >= w_val_[1])
	{
		TangoSys_MemStream out_stream;
		out_stream << "Region ["<<w_val_[0]<<","<<w_val_[1]<<"] not allowed, it has to be in ["<<x_values[0]<<"," << x_values[numPixel-1] << "]" << ends;
		Tango::Except::throw_exception(
			(const char *) "Value not Allowed",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	RegionOfInterestStartPix = WaveLenght2Pix(w_val_[0]);
	DEBUG_STREAM << __func__<<": StartROI="<<w_val_[0]<<" -> start pix="<<RegionOfInterestStartPix;
	if(x_values[RegionOfInterestStartPix] < w_val_[0])
	{
		RegionOfInterestStartPix++;
	}
	DEBUG_STREAM << __func__<<": ...-> adjusted start pix="<<RegionOfInterestStartPix;
	attr_RegionOfInterest_read[0] = x_values[RegionOfInterestStartPix];
	RegionOfInterestEndPix = WaveLenght2Pix(w_val_[1]);
	DEBUG_STREAM << __func__<<": EndROI="<<w_val_[1]<<" -> end pix="<<RegionOfInterestEndPix;
	if(x_values[RegionOfInterestEndPix] > w_val_[1])
	{
		RegionOfInterestEndPix--;
	}
	DEBUG_STREAM << __func__<<": ...-> adjusted end pix="<<RegionOfInterestEndPix;
	attr_RegionOfInterest_read[1] = x_values[RegionOfInterestEndPix];
	tbuf_array_w.reset_rt_buffer();
	tbuf_array_l.reset_rt_buffer();

	vector<Tango::DevLong> hwroi_r;
	vector<Tango::DevLong> hwroi_w;
	try {
		dpmutex->lock();
		dp->read_attribute(ROI_ATTR)>>(hwroi_r);
		if(hwroi_r.size() >= 4)
		{
			hwroi_w.push_back(RegionOfInterestStartPix);
			hwroi_w.push_back(hwroi_r[1]);
			hwroi_w.push_back(RegionOfInterestEndPix);
			hwroi_w.push_back(hwroi_r[3]);
		}
		Tango::DeviceAttribute Din(ROI_ATTR,hwroi_w);
		dp->write_attribute(Din);
		dpmutex->unlock();		
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error reading =" << e.errors[0].desc;
		Tango::Except::re_throw_exception(e,
			(const char *) "Error",
			(const char *) "Read Error",
			(const char *) __func__, Tango::ERR);
	}


	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_RegionOfInterest
}
//--------------------------------------------------------
/**
 *	Read attribute AnalysisRegion related method
 *	Description: Region used for gaussian and fwhm analysis
 *               double[0]=start of the region
 *               double[1]=end of the region
 *               
 *               Values are in nm according with the conversion factor in x_values
 *               Data attribute property
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 2
 */
//--------------------------------------------------------
void CCDSpectrometer::read_AnalysisRegion(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_AnalysisRegion(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_AnalysisRegion) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_AnalysisRegion_read, AnalysisRegionAttrib::X_DATA_SIZE);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_AnalysisRegion
}
//--------------------------------------------------------
/**
 *	Write attribute AnalysisRegion related method
 *	Description: Region used for gaussian and fwhm analysis
 *               double[0]=start of the region
 *               double[1]=end of the region
 *               
 *               Values are in nm according with the conversion factor in x_values
 *               Data attribute property
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 2
 */
//--------------------------------------------------------
void CCDSpectrometer::write_AnalysisRegion(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_AnalysisRegion(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve number of write values
	int	w_length = attr.get_write_value_length();

	//	Retrieve pointer on write values (Do not delete !)
	const Tango::DevDouble	*w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_AnalysisRegion) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	if(get_state()==Tango::FAULT)
	{
		Tango::Except::throw_exception(
			(const char *) "CCD not communicating",
			(const char *) "CCD not communicating",
			(const char *) __func__, Tango::ERR);
	}	if(w_val[0] < x_values[0] || w_val[0] > x_values[numPixel-1] ||
		w_val[1] < x_values[0] || w_val[1] > x_values[numPixel-1] ||
		w_val[0] >= w_val[1])
	{
		TangoSys_MemStream out_stream;
		out_stream << "Region not allowed, it has to be in ["<<x_values[0]<<"," << x_values[numPixel-1] << "]" << ends;
		Tango::Except::throw_exception(
			(const char *) "Value not Allowed",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	AnalysisRegionStartPix = WaveLenght2Pix(w_val[0]);
	if(x_values[AnalysisRegionStartPix] < w_val[0])
	{
		AnalysisRegionStartPix++;
	}
	attr_AnalysisRegion_read[0] = x_values[AnalysisRegionStartPix];
	AnalysisRegionEndPix = WaveLenght2Pix(w_val[1]);
	if(x_values[AnalysisRegionEndPix] > w_val[1])
	{
		AnalysisRegionEndPix--;
	}
	attr_AnalysisRegion_read[1] = x_values[AnalysisRegionEndPix];
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_AnalysisRegion
}
//--------------------------------------------------------
/**
 *	Read attribute GaussFit related method
 *	Description: double[0]= wavelength of peak of Gaussian Fit
 *               double[1]= width of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 4
 */
//--------------------------------------------------------
void CCDSpectrometer::read_GaussFit(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_GaussFit(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_GaussFit) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	if(GaussFit_valid)
	{
		attr.set_value(attr_GaussFit_read,GaussFitAttrib::X_DATA_SIZE);
	}
	else
	{
		attr.set_quality(Tango::ATTR_INVALID);
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_GaussFit
}
//--------------------------------------------------------
/**
 *	Read attribute FWHM related method
 *	Description: double[0]= wavelength of peak of FWHM
 *               double[1]= width of FWHM
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 3
 */
//--------------------------------------------------------
void CCDSpectrometer::read_FWHM(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_FWHM(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_FWHM) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_FWHM_read, FWHMAttrib::X_DATA_SIZE);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_FWHM
}
//--------------------------------------------------------
/**
 *	Read attribute GaussReference related method
 *	Description: double[0]= wavelength of peak of Gaussian Fit
 *               double[1]= width of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 4
 */
//--------------------------------------------------------
void CCDSpectrometer::read_GaussReference(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_GaussReference(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_GaussReference) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_GaussReference_read, GaussReferenceAttrib::X_DATA_SIZE);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_GaussReference
}
//--------------------------------------------------------
/**
 *	Write attribute GaussReference related method
 *	Description: double[0]= wavelength of peak of Gaussian Fit
 *               double[1]= width of Gaussian Fit
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 4
 */
//--------------------------------------------------------
void CCDSpectrometer::write_GaussReference(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_GaussReference(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve number of write values
	int	w_length = attr.get_write_value_length();

	//	Retrieve pointer on write values (Do not delete !)
	const Tango::DevDouble	*w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_GaussReference) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	attr_GaussReference_read[0] = w_val[0];
	attr_GaussReference_read[1] = w_val[1];
	attr_GaussReference_read[2] = w_val[2];
	attr_GaussReference_read[3] = w_val[3];
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_GaussReference
}
//--------------------------------------------------------
/**
 *	Read attribute DataReference related method
 *	Description: A reference curve
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::read_DataReference(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_DataReference(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_DataReference) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	if(pReferenceData)
	{
		//attr_DataReference_read = (Tango::DevLong *)&(pReferenceData[0 + WaveLenght2Pix(attr_RegionOfInterest_read[0])]);
		attr_DataReference_read = (Tango::DevDouble *)&(pReferenceData[0 + RegionOfInterestStartPix]);
		//attr.set_value(attr_DataReference_read,WaveLenght2Pix(attr_RegionOfInterest_read[1]) - WaveLenght2Pix(attr_RegionOfInterest_read[0]));
		attr.set_value(attr_DataReference_read,RegionOfInterestEndPix - RegionOfInterestStartPix + 1);
	}
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_DataReference
}
//--------------------------------------------------------
/**
 *	Write attribute DataReference related method
 *	Description: A reference curve
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::write_DataReference(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_DataReference(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve number of write values
	int	w_length = attr.get_write_value_length();

	//	Retrieve pointer on write values (Do not delete !)
	const Tango::DevDouble	*w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_DataReference) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	if((attr.get_write_value_length() != RegionOfInterestEndPix - RegionOfInterestStartPix + 1) &&
		(attr.get_write_value_length() != numPixel))
	{
		ostringstream tmp;
		tmp << "Accepting attribute size = " << numPixel << " or " << RegionOfInterestEndPix - RegionOfInterestStartPix + 1 << ends;
		Tango::Except::throw_exception(
			(const char *) "Wrong size",
			tmp.str(),
			(const char *) "CCDSpectrometer::write_DataReference()", Tango::ERR);
	}	if(attr.get_write_value_length() == RegionOfInterestEndPix - RegionOfInterestStartPix + 1)
	{
		for(unsigned int i=0; i<RegionOfInterestStartPix; i++)
			pReferenceData[i] = 0;
		for(unsigned int i=RegionOfInterestStartPix; i< RegionOfInterestEndPix + 1; i++)
			pReferenceData[i] = w_val[i-RegionOfInterestStartPix];
		for(unsigned int i=RegionOfInterestEndPix + 1; i<numPixel; i++)
			pReferenceData[i] = 0;
	}
	else if(attr.get_write_value_length() == numPixel)
	{
		for(unsigned int i=0; i< numPixel; i++)
			pReferenceData[i] = w_val[i];
	}

	ofstream  fd;		//startup file
	fd.open(dataReferenceFile.c_str());
	if (!fd)
	{
		stringstream tmp;
		tmp << "Cannot open Data Reference default file " << dataReferenceFile<< "  err:" << strerror(errno) << endl;
		INFO_STREAM << "CCDSpectrometer::write_DataReference(): " << tmp.str();
   	}
	else
	{
		DEBUG_STREAM << "CCDSpectrometer::write_DataReference(): file " << dataReferenceFile << " opened successfully" << endl;
		for(size_t i=0; i<numPixel; i++)
		{
			fd << pReferenceData[i] << endl;
		}
		fd.close();
	}
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_DataReference
}
//--------------------------------------------------------
/**
 *	Read attribute IntensityCalibration related method
 *	Description: A reference curve
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::read_IntensityCalibration(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_IntensityCalibration(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_IntensityCalibration) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
	attr.set_value(attr_IntensityCalibration_read, numPixel);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_IntensityCalibration
}
//--------------------------------------------------------
/**
 *	Write attribute IntensityCalibration related method
 *	Description: A reference curve
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::write_IntensityCalibration(Tango::WAttribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::write_IntensityCalibration(Tango::WAttribute &attr) entering... " << std::endl;
	//	Retrieve number of write values
	int	w_length = attr.get_write_value_length();

	//	Retrieve pointer on write values (Do not delete !)
	const Tango::DevDouble	*w_val;
	attr.get_write_value(w_val);
	/*----- PROTECTED REGION ID(CCDSpectrometer::write_IntensityCalibration) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	if(w_length != numPixel)
	{
		ostringstream tmp;
		tmp << "Expected size is " << numPixel << " but read " << w_length << ends;
		Tango::Except::throw_exception(
			(const char *) "Wrong size",
			tmp.str(),
			(const char *) "CCDSpectrometer::write_IntensityCalibration()", Tango::ERR);
	}
	for(int i=0; i<w_length; i++)
	{
		attr_IntensityCalibration_read[i] = w_val[i];
	}
	save_intensity_cal_file(intensityCalibrationFile);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::write_IntensityCalibration
}
//--------------------------------------------------------
/**
 *	Read attribute NoiseProfile related method
 *	Description: A reference curve
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::read_NoiseProfile(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_NoiseProfile(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_NoiseProfile) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
#ifdef _NON_AVERAGE
	if(pNoiseMask)
	{
		attr_Data_read = (Tango::DevLong *)&(pNoiseMask[0 + attr_RegionOfInterest_read[0]]);
		attr.set_value(attr_NoiseMask_read,attr_RegionOfInterest_read[1] - attr_RegionOfInterest_read[0]);
	}
#else
	if(pNoiseMask_avg)
	{
		attr_NoiseProfile_read = (Tango::DevDouble *)&(pNoiseMask_avg[0 + RegionOfInterestStartPix]);
		attr.set_value(attr_NoiseProfile_read,RegionOfInterestEndPix - RegionOfInterestStartPix + 1);
	}
#endif
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_NoiseProfile
}
//--------------------------------------------------------
/**
 *	Read attribute Wave related method
 *
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::read_Wave(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_Wave(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_Wave) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
#ifdef _NON_AVERAGE
	if(pLiveData)
	{
		attr_Wave_read = (Tango::DevLong *)&(pLiveData[0 + attr_RegionOfInterest_read[0]]);
		attr.set_value(attr_Wave_read,attr_RegionOfInterest_read[1] - attr_RegionOfInterest_read[0]);
	}
#else
	if(pLiveData_avg)
	{
		//DEBUG_STREAM << "CCDSpectrometer::read_Data() ROIStartPix"<<RegionOfInterestStartPix<<" ROIEndPix="<<RegionOfInterestEndPix<<" size="<<RegionOfInterestEndPix - RegionOfInterestStartPix + 1<< endl;
		//attr_Wave_read = (Tango::DevLong *)&(pLiveData_avg[0 + WaveLenght2Pix(attr_RegionOfInterest_read[0])]);
		attr_Wave_read = (Tango::DevDouble *)&(pLiveData_avg[0 + RegionOfInterestStartPix]);
		//attr.set_value(attr_Wave_read,WaveLenght2Pix(attr_RegionOfInterest_read[1]) - WaveLenght2Pix(attr_RegionOfInterest_read[0]));
		attr.set_value(attr_Wave_read,RegionOfInterestEndPix - RegionOfInterestStartPix + 1);
	}
#endif
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_Wave
}
//--------------------------------------------------------
/**
 *	Read attribute Lambda related method
 *
 *
 *	Data type:	Tango::DevDouble
 *	Attr type:	Spectrum max = 5000
 */
//--------------------------------------------------------
void CCDSpectrometer::read_Lambda(Tango::Attribute &attr)
{
	DEBUG_STREAM << "CCDSpectrometer::read_Lambda(Tango::Attribute &attr) entering... " << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::read_Lambda) ENABLED START -----*/
	/* clang-format on */
	//	Set the attribute value
#ifdef _NON_AVERAGE
	if(pLiveData)
	{
		attr_Lambda_read = (Tango::DevLong *)&(pLiveData[0 + attr_RegionOfInterest_read[0]]);
		attr.set_value(attr_Lambda_read,attr_RegionOfInterest_read[1] - attr_RegionOfInterest_read[0]);
	}
#else
	if(pLiveData_avg)
	{
		//DEBUG_STREAM << "CCDSpectrometer::read_Data() ROIStartPix"<<RegionOfInterestStartPix<<" ROIEndPix="<<RegionOfInterestEndPix<<" size="<<RegionOfInterestEndPix - RegionOfInterestStartPix + 1<< endl;
		//attr_Lambda_read = (Tango::DevLong *)&(x_values[0 + WaveLenght2Pix(attr_RegionOfInterest_read[0])]);
		attr_Lambda_read = (Tango::DevDouble *)&(x_values[0 + RegionOfInterestStartPix]);
		//attr.set_value(attr_Lambda_read,WaveLenght2Pix(attr_RegionOfInterest_read[1]) - WaveLenght2Pix(attr_RegionOfInterest_read[0]));
		attr.set_value(attr_Lambda_read,RegionOfInterestEndPix - RegionOfInterestStartPix + 1);
	}
#endif
	else
		attr.set_quality(Tango::ATTR_INVALID);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::read_Lambda
}

//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::add_dynamic_attributes()
 *	Description: Create the dynamic attributes if any
 *                for specified device.
 */
//--------------------------------------------------------
void CCDSpectrometer::add_dynamic_attributes()
{
	/*----- PROTECTED REGION ID(CCDSpectrometer::add_dynamic_attributes) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code to create and add dynamic attributes if any
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::add_dynamic_attributes
}

//--------------------------------------------------------
/**
 *	Command Start related method
 *
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::start()
{
	DEBUG_STREAM << "CCDSpectrometer::Start()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::start) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	start_continuous();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::start
}
//--------------------------------------------------------
/**
 *	Command Stop related method
 *
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::stop()
{
	DEBUG_STREAM << "CCDSpectrometer::Stop()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::stop) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(get_state() == Tango::ON)
	{
		TangoSys_MemStream out_stream;
		out_stream << "Device already stopped" << ends;
		Tango::Except::throw_exception(
			(const char *) "Device stopped",
			out_stream.str(),
			(const char *) "CCDSpectrometer::stop()", Tango::ERR);
	}
	try {
		dpmutex->lock();
		dp->command_inout(STOP_CMD);
		dpmutex->unlock();
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error command =" << e.errors[0].desc;
		Tango::Except::re_throw_exception(e,
			(const char *) "Error",
			(const char *) "Command Error",
			(const char *) __func__, Tango::ERR);
	}

	//	Add your own code to control device here
	loop->pausesec = 1;
	live_mode = false;
	init_live_mode = false;
	measure_mode = false;
	init_measure_mode = false;
	if(get_state() != Tango::FAULT)
		stop_mode = true;
	omni_thread::sleep(0,200000000);	//0.2 s
	//loop->mutex_sleep->lock();
	loop->pausesec = 1;
	loop->pausenano = 0;
	if(get_state() != Tango::FAULT)
		set_status("Ready");
	//loop->mutex_sleep->unlock();
	set_state(Tango::ON);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::stop
}
//--------------------------------------------------------
/**
 *	Command Reset related method
 *
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::reset()
{
	DEBUG_STREAM << "CCDSpectrometer::Reset()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::reset) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	Tango::Except::throw_exception(
			(const char *) "NotSupported",
			(const char *) "Command not supported",
			(const char *) __func__, Tango::ERR);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::reset
}
//--------------------------------------------------------
/**
 *	Command StartSingle related method
 *	Description: Start single acquisition
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::start_single()
{
	DEBUG_STREAM << "CCDSpectrometer::StartSingle()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::start_single) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	Tango::Except::throw_exception(
			(const char *) "NotSupported",
			(const char *) "Command not supported",
			(const char *) __func__, Tango::ERR);
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::start_single
}
//--------------------------------------------------------
/**
 *	Command StartContinuous related method
 *	Description: Start acquisition in Continuous mode
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::start_continuous()
{
	DEBUG_STREAM << "CCDSpectrometer::StartContinuous()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::start_continuous) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(get_state() != Tango::ON && get_state() != Tango::OFF)
	{
		TangoSys_MemStream out_stream;
		out_stream << "Device not ready, it is in '" << get_status() << "'" << ends;
		Tango::Except::throw_exception(
			(const char *) "Device not ready",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	if(get_state() == Tango::OFF)
	{
		vector<Tango::DevLong> exposure;
		try {
			dpmutex->lock();
			dp->read_attribute(EXPOSURE_ATTR)>>(exposure);
			dpmutex->unlock();
			cout << __func__ << ": exposure size=" << exposure.size();
			*attr_ExposureTime_read = (double)exposure[1]/1000.0;
		}
		catch(Tango::DevFailed &e)
		{
			dpmutex->unlock();
			INFO_STREAM << __func__ << ": error reading =" << e.errors[0].desc;
		}
	}
	if(*attr_ExposureTime_read <=0)
	{
		TangoSys_MemStream out_stream;
		out_stream << "ExposureTime invalid" << ends;
		Tango::Except::throw_exception(
			(const char *) "ExposureTime invalid",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	try {
		Tango::DeviceData Din;
        Din << cameraLabel.c_str();
		dpmutex->lock();
		dp->command_inout(START_CMD, Din);
		dpmutex->unlock();
	}
	catch(Tango::DevFailed &e)
	{
		dpmutex->unlock();
		INFO_STREAM << __func__ << ": error command =" << e.errors[0].desc;
#if 0//TODO: to skip ALARM: "signal under threshold" on the CCD
		Tango::Except::re_throw_exception(e,
			(const char *) "Error",
			(const char *) "Command Error",
			(const char *) __func__, Tango::ERR);
#endif
	}
	clock_gettime(CLOCK_MONOTONIC,&last_read);
	set_state(Tango::RUNNING);
	set_status("Continuous Mode");
	loop->min_fit_time = 1000000000.0;
	loop->max_fit_time = 0;
	loop->avg_fit_time = 0;
	loop->tot_fit_time = 0;
	loop->fit_counter = 0;
	measure_mode = false;
	init_measure_mode = false;
	acquire_noise_mode = false;
	init_acquire_noise_mode = false;
	live_mode = true;
	init_live_mode = true;
	stop_mode = false;

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::start_continuous
}
//--------------------------------------------------------
/**
 *	Command GetLastData related method
 *	Description: returns the last argin frames saved
 *
 *	@param argin number of frames to return
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_last_data(Tango::DevLong argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetLastData()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_last_data) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(get_state() == Tango::FAULT)
	{
		TangoSys_MemStream out_stream;
		out_stream << "Device not ready, it is in '" << get_status() << "'" << ends;
		Tango::Except::throw_exception(
			(const char *) "Device not ready",
			out_stream.str(),
			(const char *) "CCDSpectrometer::get_last_data()", Tango::ERR);
	}
	argout  = new Tango::DevVarDoubleArray();
	DEBUG_STREAM << "CCDSpectrometer::get_last_data(): entering... FrameBufferIndex=" << FrameBufferIndex << endl;

	//	Add your own code to control device here
	if(argin > nFramesBuffered || argin < 1)
	{
		TangoSys_MemStream out_stream;
		out_stream << "MAx number of frames=" << nFramesBuffered << ends;
		Tango::Except::throw_exception(
			(const char *) "Argin out of bounds",
			out_stream.str(),
			(const char *) "CCDSpectrometer::get_last_data()", Tango::ERR);
	}
	//int region_size = RegionOfInterestEndPix - RegionOfInterestStartPix;
	//argout->length(argin * numPixel);
	int j;
	DEBUG_STREAM << "CCDSpectrometer::get_last_data() (FrameBufferIndex - argin)=" << ((int)FrameBufferIndex - argin) << endl;
	if(((int)FrameBufferIndex - argin) >= 0)
	{
		j = (int)FrameBufferIndex - argin;
	}
	else
	{
		j = nFramesBuffered - (argin - FrameBufferIndex);
	}
	int region_size = RegionOfInterestEndPix - RegionOfInterestStartPix + 1;
	argout->length(argin * region_size);
	DEBUG_STREAM << "CCDSpectrometer::get_last_data: region size=" << region_size << " new data_counter=" << argin * region_size << endl;
	for(int i=0; i < argin; i++)
	{
		//DEBUG_STREAM << "CCDSpectrometer::get_last_data() copying DATA! from " << j*numPixel << " to " << i*numPixel << endl;
		//copying only region of interest:
		//i*region_size: beginning of frame=i reduced to dimension region_size
		//j*numPixel: beginning of original frame=j of dimension numPixel
		//j*numPixel + attr_RegionOfInterest_read[0]: beginning of region of interest in frame=j
		memcpy(&((*argout)[i*region_size]),&(pFrameBuffer[j*numPixel + RegionOfInterestStartPix]), region_size*sizeof(double));
		j = (j + 1) % nFramesBuffered;
	}

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_last_data
	return argout;
}
//--------------------------------------------------------
/**
 *	Command AcquireNoise related method
 *	Description: Acquire argin frames of background noise
 *
 *	@param argin Number of frames to acquire as noise
 */
//--------------------------------------------------------
void CCDSpectrometer::acquire_noise(Tango::DevLong argin)
{
	DEBUG_STREAM << "CCDSpectrometer::AcquireNoise()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::acquire_noise) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(get_state() != Tango::ON)
	{
		TangoSys_MemStream out_stream;
		out_stream << "Device not ready, it is in '" << get_status() << "'" << ends;
		Tango::Except::throw_exception(
			(const char *) "Device not ready",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	if(argin <= 0)
	{
		TangoSys_MemStream out_stream;
		out_stream << "Number of frames has to be > 0" << ends;
		Tango::Except::throw_exception(
			(const char *) "Wrong argument",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	if(*attr_ExposureTime_read <=0)
	{
		TangoSys_MemStream out_stream;
		out_stream << "ExposureTime invalid" << ends;
		Tango::Except::throw_exception(
			(const char *) "ExposureTime invalid",
			out_stream.str(),
			(const char *) __func__, Tango::ERR);
	}
	noise_frames = argin;
	noise_frames_counter = 0;
	set_state(Tango::RUNNING);
	set_status("Acquiring noise");
	live_mode = false;
	init_live_mode = false;
	measure_mode = false;
	init_measure_mode = false;
	acquire_noise_mode = true;
	init_acquire_noise_mode = true;

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::acquire_noise
}
//--------------------------------------------------------
/**
 *	Command SaveReferenceData related method
 *	Description: Save current curve as reference curve
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::save_reference_data()
{
	DEBUG_STREAM << "CCDSpectrometer::SaveReferenceData()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::save_reference_data) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	ofstream  fd;		//startup file
	fd.open(dataReferenceFile.c_str());
	for(unsigned int i=0; i<numPixel; i++)
	{
#ifdef _NON_AVERAGE
		if(pLiveData && pReferenceData)
		{
			pReferenceData[i] = pLiveData[i];
			if (fd)
			{
				fd << (long)pReferenceData[i] << endl;
			}
		}
#else
		if(pLiveData_avg && pReferenceData)
		{
			pReferenceData[i] = pLiveData_avg[i];
			if (fd)
			{
				fd << (double)pReferenceData[i] << endl;
			}
		}
#endif
	}

	if (!fd)
	{
		stringstream tmp;
		tmp << "Cannot save on Data Reference file " << dataReferenceFile<< "  err:" << strerror(errno) << endl;
		INFO_STREAM << "AvaSpec::save_reference_data(): " << tmp.str();
		Tango::Except::throw_exception(
			(const char *) "File opening exception",
			tmp.str(),
			(const char *) "AvaSpec::save_reference_data()", Tango::ERR);
   	}
	else
	{
		fd.close();
	}

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::save_reference_data
}
//--------------------------------------------------------
/**
 *	Command GetData related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_data(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetData()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_data) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<tbuffer::_data_array<double> >(argin, &tbuf_array, buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	num_samples *= tbuf_array.get_data_size();
	argout->length(num_samples);
	tbuffer::_data_array<double> foo;
	tbuf_array.read_data(unique, buf_idx, &(*argout)[0], &foo);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_data
	return argout;
}
//--------------------------------------------------------
/**
 *	Command GetGaussFitCenter related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_gauss_fit_center(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetGaussFitCenter()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_gauss_fit_center) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<double>(argin, &tbuf[BUF_ID_GAUSS_CENTER], buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	argout->length(num_samples);
	tbuf[BUF_ID_GAUSS_CENTER].read_data_calib(unique, buf_idx, &(*argout)[0], 0, 1, 0);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_gauss_fit_center
	return argout;
}
//--------------------------------------------------------
/**
 *	Command GetGaussFitWidth related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_gauss_fit_width(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetGaussFitWidth()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_gauss_fit_width) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<double>(argin, &tbuf[BUF_ID_GAUSS_WIDTH], buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	argout->length(num_samples);
	tbuf[BUF_ID_GAUSS_WIDTH].read_data_calib(unique, buf_idx, &(*argout)[0], 0, 1, 0);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_gauss_fit_width
	return argout;
}
//--------------------------------------------------------
/**
 *	Command GetFWHMCenter related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_fwhmcenter(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetFWHMCenter()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_fwhmcenter) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<double>(argin, &tbuf[BUF_ID_FWHM_CENTER], buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	argout->length(num_samples);
	tbuf[BUF_ID_FWHM_CENTER].read_data_calib(unique, buf_idx, &(*argout)[0], 0, 1, 0);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_fwhmcenter
	return argout;
}
//--------------------------------------------------------
/**
 *	Command GetFWHMWidth related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_fwhmwidth(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetFWHMWidth()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_fwhmwidth) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tcheck_get_data_param(argin, &tbuf[BUF_ID_FWHM_WIDTH], buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	argout->length(num_samples);
	tbuf[BUF_ID_FWHM_WIDTH].read_data_calib(unique, buf_idx, &(*argout)[0], 0, 1, 0);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_fwhmwidth
	return argout;
}
//--------------------------------------------------------
/**
 *	Command ExportWavelength related method
 *
 *
 */
//--------------------------------------------------------
void CCDSpectrometer::export_wavelength()
{
	DEBUG_STREAM << "CCDSpectrometer::ExportWavelength()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::export_wavelength) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(wavelengthAttr.size() != 2)
	{
		Tango::Except::throw_exception(
			(const char *) "Beam Status Server Not Set",
			(const char *) "Beam Status Server Not Set",
			(const char *) "SolarS100::export_wavelength()", Tango::ERR);
	}
	Tango::DeviceProxy *devbeamstatus;
	devbeamstatus = new Tango::DeviceProxy(wavelengthAttr[0]);
	try
	{
		Tango::DeviceAttribute Din(wavelengthAttr[1],*attr_Center_read);
		devbeamstatus->write_attribute(Din);
	}
	catch(Tango::DevFailed e)
	{
		delete devbeamstatus;
		stringstream tmp;
		tmp << "Failed to write attribute, err=" <<e.errors[0].desc;
		Tango::Except::re_throw_exception(e,
			(const char *) "Failed",
			tmp.str(),
			(const char *) "SolarS100::export_wavelength()", Tango::ERR);
	}
	delete devbeamstatus;

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::export_wavelength
}
//--------------------------------------------------------
/**
 *	Command GetArea related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_area(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetArea()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_area) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<double>(argin, &tbuf[BUF_ID_AREA], buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	argout->length(num_samples);
	tbuf[BUF_ID_AREA].read_data_calib(unique, buf_idx, &(*argout)[0], 0, 1, 0);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_area
	return argout;
}
//--------------------------------------------------------
/**
 *	Command GetWave related method
 *	Description: Same as GetData
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_wave(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetWave()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_wave) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<tbuffer::_data_array<double> >(argin, &tbuf_array_w, buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	num_samples *= tbuf_array_w.get_data_size();
	argout->length(num_samples);
	tbuffer::_data_array<double> foo;
	tbuf_array_w.read_data(unique, buf_idx, &(*argout)[0], &foo);

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_wave
	return argout;
}
//--------------------------------------------------------
/**
 *	Command GetLambda related method
 *
 *
 *	@param argin
 *	@returns
 */
//--------------------------------------------------------
Tango::DevVarDoubleArray *CCDSpectrometer::get_lambda(const Tango::DevVarLongArray *argin)
{
	Tango::DevVarDoubleArray *argout;
	DEBUG_STREAM << "CCDSpectrometer::GetLambda()  - " << device_name << std::endl;
	/*----- PROTECTED REGION ID(CCDSpectrometer::get_lambda) ENABLED START -----*/
	/* clang-format on */

	//	Add your own code
	if(!(*attr_RtMode_read) && ((*argin)[0] == BUF_GET_BUNCH_MODE || (*argin)[0] == BUF_GET_BUNCH_UNIQUE_MODE || (*argin)[0] == BUF_GET_BUNCH_BUNCH_MODE))
		Tango::Except::throw_exception(
				"NON RT MODE",
				"Supported only in RT mode",
				__func__, Tango::ERR);
	long buf_idx[2], num_samples;
	unsigned char unique;

	tbuffer::tcheck_get_data_param<tbuffer::_data_array<double> >(argin, &tbuf_array_l, buf_idx, &num_samples, &unique);
	argout  = new Tango::DevVarDoubleArray();
	num_samples *= tbuf_array_l.get_data_size();
	argout->length(num_samples);
	tbuffer::_data_array<double> foo;
	tbuf_array_l.read_data(unique, buf_idx, &(*argout)[0], &foo);

#if 0
	size_t num_samples = RegionOfInterestEndPix - RegionOfInterestStartPix + 1;

	argout  = new Tango::DevVarDoubleArray();
	argout->length(num_samples);
	for(size_t i=0; i<num_samples; i++)
		(*argout)[i] = x_values[i+RegionOfInterestStartPix];
#endif

	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::get_lambda
	return argout;
}
//--------------------------------------------------------
/**
 *	Method     : CCDSpectrometer::add_dynamic_commands()
 *	Description: Create the dynamic commands if any
 *                for specified device.
 */
//--------------------------------------------------------
void CCDSpectrometer::add_dynamic_commands()
{
	/*----- PROTECTED REGION ID(CCDSpectrometer::add_dynamic_commands) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code to create and add dynamic commands if any
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::add_dynamic_commands
}

/*----- PROTECTED REGION ID(CCDSpectrometer::namespace_ending) ENABLED START -----*/
/* clang-format on */
//	Additional Methods

void CCDSpectrometer::init_data(bool reconnection = false)
{
	/*if(!m_usbCCD.GetParameters())
		INFO_STREAM << "CCDSpectrometer::init_data(): error in GetParameters()" << endl;
	numPixel = m_usbCCD.m_nNumPixelsH * m_usbCCD.m_nNumPixelsV;*/
	int res;
	int flag;
	unsigned int NumPixel = numPixel;
	attr_NumPixels_read[0] = NumPixel;
	attr_NumPixels_read[1] = 1;

	if(x_values != NULL)
	{
		delete [] x_values;
		x_values = NULL;
	}
	DEBUG_STREAM << "CCDSpectrometer::init_data(): NumPixel="<<NumPixel << endl;
	x_values = new Tango::DevDouble[NumPixel];
	Tango::DbData db_data_get;
	try {
		db_data_get.push_back(Tango::DbDatum("Data"));
		get_db_device()->get_attribute_property(db_data_get);
		vector<Tango::DevDouble> xval;
		for(unsigned int i=0; i<db_data_get.size(); i++)
		{
			long nb_prop;
			//string &att_name = db_data[i].name;
			db_data_get[i] >> nb_prop;
			i++;
			for(int k=0; k < nb_prop; k++)
			{
				string &prop_name = db_data_get[i].name;
				if(prop_name == "x_values")
				{
					db_data_get[i] >> xval;
					break;
				}
			}
		}
		if(xval.size() > NumPixel)
		{
			WARN_STREAM << "CCDSpectrometer::init_data(): x_values property size=" << xval.size() << " greater than frame size=" << NumPixel << endl;
		}
		else
		{
			DEBUG_STREAM << "CCDSpectrometer::init_data(): x_values property size=" << xval.size() << ", frame size=" << NumPixel << endl;
			for(unsigned int i=0; i<xval.size(); i++)
			{
				x_values[i] = (Tango::DevDouble)xval[i];
			}
			//TEMP: if missing some xval, fill continuing with linear interpulation
			if(xval.size() < NumPixel)
			{
				for(unsigned int i=xval.size(); i<NumPixel; i++)
				{
					x_values[i] = (Tango::DevDouble)(xval[xval.size()-1] + (xval[xval.size()-1] - xval[xval.size()-2])*(i-xval.size()+1));
					DEBUG_STREAM << "CCDSpectrometer::init_data(): added missing x_values: x_values["<<i<<"]=" << x_values[i] << endl;
				}			
			}
		}
	}
	catch(Tango::DevFailed e) {
		string temp;
		temp = e.errors[0].desc;
		WARN_STREAM << "CCDSpectrometer::init_data() error getting x_values attribute property: " << temp << endl;		
	}
	if(pLiveData_avg != NULL)
	{
		delete [] pLiveData_avg;
		pLiveData_avg = NULL;
	}
	pLiveData_avg = new double[NumPixel];
	memset(pLiveData_avg,0,NumPixel*sizeof(double));
	if(pNoiseMask_avg != NULL)
	{
		delete [] pNoiseMask_avg;
		pNoiseMask_avg = NULL;
	}
	pNoiseMask_avg = new double[NumPixel];
	memset(pNoiseMask_avg,0,NumPixel*sizeof(double));
	if(pReferenceData != NULL)
	{
		delete [] pReferenceData;
		pReferenceData = NULL;
	}
	pReferenceData = new double[NumPixel];
	memset(pReferenceData,0,NumPixel*sizeof(double));

	/*defaultEndRegion = (defaultEndRegion > (int)NumPixel) ? NumPixel :
							(defaultEndRegion < 0) ? NumPixel : defaultEndRegion;
	defaultStartRegion = (defaultStartRegion < 0) ? 0 :
								((defaultStartRegion > (int)NumPixel) ? 0 :
									((defaultStartRegion >= defaultEndRegion) ? defaultEndRegion-1 : defaultStartRegion));*/

	RegionOfInterestStartPix = WaveLenght2Pix(attr_RegionOfInterest_read[0]);
	DEBUG_STREAM << __func__<<": StartROI="<<defaultStartRegion<<" -> start pix="<<RegionOfInterestStartPix;
	while(x_values[RegionOfInterestStartPix] < defaultStartRegion)
	{
		RegionOfInterestStartPix++;
	}
	DEBUG_STREAM << __func__<<": ... -> adjusted start pix="<<RegionOfInterestStartPix;
	AnalysisRegionStartPix = RegionOfInterestStartPix;
	
	RegionOfInterestEndPix = WaveLenght2Pix(attr_RegionOfInterest_read[1]);
	DEBUG_STREAM << __func__<<": EndROI="<<defaultEndRegion<<" -> end pix="<<RegionOfInterestEndPix;
	while(x_values[RegionOfInterestEndPix] > defaultEndRegion)
	{
		RegionOfInterestEndPix--;
	}
	DEBUG_STREAM << __func__<<": ... -> adjusted end pix="<<RegionOfInterestEndPix;
	AnalysisRegionEndPix = RegionOfInterestEndPix;
	attr_GaussFit_read[0] = attr_GaussFit_read[1] = attr_GaussFit_read[2] = attr_GaussFit_read[3] = 0;
	attr_FWHM_read[0] = attr_FWHM_read[1] = attr_FWHM_read[2] = 0;
	*attr_GaussFitCenter_read = 0;
	*attr_GaussFitWidth_read = 0;
	*attr_FWHMCenter_read = 0;
	*attr_FWHMWidth_read = 0;
	GaussFit_valid = false;

	Tango::MultiAttribute *attr_list = get_device_attr();

	vector<double> region_write;
	region_write.push_back(x_values[RegionOfInterestStartPix]);
	region_write.push_back(x_values[RegionOfInterestEndPix]);
	Tango::WAttribute &attr_reg = attr_list->get_w_attr_by_name ("RegionOfInterest");
	attr_reg.set_write_value(region_write,2);
	Tango::WAttribute &attr_reg2 = attr_list->get_w_attr_by_name ("AnalysisRegion");
	attr_reg2.set_write_value(region_write,2);
	if(reconnection)
	{
		usleep(500000);
		try
		{
			Tango::WAttribute &attr_reg3 = attr_list->get_w_attr_by_name ("ExposureTime");
			write_ExposureTime(attr_reg3);
		}catch (...){}
		usleep(100000);
		try
		{
			Tango::WAttribute &attr_reg4 = attr_list->get_w_attr_by_name ("SyncMode");
			write_SyncMode(attr_reg4);
		}catch (...){}
		usleep(100000);
	}
	if(nFramesBuffered > 0)
	{
		if(pFrameBuffer != NULL)
		{
			delete [] pFrameBuffer;
			pFrameBuffer = NULL;
		}
		pFrameBuffer = new double[NumPixel * nFramesBuffered];
		memset(pFrameBuffer,0,NumPixel * nFramesBuffered * sizeof(double));
	}
	ifstream  fd;		//startup file
	fd.open(dataReferenceFile.c_str());
	if (!fd)
	{
		stringstream tmp;
		tmp << "Cannot open Data Reference default file:" << strerror(errno) << endl;
		INFO_STREAM << "CCDSpectrometer::init_data(): " << tmp.str();
   	}
	else{
		DEBUG_STREAM << "CCDSpectrometer::init_data(): file opened successfully" << endl;
		string lineread;
		size_t i=0;
		double val;
		while(std::getline(fd, lineread, '\n'))
		{ // Read line by line
			if(lineread.length() > 0 && i < NumPixel)
			{
				sscanf(lineread.c_str(),"%lf",&val);
				pReferenceData[i++] = val;
			}
		}
		fd.close();
	}
	fd.open(noiseProfileFile.c_str());
	if (!fd)
	{
		stringstream tmp;
		tmp << "Cannot open Noise Profile default file:" << strerror(errno) << endl;
		INFO_STREAM << "CCDSpectrometer::init_data(): " << tmp.str();
   	}
	else{
		DEBUG_STREAM << "CCDSpectrometer::init_data(): file " << noiseProfileFile << " opened successfully" << endl;
		string lineread;
		int i=0;
		double val;
		while(std::getline(fd, lineread, '\n'))
		{ // Read line by line
			if(lineread.length() > 0 && i < NumPixel)
			{
				sscanf(lineread.c_str(),"%lf",&val);
				pNoiseMask_avg[i++] = val;
			}
		}
		fd.close();
	}
}

unsigned int CCDSpectrometer::WaveLenght2Pix(double val)
{
	if(!x_values || numPixel==0)
		return 0;
	double tmp_val;
	unsigned int tmp_pix, step;
	tmp_pix= (unsigned int)(((double)numPixel)/2);
	step= (unsigned int)(((double)numPixel)/2);
	tmp_val = x_values[tmp_pix];
	//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix: ENTERING: val="<<val<<" tmp_val="<<tmp_val<<" tmp_pix="<<tmp_pix<<" step="<<step<<endl;
	if(val <= x_values[0])
		return 0;
	else if(val >= x_values[numPixel-1])
		return numPixel-1;
	while((val != tmp_val) && (step > 1))
	{
		step = (unsigned int)((((double)step)/2) + 0.5);	//round
		//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix: LOOPING: val="<<val<<" tmp_val="<<tmp_val<<" tmp_pix="<<tmp_pix<<" step="<<step<<endl;
		if(val > tmp_val)
		{
			if((((int)tmp_pix) + ((int)step)) < (int)numPixel)
			{
				tmp_pix = tmp_pix + step;
			}
			else
			{
				//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix("<<val<<"): LOOPING: tmp_pix="<<tmp_pix<<"+step="<<step<<" >=numPixel="<<numPixel<<endl;
				tmp_pix = numPixel-1;
				//break;
			}
		}
		else if(val < tmp_val)
		{
			if((((int)tmp_pix) - ((int)step)) >= 0)
			{
				//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix("<<val<<"): LOOPING: tmp_pix="<<tmp_pix<<"-step="<<step<<" ="<<tmp_pix - step<<" new tmp_val=" << x_values[tmp_pix- step] << endl;
				tmp_pix = tmp_pix - step;
			}
			else
			{
				//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix("<<val<<"): LOOPING: tmp_pix="<<tmp_pix<<"-step="<<step<<" <=0"<<endl;
				tmp_pix = 0;
				//break;
			}
		}
		else
		{
			break;
		}
		tmp_val = x_values[tmp_pix];
	}
	if(step == 1)
	{
		//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix: LAST TEST: val="<<val<<" tmp_val="<<tmp_val<<" tmp_pix="<<tmp_pix<<" step="<<step<<endl;
		if(val > tmp_val)
		{
			if((((int)tmp_pix) + ((int)step)) < (int)numPixel)
			{
				tmp_pix = tmp_pix + step;
			}
			else
			{
				//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix("<<val<<"): LAST TEST: tmp_pix="<<tmp_pix<<"+step="<<step<<" >=numPixel="<<numPixel<<endl;
				tmp_pix = numPixel-1;
				//break;
			}
		}
		else if(val < tmp_val)
		{
			if((((int)tmp_pix) - ((int)step)) >= 0)
			{
				//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix("<<val<<"): LAST TEST: tmp_pix="<<tmp_pix<<"-step="<<step<<" ="<<tmp_pix - step<<" new tmp_val=" << x_values[tmp_pix- step] << endl;
				tmp_pix = tmp_pix - step;
			}
			else
			{
				DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix("<<val<<"): LAST TEST: tmp_pix="<<tmp_pix<<"-step="<<step<<" <=0"<<endl;
				tmp_pix = 0;
				//break;
			}
		}
	}
	//DEBUG_STREAM << "CCDSpectrometer::WaveLenght2Pix: EXITING: val="<<val<<" tmp_val="<<tmp_val<<" tmp_pix="<<tmp_pix<<" step="<<step<<endl;
	return (unsigned int)tmp_pix;
}
//==== argin:
// DWORD *data_array: sequence of "num_frames" frames
// int dim_frame: dimensione of one frame
// int x_start_analysis: start of region of analysis within the frame
// int x_end_analysis: end of region of analysis within the frame
// int num_frames: number of frames passed for the average between frames
// int avg_val: number of adjacent values with which calculate the average
//
//==== argout:
// int x_peak: x of the peak
// int y_peak: y of the peak
// int x_half_min: smallest x of the value at half maximum
// int x_half_max: largest x of the value at half maximum

bool CCDSpectrometer::fwhm_calculate(double *data_array, size_t dim_frame, size_t x_start_analysis, size_t x_end_analysis, size_t num_frames, size_t avg_val, size_t &x_peak, double &y_peak, size_t &x_half_min, size_t &x_half_max)
{
	bool ret = true;
	if(num_frames < 1)
		num_frames = 1;
	int dim_frame_analysis = x_end_analysis - x_start_analysis + 1;
	if(avg_val-1 > dim_frame_analysis)
	{
		avg_val = dim_frame_analysis;
	}
	if(avg_val < 1)
		avg_val = 1;
	if((avg_val % 2) != 1)		//has to be odd
		avg_val += 1;

	size_t half_avg_val = (size_t)(floor((double)avg_val)/2);

	double *data_tmp = new double[dim_frame_analysis];
	//memset(data_tmp, 0, sizeof(double)*dim_frame_analysis);
	double y_min=1E17;	//TODO: start from max value
	x_peak = x_start_analysis + avg_val;
	y_peak = -1E17;
	x_half_min=x_start_analysis + avg_val;
	x_half_max=x_end_analysis-(int)(((double)avg_val)/2);

	double inv_num_frame = 1.0/(double)num_frames;
	double inv_avg_val = 1.0/(double)avg_val;
	//cout << "GGG avg_val="<<avg_val<<" looping ["<<x_start_analysis + avg_val<<","<<x_end_analysis - avg_val<<"]" << endl;
	//calculate average and max
	//if(int_num_frames > 1)
	{
		for(size_t i=x_start_analysis + avg_val; i < x_end_analysis - avg_val; i++)
		{
			//average with num_frames before
			for(size_t j=0; j < num_frames; j++)
			{
				if(avg_val == 1)
				{
					data_tmp[i-x_start_analysis] = ((double)data_array[i + j*num_frames])*inv_num_frame;
				}
				else
				{
					double tmp_val=0;
					//average from (size_t)(((double)avg_val)/2) before value i to (size_t)(((double)avg_val)/2) after
					for(size_t k=i-half_avg_val; k<=i+half_avg_val; k++)
					{
						tmp_val += ((double)data_array[k + j*num_frames]);
						//cout << "GGG i="<<i<<" k="<<k<<" data_array["<<k + j*num_frames<<"]="<< ((double)data_array[k + j*num_frames]) << endl;
					}
					data_tmp[i-x_start_analysis] = tmp_val*inv_num_frame*inv_avg_val;
					//cout << "GGG i="<<i<<" data_tmp["<<i-x_start_analysis<<"]="<< data_tmp[i-x_start_analysis] << endl;
				}
			}
			if(data_tmp[i-x_start_analysis] > y_peak)
			{
				y_peak = (data_tmp[i-x_start_analysis]);
				x_peak = i;
				//cout << "GGG FOUND peak: i="<<i<<" data_tmp["<<i-x_start_analysis<<"]="<< data_tmp[i-x_start_analysis] << endl;
			}
			if(data_tmp[i-x_start_analysis] < y_min)
			{
				y_min = (data_tmp[i-x_start_analysis]);
			}
		}

		//now search for x at half maximum
		//exterior half maximum on the left
		//for(int i=x_start_analysis + avg_val; i < x_peak; i++)
		for(int i=x_peak-1; i>=x_start_analysis + avg_val; i--)
		{
			//cout << "GGG i="<<i<<" data_tmp["<<i-x_start_analysis<<"]="<< data_tmp[i-x_start_analysis] <<" y_min="<<y_min<<" y_peak="<<y_peak<<" x_peak="<<x_peak<< endl;
			//if(data_tmp[i-x_start_analysis] >= (double)y_min + ((double)y_peak-y_min)/2)
			if(data_tmp[i-x_start_analysis] < (double)y_min + ((double)y_peak-y_min)/2)
			{
				//cout << "GGG FOUND x_half_min="<<i<< endl;
				//x_half_min = i;
				x_half_min = i+1;
				break;
			}
		}

		//exterior half maximum on the right
		//for(int i=x_end_analysis - avg_val; i > x_peak; i--)
		for(int i = x_peak+1; i <= x_end_analysis - avg_val; i++)
		{
			//cout << "GGG i="<<i<<" data_tmp["<<i-x_start_analysis<<"]="<< data_tmp[i-x_start_analysis] <<" y_min="<<y_min<<" y_peak="<<y_peak<<" x_peak="<<x_peak<< endl;
			//if(data_tmp[i-x_start_analysis] >= (double)y_min + ((double)y_peak-y_min)/2)
			if(data_tmp[i-x_start_analysis] < (double)y_min + ((double)y_peak-y_min)/2)
			{
				//cout << "GGG FOUND x_half_max="<<i<< endl;
				//x_half_max = i;
				x_half_max = i-1;
				break;
			}
		}
	}
	delete [] data_tmp;
	return ret;
}

uint32_t CCDSpectrometer::myntohl(uint32_t val_l)
{
	volatile uint32_t ret_val=val_l;
	uint32_t volatile *pval_l;
	pval_l = (uint32_t volatile *)&ret_val;

#if __BYTE_ORDER == __BIG_ENDIAN		//NOT STANDARD: ASSUMING 	__LITTLE_ENDIAN as the network ordering
	*pval_l = __bswap_32(*pval_l);
#else
	*pval_l = *pval_l;
#endif

	return ret_val;
}


//+------------------------------------------------------------------
/**
 *	method:	CCDSpectrometer::string_explode
 * Explode a string
*/
//+------------------------------------------------------------------
void CCDSpectrometer::string_explode(string str, string separator, vector<string>* results)
{
	size_t found;

	found = str.find_first_of(separator);
	while(found != string::npos) {
		if(found > 0) {
			results->push_back(str.substr(0,found));
		}
		str = str.substr(found+1);
		found = str.find_first_of(separator);
	}
	if(str.length() > 0) {
		results->push_back(str);
	}

}

int CCDSpectrometer::load_intensity_cal_file(string filename)
{
	string line;
	ifstream infile (filename.c_str(), ios_base::in);
	while (getline(infile, line, '\n'))
	{
		vector<string> results;
		string_explode(line, "\t", &results);
		if(results.size() == 3)
		{
			int ind;
			float wl, cal;
			int ret = sscanf(line.c_str(), "%d\t%f\t%f", &ind, &wl, &cal);
			DEBUG_STREAM <<__func__ << ":Parsed from " << filename << " ret=" << ret << " cal[" << ind << "]=" << cal;
			if(ret == 3 && ind >=1 && ind <= numPixel)
			{
				attr_IntensityCalibration_read[ind-1] = cal;
			}
		}
	}

	infile.close();
	//DEBUG_STREAM <<__func__ << ": Read from " << filename << " " << tmp.size << " lines or " << tmp.size_d << " reals";
}

int CCDSpectrometer::save_intensity_cal_file(string filename)
{
	string line;
	ofstream outfile (filename.c_str(), ios_base::out | ios_base::trunc);
	for(size_t i=0; i<numPixel; i++)
	{
		outfile << i+1 << "\t" << x_values[i] << "\t" << attr_IntensityCalibration_read[i] << endl;
	}

	outfile.close();
}

/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	CCDSpectrometer::namespace_ending
} //	namespace