DTObs.py 7.7 KB
Newer Older
1
2
#!/usr/bin/env python3

marc's avatar
marc committed
3
4
5
import sys
import csv
import logging
marc's avatar
marc committed
6
7
8
9
import subprocess
import traceback
import time
import numpy as np
marc's avatar
marc committed
10
11

from PyQt5 import QtGui
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
12
from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, pyqtSlot, QThreadPool
marc's avatar
marc committed
13
14
15
from PyQt5.QtWidgets import (QFileDialog, QApplication, QMainWindow, QTableWidgetItem)
from ui.dtobswindow import Ui_mainWindow

marc's avatar
marc committed
16
from telescope import telescope
marc's avatar
marc committed
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from astropy import units as u
from astropy.coordinates import SkyCoord

class WorkerSignals(QObject):
    """
    Defines the signals available from a running worker thread.

    Supported signals are:

    finished
        `int` of the setpoint number

    error
        `tuple` (exctype, value, traceback.format_exc() )

    result
        `object` data returned from processing, anything

    progress
        `int` inicating % progress
    """

39
40
41
42
    finished = pyqtSignal(int, str)
    allfinished = pyqtSignal()
    # error = pyqtSignal(tuple)
    # result = pyqtSignal(object)
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
43
    progress = pyqtSignal(int, int, str) # meas_num, percent_complete, remaining
marc's avatar
marc committed
44
45
46
47
48
49
50
51
52
53
54
55
56

class Worker(QRunnable):
    """ Execute a function asynchronously, connect to signals """

    def __init__(self, function_to_run, *args, **kwargs):
        super(Worker, self).__init__()
        # Store arguments
        self.function_to_run = function_to_run
        self.args = args
        self.kwargs = kwargs
        self.signals = WorkerSignals()

        self.kwargs['oneSetpointCompleteSignal'] = self.signals.finished
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
57
        self.kwargs['progressSignal'] = self.signals.progress
marc's avatar
marc committed
58
59
60
61
62

    @pyqtSlot()
    def run(self):
        """ Initialize the runner function with passed args, kwargs """

63
64
        self.function_to_run(*self.args, **self.kwargs)
        self.signals.allfinished.emit()
marc's avatar
marc committed
65
66
67
68
69
70
71
72

class DTObservationProgram(Ui_mainWindow):
    def __init__(self, mainWindow):
        self.radec = None

        Ui_mainWindow.__init__(self)
        self.setupUi(mainWindow)
        self.actionOpen.triggered.connect(self.openFileNameDialog)
marc's avatar
marc committed
73
74
        self.actionClose.triggered.connect(self.closeMeasurement)
        self.actionQuit.triggered.connect(self.quitDTObs)
marc's avatar
marc committed
75
76
77
        self.pushButtonStartMeasurement.clicked.connect(self.startMeasurement)
        self.pushButtonStopMeasurement.clicked.connect(self.stopMeasurement)

78
        #self.myDT = telescope(setmode='J2000', consoleHost='consoledemo.dmz.camras.nl')
marc's avatar
marc committed
79
80
81
82
83
84
85
86
87
88
89

        self.threadpool = QThreadPool()

    def openFileNameDialog(self):
        '''
        Clear tableWidget and read pointings from file
        '''
        fileName,_ = QFileDialog.getOpenFileName(None, 'Open File', '/home/marc/git/CAMRASTools/DTObs')
        if fileName:
            reader = csv.reader(open(fileName),delimiter='\t')
            rowPosition = self.tableWidgetPointings.rowCount()
90

marc's avatar
marc committed
91
92
93
94
95
96
97
            for meas, ra, dec in reader:
                self.radec = SkyCoord(float(ra)*u.degree, float(dec)*u.degree, frame='icrs')
                (raStr, decStr)  = self.radec.to_string('hmsdms').split()

                self.tableWidgetPointings.insertRow(rowPosition)
                self.tableWidgetPointings.setItem(rowPosition, 0, QTableWidgetItem(raStr))
                self.tableWidgetPointings.setItem(rowPosition, 1, QTableWidgetItem(decStr))
98
99
100
                self.tableWidgetPointings.setItem(rowPosition, 2, QTableWidgetItem(""))

                rowPosition += 1
marc's avatar
marc committed
101
102
103

        self.tableWidgetPointings.resizeColumnsToContents()

marc's avatar
marc committed
104
105
106
107
108
109
110
    def closeMeasurement(self):
        for rowPosition in range(self.tableWidgetPointings.rowCount(),-1,-1):
            self.tableWidgetPointings.removeRow(rowPosition)

    def quitDTObs(self):
        sys.exit(app.exec_())

111
112
113
114
115
    def allCompleted(self):
        """ Callback function when all pointings completed """
        print("All pointings completed")

    def measCompleted(self, meas_num, status):
