<filename>Main_Tweak_Test-copy.py
import Call_UTI
from send_multiple_setpoints import *
from read_Temp_value import *
import numpy as np
import pandas as pd
import os
import sys
from threading import Thread
from ctypes import *
import time
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import numpy as np
import math
from thermocouples_reference import thermocouples
import itertools
# from initial_UTI import *

"""
1. start reading the masses cycle through 1-2 times (check)
2. take the average time to cycle = total time to write setpoints (check)
3. start the 'official' program
4. read temperature, and masses and write while reading the masses
a. assume that the time to read the temperature = 0

do read mass 2 times:
get the cycle time


for asdfa:
do read mass and write sp(cycle time) use threads
thread1.join()
thread2.join()
do read value
"""

########################################################################################################################


def thread_send_mV_setpoint(iter_freq_, mv_setpoints_, sendFreq, alpha, child_thread):
    # alpha_iter = 0
    while child_thread.isAlive():
        # start_alpha = time.time()
        # currentTime = time.time()
        # Write new setpoint for temperature
        # adjust send freq
        time.sleep(alpha*sendFreq)

        try:
            if iter_freq_ < len(mv_setpoints_):
                controlObj.write_sp(mv_setpoints_[iter_freq_])
                # TODO might insert the sleep here
                iter_freq_ += 1
            else:
                controlObj.write_sp(mv_setpoints_[0])

        except (IndexError, OSError) as e:
            print(e)
            # probably wrote past the last mv setpoint, so just go back to first setpoint....
            # this is also a safety in case theres a brief communication error
            try:
                time.sleep(0.01)
                controlObj.close_me()
                controlObj.open_me()
                if iter_freq_ < len(mv_setpoints_):
                    controlObj.write_sp(mv_setpoints_[iter_freq_])
                    iter_freq_ += 1
                else:
                    controlObj.write_sp(mv_setpoints_[0])
            except (ValueError, OSError) as e:
                print(e)
                try:
                    time.sleep(0.01)
                    controlObj.close_me()
                    controlObj.open_me()
                    if iter_freq_ < len(mv_setpoints_):
                        controlObj.write_sp(mv_setpoints_[iter_freq_])
                        iter_freq_ += 1
                    else:
                        controlObj.write_sp(mv_setpoints_[0])
                finally:
                    controlObj.close_me()
                    controlObj.open_me()
                    controlObj.write_sp(mv_setpoints_[0])
                    print('give up')
        except (ValueError, OSError) as e:
            print(e)
            try:
                time.sleep(0.01)
                controlObj.close_me()
                controlObj.open_me()
                if iter_freq_ < len(mv_setpoints_):
                    controlObj.write_sp(mv_setpoints_[iter_freq_])
                    iter_freq_ += 1
                else:
                    controlObj.write_sp(mv_setpoints_[0])
            except (ValueError, OSError) as e:
                print(e)
                try:
                    time.sleep(0.01)
                    controlObj.close_me()
                    controlObj.open_me()
                    if iter_freq_ < len(mv_setpoints_):
                        controlObj.write_sp(mv_setpoints_[iter_freq_])
                        iter_freq_ += 1
                    else:
                        controlObj.write_sp(mv_setpoints_[0])
                finally:
                    controlObj.close_me()
                    controlObj.open_me()
                    controlObj.write_sp(mv_setpoints_[0])
                    print('give up')

        # if alpha_iter%int(2/sendFreq) == 0:
        #     # do stuff, adjust alpha
        #     end_alpha = time.time() - start_alpha
        #     alpha = alpha * (end_T - start_T) / (end_alpha * heatingRate)
        #
        #
        # alpha_iter+=1
        # for controlling the frequency that data is sent
        # if time.time()-start_time < data_freq:
        #     time.sleep(data_freq - (time.time()-start_time))

    # if iter_freq_ == len(mv_setpoints_)-1:
    #     return iter_freq_, mv_setpoints_[-1]
    # else:
    #     return iter_freq_, mv_setpoints_[iter_freq_]
    return iter_freq_


def thread_read_masses(list_of_masses_, list_of_sensitivities_, mass_signals_):
    for mass, sens in zip(list_of_masses_, list_of_sensitivities_):
        mass_signals_['mass{0}'.format(mass)] = np.append(mass_signals_['mass{0}'.format(mass)],
                                                          uti1.read_mass(mass, sens))
        # mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g')
    return mass_signals_


def emergency_stop():
    # stop increasing the temp and send a safe setpoint
    controlObj.write_sp(0.0)
    time.sleep(10)
    quit()


class UTI_QMS():
    def __init__(self,path, dll='scan_single_mass.dll'):
        self.path = path
        self.dll = dll
        os.chdir(self.path)
        self.LabVIEWQMS = cdll.LoadLibrary(self.dll)
        self.LabVIEWQMS.Read_Mass_Spec.argtype = [c_int32, c_double]
        self.LabVIEWQMS.Read_Mass_Spec.restype = c_double

    def read_mass(self, _mass_, sensitivity):
        _signal_ = self.LabVIEWQMS.Read_Mass_Spec(c_int32(sensitivity), c_double(_mass_))
        # return [signal, mass, sensitivity]
        return _signal_
########################################################################################################################

rootdir = 'C:\\Users\\Administrator\\Desktop\\PythonProjects\\LabViewtest'
dlldir = 'C:\\Users\\Administrator\\Desktop\\builds\\scanmass_single\\scan_single_mass'
""" Create UTI instance """
uti1 = UTI_QMS(path=dlldir)

