source: ETALON/CLIO/control/CLIO_graphical_interface.py @ 744

Last change on this file since 744 was 744, checked in by delerue, 7 years ago

CLIO control system updated

File size: 19.9 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3Created on Fri Feb 10 08:32:18 2017
4
5@author: delerue
6"""
7
8__author__ = 'delerue'
9
10from ttk import Frame, Label, Scale, Style
11from Tkinter import *
12from PIL import ImageTk, Image
13import time
14import glob
15import os
16import subprocess
17import urllib2
18
19#from motor_function import *
20
21global basedir
22global FILE_STOP
23global FILE_PAUSE
24global data_directory
25global code_directory
26
27from clio_constants import *
28
29INSERTED_VALUE1=5500000
30INSERTED_VALUE2=5000000
31
32threshold_recent=   20
33threshold_old=      100
34
35ImagesDisplaySize=(400,300)
36N_IMAGES_LINES=2
37N_IMAGES_COLS=3
38N_IMAGES=N_IMAGES_LINES*N_IMAGES_COLS
39
40PROCESSES_REFRESH_INTERVAL=10
41
42imageNames=[]
43for iimage in range(N_IMAGES):
44    imageNames.append(code_directory+"no_data.png")
45   
46URI='http://'+IP_POWER_IP+'/Set.cmd'
47auth_handler=urllib2.HTTPBasicAuthHandler()
48auth_handler.add_password(realm='IP9258',uri=URI,user='admin',passwd='12345678')
49opener= urllib2.build_opener(auth_handler)
50urllib2.install_opener(opener)
51
52#This is used for variables that are not updated on each refresh cycle
53
54class MainWindow(Frame):
55
56    def __init__(self, parent):
57        Frame.__init__(self, parent)
58
59
60        self.parent = parent
61        self.parent.bind("q",self.onExitKey)
62        self.initUI()
63
64
65    def initUI(self):
66
67    #----------------       
68        self.terminate=0
69        self.refresh_loop=0
70        # canvas for image
71        self.canvas = Canvas(self.parent, width=800, height=800)
72        self.frameImages = Frame(self.parent, borderwidth=10)
73        self.frameImages.grid(row=1, column=0)
74        self.my_images=[]
75        self.imageLabel=[]
76        self.newImage=[]       
77        for iline in range(N_IMAGES_LINES):
78            for icol in range(N_IMAGES_COLS):
79                iimage=iline*N_IMAGES_COLS+icol
80                self.my_images.append(ImageTk.PhotoImage(Image.open(imageNames[iimage]).resize(ImagesDisplaySize, Image.ANTIALIAS)))
81                self.imageLabel.append(Label(self.frameImages,image=self.my_images[iimage]))
82                self.imageLabel[iimage].grid(row=iline,column=icol)
83
84        #Control buttons
85        self.frameAllControls = Frame(self.parent, borderwidth=10)
86        self.frameAllControls.grid(row=0, column=0) 
87
88        #data status
89        self.frameStatus = Frame(self.frameAllControls, borderwidth=10, relief=SUNKEN)
90        self.frameStatus.pack(side=LEFT)
91        self.clock = Label(self.frameStatus, font=('times', 18, 'bold'), bg='blue')
92        self.clock.pack(side=TOP)
93        self.latestFileAcquired = Label(self.frameStatus, font=('times', 14, 'bold'), bg='blue')
94        self.latestFileAcquired.pack(side=TOP)
95        self.latestFileProcessed = Label(self.frameStatus, font=('times', 14, 'bold'), bg='blue')
96        self.latestFileProcessed.pack(side=TOP)
97        self.latestFileWithSignal = Label(self.frameStatus, font=('times', 14, 'bold'), bg='blue')
98        self.latestFileWithSignal.pack(side=TOP)
99
100        #data acquisition
101        self.frameAcquisition = Frame(self.frameAllControls, borderwidth=10, relief=SUNKEN)
102        self.frameAcquisition.pack(side=LEFT)
103        labelAcquisition=Label(self.frameAcquisition,text='Data Acquisition')
104        labelAcquisition.grid(row=0,column=0,columnspan=2)
105        self.buttonAcqPause = Button(self.frameAcquisition, text="Pause acquisition", command=self.onButtonAcqPause)
106        self.buttonAcqPause.grid(row=1,column=0)
107        self.buttonAcqStop = Button(self.frameAcquisition, text="Stop acquisition", command=self.onButtonAcqStop)
108        self.buttonAcqStop.grid(row=2,column=0)
109        self.labelAcquisitionStatus=Label(self.frameAcquisition,text='Status: unkown', bg='magenta')
110        self.labelAcquisitionStatus.grid(row=3,column=0)
111        self.labelAcquisitionRate=Label(self.frameAcquisition,text='Rate: unkown', bg='magenta')
112        self.labelAcquisitionRate.grid(row=4,column=0)
113        self.labelAcquisitionPause=Label(self.frameAcquisition,text='Pause: unkown', bg='magenta')
114        self.labelAcquisitionPause.grid(row=5,column=0)
115     
116        #Power status
117        self.framePower = Frame(self.frameAllControls, borderwidth=10, relief=SUNKEN)
118        self.framePower.pack(side=LEFT)
119        labelPower=Label(self.framePower,text='IP Power')
120        labelPower.grid(row=0,column=0,columnspan=2)
121        self.buttonPower=[ Button(self.framePower, text=str(ipower), command= lambda v=ipower: self.onButtonPower(v)) for ipower in range(4) ]
122        for ipower in range(4):
123            self.buttonPower[ipower].grid(row=ipower+1,column=0)
124            #self.buttonPower[ipower].pack(side=BOTTOM)
125        self.buttonPower[0].config(text="Camera")
126        self.buttonPower[1].config(text="Blinker")
127        self.buttonPower[2].config(text="Amplifier")
128        self.buttonPower[3].config(text="Wago+Pot")
129                   
130        #Motor function
131        self.frameMotors = Frame(self.frameAllControls, borderwidth=10, relief=SUNKEN)
132        self.frameMotors.pack(side=LEFT)
133        labelMotors=Label(self.frameMotors,text='Motors Control')
134        labelMotors.grid(row=0,column=0,columnspan=4)
135        buttonRetractFull = Button(self.frameMotors, text="Retract completely", command=self.onButtonRetract)
136        buttonRetractFull.grid(row=1,column=0)
137        buttonInsert1 = Button(self.frameMotors, text="Insert to "+str(INSERTED_VALUE1), command=self.onButtonInsert1)
138        buttonInsert1.grid(row=2,column=0)
139        buttonBackward20k = Button(self.frameMotors, text="Backward 20k", command=self.onButtonBkd20k)
140        buttonBackward20k.grid(row=1,column=1)
141        buttonBackward100k = Button(self.frameMotors, text="Backward 100k", command=self.onButtonBkd100k)
142        buttonBackward100k.grid(row=1,column=2)
143        buttonBackward1m = Button(self.frameMotors, text="Backward 1M", command=self.onButtonBkd1m)
144        buttonBackward1m.grid(row=1,column=3)
145        buttonForward20k = Button(self.frameMotors, text="Forward 20k", command=self.onButtonFwd20k)
146        buttonForward20k.grid(row=2,column=1)
147        buttonForward100k = Button(self.frameMotors, text="Forward 100k", command=self.onButtonFwd100k)
148        buttonForward100k.grid(row=2,column=2)
149        buttonForward1m = Button(self.frameMotors, text="Forward 1M", command=self.onButtonFwd1m)
150        buttonForward1m.grid(row=2,column=3)
151        self.labelPositionStepTitle=Label(self.frameMotors,text='Position (steps):', bg='grey')
152        self.labelPositionStepTitle.grid(row=3,column=0,columnspan=1)
153        self.labelPositionStep=Label(self.frameMotors,text='Status: unkown', bg='blue')
154        self.labelPositionStep.grid(row=3,column=1,columnspan=1)
155     
156        self.labelPositionCurrentTitle=Label(self.frameMotors,text=' (current):', bg='grey')
157        self.labelPositionCurrentTitle.grid(row=3,column=2,columnspan=1)
158        self.labelPositionCurrent=Label(self.frameMotors,text='Status: unkown', bg='blue')
159        self.labelPositionCurrent.grid(row=3,column=3,columnspan=1)
160
161       
162        #Check process status
163        self.frameProcesses = Frame(self.frameAllControls, borderwidth=10, relief=SUNKEN)
164        self.frameProcesses.pack(side=LEFT)
165        self.labelProcessIPPower=Label(self.frameProcesses,text='IP Power', bg='blue')
166        self.labelProcessIPPower.grid(row=0,column=0,columnspan=1)
167        self.labelProcessWago=Label(self.frameProcesses,text='WAGO', bg='blue')
168        self.labelProcessWago.grid(row=1,column=0,columnspan=1)
169        self.labelProcessMotorMonitor=Label(self.frameProcesses,text='Motor monitor', bg='blue')
170        self.labelProcessMotorMonitor.grid(row=2,column=0,columnspan=1)
171        self.labelProcessSaveData=Label(self.frameProcesses,text='Savedata', bg='blue')
172        self.labelProcessSaveData.grid(row=3,column=0,columnspan=1)
173        self.labelProcessProcessRecent=Label(self.frameProcesses,text='Process recent', bg='blue')
174        self.labelProcessProcessRecent.grid(row=4,column=0,columnspan=1)
175       
176        #Exit
177        self.buttonExit = Button(self.frameAllControls, text="Exit", command=self.onExit)
178        self.buttonExit.pack(side=LEFT)
179
180        self.update_clock()
181        self.motorUpdateErrors=0;
182        self.getMotorPosition()
183
184
185    def update_clock(self):
186        self.refresh_loop=self.refresh_loop+1
187        now = time.strftime("%d/%m/%Y %H:%M:%S")
188        self.clock.config(text=now,bg='green')
189       
190        list_of_files_acquired = glob.glob(data_directory+"data_CLIO*.txt")
191        #print(list_of_files_acquired)
192        if (len(list_of_files_acquired)>0):
193            latest_file_acquired = max(list_of_files_acquired, key=os.path.getctime)
194            filetime=os.path.getctime(latest_file_acquired)
195            if (time.time()-filetime)<threshold_recent:
196                bgcolortxt='green'
197                fgcolortxt='black'
198            elif (time.time()-filetime)<threshold_old:
199                bgcolortxt='blue'
200                fgcolortxt='white'
201            else:
202                bgcolortxt='red'
203                fgcolortxt='black'
204            self.latestFileAcquired.config(text=os.path.basename(latest_file_acquired),bg=bgcolortxt,fg=fgcolortxt)
205
206        list_of_files_processed = glob.glob(data_directory+"data_CLIO*.png")
207        #print(list_of_files_processed)
208        if (len(list_of_files_processed)>0):
209            #latest_file_processed = max(list_of_files_processed, key=os.path.getctime)
210            latest_file_processed = max(sorted(list_of_files_processed))
211            filetime=os.path.getctime(latest_file_processed)
212            if (time.time()-filetime)<threshold_recent:
213                bgcolortxt='green'
214                fgcolortxt='black'
215            elif (time.time()-filetime)<threshold_old:
216                bgcolortxt='blue'
217                fgcolortxt='white'
218            else:
219                bgcolortxt='red'
220                fgcolortxt='black'
221            self.latestFileProcessed.config(text=os.path.basename(latest_file_processed),bg=bgcolortxt,fg=fgcolortxt)
222            imageNames[0]=latest_file_processed;
223
224
225        list_of_files_with_signal = glob.glob(data_directory+"data_CLIO*.sig")
226        #print(list_of_files_with_signal)
227        if (len(list_of_files_with_signal)>0):
228            #latest_file_with_signal = max(list_of_files_with_signal, key=os.path.getctime)
229            latest_file_with_signal = max(sorted(list_of_files_with_signal))
230            filetime=os.path.getctime(latest_file_with_signal)
231            if (time.time()-filetime)<threshold_recent:
232                bgcolortxt='green'
233                fgcolortxt='black'
234            elif (time.time()-filetime)<threshold_old:
235                bgcolortxt='blue'
236                fgcolortxt='white'
237            else:
238                bgcolortxt='red'
239                fgcolortxt='black'
240            self.latestFileWithSignal.config(text=os.path.basename(latest_file_with_signal),bg=bgcolortxt,fg=fgcolortxt)
241
242            imageNames[0]=latest_file_with_signal.replace(".sig",".png")
243            imageNames[1]=latest_file_with_signal.replace(".sig","_zoom.png")
244            imageNames[2]=latest_file_with_signal.replace(".sig","_signal.png")
245            time.sleep(0.1)
246
247            self.newImage=[]
248            for iimage in range(N_IMAGES):
249                try:
250                    self.newImage.append(ImageTk.PhotoImage(Image.open(imageNames[iimage]).resize(ImagesDisplaySize, Image.ANTIALIAS)))
251                    self.imageLabel[iimage].configure(image=self.newImage[iimage])
252                    self.imageLabel[iimage].image=self.newImage[iimage]
253                except:
254                    print("An error occurred while opening the image: "+imageNames[iimage]+" image "+str(iimage))
255                time.sleep(0.1)
256
257       
258        self.getMotorPosition()
259        #Check acquisition status
260        stop_file = glob.glob(FILE_STOP)
261        pause_file = glob.glob(FILE_PAUSE)
262        if (len(stop_file)):
263            self.labelAcquisitionStatus.config(text="Stop",bg='red',fg='black')
264            self.buttonAcqPause.config(text="Program stopped!")
265        elif (len(pause_file)):
266            self.labelAcquisitionStatus.config(text="Pause", bg='blue',fg='white')
267            self.buttonAcqPause.config(text="Restart")
268        else:
269            self.labelAcquisitionStatus.config(text="Enabled", bg='green',fg='black')
270
271        #check remote processes
272        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==1):
273            response=os.system("ping -c 1 "+motor_controller_IP)
274            if response==0:
275                self.labelProcessWago.config(bg='green')
276            else:
277                self.labelProcessWago.config(bg='red')
278
279        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==2):
280            filetime=0
281            iloop=0
282            while ((filetime==0)or((time.time()-filetime)>threshold_old))and(iloop<5):
283                if (iloop>0):
284                    time.sleep(0.5)
285                iloop=iloop+1
286                try:
287                    filetime=os.path.getctime(motor_position_info)
288                except:
289                    filetime=0
290                   
291            if (time.time()-filetime)<threshold_recent:
292                bgcolortxt='green'
293            elif (time.time()-filetime)<threshold_old:
294                bgcolortxt='cyan'
295            else:
296                bgcolortxt='red'
297            self.labelProcessMotorMonitor.config(bg=bgcolortxt)
298
299        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==3):
300            try:
301                response=subprocess.check_output("ps -edf | grep -v grep | grep -c savedata_CLIO",shell=True)
302            except:
303                response='0' 
304            if (response[0]=='1'):
305                bgcolortxt='green'
306            else:
307                bgcolortxt='red'
308            self.labelProcessSaveData.config(bg=bgcolortxt)
309
310        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==4):
311            try:
312#                response=subprocess.check_output("ps -edf | grep -v grep | grep -c process_recent_files",shell=True)
313                response=subprocess.check_output("ps -edf | grep -v grep | grep -c makefile_recent",shell=True)
314            except:
315                response='0' 
316            if (response[0]=='1'):
317                bgcolortxt='green'
318            else:
319                bgcolortxt='red'
320            self.labelProcessProcessRecent.config(bg=bgcolortxt)
321               
322        self.update_idletasks()
323        if self.terminate==0:
324                self.after(500, self.update_clock)
325
326        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==5):
327            response=os.system("ping -c 1 "+IP_POWER_IP)
328            if response==0:
329                self.labelProcessIPPower.config(bg='green')
330            else:
331                self.labelProcessIPPower.config(bg='red')
332
333        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==6):
334            self.set_power_buttons_color()
335
336        if (self.refresh_loop%PROCESSES_REFRESH_INTERVAL==7):
337            fid=open(FILE_ACQ_INFO,'r')
338            fileline=fid.readline()
339            print fileline
340            key_values={}
341            while len(fileline)>0:
342                print fileline
343                entries=fileline.replace('\n','').split(' ')
344                key_values[entries[0]]=entries[1]
345                fileline=fid.readline()
346            fid.close()
347            if (key_values['RATE']):
348                rate_value=36000./float(key_values['RATE'])
349                self.labelAcquisitionRate.config(text='Rate= '+str(rate_value)+'kS/s',bg='white')
350           
351            if (key_values['PAUSE']):
352                self.labelAcquisitionPause.config(text='Wait= '+key_values['PAUSE']+' ms',bg='white')
353           
354    def getMotorPosition(self):
355        if (len(glob.glob(motor_position_info))>0):
356            fid=open(motor_position_info,'r')
357            fileline=fid.readline()
358            key_values={}
359            while len(fileline)>0:
360                print fileline
361                entries=fileline.replace('#','').replace(' ','').replace('\n','').split('=')
362                key_values[entries[0]]=entries[1]
363                fileline=fid.readline()
364            fid.close()
365            if key_values['motor_value']:
366                self.labelPositionStep.config(text=key_values['motor_value']);
367                self.labelPositionStep.config(bg='green',fg='black');
368            else:
369                self.labelPositionStep.config(bg='red',fg='black');
370
371            if key_values['current_value']:
372                self.labelPositionCurrent.config(text=key_values['current_value']);
373                self.labelPositionCurrent.config(bg='green',fg='black');
374            else:
375                self.labelPositionCurrent.config(bg='red',fg='black');
376        else:
377            self.labelPositionCurrent.config(bg='blue',fg='white');
378            self.labelPositionStep.config(bg='blue',fg='white');
379
380    def set_power_buttons_color(self):
381        power_request=urllib2.urlopen(URI+'?CMD=GetPower')
382        values=power_request.read().replace('<html>','').replace('</html>\r\n','').replace('p6','').split(',')
383        #            print repr(values)
384        for ipower in range(4):
385            print values[ipower].split('=')[1]
386            if (values[ipower].split('=')[1]=='1'):
387                self.buttonPower[ipower].config(bg='green')
388            else:
389                self.buttonPower[ipower].config(bg='cyan')       
390               
391    #----------------
392    def onButtonRetract(self):
393        print "Move motor Retract"       
394        fid=open(motor_position_request,'w')
395        fid.write("abs0;\n")
396        self.labelPositionCurrent.config(bg='cyan');
397        self.labelPositionStep.config(bg='cyan');
398        fid.close()
399
400    def onButtonInsert1(self):
401        print "Move motor Insert "+str(INSERTED_VALUE1)       
402        fid=open(motor_position_request,'w')
403        fid.write("abs"+str(INSERTED_VALUE1)+";\n")
404        fid.close()
405        self.labelPositionCurrent.config(bg='cyan');
406        self.labelPositionStep.config(bg='cyan');
407
408    def moveMotor(self,direction,step):
409        if ((direction!=0)and(step>0)):
410            fid=open(motor_position_request,'w')
411            fid.write("rel"+str(direction*step)+";\n")
412            fid.close()
413        self.labelPositionCurrent.config(bg='cyan');
414        self.labelPositionStep.config(bg='cyan');
415   
416    #----------------
417    def onButtonBkd20k(self):
418        self.moveMotor(-1,20000)
419
420        #----------------
421    def onButtonBkd100k(self):
422        self.moveMotor(-1,100000)
423
424    #----------------
425    def onButtonBkd1m(self):
426        self.moveMotor(-1,1000000)
427
428    #----------------
429    def onButtonFwd20k(self):
430        self.moveMotor(1,20000)
431
432    #----------------
433    def onButtonFwd100k(self):
434        self.moveMotor(1,100000)
435
436    #----------------
437    def onButtonFwd1m(self):
438        self.moveMotor(1,1000000)
439
440    def onButtonPower(self,value):
441        print('Power value='+str(value))
442        print(repr(self.buttonPower[value].cget("bg")))
443        power_state=0
444        if (self.buttonPower[value].cget("bg")=='green'):
445            power_state=1
446        self.buttonPower[value].config(bg='blue')
447        power_request=urllib2.urlopen(URI+'?CMD=SetPower+P6'+str(value+1)+'='+str(1-power_state))
448        values=power_request.read().replace('<html>','').replace('</html>\r\n','').replace('p6','').split(',')
449        self.after(2000, self.set_power_buttons_color)
450
451    #----------------
452    def onButtonAcqPause(self):
453        pause_file = glob.glob(FILE_PAUSE)
454        if (len(pause_file)==0):
455            filename=FILE_PAUSE
456            fid=open(filename,'w')
457            fid.write("pause")
458            fid.close()
459        else:
460            os.remove(FILE_PAUSE)
461            self.buttonAcqPause.config(text="Pause")
462
463    #----------------
464    def onButtonAcqStop(self):
465        filename=FILE_STOP
466        fid=open(filename,'w')
467        fid.write("stop")
468        fid.close()
469       
470    #----------------
471#    def onButton(self):
472
473        # next image
474#        self.my_image_number += 1
475
476        # return to first image
477#        self.my_image_number = 0
478
479    def onExitKey(self,event):
480        print "Exit key"
481        self.onExit()
482
483    def onExit(self):
484        print "Exit"
485        self.terminate=1
486        time.sleep(0.2)
487        self.quit()
488        self.master.destroy()
489
490
491#----------------------------------------------------------------------
492
493root = Tk()
494MainWindow(root)
495
496root.mainloop()
Note: See TracBrowser for help on using the repository browser.