-
Arafat Nourredine authoredArafat Nourredine authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MythenPool.cpp 25.28 KiB
//=============================================================================
//
// file : MythenPool.cpp
//
// description : Manage access to a set of MythenDetector device
//
// project : MythenWAXS Project
//
// $Author: noureddine $
//
// copyleft : Synchrotron SOLEIL
// L'Orme des merisiers - Saint Aubin
// BP48 - 91192 Gif sur Yvette
// FRANCE
//=============================================================================
#include <tango.h>
//- YAT stuff
#include <yat/utils/XString.h>
#include <iomanip>
#include "MythenPool.h"
namespace MythenWAXS_ns
{
//----------------------------------------------------------------------------------------------------------------------
//- MythenPool Ctor
//----------------------------------------------------------------------------------------------------------------------
MythenPool::MythenPool(Tango::DeviceImpl *dev, PropertyLoader prop)
: yat4tango::DeviceTask(dev),
m_device(dev),
m_prop(prop)
{
DEBUG_STREAM << "MythenPool::MythenPool() - [BEGIN]" << endl;
set_state(Tango::INIT);
set_periodic_msg_period(TASK_PERIODIC__MS);//1Hz
enable_periodic_msg(false);
DEBUG_STREAM << "MythenPool::MythenPool() - [END]" << endl;
}
//----------------------------------------------------------------------------------------------------------------------
//- MythenPool Dtor
//----------------------------------------------------------------------------------------------------------------------
MythenPool::~MythenPool()
{
DEBUG_STREAM << "MythenPool::~MythenPool() - [BEGIN]" << endl;
DEBUG_STREAM << "MythenPool::~MythenPool() - [END]" << endl;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::set_state(Tango::DevState state)
{
{
//- AutoLock the following
yat::MutexLock scoped_lock(m_proxy_lock);
m_state = state;
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
Tango::DevState MythenPool::get_state()
{
{
//- AutoLock the following
yat::MutexLock scoped_lock(m_proxy_lock);
compute_state_status();
return m_state;
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::set_status(const std::string& status)
{
{
//- AutoLock the following
yat::MutexLock scoped_lock(m_proxy_lock);
m_status.str("");
m_status << status.c_str();
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
std::string MythenPool::get_status()
{
{
//- AutoLock the following
yat::MutexLock scoped_lock(m_proxy_lock);
return (m_status.str());
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_energy(float value)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
long nb_modules = 0;
m_proxy_mythens.at(i)->read_attribute("nbModules", nb_modules, m_prop.proxy_nb_retry);
for (unsigned j = 0; j < nb_modules; j++)
{
stringstream ss("");
std::string name("");
name = "energy";
ss << name << std::setfill('0') << std::setw(2) << j + 1;//index of energy start with '01'
m_proxy_mythens.at(i)->write_attribute(ss.str(), value, m_prop.proxy_nb_retry);
}
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_threshold(float value)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
long nb_modules = 0;
m_proxy_mythens.at(i)->read_attribute("nbModules", nb_modules, m_prop.proxy_nb_retry);
for (unsigned j = 0; j < nb_modules; j++)
{
stringstream ss("");
std::string name("");
name = "threshold";
ss << name << std::setfill('0') << std::setw(2) << j + 1;//index of threshold start with '01'
m_proxy_mythens.at(i)->write_attribute(ss.str(), value, m_prop.proxy_nb_retry);
}
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_exposure_time(double value)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->write_attribute("exposureTime", value, m_prop.proxy_nb_retry);
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_nb_frames(long value)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->write_attribute("nbFrames", value, m_prop.proxy_nb_retry);
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_flatfield_correction(bool flag)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->write_attribute("flatFieldCorrection", flag, m_prop.proxy_nb_retry);
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_rate_correction(bool flag)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->write_attribute("rateCorrection", flag, m_prop.proxy_nb_retry);
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::write_badchannel_interpolation(bool flag)
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->write_attribute("badChannelInterpolation", flag, m_prop.proxy_nb_retry);
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
long MythenPool::get_nb_modules()
{
yat::MutexLock scoped_lock(m_proxy_lock);
long nb_total_modules = 0;
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
long nb_modules = 0;
m_proxy_mythens.at(i)->read_attribute("nbModules", nb_modules, m_prop.proxy_nb_retry);
nb_total_modules += nb_modules;
}
return nb_total_modules;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
long MythenPool::get_nb_channels()
{
yat::MutexLock scoped_lock(m_proxy_lock);
long nb_total_channels = 0;
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
long nb_channels = 0;
m_proxy_mythens.at(i)->read_attribute("nbChannels", nb_channels, m_prop.proxy_nb_retry);
nb_total_channels += nb_channels;
}
return nb_total_channels;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::snap()
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->command("Snap", m_prop.proxy_nb_retry);
}
//start the PERIOODIC_MSG in order to execute compute_frame_xy()
enable_periodic_msg(true);
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::stop()
{
yat::MutexLock scoped_lock(m_proxy_lock);
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
m_proxy_mythens.at(i)->command("Stop", m_prop.proxy_nb_retry);
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
const std::vector<float>& MythenPool::get_frame_x()
{
yat::MutexLock scoped_lock(m_proxy_lock);
return m_frame_x_values;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
const std::vector<float>& MythenPool::get_frame_y()
{
yat::MutexLock scoped_lock(m_proxy_lock);
return m_frame_y_values;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::compute_frame_xy()
{
yat::MutexLock scoped_lock(m_proxy_lock);
m_frame_x_values.clear();
m_frame_y_values.clear();
unsigned nb_total_modules = 0;
//get the motor position tth2C
double theta_position;
m_proxy_motor->read_attribute("position", theta_position, m_prop.proxy_nb_retry);
//compute tth
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
long nb_modules = 0;
m_proxy_mythens.at(i)->read_attribute("nbModules", nb_modules, m_prop.proxy_nb_retry);
INFO_STREAM << "nb_modules = " << nb_modules << std::endl;
long nb_channels = 0;
m_proxy_mythens.at(i)->read_attribute("nbChannels", nb_channels, m_prop.proxy_nb_retry);
INFO_STREAM << "nb_channels = " << nb_channels << std::endl;
for (unsigned j = 0; j < nb_modules; j++)
{
std::vector<long> frame;
stringstream ss("");
std::string name("");
name = "frame";
ss << name << std::setfill('0') << std::setw(2) << j + 1;//index of frame start with '01'
m_proxy_mythens.at(i)->read_attribute(ss.str(), frame, m_prop.proxy_nb_retry);
INFO_STREAM << ss.str() << " size = " << frame.size() << std::endl;
for (unsigned k = 0;k < frame.size();k++)
{
double twotheta = theta_position -
m_deltas.at(nb_total_modules + j) +
(180.0 / M_PI) * atan((m_centers.at(nb_total_modules + j)-(1279 - k)) * m_prop.pixel_size / m_distances.at(nb_total_modules + j));
//NB: Mythen modules are mounted in opposite sens, why we use (1279-k) instead of k !!
m_frame_x_values.push_back(twotheta);
m_frame_y_values.push_back(frame.at(k) * m_scales.at(nb_total_modules + j));
}
}
INFO_STREAM << "m_frame_x_values.size() = " << m_frame_x_values.size() << std::endl;
INFO_STREAM << "m_frame_y_values.size() = " << m_frame_y_values.size() << std::endl;
nb_total_modules += nb_modules;
INFO_STREAM << "\n" << std::endl;
INFO_STREAM << "nb_total_modules = " << nb_total_modules << std::endl;
}
// INFO_STREAM << "m_twotheta_values.size() = " << m_twotheta_values.size() << std::endl;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::decode_equation_parameters()
{
try
{
INFO_STREAM << "\n" << endl;
INFO_STREAM << "----------------------------------------------------" << endl;
INFO_STREAM << "Decode the EquationPrameters Device Property ..." << endl;
INFO_STREAM << "----------------------------------------------------" << endl;
//there is 9 lines
//each line contains : delta=value;center=value;distance=value;
for (unsigned i = 0; i < m_prop.equation_parameters.size(); i++)
{
Tokenizer line(m_prop.equation_parameters.at(i), ';');
if (line.count() != 4)
{
Tango::Except::throw_exception( "LOGIC_ERROR",
"Check the format of the 'EquationParameters' Device Property !",
"MythenPool::decode_equation_parameters()");
}
for (unsigned itoken = 0; itoken < line.count(); itoken++)
{
try
{
string item_name;
float item_val;
//try catch used to check the end of items
Tokenizer field(line[itoken], '=');
if (field.count() != 2)
{
Tango::Except::throw_exception( "LOGIC_ERROR",
"Check the format of the 'EquationParameters' Device Property !",
"MythenPool::decode_equation_parameters()");
}
item_name = field[0];
istringstream iss_val(field[1]);//val
iss_val >> item_val;
if (item_name == "delta")
m_deltas.push_back(item_val);
else if (item_name == "center")
m_centers.push_back(item_val);
else if (item_name == "distance")
m_distances.push_back(item_val);
else if (item_name == "scale")
m_scales.push_back(item_val);
}
catch (exception& e)
{
//indicate that token has not the good format or no token anymore, Nothing to do
//DEBUG_STREAM<<"token has not the good format or no token anymore ! "<<endl;
continue;
}
}
}
//display values
for (unsigned i = 0; i < m_deltas.size(); i++)
{
INFO_STREAM << "m_deltas[" << i << "] = " << m_deltas[i] << std::endl;
}
INFO_STREAM << "\n" << std::endl;
for (unsigned i = 0; i < m_centers.size(); i++)
{
INFO_STREAM << "m_centers[" << i << "] = " << m_centers[i] << std::endl;
}
INFO_STREAM << "\n" << std::endl;
for (unsigned i = 0; i < m_distances.size(); i++)
{
INFO_STREAM << "m_distances[" << i << "] = " << m_distances[i] << std::endl;
}
INFO_STREAM << "\n" << std::endl;
for (unsigned i = 0; i < m_scales.size(); i++)
{
INFO_STREAM << "m_scales[" << i << "] = " << m_scales[i] << std::endl;
}
INFO_STREAM << "\n" << std::endl;
}
catch (exception& e)
{
//indicate that token has not the good format or no token anymore
ERROR_STREAM << e.what() << endl;
ostringstream ossMsgErr;
ossMsgErr << e.what();
Tango::Except::throw_exception("LOGIC_ERROR",
ossMsgErr.str().c_str(),
"MythenPool::decode_equation_parameters()");
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::compute_state_status()
{
{
//- AutoLock the following
yat::MutexLock scoped_lock(m_proxy_lock);
DEBUG_STREAM << "MythenPool::compute_state_status() - [BEGIN]" << endl;
unsigned proxy_num;
Tango::DevState global_state;
stringstream proxy_status;
proxy_status.str("");
vector <Tango::DevState> states;
unsigned int fault_count = 0;
unsigned int running_count = 0;
unsigned int standby_count = 0;
if (m_state != Tango::INIT)
{
//////////////////////////////////////////////////////////
try
{
//more than one proxy mythen devices
for (unsigned i = 0; i < m_prop.proxy_mythen_names.size(); i++)
{
proxy_num = i;
Tango::DevState simple_state;
m_proxy_mythens.at(i)->command_out("State", simple_state, m_prop.proxy_nb_retry);
proxy_status << "Mythen[" << proxy_num << "]\t\t" << " --> " << Tango::DevStateName[simple_state] << "\n";
states.push_back(simple_state);
}
//only one proxy motor device
Tango::DevState simple_state;
m_proxy_motor->command_out("State", simple_state, m_prop.proxy_nb_retry);
proxy_status << "Motor " << "\t\t" << " --> " << Tango::DevStateName[simple_state] << "\n";
states.push_back(simple_state);
//counting each kind of state
for (unsigned i = 0; i < states.size(); i++)
{
switch (states.at(i))
{
case Tango::FAULT:
fault_count++;
break;
case Tango::OFF: //NOP (don't manage this motor state)
case Tango::ALARM: //NOP (don't manage this motor state)
case Tango::MOVING: //NOP (don't manage this motor state)
case Tango::STANDBY:
standby_count++;
break;
case Tango::RUNNING:
running_count++;
break;
default:
fault_count++;
break; //NOP
}
}
//////
if (fault_count)
{
global_state = Tango::FAULT; //if at least one device is in fault
}
else if (running_count)
{
global_state = Tango::RUNNING; //if all devices are RUNNING
}
else if (standby_count == states.size())
{
global_state = Tango::STANDBY; //if all devices are STANDBY
}
else
{
global_state = Tango::ALARM; //Otherwise ALARM
}
}
catch (Tango::DevFailed& e)
{
ERROR_STREAM << e << ENDLOG;
proxy_status << "Proxy[" << proxy_num << "]\t\t" << " --> Unable to read State !\n";
global_state = Tango::FAULT;
}
//////////////////////////////////////////////////////////
//if pilatus is in "FAULTy" state
if (global_state == Tango::FAULT || global_state == Tango::OFF || global_state == Tango::INIT)
{
set_state(Tango::FAULT);
std::stringstream status;
status.str("");
status << "At least one Device is in FAULTy state !\n";
status << "---------------------------------------------------\n";
status << proxy_status.str();
set_status(status.str());
DEBUG_STREAM << "MythenPool::compute_state_status() - [END]" << endl;
return;
}
//if pilatus is in "RUNNING" state
if (global_state == Tango::RUNNING || global_state == Tango::MOVING)
{
set_state(Tango::RUNNING);
std::stringstream status;
status.str("");
status << "Acquisition is Running ...\n";
status << "---------------------------------------------------\n";
status << proxy_status.str();
set_status(status.str());
DEBUG_STREAM << "MythenPool::compute_state_status() - [END]" << endl;
return;
}
if (global_state == Tango::STANDBY)
{
//STANDBY
set_state(Tango::STANDBY);
std::stringstream status;
status.str("");
status << "Waiting for request ...\n";
status << "---------------------------------------------------\n";
status << proxy_status.str();
set_status(status.str());
DEBUG_STREAM << "MythenPool::compute_state_status() - [END]" << endl;
return;
}
if (global_state == Tango::ALARM)
{
//ALARM
set_state(Tango::ALARM);
std::stringstream status;
status.str("");
status << "At least one Device is not in the expected state !\n";
status << "---------------------------------------------------\n";
status << proxy_status.str();
set_status(status.str());
DEBUG_STREAM << "MythenPool::compute_state_status() - [END]" << endl;
return;
}
}
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void MythenPool::process_message(yat::Message& msg) throw (Tango::DevFailed)
{
try
{
switch (msg.type())
{
//-----------------------------------------------------
case yat::TASK_INIT:
{
INFO_STREAM << " " << std::endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
INFO_STREAM << "-> MythenPool::TASK_INIT" << endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
std::string proxy_name;
try
{
INFO_STREAM << "" << endl;
//create proxies to Mthen2Detector
for (int i = 0;i < m_prop.proxy_mythen_names.size();i++)
{
proxy_name = m_prop.proxy_mythen_names.at(i);
INFO_STREAM << "\t- Create the Proxy to the device (" << proxy_name << ")" << endl;
m_proxy_mythens.push_back(new yat4tango::DeviceProxyHelper(proxy_name, m_device));
m_proxy_mythens[i]->get_device_proxy()->ping();
}
//create proxy to the motor
proxy_name = m_prop.proxy_motor_name;
INFO_STREAM << "\t- Create the Proxy to the motor (" << proxy_name << ")" << endl;
m_proxy_motor.reset(new yat4tango::DeviceProxyHelper(proxy_name, m_device));
m_proxy_motor->get_device_proxy()->ping();
}
catch (const std::bad_alloc& e)
{
ERROR_STREAM << e.what() << ENDLOG;
std::stringstream status;
status << "Unable to create proxy to ( " << proxy_name << " ) :\n"
<< "--> Memory allocation exception.\n"
<< endl;
set_state(Tango::INIT);
set_status(status.str());
return;
}
catch (Tango::DevFailed& e)
{
ERROR_STREAM << e << ENDLOG;
std::stringstream status;
status << "Unable to create proxy to ( " << proxy_name << " ) :\n"
<< "--> check the value of the 'ProxiesNames' property.\n"
<< "--> check the state of the device ( " << proxy_name << " ).\n"
<< endl;
set_state(Tango::INIT);
set_status(status.str());
return;
}
//decode constants from equation_constants property
decode_equation_parameters();
//set state STANDBY if everything is ok
set_state(Tango::STANDBY);
//enable_periodic_msg(true);
}
break;
//-----------------------------------------------------
case yat::TASK_EXIT:
{
INFO_STREAM << " " << std::endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
INFO_STREAM << "-> MythenPool::TASK_EXIT" << endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
}
break;
//-----------------------------------------------------
case yat::TASK_TIMEOUT:
{
INFO_STREAM << " " << std::endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
INFO_STREAM << "-> MythenPool::TASK_TIMEOUT" << endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
}
break;
//-----------------------------------------------------
case yat::TASK_PERIODIC:
{
//- AutoLock the following
yat::MutexLock scoped_lock(m_proxy_lock);
Tango::DevState state = get_state();
if (state == Tango::STANDBY)
{
enable_periodic_msg(false);
DEBUG_STREAM << " " << std::endl;
DEBUG_STREAM << "--------------------------------------------" << std::endl;
DEBUG_STREAM << "-> MythenPool::TASK_PERIODIC" << endl;
DEBUG_STREAM << "--------------------------------------------" << std::endl;
try
{
INFO_STREAM << "--------------------------------------------" << std::endl;
INFO_STREAM << "Compute frameX & frameY" << endl;
INFO_STREAM << "--------------------------------------------" << std::endl;
compute_frame_xy();
}
catch (Tango::DevFailed &df)
{
ERROR_STREAM << df << endl;
std::stringstream status;
status.str("");
status << "Origin\t: " << df.errors[0].origin << endl;
status << "Desc\t: " << df.errors[0].desc << endl;
set_status(status.str());
set_state(Tango::FAULT);
}
}
}
break;
//-----------------------------------------------------
}
}
catch (yat::Exception& ex)
{
//- TODO Error Handling
ex.dump();
std::stringstream error_msg("");
error_msg << "Origin\t: " << ex.errors[0].origin << endl;
error_msg << "Desc\t: " << ex.errors[0].desc << endl;
error_msg << "Reason\t: " << ex.errors[0].reason << endl;
ERROR_STREAM << "Exception from - MythenPool::process_message() : " << error_msg.str() << endl;
throw;
}
}
} // namespace