""" Create Eurotherm instances """
"Create obj for reading and writing temperature to Eurotherm"
port1 = 'COM4'
controlObj = Eurotherm(port1)
"Create obj for reading Room temperature from Eurotherm"
port2 = 'COM5'
controlObj2 = Eurotherm(port2)

"For reading in Room Temp to correct Temp reading"
typeC = thermocouples['C']

########################################################################################################################
""" User-Defined Parameters: """

os.chdir(rootdir)
project_folder = 'project_name'
os.makedirs(project_folder, exist_ok=True)
experiment_name ='name1.csv'
# TODO vary masses and see how that affects response
number_of_masses = 8
list_of_masses = [4.0, 12.2, 28.1, 32.4,4.1, 12.3, 28.12, 32.5]
list_of_sensitivities = [4, 4, 4, 4,4, 4, 4, 4]
heating_rate = 7    # K/s
os.chdir(rootdir)
with open('interp_mV_to_Temp_func.pickle', 'rb') as f:
    mV_T_table = pickle.load(f)
start_temp = np.round(read_temp(
                    controlObj.read_val(), typeC.emf_mVC(controlObj2.read_rt()), mV_T_table), 2)
end_temp = 700

assert len(list_of_masses) == number_of_masses, 'lengths do not match up'
assert len(list_of_sensitivities) == number_of_masses, 'lengths do not match up'
assert len(list_of_masses) == len(set(list_of_masses)), 'you have duplicate masses being monitored'

########################################################################################################################

""" Check time to loop through masses: """
no_of_loops = 5
single_read_times = []
set_read_times = []
for i in range(no_of_loops):
    start_set = time.time()
    for j in range(number_of_masses):
        start_single = time.time()
        signal = uti1.read_mass(list_of_masses[j], list_of_sensitivities[j])
        end_single = time.time() - start_single
        single_read_times.append(end_single)
    end_set = time.time() - start_set
    set_read_times.append(end_set)

mean_single = np.mean(single_read_times)
""" This should be the time taken each loop to write setpoints """
mean_set = np.mean(set_read_times)
print("Average single read time is:   {0}".format(np.round(mean_single, 4)))
print("Average set read time is:   {0}".format(np.round(mean_set, 4)))


# Initial UTI looping
# mean_single, mean_set = loop__time(number_of_masses, list_of_masses, list_of_sensitivities)


""" Determine setpoint increment """
# multiple = 2 # how many times per second to change the setpoint
# temp_set_incr = heating_rate * mean_set/multiple     # setpoint increment assuming each loop takes "mean_set" seconds

sendFreq = 0.1
alpha = 1
# rate_adjust = 1.9
# temp_set_incr = heating_rate * data_freq * rate_adjust    # setpoint increment assuming each loop takes "mean_set" seconds
temp_set_incr = heating_rate * sendFreq*2  # setpoint increment assuming each loop takes "mean_set" seconds
# temp_set_incr = heating_rate * sendFreq*1.75   # setpoint increment assuming each loop takes "mean_set" seconds
temp_setpoints = np.arange(start_temp, end_temp+1, temp_set_incr)
# making the list of setpoint values to be sent at each loop iteration
os.chdir(rootdir)
with open('interp_Temp_to_mV_func.pickle','rb') as interpdvalues:
    interpd = pickle.load(interpdvalues)
    # These are the mV that will be sent to the Eurotherm
    mv_setpoints = interpd(temp_setpoints - controlObj2.read_rt())

""" Set up multiple plot windows for TPD """
app = pg.QtGui.QApplication([])
win1 = pg.GraphicsWindow(title="QMS Signal Plots")
win1.resize(710, 970/4*math.ceil(number_of_masses/2))
win2 = pg.GraphicsWindow(title="Temperature Plot")
win2.resize(420, 400)

proxy = QtGui.QGraphicsProxyWidget()
button = QtGui.QPushButton('STOP')
proxy.setWidget(button)

Tplot = win2.addPlot(title="Temperature (K)", labels={'bottom': 'Time(s)', 'left': 'Temperature (K)'})
Tplot.addLegend()
Tplot.showGrid(x=True, y=True, alpha=1)

stop_button = win2.addItem(proxy)
button.clicked.connect(emergency_stop)

plots = []
for j in range(int(math.ceil(number_of_masses/2))):
    plots.append([win1.addPlot(title="m/e = {0}".format(list_of_masses[2*j+i]), labels={'bottom': 'Temperature(K)',
                                                                                        'left': 'Signal (a.u.)'})
                  for i in range(2) if 2*j+i < number_of_masses])
    win1.nextRow()

plots = list(itertools.chain.from_iterable(plots))

curves = [plots[k].plot() for k in range(number_of_masses)]

T_read_curve = Tplot.plot(name='readout')
T_set_curve = Tplot.plot(name='setpoint')

pg.QtGui.QApplication.processEvents()

""" Main script loops for TPD """

"""
Basic structure of measurement loop:
for asdfa:
do read mass and write sp(cycle time) use threads
thread1.join()
thread2.join()
do read value

"""

T_array = np.array([])
time_array = np.array([])

# Make mass spec signals a dictionary of np.arrays so we can append to and manipulate each individually
# initialize dictionary of empty arrays
mass_signals = {}
for i in list_of_masses:
    mass_signals["mass{0}".format(i)] = np.array([])


""" 
This will need to be threaded, below
"""

