Skip to content
Snippets Groups Projects
Commit 90c2ed73 authored by Christian Koernig's avatar Christian Koernig
Browse files

Added special Simulator command to set the count rate

Added optional channel to control the simulator count rate via another
tango attribute value
parent 6ac8b343
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "AmptekConnectionHandler.h" #include "AmptekConnectionHandler.h"
#include <thread> // std::thread #include <thread> // std::thread
#include <map> #include <map>
#include <random>
#define STATUS_SIZE 64 #define STATUS_SIZE 64
class AmptekSimulatorConnectionHandler : public AmptekConnectionHandler{ class AmptekSimulatorConnectionHandler : public AmptekConnectionHandler{
...@@ -36,6 +37,10 @@ private: ...@@ -36,6 +37,10 @@ private:
double acquisition_time = -1; double acquisition_time = -1;
std::thread* spectrum_thread; std::thread* spectrum_thread;
std::chrono::system_clock::time_point start_time;
std::default_random_engine delay_gen;
std::normal_distribution<double> delay_dist;
}; };
#endif #endif
\ No newline at end of file
...@@ -42,6 +42,8 @@ namespace std { ...@@ -42,6 +42,8 @@ namespace std {
} }
} }
%ignore AmptekSimulatorConnectionHandler::start_time;
%include "include/AmptekHardwareInterface.h" %include "include/AmptekHardwareInterface.h"
%include "include/AmptekStatus.h" %include "include/AmptekStatus.h"
%include "include/AmptekSpectrum.h" %include "include/AmptekSpectrum.h"
...@@ -6,7 +6,7 @@ logging.basicConfig( ...@@ -6,7 +6,7 @@ logging.basicConfig(
level=logging.DEBUG, level=logging.DEBUG,
datefmt='%Y-%m-%d %H:%M:%S') datefmt='%Y-%m-%d %H:%M:%S')
from tango import AttrQuality, AttrWriteType, DispLevel, DevState, DebugIt from tango import AttrQuality, AttrWriteType, DispLevel, DevState, DebugIt, AttributeProxy, EventType
from tango.server import Device, attribute, command, pipe, device_property from tango.server import Device, attribute, command, pipe, device_property
from collections import OrderedDict from collections import OrderedDict
import tango import tango
...@@ -25,6 +25,8 @@ class AmptekPX5(Device): ...@@ -25,6 +25,8 @@ class AmptekPX5(Device):
connection_mode = device_property(dtype=str, default_value="UDP") connection_mode = device_property(dtype=str, default_value="UDP")
configuration_file = device_property(dtype=str, default_value="") configuration_file = device_property(dtype=str, default_value="")
incident_channel = device_property(dtype=str, default_value = "")
MaxInfoAge = attribute(label = "MaxInfoAge", dtype=float, MaxInfoAge = attribute(label = "MaxInfoAge", dtype=float,
fget = "get_maxinfoage", fset = "set_maxinfoage") fget = "get_maxinfoage", fset = "set_maxinfoage")
...@@ -50,6 +52,9 @@ class AmptekPX5(Device): ...@@ -50,6 +52,9 @@ class AmptekPX5(Device):
SlowCount = attribute(label="SlowCount", dtype=int, SlowCount = attribute(label="SlowCount", dtype=int,
fget=lambda self: self.GetSlowCount(self._max_info_age)) fget=lambda self: self.GetSlowCount(self._max_info_age))
FastRate = attribute(label="FastRate", dtype=int,
fget=lambda self: self.GetFastRate(self._max_info_age))
GpCount = attribute(label="GpCount", dtype=int, GpCount = attribute(label="GpCount", dtype=int,
fget=lambda self: self.GetGpCount(self._max_info_age)) fget=lambda self: self.GetGpCount(self._max_info_age))
...@@ -246,6 +251,21 @@ class AmptekPX5(Device): ...@@ -246,6 +251,21 @@ class AmptekPX5(Device):
self.load_config_dict(c) self.load_config_dict(c)
if self.connection_mode == 'Simulator':
if self.incident_channel != "":
logging.debug(f"Add change event callback to determine incident rate. Channel is {self.incident_channel}")
self.incident_proxy = AttributeProxy(self.incident_channel)
d = self.incident_proxy.get_device_proxy()
self.incident_proxy.poll(50)
cnf = d.get_attribute_config(self.incident_proxy.name())
cnf.events.ch_event.abs_change = "1"
d.set_attribute_config(cnf)
self.incident_proxy.subscribe_event(EventType.CHANGE_EVENT, self.update_simulator_rate, [], False)
else:
logging.debug(f"No (valid) channel for incident rate is given. Value will be fixed (channel: '{self.incident_channel}')")
else:
logging.debug("Device not in Simulator Mode. 'inciden_channel' property will be ignored")
def load_config_dict( self, configs ): def load_config_dict( self, configs ):
cmd_strings = [] cmd_strings = []
for cmd, setting in configs.items(): for cmd, setting in configs.items():
...@@ -565,6 +585,16 @@ class AmptekPX5(Device): ...@@ -565,6 +585,16 @@ class AmptekPX5(Device):
def GetFastCount(self, max_age_ms): def GetFastCount(self, max_age_ms):
return self.get_status_attribute(max_age_ms, "FastCount") return self.get_status_attribute(max_age_ms, "FastCount")
@command(dtype_in = float, dtype_out=float)
def GetFastRate(self, max_age_ms):
counts = self.get_status_attribute(max_age_ms, "FastCount")
acctime = self.get_status_attribute(max_age_ms, "AccTime")
if (acctime) > 0:
return counts/acctime
else:
return 0
@command(dtype_in=float, dtype_out=(int,)) @command(dtype_in=float, dtype_out=(int,))
def GetSpectrum(self, max_age_ms): def GetSpectrum(self, max_age_ms):
return self.interface.GetSpectrum(max_age_ms) return self.interface.GetSpectrum(max_age_ms)
...@@ -796,5 +826,9 @@ class AmptekPX5(Device): ...@@ -796,5 +826,9 @@ class AmptekPX5(Device):
outstring += "<<END>>\n" outstring += "<<END>>\n"
return outstring return outstring
def update_simulator_rate(self, event):
cnf_str = f"SCR={event.attr_value.value:.0f}"
self.interface.SetTextConfiguration( [cnf_str] )
if __name__ == "__main__": if __name__ == "__main__":
AmptekPX5.run_server() AmptekPX5.run_server()
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <cmath>
Packet AmptekSimulatorConnectionHandler::sendAndReceive( const Packet& request){ Packet AmptekSimulatorConnectionHandler::sendAndReceive( const Packet& request){
byte pid1 = request.at(PID1); byte pid1 = request.at(PID1);
...@@ -142,11 +144,12 @@ Packet AmptekSimulatorConnectionHandler::sendAndReceive( const Packet& request){ ...@@ -142,11 +144,12 @@ Packet AmptekSimulatorConnectionHandler::sendAndReceive( const Packet& request){
AmptekSimulatorConnectionHandler::AmptekSimulatorConnectionHandler(){ AmptekSimulatorConnectionHandler::AmptekSimulatorConnectionHandler(){
spectrum = new unsigned int[speclen]; spectrum = new unsigned int[speclen];
start_time = std::chrono::system_clock::now();
clear(); clear();
initConfigs(); initConfigs();
delay_dist = std::normal_distribution<double>( 1000.,31. ); // default count rate is 1000cps, i.e. 1000us delay
spectrum_thread = new std::thread( spectrum_thread = new std::thread(
[&]{ [&]{
auto start_time = std::chrono::system_clock::now();
while( is_running ){ while( is_running ){
if (flag_enable){ if (flag_enable){
is_enabled = true; is_enabled = true;
...@@ -170,7 +173,7 @@ AmptekSimulatorConnectionHandler::AmptekSimulatorConnectionHandler(){ ...@@ -170,7 +173,7 @@ AmptekSimulatorConnectionHandler::AmptekSimulatorConnectionHandler(){
} }
} }
std::this_thread::sleep_for(std::chrono::milliseconds(2)); std::this_thread::sleep_for(std::chrono::microseconds( std::max(1, std::min((int) delay_dist(delay_gen),100000) ) ) );
} }
...@@ -195,6 +198,7 @@ void AmptekSimulatorConnectionHandler::disable(){ ...@@ -195,6 +198,7 @@ void AmptekSimulatorConnectionHandler::disable(){
void AmptekSimulatorConnectionHandler::clear(){ void AmptekSimulatorConnectionHandler::clear(){
total_counts = 0; total_counts = 0;
acc_time = 0; acc_time = 0;
start_time = std::chrono::system_clock::now();
for (int i = 0; i < speclen; ++i){ for (int i = 0; i < speclen; ++i){
spectrum[i] = 0; spectrum[i] = 0;
} }
...@@ -257,6 +261,18 @@ void AmptekSimulatorConnectionHandler::readConfig(char* configs){ ...@@ -257,6 +261,18 @@ void AmptekSimulatorConnectionHandler::readConfig(char* configs){
std::stringstream linestream(configline); std::stringstream linestream(configline);
std::getline(linestream, config_name,'='); std::getline(linestream, config_name,'=');
linestream >> config_value; linestream >> config_value;
if (config_name == "SCR"){
// this is a special command to set the simulator count rate, not part of the DP5 protocol!
// calculate average delay in us between pulses for target count rate
double scr = std::stoi(config_value);
if (scr < 1){
scr = 1;
}
double dt = 1e6/scr;
delay_dist = std::normal_distribution<double>( dt,sqrt(dt) );
}
else{
if (config_name == "MCAC"){ if (config_name == "MCAC"){
speclen = std::stoi(config_value); speclen = std::stoi(config_value);
delete[] spectrum; delete[] spectrum;
...@@ -272,7 +288,7 @@ void AmptekSimulatorConnectionHandler::readConfig(char* configs){ ...@@ -272,7 +288,7 @@ void AmptekSimulatorConnectionHandler::readConfig(char* configs){
} }
} }
text_configs[config_name] = config_value; text_configs[config_name] = config_value;
}
}catch(...){ }catch(...){
std::cerr << "Failed reading config " << configline << std::endl; std::cerr << "Failed reading config " << configline << std::endl;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment