#!/usr/bin/env python
# -*- coding:utf-8 -*-


# ############################################################################
#  license :
# ============================================================================
#
#  File :        DG_PY_Kalypso.py
#
#  Project :     DG_PY_Kalypso
#
# 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/>.
# 
#
#  $Author :      bence$
#
#  $Revision :    $
#
#  $Date :        $
#
#  $HeadUrl :     $
# ============================================================================
#            This file is generated by POGO
#     (Program Obviously used to Generate tango Object)
# ############################################################################

__all__ = ["DG_PY_Kalypso", "DG_PY_KalypsoClass", "main"]

__docformat__ = 'restructuredtext'

import PyTango
import sys
# Add additional import
# ----- PROTECTED REGION ID(DG_PY_Kalypso.additionnal_import) ENABLED START -----#
import time
from threading import Thread, Lock, Event
import numpy as np
import tango
import os
import glob
import subprocess
import signal
import io
from contextlib import redirect_stdout

from lib import kalypso_tools_for_acquisition, kalypso_tools_for_analysis, Keithley2400_v01


class DriveThread(Thread):
    def __init__(self, mother):
        Thread.__init__(self)
        print("init kalypso_drive_thread")
        self.mother = mother
        self.stopasked = True

    def run(self):
        print("start kalypso_drive_thread")
        while not (self.stopasked):
            try:
                # reset
                reset_bool=getattr(self.mother,"reset_in_progress")
                #print(reset_bool)
                if reset_bool:
                    self.mother.error_stream('reset')
                    if self.mother.opt_nb_pixels == 512:

                        kalypso_tools_for_acquisition.restart_system_w_512_pixels(self.mother)
                        #kalypso_tools_for_acquisition.start_system_w_512_pixels()
                    elif self.mother.opt_nb_pixels == 1024:
                        kalypso_tools_for_acquisition.start_system_w_1024_pixels()
                    else:
                        self.mother.error_stream('wrong number number of pixels set in property')

                # start acquisition
                if getattr(self.mother,"acquisition_in_progress") or getattr(self.mother,"snap_in_progress"):
                    self.mother.error_stream('begin')
                    kalypso_tools_for_acquisition.set_acquisition_parameters(self.mother.opt_nb_pixels,
                                                                             self.mother.attr_exp_time_read,
                                                                             self.mother.attr_nb_frames_read,
                                                                             self.mother.opt_fast_trigger_mode,
                                                                             self.mother.attr_delay_for_fast_trigger_read,
                                                                             self.mother.opt_slow_trigger_mode,
                                                                             self.mother.nb_acq_w_slow_trigger,
                                                                             self.mother.nb_skip_slow_trigger,self.mother)
                    self.mother.error_stream('set_acq_OK')
                    file_out = kalypso_tools_for_acquisition.record_data(self.mother.Data_Path, self.mother.fileroot,
                                                                         self.mother.opt_slow_trigger_mode,
                                                                         self.mother.nb_acq_w_slow_trigger,
                                                                         self.mother.dct_data_obl,self.mother)
                    self.mother.error_stream('rec_data')
                    setattr(self.mother, 'attr_Last_File_Name_read', file_out[-1] + '.bin')
                    setattr(self.mother, "file_out",file_out)
                    size = os.stat(os.path.join(self.mother.Data_Path, file_out[-1] + '.bin')).st_size
                    if size == 0:
                        raise ValueError(
                            'At least one of files is empty - please do Init and Reset sequence\n before restart acquisition')
                    self.mother.Load_Data(os.path.join(self.mother.Data_Path, file_out[-1] + '.bin'))
                    if getattr(self.mother,"acquisition_in_progress") and getattr(self.mother,"Start_Drop_files"): #remove file
                        for f in file_out:
                            os.remove(os.path.join(self.mother.Data_Path, f + '.bin'))
                            os.remove(os.path.join(self.mother.Data_Path, f + '.h5'))

                if getattr(self.mother,"snap_in_progress"):
                    setattr(self.mother, 'snap_in_progress', False)
                if getattr(self.mother,"reset_in_progress"):
                    setattr(self.mother, 'reset_in_progress', False)

            except Exception as ex:
                print("exception in drivethread:")
                print(ex)
                setattr(self.mother, 'acquisition_in_progress', False)
                setattr(self.mother, 'snap_in_progress', False)
                setattr(self.mother, 'reset_in_progress', False)
            time.sleep(self.mother.th_drive_pause)



        print("kalypso_drive_thread stopped")