# num_freq = 1
iter_freq = 0
temp_plot_arr = np.array([])
# this needs to be the max temperature or allowed to cut short if needed, also allow for the threading
# TODO increase frequency that setpoints are sent, maybe this fixes the tracking issue at higher temperatures.
# for i in range(50):
print('len of setpoints is: '+str(len(mv_setpoints)))
# for i, v, in enumerate(mv_setpoints):
#     # for i in range(len(temp_setpoints)):
#     #     line below may be useful at times for debugging
#     currentTime = time.time()
#     # append current time to the array.
#     time_array = np.append(time_array, time.time())
#     # Read time and temperature data
#     cum_time = np.cumsum(np.concatenate(([0], np.diff(time_array))))
#     T_array = np.append(T_array, read_Temp_value())
#     T_read_curve.setData(x=cum_time, y=T_array, pen='b', name='readout')
#     # Write new setpoint for temperature
#     try:
#         # controlObj.write_sp(mv_setpoints[iter_freq])
#         if iter_freq <= len(temp_setpoints) and iter_freq != 0:
#             # temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[multiple*i])
#             temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[i])
#         else:
#             temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[0])
#     except IndexError as e:
#         print(e)
#         controlObj.write_sp(mv_setpoints[0])
#     # T_set_curve.setData(x=cum_time,y=temp_setpoints[:2*i+1:2], pen='r',name='setpoint')
#     # T_set_curve.setData(x=cum_time, y=temp_plot_arr[:2*len(cum_time):2], pen='r', name='setpoint')
#     T_set_curve.setData(x=cum_time, y=temp_plot_arr, pen='r', name='setpoint')
#
#     # for j in range(number_of_masses):
#
#     for mass, sens, mass_plot in zip(list_of_masses, list_of_sensitivities, curves):
#         # np.append(mass_signals["mass{0}".format(list_of_masses[j])], uti1.read_mass(list_of_masses[j],list_of_sensitivities[j]))
#         mass_signals['mass{0}'.format(mass)] = np.append(mass_signals['mass{0}'.format(mass)], uti1.read_mass(mass, sens))
#         mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g')
#         # if num_freq%2 == 0:
#     try:
#         if iter_freq < len(mv_setpoints):
#             controlObj.write_sp(mv_setpoints[iter_freq])
#             iter_freq+=1
#         else:
#             controlObj.write_sp(mv_setpoints[0])
#
#     except (IndexError, OSError) as e:
#         print(e)
#         # probably wrote past the last mv setpoint, so just go back to first setpoint....
#         # this is also a safety in case theres a brief communication error
#         try:
#             time.sleep(0.01)
#             controlObj.close_me()
#             controlObj.open_me()
#             if iter_freq < len(mv_setpoints):
#                 controlObj.write_sp(mv_setpoints[iter_freq])
#                 iter_freq += 1
#             else:
#                 controlObj.write_sp(mv_setpoints[0])
#         except (ValueError, OSError) as e:
#             print(e)
#             try:
#                 time.sleep(0.01)
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 if iter_freq < len(mv_setpoints):
#                     controlObj.write_sp(mv_setpoints[iter_freq])
#                     iter_freq += 1
#                 else:
#                     controlObj.write_sp(mv_setpoints[0])
#             finally:
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 controlObj.write_sp(mv_setpoints[0])
#                 print('give up')
#     except (ValueError, OSError) as e:
#         print(e)
#         try:
#             time.sleep(0.01)
#             controlObj.close_me()
#             controlObj.open_me()
#             if iter_freq < len(mv_setpoints):
#                 controlObj.write_sp(mv_setpoints[iter_freq])
#             else:
#                 controlObj.write_sp(mv_setpoints[0])
#         except (ValueError, OSError) as e:
#             print(e)
#             try:
#                 time.sleep(0.01)
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 if iter_freq < len(mv_setpoints):
#                     controlObj.write_sp(mv_setpoints[iter_freq])
#                 else:
#                     controlObj.write_sp(mv_setpoints[0])
#             finally:
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 controlObj.write_sp(mv_setpoints[0])
#                 print('give up')
#
#         num_freq+=1
#     # update the plots after going through all the masses

alpha_iter = 1
while iter_freq < len(mv_setpoints):
    # append current time to the array.
    time_array = np.append(time_array, time.time())
    # Read time and temperature data
    cum_time = np.cumsum(np.concatenate(([0], np.diff(time_array))))

    t = Thread(target=thread_read_masses, args=(list_of_masses, list_of_sensitivities, mass_signals))
    t.start()
    start_alpha = time.time()
    iter_freq = thread_send_mV_setpoint(iter_freq, mv_setpoints, sendFreq,alpha, t)

    # Write new setpoint for temperature
    try:
        # controlObj.write_sp(mv_setpoints[iter_freq])
        if iter_freq <= len(temp_setpoints) and iter_freq != 0:
            # temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[multiple*i])
            temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[iter_freq])
        else:
            temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[0])
    except IndexError as e:
        print(e)
        controlObj.write_sp(mv_setpoints[0])
    # T_set_curve.setData(x=cum_time,y=temp_setpoints[:2*i+1:2], pen='r',name='setpoint')
    # T_set_curve.setData(x=cum_time, y=temp_plot_arr[:2*len(cum_time):2], pen='r', name='setpoint')

    try:
        T_set_curve.setData(x=cum_time[:len(temp_plot_arr)], y=temp_plot_arr, pen='r', name='setpoint')
    except:
        T_set_curve.setData(x=cum_time, y=temp_plot_arr[:len(cum_time)], pen='r', name='setpoint')

    T_array = np.append(T_array, read_Temp_value())
    T_read_curve.setData(x=cum_time, y=T_array, pen='b', name='readout')

    # if alpha_iter % int(2 / sendFreq) == 0:
    if alpha_iter % 2 == 0:
        # do stuff, adjust alpha
        end_alpha = time.time() - start_alpha
        eval_alpha = alpha * (T_array[-1] - T_array[-2]) / (end_alpha * heating_rate)
        if eval_alpha > 0.7:
            alpha = eval_alpha
        print('alpha: ' + str(alpha))
    alpha_iter += 1

    for mass, mass_plot in zip(list_of_masses, curves):
        mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g')

    # T_set_curve.setData(x=cum_time,y=temp_plot_arr[:len(cum_time)], pen='r',name='setpoint')
    pg.QtGui.QApplication.processEvents()

    # uncomment if you want to see some cooldown
    if iter_freq == len(mv_setpoints):
        break
# include changing setpoints in stuff above

# at the very end, go back to initial mV setpoint
controlObj.write_sp(mv_setpoints[0] - interpd(controlObj2.read_rt()+273.15))

"""
read current value and add to plot, also include setpoint curve here too
"""
# T_array = np.append(T_array, read_Temp_value())
# T_read_curve.setData(x=cum_time, y=T_array)
pg.QtGui.QApplication.processEvents()

controlObj.close_me()
controlObj2.close_me()

os.chdir(project_folder)

time_Temp_arr = np.vstack((cum_time, T_array))
combined_data = pd.concat([pd.DataFrame(time_Temp_arr).T, pd.DataFrame.from_dict(mass_signals)], axis=1)
combined_data.rename(columns={0:'Time(s)', 1:'Temp(K)'}, inplace=True)

# save experiment
combined_data.to_csv(experiment_name, index=False, sep='\t')

print('hi')

if __name__ == '__main__':
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        app.exec_()  # Start QApplication event loop ***

<filename>Main_Tweak_Test-copy.py
import Call_UTI
from send_multiple_setpoints import *
from read_Temp_value import *
import numpy as np
import pandas as pd
import os
import sys
from threading import Thread
from ctypes import *
import time
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import numpy as np
import math
from thermocouples_reference import thermocouples
import itertools
# from initial_UTI import *

"""
1. start reading the masses cycle through 1-2 times (check)
2. take the average time to cycle = total time to write setpoints (check)
3. start the 'official' program
4. read temperature, and masses and write while reading the masses
a. assume that the time to read the temperature = 0

do read mass 2 times:
get the cycle time


for asdfa:
do read mass and write sp(cycle time) use threads
thread1.join()
thread2.join()
do read value
"""

########################################################################################################################


def thread_send_mV_setpoint(iter_freq_, mv_setpoints_, sendFreq, alpha, child_thread):
    # alpha_iter = 0
    while child_thread.isAlive():
        # start_alpha = time.time()
        # currentTime = time.time()
        # Write new setpoint for temperature
        # adjust send freq
        time.sleep(alpha*sendFreq)

        try:
            if iter_freq_ < len(mv_setpoints_):
                controlObj.write_sp(mv_setpoints_[iter_freq_])
                # TODO might insert the sleep here
                iter_freq_ += 1
            else:
                controlObj.write_sp(mv_setpoints_[0])

        except (IndexError, OSError) as e:
            print(e)
            # probably wrote past the last mv setpoint, so just go back to first setpoint....
            # this is also a safety in case theres a brief communication error
            try:
                time.sleep(0.01)
                controlObj.close_me()
                controlObj.open_me()
                if iter_freq_ < len(mv_setpoints_):
                    controlObj.write_sp(mv_setpoints_[iter_freq_])
                    iter_freq_ += 1
                else:
                    controlObj.write_sp(mv_setpoints_[0])
            except (ValueError, OSError) as e:
                print(e)
                try:
                    time.sleep(0.01)
                    controlObj.close_me()
                    controlObj.open_me()
                    if iter_freq_ < len(mv_setpoints_):
                        controlObj.write_sp(mv_setpoints_[iter_freq_])
                        iter_freq_ += 1
                    else:
                        controlObj.write_sp(mv_setpoints_[0])
                finally:
                    controlObj.close_me()
                    controlObj.open_me()
                    controlObj.write_sp(mv_setpoints_[0])
                    print('give up')
        except (ValueError, OSError) as e:
            print(e)
            try:
                time.sleep(0.01)
                controlObj.close_me()
                controlObj.open_me()
                if iter_freq_ < len(mv_setpoints_):
                    controlObj.write_sp(mv_setpoints_[iter_freq_])
                    iter_freq_ += 1
                else:
                    controlObj.write_sp(mv_setpoints_[0])
            except (ValueError, OSError) as e:
                print(e)
                try:
                    time.sleep(0.01)
                    controlObj.close_me()
                    controlObj.open_me()
                    if iter_freq_ < len(mv_setpoints_):
                        controlObj.write_sp(mv_setpoints_[iter_freq_])
                        iter_freq_ += 1
                    else:
                        controlObj.write_sp(mv_setpoints_[0])
                finally:
                    controlObj.close_me()
                    controlObj.open_me()
                    controlObj.write_sp(mv_setpoints_[0])
                    print('give up')

        # if alpha_iter%int(2/sendFreq) == 0:
        #     # do stuff, adjust alpha
        #     end_alpha = time.time() - start_alpha
        #     alpha = alpha * (end_T - start_T) / (end_alpha * heatingRate)
        #
        #
        # alpha_iter+=1
        # for controlling the frequency that data is sent
        # if time.time()-start_time < data_freq:
        #     time.sleep(data_freq - (time.time()-start_time))

    # if iter_freq_ == len(mv_setpoints_)-1:
    #     return iter_freq_, mv_setpoints_[-1]
    # else:
    #     return iter_freq_, mv_setpoints_[iter_freq_]
    return iter_freq_