marc's avatar
marc committed
116
        """ Make the meas_num-th row of the table green """
117
118
119
        colors = {'Completed': QtGui.QColor('green'),
                  'Slewing'  : QtGui.QColor('yellow'),
                  'Measuring': QtGui.QColor('cyan')}
120
121

        self.tableWidgetPointings.item(meas_num, 2).setText(status)
marc's avatar
marc committed
122
        for column in range(3):
123
            self.tableWidgetPointings.item(meas_num,column).setBackground(colors[status])
marc's avatar
marc committed
124
125
        self.tableWidgetPointings.resizeColumnsToContents()

Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
126
    def goToSetpoints(self, setpoints, oneSetpointCompleteSignal=None, progressSignal=None):
marc's avatar
marc committed
127
128
129
        """ Send a list of setpoints to the telescope """
        for setpoint_nr, setpoint in enumerate(setpoints):
            self.myDT.setRaDec(setpoint)
130
            oneSetpointCompleteSignal.emit(setpoint_nr, 'Slewing')
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
131
132
133
134
135
136
137
138
139
140
141
            time.sleep(3)
            dist = np.sqrt(self.myDT.dist_el**2+self.myDT.dist_az**2)
            firstDist = dist
            while not dist < 0.01*u.deg:
                percentSlew = max(100 - dist/firstDist*100, 0)
                progressSignal.emit(setpoint_nr, percentSlew, "{:.3f}°".format(dist.value))
                #print("{:.3f}".format(dist))
                #print("{:2.0f}".format(percentSlew.value))
                self.myDT.getDistance(waitForUpdate=True)
                dist = np.sqrt(self.myDT.dist_el**2+self.myDT.dist_az**2)

142
            oneSetpointCompleteSignal.emit(setpoint_nr, 'Measuring')
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
143
            self.doMeasurement(setpoint_nr, progressSignal=progressSignal)
144
            oneSetpointCompleteSignal.emit(setpoint_nr, 'Completed')
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
145
146
147
148
149
150
151
152
153

    def updateProgress(self, meas_num, progress_percent, remaining_str):
        """
        Update the table with some progress indicator

        meas_num: the row which needs to be updated
        progress_percent: integer giving the percentage complete
        remaining_str: string indicating how much remaining, e.g. "1:30" or "3°"
        """
154
155
        #self.tableWidgetPointings.item(meas_num, 2).setText(remaining_str)
        self.tableWidgetPointings.item(meas_num, 2).setText(str(progress_percent)+"%")
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
156
157
158


    def doMeasurement(self, measnum, progressSignal=None):
159
        """ Dumping data into file including meta-data"""
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
160
        integrationTime = self.spinBoxIntTime.value()
161
162
        measProgramme = self.comboBoxProgramma.currentText()
        measFile = open(str(measnum),'w')
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
163
        #self.measprog = subprocess.Popen(["cat","/home_local/camrasdemo/test-001.txt"], stdout=subprocess.PIPE)
164
        self.measprog = subprocess.Popen([str(measProgramme), str(integrationTime)], stdout=subprocess.PIPE)
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
165
166
167
168
169
170
171
        for sec in range(integrationTime):
            remainstring =  str(int((integrationTime-sec)/60)) + ":"
            remainstring += "{:02}".format((integrationTime-sec)%60)
            progressSignal.emit(measnum, int(float(sec)/integrationTime*100), remainstring)
            time.sleep(1)
        self.measprog.wait()
        data = self.measprog.stdout
172
173
        for line in data:
            measFile.write(str(line))
marc's avatar
marc committed
174
175
176
177
178

    def startMeasurement(self):
        print("Measurement started")
        setpoints = []
        for meas in range(0,self.tableWidgetPointings.rowCount()):
179
            ra  = self.tableWidgetPointings.item(meas, 0).text()
marc's avatar
marc committed
180
181
            dec = self.tableWidgetPointings.item(meas, 1).text()

182
            self.tableWidgetPointings.item(meas, 2).setText("Scheduled")
marc's avatar
marc committed
183
184
185
186
187
188
            self.tableWidgetPointings.resizeColumnsToContents()
            setpoint = SkyCoord(ra, dec, frame='icrs')
            setpoints.append(setpoint)

        worker = Worker(self.goToSetpoints, setpoints)
        worker.signals.finished.connect(self.measCompleted)
189
        worker.signals.allfinished.connect(self.allCompleted)
Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
190
        worker.signals.progress.connect(self.updateProgress)
marc's avatar
marc committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
        self.threadpool.start(worker)

    def stopMeasurement(self):
        print("Measurement stopped")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = QMainWindow()

    prog = DTObservationProgram(mainWindow)

    mainWindow.show()
    sys.exit(app.exec_())

Tammo Jan Dijkema's avatar
Tammo Jan Dijkema committed
205