class FileListThread(Thread):
    def __init__(self, mother):
        Thread.__init__(self)
        print("init FileList thread")
        self.mother = mother
        self.stopasked = True


    def run(self):
        print("start FileList thread")
        while not (self.stopasked):
            try:
                if not self.mother.Data_Path.endswith(os.path.sep):
                    dirname = self.mother.Data_Path + os.path.sep
                else:
                    dirname = self.mother.Data_Path
                files_list = glob.glob(os.path.join(dirname, "*.bin"))
                files_list.sort(key=os.path.getmtime, reverse=True)
                new_files_list = []
                for file in files_list:
                    warn_str = ''
                    size = os.stat(file).st_size
                    if size == 0:
                        warn_str = ' !! Empty File !!'
                    file_str = file + '\tSize=' + str(size) + warn_str
                    new_files_list.append(file_str)
                    setattr(self.mother,"attr_Files_list_read",new_files_list)
            except Exception as ex:
                raise ex
            time.sleep(self.mother.th_file_list_pause)
        print("State thread stopped")

class StateThread(Thread):
    def __init__(self, mother):
        Thread.__init__(self)
        print("init Statethread")
        self.mother = mother
        self.stopasked = True
        self.mother.set_state(tango.DevState.INIT)
        self.str_sep = '\n--------------------------\n'
        self.led_attr=['attr_Trigger_Fault_read','attr_Cam_Fault_read']

    def run(self):
        print("start State thread")
        while not (self.stopasked):
            try:
                try:
                    ps_outut = self.mother.keithley_ps.get_source_state()
                except Exception as ex:
                    self.mother.set_status("\nunable to communicate with Keitley power_supply !! check GPIB and powerSupply\n")
                    self.mother.set_state(tango.DevState.FAULT)
                r_led_status=kalypso_tools_for_acquisition.led_update()
                led_str='Boolean Status:\n-'+'\n-'.join(r_led_status[1])
                led_bool=r_led_status[0]
                led_bool_pll=led_bool[2:5]
                del led_bool[2:5]
                setattr(self.mother, self.led_attr[0], any(led_bool_pll))
                setattr(self.mother, self.led_attr[1], any(led_bool))
                str_state = ''
                if getattr(self.mother,"reset_in_progress") or getattr(self.mother,"acquisition_in_progress") or getattr(self.mother,"snap_in_progress"):
                    self.mother.set_state(PyTango.DevState.MOVING)
                    if getattr(self.mother,"reset_in_progress"):
                        str_state = 'Reset in progress... please be patient'
                    elif getattr(self.mother,"snap_in_progress"):
                        str_state = 'acquisition in progress...please be patient'
                    else:
                        str_state = 'acquisition in progress...please be patient -to stop acquisition send Stop command'
                elif self.mother.Local_synchro_attr !="":
                    loc_syn_attr=tango.AttributeProxy(self.mother.Local_synchro_attr)
                    loc_syn_attr_state=loc_syn_attr.state()
                    loc_syn_attr_value=loc_syn_attr.read().value
                    if loc_syn_attr_value != 3 or loc_syn_attr_state != tango.DevState.ON:
                        self.mother.set_state(tango.DevState.ALARM)
                        str_state = 'Please check Local synchro card: '+self.mother.Local_synchro_attr
                elif ps_outut == False:
                    self.mother.set_state(tango.DevState.ALARM)
                    str_state = 'Alarm Power_supply Off'
                else:
                    self.mother.set_state(tango.DevState.ON)
                    str_state = 'Ready to start measure'

                ps_state = 'Off !'
                ps_voltage = '\nVoltage= ' + str('%4.2f' % float(0)) + ' V'
                if ps_outut:
                    ps_state = 'On'
                    ps_voltage = self.mother.keithley_ps.measure_voltage()
                    ps_voltage = '\nVoltage= ' + str('%4.2f' % float(ps_voltage)) + ' V'
                str_ps = 'PowerSupply output:' + ps_state
                str_ps += ps_voltage
                str_ps += '\nGPIB device: ' + self.mother.keithley_GPIB_device
                str_conf_cam = 'ConfCam:' + self.mother.strconfcam
                str_data_path = 'DataPath:' + self.mother.strdatapath
                str_obl = 'OBL:' + self.mother.strconfobl
                status_list = [str_state, str_ps, str_conf_cam, str_data_path, str_obl,led_str]
                self.mother.strstatus = self.str_sep.join(status_list)
                self.mother.set_status(self.mother.strstatus)
                # kalypso_tools_for_acquisition.
                # status_led = read_register("STATUS_1", hex=True)
                # status_led = read_register("STATUS_1", hex=True)
                # status_led = int(status_led, 16)
                # status_led = '{:032b}'.format(status_led)


            except Exception as ex:
                print(ex)
                self.mother.set_state(tango.DevState.FAULT)


            time.sleep(self.mother.th_state_pause)
        print("State thread stopped")

class LoadImageThread(Thread):
    def __init__(self, mother):
        Thread.__init__(self)
        print("init LoadImagethread")
        self.mother = mother
        self.stopasked = True
        self.prev_file=''


    def run(self):
        print("start LoadImage thread")
        while not (self.stopasked):
            try:
                file=getattr(self.mother,"attr_Last_File_Name_read")
                if self.prev_file != file:
                    try:
                        self.mother.Load_Data(os.path.join(self.mother.Data_Path, file))
                    except Exception as ex:
                        print('!Loadimage:')
                        print(ex)
                self.prev_file=file
                if getattr(self.mother,"acquisition_in_progress") and getattr(self.mother,"Start_Drop_files"): #remove file
                    print('DropFiles:')
                    for f in getattr(self.mother,"file_out"):
                        print(str(os.path.join(self.mother.Data_Path, f + '.bin')))
                        try:
                            os.remove(os.path.join(self.mother.Data_Path, f + '.bin'))
                        except Exception as ex:
                            print(ex)
                        try:
                            os.remove(os.path.join(self.mother.Data_Path, f + '.h5'))
                        except Exception as ex:
                            print(ex)
            except Exception as ex:
                print(ex)
            time.sleep(self.mother.th_ldimg_pause)
        print("Loadimg thread stopped")

# ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.additionnal_import

# Device States Description
# No states for this device