def thread_read_masses(list_of_masses_, list_of_sensitivities_, mass_signals_):
    for mass, sens in zip(list_of_masses_, list_of_sensitivities_):
        mass_signals_['mass{0}'.format(mass)] = np.append(mass_signals_['mass{0}'.format(mass)],
                                                          uti1.read_mass(mass, sens))
        # mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g')
    return mass_signals_


def emergency_stop():
    # stop increasing the temp and send a safe setpoint
    controlObj.write_sp(0.0)
    time.sleep(10)
    quit()


class UTI_QMS():
    def __init__(self,path, dll='scan_single_mass.dll'):
        self.path = path
        self.dll = dll
        os.chdir(self.path)
        self.LabVIEWQMS = cdll.LoadLibrary(self.dll)
        self.LabVIEWQMS.Read_Mass_Spec.argtype = [c_int32, c_double]
        self.LabVIEWQMS.Read_Mass_Spec.restype = c_double

    def read_mass(self, _mass_, sensitivity):
        _signal_ = self.LabVIEWQMS.Read_Mass_Spec(c_int32(sensitivity), c_double(_mass_))
        # return [signal, mass, sensitivity]
        return _signal_
########################################################################################################################

rootdir = 'C:\\Users\\Administrator\\Desktop\\PythonProjects\\LabViewtest'
dlldir = 'C:\\Users\\Administrator\\Desktop\\builds\\scanmass_single\\scan_single_mass'
""" Create UTI instance """
uti1 = UTI_QMS(path=dlldir)

""" Create Eurotherm instances """
"Create obj for reading and writing temperature to Eurotherm"
port1 = 'COM4'
controlObj = Eurotherm(port1)
"Create obj for reading Room temperature from Eurotherm"
port2 = 'COM5'
controlObj2 = Eurotherm(port2)

"For reading in Room Temp to correct Temp reading"
typeC = thermocouples['C']

########################################################################################################################
""" User-Defined Parameters: """

os.chdir(rootdir)
project_folder = 'project_name'
os.makedirs(project_folder, exist_ok=True)
experiment_name ='name1.csv'
# TODO vary masses and see how that affects response
number_of_masses = 8
list_of_masses = [4.0, 12.2, 28.1, 32.4,4.1, 12.3, 28.12, 32.5]
list_of_sensitivities = [4, 4, 4, 4,4, 4, 4, 4]
heating_rate = 7    # K/s
os.chdir(rootdir)
with open('interp_mV_to_Temp_func.pickle', 'rb') as f:
    mV_T_table = pickle.load(f)
start_temp = np.round(read_temp(
                    controlObj.read_val(), typeC.emf_mVC(controlObj2.read_rt()), mV_T_table), 2)
end_temp = 700

assert len(list_of_masses) == number_of_masses, 'lengths do not match up'
assert len(list_of_sensitivities) == number_of_masses, 'lengths do not match up'
assert len(list_of_masses) == len(set(list_of_masses)), 'you have duplicate masses being monitored'

########################################################################################################################

""" Check time to loop through masses: """
no_of_loops = 5
single_read_times = []
set_read_times = []
for i in range(no_of_loops):
    start_set = time.time()
    for j in range(number_of_masses):
        start_single = time.time()
        signal = uti1.read_mass(list_of_masses[j], list_of_sensitivities[j])
        end_single = time.time() - start_single
        single_read_times.append(end_single)
    end_set = time.time() - start_set
    set_read_times.append(end_set)

mean_single = np.mean(single_read_times)
""" This should be the time taken each loop to write setpoints """
mean_set = np.mean(set_read_times)
print("Average single read time is:   {0}".format(np.round(mean_single, 4)))
print("Average set read time is:   {0}".format(np.round(mean_set, 4)))


# Initial UTI looping
# mean_single, mean_set = loop__time(number_of_masses, list_of_masses, list_of_sensitivities)


""" Determine setpoint increment """
# multiple = 2 # how many times per second to change the setpoint
# temp_set_incr = heating_rate * mean_set/multiple     # setpoint increment assuming each loop takes "mean_set" seconds

sendFreq = 0.1
alpha = 1
# rate_adjust = 1.9
# temp_set_incr = heating_rate * data_freq * rate_adjust    # setpoint increment assuming each loop takes "mean_set" seconds
temp_set_incr = heating_rate * sendFreq*2  # setpoint increment assuming each loop takes "mean_set" seconds
# temp_set_incr = heating_rate * sendFreq*1.75   # setpoint increment assuming each loop takes "mean_set" seconds
temp_setpoints = np.arange(start_temp, end_temp+1, temp_set_incr)
# making the list of setpoint values to be sent at each loop iteration
os.chdir(rootdir)
with open('interp_Temp_to_mV_func.pickle','rb') as interpdvalues:
    interpd = pickle.load(interpdvalues)
    # These are the mV that will be sent to the Eurotherm
    mv_setpoints = interpd(temp_setpoints - controlObj2.read_rt())

""" Set up multiple plot windows for TPD """
app = pg.QtGui.QApplication([])
win1 = pg.GraphicsWindow(title="QMS Signal Plots")
win1.resize(710, 970/4*math.ceil(number_of_masses/2))
win2 = pg.GraphicsWindow(title="Temperature Plot")
win2.resize(420, 400)

proxy = QtGui.QGraphicsProxyWidget()
button = QtGui.QPushButton('STOP')
proxy.setWidget(button)

Tplot = win2.addPlot(title="Temperature (K)", labels={'bottom': 'Time(s)', 'left': 'Temperature (K)'})
Tplot.addLegend()
Tplot.showGrid(x=True, y=True, alpha=1)

