def __init__(self, pv, moving_pv=None, moving_val=0, precision=5, convert=None, *args, **kwargs): super(EpicsValueLabel, self).__init__(*args, **kwargs) # Value conversion function self.convert = convert self.precision = precision self.setMinimumSize(qt.QSize(130, 30)) self.setMaximumSize(qt.QSize(130, 30)) self.setFrameShape(qt.QFrame.Panel) self.setFrameShadow(qt.QFrame.Sunken) self.setAlignment(qt.Qt.AlignCenter) self.setText("not connected") self.formatStr = "{:." + str(self.precision) + "f}" self.moving_val = moving_val self.pv = epics.PV(pv, auto_monitor=True) self.pv.add_callback(self.update_value) if moving_pv is not None: self.moving_pv = epics.PV(moving_pv, auto_monitor=True) self.moving_pv.add_callback(self.update_color) # Set initial value from pv if self.pv.connected: _submit(self.setText, str(round(self.pv.get(), self.precision)))
def update_value(self, *args, **kwargs): value = kwargs['value'] if self.convert: value = self.convert(value) _submit(self.setText, self.formatStr.format(value))
def fly_scan(E0, mono_speed, device_dict, parent): # Initial settings flyer = device_dict['energyFlyer'] parent.subscribe_callback() parent.toLog("A new fly scan is started!", color='blue') # Set to fly scan speed yield from bps.abs_set(flyer.fly_motor_speed, mono_speed) # Do fly scan yield from bpp.monitor_during_wrapper(bp.fly([flyer]), [ device_dict['ENC_fly_counter'], device_dict['I0_fly_counter'], device_dict['It_fly_counter'], device_dict['If_fly_counter'], device_dict['Ir_fly_counter'] ]) # Set to normal speed yield from bps.abs_set(flyer.fly_motor_speed, parent._orig_mono_speed) # Move to E0 yield from stop_and_mv(dcm, E0) parent.unsubscribe_callback() # Decrease remaining scan-number num_scan = int(parent.control.number_of_scan_edit.value()) if num_scan > 1: _submit(parent.control.number_of_scan_edit.setValue, num_scan - 1) cooling_time = parent.control.flyControl.flyCoolTime.value() parent.toLog( "Cooling dcm. The next scan starts after {} seconds.".format( cooling_time)) yield from bps.sleep(cooling_time)
def update_value(self, *args, **kwargs): mode = int(self.count_mode.get()) if mode: time = self.auto_count_time.get() else: time = self.count_time.get() # Counts per seconds value = float(kwargs['value']) / time _submit(self.setText, self.formatStr.format(value))
def __init__(self, pv, read_pv=None, suppression=False, *args, **kwargs): super(GainComboBox, self).__init__(*args, **kwargs) self.lastUpdate = 0 self.setEditable(True) self.lineEdit = self.lineEdit() self.lineEdit.setAlignment(qt.Qt.AlignCenter) self.lineEdit.setReadOnly(True) self.setMinimumSize(qt.QSize(100, 30)) self.setMaximumSize(qt.QSize(100, 30)) self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.setItemText(0, "1E3 V/A") self.setItemText(1, "1E4 V/A") self.setItemText(2, "1E5 V/A") self.setItemText(3, "1E6 V/A") self.setItemText(4, "1E7 V/A") self.setItemText(5, "1E8 V/A") self.setItemText(6, "1E9 V/A") self.setItemText(7, "1E10 V/A") self.suppression = suppression if suppression: self.prefix = pv[:-4] self.suppressionValuePV = epics.PV(self.prefix + 'SuppressionValue', auto_monitor=True) self.suppressionExponentPV = epics.PV(self.prefix + 'SuppressionExponent', auto_monitor=True) self.pv = epics.PV(pv, auto_monitor=True) if read_pv: self.read_pv = epics.PV(read_pv, auto_monitor=True) else: self.read_pv = self.pv self.read_pv.add_callback(self.update_value) # Set initial value from pv if self.read_pv.connected: _submit(self.update_value) self.currentIndexChanged.connect(self.update_pv)
def update_value(self, *args, **kwargs): mode = int(self.count_mode.get()) if mode: time = self.auto_count_time.get() else: time = self.count_time.get() # Counts per seconds and then convert in voltage value = float(kwargs['value']) / time / 1e5 # Update readback _submit(self.setText, self.formatStr.format(value))
def __init__(self, pv, read_pv=None, *args, **kwargs): super().__init__(*args, **kwargs) self.lastUpdate = 0 self.setEditable(True) self.lineEdit = self.lineEdit() self.lineEdit.setAlignment(qt.Qt.AlignCenter) self.lineEdit.setReadOnly(True) self.setMinimumSize(qt.QSize(100, 30)) self.setMaximumSize(qt.QSize(100, 30)) self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.addItem("") self.setItemText(0, "10 usec") self.setItemText(1, "30 usec") self.setItemText(2, "100 usec") self.setItemText(3, "300 usec") self.setItemText(4, "1 msec") self.setItemText(5, "3 msec") self.setItemText(6, "10 msec") self.setItemText(7, "30 msec") self.setItemText(8, "100 msec") self.setItemText(9, "300 msec") if type(pv) in (list, tuple): self.pvs = {} for idx, _pv in enumerate(pv): self.pvs[idx] = epics.PV(_pv, auto_monitor=True) else: self.pvs[0] = epics.PV(pv, auto_monitor=True) if read_pv: self.read_pv = epics.PV(read_pv, auto_monitor=True) else: self.read_pv = self.pvs[0] self.read_pv.add_callback(self.update_value) # Set initial value from pv if self.read_pv.connected: _submit(self.update_value) self.currentIndexChanged.connect(self.update_pv)
def update_value(self, *args, **kwargs): if 'value' in kwargs.keys(): value = kwargs['value'] else: value = self.pv.get() if value == 0: text = 'Off' elif value == 1: text = 'On' elif value == 2: text = 'AutoCorrect' _submit(self.setText, text)
def __init__(self, pv, *args, **kwargs): super().__init__(*args, **kwargs) self.setMinimumSize(qt.QSize(100, 30)) self.setMaximumSize(qt.QSize(100, 30)) self.setFrameShape(qt.QFrame.Panel) self.setFrameShadow(qt.QFrame.Sunken) self.setAlignment(qt.Qt.AlignCenter) self.setText("not connected") self.pv = epics.PV(pv, auto_monitor=True) self.pv.add_callback(self.update_value) # Set initial value from pv if self.pv.connected: _submit(self.update_value)
def __init__(self, pv, *args, **kwargs): super(TweakDoubleSpinBox, self).__init__(*args, **kwargs) self.lastUpdate = 0 self.setMinimumSize(qt.QSize(130, 30)) self.setMaximumSize(qt.QSize(130, 30)) self.setAlignment(qt.Qt.AlignCenter) self.setButtonSymbols(qt.QAbstractSpinBox.UpDownArrows) self.setDecimals(3) self.setMinimum(-9999999.0) self.setMaximum(9999999.99) self.setSingleStep(0.01) self.pv = epics.PV(pv, auto_monitor=True) self.pv.add_callback(self.update_value) # Set initial value from pv _submit(self.setValue, self.pv.get()) self.valueChanged.connect(self.update_pv) self.setKeyboardTracking(False)
def run(self, *args, **kwargs): """ Do not call this from the main thread; you're probably looking for start() """ self.cancelled = False self.exception = None try: for self._result in self._run(*args, **kwargs): if not isinstance(self._result, tuple): self._result = (self._result,) if self.callback_slot: _submit(self.callback_slot, *self._result) except Exception as ex: self.exception = ex self.sigExcept.emit(ex) else: self.sigFinished.emit() finally: self.quit() qt.QApplication.instance().aboutToQuit.disconnect(self.quit)
def __init__(self, pv, *args, **kwargs): super(EpicsStringLabel, self).__init__(*args, **kwargs) self._dummyIndex = 0 self.setMinimumSize(qt.QSize(130, 30)) self.setMaximumSize(qt.QSize(130, 30)) self.setFrameShape(qt.QFrame.Panel) self.setFrameShadow(qt.QFrame.Sunken) self.setAlignment(qt.Qt.AlignCenter) self.setText("not connected") self.pv = epics.PV(pv, auto_monitor=True) self.pv.add_callback(self.update_value) self.notifyTimer = qt.QTimer() self.notifyTimer.timeout.connect(self._notifyColor) self.notifyTimer.start(1000) # Set initial value from pv if self.pv.connected: if self.pv.get(): _submit(self.setText, str("On"))
def __init__(self, pv, *args, read_pv=None, maximum=None, minimum=None, step=None, precision=None, **kwargs): super().__init__(*args, **kwargs) if maximum: self.setMaximum(maximum) if minimum: self.setMinimum(minimum) if step: self.setSingleStep(step) if precision: self.setDecimals(precision) self.valueBeingSet = False self.setMinimumSize(qt.QSize(130, 30)) self.setMaximumSize(qt.QSize(130, 30)) self.pv = epics.PV(pv) if read_pv: self.read_pv = epics.PV(read_pv, auto_monitor=True) else: self.read_pv = self.pv # Set initial value from pv if self.read_pv.connected: _submit(self.setValue, self.read_pv.get()) self.read_pv.add_callback(self.update_value)
def finalize(parent, device_dict, E0): """ Cleanup exafs_scan """ device_keys = device_dict.keys() try: fly_mode = parent.control.run_type.currentIndex() == 2 if fly_mode: orig_mono_speed = parent._orig_mono_speed flyer = device_dict['energyFlyer'] yield from bps.abs_set(flyer.fly_motor_speed, orig_mono_speed) # yield from bps.abs_set(flyer.fly_motor_stop, 1) if 'dcm' in device_keys: _submit(parent.control.abortButton.setDisabled, True) # _submit(parent.control.pauseButton.setDisabled, True) # _submit(parent.control.resumeButton.setDisabled, True) _submit(parent.control.ecal_abortButton.setDisabled, True) _submit(parent.control.run_start.setDisabled, True) _submit(parent.control.run_calibrate_button.setDisabled, True) dcm = device_dict['dcm'] parent.toLog("Energy is moving to " + str(E0) + " keV", color='blue') yield from stop_and_mv(dcm.energy, E0) finally: parent.blinkStatus = False parent.control_enable(True) try: parent.unsubscribe_callback() except Exception as e: print("Exception in unsubscribe callback : {}".format(e)) parent.toLog("Scan is finished", color='blue')
def receiveZmq(self): sock = CONTEXT.socket(zmq.SUB) sock.connect("tcp://localhost:" + str(self.zmqRecvPort)) sock.setsockopt_string(zmq.SUBSCRIBE, '') while True: msg = sock.recv().decode() logger.error("{}".format(msg)) if len(msg): try: if msg.startswith('tabChanged'): index = int(msg.split(':')[-1].strip()) self.tabChanged(index) elif msg.startswith('UpdateViewer'): self.updatePlotThread.update() elif msg.startswith('XLabel:'): label = msg.split(':')[-1] _submit(self.plot.setGraphXLabel, label) elif msg.startswith('YLabel:'): label = msg.split(':')[-1] _submit(self.plot.setGraphYLabel, label) elif msg.startswith('Blink:'): value = msg.split(':')[-1] if value.lower() in ('true', '1'): self.settings['blink'] = True else: self.settings['blink'] = False elif msg.startswith('RunEngine:'): value = msg.split(':')[-1] _submit(self.status.engineStatus.setText, value) elif msg.startswith('RemoveCurves'): _submit(self.plot.clearCurves) elif msg.startswith('RemoveCurve:'): value = msg.split(':')[-1] _submit(self.plot.removeCurve, value) elif msg.startswith('FlyStartTime:'): value = np.double(msg.split(':')[-1]) self.start_timer = value elif msg.startswith('DisableAbortButton:'): value = msg.split(':')[-1] if value.lower() in ('true', '1'): _submit(self.status.abortButton.setDisabled, True) else: _submit(self.status.abortButton.setDisabled, False) except Exception as e: print("Exception in receiveZmq : {}".format(e))
def run(self): idx = 1 while True: logger.error("waiting") self.event.wait() logger.error("start") xdata = self.xdata[:idx] ydata = self.ydata[:idx] curve = self.parent.plot.getCurve('Data 0') if curve: oldXData = curve.getXData(copy=True) oldYData = curve.getYData(copy=True) if np.any(oldXData != xdata) or np.any(oldYData != ydata): _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data 0', color=ColorDict[0], linestyle='-', resetzoom=True, z=ZOrder[0], selectable=False) _submit(self.parent.plot.addCurve, xdata, ydata * 5, legend='Data 1', color=ColorDict[1], linestyle='-', resetzoom=True, z=ZOrder[1], selectable=False) else: _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data 0', color=ColorDict[0], linestyle='-', resetzoom=True, z=ZOrder[0], selectable=False) _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data 1', color=ColorDict[1], linestyle='-', resetzoom=True, z=ZOrder[1], selectable=False) if idx >= 2000: idx = 1 else: idx += 10 ttime.sleep(0.1) logger.error("clear") self.event.clear()
def cancel(self): self.cancelled = True if self.except_slot: _submit(self.except_slot, InterruptedError("Thread cancelled.")) self.quit() self.wait()
def updateFlyInfo(self): try: startE = self.flyStartE.value() stopE = self.flyStopE.value() resolution = self.flyResolutionE.value() time = self.flyScanTime.value() E0 = self._parent.edit_E0.value() encResolution = self._parent.parent.ophydDict[ 'dcm'].encResolution.get() # Angles at E0 and E0 + Resolution th0 = np.rad2deg(np.arcsin(_hc / (2. * _si_111 * float(E0)))) th0_plus_step = np.rad2deg( np.arcsin(_hc / (2. * _si_111 * float(E0 + resolution)))) th0_step = abs(th0 - th0_plus_step) if th0_step < encResolution: th0_step = encResolution newEnergyResolution = round( abs(_hc / (2. * _si_111 * np.sin(np.deg2rad(th0 - th0_step))) - E0), 2) self.flyResolutionE.setValue(newEnergyResolution) Energy_start = E0 + startE th_start = np.rad2deg( np.arcsin(_hc / (2. * _si_111 * float(Energy_start)))) currentTab = self._parent.tabWidget.currentIndex() currentStack = self._parent.stackedWidget.currentIndex() # When currentTab is 'Energy Scan' and currentStack is in 'fly-mode' if currentTab == 0 and currentStack == 1: # Switch startE and stopE if startE > stopE: # Swap tmp = startE startE = stopE stopE = tmp _submit(self.flyStartE.setValue, startE) _submit(self.flyStopE.setValue, stopE) Energy_stop = E0 + stopE th_stop = np.rad2deg( np.arcsin(_hc / (2. * _si_111 * float(Energy_stop)))) # DCM fly-scan speed [Deg/sec] estimated_speed = round(abs(th_stop - th_start) / time, 4) # Check encoder steps per point enc_steps_per_point = int(th0_step / encResolution) # Set total scan counts scan_total_counts = int( abs(th_start - th_stop) / encResolution / enc_steps_per_point) + 1 # Check number of scan points maxPoints = int(self._parent.parent.pv_names['Scaler'] ['HC10E_FlyMaxPoints']) if scan_total_counts > maxPoints: while 1: enc_steps_per_point += 1 # Calculate scan_total_counts again scan_total_counts = int( abs(th_start - th_stop) / encResolution / enc_steps_per_point) + 1 # Escape if scan_total_counts < maxPoints: break new_th0_step = enc_steps_per_point * encResolution newEnergyResolution = round( abs(_hc / (2. * _si_111 * np.sin(np.deg2rad(th0 - new_th0_step))) - E0), 2) self.flyResolutionE.setValue(newEnergyResolution) elif scan_total_counts < 30: while 1: enc_steps_per_point -= 1 # Calculate scan_total_counts again scan_total_counts = int( abs(th_start - th_stop) / encResolution / enc_steps_per_point) + 1 # Escape if scan_total_counts > 30: break new_th0_step = enc_steps_per_point * encResolution newEnergyResolution = round( abs(_hc / (2. * _si_111 * np.sin(np.deg2rad(th0 - new_th0_step))) - E0), 2) self.flyResolutionE.setValue(newEnergyResolution) # Check speed range speed = estimated_speed vmax = self._parent.parent.ophydDict['dcm_etc'].mono_vmax.get() vmin = self._parent.parent.ophydDict['dcm_etc'].mono_vbas.get() if speed > vmax: new_time = round(abs(th_stop - th_start) / vmax + 0.01, 2) self.flyScanTime.setValue(new_time) speed = round(abs(th_stop - th_start) / new_time, 3) elif speed < vmin: new_time = round(abs(th_stop - th_start) / vmin - 0.01, 2) self.flyScanTime.setValue(new_time) speed = round(abs(th_stop - th_start) / new_time, 3) _submit(self.flyMotorSpeed.setText, str(speed)) _submit(self.flyEncoderStepSize.setText, str(enc_steps_per_point)) _submit(self.flyNumOfPoints.setText, str(scan_total_counts)) except Exception as e: print("Exception in FlyControlWidget.updateFlyInfo : {}".format(e))
def update_value(self, *args, **kwargs): delta = abs(time.time() - self.lastUpdate) # Prevent looping if delta > 1: _submit(self.setValue, self.pv.get())
def update_value(self, *args, **kwargs): delta = abs(time.time() - self.lastUpdate) # Prevent looping if delta > 1: _submit(self.setCurrentIndex, self.read_pv.get())
def update_color(self, *args, **kwargs): if self.moving_pv.get() == self.moving_val: _submit(self.setStyleSheet, "QLabel { background-color: green }") else: _submit(self.setStyleSheet, "QLabel { background-color: 0 }")
def update_scan_status(self, dataFrame=None, meta_data=None): data = dataFrame current_points = len(data['I0']) scan_mode = meta_data['scan_mode'] # update scanPoint _submit(self.status.scan_point_label.setText, str(current_points)) if current_points > 2: if scan_mode == 'normal': # Set loop time in seconds loop_time = np.round( float(data['time'][-1] - data['time'][-2]), 2) # Label Name to 'LoopTime : ' if self.status.scanInfoLoopTimeLabel.text() != 'LoopTime : ': _submit(self.status.scanInfoLoopTimeLabel.setText, 'LoopTime : ') # Update loop time _submit(self.status.loop_time_label.setText, str(loop_time)) elif scan_mode == 'fly': # Set elapsed time elapsed_time = ttime.time() - meta_data['time'] # Label Name to 'ElapsedTime : ' if self.status.scanInfoLoopTimeLabel.text( ) != 'ElapsedTime : ': _submit(self.status.scanInfoLoopTimeLabel.setText, 'ElapsedTime : ') # Update Elapsed time _submit(self.status.loop_time_label.setText, str(round(elapsed_time, 1))) if self.plot_type != 'align': total_points = meta_data['scan_points'] # total number _submit(self.status.num_of_steps_label.setText, str(total_points)) # current_points+1 is due to first element always excluded from dataFrame msg = "ProgressBar:{:d}".format( int((current_points + 1) / total_points * 100)) self.zmqSendSock.send(msg.encode()) else: _submit(self.status.num_of_steps_label.setText, "") _submit(self.status.progressBar.setValue, 0)
def update_value(self, *args, **kwargs): value = kwargs['value'] _submit(self.setText, self.formatStr.format(value))
def multi_exafs_scan(detectors, motor, E0, energy_list, time_list, delay_time, waitTime, device_dict, parent): """ Repeat multiple or batch exafs_scan""" batch_scan = parent.control.use_batch_checkbox.isChecked() if batch_scan: # Batch scan sample_names, sample_info = parent.sampleTable.getData() for idx, sample_name in enumerate(sample_names): # Do not run this scan if sample_name is empty if not len(sample_name): continue sample_pos, num_scan = sample_info[idx] num_scan = int(num_scan) if num_scan > 1: # Multi-scan _submit(parent.control.run_type.setCurrentIndex, 1) else: # Single-scan _submit(parent.control.run_type.setCurrentIndex, 0) # Set number of scan _submit(parent.control.number_of_scan_edit.setValue, num_scan) # Set filename _submit(parent.control.filename_edit.setText, sample_name) parent.toLog("Current sample_name in Batch mode is " + sample_name) # Disable controls parent.control_enable(False) # Move to sample position sample_changer = device_dict['sampleChanger'] yield from stop_and_mv(sample_changer, sample_pos) parent.toLog("Sample position is moving to " + str(sample_pos)) for _ in range(num_scan): parent.subscribe_callback() parent.toLog("A new scan is started", color='blue') # Do exafs scan yield from exafs_scan(detectors, motor, E0, energy_list, time_list, delay_time, waitTime) parent.unsubscribe_callback() # Decrease remaining scan-number remaining_scan = num_scan - (idx + 1) if remaining_scan > 0: _submit(parent.control.number_of_scan_edit.setValue, remaining_scan) _submit(parent.control.number_of_scan_edit.setDisabled, True) else: # Multi scan num_scan = int(parent.control.number_of_scan_edit.value()) for idx in range(num_scan): parent.subscribe_callback() parent.toLog("A new scan is started : {}".format(idx + 1), color='blue') # Do exafs scan yield from exafs_scan(detectors, motor, E0, energy_list, time_list, delay_time, waitTime) parent.unsubscribe_callback() # Decrease remaining scan-number remaining_scan = num_scan - (idx + 1) if remaining_scan > 0: _submit(parent.control.number_of_scan_edit.setValue, remaining_scan) _submit(parent.control.number_of_scan_edit.setDisabled, True)
def tabChanged(self, index): if index == 0: self.plot_type = 'measure' if self._last_tab_index not in [0]: idx = self._last_y_axis_type _submit(self.status.y_axis_type_combo_box.setCurrentIndex, idx) _submit(self.status.derivativeCB.setChecked, False) _submit(self.plot.removeCurve, 'derivative') _submit(self.plot.setGraphXLabel, "Energy [eV]") elif index == 1: self.plot_type = 'calibration' # Save previous y-axis selection if self._last_tab_index in [0]: self._last_y_axis_type = self.status.y_axis_type_combo_box.currentIndex( ) # default as Transmission for calibration _submit(self.status.y_axis_type_combo_box.setCurrentIndex, 0) _submit(self.status.derivativeCB.setChecked, True) _submit(self.plot.setGraphXLabel, "Energy [eV]") else: self.plot_type = 'align' # Save previous y-axis selection if self._last_tab_index in [0]: self._last_y_axis_type = self.status.y_axis_type_combo_box.currentIndex( ) # Set y-axis type to I0 Only _submit(self.status.y_axis_type_combo_box.setCurrentIndex, 4) _submit(self.status.derivativeCB.setChecked, False) _submit(self.plot.removeCurve, 'derivative') _submit(self.plot.setGraphXLabel, "index") # Last tab index self._last_tab_index = index
def clear_extra_graph(self, num_of_history): null_data = np.array([]) for idx in range(10): if idx >= num_of_history: # clear data on plot _submit(self.plot.removeCurve, "Data " + str(idx))
def update_value(self, *args, **kwargs): value = kwargs['value'] if value: _submit(self.setText, "On") else: _submit(self.setText, "Off")
def clear_graph(self): for idx in range(10): _submit(self.plot.removeCurve, "Data " + str(idx))
def run(self): """Thread loop that updates the plot""" while self.running: try: # Check force update self.force_update.pop() except: # Wait for update event self.event.wait() try: num_of_history = int( self.parent.status.num_of_history_spin_box.value()) # Remove extra curves for idx in range(num_of_history, 10): self.parent.plot.removeCurve('Data {:d}'.format(idx)) x_type = self.parent.status.x_axis_type_combo_box.currentIndex( ) y_type = self.parent.status.y_axis_type_combo_box.currentIndex( ) # derivate status derivativeStatus = bool( self.parent.status.derivativeCB.isChecked()) # plot for energy scan if self.parent.plot_type == 'measure': # clear unnecessary graph _submit(self.parent.clear_extra_graph, num_of_history) search_results = self.parent.db.search({ 'scan_type': 'measure' }).items() for idx, (_, run) in enumerate(search_results): if idx >= num_of_history: break meta_data = run.metadata['start'] scan_mode = meta_data['scan_mode'] if 'sdd' in meta_data.keys(): sdd = meta_data['sdd'] else: sdd = False # get dark current I0_dark_current = meta_data['darkI0'] It_dark_current = meta_data['darkIt'] If_dark_current = meta_data['darkIf'] Ir_dark_current = meta_data['darkIr'] # Get E0 E0 = meta_data['E0'] # Retrieve scan data if scan_mode == 'normal': try: data = run.primary.read() except: # Do reset when there is no zoomed history resetzoom = len( self.parent.plot.getLimitsHistory( )) == 0 and not self.parent.dragging # Plot with null data _submit(self.parent.plot.addCurve, [], [], legend='Data ' + str(idx), color=ColorDict[idx], linestyle='-', resetzoom=resetzoom, z=ZOrder[idx], selectable=False) continue # To eV unit # data['dcm_energy'] *= 1000.0 # compensate dark current data['I0'] = data[ 'I0'] - I0_dark_current * data['scaler_time'] data['It'] = data[ 'It'] - It_dark_current * data['scaler_time'] data['If'] = data[ 'If'] - If_dark_current * data['scaler_time'] data['Ir'] = data[ 'Ir'] - Ir_dark_current * data['scaler_time'] if sdd: # DeadTime correction mca1_icr = data['falconX4_mca1InputCountRate'] mca2_icr = data['falconX4_mca2InputCountRate'] mca3_icr = data['falconX4_mca3InputCountRate'] mca4_icr = data['falconX4_mca4InputCountRate'] mca1_ocr = data['falconX4_mca1OutputCountRate'] mca2_ocr = data['falconX4_mca2OutputCountRate'] mca3_ocr = data['falconX4_mca3OutputCountRate'] mca4_ocr = data['falconX4_mca4OutputCountRate'] data[ 'falconX4_mca1_rois_roi0_count'] *= mca1_icr / mca1_ocr data[ 'falconX4_mca2_rois_roi0_count'] *= mca2_icr / mca2_ocr data[ 'falconX4_mca3_rois_roi0_count'] *= mca3_icr / mca3_ocr data[ 'falconX4_mca4_rois_roi0_count'] *= mca4_icr / mca4_ocr # MCA Sum data['mcaSum'] = data['falconX4_mca1_rois_roi0_count'] +\ data['falconX4_mca2_rois_roi0_count'] +\ data['falconX4_mca3_rois_roi0_count'] +\ data['falconX4_mca4_rois_roi0_count'] elif scan_mode == 'fly': # header headers = self.parent.dbv1(scan_type='measure') for _idx, hd in enumerate(headers): header = hd if idx == _idx: break if 'primary' in header.stream_names: data = header.table('primary') meta_data = header.start # Convert encoder to energy data_enc = np.array(data['ENC']) enc_resolution = meta_data['enc_resolution'] startTh = meta_data['startTh'] # Multiply sign for direction conversion. Increased encoder counter means the th-angle decreases scan_pos_th = self.enc_sign * data_enc * enc_resolution + startTh energy = _hc / (2. * _si_111 * np.sin( np.deg2rad(scan_pos_th))) data['dcm_energy'] = energy else: # delay for monitor update ttime.sleep(0.2) # During fly-scan, retrieve data from EPICS IOC enc_pos = np.array(self.encPV.get()) chan1 = np.array(self.I0PV.get()) chan2 = np.array(self.ItPV.get()) chan3 = np.array(self.IfPV.get()) chan4 = np.array(self.IrPV.get()) _arrayMinSize = int( min(enc_pos.size, chan1.size, chan2.size, chan3.size, chan4.size)) # The arrays must be the same size if _arrayMinSize < enc_pos.size: enc_pos = enc_pos[:_arrayMinSize] if _arrayMinSize < chan1.size: chan1 = chan1[:_arrayMinSize] if _arrayMinSize < chan2.size: chan2 = chan2[:_arrayMinSize] if _arrayMinSize < chan3.size: chan3 = chan3[:_arrayMinSize] if _arrayMinSize < chan4.size: chan4 = chan4[:_arrayMinSize] # Load scan parameters enc_resolution = meta_data['enc_resolution'] startTh = meta_data['startTh'] # Multiply sign for direction conversion. Increased encoder counter means the th-angle decreases scan_pos_th = self.enc_sign * enc_pos * enc_resolution + startTh energy = np.array( _hc / (2. * _si_111 * np.sin(np.deg2rad(scan_pos_th)))) # Drop the first element and create a DataFrame data = pd.DataFrame({ 'dcm_energy': energy, 'I0': chan1, 'It': chan2, 'If': chan3, 'Ir': chan4 }) # Skip if DataFrame is empty if not bool(int(data['dcm_energy'].count())): continue # Update scan status # Don't update for fly scan if idx == 0: _submit(self.parent.update_scan_status, data, meta_data) xdata, ydata = retrieve_data(data, meta_data, x_type, y_type) if ydata is None: continue xdata = np.array(xdata) ydata = np.array(ydata) # Select only finite values _finiteIndex = np.isfinite(ydata) xdata = xdata[_finiteIndex] ydata = ydata[_finiteIndex] # Do reset when there is no zoomed history resetzoom = len(self.parent.plot.getLimitsHistory() ) == 0 and not self.parent.dragging # Data plot curve = self.parent.plot.getCurve('Data ' + str(idx)) if curve: oldXData = curve.getXData(copy=True) oldYData = curve.getYData(copy=True) if np.any(oldXData != xdata) or np.any( oldYData != ydata): _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data ' + str(idx), color=ColorDict[idx], linestyle='-', resetzoom=resetzoom, z=ZOrder[idx], selectable=False) else: _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data ' + str(idx), color=ColorDict[idx], linestyle='-', resetzoom=resetzoom, z=ZOrder[idx], selectable=False) # Derivative plot if idx == 0: # derivative axis if derivativeStatus: _derivative = np.array(derivative( xdata, ydata)) # Select only finite values _finiteIndex = np.isfinite(_derivative) _xdata = xdata[_finiteIndex] _derivative = _derivative[_finiteIndex] # Previous derivative curve curve = self.parent.plot.getCurve('derivative') # Derivative Plot if curve: oldXData = curve.getXData(copy=True) oldYData = curve.getYData(copy=True) if np.any(oldXData != _xdata) or np.any( oldYData != _derivative): _submit(self.parent.plot.addCurve, _xdata, _derivative, yaxis='right', linestyle='-', color=ColorDict[10], resetzoom=resetzoom, legend='derivative', z=ZOrder[10], selectable=False) else: _submit(self.parent.plot.addCurve, _xdata, _derivative, yaxis='right', linestyle='-', color=ColorDict[10], resetzoom=resetzoom, legend='derivative', z=ZOrder[10], selectable=False) else: _submit(self.parent.plot.removeCurve, 'derivative') # plot for energy calibration elif self.parent.plot_type == 'calibration': # clear unnecessary graph _submit(self.parent.clear_extra_graph, num_of_history) search_results = self.parent.db.search({ 'scan_type': 'calibration' }).items() for idx, (_, run) in enumerate(search_results): if idx >= num_of_history: break # scan meta data meta_data = run.metadata['start'] # get dark current I0_dark_current = meta_data['darkI0'] It_dark_current = meta_data['darkIt'] If_dark_current = meta_data['darkIf'] Ir_dark_current = meta_data['darkIr'] # Retrieve scan data try: data = run.primary.read() except: # Do reset when there is no zoomed history resetzoom = len(self.parent.plot.getLimitsHistory( )) == 0 and not self.parent.dragging # Plot with null data _submit(self.parent.plot.addCurve, [], [], legend='Data ' + str(idx), color=ColorDict[idx], linestyle='-', resetzoom=resetzoom, z=ZOrder[idx], selectable=False) continue # data['dcm_energy'] *= 1000.0 # compensate dark current data['I0'] = data[ 'I0'] - I0_dark_current * data['scaler_time'] data['It'] = data[ 'It'] - It_dark_current * data['scaler_time'] data['If'] = data[ 'If'] - If_dark_current * data['scaler_time'] data['Ir'] = data[ 'Ir'] - Ir_dark_current * data['scaler_time'] # Get E0 # To eV unit E0 = meta_data['E0'] # Skip if DataFrame is empty if not bool(len(data['time'])): continue # update scan status if idx == 0: _submit(self.parent.update_scan_status, data, meta_data) xdata, ydata = retrieve_data(data, meta_data, x_type, y_type) if ydata is None: continue xdata = np.array(xdata) ydata = np.array(ydata) # Select only finite values _finiteIndex = np.isfinite(ydata) xdata = xdata[_finiteIndex] ydata = ydata[_finiteIndex] resetzoom = len(self.parent.plot.getLimitsHistory() ) == 0 and not self.parent.dragging # Set data curve = self.parent.plot.getCurve('Data ' + str(idx)) if curve is not None: oldXData = curve.getXData(copy=True) oldYData = curve.getYData(copy=True) if np.any(oldXData != xdata) or np.any( oldYData != ydata): _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data ' + str(idx), color=ColorDict[idx], linestyle='-', resetzoom=resetzoom, z=ZOrder[idx], selectable=False) else: _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data ' + str(idx), color=ColorDict[idx], linestyle='-', resetzoom=resetzoom, z=ZOrder[idx], selectable=False) # Derivative plot if len(xdata) > 2 and idx == 0: _derivative = np.array(derivative(xdata, ydata)) # Select only finite values _finiteIndex = np.isfinite(_derivative) _xdata = xdata[_finiteIndex] _derivative = _derivative[_finiteIndex] derivative_max = max(_derivative) idx_max = np.where( _derivative == derivative_max)[0][0] # x_type == 0 : delta energy, x_type == 1 : energy[eV] if x_type == 0: energy_derivative_max = _xdata[idx_max] + E0 else: energy_derivative_max = _xdata[idx_max] msg = "EcalPeakEnergyLabel:{}".format( str(np.round(float(energy_derivative_max), 4))) self.parent.sendZmq(msg) msg = "EcalEnergyDifferenceLabel:{}".format( str( np.round(float(energy_derivative_max - E0), 4))) self.parent.sendZmq(msg) # derivative axis if derivativeStatus: _derivative = np.array(derivative( xdata, ydata)) # Select only finite values _finiteIndex = np.isfinite(_derivative) _xdata = xdata[_finiteIndex] _derivative = _derivative[_finiteIndex] # Previous derivative curve curve = self.parent.plot.getCurve('derivative') # Derivative Plot if curve is not None: oldXData = curve.getXData(copy=True) oldYData = curve.getYData(copy=True) if np.any(oldXData != _xdata) or np.any( oldYData != _derivative): _submit(self.parent.plot.addCurve, _xdata, _derivative, yaxis='right', linestyle='-', color=ColorDict[10], resetzoom=resetzoom, legend='derivative', z=ZOrder[10], selectable=False) else: _submit(self.parent.plot.addCurve, _xdata, _derivative, yaxis='right', linestyle='-', color=ColorDict[10], resetzoom=resetzoom, legend='derivative', z=ZOrder[10], selectable=False) else: _submit(self.parent.plot.removeCurve, 'derivative') # plot for tweak plan elif self.parent.plot_type == 'align': # clear unnecessary graph _submit(self.parent.clear_extra_graph, num_of_history) _submit(self.parent.plot.removeCurve, 'derivative') search_results = self.parent.db.search({ 'scan_type': 'tweak' }).items() for idx, (_, run) in enumerate(search_results): if idx >= 1: break try: data = run.primary.read() except: continue meta_data = run.metadata['start'] # Skip if DataFrame is empty if not bool(len(data['time'])): continue # update scan status if idx == 0: _submit(self.parent.update_scan_status, data, meta_data) xdata, ydata = retrieve_data(data, meta_data, x_type, y_type) if ydata is None: continue ydata = np.array(ydata) # Select only finite values _finiteIndex = np.isfinite(ydata) xdata = xdata[_finiteIndex] ydata = ydata[_finiteIndex] resetzoom = len(self.parent.plot.getLimitsHistory() ) == 0 and not self.parent.dragging ratio = float(self.parent.settings['ratio']) _submit(self.parent.plot.addCurve, xdata, ydata, legend='Data 0', color=ColorDict[0], linestyle='-', resetzoom=resetzoom, z=ZOrder[0], selectable=False) msg = "DCM_I0:{}".format(str(np.round(ydata[-1], 2))) self.parent.sendZmq(msg) msg = "DCM_I0_2:{}".format( str(np.round(ydata[-1] * ratio, 2))) self.parent.sendZmq(msg) except Exception as e: print("Exception occured in scan_utils.UpdatePlotThread {}", e) # Set wait for events self.event.clear()