class DG_PY_Kalypso (PyTango.Device_4Impl):
    """Used with kalypso detector"""
    
    # -------- Add you global variables here --------------------------
    # ----- PROTECTED REGION ID(DG_PY_Kalypso.global_variables) ENABLED START -----#
    def append_log_stdout(self,line):
        log_arr=getattr(self,"attr_log_read")
        log_arr.append(line)
        setattr(self,"attr_log_read",log_arr)

    def heartbeat_log_stdout(self):
        log_arr=getattr(self,"attr_log_read")
        line=log_arr[-1]
        if line[-10:]=='..........':
            line = line[:-10]
        else:
            line=line+'.'
        log_arr[-1]=line
        setattr(self,"attr_log_read",log_arr)

    def clear_log_stdout(self):
        setattr(self,"attr_log_read",[''])

    # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.global_variables

    def __init__(self, cl, name):
        PyTango.Device_4Impl.__init__(self,cl,name)
        self.debug_stream("In __init__()")
        DG_PY_Kalypso.init_device(self)
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.__init__) ENABLED START -----#
        self.th = StateThread(self)
        self.th.stopasked = False
        self.th.start()
        time.sleep(0.5)
        self.th2 = DriveThread(self)
        self.th2.stopasked = False
        self.th2.start()
        time.sleep(0.5)
        self.th3 = FileListThread(self)
        self.th3.stopasked = False
        self.th3.start()
        time.sleep(0.5)
        # self.th4 = LoadImageThread(self)
        # self.th4.stopasked = False
        # self.th4.start()
        # time.sleep(0.5)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.__init__
        
    def delete_device(self):
        self.debug_stream("In delete_device()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.delete_device) ENABLED START -----#

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.delete_device

    def init_device(self):
        self.debug_stream("In init_device()")
        self.get_device_properties(self.get_device_class())
        self.attr_nb_frames_read = 0
        self.attr_exp_time_read = 0
        self.attr_delay_for_fast_trigger_read = 0
        self.attr_Fast_Trig_Mode_External_read = False
        self.attr_Fast_Trig_Mode_Internal_read = False
        self.attr_Slow_Trig_Mode_External_read = False
        self.attr_Slow_Trig_Mode_Internal_read = False
        self.attr_Last_File_Name_read = ""
        self.attr_nb_acq_w_slow_trigger_read = 0
        self.attr_nb_skip_slow_trigger_read = 0
        self.attr_Trigger_Fault_read = False
        self.attr_Cam_Fault_read = False
        self.attr_Files_list_read = [""]
        self.attr_log_read = [""]
        self.attr_image_read = [[0.0]]
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.init_device) ENABLED START -----#
        self.set_state(tango.DevState.INIT)
        if hasattr(self, 'kill'):
            self.kill=True
        self.th_state_pause = 3
        self.th_ldimg_pause = 0.1
        self.th_drive_pause = 0.2
        self.th_file_list_pause = 3
        self.file_out=[] #to manage removing of files list
        self.reset_in_progress = False
        self.snap_in_progress = False
        self.acquisition_in_progress = False
        self.opt_slow_trigger_mode = 0 #previously set to 1
        self.opt_fast_trigger_mode = 0
        self.nb_acq_w_slow_trigger = 10
        self.nb_skip_slow_trigger = 0
        self.attr_delay_for_fast_trigger_read = int(self.delay_for_fast_trigger)
        self.keithley_ps = Keithley2400_v01.keithley2400(self.keithley_GPIB_device)
        self.dct_data_obl = {}
        self.dct_data_obl['pixel_size'] = self.OBL_pixel_size  # Kalypso detector pixel size (micron)
        self.dct_data_obl['beam'] = self.OBL_beam  # X or Z Beam diemnsion imaged on Kalypso camera
        self.dct_data_obl['BP_filter'] = self.OBL_BP_filter  # BandPass filter for spectral selection
        self.dct_data_obl['Polarization'] = self.OBL_Polarization  # Polarization of SR on Kalypso
        self.dct_data_obl[
            'dist_FirstHole_L1'] = self.OBL_dist_FirstHole_L1  # (mm) Dist. from first hole on optical table to first cylindric lens L1
        self.dct_data_obl['dist_L1_L2'] = self.OBL_dist_L1_L2  # Distance from L1 to second cylindric lens L2
        self.dct_data_obl['dist_L2_cam'] = self.OBL_dist_L2_cam  # Distance from L2 to Kalypso detector
        loop = 0
        self.fileroot = 'device_data_' + str(self.opt_nb_pixels) + 'pix_' + str(self.dct_data_obl['beam']) + '_n' + str(
            loop)
        self.strstatus = ''
        self.strconfcam = '\nnb_pixels: ' + str(self.opt_nb_pixels) + '\ndelay: ' + str(self.delay_for_fast_trigger)
        self.strdatapath = '\n' + self.Data_Path
        self.strconfobl = '\nOBL_beam: ' + self.OBL_beam + \
                          '\nOBL_BP_filter: ' + self.OBL_BP_filter + \
                          '\nOBL_Polarization: ' + self.OBL_Polarization + \
                          '\nOBL_pixel_size: ' + str(self.OBL_pixel_size) + \
                          '\nOBL_dist_FirstHole_L1: ' + str(
            eval(self.OBL_dist_FirstHole_L1)) + '-> ' + self.OBL_dist_FirstHole_L1 + \
                          '\nOBL_dist_L1_L2: ' + str(eval(self.OBL_dist_L1_L2)) + ' -> ' + self.OBL_dist_L1_L2 + \
                          '\nOBL_dist_L2_cam: ' + str(eval(self.OBL_dist_L2_cam)) + ' -> ' + self.OBL_dist_L2_cam
        time.sleep(3)
        self.set_state(tango.DevState.ON)
        self.kill = False

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.init_device

    def always_executed_hook(self):
        self.debug_stream("In always_excuted_hook()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.always_executed_hook) ENABLED START -----#

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.always_executed_hook

    # -------------------------------------------------------------------------
    #    DG_PY_Kalypso read/write attribute methods
    # -------------------------------------------------------------------------
    
    def read_nb_frames(self, attr):
        self.debug_stream("In read_nb_frames()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.nb_frames_read) ENABLED START -----#
        attr.set_value(self.attr_nb_frames_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.nb_frames_read
        
    def write_nb_frames(self, attr):
        self.debug_stream("In write_nb_frames()")
        data = attr.get_write_value()
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.nb_frames_write) ENABLED START -----#
        setattr(self, 'attr_nb_frames_read', data)
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.nb_frames_write
        
    def read_exp_time(self, attr):
        self.debug_stream("In read_exp_time()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.exp_time_read) ENABLED START -----#
        attr.set_value(self.attr_exp_time_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.exp_time_read
        
    def write_exp_time(self, attr):
        self.debug_stream("In write_exp_time()")
        data = attr.get_write_value()
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.exp_time_write) ENABLED START -----#
        setattr(self, 'attr_exp_time_read', data)
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.exp_time_write
        
    def read_delay_for_fast_trigger(self, attr):
        self.debug_stream("In read_delay_for_fast_trigger()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.delay_for_fast_trigger_read) ENABLED START -----#
        attr.set_value(self.attr_delay_for_fast_trigger_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.delay_for_fast_trigger_read
        
    def read_Fast_Trig_Mode_External(self, attr):
        self.debug_stream("In read_Fast_Trig_Mode_External()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Fast_Trig_Mode_External_read) ENABLED START -----#
        attr.set_value(not (self.opt_fast_trigger_mode))

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Fast_Trig_Mode_External_read
        
    def read_Fast_Trig_Mode_Internal(self, attr):
        self.debug_stream("In read_Fast_Trig_Mode_Internal()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Fast_Trig_Mode_Internal_read) ENABLED START -----#
        attr.set_value(self.opt_fast_trigger_mode)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Fast_Trig_Mode_Internal_read
        
    def read_Slow_Trig_Mode_External(self, attr):
        self.debug_stream("In read_Slow_Trig_Mode_External()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Slow_Trig_Mode_External_read) ENABLED START -----#
        attr.set_value(self.opt_slow_trigger_mode)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Slow_Trig_Mode_External_read
        
    def read_Slow_Trig_Mode_Internal(self, attr):
        self.debug_stream("In read_Slow_Trig_Mode_Internal()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Slow_Trig_Mode_Internal_read) ENABLED START -----#
        attr.set_value(not (self.opt_slow_trigger_mode))

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Slow_Trig_Mode_Internal_read
        
    def read_Last_File_Name(self, attr):
        self.debug_stream("In read_Last_File_Name()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Last_File_Name_read) ENABLED START -----#
        attr.set_value(self.attr_Last_File_Name_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Last_File_Name_read
        
    def read_nb_acq_w_slow_trigger(self, attr):
        self.debug_stream("In read_nb_acq_w_slow_trigger()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.nb_acq_w_slow_trigger_read) ENABLED START -----#
        attr.set_value(self.attr_nb_acq_w_slow_trigger_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.nb_acq_w_slow_trigger_read
        
    def write_nb_acq_w_slow_trigger(self, attr):
        self.debug_stream("In write_nb_acq_w_slow_trigger()")
        data = attr.get_write_value()
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.nb_acq_w_slow_trigger_write) ENABLED START -----#
        self.nb_acq_w_slow_trigger = data
        self.attr_nb_acq_w_slow_trigger_read = data
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.nb_acq_w_slow_trigger_write
        
    def read_nb_skip_slow_trigger(self, attr):
        self.debug_stream("In read_nb_skip_slow_trigger()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.nb_skip_slow_trigger_read) ENABLED START -----#
        attr.set_value(self.attr_nb_skip_slow_trigger_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.nb_skip_slow_trigger_read
        
    def write_nb_skip_slow_trigger(self, attr):
        self.debug_stream("In write_nb_skip_slow_trigger()")
        data = attr.get_write_value()
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.nb_skip_slow_trigger_write) ENABLED START -----#
        self.nb_skip_slow_trigger = data
        self.attr_nb_skip_slow_trigger_read = data
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.nb_skip_slow_trigger_write
        
    def read_Trigger_Fault(self, attr):
        self.debug_stream("In read_Trigger_Fault()")
        #----- PROTECTED REGION ID(DG_PY_Kalypso.Trigger_Fault_read) ENABLED START -----#
        attr.set_value(self.attr_Trigger_Fault_read)
        
        #----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Trigger_Fault_read
        
    def read_Cam_Fault(self, attr):
        self.debug_stream("In read_Cam_Fault()")
        #----- PROTECTED REGION ID(DG_PY_Kalypso.Cam_Fault_read) ENABLED START -----#
        attr.set_value(self.attr_Cam_Fault_read)
        
        #----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Cam_Fault_read
        
    def read_Files_list(self, attr):
        self.debug_stream("In read_Files_list()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Files_list_read) ENABLED START -----#
        attr.set_value(self.attr_Files_list_read)
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Files_list_read
        
    def read_log(self, attr):
        self.debug_stream("In read_log()")
        #----- PROTECTED REGION ID(DG_PY_Kalypso.log_read) ENABLED START -----#
        attr.set_value(self.attr_log_read)
        
        #----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.log_read
        
    def read_image(self, attr):
        self.debug_stream("In read_image()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.image_read) ENABLED START -----#
        attr.set_value(self.attr_image_read)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.image_read
        
    
    
            
    def read_attr_hardware(self, data):
        self.debug_stream("In read_attr_hardware()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.read_attr_hardware) ENABLED START -----#

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.read_attr_hardware


    # -------------------------------------------------------------------------
    #    DG_PY_Kalypso command methods
    # -------------------------------------------------------------------------
    
    def Start_PowerSupply(self):
        """ Activate output of Keithley PS
        with good setup of current and voltage
        """
        self.debug_stream("In Start_PowerSupply()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Start_PowerSupply) ENABLED START -----#
        kalypso_tools_for_acquisition.switch_on_power_supply(self.current_max, self.keithley_GPIB_device)
        kalypso_tools_for_acquisition.set_voltage_power_supply(self.voltage_value, self.current_max)  # voltage, curent_limit
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Start_PowerSupply
        
    def Stop_PowerSupply(self):
        """ Disable output of Keithley PS
        """
        self.debug_stream("In Stop_PowerSupply()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Stop_PowerSupply) ENABLED START -----#
        kalypso_tools_for_acquisition.switch_off_power_supply(self.current_max, self.keithley_GPIB_device)
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Stop_PowerSupply
        
    def Load_Data(self, argin):
        """ load data to plot in image attribut
        :param argin: 
        :type argin: PyTango.DevString
        """
        self.debug_stream("In Load_Data()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Load_Data) ENABLED START -----#
        print(argin)
        if os.path.exists(argin):
            fullpath = argin
        else:
            fullpath = os.path.join(self.Data_Path, argin)
        print('Load_File:')
        print(fullpath)
        size = os.stat(fullpath).st_size
        if size == 0:
            raise ValueError('File is Empty!')
        image = kalypso_tools_for_analysis.get_image(fullpath, self.opt_nb_pixels)
        image=np.rot90(image,k=1)
        setattr(self, 'attr_image_read', image)
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Load_Data
        
    def Reset(self):
        """ send sequence to reset kalypso detector
        """
        self.debug_stream("In Reset()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Reset) ENABLED START -----#
        state=self.get_state()
        self.error_stream(str(state))
        if state != tango.DevState.MOVING:
            self.error_stream("troiz In Reset()")
            setattr(self, 'reset_in_progress', True)
        else:
            self.error_stream('not allowed to reset device when it is in moving state')
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Reset
        
    def Snap(self):
        """ make one serie of acquisition with kalypso camera
        """
        self.debug_stream("In Snap()")
        #----- PROTECTED REGION ID(DG_PY_Kalypso.Snap) ENABLED START -----#
        if self.get_state() != tango.DevState.MOVING:
            setattr(self, 'snap_in_progress', True)
        else:
            self.error_stream('not allowed to get acquisition with device when it is in moving state')
        #----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Snap
        
    def Start(self):
        """ Start a serie of acquisition with kalypso camera
        """
        self.debug_stream("In Start()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Start) ENABLED START -----#
        if self.get_state() != tango.DevState.MOVING:
            setattr(self,'acquisition_in_progress', True)
        else:
            self.error_stream('not allowed to get acquisition with device when it is in moving state')
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Start
        
    def Stop(self):
        """ Stop the acquisition sequence
        """
        self.debug_stream("In Stop()")
        #----- PROTECTED REGION ID(DG_PY_Kalypso.Stop) ENABLED START -----#
        setattr(self,'acquisition_in_progress', False)
        #----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Stop
        
    def Set_Fast_Trigger_Mode(self):
        """ switch mode of fast Trigger
        """
        self.debug_stream("In Set_Fast_Trigger_Mode()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Set_Fast_Trigger_Mode) ENABLED START -----#
        if self.opt_fast_trigger_mode == 0:
            setattr(self, 'opt_fast_trigger_mode', 1)
        else:
            setattr(self, 'opt_fast_trigger_mode', 0)

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Set_Fast_Trigger_Mode
        
    def Set_Slow_Trigger_Mode(self):
        """ switch mode of slow Trigger
        """
        self.debug_stream("In Set_Slow_Trigger_Mode()")
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.Set_Slow_Trigger_Mode) ENABLED START -----#
        if self.opt_slow_trigger_mode == 0:
            setattr(self, 'opt_slow_trigger_mode', 1)
        else:
            setattr(self, 'opt_slow_trigger_mode', 0)
        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.Set_Slow_Trigger_Mode
        

    # ----- PROTECTED REGION ID(DG_PY_Kalypso.programmer_methods) ENABLED START -----#

    # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.programmer_methods

class DG_PY_KalypsoClass(PyTango.DeviceClass):
    # -------- Add you global class variables here --------------------------
    # ----- PROTECTED REGION ID(DG_PY_Kalypso.global_class_variables) ENABLED START -----#

    # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.global_class_variables


    #    Class Properties
    class_property_list = {
        'current_max':
            [PyTango.DevDouble, 
            "define the maximum current supported by kalypso detector",
            [15.e-6]],
        'voltage_value':
            [PyTango.DevDouble, 
            "define the standard value of voltage for Keithley_PS",
            [130.0]],
        }


    #    Device Properties
    device_property_list = {
        'Data_Path':
            [PyTango.DevString, 
            "the location of Folder where device store/load data files",
            ["/home/soleilg/kalypso/data"] ],
        'OBL_pixel_size':
            [PyTango.DevDouble, 
            "Kalypso detector pixel size (micron)",
            [25]],
        'OBL_beam':
            [PyTango.DevString, 
            "X or Z Beam diemnsion imaged on Kalypso camera",
            ["Z"] ],
        'OBL_BP_filter':
            [PyTango.DevString, 
            "BandPass filter for spectral selection",
            ["CL600nm_BW80nm"] ],
        'OBL_Polarization':
            [PyTango.DevString, 
            "Polarization of SR on Kalypso",
            ["H"] ],
        'OBL_dist_FirstHole_L1':
            [PyTango.DevString, 
            "(mm) Dist. from first hole on optical table to first cylindric lens L1",
            ["210.+120.+130.+30.+330."] ],
        'OBL_dist_L1_L2':
            [PyTango.DevString, 
            "Distance from L1 to second cylindric lens L2",
            ["230."] ],
        'OBL_dist_L2_cam':
            [PyTango.DevString, 
            "Distance from L2 to Kalypso detector",
            ["115."] ],
        'delay_for_fast_trigger':
            [PyTango.DevString, 
            "delay_for_fast_trigger",
            ["35"] ],
        'opt_nb_pixels':
            [PyTango.DevUShort, 
            "512 or 1024 \nfor standard operation use 512 pixels",
            [512]],
        'keithley_GPIB_device':
            [PyTango.DevString, 
            "the path of Prologix (GPIB) tango device to drive keithley PowerSupply",
            ["ans-c01/dg/gpib"] ],
        'Start_Drop_files':
            [PyTango.DevBoolean, 
            "If you dont want to keep files when you are in Star sequence mode",
            [False]],
        'Local_synchro_attr':
            [PyTango.DevString, 
            "check if local synchro was in good state to trig kalypso",
            [] ],
        }


    #    Command definitions
    cmd_list = {
        'Start_PowerSupply':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Stop_PowerSupply':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Load_Data':
            [[PyTango.DevString, "none"],
            [PyTango.DevVoid, "none"]],
        'Reset':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Snap':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Start':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Stop':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Set_Fast_Trigger_Mode':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'Set_Slow_Trigger_Mode':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        }


    #    Attribute definitions
    attr_list = {
        'nb_frames':
            [[PyTango.DevUShort,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'unit': "#",
                'max value': "2048",
                'min value': "0",
                'description': "100 / 256 / 512 / 1024 / 2048",
                'Memorized':"true"
            } ],
        'exp_time':
            [[PyTango.DevULong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'unit': "ns",
                'min value': "0",
                'description': "	# MEMO\n	# 1 turn = 1180 ns\n	# 1 quart = 295 ns\n	# 2 quarts = 590 ns\n	# 3 quarts = 886 ns\n	# 4 quarts = 1180 ns ",
                'Memorized':"true"
            } ],
        'delay_for_fast_trigger':
            [[PyTango.DevULong,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'unit': "ns",
                'description': "	# MEMO\n	# 127 = Delay for single bunch / isolated bunch in hybrid (middle of Q4)\n	# 108 = 127 - (295/2)/8 = Delay to start recording at begining of Q4\n	# 146 = 127 + (295/2)/8 = Delay to start recording at begining of Q1\n	# 183 = 146. + 295./8. = Delay to start recording at begining of Q2\n	# 220 = 146. + 295./8.*2. = Delay to start recording at begining of Q3\n	# 257 = 146. + 295./8.*3. = Delay to start recording at begining of Q4\n	# 147 * 8 = 1180 ns",
            } ],
        'Fast_Trig_Mode_External':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ]],
        'Fast_Trig_Mode_Internal':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ]],
        'Slow_Trig_Mode_External':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ]],
        'Slow_Trig_Mode_Internal':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ]],
        'Last_File_Name':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ]],
        'nb_acq_w_slow_trigger':
            [[PyTango.DevUShort,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'min value': "10",
                'description': "number of slow acquisition \nminimum 10",
                'Display level': PyTango.DispLevel.EXPERT,
                'Memorized':"true"
            } ],
        'nb_skip_slow_trigger':
            [[PyTango.DevUShort,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'min value': "0",
                'description': "if you want to skip some acquisition",
                'Display level': PyTango.DispLevel.EXPERT,
                'Memorized':"true"
            } ],
        'Trigger_Fault':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ]],
        'Cam_Fault':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ]],
        'Files_list':
            [[PyTango.DevString,
            PyTango.SPECTRUM,
            PyTango.READ, 5000]],
        'log':
            [[PyTango.DevString,
            PyTango.SPECTRUM,
            PyTango.READ, 500]],
        'image':
            [[PyTango.DevDouble,
            PyTango.IMAGE,
            PyTango.READ, 2048, 2048]],
        }


def main():
    try:
        py = PyTango.Util(sys.argv)
        py.add_class(DG_PY_KalypsoClass, DG_PY_Kalypso, 'DG_PY_Kalypso')
        # ----- PROTECTED REGION ID(DG_PY_Kalypso.add_classes) ENABLED START -----#

        # ----- PROTECTED REGION END -----#	//	DG_PY_Kalypso.add_classes

        U = PyTango.Util.instance()
        U.server_init()
        U.server_run()

    except PyTango.DevFailed as e:
        print ('-------> Received a DevFailed exception:', e)
    except Exception as e:
        print ('-------> An unforeseen exception occured....', e)

if __name__ == '__main__':
    main()