stop_button = win2.addItem(proxy)
button.clicked.connect(emergency_stop)

plots = []
for j in range(int(math.ceil(number_of_masses/2))):
    plots.append([win1.addPlot(title="m/e = {0}".format(list_of_masses[2*j+i]), labels={'bottom': 'Temperature(K)',
                                                                                        'left': 'Signal (a.u.)'})
                  for i in range(2) if 2*j+i < number_of_masses])
    win1.nextRow()

plots = list(itertools.chain.from_iterable(plots))

curves = [plots[k].plot() for k in range(number_of_masses)]

T_read_curve = Tplot.plot(name='readout')
T_set_curve = Tplot.plot(name='setpoint')

pg.QtGui.QApplication.processEvents()

""" Main script loops for TPD """

"""
Basic structure of measurement loop:
for asdfa:
do read mass and write sp(cycle time) use threads
thread1.join()
thread2.join()
do read value

"""

T_array = np.array([])
time_array = np.array([])

# Make mass spec signals a dictionary of np.arrays so we can append to and manipulate each individually
# initialize dictionary of empty arrays
mass_signals = {}
for i in list_of_masses:
    mass_signals["mass{0}".format(i)] = np.array([])


""" 
This will need to be threaded, below
"""

# num_freq = 1
iter_freq = 0
temp_plot_arr = np.array([])
# this needs to be the max temperature or allowed to cut short if needed, also allow for the threading
# TODO increase frequency that setpoints are sent, maybe this fixes the tracking issue at higher temperatures.
# for i in range(50):
print('len of setpoints is: '+str(len(mv_setpoints)))
# for i, v, in enumerate(mv_setpoints):
#     # for i in range(len(temp_setpoints)):
#     #     line below may be useful at times for debugging
#     currentTime = time.time()
#     # append current time to the array.
#     time_array = np.append(time_array, time.time())
#     # Read time and temperature data
#     cum_time = np.cumsum(np.concatenate(([0], np.diff(time_array))))
#     T_array = np.append(T_array, read_Temp_value())
#     T_read_curve.setData(x=cum_time, y=T_array, pen='b', name='readout')
#     # Write new setpoint for temperature
#     try:
#         # controlObj.write_sp(mv_setpoints[iter_freq])
#         if iter_freq <= len(temp_setpoints) and iter_freq != 0:
#             # temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[multiple*i])
#             temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[i])
#         else:
#             temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[0])
#     except IndexError as e:
#         print(e)
#         controlObj.write_sp(mv_setpoints[0])
#     # T_set_curve.setData(x=cum_time,y=temp_setpoints[:2*i+1:2], pen='r',name='setpoint')
#     # T_set_curve.setData(x=cum_time, y=temp_plot_arr[:2*len(cum_time):2], pen='r', name='setpoint')
#     T_set_curve.setData(x=cum_time, y=temp_plot_arr, pen='r', name='setpoint')
#
#     # for j in range(number_of_masses):
#
#     for mass, sens, mass_plot in zip(list_of_masses, list_of_sensitivities, curves):
#         # np.append(mass_signals["mass{0}".format(list_of_masses[j])], uti1.read_mass(list_of_masses[j],list_of_sensitivities[j]))
#         mass_signals['mass{0}'.format(mass)] = np.append(mass_signals['mass{0}'.format(mass)], uti1.read_mass(mass, sens))
#         mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g')
#         # if num_freq%2 == 0:
#     try:
#         if iter_freq < len(mv_setpoints):
#             controlObj.write_sp(mv_setpoints[iter_freq])
#             iter_freq+=1
#         else:
#             controlObj.write_sp(mv_setpoints[0])
#
#     except (IndexError, OSError) as e:
#         print(e)
#         # probably wrote past the last mv setpoint, so just go back to first setpoint....
#         # this is also a safety in case theres a brief communication error
#         try:
#             time.sleep(0.01)
#             controlObj.close_me()
#             controlObj.open_me()
#             if iter_freq < len(mv_setpoints):
#                 controlObj.write_sp(mv_setpoints[iter_freq])
#                 iter_freq += 1
#             else:
#                 controlObj.write_sp(mv_setpoints[0])
#         except (ValueError, OSError) as e:
#             print(e)
#             try:
#                 time.sleep(0.01)
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 if iter_freq < len(mv_setpoints):
#                     controlObj.write_sp(mv_setpoints[iter_freq])
#                     iter_freq += 1
#                 else:
#                     controlObj.write_sp(mv_setpoints[0])
#             finally:
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 controlObj.write_sp(mv_setpoints[0])
#                 print('give up')
#     except (ValueError, OSError) as e:
#         print(e)
#         try:
#             time.sleep(0.01)
#             controlObj.close_me()
#             controlObj.open_me()
#             if iter_freq < len(mv_setpoints):
#                 controlObj.write_sp(mv_setpoints[iter_freq])
#             else:
#                 controlObj.write_sp(mv_setpoints[0])
#         except (ValueError, OSError) as e:
#             print(e)
#             try:
#                 time.sleep(0.01)
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 if iter_freq < len(mv_setpoints):
#                     controlObj.write_sp(mv_setpoints[iter_freq])
#                 else:
#                     controlObj.write_sp(mv_setpoints[0])
#             finally:
#                 controlObj.close_me()
#                 controlObj.open_me()
#                 controlObj.write_sp(mv_setpoints[0])
#                 print('give up')
#
#         num_freq+=1
#     # update the plots after going through all the masses

alpha_iter = 1
while iter_freq < len(mv_setpoints):
    # append current time to the array.
    time_array = np.append(time_array, time.time())
    # Read time and temperature data
    cum_time = np.cumsum(np.concatenate(([0], np.diff(time_array))))

    t = Thread(target=thread_read_masses, args=(list_of_masses, list_of_sensitivities, mass_signals))
    t.start()
    start_alpha = time.time()
    iter_freq = thread_send_mV_setpoint(iter_freq, mv_setpoints, sendFreq,alpha, t)

    # Write new setpoint for temperature
    try:
        # controlObj.write_sp(mv_setpoints[iter_freq])
        if iter_freq <= len(temp_setpoints) and iter_freq != 0:
            # temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[multiple*i])
            temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[iter_freq])
        else:
            temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[0])
    except IndexError as e:
        print(e)
        controlObj.write_sp(mv_setpoints[0])
    # T_set_curve.setData(x=cum_time,y=temp_setpoints[:2*i+1:2], pen='r',name='setpoint')
    # T_set_curve.setData(x=cum_time, y=temp_plot_arr[:2*len(cum_time):2], pen='r', name='setpoint')

    try:
        T_set_curve.setData(x=cum_time[:len(temp_plot_arr)], y=temp_plot_arr, pen='r', name='setpoint')
    except:
        T_set_curve.setData(x=cum_time, y=temp_plot_arr[:len(cum_time)], pen='r', name='setpoint')

    T_array = np.append(T_array, read_Temp_value())
    T_read_curve.setData(x=cum_time, y=T_array, pen='b', name='readout')

    # if alpha_iter % int(2 / sendFreq) == 0:
    if alpha_iter % 2 == 0:
        # do stuff, adjust alpha
        end_alpha = time.time() - start_alpha
        eval_alpha = alpha * (T_array[-1] - T_array[-2]) / (end_alpha * heating_rate)
        if eval_alpha > 0.7:
            alpha = eval_alpha
        print('alpha: ' + str(alpha))
    alpha_iter += 1

    for mass, mass_plot in zip(list_of_masses, curves):
        mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g')

    # T_set_curve.setData(x=cum_time,y=temp_plot_arr[:len(cum_time)], pen='r',name='setpoint')
    pg.QtGui.QApplication.processEvents()

    # uncomment if you want to see some cooldown
    if iter_freq == len(mv_setpoints):
        break
# include changing setpoints in stuff above

# at the very end, go back to initial mV setpoint
controlObj.write_sp(mv_setpoints[0] - interpd(controlObj2.read_rt()+273.15))

"""
read current value and add to plot, also include setpoint curve here too
"""
# T_array = np.append(T_array, read_Temp_value())
# T_read_curve.setData(x=cum_time, y=T_array)
pg.QtGui.QApplication.processEvents()

controlObj.close_me()
controlObj2.close_me()

os.chdir(project_folder)

time_Temp_arr = np.vstack((cum_time, T_array))
combined_data = pd.concat([pd.DataFrame(time_Temp_arr).T, pd.DataFrame.from_dict(mass_signals)], axis=1)
combined_data.rename(columns={0:'Time(s)', 1:'Temp(K)'}, inplace=True)

# save experiment
combined_data.to_csv(experiment_name, index=False, sep='\t')

print('hi')

if __name__ == '__main__':
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        app.exec_()  # Start QApplication event loop ***

# from initial_UTI import * 1. start reading the masses cycle through 1-2 times (check) 2. take the average time to cycle = total time to write setpoints (check) 3. start the 'official' program 4. read temperature, and masses and write while reading the masses a. assume that the time to read the temperature = 0  do read mass 2 times: get the cycle time   for asdfa: do read mass and write sp(cycle time) use threads thread1.join() thread2.join() do read value ######################################################################################################################## # alpha_iter = 0 # start_alpha = time.time() # currentTime = time.time() # Write new setpoint for temperature # adjust send freq # TODO might insert the sleep here # probably wrote past the last mv setpoint, so just go back to first setpoint.... # this is also a safety in case theres a brief communication error # if alpha_iter%int(2/sendFreq) == 0: #     # do stuff, adjust alpha #     end_alpha = time.time() - start_alpha #     alpha = alpha * (end_T - start_T) / (end_alpha * heatingRate) # # # alpha_iter+=1 # for controlling the frequency that data is sent # if time.time()-start_time < data_freq: #     time.sleep(data_freq - (time.time()-start_time)) # if iter_freq_ == len(mv_setpoints_)-1: #     return iter_freq_, mv_setpoints_[-1] # else: #     return iter_freq_, mv_setpoints_[iter_freq_] # mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g') # stop increasing the temp and send a safe setpoint # return [signal, mass, sensitivity] ######################################################################################################################## Create UTI instance Create Eurotherm instances ######################################################################################################################## User-Defined Parameters: # TODO vary masses and see how that affects response # K/s ######################################################################################################################## Check time to loop through masses: This should be the time taken each loop to write setpoints # Initial UTI looping # mean_single, mean_set = loop__time(number_of_masses, list_of_masses, list_of_sensitivities) Determine setpoint increment # multiple = 2 # how many times per second to change the setpoint # temp_set_incr = heating_rate * mean_set/multiple     # setpoint increment assuming each loop takes "mean_set" seconds # rate_adjust = 1.9 # temp_set_incr = heating_rate * data_freq * rate_adjust    # setpoint increment assuming each loop takes "mean_set" seconds # setpoint increment assuming each loop takes "mean_set" seconds # temp_set_incr = heating_rate * sendFreq*1.75   # setpoint increment assuming each loop takes "mean_set" seconds # making the list of setpoint values to be sent at each loop iteration # These are the mV that will be sent to the Eurotherm Set up multiple plot windows for TPD Main script loops for TPD Basic structure of measurement loop: for asdfa: do read mass and write sp(cycle time) use threads thread1.join() thread2.join() do read value # Make mass spec signals a dictionary of np.arrays so we can append to and manipulate each individually # initialize dictionary of empty arrays This will need to be threaded, below # num_freq = 1 # this needs to be the max temperature or allowed to cut short if needed, also allow for the threading # TODO increase frequency that setpoints are sent, maybe this fixes the tracking issue at higher temperatures. # for i in range(50): # for i, v, in enumerate(mv_setpoints): #     # for i in range(len(temp_setpoints)): #     #     line below may be useful at times for debugging #     currentTime = time.time() #     # append current time to the array. #     time_array = np.append(time_array, time.time()) #     # Read time and temperature data #     cum_time = np.cumsum(np.concatenate(([0], np.diff(time_array)))) #     T_array = np.append(T_array, read_Temp_value()) #     T_read_curve.setData(x=cum_time, y=T_array, pen='b', name='readout') #     # Write new setpoint for temperature #     try: #         # controlObj.write_sp(mv_setpoints[iter_freq]) #         if iter_freq <= len(temp_setpoints) and iter_freq != 0: #             # temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[multiple*i]) #             temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[i]) #         else: #             temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[0]) #     except IndexError as e: #         print(e) #         controlObj.write_sp(mv_setpoints[0]) #     # T_set_curve.setData(x=cum_time,y=temp_setpoints[:2*i+1:2], pen='r',name='setpoint') #     # T_set_curve.setData(x=cum_time, y=temp_plot_arr[:2*len(cum_time):2], pen='r', name='setpoint') #     T_set_curve.setData(x=cum_time, y=temp_plot_arr, pen='r', name='setpoint') # #     # for j in range(number_of_masses): # #     for mass, sens, mass_plot in zip(list_of_masses, list_of_sensitivities, curves): #         # np.append(mass_signals["mass{0}".format(list_of_masses[j])], uti1.read_mass(list_of_masses[j],list_of_sensitivities[j])) #         mass_signals['mass{0}'.format(mass)] = np.append(mass_signals['mass{0}'.format(mass)], uti1.read_mass(mass, sens)) #         mass_plot.setData(x=T_array, y=mass_signals['mass{0}'.format(mass)], pen='g') #         # if num_freq%2 == 0: #     try: #         if iter_freq < len(mv_setpoints): #             controlObj.write_sp(mv_setpoints[iter_freq]) #             iter_freq+=1 #         else: #             controlObj.write_sp(mv_setpoints[0]) # #     except (IndexError, OSError) as e: #         print(e) #         # probably wrote past the last mv setpoint, so just go back to first setpoint.... #         # this is also a safety in case theres a brief communication error #         try: #             time.sleep(0.01) #             controlObj.close_me() #             controlObj.open_me() #             if iter_freq < len(mv_setpoints): #                 controlObj.write_sp(mv_setpoints[iter_freq]) #                 iter_freq += 1 #             else: #                 controlObj.write_sp(mv_setpoints[0]) #         except (ValueError, OSError) as e: #             print(e) #             try: #                 time.sleep(0.01) #                 controlObj.close_me() #                 controlObj.open_me() #                 if iter_freq < len(mv_setpoints): #                     controlObj.write_sp(mv_setpoints[iter_freq]) #                     iter_freq += 1 #                 else: #                     controlObj.write_sp(mv_setpoints[0]) #             finally: #                 controlObj.close_me() #                 controlObj.open_me() #                 controlObj.write_sp(mv_setpoints[0]) #                 print('give up') #     except (ValueError, OSError) as e: #         print(e) #         try: #             time.sleep(0.01) #             controlObj.close_me() #             controlObj.open_me() #             if iter_freq < len(mv_setpoints): #                 controlObj.write_sp(mv_setpoints[iter_freq]) #             else: #                 controlObj.write_sp(mv_setpoints[0]) #         except (ValueError, OSError) as e: #             print(e) #             try: #                 time.sleep(0.01) #                 controlObj.close_me() #                 controlObj.open_me() #                 if iter_freq < len(mv_setpoints): #                     controlObj.write_sp(mv_setpoints[iter_freq]) #                 else: #                     controlObj.write_sp(mv_setpoints[0]) #             finally: #                 controlObj.close_me() #                 controlObj.open_me() #                 controlObj.write_sp(mv_setpoints[0]) #                 print('give up') # #         num_freq+=1 #     # update the plots after going through all the masses # append current time to the array. # Read time and temperature data # Write new setpoint for temperature # controlObj.write_sp(mv_setpoints[iter_freq]) # temp_plot_arr = np.append(temp_plot_arr, temp_setpoints[multiple*i]) # T_set_curve.setData(x=cum_time,y=temp_setpoints[:2*i+1:2], pen='r',name='setpoint') # T_set_curve.setData(x=cum_time, y=temp_plot_arr[:2*len(cum_time):2], pen='r', name='setpoint') # if alpha_iter % int(2 / sendFreq) == 0: # do stuff, adjust alpha # T_set_curve.setData(x=cum_time,y=temp_plot_arr[:len(cum_time)], pen='r',name='setpoint') # uncomment if you want to see some cooldown # include changing setpoints in stuff above # at the very end, go back to initial mV setpoint read current value and add to plot, also include setpoint curve here too # T_array = np.append(T_array, read_Temp_value()) # T_read_curve.setData(x=cum_time, y=T_array) # save experiment # Start QApplication event loop ***