class UserLoginModule(QDialog, Ui_Dialog): def __init__(self, menu, parent=None): super(UserLoginModule, self).__init__(parent) self.setupUi(self) self.menu = menu self.label_tips.setVisible(False) self.CC = ClerksController() return_row = ('autoid', 'clerkid', 'clerkname') condition_key = ('clerkid', 'clerkname') treeheader_name = ["id", "编号", "姓名"] self.lineEdit_username.setup('Clerks', return_row, condition_key, treeheader_name, None, 250, 200) @pyqtSlot() def on_pushButton_accept_clicked(self): try: userid, username = self.lineEdit_username.text().split(' ') except: self.label_tips.setVisible(True) self.lineEdit_username.setFocus() return password = md5( self.lineEdit_password.text().encode('UTF-8')).hexdigest() condition = { 'clerkid': userid, 'clerkname': username, 'password': password } res = self.CC.get_data(0, False, *VVALUES_TUPLE_CL, **condition) if len(res): user.user_id = userid user.user_name = username if res[0]['powers'] != '': try: user.powers = json.loads(res[0]['powers']) except json.decoder.JSONDecodeError: pass condition = {'clerkid': res[0]['autoid']} dept_res = self.CC.get_data(1, False, **condition).order_by('-defaultdept') if len(dept_res): user.dept_id = dept_res[0].deptid.deptid user.dept_name = dept_res[0].deptid.deptname self.menu.showMaximized() self.menu.set_module() self.setHidden(True) else: self.label_tips.setVisible(True) pyqtSlot(str) def on_lineEdit_username_textChanged(self, p_str): self.label_tips.setVisible(False) pyqtSlot(str) def on_lineEdit_password_textChanged(self, p_str): self.label_tips.setVisible(False)
def create_slot(argType=None, name=None): if not name or name is None: if argType is None: return pyqtSlot() else: return pyqtSlot(argType) else: if argType is None: return pyqtSlot(name=name) else: return pyqtSlot(argType, name=name)
def qtSlot(f: Callable[..., Any]) -> Callable[..., Any]: sig = inspect.signature(f) result_type = sig.return_annotation assert result_type != sig.empty, "Return annotation missing" parameters = [] for par in sig.parameters.values(): if par.name == "self": continue assert par.annotation != sig.empty, "Parameter annotation missing for %s" % ( par.name) parameters.append(_toQtType(par.annotation)) if result_type is not None: return pyqtSlot(*parameters, result=_toQtType(result_type))(f) return pyqtSlot(*parameters)(f)
def slot(function: FuncT) -> FuncT: """Annotation based slot decorator using pyqtSlot. Syntactic sugar for pyqtSlot so the parameter types do not have to be repeated when there are type annotations. Example: @slot def function(self, x: int, y: int) -> None: ... """ annotations = typing.get_type_hints(function) pyqtSlot(*_slot_args(function, annotations), **_slot_kwargs(annotations))(function) return function
class VideoHandler: def __init__(self, filename): self.video_filename = filename try: self.video_handler = cv2.VideoCapture(self.video_filename) except: # there was an error reading the file, return # we need to add error codes so that the user can knows what happened return self.video_length = int(self.video_handler.get(cv2.CAP_PROP_FRAME_COUNT)) self.video_fps = int(self.video_handler.get(cv2.CAP_PROP_FPS)) self.playbackspeed = self.video_fps self.video_exist_landmarks = None self.video_landmarks_filename = None self.video_landmarks = None pyqtSlot(object) def emitimage(self, image): return image def playvideo(self): th = ThreadReadVideo(self.video_handler) th.videoframe.connect(self.emitimage) th.start()
class App(QWidget): def __init__(self): super().__init__() self.title = "BLACKPINK Secret Word Song" self.left = 200 self.top = 200 self.width = 640 self.height = 480 self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.textbox1 = QLineEdit(self) self.textbox1.move(30, 30) self.textbox1.resize(280, 40) self.button = QPushButton('Click me', self) self.button.move(15, 85) self.button.clicked.connect(self.on_click) self.show() pyqtSlot() def on_click(self): textboxValue = self.textbox1.text() QMessageBox.question(self, 'Hello', 'Confirm: ' + textboxValue, QMessageBox.Ok, QMessageBox.Cancel) self.textbox1.setText('')
def __init__(self, parent=None): super().__init__(parent) uic.loadUi('system/gui/chat_test.ui', self) self.listContacts.setSortingEnabled(True) self.selected_item_row = None self.selected_item_text = "" self.notifier = Notifier() self.receiver = ReceiverHandler() self.thread = QThread() self.auth = AuthReg() self.reg = AuthReg(auth=False) self.got_img = pyqtSlot(dict)
def _decorator(method): @functools.wraps(method) def new_method(self, *args, **kwargs): try: return method(self, *args, **kwargs) except: e = str(sys.exc_info()[0]) log.network.exception("PAC evaluation error") # pylint: disable=protected-access return self._error_con.callAsConstructor([e]) # pylint: enable=protected-access return pyqtSlot(*args, result=QJSValue)(new_method)
class OSCclient(QObject): """Connects to OSC server to send OSC messages to server input: ip of qlab machine, input port number default localhost, 53000 (QLab settings)""" def __init__(self, ip="127.0.0.1", port=53000): QObject.__init__(self) self.ip = ip self.port = port self.client = udp_client.UDPClient(ip, port) pyqtSlot(object) def emit(self, cuenum): msg_raw = f"/cue/{cuenum}/start" print(f'{msg_raw} sent') msg = osc_message_builder.OscMessageBuilder(msg_raw) msg = msg.build() self.client.send(msg)
class Reader(QObject): ''' Synchronous data reader. ''' received = pyqtSignal(bytes) done = pyqtSignal() def __init__(self, io): QObject.__init__(self) self.io = io self.proceedToExit = None pyqtSlot() def read(self): ''' Infinitely wait for incoming data in an infinite loop. All the incoming data is passed outside with the signal. :return data: bytes, incoming data ''' self.proceedToExit = False while not self.proceedToExit: data = self.io.read() QCoreApplication.processEvents( ) # need to process events, and delivered signals if not data: continue self.received.emit(data) self.io.close() self.done.emit() @pyqtSlot() def quit(self): self.proceedToExit = True
def decorator(func): if os.environ.get('READTHEDOCS') != 'True': func = pyqtSlot(*args, **kwargs)(func) signatures = [] for srcline in inspect.getsourcelines(func)[0]: srcline = srcline.strip() mtc = SLOT_RE.match(srcline) if mtc: signatures.append(mtc.group(1)) elif srcline.startswith('def '): break text = '\n\n'.join('This slot has signature ``%s%s``.' % (func.__name__, sig) for sig in signatures) _addDoc(func, text) return func
def start(self): self.setIptables(self.APmode, option="A") self.procThreadDNS = QProcess(self) self.procThreadDNS.setProcessChannelMode(QProcess.MergedChannels) QObject.connect( self.procThreadDNS, pyqtSignal("readyReadStandardOutput()"), self, pyqtSlot("readProcessOutput()"), ) self.procThreadDNS.start( "python", [ "core/packets/dnsspoofNF.py", "-r", self.redirect, "-d", ",".join(self.domains), ], )
def decorator(func): if os.environ.get('READTHEDOCS') != 'True': func = pyqtSlot(*args, **kwargs)(func) signatures = [] for srcline in inspect.getsourcelines(func)[0]: srcline = srcline.strip() mtc = SLOT_RE.match(srcline) if mtc: signatures.append('@Slot%s' % mtc.group(1)) elif srcline.startswith('def '): break text = '\n\n'.join(signatures) if func.__doc__ is None: func.__doc__ = text else: func.__doc__ += '\n\n' + text return func
def wrapper(func): if is_slot: func = pyqtSlot()(func) @wraps(func) def decorator(*args, **kwargs): qobj = args[0] if is_qt_method else None result, exception = None, None loop = QEventLoop() progress = ProgressWindow(parent=qobj, window_title=window_title, label_text=label_text) class Thread(QtCore.QThread): def run(self): nonlocal result, exception try: result = func(*args, **kwargs) except Exception as e: exception = e task = Thread() task.finished.connect(progress.close) task.finished.connect(loop.exit) nonlocal disable disable = disable and qobj is not None with disabled(qobj, enable=disable, except_objs=[progress]): progress.show() task.start() loop.exec() if exception is not None: raise exception return result return decorator
class ColorPalette(QFrame): """Represents the entire grid of color tiles in the color picker """ def __init__(self): super().__init__() self.grid = QGridLayout() self.grid.setSpacing(0) self.grid.setContentsMargins(0, 0, 0, 0) self.setLayout(self.grid) self.palette = [Color(n) for n in range(256)] self.setFrameShape(QFrame.Panel) self.setFrameShadow(QFrame.Sunken) self.setLineWidth(3) self.setFixedSize(400 + self.lineWidth() * 2, 400 + self.lineWidth() * 2) positions = [(row, col) for row in range(16) for col in range(16)] colors = [(red, green, blue) for blue in range(4) for red in range(8) for green in range(8)] for position, color, swatch in zip(positions, colors, self.palette): color = QColor(*upsample(*color)) swatch.fill(color) swatch.color_selected.connect(self.selectColor) self.grid.addWidget(swatch, *position) self.enabled = False pyqtSlot(int) def selectColor(self, index): """Selects a color in the color picker :param index: Index of the selected color :type index: int """ for idx in range(self.grid.count()): if idx != index: self.grid.itemAt(idx).widget().deselect()
class ModulesManager(QObject): detectors_changed = pyqtSignal(list) actuators_changed = pyqtSignal(list) det_done_signal = pyqtSignal(OrderedDict) move_done_signal = pyqtSignal(OrderedDict) timeout_signal = pyqtSignal(bool) params = [ { 'title': 'Actuators/Detectors Selection', 'name': 'modules', 'type': 'group', 'children': [ { 'title': 'detectors', 'name': 'detectors', 'type': 'itemselect' }, { 'title': 'Actuators', 'name': 'actuators', 'type': 'itemselect' }, ] }, { 'title': "Moves done?", 'name': 'move_done', 'type': 'led', 'value': False }, { 'title': "Detections done?", 'name': 'det_done', 'type': 'led', 'value': False }, { 'title': 'Data dimensions', 'name': 'data_dimensions', 'type': 'group', 'children': [ { 'title': "Probe detector's data", 'name': 'probe_data', 'type': 'action' }, { 'title': 'Data0D list:', 'name': 'det_data_list0D', 'type': 'itemselect' }, { 'title': 'Data1D list:', 'name': 'det_data_list1D', 'type': 'itemselect' }, { 'title': 'Data2D list:', 'name': 'det_data_list2D', 'type': 'itemselect' }, { 'title': 'DataND list:', 'name': 'det_data_listND', 'type': 'itemselect' }, ] }, { 'title': 'Actuators positions', 'name': 'actuators_positions', 'type': 'group', 'children': [ { 'title': "Test actuators", 'name': 'test_actuator', 'type': 'action' }, { 'title': 'Positions:', 'name': 'positions_list', 'type': 'itemselect' }, ] }, ] def __init__(self, detectors=[], actuators=[], selected_detectors=[], selected_actuators=[], timeout=10000): super().__init__() for mod in selected_actuators: assert mod in actuators for mod in selected_detectors: assert mod in detectors self.timeout = timeout #in ms self.det_done_datas = OrderedDict() self.det_done_flag = False self.move_done_positions = OrderedDict() self.move_done_flag = False self.settings = Parameter.create(name='Settings', type='group', children=self.params) self.settings_tree = ParameterTree() self.settings_tree.setMinimumWidth(300) self.settings_tree.setParameters(self.settings, showTop=False) self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed) self.settings.child('data_dimensions', 'probe_data').sigActivated.connect( self.get_det_data_list) self.settings.child('actuators_positions', 'test_actuator').sigActivated.connect( self.test_move_actuators) self._detectors = [] self._actuators = [] self.grab_done_signals = [] self.det_commands_signal = [] self.set_actuators(actuators, selected_actuators) self.set_detectors(detectors, selected_detectors) @classmethod def get_names(cls, modules): if not hasattr(modules, '__iter__'): modules = [modules] return [mod.title for mod in modules] def get_mods_from_names(self, names, mod='det'): mods = [] for name in names: d = self.get_mod_from_name(name, mod) if d is not None: mods.append(d) return mods def get_mod_from_name(self, name, mod='det'): if mod == 'det': modules = self._detectors else: modules = self._actuators if name in self.get_names(modules): return modules[self.get_names(modules).index(name)] else: logger.warning(f'No detector with this name: {name}') return None def set_actuators(self, actuators, selected_actuators): self._actuators = actuators self.settings.child('modules', 'actuators').setValue( dict(all_items=self.get_names(actuators), selected=self.get_names(selected_actuators))) def set_detectors(self, detectors, selected_detectors): self._detectors = detectors self.settings.child('modules', 'detectors').setValue( dict(all_items=self.get_names(detectors), selected=self.get_names(selected_detectors))) @property def detectors(self): return self.get_mods_from_names(self.selected_detectors_name) @property def actuators(self): return self.get_mods_from_names(self.selected_actuators_name, mod='act') @property def Ndetectors(self): return len(self.detectors) @property def Nactuators(self): return len(self.actuators) @property def detectors_name(self): return self.settings.child('modules', 'detectors').value()['all_items'] @property def selected_detectors_name(self): return self.settings.child('modules', 'detectors').value()['selected'] @property def actuators_name(self): return self.settings.child('modules', 'actuators').value()['all_items'] @property def selected_actuators_name(self): return self.settings.child('modules', 'actuators').value()['selected'] def parameter_tree_changed(self, param, changes): """ Check for changes in the given (parameter,change,information) tuple list. In case of value changed, update the DAQscan_settings tree consequently. =============== ============================================ ============================== **Parameters** **Type** **Description** *param* instance of pyqtgraph parameter the parameter to be checked *changes* (parameter,change,information) tuple list the current changes state =============== ============================================ ============================== """ for param, change, data in changes: path = self.settings.childPath(param) if change == 'childAdded': pass elif change == 'value': if param.name() == 'detectors': self.detectors_changed.emit(data['selected']) elif param.name() == 'actuators': self.actuators_changed.emit(data['selected']) elif change == 'parent': pass def get_det_data_list(self): self.connect_detectors() datas = self.grab_datas() data_list0D = [] data_list1D = [] data_list2D = [] data_listND = [] for k in datas.keys(): if 'data0D' in datas[k].keys(): data_list0D.extend( [f'{k}/{name}' for name in datas[k]['data0D'].keys()]) if 'data1D' in datas[k].keys(): data_list1D.extend( [f'{k}/{name}' for name in datas[k]['data1D'].keys()]) if 'data2D' in datas[k].keys(): data_list2D.extend( [f'{k}/{name}' for name in datas[k]['data2D'].keys()]) if 'dataND' in datas[k].keys(): data_listND.extend( [f'{k}/{name}' for name in datas[k]['dataND'].keys()]) self.settings.child('data_dimensions', 'det_data_list0D').setValue( dict(all_items=data_list0D, selected=[])) self.settings.child('data_dimensions', 'det_data_list1D').setValue( dict(all_items=data_list1D, selected=[])) self.settings.child('data_dimensions', 'det_data_list2D').setValue( dict(all_items=data_list2D, selected=[])) self.settings.child('data_dimensions', 'det_data_listND').setValue( dict(all_items=data_listND, selected=[])) self.connect_detectors(False) def get_selected_probed_data(self, dim='0D'): return self.settings.child( 'data_dimensions', f'det_data_list{dim.upper()}').value()['selected'] def grab_datas(self, **kwargs): self.det_done_datas = OrderedDict() self.det_done_flag = False self.settings.child(('det_done')).setValue(self.det_done_flag) tzero = time.perf_counter() for sig in [mod.command_detector for mod in self.detectors]: sig.emit(utils.ThreadCommand("single", [1, kwargs])) while not self.det_done_flag: #wait for grab done signals to end QtWidgets.QApplication.processEvents() if time.perf_counter() - tzero > self.timeout: self.timeout_signal.emit(True) logger.error( 'Timeout Fired during waiting for data to be acquired') break self.det_done_signal.emit(self.det_done_datas) return self.det_done_datas def connect_actuators(self, connect=True, slot=None): if slot is None: slot = self.move_done if connect: for sig in [mod.move_done_signal for mod in self.actuators]: sig.connect(slot) else: try: for sig in [mod.move_done_signal for mod in self.actuators]: sig.disconnect(slot) except Exception as e: logger.error(str(e)) def connect_detectors(self, connect=True, slot=None): if slot is None: slot = self.det_done if connect: for sig in [mod.grab_done_signal for mod in self.detectors]: sig.connect(slot) else: try: for sig in [mod.grab_done_signal for mod in self.detectors]: sig.disconnect(slot) except Exception as e: logger.error(str(e)) def test_move_actuators(self): positions = dict() for act in self.get_names(self.actuators): pos, done = QtWidgets.QInputDialog.getDouble( None, f'Enter a target position for actuator {act}', 'Position:') if not done: pos = 0. positions[act] = pos self.connect_actuators() positions = self.move_actuators(positions) self.settings.child('actuators_positions', 'positions_list').setValue( dict(all_items=[f'{k}: {positions[k]}' for k in positions], selected=[])) self.connect_actuators(False) def move_actuators(self, positions): self.move_done_positions = OrderedDict() self.move_done_flag = False self.settings.child(('move_done')).setValue(self.move_done_flag) if not hasattr(positions, '__iter__'): positions = [positions] if len(positions) == self.Nactuators: if isinstance(positions, dict): for k in positions: act = self.get_mod_from_name(k, 'act') if act is not None: act.command_stage.emit( utils.ThreadCommand(command="move_Abs", attributes=[positions[k]])) else: for ind, act in enumerate(self.actuators): act.command_stage.emit( utils.ThreadCommand(command="move_Abs", attributes=[positions[ind]])) else: logger.error( 'Invalid number of positions compared to selected actuators') return self.move_done_positions tzero = time.perf_counter() while not self.move_done_flag: QtWidgets.QApplication.processEvents() if time.perf_counter() - tzero > self.timeout: self.timeout_signal.emit(True) logger.error( 'Timeout Fired during waiting for data to be acquired') break self.move_done_signal.emit(self.move_done_positions) return self.move_done_positions def order_positions(self, positions_as_dict): actuators = self.selected_actuators_name pos = [] for act in actuators: pos.append(positions_as_dict[act]) return pos pyqtSlot(str, float) def move_done(self, name, position): """ """ try: if name not in list(self.move_done_positions.keys()): self.move_done_positions[name] = position if len(self.move_done_positions.items()) == len(self.actuators): self.move_done_flag = True self.settings.child( ('move_done')).setValue(self.move_done_flag) except Exception as e: logger.exception(str(e)) @pyqtSlot(OrderedDict) def det_done(self, data): try: if data['name'] not in list(self.det_done_datas.keys()): self.det_done_datas[data['name']] = data if len(self.det_done_datas.items()) == len(self.detectors): self.det_done_flag = True self.settings.child(('det_done')).setValue(self.det_done_flag) except Exception as e: logger.exception(str(e))
class StuffRepositoryModule(QWidget, Ui_Form): def __init__(self, parent=None): super(StuffRepositoryModule, self).__init__(parent) self.setupUi(self) if '41' not in user.powers: self.close() if user.powers['41'] == 0: self.close() self.power = '{:03b}'.format(user.powers['41']) self.WC = WarehouseController() self.CI = CheckItem() self.LC = LabrecordsController() self.SFC = StuffController() self.current_button = self.radioButton_batchno self.get_stuff_list() def get_stuff_list(self): if self.current_button == self.radioButton_batchno: values_tuple = VALUES_TUPLE_BATCHNO self.treeWidget_stuffbatchnolist.setVisible(True) self.treeWidget_stuffkindlist.setVisible(False) current_tree = self.treeWidget_stuffbatchnolist current_tree.hideColumn(0) current_tree.hideColumn(1) elif self.current_button == self.radioButton_kind: values_tuple = VALUES_TUPLE_KIND self.treeWidget_stuffbatchnolist.setVisible(False) self.treeWidget_stuffkindlist.setVisible(True) current_tree = self.treeWidget_stuffkindlist else: return current_tree.clear() index = self.tabWidget.currentIndex() key_dict = {'amount__gt': 0} if index != 0: key_dict['stufftype'] = index - 1 stuff_list = self.WC.get_stuffrepository(False, *values_tuple, **key_dict) if not len(stuff_list): return if current_tree == self.treeWidget_stuffbatchnolist: self.set_batchno_tree(current_tree, stuff_list) for i in range(2, 25): current_tree.resizeColumnToContents(i) elif current_tree == self.treeWidget_stuffkindlist: self.set_kind_tree(current_tree, stuff_list) for i in range(0, 3): current_tree.resizeColumnToContents(i) else: return def set_batchno_tree(self, current_tree, stuff_list): for item in stuff_list: qtreeitem = QTreeWidgetItem(current_tree) qtreeitem.setText(0, str(item['autoid'])) qtreeitem.setText(1, str(item['lrid'])) qtreeitem.setText(2, STATUS[item['status']]) qtreeitem.setText(3, item['stuffid'] + ' ' + item['stuffname']) qtreeitem.setText(4, item['stuffkind']) qtreeitem.setText(5, STUFF_KIND[item['stufftype']]) qtreeitem.setText(6, item['batchno']) qtreeitem.setText(7, item['mbatchno']) qtreeitem.setText(8, item['spec']) qtreeitem.setText(9, item['package']) qtreeitem.setText(10, str(item['piamount'])) qtreeitem.setText(11, str(item['amount'])) qtreeitem.setText(12, item['basicunit']) qtreeitem.setText(13, item['position']) qtreeitem.setText(14, str(item['makedate'])) qtreeitem.setText(15, str(item['putindate'])) qtreeitem.setText(16, str(item['expireddate'])) qtreeitem.setText(17, str(item['nextcheckdate'])) qtreeitem.setText(18, item['supid'] + ' ' + item['supname']) qtreeitem.setText(19, item['producer']) qtreeitem.setText(20, str(item['content']) + item['cunit']) qtreeitem.setText(21, str(item['water']) + '%') qtreeitem.setText(22, str(item['rdensity'])) qtreeitem.setText(23, str(item['impurity']) + '%') qtreeitem.setText( 24, item['warehousemanid'] + item['warehousemanname']) def set_kind_tree(self, current_tree, stuff_list): kind_list = stuff_list.annotate(amount=Sum('amount'), piamount=Sum('piamount')) for item in kind_list: qtreeitem = QTreeWidgetItem(current_tree) qtreeitem.setText(0, item['stuffkind']) qtreeitem.setText(1, str(item['piamount'])) qtreeitem.setText(2, str(item['amount'])) qtreeitem.setText(3, item['basicunit']) @pyqtSlot(int) def on_tabWidget_currentChanged(self, p_int): curent_tab = getattr(self, 'tab_' + str(p_int)) curent_tab.setLayout(self.gridLayout_2) self.get_stuff_list() pyqtSlot(bool) def on_radioButton_batchno_toggled(self, p_bool): if p_bool: self.current_button = self.radioButton_batchno self.get_stuff_list() pyqtSlot(bool) def on_radioButton_kind_toggled(self, p_bool): if p_bool: self.current_button = self.radioButton_kind self.get_stuff_list() @pyqtSlot(QPoint) def on_treeWidget_stuffbatchnolist_customContextMenuRequested(self, pos): if self.power[1] == '0': return id = 0 lrid = 0 stuffid = '' batchno = '' sender_widget = self.sender() current_item = sender_widget.currentItem() if current_item is None: return id = int(current_item.text(0)) lrid = int(current_item.text(1)) stuffid, stuffname = current_item.text(3).split(' ') batchno = current_item.text(6) menu = QMenu() button1 = menu.addAction("修改记录") button2 = menu.addAction("查看检验报告") button3 = menu.addAction("新建库存复检申请单") global_pos = sender_widget.mapToGlobal(pos) action = menu.exec(global_pos) if action == button1: detail = ModifyStuffParmeter(id, self) detail.accepted.connect(self.get_stuff_list) detail.show() elif action == button2: detail = FindCheckReportModule(stuffid, batchno, self) detail.show() elif action == button3: key_dict = {'stuffid': stuffid, 'stuffname': stuffname} checkunit = '' res = self.SFC.get_stuffdict(True, *VALUES_TUPLE_SD, **key_dict) if len(res): checkunit = res[0] kwargs = { 'labtype': 1, 'chkid': stuffid, 'chkname': stuffname, 'batchno': current_item.text(6), 'mbatchno': current_item.text(7), 'spec': current_item.text(8), 'package': current_item.text(9), 'producer': current_item.text(19), 'supplyer': current_item.text(18) if current_item.text(18) in ('', ' ') else current_item.text(18).split(' ')[2], 'ciid': int(current_item.text(0)), 'createdate': user.now_date, 'checkamount': decimal.Decimal(current_item.text(11)), 'caunit': current_item.text(12), 'sampleunit': checkunit, 'samplesource': current_item.text(13) } labrecord = self.LC.update_labrecord(**kwargs) key_dict_checkitem = {'stuffid': stuffid, 'itemtype': 0} checkitems = self.CI.get_checkitems(False, *VALUES_TUPLE_CHECKITEM, **key_dict_checkitem) for item in checkitems: kwargs_checkitem = { 'lrid': labrecord.autoid, 'seqid': item['seqid'], 'itemname': item['itemname'], 'kind': item['kind'], 'referencevalue': item['referencevalue'], 'labvalue': item['referencevalue'], 'putintype': item['putintype'], 'startdate': user.now_date, 'enddate': user.now_date, 'checked': 2 } self.LC.update_labitem(**kwargs_checkitem) detail = ApplycheckModule(autoid=labrecord.autoid, parent=self) detail.rejected.connect( lambda: self.delete_check_report(labrecord.autoid)) detail.show() def delete_check_report(self, lrid): self.LC.delete_labrecord(lrid) self.LC.delete_labitem(lrid) @pyqtSlot(QTreeWidgetItem, int) def on_treeWidget_stuffbatchnolist_itemDoubleClicked( self, qtreeitem, p_int): if self.power[1] == '0': return id = int(qtreeitem.text(0)) lrid = int(qtreeitem.text(1)) detail = ModifyStuffParmeter(id, self) detail.accepted.connect(self.get_stuff_list) detail.show()
class DAQ_PID(QObject): """ """ log_signal = pyqtSignal(str) #look for eventual model files command_pid = pyqtSignal(ThreadCommand) command_stage = pyqtSignal(ThreadCommand) move_done_signal = pyqtSignal(str, float) models = [] try: model_mod = importlib.import_module('pymodaq_pid_models') for ind_file, entry in enumerate(os.scandir(os.path.join(model_mod.__path__[0], 'models'))): if not entry.is_dir() and entry.name != '__init__.py': try: file, ext = os.path.splitext(entry.name) importlib.import_module('.'+file, model_mod.__name__+'.models') models.append(file) except Exception as e: print(e) if 'PIDModelMock' in models: mods = models mods.pop(models.index('PIDModelMock')) models = ['PIDModelMock'] models.extend(mods) except Exception as e: print(e) if len(models) == 0: logger.warning('No valid installed models') def __init__(self,area, detector_modules = [], actuator_modules =[]): QLocale.setDefault(QLocale(QLocale.English, QLocale.UnitedStates)) super(DAQ_PID,self).__init__() self.settings = Parameter.create(title='PID settings', name='pid_settings', type='group', children=params) self.title = 'PyMoDAQ PID' self.Initialized_state = False self.model_class = None self.detector_modules = detector_modules self.actuator_modules = actuator_modules self.dock_area = area self.overshoot = None self.check_moving = False self.preset_manager = PresetManager() self.setupUI() self.command_stage.connect(self.move_Abs) #to be compatible with actuator modules within daq scan self.enable_controls_pid(False) self.enable_controls_pid_run(False) def ini_PID(self): if self.ini_PID_action.isChecked(): output_limits =[None,None] if self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_min_enabled').value(): output_limits[0] = self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_min').value() if self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_max_enabled').value(): output_limits[1] = self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_max').value() self.PIDThread = QThread() pid_runner = PIDRunner(self.model_class, [mod.move_done_signal for mod in self.actuator_modules], [mod.grab_done_signal for mod in self.detector_modules], [mod.command_stage for mod in self.actuator_modules], [mod.command_detector for mod in self.detector_modules], dict(Kp=self.settings.child('main_settings', 'pid_controls', 'pid_constants', 'kp').value(), Ki=self.settings.child('main_settings', 'pid_controls', 'pid_constants', 'ki').value(), Kd=self.settings.child('main_settings', 'pid_controls', 'pid_constants', 'kd').value(), setpoint=self.settings.child('main_settings', 'pid_controls', 'set_point').value(), sample_time=self.settings.child('main_settings', 'pid_controls', 'sample_time').value()/1000, output_limits=output_limits, auto_mode=False), filter=dict(enable=self.settings.child('main_settings', 'pid_controls', 'filter', 'filter_enable').value(), value=self.settings.child('main_settings', 'pid_controls', 'filter', 'filter_step').value()), det_averaging=[mod.settings.child('main_settings', 'Naverage').value() for mod in self.detector_modules], ) self.PIDThread.pid_runner = pid_runner pid_runner.pid_output_signal.connect(self.process_output) pid_runner.status_sig.connect(self.thread_status) self.command_pid.connect(pid_runner.queue_command) pid_runner.moveToThread(self.PIDThread) self.PIDThread.start() self.pid_led.set_as_true() self.enable_controls_pid_run(True) else: if hasattr(self,'PIDThread'): if self.PIDThread.isRunning(): try: self.PIDThread.quit() except: pass self.pid_led.set_as_false() self.enable_controls_pid_run(False) self.Initialized_state = True pyqtSlot(dict) def process_output(self, datas): self.output_viewer.show_data([[dat] for dat in datas['output']]) self.input_viewer.show_data([[dat] for dat in datas['input']]) self.currpoint_sb.setValue(np.mean(datas['input'])) if self.check_moving: if np.abs(np.mean(datas['input'])-self.settings.child('main_settings', 'pid_controls', 'set_point').value()) < \ self.settings.child('main_settings', 'epsilon').value(): self.move_done_signal.emit(self.title, np.mean(datas['input'])) self.check_moving = False print('Move from {:s} is done: {:f}'.format('PID', np.mean(datas['input']))) @pyqtSlot(ThreadCommand) def move_Abs(self, command=ThreadCommand()): """ """ if command.command == "move_Abs": self.check_moving = True self.setpoint_sb.setValue(command.attributes[0]) QtWidgets.QApplication.processEvents() def enable_controls_pid(self,enable = False): self.ini_PID_action.setEnabled(enable) self.setpoint_sb.setOpts(enabled = enable) def enable_controls_pid_run(self,enable = False): self.run_action.setEnabled(enable) self.pause_action.setEnabled(enable) def setupUI(self): self.dock_pid = Dock('PID controller', self.dock_area) self.dock_area.addDock(self.dock_pid) #%% create logger dock self.logger_dock=Dock("Logger") self.logger_list=QtWidgets.QListWidget() self.logger_list.setMinimumWidth(300) self.logger_dock.addWidget(self.logger_list) self.dock_area.addDock(self.logger_dock,'right') self.logger_dock.setVisible(True) widget = QtWidgets.QWidget() widget_toolbar = QtWidgets.QWidget() verlayout = QtWidgets.QVBoxLayout() widget.setLayout(verlayout) toolbar_layout = QtWidgets.QGridLayout() widget_toolbar.setLayout(toolbar_layout) iconquit = QtGui.QIcon() iconquit.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/close2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.quit_action = QtWidgets.QPushButton(iconquit, "Quit") self.quit_action.setToolTip('Quit the application') toolbar_layout.addWidget(self.quit_action,0,0,1,2) self.quit_action.clicked.connect(self.quit_fun) iconini = QtGui.QIcon() iconini.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/ini.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ini_model_action = QtWidgets.QPushButton(iconini, "Init Model") self.ini_model_action.setToolTip('Initialize the chosen model') toolbar_layout.addWidget(self.ini_model_action,2,0) self.ini_model_action.clicked.connect(self.ini_model) self.model_led = QLED() toolbar_layout.addWidget(self.model_led, 2,1) self.ini_PID_action = QtWidgets.QPushButton(iconini, "Init PID") self.ini_PID_action.setToolTip('Initialize the PID loop') toolbar_layout.addWidget(self.ini_PID_action,2,2) self.ini_PID_action.setCheckable(True) self.ini_PID_action.clicked.connect(self.ini_PID) self.pid_led = QLED() toolbar_layout.addWidget(self.pid_led, 2,3) self.iconrun = QtGui.QIcon() self.iconrun.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/run2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.icon_stop = QtGui.QIcon() self.icon_stop.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/stop.png")) self.run_action = QtWidgets.QPushButton(self.iconrun, "", None) self.run_action.setToolTip('Start PID loop') self.run_action.setCheckable(True) toolbar_layout.addWidget(self.run_action,0,2) self.run_action.clicked.connect(self.run_PID) iconpause = QtGui.QIcon() iconpause.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/pause.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.pause_action = QtWidgets.QPushButton(iconpause, "", None) self.pause_action.setToolTip('Pause PID') self.pause_action.setCheckable(True) toolbar_layout.addWidget(self.pause_action,0,3) self.pause_action.setChecked(True) self.pause_action.clicked.connect(self.pause_PID) lab = QtWidgets.QLabel('Set Point:') toolbar_layout.addWidget(lab, 3,0,1,2) self.setpoint_sb = custom_tree.SpinBoxCustom() self.setpoint_sb.setMinimumHeight(40) font = self.setpoint_sb.font() font.setPointSizeF(20) self.setpoint_sb.setFont(font) self.setpoint_sb.setDecimals(6) toolbar_layout.addWidget(self.setpoint_sb,3,2,1,2) self.setpoint_sb.valueChanged.connect(self.settings.child('main_settings', 'pid_controls', 'set_point').setValue) lab1 = QtWidgets.QLabel('Current Point:') toolbar_layout.addWidget(lab1, 4,0,1,2) self.currpoint_sb = custom_tree.SpinBoxCustom() self.currpoint_sb.setMinimumHeight(40) self.currpoint_sb.setReadOnly(True) self.currpoint_sb.setDecimals(6) self.currpoint_sb.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) font = self.currpoint_sb.font() font.setPointSizeF(20) self.currpoint_sb.setFont(font) toolbar_layout.addWidget(self.currpoint_sb,4,2,1,2) #create main parameter tree self.settings_tree = ParameterTree() self.settings_tree.setParameters(self.settings, showTop=False) verlayout.addWidget(widget_toolbar) verlayout.addWidget(self.settings_tree) self.dock_output = Dock('PID output') widget_output = QtWidgets.QWidget() self.output_viewer = Viewer0D(widget_output) self.dock_output.addWidget(widget_output) self.dock_area.addDock(self.dock_output, 'right') self.dock_input = Dock('PID input') widget_input = QtWidgets.QWidget() self.input_viewer = Viewer0D(widget_input) self.dock_input.addWidget(widget_input) self.dock_area.addDock(self.dock_input, 'bottom',self.dock_output) if len(self.models) != 0: self.get_set_model_params(self.models[0]) #connecting from tree self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed)#any changes on the settings will update accordingly the detector self.dock_pid.addWidget(widget) def get_set_model_params(self, model_file): self.settings.child('models', 'model_params').clearChildren() model = importlib.import_module('.' + model_file, self.model_mod.__name__+'.models') model_class = getattr(model, model_file) params = getattr(model_class, 'params') self.settings.child('models', 'model_params').addChildren(params) def run_PID(self): if self.run_action.isChecked(): self.run_action.setIcon(self.icon_stop) self.command_pid.emit(ThreadCommand('start_PID', [self.model_class.curr_input])) QtWidgets.QApplication.processEvents() QtWidgets.QApplication.processEvents() self.command_pid.emit(ThreadCommand('run_PID', [self.model_class.curr_output])) else: self.run_action.setIcon(self.iconrun) self.command_pid.emit(ThreadCommand('stop_PID')) QtWidgets.QApplication.processEvents() def pause_PID(self): self.command_pid.emit(ThreadCommand('pause_PID', [self.pause_action.isChecked()])) def update_status(self,txt,log_type=None): """ Show the txt message in the status bar with a delay of wait_time ms. =============== =========== ======================= **Parameters** **Type** **Description** *txt* string The message to show *wait_time* int the delay of showing *log_type* string the type of the log =============== =========== ======================= """ try: if log_type is not None: self.log_signal.emit(txt) logging.info(txt) except Exception as e: pass @pyqtSlot(str) def add_log(self,txt): """ Add the QListWisgetItem initialized with txt informations to the User Interface logger_list and to the save_parameters.logger array. =============== =========== ====================== **Parameters** **Type** **Description** *txt* string the log info to add. =============== =========== ====================== """ try: now=datetime.datetime.now() new_item=QtWidgets.QListWidgetItem(now.strftime('%Y/%m/%d %H:%M:%S')+": "+txt) self.logger_list.addItem(new_item) except: pass def set_file_preset(self,model): """ Set a file managers from the converted xml file given by the filename parameter. =============== =========== =================================================== **Parameters** **Type** **Description** *filename* string the name of the xml file to be converted/treated =============== =========== =================================================== Returns ------- (Object list, Object list) tuple The updated (Move modules list, Detector modules list). See Also -------- custom_tree.XML_file_to_parameter, set_param_from_param, stop_moves, update_status,DAQ_Move_main.daq_move, DAQ_viewer_main.daq_viewer """ filename = os.path.join(get_set_pid_path(), model + '.xml') self.preset_file = filename self.preset_manager.set_file_preset(filename, show=False) self.move_docks = [] self.det_docks_settings = [] self.det_docks_viewer = [] move_forms = [] actuator_modules = [] detector_modules = [] move_types = [] ################################################################# ###### sort plugins by IDs and within the same IDs by Master and Slave status plugins=[{'type': 'move', 'value': child} for child in self.preset_manager.preset_params.child(('Moves')).children()]+[{'type': 'det', 'value': child} for child in self.preset_manager.preset_params.child(('Detectors')).children()] for plug in plugins: plug['ID']=plug['value'].child('params','main_settings','controller_ID').value() if plug["type"]=='det': plug['status']=plug['value'].child('params','detector_settings','controller_status').value() else: plug['status']=plug['value'].child('params','move_settings', 'multiaxes', 'multi_status').value() IDs=list(set([plug['ID'] for plug in plugins])) #%% plugins_sorted=[] for id in IDs: plug_Ids=[] for plug in plugins: if plug['ID']==id: plug_Ids.append(plug) plug_Ids.sort(key=lambda status: status['status']) plugins_sorted.append(plug_Ids) ################################################################# ####################### ind_move=-1 ind_det=-1 for plug_IDs in plugins_sorted: for ind_plugin, plugin in enumerate(plug_IDs): plug_name=plugin['value'].child(('name')).value() plug_init=plugin['value'].child(('init')).value() plug_settings=plugin['value'].child(('params')) if plugin['type'] == 'move': ind_move+=1 plug_type=plug_settings.child('main_settings','move_type').value() self.move_docks.append(Dock(plug_name, size=(150,250))) if ind_move==0: self.dock_area.addDock(self.move_docks[-1], 'top',self.logger_dock) else: self.dock_area.addDock(self.move_docks[-1], 'above',self.move_docks[-2]) move_forms.append(QtWidgets.QWidget()) mov_mod_tmp=DAQ_Move(move_forms[-1],plug_name) mov_mod_tmp.ui.Stage_type_combo.setCurrentText(plug_type) mov_mod_tmp.ui.Quit_pb.setEnabled(False) QtWidgets.QApplication.processEvents() set_param_from_param(mov_mod_tmp.settings,plug_settings) QtWidgets.QApplication.processEvents() mov_mod_tmp.bounds_signal[bool].connect(self.stop_moves) self.move_docks[-1].addWidget(move_forms[-1]) actuator_modules.append(mov_mod_tmp) try: if ind_plugin==0: #should be a master type plugin if plugin['status']!="Master": raise Exception('error in the master/slave type for plugin {}'.format(plug_name)) if plug_init: actuator_modules[-1].ui.IniStage_pb.click() QtWidgets.QApplication.processEvents() if 'Mock' in plug_type: QThread.msleep(500) else: QThread.msleep(4000) # to let enough time for real hardware to init properly QtWidgets.QApplication.processEvents() master_controller=actuator_modules[-1].controller else: if plugin['status']!="Slave": raise Exception('error in the master/slave type for plugin {}'.format(plug_name)) if plug_init: actuator_modules[-1].controller=master_controller actuator_modules[-1].ui.IniStage_pb.click() QtWidgets.QApplication.processEvents() if 'Mock' in plug_type: QThread.msleep(500) else: QThread.msleep(4000) # to let enough time for real hardware to init properly QtWidgets.QApplication.processEvents() except Exception as e: self.update_status(getLineInfo()+ str(e),'log') else: ind_det+=1 plug_type=plug_settings.child('main_settings','DAQ_type').value() plug_subtype=plug_settings.child('main_settings','detector_type').value() self.det_docks_settings.append(Dock(plug_name+" settings", size=(150,250))) self.det_docks_viewer.append(Dock(plug_name+" viewer", size=(350,350))) if ind_det==0: self.logger_dock.area.addDock(self.det_docks_settings[-1], 'bottom', self.dock_input) #dock_area of the logger dock else: self.dock_area.addDock(self.det_docks_settings[-1], 'bottom',self.det_docks_settings[-2]) self.dock_area.addDock(self.det_docks_viewer[-1],'right',self.det_docks_settings[-1]) det_mod_tmp=DAQ_Viewer(self.dock_area,dock_settings=self.det_docks_settings[-1], dock_viewer=self.det_docks_viewer[-1],title=plug_name, DAQ_type=plug_type, parent_scan=self) detector_modules.append(det_mod_tmp) detector_modules[-1].ui.Detector_type_combo.setCurrentText(plug_subtype) detector_modules[-1].ui.Quit_pb.setEnabled(False) set_param_from_param(det_mod_tmp.settings,plug_settings) QtWidgets.QApplication.processEvents() try: if ind_plugin==0: #should be a master type plugin if plugin['status']!="Master": raise Exception('error in the master/slave type for plugin {}'.format(plug_name)) if plug_init: detector_modules[-1].ui.IniDet_pb.click() QtWidgets.QApplication.processEvents() if 'Mock' in plug_subtype: QThread.msleep(500) else: QThread.msleep(4000) # to let enough time for real hardware to init properly QtWidgets.QApplication.processEvents() master_controller=detector_modules[-1].controller else: if plugin['status']!="Slave": raise Exception('error in the master/slave type for plugin {}'.format(plug_name)) if plug_init: detector_modules[-1].controller=master_controller detector_modules[-1].ui.IniDet_pb.click() QtWidgets.QApplication.processEvents() if 'Mock' in plug_subtype: QThread.msleep(500) else: QThread.msleep(4000) # to let enough time for real hardware to init properly QtWidgets.QApplication.processEvents() except Exception as e: self.update_status(getLineInfo()+ str(e),'log') detector_modules[-1].settings.child('main_settings','overshoot').show() detector_modules[-1].overshoot_signal[bool].connect(self.stop_moves) QtWidgets.QApplication.processEvents() return actuator_modules,detector_modules pyqtSlot(bool) def stop_moves(self,overshoot): """ Foreach module of the move module object list, stop motion. See Also -------- stop_scan, DAQ_Move_main.daq_move.stop_Motion """ self.overshoot = overshoot for mod in self.actuator_modules: mod.stop_Motion() def set_default_preset(self): actuators = self.model_class.actuators actuator_names = self.model_class.actuators_name detectors_type = self.model_class.detectors_type detectors = self.model_class.detectors detectors_name = self.model_class.detectors_name detector_modules = [] for ind_det, det in enumerate(detectors): detector_modules.append(DAQ_Viewer(area, title=detectors_name[ind_det], DAQ_type=detectors_type[ind_det])) #self.detector_modules[-1].ui.IniDet_pb.click() QtWidgets.QApplication.processEvents() detector_modules[-1].ui.Detector_type_combo.setCurrentText(detectors[ind_det]) detector_modules[-1].ui.Quit_pb.setEnabled(False) self.dock_area.addDock(self.dock_output, 'bottom') self.dock_area.moveDock(self.dock_input, 'bottom', self.dock_output) self.dock_area.addDock(self.dock_pid, 'left') dock_moves = [] actuator_modules = [] for ind_act, act in enumerate(actuators): form = QtWidgets.QWidget() dock_moves.append(Dock(actuator_names[ind_act])) area.addDock(dock_moves[-1], 'bottom', self.dock_pid) dock_moves[-1].addWidget(form) actuator_modules.append(DAQ_Move(form)) QtWidgets.QApplication.processEvents() actuator_modules[-1].ui.Stage_type_combo.setCurrentText(actuators[ind_act]) actuator_modules[-1].ui.Quit_pb.setEnabled(False) #self.actuator_modules[-1].ui.IniStage_pb.click() #QThread.msleep(1000) QtWidgets.QApplication.processEvents() return actuator_modules, detector_modules def ini_model(self): try: model_name = self.settings.child('models', 'model_class').value() model = importlib.import_module('.' +model_name, self.model_mod.__name__+'.models') self.model_class = getattr(model, model_name)(self) #try to get corresponding managers file filename = os.path.join(get_set_pid_path(), model_name + '.xml') if os.path.isfile(filename): self.actuator_modules, self.detector_modules = self.set_file_preset(model_name) else: self.actuator_modules, self.detector_modules = self.set_default_preset() # # connecting to logger # for mov in self.actuator_modules: # mov.log_signal[str].connect(self.add_log) # for det in self.detector_modules: # det.log_signal[str].connect(self.add_log) # self.log_signal[str].connect(self.add_log) self.model_class.ini_model() self.enable_controls_pid(True) self.model_led.set_as_true() self.ini_model_action.setEnabled(False) except Exception as e: self.update_status(getLineInfo() + str(e), log_type='log') def quit_fun(self): """ """ try: try: self.PIDThread.exit() except Exception as e: print(e) for module in self.actuator_modules: try: module.quit_fun() QtWidgets.QApplication.processEvents() QThread.msleep(1000) QtWidgets.QApplication.processEvents() except Exception as e: print(e) for module in self.detector_modules: try: module.stop_all() QtWidgets.QApplication.processEvents() module.quit_fun() QtWidgets.QApplication.processEvents() QThread.msleep(1000) QtWidgets.QApplication.processEvents() except Exception as e: print(e) areas=self.dock_area.tempAreas[:] for area in areas: area.win.close() QtWidgets.QApplication.processEvents() QThread.msleep(1000) QtWidgets.QApplication.processEvents() self.dock_area.parent().close() except Exception as e: print(e) def parameter_tree_changed(self,param,changes): """ Foreach value changed, update : * Viewer in case of **DAQ_type** parameter name * visibility of button in case of **show_averaging** parameter name * visibility of naverage in case of **live_averaging** parameter name * scale of axis **else** (in 2D pymodaq type) Once done emit the update settings signal to link the commit. =============== =================================== ================================================================ **Parameters** **Type** **Description** *param* instance of ppyqtgraph parameter the parameter to be checked *changes* tuple list Contain the (param,changes,info) list listing the changes made =============== =================================== ================================================================ See Also -------- change_viewer, daq_utils.custom_parameter_tree.iter_children """ for param, change, data in changes: path = self.settings.childPath(param) if change == 'childAdded': pass elif change == 'value': if param.name() == 'model_class': self.get_set_model_params(param.value()) elif param.name() == 'module_settings': if param.value(): self.settings.sigTreeStateChanged.disconnect( self.parameter_tree_changed) param.setValue(False) self.settings.sigTreeStateChanged.connect( self.parameter_tree_changed) self.preset_manager.set_PID_preset(self.settings.child('models','model_class').value()) elif param.name() == 'refresh_plot_time' or param.name() == 'timeout': self.command_pid.emit(ThreadCommand('update_timer', [param.name(),param.value()])) elif param.name() == 'set_point': if self.pid_led.state: self.command_pid.emit(ThreadCommand('update_options', dict(setpoint=param.value()))) else: output = self.model_class.convert_output(param.value(),0, stab=False) for ind_act, act in enumerate(self.actuator_modules): act.move_Abs(output[ind_act]) elif param.name() == 'sample_time': self.command_pid.emit(ThreadCommand('update_options', dict(sample_time=param.value()))) elif param.name() in custom_tree.iter_children(self.settings.child('main_settings', 'pid_controls', 'output_limits'), []): output_limits = [None, None] if self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_min_enabled').value(): output_limits[0] = self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_min').value() if self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_max_enabled').value(): output_limits[1] = self.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_max').value() self.command_pid.emit(ThreadCommand('update_options', dict(output_limits=output_limits))) elif param.name() in custom_tree.iter_children(self.settings.child('main_settings', 'pid_controls', 'filter'), []): self.command_pid.emit(ThreadCommand('update_filter', [dict(enable=self.settings.child('main_settings', 'pid_controls', 'filter', 'filter_enable').value(), value=self.settings.child('main_settings', 'pid_controls', 'filter', 'filter_step').value())])) elif param.name() in custom_tree.iter_children(self.settings.child('main_settings', 'pid_controls', 'pid_constants'), []): Kp = self.settings.child('main_settings', 'pid_controls', 'pid_constants', 'kp').value() Ki = self.settings.child('main_settings', 'pid_controls', 'pid_constants', 'ki').value() Kd = self.settings.child('main_settings', 'pid_controls', 'pid_constants', 'kd').value() self.command_pid.emit(ThreadCommand('update_options', dict(tunings= (Kp, Ki, Kd)))) elif param.name() in custom_tree.iter_children(self.settings.child('models', 'model_params'),[]): self.model_class.update_settings(param) elif param.name() == 'detector_modules': self.model_class.update_detector_names() elif change == 'parent': pass @pyqtSlot(list) def thread_status(self,status): # general function to get datas/infos from all threads back to the main """ | General function to get datas/infos from all threads back to the main. | Switch the status with : * *"Update status"* : Update the status bar with the status attribute txt message """ if status[0]=="Update_Status": self.update_status(status[1],log_type=status[2])
class ShowImage(QMainWindow): def __init__(self): super(ShowImage,self).__init__() loadUi('latihan.ui',self) self.image=None self.loadButton.clicked.connect(self.loadClicked) self.saveButton.clicked.connect(self.saveClicked) self.grayButton.clicked.connect(self.grayClicked) self.actionBrightness.triggered.connect(self.brightClicked) self.actionContrast.triggered.connect(self.contrastClicked) self.actionContrastScretch.triggered.connect(self.scretchClicked) self.actionNegative.triggered.connect(self.negativeClicked) self.actionBiner.triggered.connect(self.binerClicked) self.actiongrayHistogram.triggered.connect(self.grayHistogramClicked) self.actionRGBHistogram.triggered.connect(self.RGBHistogramClicked) self.actionEqualHistogram.triggered.connect(self.EqualHistogramClicked) self.actionTranslasi.triggered.connect(self.TranslasiClicked) self.actionmin45derajat.triggered.connect(self.minus45Derajat) self.actionrot45derajat.triggered.connect(self.rot45Derajat) self.actionmin90derajat.triggered.connect(self.minus90Derajat) self.actionrot90derajat.triggered.connect(self.rot90Derajat) self.actionmin180derajat.triggered.connect(self.minus180Derajat) self.actionrot180derajat.triggered.connect(self.rot180Derajat) self.actionZoomIn.triggered.connect(self.LinearInterpolationClicked) self.actionZoomOut.triggered.connect(self.CubicInterppolationClicked) self.actionSkewedImage.triggered.connect(self.skewedSizeClicked) self.actionCrop.triggered.connect(self.CropClicked) self.actionAritmatika.triggered.connect(self.AritmatikaClicked) self.actionBoolean.triggered.connect(self.BooleanClicked) self.actionFilter.triggered.connect(self.FilteringClicked) self.actionMean.triggered.connect(self.MeanClicked) self.actionGaussian.triggered.connect(self.GaussianClicked) self.actionSharpening.triggered.connect(self.SharpeningClicked) self.actionMedian.triggered.connect(self.MedianClicked) self.actionMax.triggered.connect(self.MaxClicked) self.actionSobel.triggered.connect(self.SobelClicked) self.actionPrewit.triggered.connect(self.PrewitClicked) self.actionRobert.triggered.connect(self.RobertClicked) self.actionLaplace.triggered.connect(self.LaplaceClicked) self.actionLaplaceOfGaussian.triggered.connect(self.LaplaceofGaussianClicked) self.actionCanny.triggered.connect(self.CannyClicked) self.actionDilasi.triggered.connect(self.Dilasi) self.actionErosi.triggered.connect(self.Erosi) self.actionOpening.triggered.connect(self.Opening) self.actionClosing.triggered.connect(self.Closing) self.actionSkeleton.triggered.connect(self.SkeletonClicked) self.actionBinary.triggered.connect(self.Binary) self.actionBinaryInvers.triggered.connect(self.BinaryInvers) self.actionTrunc.triggered.connect(self.Trunc) self.actionToZero.triggered.connect(self.ToZero) self.actionToZeroInvers.triggered.connect(self.ToZeroInvers) self.actionOtsu.triggered.connect(self.otsuClicked) @pyqtSlot() def grayClicked(self): H,W = self.image.shape[:2] gray=np.zeros((H,W),np.uint8) for i in range (H): for j in range (W): gray[i,j]=np.clip(0.07*self.image[i,j,0]+0.72*self.image[i,j,1]+0.21*self.image[i,j,2],0,255) self.image=gray self.displayImage(2) @pyqtSlot() def loadClicked(self): flname,filter=QFileDialog.getOpenFileName(self,'Open File','D:/Foto',"Image Files (*.jpg)") if flname: self.loadImage(flname) else: print('Invalid Image') @pyqtSlot() def saveClicked(self): flname, filter=QFileDialog.getSaveFileName(self,'Save File','D:/',"Image Files (*.jpg)") if flname: cv2.imwrite(flname, self.image) else: print('Error') def loadImage(self,flname): self.image=cv2.imread(flname) self.displayImage(1) def brightClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) brightness = 50 h,w = img.shape[:2] for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) b = a + brightness if b > 255: b = 255 elif b < 0: b = 0 else: b = b img.itemset((i,j), b) self.image = img self.displayImage(2) def contrastClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) h = img.shape[0] w = img.shape[1] contrast = 1.6 for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) b = math.ceil(a * contrast) if b > 255: b = 255 img.itemset((i, j), b) self.image = img self.displayImage(2) def scretchClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) max = 255 min = 0 h, w = img.shape[:2] for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) if a > max: max = a if a < min: min = a for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) b = float(a - min) / (max - min) * 255 img.itemset((i, j), b) self.image = img self.displayImage(2) def negativeClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) h, w = img.shape[:2] max_intensity = 255 for i in range(h): for j in range(w): a = img.item(i, j) b = max_intensity - a img.itemset((i, j), b) self.image = img self.displayImage(2) def binerClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) thres = 100 h, w = img.shape[:2] for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) if a > thres: a = 255 elif a < thres: a = 0 else: a = a img.itemset((i, j), a) self.image = img self.displayImage(2) def grayHistogramClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) self.image = img self.displayImage(2) plt.hist(img.ravel(), 255, [0, 255]) plt.show() def RGBHistogramClicked(self): color = ('b', 'g', 'r') for i, col in enumerate(color): histo = cv2.calcHist([self.image], [i], None, [256], [0, 256]) plt.plot(histo, color=col) plt.xlim([0, 256]) plt.show() def EqualHistogramClicked(self): hist, bins = np.histogram(self.image.flatten(), 256, [0, 256]) cdf = hist.cumsum() cdf_normalized = cdf * hist.max() / cdf.max() cdf_m = np.ma.masked_equal(cdf, 0) cdf_m = (cdf_m - cdf_m.min()) * 255 / (cdf_m.max() - cdf_m.min()) cdf = np.ma.filled(cdf_m, 0).astype('uint8') self.image = cdf[self.image] self.displayImage(2) plt.plot(cdf_normalized, color='b') plt.hist(self.image.flatten(), 256, [0, 256], color='r') plt.xlim([0, 256]) plt.legend(('cdf', 'histogram'), loc='upper left') plt.show() def TranslasiClicked(self): h, w = self.image.shape[:2] quarter_h, quarter_w = h / 4, w / 4 t = np.float32([[1, 0, quarter_w], [0, 1, quarter_h]]) img = cv2.warpAffine(self.image, t, (w, h)) self.image = img self.displayImage(2) def RotasiClicked(self,degree): h, w = self.image.shape[:2] rotationMatrix = cv2.getRotationMatrix2D((w / 2, h / 2), degree, .7) cos = np.abs(rotationMatrix[0, 0]) sin = np.abs(rotationMatrix[0, 1]) nW = int((h * sin) * (w * cos)) nH = int((h * cos) * (w * sin)) rotationMatrix[0, 2] += (nW / 2) - w / 2 rotationMatrix[1, 2] += (nH / 2) - h / 2 rot_image = cv2.warpAffine(self.image, rotationMatrix, (h, w)) self.image = rot_image def minus45Derajat(self): self.RotasiClicked(-45) self.displayImage(2) def rot45Derajat(self): self.RotasiClicked(45) self.displayImage(2) def minus90Derajat(self): self.RotasiClicked(-90) self.displayImage(2) def rot90Derajat(self): self.RotasiClicked(90) self.displayImage(2) def minus180Derajat(self): self.RotasiClicked(-180) self.displayImage(2) def rot180Derajat(self): self.RotasiClicked(180) self.displayImage(2) @pyqtSlot() def LinearInterpolationClicked(self): # make size 3/4 original image size cv2.imshow('Original',self.image) resize_img=cv2.resize(self.image,None,fx=0.50, fy=0.50) self.image=resize_img cv2.imshow('',self.image) #self.displayImage(2) @pyqtSlot() def CubicInterppolationClicked(self): # double size of original image size/zooming(scaling up) cv2.imshow('Original', self.image) resize_img=cv2.resize(self.image,None,fx=2,fy=2,interpolation= cv2.INTER_CUBIC) self.image = resize_img cv2.imshow('',self.image) #self.displayImage(2) @pyqtSlot() def skewedSizeClicked(self): # resize image based on exacat dimension cv2.imshow('Original', self.image) resize_img = cv2.resize(self.image, (900, 400), interpolation=cv2.INTER_AREA) self.image = resize_img cv2.imshow('', self.image) # self.displayImage(2) def CropClicked(self): h, w = self.image.shape[:2] # get the strating point of pixel coord(top left) start_row, start_col = int(h * .1), int(w * .1) # get the ending point coord (botoom right) end_row, end_col = int(h * .5), int(w * .5) crop = self.image[start_row:end_row, start_col:end_col] cv2.imshow('Original', self.image) cv2.imshow('Cropped', crop) def AritmatikaClicked(self): img1 = cv2.imread('2.jpg', 0) img2 = cv2.imread('1.jpg', 0) add_img = img1 + img2 subtract = img1 - img2 subtract2 = img2 - img1 mul = img1 * img2 div = img1 / img2 cv2.imshow('Image 1', img1) cv2.imshow('Image 2', img2) cv2.imshow('Add', add_img) cv2.imshow('Subtraction', subtract) cv2.imshow('Multiply', mul) cv2.imshow('Divide', div) def BooleanClicked(self): img1 = cv2.imread('1.jpg', 1) img2 = cv2.imread('2.jpg', 1) img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) op_and = cv2.bitwise_and(img1, img2) op_or = cv2.bitwise_or(img2, img2) op_xor = cv2.bitwise_xor(img1, img2) cv2.imshow('Image 1', img1) cv2.imshow('Image 2', img2) cv2.imshow('And', op_and) cv2.imshow('OR', op_or) cv2.imshow('XOR', op_xor) def FilteringClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) gauss = (1.0 / 57) * np.array( [[0, 1, 0], [1, 0, 1], [0, 1, 0]]) img_out = conv(img, gauss) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() def MeanClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) gauss = (1.0 / 57) * np.array( [[1/9, 1/9, 1/9], [1/9, 1/9, 1/9], [1/9, 1/9, 1/9]]) img_out = conv(img, gauss) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() def GaussianClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) gauss = (1.0 / 57) * np.array( [[0.0029, 0.0131, 0.0215, 0.0131, 0.0029], [0.0131, 0.0585, 0.0965, 0.0585, 0.0131], [0.0215, 0.0965, 0.1592, 0.0965, 0.0215], [0.0131, 0.0585, 0.0965, 0.0585, 0.0131], [0.0029, 0.0131, 0.0215, 0.0131, 0.0029]]) img_out = conv(img, gauss) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() def SharpeningClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) gauss = (1.0 / 16) * np.array( [[1, -2, 1], [-2, 5, -2], [1, -2, 1]]) img_out = conv(img, gauss) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() @pyqtSlot() def MedianClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) img_out = img.copy() h, w = self.image.shape[:2] for i in np.arange(3, h - 3): for j in np.arange(3, w - 3): neighbors = [] for k in np.arange(-3, 4): for l in np.arange(-3, 4): a = img.item(i + k, j + l) neighbors.append(a) neighbors.sort() median = neighbors[24] b = median plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() pyqtSlot() @pyqtSlot() def MaxClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) img_out = img.copy() h, w = self.image.shape[:2] for i in np.arange(3, h - 3): for j in np.arange(3, w - 3): max = 0 for k in np.arange(-3, 4): for l in np.arange(-3, 4): a = img.item(i + k, j + l) if a > max: max = a b = max img_out.itemset((i, j), b) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() pyqtSlot() @pyqtSlot() def SobelClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) Sx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) Sy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) img_x = conv(img, Sx) img_y = conv(img, Sy) img_out = np.sqrt(img_x * img_x + img_y * img_y) img_out = (img_out / np.max(img_out)) * 255 self.image = img self.displayImage(2) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis plt.show() def PrewitClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) Px = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]]) Py = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]]) img_x = conv(img, Px) img_y = conv(img, Py) img_out = np.sqrt((img_x * img_x) + (img_y * img_y)) img_out = (img_out / np.max(img_out)) * 255 self.image = img self.displayImage(2) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis plt.show() def RobertClicked(self): img = cv2.imread('1.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) x = np.array([[1, 0], [0, -1]]) y = np.array([[0, 1], [-1, 0]]) sx = cv2.filter2D(gray, cv2.CV_64F, x) sy = cv2.filter2D(gray, cv2.CV_64F, y) hitung = cv2.sqrt((sx * sx) + (sy * sy)) h, w = hitung.shape[:2] for i in np.arange(h): for j in np.arange(w): a = hitung.item(i, j) if a > 255: a = 255 elif a < 0: a = 0 else: a = a plt.imshow(hitung, cmap='gray', interpolation='bicubic') plt.xticks([]), plt.yticks([]) print(hitung) plt.show() def LaplaceClicked(self): img = cv2.imread('1.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) x = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]]) y = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) sx = cv2.filter2D(gray, cv2.CV_64F, x) sy = cv2.filter2D(gray, cv2.CV_64F, y) hitung = cv2.sqrt((sx * sx) + (sy * sy)) h, w = hitung.shape[:2] for i in np.arange(h): for j in np.arange(w): a = hitung.item(i, j) if a > 255: a = 255 elif a < 0: a = 0 else: a = a plt.imshow(hitung, cmap='gray', interpolation='bicubic') plt.xticks([]), plt.yticks([]) print(hitung) plt.show() def LaplaceofGaussianClicked(self): img = cv2.imread('1.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img_out = cv2.GaussianBlur(gray, (5,5),0) x = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]]) y = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) sx = cv2.filter2D(img_out, cv2.CV_64F, x) sy = cv2.filter2D(img_out, cv2.CV_64F, y) hitung = cv2.sqrt((sx * sx) + (sy * sy)) h, w = hitung.shape[:2] for i in np.arange(h): for j in np.arange(w): a = hitung.item(i, j) if a > 255: a = 255 elif a < 0: a = 0 else: a = a plt.imshow(hitung, cmap='gray', interpolation='bicubic') plt.xticks([]), plt.yticks([]) print(hitung) plt.show() @pyqtSlot() def CannyClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) gaus = (1.0 / 9) * np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) img_gaus = conv(img, gaus) # ubah format gambar img_gaus = img_gaus.astype("uint8") cv2.imshow("gaus",img_gaus) #sobel Sx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) Sy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) img_x = conv(img_gaus, Sx) img_y = conv(img_gaus, Sy) H, W = img.shape[:2] img_out = np.zeros((H, W)) for i in np.arange(H): for j in np.arange(W): x = img_x.item(i, j) y = img_y.item(i, j) hasil = np.abs(x) + np.abs(y) if (hasil > 255): hasil = 255 if (hasil < 0): hasil = 0 else: hasil = hasil img_out.itemset((i, j), hasil) # hasil gradient img_out = img_out.astype("uint8") #arah tepi theta = np.arctan2(img_y, img_x) cv2.imshow("sobel",img_out) #non-max supresion Z = np.zeros((H, W), dtype=np.int32) angle = theta * 180. / np.pi angle[angle < 0] += 180 for i in range(1, H - 1): for j in range(1, W - 1): try: q = 255 r = 255 # angle 0 if (0 <= angle[i, j] < 22.5) or (157.5 <= angle[i, j] <= 180): q = img_out[i, j + 1] r = img_out[i, j - 1] # angle 45 elif (22.5 <= angle[i, j] < 67.5): q = img_out[i + 1, j - 1] r = img_out[i - 1, j + 1] # angle 90 elif (67.5 <= angle[i, j] < 112.5): q = img_out[i + 1, j] r = img_out[i - 1, j] # angle 135 elif (112.5 <= angle[i, j] < 157.5): q = img_out[i - 1, j - 1] r = img_out[i + 1, j + 1] if (img_out[i, j] >= q) and (img_out[i, j] >= r): Z[i, j] = img_out[i, j] else: Z[i, j] = 0 except IndexError as e: pass img_N = Z.astype("uint8") cv2.imshow("NON", img_N) # hysteresis Thresholding menentukan tepi lemah dan kuat weak = 50 strong = 100 for i in np.arange(H): for j in np.arange(W): a = img_N.item(i, j) if (a > weak) : #weak b = weak if (a > strong): #strong b = 255 else: b = 0 img_N.itemset((i, j), b) img_H1 = img_N.astype("uint8") cv2.imshow("hysteresis part 1", img_H1) # hysteresis Thresholding eliminasi titik tepi lemah jika tidak terhubung dengan tetangga tepi kuat strong = 255 for i in range(1, H - 1): for j in range(1, W - 1): if (img_H1[i, j] == weak): try: if ((img_H1[i + 1, j - 1] == strong) or (img_H1[i + 1, j] == strong) or (img_H1[i + 1, j + 1] == strong) or (img_H1[i, j - 1] == strong) or (img_H1[i, j + 1] == strong) or (img_H1[i - 1, j - 1] == strong) or (img_H1[i - 1, j] == strong) or (img_H1[i - 1, j + 1] == strong)): img_H1[i, j] = strong else: img_H1[i, j] = 0 except IndexError as e: pass img_H2 = img_H1.astype("uint8") cv2.imshow("Canny Edge Detection", img_H2) @pyqtSlot() def Dilasi(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _,thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) strel = np.ones((5, 5), np.uint8) dilasi = cv2.dilate(thresh, strel, iterations=1) cv2.imshow("Dilasi", dilasi) def Erosi(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) strel = np.ones((5, 5), np.uint8) erosi = cv2.erode(thresh, strel, iterations=1) cv2.imshow("Erosi", erosi) def Opening(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) strel = np.ones((5, 5), np.uint8) Opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, strel, iterations=1) cv2.imshow("Opening", Opening) def Closing(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) strel = np.ones((5, 5), np.uint8) Closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, strel, iterations=1) cv2.imshow("Closing", Closing) @pyqtSlot() def SkeletonClicked(self): img = cv2.cvtColor(self.image) size = np.size(img) skeleton = np.zeros(img.shape, np.uint8) ret, img = cv2.threshold(img, 127, 255, 0) strel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) done = False while (not done): erosi = cv2.erode(img, strel) temp = cv2.dilate(erosi, strel) temp = cv2.subtract(img, temp) skeleton = cv2.bitwise_or(skeleton, temp) img = erosi.copy() zeros = size - cv2.countNonZero(img) if zeros == size: done = True cv2.imshow('Image Asli', img) cv2.imshow('Skeletonizing', skeleton) @pyqtSlot() def Binary(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) cv2.imshow("Binary", thresh) def BinaryInvers(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) cv2.imshow("Binary Invers", thresh) def Trunc(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC) cv2.imshow("Trunc", thresh) def ToZero(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO) cv2.imshow("To Zero", thresh) def ToZeroInvers(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV) cv2.imshow("To Zero Invers", thresh) @pyqtSlot() def otsuClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) retval2, otsu_thres = cv2.threshold(img, 125, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) mean_c = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 115, 1) gaus = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 115, 1) cv2.imshow("Retval", retval2) cv2.imshow("Otsu", otsu_thres) cv2.imshow("mean_c", mean_c) cv2.imshow("gaus", gaus) def displayImage(self, windows=1): qformat=QImage.Format_Indexed8 if len(self.image.shape)==3: if(self.image.shape[2])==4: qformat=QImage.Format_RGBA8888 else: qformat=QImage.Format_RGB888 img=QImage(self.image,self.image.shape[1],self.image.shape[0],self.image.strides[0],qformat) #cv membaca image dalam format BGR, PyQt membaca dalam format RGB img=img.rgbSwapped() #menyimpan gambar hasil load di dalam imgLabel if windows==1: self.imgLabel.setPixmap(QPixmap.fromImage(img)) #memposisikan gambar self.imgLabel.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) self.imgLabel.setScaledContents(True) if windows==2: self.imgLabel2.setPixmap(QPixmap.fromImage(img)) #memposisikan gambar self.imgLabel2.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) self.imgLabel2.setScaledContents(True)
class FieldSelector(QDialog, Ui_FieldSelector): """ Class documentation goes here. """ textualId = -1 columnId = -1 def __init__(self, base, url, currenttextualization, inColumnName, newLineTags, sentenceSplit): """ Constructor """ QDialog.__init__(self) self.setupUi(self) self.base = base self.currenturl = url self.constraints = None # self.content="" self.columnName = '' # self.inColumnName=inColumnName self.textualName = '' self.sourceTextualName = currenttextualization self.selectableTags = [ "div", "span", "p", "h1", "h2", "h3", "tr", "ul", "li" ] #print newLineTags #print "|".join(newLineTags ) self.newLineRe = re.compile(newLineTags, re.M + re.I) self.sentenceSplit = sentenceSplit self.progressBar.hide() self.selectedColor = '#b0c4de' self.webView.mousePressEvent = self.mousePressed self.selectColumnName = None if inColumnName: if self.base.columnIsSourceColumn(currenttextualization, inColumnName): self.selectColumnName = inColumnName self.getWebViewPage(self.currenturl) self.listTextualizations() self.listTextColumns() def getWebViewPage(self, url): self.currentrowid, source = self.base.getSourceByURL( url, self.sourceTextualName, self.selectColumnName) self.url.setText(url) if self.currentrowid == 1: self.backButton.setEnabled(False) if source: self.showPage(source) def showPage(self, source): """ inserts interactive js into a page before showing it in the webView the interactive js copies the element under the mouse into an invisible node 'grogro' """ soup = BeautifulSoup(source, "html.parser") js = """ function cli(e, ele) { ele.style.borderStyle = 'solid'; event.cancelBubble = true; host=document.getElementById("grogro"); oldnode=host.firstChild; newnode=ele.cloneNode(true) host.replaceChild(newnode, oldnode); return false } """ #insert js newTag = soup.new_tag('script') newString = soup.new_string(js) newTag.append(newString) # print "____________", soup.head if soup.html == None: return # print soup.html, soup.html==None if not soup.head: soup.html.append(soup.new_tag("head")) if not soup.body: soup.html.append(soup.new_tag("body")) soup.head.append(newTag) #insert invisible div in the end new_tag = soup.new_tag("div", id="grogro", style="visibility:hidden") new_tag.append("nothing") soup.body.append(new_tag) for tag in self.selectableTags: for d in soup.findAll(tag): d['onmouseover'] = "cli(event,this);" d['onmouseout'] = "this.style.borderStyle='none';" self.webView.setHtml(str(soup)) # @pyqtSignature("bool") # def on_webView_loadFinished(self, p0): # """ # Slot documentation goes here. # """ # self.webViewIsLoading=False # @pyqtSignature("QMouseEvent") def mousePressed(self, me): """ Slot documentation goes here. """ self.constraints = [None, None, None] doc = self.webView.page().mainFrame().documentElement() host = doc.findFirst("div[id='grogro']").firstChild() #show the tag name self.tagCheckBox.setText('tag : ' + host.tagName()) self.tagCheckBox.setEnabled(True) self.constraints[0] = str(host.tagName()) #show the id name if host.hasAttribute('id'): self.idCheckBox.setText('id : ' + host.attribute('id')) self.idCheckBox.setEnabled(True) self.constraints[1] = str(host.attribute('id')) else: self.idCheckBox.setText('id') self.idCheckBox.setEnabled(False) #show the class name if host.hasAttribute('class'): self.classCheckBox.setText('class : ' + host.attribute('class')) self.classCheckBox.setEnabled(True) self.constraints[2] = str(host.attribute('class')) else: self.classCheckBox.setText('class') self.classCheckBox.setEnabled(False) #self.sourceText.setPlainText(self.applyConstraints()[0]) self.applyConstraints() # self.sourceText.setPlainText(BeautifulSoup(unicode(host.toOuterXml()) ).get_text()) #if self.constraints: #self.textualComboBox.setEnabled(True) #self.listTextualizations() #else: #self.textualComboBox.setEnabled(False) # self.buttonBox.setEnabled(True) def listTextualizations(self): """ shows the textualizations existing in the base """ self.textualNames = [] #remember the names that exist in the database self.textualComboBox.clear() #self.textualComboBox.addItem("") for cf in self.base.getTextualizations(): self.textualComboBox.addItem(cf) self.textualNames.append(cf) self.textualComboBox.setCurrentIndex(self.textualComboBox.count() - 1) self.textualName = str(self.textualComboBox.currentText()) self.textualComboBox.setEnabled(False) def listTextColumns(self): """ get the column name you want 1.if use the textualizations existing in the database , then list the column name belongs to the textualizations we can choose the existing column name or creat new names we want 2. if we creat a new textualizations , then no list for the column ,and we can creat a new name 3. the name can only Start with 'A~Z' and 'a~z """ self.columnNames = [] self.textcolComboBox.clear() if self.textualName in self.textualNames: (textualId, ) = next( self.base.select( "select id from textualizations where name='" + self.textualName + "';")) for id, in self.base.select( "select columnid from textualcolumns where textualid=" + str(textualId) + ";"): (columnName, ) = next( self.base.select( "select name from textcolumns where id=" + str(id) + ";")) self.columnNames.append(columnName) self.textcolComboBox.addItem("") for cf in self.columnNames: self.textcolComboBox.addItem(cf) self.columnName = str(self.textcolComboBox.currentText()) else: self.textcolComboBox.clear() #@pyqtSignature("int") def on_textualComboBox_currentIndexChanged(self, index): """ Slot documentation goes here. """ self.textualName = str(self.textualComboBox.currentText()) self.listTextColumns() self.setExtractionEnabled() #@pyqtSignature("QString") @pyqtSlot(str) def on_textualComboBox_editTextChanged(self, p0): """ Slot documentation goes here. """ self.textualName = str(self.textualComboBox.currentText()) if len(self.textualName) == 0: self.textcolComboBox.clear() self.textcolComboBox.clearEditText() self.warnLabel.setText("") else: if self.textualName < 'A' or 'Z' < self.textualName[ 0] < 'a' or self.textualName[0] >= 'z': self.warnLabel.setText( "Illegal Name . Please Start with 'A~Z' and 'a~z'") else: self.warnLabel.setText("") self.listTextColumns() self.setExtractionEnabled() #@pyqtSignature("int") def on_textcolComboBox_currentIndexChanged(self, index): """ Slot documentation goes here. """ self.columnName = str(self.textcolComboBox.currentText()) self.setExtractionEnabled() #@pyqtSignature("QString") @pyqtSlot(str) def on_textcolComboBox_editTextChanged(self, p0): """ Slot documentation goes here. """ self.columnName = str(self.textcolComboBox.currentText()) if len(self.columnName) == 0: self.warnLabel.setText("") else: if self.columnName < 'A' or 'Z' < self.columnName[ 0] < 'a' or self.columnName[0] > 'z': self.warnLabel.setText( "Illegal Name . Please Start with a letter") elif self.columnName in self.columnNames: self.warnLabel.setText("Existing columns will be overwritten!") else: self.warnLabel.setText("") self.setExtractionEnabled() #@pyqtSignature("") def on_additionTagLineEdit_returnPressed(self): # print "iiii" newselectabletag = str(self.additionTagLineEdit.text()) if newselectabletag: self.selectableTags = list( set(self.selectableTags + [newselectabletag])) #print self.selectableTags def setExtractionEnabled(self): if self.columnName != '' and self.textualName != '' and ( self.warnLabel.text() == "" or self.warnLabel.text() == "Existing columns will be overwritten!"): self.extractFrame.setEnabled(True) self.newcolumnButton.setEnabled(True) self.textExtraction.setEnabled(True) else: self.extractFrame.setEnabled(False) self.newcolumnButton.setEnabled(False) self.textExtraction.setEnabled(False) def applyConstraints(self): """ marks the divs of the current html document corresponding to the selected constraints gives back the selection as text and as source """ # print "marking constraints" doc = self.webView.page().mainFrame().documentElement() # for ele in doc.findAll("div") + doc.findAll("p")+doc.findAll("span"): for tag in self.selectableTags: for ele in doc.findAll(tag): ele.setStyleProperty( 'background-color', '#ffffff' ) # TODO: make this customizable or the contrary of the font color to remain readable if self.tagCheckBox.isChecked(): constring = self.constraints[0] or "*" else: constring = "*" if self.idCheckBox.isChecked() and self.constraints[1]: constr1 = '[' + "id=" + '"' + self.constraints[1] + '"' + ']' constring += constr1 if self.classCheckBox.isChecked() and self.constraints[2]: constr2 = '[' + "class=" + '"' + self.constraints[2] + '"' + ']' constring += constr2 #the format of the css selector is span[hello="Cleveland"][goodbye="Columbus"] { color: blue; } !important elemsSource = "" #paint the node if constring != "*": for elem in doc.findAll(constring): elemsSource += str(elem.toOuterXml()) + " " # self.content=unicode(elem.toOuterXml())+self.content elem.setStyleProperty('background-color', self.selectedColor) for tag in self.selectableTags: for child in elem.findAll(tag): # all children child.setStyleProperty('background-color', self.selectedColor) pureText = self.html2text(elemsSource) self.sourceText.setPlainText(pureText) return pureText, elemsSource def computeStat(self, content=""): """ called from on_newcolumnButton_clicked when calculating the nbWords just calculate the number of characters """ # content =content or self.content if self.isLinguaContinua(content): nbWords = len( str(content) ) #count the number of characters (word counting is too difficult for Chinese) else: nbWords = len(whiteSpaceRe.split(content)) nbSentences = 0 for line in content.split("\n"): num = len(self.sentenceSplit.findall(line)) if num == 0: nbSentences = nbSentences + 1 else: nbSentences = nbSentences + len( self.sentenceSplit.findall(line)) return nbWords, nbSentences def on_tagCheckBox_stateChanged(self, p0): self.applyConstraints() def on_idCheckBox_stateChanged(self, p0): self.applyConstraints() def on_classCheckBox_stateChanged(self, p0): self.applyConstraints() #@pyqtSignature("") pyqtSlot() def on_nextButton_clicked(self): #print 8888 rowid, url, source = self.base.getNextSource(self.currentrowid, self.sourceTextualName, self.selectColumnName) if rowid: #print 777 self.url.setText(url) self.currentrowid += 1 if not len(source.strip( )): # if the next page was empty, take the following one. #print 999 self.on_nextButton_clicked() return self.nextButton.setEnabled(True) self.backButton.setEnabled(True) self.currentrowid = rowid self.showPage(source) if self.constraints: self.applyConstraints() #print 7777 # self.sourceText.clear() else: self.nextButton.setEnabled(False) #@pyqtSignature("") pyqtSlot() def on_backButton_clicked(self): #print 111 rowid, url, source = self.base.getLastSource(self.currentrowid, self.sourceTextualName, self.selectColumnName) if rowid: self.url.setText(url) self.currentrowid -= 1 if not len(source.strip()): self.on_backButton_clicked() return self.backButton.setEnabled(True) self.nextButton.setEnabled(True) self.currentrowid = rowid self.showPage(source) if self.constraints: self.applyConstraints() # self.sourceText.clear() if rowid == 1: self.backButton.setEnabled(False) else: self.backButton.setEnabled(False) def on_numElecomboBox_currentIndexChanged(self, index): raise NotImplementedError #@pyqtSignature("") pyqtSlot() def on_newcolumnButton_clicked(self): """ the function is to insert the new textualization and columnName information into the database then extract the part we choose and insert into the database show the progress bar and hide the progress bar in the database, should make the textualizations. """ #print "mmm",self.textualName,self.textualNames,self.textualName in self.textualNames if self.textualName in self.textualNames: (self.textualId, ) = next( self.base.select( "select id from textualizations where name='" + self.textualName + "';")) if self.columnName not in self.columnNames: count = len(self.columnNames) + 1 self.base.execute( "insert into textcolumns(name) values (?) ;", (self.columnName, )) self.base.execute( "insert into textualcolumns(textualid,columnid) values (?,?) ;", ( self.textualId, count, )) self.columnId = count self.overwrite = False else: # textualName and culumnName existed in the database . if the button are clicked, just overwrite (self.columnId, ) = next( self.base.select( "select id from textcolumns where name='" + self.columnName + "';")) self.overwrite = True else: qsdf self.textualId = len(self.textualNames) + 1 self.base.execute( "insert into textualizations(name) values (?) ;", (self.textualName, )) self.base.execute("insert into textcolumns(name) values (?) ;", (self.columnName, )) (self.columnId, ) = next( self.base.select("select id from textcolumns where name='" + self.columnName + "';")) self.base.execute( "insert into textualcolumns(textualid,columnid) values (?,?) ;", ( self.textualId, self.columnId, )) self.overwrite = False while not self.base.reqs.empty(): pass sleep( .01 ) # wait for the database to close completely before giving back the textualName self.progressBar.show() (totalnum, ) = next(self.base.select("select count(*) from sources;")) self.progressBar.setMaximum(totalnum) #go extract the part we choose for i in range(1, totalnum + 1): source = self.base.getSourceById( i, self.textualName, self.selectColumnName ) #extract the part from the first to the last # if not self.webViewIsLoading: self.webView.setHtml(source) textcontent, sourcecontent = self.applyConstraints() # self.webView._wait_load() # textcontent=self.html2text(self.content) # if textcontent: nbWords, nbSentences = self.computeStat(textcontent) if self.textExtraction.isChecked(): enterstuff = textcontent else: enterstuff = "<html>\n" + sourcecontent + "\n</html>" self.base.enterNewText(i, self.textualId, self.columnId, enterstuff, nbSentences, nbWords, self.overwrite) self.progressBar.setValue(i) if self.base.errorState: # print self.base.errorState QtWidgets.QMessageBox.critical( self, "Problem with database", self.base.errorState + "\n\nDoes another program access the database file?") break self.base.makeTextual(self.textualName, self.textualId) # self.textualizationName=self.textualName self.progressBar.hide() self.progressBar.setValue(totalnum) #self.textualComboBox.setCurrentIndex(self.textualComboBox.count()) #self.textualComboBox.setEnabled(False) self.setExtractionEnabled() ################## stuff for text extraction ################################ def html2text(self, htmlSource): # if "doubleclick" in htmlSource: print "doubleclick","\n\n", htmlSource, "\n" htmlSource = whiteSpaceRe.sub( " ", htmlSource) # all white space (including new line) => simple space htmlSource = scriptex.sub(" ", htmlSource) htmlSource = styleex.sub(" ", htmlSource) htmlSource = rssex.sub(" ", htmlSource) htmlSource = commentex.sub(" ", htmlSource) htmlSource = imageex.sub(" ", htmlSource) htmlSource = self.newLineRe.sub("\n", htmlSource) # if "doubleclick" in htmlSource:print "\n\navant", htmlSource, "\n\n" pureText = anyTagRe.sub( " ", htmlSource) # the great moment: we're down to pure text ! pureText = redoubleclick.sub( " ", pureText ) # just in case the evil guys from doubleclick where around # if "doubleclick" in htmlSource:print "\n\n après", htmlSource, "\n\n" pureText = self._specialChar2UTF8(pureText) for g in getRid: # des trucs bizarres à virer : pureText = re.sub(g, " ", pureText) # enlever les espaces et passages à la ligne successifs : pureText = re.sub("[ \t\r\f\v\n]*\n+[ \t\r\f\v\n]*", "\n", pureText) pureText = re.sub("[ \t\r\f\v]+", " ", pureText)[1:-1] return pureText def _specialChar2UTF8(self, codeHTML): """ trying to replace things of type Ӓ and é by the unicode chars """ codeHTML = re.sub("&.+?;", self._replacementHtmlUnicode, codeHTML) return codeHTML def _replacementHtmlUnicode(self, s): match = s.group()[1:-1] # get rid of & and ; if match[:2] == "#x": # if of type ꯍ try: return chr(int(match[2:], 16)) except Exception as e: if verbose: print("0. strange html like thing:", match, e) elif match[0] == "#": i = int(match[1:]) if i in windowsGarbage: return windowsGarbage[i] #.decode("utf-8") else: try: return chr(i) # if of type Ӓ except Exception as e: if verbose: print("1. strange html like thing:", match, e) return " " try: return chr(name2codepoint[match]) except Exception as e: if verbose: print("2. strange html like thing:", match, e) return " " def isLinguaContinua(self, text, threshold=0.9): """ returns true if the percentage of spaces in the text is below 10% """ txt = spaceRe.sub("", text) return (float(len(txt)) / len(text + " ") > threshold)
class PIDRunner(QObject): status_sig = pyqtSignal(list) pid_output_signal = pyqtSignal(dict) def __init__(self,model_class, move_done_signals=[], grab_done_signals=[], move_modules_commands=[], detector_modules_commands=[], params=dict([]), filter=dict([]), det_averaging = [] ): """ Init the PID instance with params as initial conditions Parameters ---------- params: (dict) Kp=1.0, Ki=0.0, Kd=0.0,setpoint=0, sample_time=0.01, output_limits=(None, None), auto_mode=True, proportional_on_measurement=False) """ super().__init__() self.model_class = model_class self.move_done_signals = move_done_signals self.grab_done_signals = grab_done_signals self.det_averaging = det_averaging self.move_modules_commands = move_modules_commands self.detector_modules_commands = detector_modules_commands self.current_time = 0 self.input = 0 self.output = None self.output_to_actuator = None self.output_limits = None, None self.filter = filter #filter=dict(enable=self.settings.child('main_settings', 'filter', 'filter_enable').value(), value=self.settings.child('main_settings', 'filter', 'filter_step').value()) self.pid = PID(**params) ##PID(object): self.pid.set_auto_mode(False) self.refreshing_ouput_time = 200 self.running = True self.timer = self.startTimer(self.refreshing_ouput_time) self.det_done_datas = OrderedDict() self.move_done_positions = OrderedDict() self.move_done_flag = False self.det_done_flag = False self.paused = True self.timeout_timer = QtCore.QTimer() self.timeout_timer.setInterval(10000) self.timeout_scan_flag = False self.timeout_timer.timeout.connect(self.timeout) def timerEvent(self, event): if self.output_to_actuator is not None: self.pid_output_signal.emit(dict(output=self.output_to_actuator, input=[self.input])) else: self.pid_output_signal.emit(dict(output=[0], input=[self.input])) def timeout(self): self.status_sig.emit(["Update_Status", 'Timeout occured', 'log']) self.timeout_scan_flag = True def wait_for_det_done(self): self.timeout_scan_flag=False self.timeout_timer.start() while not(self.det_done_flag or self.timeout_scan_flag): #wait for grab done signals to end QtWidgets.QApplication.processEvents() self.timeout_timer.stop() def wait_for_move_done(self): self.timeout_scan_flag=False self.timeout_timer.start() while not(self.move_done_flag or self.timeout_scan_flag): #wait for move done signals to end QtWidgets.QApplication.processEvents() self.timeout_timer.stop() @pyqtSlot(ThreadCommand) def queue_command(self, command=ThreadCommand()): """ """ if command.command == "start_PID": self.start_PID(*command.attributes) elif command.command == "run_PID": self.run_PID(*command.attributes) elif command.command == "pause_PID": self.pause_PID(*command.attributes) elif command.command == "stop_PID": self.stop_PID() elif command.command == 'update_options': self.set_option(**command.attributes) elif command.command == 'input': self.update_input(*command.attributes) elif command.command == 'update_timer': if command.attributes[0] == 'refresh_plot_time': self.killTimer(self.timer) self.refreshing_ouput_time = command.attributes[1] self.timer = self.startTimer(self.refreshing_ouput_time) elif command.attributes[0] =='timeout': self.timeout_timer.setInterval(command.attributes[1]) elif command.command == 'update_filter': self.filter = command.attributes[0] # elif command.command == "move_Abs": # self.set_option(dict(setpoint=command.attributes[0])) def update_input(self, measurements): self.input =self.model_class.convert_input(measurements) def start_PID(self, input = None): try: for sig in self.move_done_signals: sig.connect(self.move_done) for sig in self.grab_done_signals: sig.connect(self.det_done) self.current_time = time.perf_counter() self.status_sig.emit(["Update_Status", 'PID loop starting', 'log']) while self.running: #print('input: {}'.format(self.input)) ## GRAB DATA FIRST AND WAIT ALL DETECTORS RETURNED self.det_done_flag = False self.det_done_datas = OrderedDict() for ind_det, cmd in enumerate(self.detector_modules_commands): cmd.emit(ThreadCommand("single", [self.det_averaging[ind_det]])) QtWidgets.QApplication.processEvents() self.wait_for_det_done() self.input = self.model_class.convert_input(self.det_done_datas) ## EXECUTE THE PID output = self.pid(self.input) ## PROCESS THE OUTPUT IF NEEDED if output is not None and self.output is not None: if self.filter['enable']: if np.abs(output-self.output) <= self.filter['value']: self.output = output else: self.output += np.abs(self.filter['value'])*np.sign(output - self.output) self.pid._last_output = self.output else: self.output = output else: self.output = output ## APPLY THE PID OUTPUT TO THE ACTUATORS #print('output: {}'.format(self.output)) if self.output is None: self.output = self.pid.setpoint dt = time.perf_counter() - self.current_time self.output_to_actuator = self.model_class.convert_output(self.output, dt, stab=True) if not self.paused: self.move_done_positions = OrderedDict() for ind_mov, cmd in enumerate(self.move_modules_commands): cmd.emit(ThreadCommand('move_Abs',[self.output_to_actuator[ind_mov]])) QtWidgets.QApplication.processEvents() self.wait_for_move_done() self.current_time = time.perf_counter() QtWidgets.QApplication.processEvents() QThread.msleep(int(self.pid.sample_time*1000)) self.status_sig.emit(["Update_Status", 'PID loop exiting', 'log']) for sig in self.move_done_signals: sig.disconnect(self.move_done) for sig in self.grab_done_signals: sig.disconnect(self.det_done) except Exception as e: self.status_sig.emit(["Update_Status", str(e), 'log']) pyqtSlot(OrderedDict) #OrderedDict(name=self.title,data0D=None,data1D=None,data2D=None) def det_done(self,data): """ """ try: if data['name'] not in list(self.det_done_datas.keys()): self.det_done_datas[data['name']]=data if len(self.det_done_datas.items())==len(self.grab_done_signals): self.det_done_flag=True except Exception as e: self.status_sig.emit(["Update_Status", str(e), 'log']) pyqtSlot(str,float) def move_done(self,name,position): """ | Update the move_done_positions attribute if needed. | If position attribute is setted, for all move modules launched, update scan_read_positions with a [modulename, position] list. ============== ============ ================= **Parameters** **Type** **Description** *name* string the module name *position* float ??? ============== ============ ================= """ try: if name not in list(self.move_done_positions.keys()): self.move_done_positions[name]=position if len(self.move_done_positions.items())==len(self.move_done_signals): self.move_done_flag=True except Exception as e: self.status_sig.emit(["Update_Status",str(e),'log']) def set_option(self,**option): for key in option: if hasattr(self.pid, key): if key == 'sample_time': setattr(self.pid, key, option[key]/1000) else: setattr(self.pid,key, option[key]) if key == 'setpoint' and not self.pid.auto_mode: dt = time.perf_counter() - self.current_time self.output = option[key] self.output_to_actuator = self.model_class.convert_output(self.output, dt, stab=False) for ind_move, cmd in enumerate(self.move_modules_commands): cmd.emit(ThreadCommand('move_Abs', [self.output_to_actuator[ind_move]])) self.current_time = time.perf_counter() if key == 'output_limits': self.output_limits = option[key] def run_PID(self, last_value): self.status_sig.emit(["Update_Status", 'Stabilization started', 'log']) self.running = True self.pid.set_auto_mode(True, last_value) def pause_PID(self, pause_state): if pause_state: self.pid.set_auto_mode(False, self.output) self.status_sig.emit(["Update_Status", 'Stabilization paused', 'log']) else: self.pid.set_auto_mode(True, self.output) self.status_sig.emit(["Update_Status", 'Stabilization restarted from pause', 'log']) self.paused = pause_state def stop_PID(self): self.running = False self.status_sig.emit(["Update_Status", 'PID loop exiting', 'log'])
class PIDModelMichelsonDemo(PIDModelGeneric): params = [ {'title': 'Stabilization', 'name': 'stabilization', 'type': 'group', 'children': [ {'title': 'Set as zero:', 'name': 'set_zero', 'type': 'bool', 'value': False}, {'title': 'Laser wavelength (nm):', 'name': 'laser_wl', 'type': 'float', 'value': 632.0}, {'title': 'Interfero phase (deg):', 'name': 'interfero_phase', 'type': 'float', 'value': 0}, {'title': 'Interfero position (nm):', 'name': 'interfero_position', 'type': 'float', 'value': 0}, {'title': 'phase sign:', 'name': 'phase_sign', 'type': 'int', 'value': 1, 'min': -1, 'max': 1, 'step': 2}, {'title': 'Offsets', 'name': 'offsets', 'type': 'group', 'children': [ {'title': 'Phase offset (deg):', 'name': 'phase_offset', 'type': 'float', 'value': 0}, {'title': 'Interfero (nm):', 'name': 'interfero_offset', 'type': 'float', 'value': 0}, {'title': 'Piezo (nm):', 'name': 'piezo_offset', 'type': 'float', 'value': 0}, ]}, ]}, {'title': 'Calibration', 'name': 'calibration', 'type': 'group', 'expanded': True, 'visible': True, 'children': [ {'title': 'Do calibration:', 'name': 'do_calibration', 'type': 'bool', 'value': False}, {'title': 'Timeout:', 'name': 'timeout', 'type': 'int', 'value': 10000}, {'title': 'Calibration', 'name': 'calibration_move', 'type': 'group', 'expanded': True, 'visible': True, 'children': [ {'title': 'Start pos:', 'name': 'start', 'type': 'float', 'value': 7.}, {'title': 'Stop pos:', 'name': 'stop', 'type': 'float', 'value': 8.}, {'title': 'Step size:', 'name': 'step', 'type': 'float', 'value': 0.04}, {'title': 'Averaging:', 'name': 'average', 'type': 'int', 'value': 1}, ]}, {'title': 'Ellipse params', 'name': 'calibration_ellipse', 'type': 'group', 'expanded': True, 'visible': True, 'children': [ {'title': 'Dx:', 'name': 'dx', 'type': 'float', 'value': 0.0}, {'title': 'Dy:', 'name': 'dy', 'type': 'float', 'value': 0.0}, {'title': 'x0:', 'name': 'x0', 'type': 'float', 'value': 0.00}, {'title': 'y0:', 'name': 'y0', 'type': 'float', 'value': 0.00}, {'title': 'phi (°):', 'name': 'theta', 'type': 'float', 'value': 0.00}, ]}, ]}, ] actuators = ['PI'] actuators_name = ['Axis test PID'] detectors_type = ['DAQ2D'] # with entries either 'DAQ0D', 'DAQ1D' or 'DAQ2D'or 'DAQND' detectors = ['OpenCVCam'] detectors_name = ['Testing PID'] check_modules(detectors, detectors_type, actuators) def __init__(self, pid_controller): super().__init__(pid_controller) self.running = False self.det_done_flag = False self.move_done_flag = False self.timeout_scan_flag = False self.curr_time = time.perf_counter() self.lsqe = LSqEllipse() self.phases = np.zeros((100,)) self.curr_phase = 0 self.curr_position = 0 self.dock_calib = Dock('Calibration') widget_calib = QtWidgets.QWidget() self.viewer_calib = Viewer1D(widget_calib) widget_ellipse = QtWidgets.QWidget() self.viewer_ellipse = Viewer1D(widget_ellipse) self.viewer_ellipse.show_data([np.zeros((10,)), np.zeros((10,))]) self.dock_calib.addWidget(widget_calib) self.dock_calib.addWidget(widget_ellipse, row=0, col = 1) self.pid_controller.dock_area.addDock(self.dock_calib) self.dock_calib.float() self.timer = QTimer() self.timer.setSingleShot(True) self.timer.timeout.connect(self.timeout) def ini_model(self): """ Defines all the action to be performed on the initialized modules (main pid, actuators, detectors) Either here for specific things (ROI, ...) or within the preset of the current model """ model_name = self.pid_controller.settings.child('models', 'model_class').value() self.pid_controller.detector_modules[0].ui.viewers[0].ui.roiBtn.click() #try to get corresponding roi file filename = os.path.join(get_set_pid_path(), model_name + '.roi2D') if os.path.isfile(filename): self.pid_controller.detector_modules[0].ui.viewers[0].load_ROI(filename) QtWidgets.QApplication.processEvents() if self.pid_controller.detector_modules[0].Initialized_state: #self.pid_controller.detector_modules[0].settings.child('main_settings', 'wait_time').setValue(0) self.pid_controller.detector_modules[0].grab_data() QThread.msleep(500) QtWidgets.QApplication.processEvents() self.pid_controller.settings.child('main_settings', 'update_modules').setValue(True) QtWidgets.QApplication.processEvents() QThread.msleep(500) QtWidgets.QApplication.processEvents() items = self.pid_controller.settings.child('main_settings', 'detector_modules').value().copy() if items is not None: items['selected'] = items['all_items'][0:2] self.pid_controller.settings.child('main_settings', 'detector_modules').setValue(items) self.pid_controller.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_min').setValue(0) #in microns self.pid_controller.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_min_enabled').setValue(True) self.pid_controller.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_max').setValue(15) #in microns self.pid_controller.settings.child('main_settings', 'pid_controls', 'output_limits', 'output_limit_max_enabled').setValue(True) self.pid_controller.settings.child('main_settings', 'pid_controls', 'pid_constants', 'kp').setValue(0.5) self.pid_controller.settings.child('main_settings', 'pid_controls', 'pid_constants', 'ki').setValue(0.2) self.pid_controller.settings.child('main_settings', 'pid_controls', 'pid_constants', 'kd').setValue(0.0001) self.pid_controller.settings.child('main_settings', 'pid_controls', 'filter', 'filter_enable').setValue(True) self.pid_controller.settings.child('main_settings', 'pid_controls', 'filter', 'filter_step').setValue(self.settings.child('stabilization', 'laser_wl').value()/1000/6/2) #in microns self.pid_controller.setpoint_sb.setValue(7.5) self.pid_controller.settings.child('main_settings', 'pid_controls', 'sample_time').setValue(50) def get_ellipse_fit(self, center, width, height, theta): t = np.linspace(0, 2 * np.pi, 1000) ellipse_x = center[0] + width * np.cos(t) * np.cos(theta) - height * np.sin(t) * np.sin(theta) ellipse_y = center[1] + width * np.cos(t) * np.sin(theta) + height * np.sin(t) * np.cos(theta) return ellipse_x, ellipse_y def update_settings(self, param): """ Get a parameter instance whose value has been modified by a user on the UI Parameters ---------- param: (Parameter) instance of Parameter object """ if param.name() == 'do_calibration': if param.value(): self.running = True self.do_calibration() QtWidgets.QApplication.processEvents() else: self.running = False elif param.name() == 'set_zero': self.phases = np.zeros((100,)) position = self.pid_controller.actuator_modules[0].current_position self.settings.child('stabilization', 'offsets', 'phase_offset').setValue(self.curr_phase) self.settings.child('stabilization', 'offsets', 'interfero_offset').setValue(position*1000) self.settings.child('stabilization', 'offsets', 'piezo_offset').setValue(position*1000) data = self.pid_controller.detector_modules[0].data_to_save_export data_export = OrderedDict() data_export[data['name']] = data self.pid_controller.command_pid.emit(ThreadCommand('input', [data_export])) QtWidgets.QApplication.processEvents() self.settings.child('stabilization', 'set_zero').setValue(False) def do_calibration(self): Naverage = self.settings.child('calibration', 'calibration_move', 'average').value() steps = linspace_step(self.settings.child('calibration', 'calibration_move', 'start').value(), self.settings.child('calibration', 'calibration_move', 'stop').value(), self.settings.child('calibration', 'calibration_move', 'step').value()) self.detector_data = np.zeros((steps.size,2)) self.detector_data_average = np.zeros((steps.size, 2)) for mod in self.pid_controller.actuator_modules: mod.move_done_signal.connect(self.move_done) for mod in self.pid_controller.detector_modules: mod.grab_done_signal.connect(self.det_done) self.viewer_calib.x_axis = steps for ind_average in range(Naverage): for ind_step, step in enumerate(steps): self.move_done_flag = False self.pid_controller.actuator_modules[0].move_Abs(step) self.wait_for_move_done() self.det_done_flag = False self.pid_controller.detector_modules[0].grab_data() self.wait_for_det_done() for ind_data, name in enumerate(self.data_names): self.detector_data[ind_step, ind_data] = \ self.pid_controller.detector_modules[0].data_to_save_export[name[1]][name[2]] if not self.running: break self.detector_data_average = (ind_average*self.detector_data_average+self.detector_data)/(ind_average+1) self.viewer_calib.show_data([self.detector_data_average[:,0], self.detector_data_average[:,1]]) self.lsqe.fit([self.detector_data_average[:,0], self.detector_data_average[:,1]]) center, width, height, theta = self.lsqe.parameters() ellipse_x, ellipse_y = self.get_ellipse_fit(center, width, height, theta) self.viewer_ellipse.plot_channels[0].setData(x=self.detector_data_average[:,0], y=self.detector_data_average[:,1]) self.viewer_ellipse.plot_channels[1].setData(x=ellipse_x, y=ellipse_y) self.settings.child('calibration', 'calibration_ellipse', 'x0').setValue(center[0]) self.settings.child('calibration', 'calibration_ellipse', 'y0').setValue(center[1]) self.settings.child('calibration', 'calibration_ellipse', 'dx').setValue(width) self.settings.child('calibration', 'calibration_ellipse', 'dy').setValue(height) self.settings.child('calibration', 'calibration_ellipse', 'theta').setValue(np.rad2deg(theta)) if not self.running: break QtWidgets.QApplication.processEvents() self.pid_controller.setpoint_sb.setValue(self.pid_controller.setpoint_sb.value()) self.settings.child('calibration', 'do_calibration').setValue(False) for mod in self.pid_controller.actuator_modules: mod.move_done_signal.disconnect(self.move_done) for mod in self.pid_controller.detector_modules: mod.grab_done_signal.disconnect(self.det_done) def timeout(self): """ Send the status signal *'Time out during acquisition'* and stop the timer. """ self.timeout_scan_flag=True self.timer.stop() self.pid_controller.update_status("Timeout during acquisition",log_type='log') def wait_for_det_done(self): self.timeout_scan_flag=False self.timer.start(self.settings.child('calibration','timeout').value()) while not(self.det_done_flag or self.timeout_scan_flag): #wait for grab done signals to end QtWidgets.QApplication.processEvents() self.timer.stop() pyqtSlot(OrderedDict) #edict(name=self.title,data0D=None,data1D=None,data2D=None) def det_done(self,data): """ | Initialize 0D/1D/2D datas from given data parameter. | Update h5_file group and array. | Save 0D/1D/2D datas. =============== ============================== ====================================== **Parameters** **Type** **Description** *data* Double precision float array The initializing data of the detector =============== ============================== ====================================== """ #print(data['data0D']['OpenCV_Integrated_ROI_00']) if not (self.settings.child('calibration', 'do_calibration').value() or self.pid_controller.run_action.isChecked()): det_done_datas = OrderedDict() det_done_datas[data['name']] = data self.convert_input(det_done_datas) self.det_done_flag = True def wait_for_move_done(self): self.timeout_scan_flag=False self.timer.start(self.settings.child('calibration','timeout').value()) while not(self.move_done_flag or self.timeout_scan_flag): #wait for move done signals to end QtWidgets.QApplication.processEvents() self.timer.stop() pyqtSlot(str,float) def move_done(self,name,position): #print(position) self.curr_position = position self.move_done_flag=True def get_phi_from_xy(self,x,y): x0 = self.settings.child('calibration', 'calibration_ellipse', 'x0').value() y0 = self.settings.child('calibration', 'calibration_ellipse', 'y0').value() dx = self.settings.child('calibration', 'calibration_ellipse', 'dx').value() dy = self.settings.child('calibration', 'calibration_ellipse', 'dy').value() theta = np.deg2rad(self.settings.child('calibration', 'calibration_ellipse', 'theta').value()) #apply rotation of -theta to get ellipse on main axes v = np.array([x, y]) rot = rot = np.array([[np.cos(-theta), -np.sin(-theta)],[np.sin(-theta),np.cos(-theta)]]) vprim = rot @ v phi = np.arctan2((vprim[1]+x0*np.sin(theta)-y0*np.cos(theta))/dy, (vprim[0]-x0*np.cos(theta)-y0*np.sin(theta))/dx) self.settings.child('stabilization', 'interfero_phase').setValue(phi) self.curr_phase = phi return phi def interfero_from_phase(self, phi): laser_wl = self.settings.child('stabilization', 'laser_wl').value() phi_offset = self.settings.child('stabilization', 'offsets', 'phase_offset').value() interfero_offset = self.settings.child('stabilization', 'offsets', 'interfero_offset').value() phase_sign = self.settings.child('stabilization', 'phase_sign').value() self.phases = np.append(self.phases, [phi]) self.phases = np.unwrap(self.phases[1:]) interfero_position = interfero_offset+phase_sign*laser_wl/(2*np.pi*2)*(self.phases[-1]-phi_offset) return interfero_position def convert_input(self, measurements): """ Convert the measurements in the units to be fed to the PID (same dimensionality as the setpoint) Parameters ---------- measurements: (list) List of object from which the model extract a value of the same units as the setpoint Returns ------- float: the converted input """ #print('input conversion done') x = measurements[self.data_names[0][0]][self.data_names[0][1]][self.data_names[0][2]] y = measurements[self.data_names[1][0]][self.data_names[1][1]][self.data_names[1][2]] phi = self.get_phi_from_xy(x, y) pos = self.interfero_from_phase(phi) #in nm self.settings.child('stabilization', 'interfero_position').setValue(pos) self.curr_input = pos/1000 return pos/1000 # in microns for the PI stage def convert_output(self, output, dt, stab=True): """ Convert the output of the PID in units to be fed into the actuator Parameters ---------- output: (float) output value from the PID from which the model extract a value of the same units as the actuator Returns ------- list: the converted output as a list (if there are a few actuators) """ #print('output converted') #no conversion needed self.curr_output = output if stab: offset = 0#self.settings.child('stabilization', 'offsets', 'piezo_offset').value() else: offset = 0 return [output+offset]
class Server(QObject): debug = True log = sys.stderr username = '******' password = '******' stopServing = pyqtSlot() def __init__(self, parent=None): super(Server, self).__init__(parent) self.proxy_server = QTcpServer(self) self.proxy_server.listen(QHostAddress.Any, 8000) self.proxy_server.newConnection.connect(self.manage_request) if self.debug: self.log.write('Server running on localhost port %s\n\n' % self.port()) def port(self): return self.proxy_server.serverPort() def addr(self): return self.proxy_server.serverAddress().toString() def stopServing(self): if self.debug: self.log.write('Service is stopping...\n\n') # does not "close" the server, just stop listening... self.proxy_server.close() if self.proxy_server.hasPendingConnections(): socket = self.proxy_server.nextPendingConnection() while socket: socket.abort() socket = self.proxy_server.nextPendingConnection() def manage_request(self): proxy_server = self.sender() # Qt docs says that the caller of nextPendingConnection() # is the parent of the socket socket = proxy_server.nextPendingConnection() socket.readyRead.connect(self.process_request) socket.disconnected.connect(socket.deleteLater) def authorize_request(self, request_data): return True header = QHttpRequestHeader(QString(request_data)) if self.debug: self.log.write(header.toString()) auth = header.value('Proxy-Authorization') if not auth: return False challenge = base64.b64encode(self.username + ':' + self.password) return challenge == str(auth).split()[1] def process_request(self): socket = self.sender() request_data = socket.readAll() if not self.authorize_request(request_data): socket.write('HTTP/1.1 407 Proxy Authentication Required\r\n') if self.debug: self.log.write('407 Proxy Authentication Required\n\n') socket.write('Proxy-Authenticate: Basic realm="test"\r\n') socket.write('\r\n') socket.disconnectFromHost() return else: # remove Proxy-Authorization header start = request_data.indexOf('Proxy-Authorization:') end = request_data.lastIndexOf('\r\n') request_data.remove(start, end) request_data.append('\r\n') pos = request_data.indexOf('\r\n') request_line = request_data.left(pos) request_data.remove(0, pos + 2) entries = request_line.split(' ') method = entries[0] address = entries[1] version = entries[2] port = '80' if address.count(':') > 1: protocol, host, port = address.split(':') else: protocol, host = address.split(':') print('address' + str(address)) #url = QUrl( protocol + host ) url = QUrl.fromEncoded(address) #url.setHost( host ) #url.setPort( int(port) ) if not url.isValid(): if self.debug: self.log.write('Invalid URL: %s\n\n', url) socket.disconnectFromHost() return host = url.host() port = 80 if (url.port() < 0) else url.port() req = url.encodedPath() if url.hasQuery(): req.append('?').append(url.encodedQuery()) request_line = method + ' ' + req + ' ' + version + '\r\n' request_data.prepend(request_line) if self.debug: self.log.write(method + ' ' + address + ' ' + version + '\n\n') key = host + ':' + QString.number(port) proxy_socket = socket.findChild(QTcpSocket, key) if proxy_socket: proxy_socket.setObjectName(key) proxy_socket.setProperty('url', url) proxy_socket.setProperty('request_data', request_data) proxy_socket.write(request_data) else: proxy_socket = QTcpSocket(socket) proxy_socket.setObjectName(key) proxy_socket.setProperty('url', url) proxy_socket.setProperty('request_data', request_data) proxy_socket.connected.connect(self.send_request) proxy_socket.readyRead.connect(self.transfer_data) proxy_socket.disconnected.connect(self.close_connection) proxy_socket.error.connect(self.close_connection) proxy_socket.connectToHost(host, port) def send_request(self): proxy_socket = self.sender() request_data = proxy_socket.property('request_data').toByteArray() proxy_socket.write(request_data) def transfer_data(self): proxy_socket = self.sender() socket = proxy_socket.parent() socket.write(proxy_socket.readAll()) def close_connection(self): proxy_socket = self.sender() if proxy_socket: socket = proxy_socket.parent() if isinstance(socket, QTcpSocket) and socket: socket.disconnectFromHost() if proxy_socket.error() != QTcpSocket.RemoteHostClosedError: url = proxy_socket.property('url').toUrl() error_string = proxy_socket.errorString() if self.debug: self.log.write('Error for %s %s\n\n' % (url, error_string)) proxy_socket.deleteLater()
class SuperGrep(QMainWindow): def __init__(self): super(SuperGrep, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.tableSearch() self.setWindowIcon(QIcon("resources/lupa.png")) self.ui.btn_rutaExaminar.setIcon( QIcon(QPixmap("resources/carpeta.png"))) self.ui.btn_rutaExaminar.setLayoutDirection(Qt.RightToLeft) self.ui.btn_excluirExaminar.setIcon( QIcon(QPixmap("resources/carpeta.png"))) self.ui.btn_excluirExaminar.setLayoutDirection(Qt.RightToLeft) self.ui.btn_buscar.setIcon(QIcon(QPixmap("resources/encontrar.png"))) self.ui.btn_buscar.setLayoutDirection(Qt.RightToLeft) self.ui.btn_rutaExaminar.clicked.connect( partial(self.browse, self.ui.txt_ruta)) self.ui.btn_excluirExaminar.clicked.connect( partial(self.browse, self.ui.txt_excluirRuta)) self.ui.btn_buscar.clicked.connect(self.scan) self.ui.btn_pausar.clicked.connect(self.toggle_status) self.ui.btn_parar.clicked.connect(self.stop) self.ui.tableSearch.currentCellChanged.connect(self.dataRow) self.result_search = list() self.list_files = list() self.count = 0 self.flag_thread = False def browse(self, edit): fileName = QFileDialog.getExistingDirectory(self, 'Select directory') if fileName: edit.setText(fileName) def toggle_status(self): self.flag_thread = not self.flag_thread if self.flag_thread: self.pause() self.ui.btn_pausar.setText('Start') else: self.resume() self.ui.btn_pausar.setText('Pause') def resume(self): self.searcher.resume() def pause(self): self.searcher.pause() def stop(self): self.searcher.stop() def scan(self): ruta = self.ui.txt_ruta.text() excluido = list() excluir_ruta = Path(self.ui.txt_excluirRuta.text()) self.searcher = Searcher(ruta, self.ui.txt_consulta.text(), excluir_ruta, excluido) self.searcher.updated.connect(self.add_row) self.searcher.files.connect(self.countFiles) self.searcher.finished.connect(self.endScan) self.searcher.start() def dataRow(self, row, column): # Sumary self.ui.tedit_sumary.clear() r_files = [] contador = 0 self.ui.tedit_sumary.appendHtml("Resultados de la busqueda: ") self.ui.tedit_sumary.appendHtml("<br>Palabra: <b>" + self.ui.txt_consulta.text() + " <b>") for j in range(len(self.result_search)): if self.ui.txt_consulta.text() == self.result_search[j][6]: if self.result_search[j][0] not in r_files: r_files.append(self.result_search[j][0]) contador += 1 self.ui.tedit_sumary.appendHtml("Cantidad coincidencias: " + str(contador)) self.ui.tedit_sumary.appendHtml("Cantidad Archivos: " + str(len(r_files)) + "<br>") for r_file in r_files: self.ui.tedit_sumary.appendHtml(r_file) r_files.clear() # hints self.ui.tedit_hints.clear() self.ui.tedit_hints.appendHtml("<b>Archivo:</b> " + self.result_search[row][0]) self.ui.tedit_hints.appendHtml("<b>Extension:</b> " + self.result_search[row][1]) self.ui.tedit_hints.appendHtml("<b>Ruta:</b> " + self.result_search[row][2]) self.ui.tedit_hints.appendHtml("<b>Palabra encontrada:</b> " + self.result_search[row][3]) self.ui.tedit_hints.appendHtml("<b>Palabra buscada:</b> " + self.result_search[row][6]) self.ui.tedit_hints.appendHtml("<b>Nro Linea:</b> " + str(self.result_search[row][4])) linea = html.escape(self.result_search[row][5]) linea = linea.replace( self.result_search[row][3], "<font color=\"red\">" + self.result_search[row][3] + "</font>") self.ui.tedit_hints.appendHtml("<b>Linea:</b> <br><br>" + linea) def endScan(self): QMessageBox.information(self, "SuperGrep", "Busqueda finalizada", QMessageBox.Ok) pyqtSlot(str) def countFiles(self, files): if files not in self.list_files: self.list_files.append(files) self.statusBar().showMessage( 'Archivos buscados: %i Resultados Encontrados: %i' % (len(self.list_files), self.count)) pyqtSlot(list) def add_row(self, result): self.count += 1 self.result_search.append(result) rowPosition = self.ui.tableSearch.rowCount() self.ui.tableSearch.insertRow(rowPosition) header = self.ui.tableSearch.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) item1 = QTableWidgetItem(result[0]) item2 = QTableWidgetItem(result[1]) item3 = QTableWidgetItem(result[2]) item4 = QTableWidgetItem(result[3]) item5 = QTableWidgetItem(str(result[4])) item1.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter) item2.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter) item3.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter) item4.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter) item5.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter) self.ui.tableSearch.setItem(rowPosition, 0, QTableWidgetItem(item1)) # item1 self.ui.tableSearch.setItem(rowPosition, 1, QTableWidgetItem(item2)) # item2 self.ui.tableSearch.setItem(rowPosition, 2, QTableWidgetItem(item3)) # item3 self.ui.tableSearch.setItem(rowPosition, 3, QTableWidgetItem(item4)) # item4 self.ui.tableSearch.setItem(rowPosition, 4, QTableWidgetItem(item5)) # item5 def tableSearch(self): # Deshabilitar edición self.ui.tableSearch.setEditTriggers(QAbstractItemView.NoEditTriggers) # Deshabilitar el comportamiento de arrastrar y soltar self.ui.tableSearch.setDragDropOverwriteMode(False) # Seleccionar toda la fila self.ui.tableSearch.setSelectionBehavior(QAbstractItemView.SelectRows) # Establecer el número de columnas self.ui.tableSearch.setColumnCount(5) # Establecer el número de filas self.ui.tableSearch.setRowCount(0) # Alineación del texto del encabezado self.ui.tableSearch.horizontalHeader().setDefaultAlignment( Qt.AlignHCenter | Qt.AlignVCenter | Qt.AlignCenter) # Ocultar encabezado vertical self.ui.tableSearch.verticalHeader().setVisible(False) nombreColumnas = ('Nombre Archivo', 'Extension', 'Ruta', 'Palabra', 'Linea #') # Establecer las etiquetas de encabezado horizontal usando etiquetas self.ui.tableSearch.setHorizontalHeaderLabels(nombreColumnas) # todo los headers de la tabla se ponen del mismo tamaño self.ui.tableSearch.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch)
def method(*args, **kwargs): return pyqtSlot(*args, **kwargs)
def enableFindButton(self, text): self.findButton.setEnabled(bool(text)) @ pyqtSlot()
from PyQt5.uic import loadUiType from PyQt5.QtGui import QPixmap, QImage from graphviz import Digraph import os.path from gui.read_data import read_data from gui.error_message import error from gui.tablewidget import tw import pandas as pd import datetime as dt from logic.math import * form_class, base_class = loadUiType(os.path.join(os.path.dirname(__file__), 'main_form.ui')) scaleUp = pyqtSlot() scaleDown = pyqtSlot() class MainWindow(QDialog): def __init__(self, *args): super(MainWindow, self).__init__(*args) self.ui = form_class() self.ui.setupUi(self) self.ui.tabWidget.setCurrentIndex(0) self.graph = Digraph(comment='Когнитивная карта', name='Cognitive map', format='png') self.labels = None self.matrix = None
class ScanSelector(QObject): scan_select_signal = pyqtSignal(ROI) params = [ { 'title': 'Scan options', 'name': 'scan_options', 'type': 'group', 'children': [ { 'title': 'Sources:', 'name': 'sources', 'type': 'list', }, { 'title': 'Viewers:', 'name': 'viewers', 'type': 'list', }, { 'title': 'Scan type:', 'name': 'scan_type', 'type': 'list', 'values': ['Scan1D', 'Scan2D'], 'value': 'Scan2D' }, ] }, { 'title': 'Scan Area', 'name': 'scan_area', 'type': 'group', 'children': [ { 'title': 'ROI select:', 'name': 'ROIselect', 'type': 'group', 'visible': True, 'children': [ { 'title': 'x0:', 'name': 'x0', 'type': 'int', 'value': 0, 'min': 0 }, { 'title': 'y0:', 'name': 'y0', 'type': 'int', 'value': 0, 'min': 0 }, { 'title': 'width:', 'name': 'width', 'type': 'int', 'value': 10, 'min': 1 }, { 'title': 'height:', 'name': 'height', 'type': 'int', 'value': 10, 'min': 1 }, ] }, { 'title': 'Coordinates:', 'name': 'coordinates', 'type': 'itemselect', 'visible': True }, ] }, ] def __init__(self, viewer_items=[], scan_type='Scan2D', positions=[]): """ Parameters ---------- viewer_items: dict where the keys are the titles of the sources while the values are dict with keys viewers: list of plotitems names: list of viewer titles scan_type: (str) either 'Scan1D' correspondign to a polyline ROI or 'Scan2D' for a rect Roi positions: list in case of 'Scan1D', should be a sequence of 2 floats sequence [(x1,y1),(x2,y2),(x3,y3),...] in case of 'Scan2D', should be a sequence of 4 floats (x, y , w, h) """ super(ScanSelector, self).__init__() self._viewers_items = viewer_items self.sources_names = list(viewer_items.keys()) if len(viewer_items) != 0: self.scan_selector_source = viewer_items[ self.sources_names[0]]['viewers'][0] else: self.scan_selector_source = None self.scan_selector = None self.setupUI() self.settings.child('scan_options', 'scan_type').setValue(scan_type) self.remove_scan_selector() if self.scan_selector_source is not None: if len(viewer_items[self.sources_names[0]]['viewers']) == 1: self.settings.child('scan_options', 'viewers').hide() else: self.settings.child('scan_options', 'viewers').hide() self.update_scan_area_type() if scan_type == "Scan1D" and positions != []: self.scan_selector.setPoints(positions) elif scan_type == 'Scan2D' and positions != []: self.scan_selector.setPos(positions[:2]) self.scan_selector.setSize(positions[3:]) @property def viewers_items(self): return self._viewers_items @viewers_items.setter def viewers_items(self, items): self._viewers_items = items self.sources_names = list(items.keys()) self.scan_selector_source = items[self.sources_names[0]]['viewers'][0] self.settings.child('scan_options', 'sources').setOpts(limits=self.sources_names) viewer_names = self._viewers_items[self.sources_names[0]]['names'] self.settings.child('scan_options', 'viewers').setOpts(limits=viewer_names) def show(self, visible=True): self.show_scan_selector(visible) if visible: self.widget.show() else: self.widget.hide() def hide(self): self.show(False) def setupUI(self): self.widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() self.settings_tree = ParameterTree() layout.addWidget(self.settings_tree, 10) self.settings_tree.setMinimumWidth(300) self.settings = Parameter.create(name='Settings', type='group', children=self.params) self.settings_tree.setParameters(self.settings, showTop=False) self.settings.child('scan_options', 'sources').setOpts(limits=self.sources_names) if len(self.viewers_items): viewer_names = self._viewers_items[self.sources_names[0]]['names'] else: viewer_names = [] self.settings.child('scan_options', 'viewers').setOpts(limits=viewer_names) self.settings.sigTreeStateChanged.connect(self.source_changed) self.widget.setLayout(layout) #self.widget.show() self.widget.setWindowTitle('Scan Selector') def source_changed(self, param, changes): for param, change, data in changes: path = self.settings.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() if change == 'childAdded': pass elif change == 'value': if param.name() == 'sources' and param.value() is not None: viewer_names = self._viewers_items[param.value()]['names'] self.settings.child('scan_options', 'viewers').setOpts(limits=viewer_names) if len(viewer_names) == 1: self.settings.child('scan_options', 'viewers').hide() self.remove_scan_selector() self.scan_selector_source = self._viewers_items[ param.value()]['viewers'][0] self.update_scan_area_type() if param.name() == 'scan_type': if param.value() == 'Scan1D': self.settings.child('scan_area', 'ROIselect').hide() self.settings.child('scan_area', 'coordinates').show() self.remove_scan_selector() self.update_scan_area_type() else: self.settings.child('scan_area', 'ROIselect').show() self.settings.child('scan_area', 'coordinates').hide() self.remove_scan_selector() self.update_scan_area_type() self.scan_selector.sigRegionChangeFinished.emit( self.scan_selector) elif change == 'parent': pass def remove_scan_selector(self): if self.scan_selector_source is not None: try: self.scan_selector_source.image_widget.plotitem.removeItem( self.scan_selector) except: pass pyqtSlot(str) def update_scan_area_type(self): if self.settings.child('scan_options', 'scan_type').value() == 'Scan1D': scan_area_type = 'PolyLines' else: scan_area_type = 'Rect' self.remove_scan_selector() if scan_area_type == 'Rect': self.scan_selector = RectROI([0, 0], [10, 10]) elif scan_area_type == 'PolyLines': self.scan_selector = PolyLineROI_custom([(0, 0), [10, 10]]) if self.scan_selector_source is not None: self.scan_selector.sigRegionChangeFinished.connect( self.update_scan) self.scan_selector_source.image_widget.plotitem.addItem( self.scan_selector) self.show_scan_selector() self.scan_selector.sigRegionChangeFinished.emit(self.scan_selector) def show_scan_selector(self, visible=True): self.scan_selector.setVisible(visible) def update_scan(self, roi): if self.scan_selector_source is not None: if isinstance(roi, RectROI): self.settings.child('scan_area', 'ROIselect', 'x0').setValue(roi.pos().x()) self.settings.child('scan_area', 'ROIselect', 'y0').setValue(roi.pos().y()) self.settings.child('scan_area', 'ROIselect', 'width').setValue(roi.size().x()) self.settings.child('scan_area', 'ROIselect', 'height').setValue(roi.size().y()) elif isinstance(roi, PolyLineROI_custom): self.settings.child('scan_area', 'coordinates').setValue( dict(all_items=[ '({:.03f} , {:.03f})'.format(pt.x(), pt.y()) for pt in roi.get_vertex() ], selected=[])) self.scan_select_signal.emit(roi)
class ImageProc(QMainWindow): def __init__(self): super(ImageProc,self).__init__() loadUi('showgui.ui',self) self.image=None newImage=None self.loadButton.clicked.connect(self.loadClicked) self.saveButton.clicked.connect(self.saveClicked) self.action_Load_Image.triggered.connect(self.loadClicked) self.action_Save_Image.triggered.connect(self.saveClicked) self.actionGrayscale.triggered.connect(self.grayClicked) self.actionBrightness.triggered.connect(self.brightClicked) self.actionSimple_Contrast.triggered.connect(self.contrastClicked) self.actionAuto_Contrast_2.triggered.connect(self.autocontrastClicked) self.actionNegative_Image.triggered.connect(self.negatifClicked) self.actionGrayscale_Histogram.triggered.connect(self.GrayHistogramClicked) self.actionRGB_Histogram.triggered.connect(self.RGBHistogramClicked) self.actionBiner_Image.triggered.connect(self.BinerClicked) self.actionPerataan_Histogram.triggered.connect(self.EqualHistogramClicked) self.action_min_45_Derajat.triggered.connect(self.RotasiMin45Clicked) self.action_plus_45Derajat.triggered.connect(self.RotasiPlus45Clicked) self.action_Min_90_Derajat.triggered.connect(self.RotasiMin90Clicked) self.action_plus_90_Derajat .triggered.connect(self.RotasiPlus90Clicked) self.action180_Derajat.triggered.connect(self.Rotasi180Clicked) self.actionTranslasi.triggered.connect(self.TranslasiClicked) self.actionTranspose.triggered.connect(self.TransposeClicked) self.actionLinear_Interpolation.triggered.connect(self.Linear_InterpolationClicked) self.actionCubic_Interppolation.triggered.connect(self.Cubic_InterppolationClicked) self.actionSkewed_Size.triggered.connect(self.skewed_SizeClicked) self.actionCroping.triggered.connect(self.CropingClicked) self.actionPenambahan_Citra.triggered.connect(self.aritmatika_CitraClicked) self.actionLogika_Not.triggered.connect(self.Logika_NotClicked) self.actionLogika_AND.triggered.connect(self.Logika_ANDClicked) self.actionSmoothing_Image.triggered.connect(self.SmoothClicked) self.actionSharpening_Image.triggered.connect(self.SharpClicked) self.actionMean.triggered.connect(self.MeanClicked) self.actionMedian.triggered.connect(self.MedianClicked) self.actionMax_Filter.triggered.connect(self.MaxClicked) self.actionMin_Filter.triggered.connect(self.MinClicked) self.actionSobel.triggered.connect(self.SobelClicked) self.actionPrewitt.triggered.connect(self.PrewittClicked) self.actionCanny.triggered.connect(self.CannyClicked) @pyqtSlot() def loadClicked(self): flname,filter=QFileDialog.getOpenFileName(self,'Open File','D:\\Programming\\Python',"Image Files (*.jpg)") if flname: self.loadImage(flname) else: print('Invalid Image') @pyqtSlot() def saveClicked(self): flname, filter = QFileDialog.getSaveFileName(self, 'Save File', 'D:\\', "Image Files (*.jpg)") if flname: cv2.imwrite(flname, self.image) else: print('Error') @pyqtSlot() def grayClicked(self): H, W = self.image.shape[:2] gray = np.zeros((H, W), np.uint8) for i in range(H): for j in range(W): gray[i,j]= np.clip(0.299 * self.image[i, j, 0] + 0.587 * self.image[i, j, 1] + 0.114 * self.image[i, j, 2], 0, 255) self.image=gray self.displayImage(2) @pyqtSlot() def brightClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) brightness = 50 h, w = img.shape[:2] for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) b = a + brightness if b > 255: b = 255 elif b < 0: b = 0 else: b = b img.itemset((i, j), b) self.image = img self.displayImage(2) @pyqtSlot() # contrast def contrastClicked(self): gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) height = gray.shape[0] width = gray.shape[1] contrast = 1.6 for i in np.arange(height): for j in np.arange(width): a = gray.item(i, j) b = math.ceil(a * contrast) if b > 255: b = 255 gray.itemset((i, j), b) self.image = gray self.displayImage(2) @pyqtSlot() def autocontrastClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) h, w = img.shape[:2] min = 255 max = 0 for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) if a > max: max = a if a < min: min = a for i in np.arange(h): for j in np.arange(w): a = img.item(i, j) b = float(a - min) / (max - min) * 255 img.itemset((i, j), b) self.image = img self.displayImage(2) @pyqtSlot() def BinerClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) thres=100 h, w = img.shape[:2] for i in np.arange(h): for j in np.arange(w): a=img.item(i,j) if a > thres: a = 1 else: a = 0 img.itemset((i,j),a) print(img) self.image = img self.displayImage(2) @pyqtSlot() def negatifClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) h, w = img.shape[:2] max_intensity = 255 for i in range(h): for j in range(w): a = img.item(i, j) b = max_intensity - a img.itemset((i, j), b) self.image = img self.displayImage(2) @pyqtSlot() def GrayHistogramClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) self.image = img self.displayImage(2) plt.hist(img.ravel(), 255, [0, 255]) plt.show() @pyqtSlot() def RGBHistogramClicked(self): color = ('b', 'g', 'r') for i,col in enumerate(color): histo=cv2.calcHist([self.image],[i],None,[256],[0,256]) plt.plot(histo,color=col) plt.xlim([0,256]) plt.show() @pyqtSlot() def EqualHistogramClicked(self): hist, bins = np.histogram(self.image.flatten(), 256, [0, 256]) cdf = hist.cumsum() cdf_normalized = cdf * hist.max() / cdf.max() cdf_m = np.ma.masked_equal(cdf, 0) cdf_m = (cdf_m - cdf_m.min()) * 255 / (cdf_m.max() - cdf_m.min()) cdf = np.ma.filled(cdf_m, 0).astype('uint8') self.image = cdf[self.image] self.displayImage(2) plt.plot(cdf_normalized, color='b') plt.hist(self.image.flatten(), 256, [0, 256], color='r') plt.xlim([0, 256]) plt.legend(('cdf', 'histogram'), loc='upper left') plt.show() #-------------------------------------------------Operation Geometry----------------------------------------------------------------------# @pyqtSlot() def TranslasiClicked(self): h,w=self.image.shape[:2] print(h) print(w) quarter_h,quarter_w=h/4,w/4 print(quarter_h) print(quarter_w) T=np.float32([[1,0,quarter_w],[0,1,quarter_h]]) print(T) img=cv2.warpAffine(self.image,T,(w,h)) # sx=45 # sy=-35 # img=cv2.cvtColor(self.image,cv2.COLOR_BGR2RGB) # h,w=img.shape[:2] # for y in np.arange(1,h): # for x in np.arange(1,w): # xlama=x+sx # ylama=y+sy # img[ylama,xlama] self.image = img self.displayImage(2) @pyqtSlot() def RotasiMin45Clicked(self): self.rotasi(45) self.displayImage(2) @pyqtSlot() def RotasiPlus45Clicked(self): self.rotasi(-45) self.displayImage(2) @pyqtSlot() def RotasiMin90Clicked(self): self.rotasi(-90) self.displayImage(2) @pyqtSlot() def RotasiPlus90Clicked(self): self.rotasi(90) self.displayImage(2) @pyqtSlot() def Rotasi180Clicked(self): self.rotasi(180) self.displayImage(2) def rotasi(self,degree): h, w = self.image.shape[:2] rotationMatrix = cv2.getRotationMatrix2D((w / 2, h / 2), degree, .7) cos = np.abs(rotationMatrix[0, 0]) sin = np.abs(rotationMatrix[0, 1]) nW = int((h * sin) + (w * cos)) nH = int((h * cos) + (w * sin)) rotationMatrix[0, 2] += (nW / 2) - w / 2 rotationMatrix[1, 2] += (nH / 2) - h / 2 rot_image = cv2.warpAffine(self.image, rotationMatrix, (h, w)) self.image=rot_image @pyqtSlot() def TransposeClicked(self): trans_img=cv2.transpose(self.image) self.image=trans_img self.displayImage(2) @pyqtSlot() def Linear_InterpolationClicked(self): #make size 3/4 original image size cv2.imshow('Original',self.image) resize_img=cv2.resize(self.image,None,fx=0.50, fy=0.50) self.image=resize_img cv2.imshow('',self.image) #self.displayImage(2) @pyqtSlot() def Cubic_InterppolationClicked(self): #double size of original image size/zooming(scaling up) cv2.imshow('Original', self.image) resize_img=cv2.resize(self.image,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC) self.image = resize_img cv2.imshow('',self.image) #self.displayImage(2) @pyqtSlot() def skewed_SizeClicked(self): #resize image based on exacat dimension cv2.imshow('Original', self.image) resize_img=cv2.resize(self.image,(900,400),interpolation=cv2.INTER_AREA) self.image=resize_img cv2.imshow('',self.image) #self.displayImage(2) @pyqtSlot() def CropingClicked(self): h,w=self.image.shape[:2] #get the strating point of pixel coord(top left) start_row, start_col=int(h*.1),int(w*.1) #get the ending point coord (botoom right) end_row, end_col=int(h*.5),int(w*.5) crop=self.image[0:1000,0:500] cv2.imshow('Original',self.image) cv2.imshow('Crop Image',crop) #-----------------------------------operasi aritmatika--------------------------------------------------- @pyqtSlot() def aritmatika_CitraClicked(self): img1 = cv2.imread('img1.jpg', 0) img2 = cv2.imread('img2.jpg', 0) # img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB) # img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) add_img = img1 + img2 subtract = img1 - img2 subtract2=img2-img1 mul = img1 * img2 div = img1 / img2 # titles=['Image 1','Image 2','Add','Subtract (1-2)','Subtract(2-1)','Multiply','Divided'] # images=[img1,img2,add_img,subtract,subtract2,mul,div] # print() # # for i in range(8): # plt.subplot(1,8,i+1) # plt.imshow(images[i]) # plt.title(titles[i]) # plt.xticks([]) # plt.yticks([]) # plt.show() cv2.imshow('Image 1', img1) cv2.imshow('Image 2', img2) cv2.imshow('Add', add_img) cv2.imshow('Subtraction', subtract) cv2.imshow('Multiply', mul) cv2.imshow('Divide', div) @pyqtSlot() def Logika_NotClicked(self): # img=cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY) #cv2.bitwise_not(img) img=cv2.bitwise_not(img) self.image=img self.displayImage(2) # # img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) # thres = 100 # h, w = img.shape[:2] # for i in np.arange(h): # for j in np.arange(w): # a = img.item(i, j) # if a > thres: # a = 255 # elif a < thres: # a = 0 # else: # a = a # img=img.itemset((i, j), a) # img2=cv2.bitwise_not(img) # # self.image=img2 # self.displayImage(2) @pyqtSlot() def Logika_ANDClicked(self): img1 = cv2.imread('img1.jpg', 1) img2 = cv2.imread('img2.jpg', 1) img1=cv2.cvtColor(img1,cv2.COLOR_BGR2RGB) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) op_and=cv2.bitwise_and(img1,img2) op_or=cv2.bitwise_or(img2,img2) op_xor=cv2.bitwise_xor(img1,img2) cv2.imshow('Image 1', img1) cv2.imshow('Image 2', img2) cv2.imshow('And', op_and) cv2.imshow('OR', op_or) cv2.imshow('XOR', op_xor) #--------------------------------------------------------OPERASI SPASIAL------------------------------------------------------------------# @pyqtSlot() def SmoothClicked(self): img=cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY) #h,w=img.shape[:2] gauss =(1.0 / 57)* np.array( [[0, 1, 2, 1, 0], [1, 3, 5, 3, 1], [2, 5, 9, 5, 2], [1, 3, 5, 3, 1], [0, 1, 2, 1, 0]]) img_out=conv(img,gauss) # # #cv2.imshow('',img_out) # self.image=img_out # self.displayImage(i) plt.imshow(img_out,cmap='gray',interpolation='bicubic') plt.xticks([],plt.yticks([])) plt.show() pyqtSlot() def SharpClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) laplace = (1.0 / 16) * np.array( [[0, 0, -1, 0, 0], [0, -1, -2, -1, 0], [-1, -2, 16, -2, -1], [0, -1, -2, -1, 0], [0, 0, -1, 0, 0]]) img_out = conv(img, laplace) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() pyqtSlot() def MeanClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) laplace = (1.0 / 9) * np.array( [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]) img_out = conv(img, laplace) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() pyqtSlot() def MedianClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) img_out=img.copy() h,w=img.shape[:2] for i in np.arange(3,h-3): for j in np.arange(3,w-3): neighbors=[] for k in np.arange(-3,4): for l in np.arange(-3,4): a=img.item(i+k, j+l) neighbors.append(a) neighbors.sort() median=neighbors[24] b=median img_out.itemset((i,j),b) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() @pyqtSlot() def MaxClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) img_out = img.copy() h, w = img.shape[:2] for i in np.arange(3, h - 3): for j in np.arange(3, w - 3): max = 0 for k in np.arange(-3, 4): for l in np.arange(-3, 4): a = img.item(i + k, j + l) if a > max: max=a b=max img_out.itemset((i, j), b) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() @pyqtSlot() def MinClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) img_out = img.copy() h, w = img.shape[:2] for i in np.arange(3, h - 3): for j in np.arange(3, w - 3): min = 255 for k in np.arange(-3, 4): for l in np.arange(-3, 4): a = img.item(i + k, j + l) if a < min: min=a b=min img_out.itemset((i, j), b) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([], plt.yticks([])) plt.show() #--------------------------------------------------------ANALISIS CITRA------------------------------------------------------------------------------# @pyqtSlot() def SobelClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) Sx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) Sy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]) img_x = conv(img,Sx)/8.0 img_y = conv(img,Sy)/8.0 img_out = np.sqrt(np.power(img_x, 2) + np.power(img_y, 2)) img_out = (img_out / np.max(img_out)) * 255 self.image=img self.displayImage(2) plt.imshow(img_out, cmap='gray', interpolation='bicubic') plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis plt.show() @pyqtSlot() def PrewittClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) Px = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]]) Py = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]]) img_x = conv(img, Px) / 6.0 img_y = conv(img, Py) / 6.0 img_out = np.sqrt(np.power(img_x, 2) + np.power(img_y, 2)) img_out = (img_out / np.max(img_out)) * 255 self.image = img self.displayImage(2) plt.imshow(img_out,cmap = 'gray',interpolation='bicubic') plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis plt.show() @pyqtSlot() def CannyClicked(self): img = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) h,w=img.shape[:2] #step 1: reduce noise with Gaussian Filter gauss = (1.0 / 57) * np.array( [[0, 1, 2, 1, 0], [1, 3, 5, 3, 1], [2, 5, 9, 5, 2], [1, 3, 5, 3, 1], [0, 1, 2, 1, 0]]) img_blur = conv(img, gauss) #step 2: Finding Gradien img_x=conv(img_blur,np.array([[-0.5,0,0.5]])) img_y=conv(img_blur,np.array([[-0.5,0,0.5]])) E_mag=np.sqrt(np.power(img_x,2)+np.power(img_y,2)) E_mag=(E_mag/np.max(E_mag))*255 #step 3: non-maximum suppresion t_low=4 E_nms=np.zeros((h,w)) for i in np.arange(1,h-1): for j in np.arange(1,w-1): dx=img_x[i,j] dy=img_y[i,j] s_theta=fg.FindingGradien(dx,dy) if locmax.MaxSuppesion(E_mag,i,j,s_theta,t_low): E_nms[i,j]=E_mag[i,j] #step 4: Hysterisis Thresholding t_high=15 E_bin=np.zeros((h,w)) for i in np.arange(1,h-1): for j in np.arange(1,w-1): if E_nms[i,j]>=t_high and E_bin[i,j]==0: ht.HysterisisThres(E_nms,E_bin,i,j,t_low) self.image=img self.displayImage(2) plt.imshow(E_bin,cmap='gray', interpolation='bicubic') plt.xticks([]),plt.yticks([]) plt.show() #--------------------------------------------------------FUNGSI UMUM----------------------------------------------------------------------# def loadImage(self,flname): self.image=cv2.imread(flname,cv2.IMREAD_COLOR) self.displayImage() def displayImage(self, windows=1): qformat=QImage.Format_Indexed8 if len(self.image.shape)==3: if(self.image.shape[2])==4: qformat=QImage.Format_RGBA8888 else: qformat=QImage.Format_RGB888 img=QImage(self.image,self.image.shape[1],self.image.shape[0],self.image.strides[0],qformat) #BGR>RGB img=img.rgbSwapped() if windows==1: self.imgLabel.setPixmap(QPixmap.fromImage(img)) self.imgLabel.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) self.imgLabel.setScaledContents(True) if windows==2: self.hasilLabel.setPixmap(QPixmap.fromImage(img)) self.hasilLabel.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) self.hasilLabel.setScaledContents(True)
class MainWindow(QMainWindow, Ui_MainWindow): """ Class documentation goes here. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ QMainWindow.__init__(self, parent) self.setupUi(self) self.progressBar = QProgressBar() self.progressBar.setMaximum(0) self.progressBar.setMaximum(0) self.progressBar.setEnabled(False) self.statusBar.addPermanentWidget(self.progressBar) self.statusBar.showMessage(_translate("MainWindow", "Welcome to PyDSF")) self.buttonBox_process.addButton( _translate("MainWindow", "&Start Processing"), QDialogButtonBox.AcceptRole) self.tasks = Tasks() self.tasks.signals.finished.connect(self.on_processing_finished) self.worker = None self.outputPath = None self.instrument = None self.populateInstrumentList() def populateInstrumentList(self): self.instruments = [AnalytikJenaqTower2()] for i in range(len(self.instruments)): instrument = self.instruments[i] self.comboBox_instrument.setItemText(i, instrument.name) def getInstrumentFromName(self, name): for instrument in self.instruments: if instrument.name == name: return instrument raise IndexError("Requested instrument not") def getSelectedInstrument(self): name = str(self.comboBox_instrument.currentText()) instrument = self.getInstrumentFromName(name) return instrument @pyqtSlot("QAbstractButton*") def on_buttonBox_open_reset_clicked(self, button): """ Triggered when either the open or reset button in the data file dialog is clicked. Spawns an open file dialog or resets the listview. """ if button == self.buttonBox_open_reset.button(QDialogButtonBox.Open): filenames = QFileDialog.getOpenFileNames( self, _translate("MainWindow", "Open data file"), '', _translate("MainWindow", "Text files (*.txt *.csv)")) self.listWidget_data.addItems(filenames[0]) if self.listWidget_data.count() > 1: self.groupBox_replicates.setChecked(True) self.radioButton_rep_files.setEnabled(True) elif button == self.buttonBox_open_reset.button( QDialogButtonBox.Reset): self.listWidget_data.clear() @pyqtSlot("QAbstractButton*") def on_buttonBox_output_clicked(self, button): if button == self.buttonBox_output.button(QDialogButtonBox.Open): caption = _translate('MainWindow', 'Choose output path') path = QFileDialog.getExistingDirectory( parent=self, caption=caption, options=QFileDialog.ShowDirsOnly) self.lineEdit_output.setText(path.strip()) @pyqtSlot("QString") def on_comboBox_instrument_currentIndexChanged(self, p0): """ Triggered when another instrument is selected from the combobox. """ self.instrument = self.getInstrumentFromName(p0) if self.instrument.providesTempRange: self.groupBox_temp.setEnabled(False) else: self.groupBox_temp.setEnabled(True) def generate_plot_tab(self, name): tab = MplWidget(parent=self.tabWidget) tab.setObjectName(name) return tab def remove_plate_tabs(self): for i in range(self.tabWidget.count()): try: widget = self.tabWidget.widget(i) widget.deleteLater() except IndexError: pass self.tabWidget.clear() def generate_plate_tabs(self, plate): plotter = PlotResults() if plate.id != 'average': tab = self.generate_plot_tab("tab_heatmap_{}".format(plate.id)) title = _translate("MainWindow", "Heatmap #") self.tabWidget.addTab(tab, title + str(plate.id)) plotter.plot_tm_heatmap_single(plate, tab) if self.checkBox_saveplots.isChecked(): tab.canvas.save("{}/heatmap_{}.svg".format( self.outputPath, plate.id)) tab = self.generate_plot_tab("tab_raw_{}".format(plate.id)) title = _translate("MainWindow", "Raw Data #") self.tabWidget.addTab(tab, title + str(plate.id)) plotter.plot_raw(plate, tab) if self.checkBox_saveplots.isChecked(): tab.canvas.save("{}/raw_{}.svg".format(self.outputPath, plate.id)) tab = self.generate_plot_tab("tab_derivative_{}".format(plate.id)) title = _translate("MainWindow", "Derivatives #") self.tabWidget.addTab(tab, title + str(plate.id)) plotter.plot_derivative(plate, tab) if self.checkBox_saveplots.isChecked(): tab.canvas.save("{}/derivatives_{}.svg".format( self.outputPath, plate.id)) else: tab = self.generate_plot_tab("tab_heatmap_{}".format(plate.id)) title = _translate("MainWindow", "Heatmap ") self.tabWidget.addTab(tab, title + str(plate.id)) plotter.plot_tm_heatmap_single(plate, tab) if self.checkBox_saveplots.isChecked(): tab.canvas.save("{}/heatmap_{}.svg".format( self.outputPath, plate.id)) @pyqtSlot() def on_buttonBox_process_accepted(self): """ Slot documentation goes here. """ self.remove_plate_tabs() self.instrument = self.getSelectedInstrument() if self.listWidget_data.count() < 1: QMessageBox.critical( self, _translate("MainWindow", "Error"), _translate("MainWindow", "No data file loaded!"), QMessageBox.Close, QMessageBox.Close) return if (self.groupBox_output.isChecked() and self.lineEdit_output.text().strip() == ''): QMessageBox.critical( self, _translate("MainWindow", "Error"), _translate("MainWindow", "No output path set!"), QMessageBox.Close, QMessageBox.Close) return elif (self.groupBox_output.isChecked() and self.lineEdit_output.text().strip() != ''): path = self.lineEdit_output.text().strip() if os.path.isdir(path): self.outputPath = self.lineEdit_output.text().strip() else: QMessageBox.critical( self, _translate("MainWindow", "Error"), _translate("MainWindow", "Output path does not exist!"), QMessageBox.Close, QMessageBox.Close) if self.spinBox_signal_threshold.value( ) == 0 and self.groupBox_signal_threshold.isChecked(): QMessageBox.warning( self, _translate("MainWindow", "Warning"), _translate("MainWindow", "Signal threshold is currently set to zero."), QMessageBox.Ok, QMessageBox.Ok) self.progressBar.setEnabled(True) self.statusBar.showMessage(_translate("MainWindow", "Processing...")) self.worker = Worker(self) self.tasks.add_task(self.worker) self.tasks.start() @pyqtSlot() def on_processing_finished(self): # Clear all jobs from task list # self.tasks.clear() # For now, only read the first entry exp = self.tasks.data[0] # clear data in tasks object self.tasks.clear_data() for i in range(len(self.worker.exp.plates)): plate = exp.plates[i] self.generate_plate_tabs(plate) if exp.avg_plate: plate = exp.avg_plate self.generate_plate_tabs(plate) if self.groupBox_output.isChecked(): if self.checkBox_savetables.isChecked(): for plate in exp.plates: plate.write_tm_table('{}/plate_{}_tm.csv'.format( self.outputPath, str(plate.id))) plate.write_data_table('{}/plate_{}_dI_dT.csv'.format( self.outputPath, str(plate.id)), dataType='derivative') plate.write_data_table( '{}/plate_{}_filtered_data.csv'.format( self.outputPath, str(plate.id)), dataType='filtered') plate.write_data_table('{}/plate_{}_raw_data.csv'.format( self.outputPath, str(plate.id))) if exp.avg_plate: exp.avg_plate.write_tm_table( '{}/plate_{}_tm_avg.csv'.format( self.outputPath, str(self.worker.exp.avg_plate.id)), avg=True) self.progressBar.setEnabled(False) self.statusBar.showMessage(_translate("MainWindow", "Finished!")) @pyqtSlot() def on_buttonBox_process_rejected(self): """ Slot documentation goes here. """ QApplication.quit() pyqtSlot() def on_actionQuit_triggered(self): """ Slot documentation goes here. """ QApplication.quit() @pyqtSlot("bool") def on_groupBox_cutoff_toggled(self): """ Slot documentation goes here. """ self.doubleSpinBox_upper.setValue(self.doubleSpinBox_tmax.value()) self.doubleSpinBox_lower.setValue(self.doubleSpinBox_tmin.value()) @pyqtSlot() def on_actionAbout_triggered(self): """ Slot documentation goes here. """ # TODO: not implemented yet dialog = QDialog() dialog.ui = Ui_DialogAbout() dialog.ui.setupUi(dialog) dialog.exec_() @pyqtSlot() def on_actionAbout_Qt_triggered(self): """ Slot documentation goes here. """ QApplication.aboutQt()
class mainForm(QMainWindow): get_template_filename = pyqtSignal(str) exit_program = pyqtSignal() camera_changed = pyqtSignal(int) def __init__(self): super().__init__() self.stream = None self.image_difference_thread = None self.template_set = False self._countour_max_tresh = 10 self._countour_min_tresh = 1 self._transparency_max = 10 self._transparency_min = 0 self._countour_gamma_max = 10 self._countour_gamma_min = 1 self._color_max = 255 self._color_min = 0 self.screen_resolution = None self.grid_layout = None self.output_picture = None self.initUI() self.init_image_difference() if self.webcam_switcher.count() > 0: self.stream = streamCapture(self.webcam_switcher.itemData(self.webcam_switcher.currentIndex())) self.stream.getframe.connect(self.mat2qimage) self.webcam_switcher.currentIndexChanged.connect(self.camera_switcher_index_changed) self.camera_changed.connect(self.stream.reopenStream) self.stream.start() self.exit_program.connect(self.stream.exit) ### отрисовка интерфейса def initUI(self): self.screen_resolution = QApplication.desktop().screenGeometry() # self.resize(self.screen_resolution.size()) # self.move(self.screen_resolution.left(), self.screen_resolution.top()) self.grid_layout = QGridLayout() self.central_widget = QWidget() self.central_widget.setLayout(self.grid_layout) self.central_widget.setMaximumSize(self.screen_resolution.width() // 4 * 3, self.screen_resolution.height() // 4 * 3) self.setCentralWidget(self.central_widget) self.camera_label = QLabel("Camera:") self.grid_layout.addWidget(self.camera_label, 0, 0, 1, 1, Qt.AlignmentFlag.AlignHCenter) self.webcam_switcher = QComboBox() self.detect_webcam_devices(self.webcam_switcher) self.grid_layout.addWidget(self.webcam_switcher, 0, 1, 1, 3) self.output_picture = QLabel() self.grid_layout.addWidget(self.output_picture, 1, 0, 1, 4) ### creating right dock self.right_dock_layout = QVBoxLayout() self.right_dock_widget = QDockWidget() self.right_dock_widget.setFeatures(QDockWidget.DockWidgetFeature.DockWidgetMovable | QDockWidget.DockWidgetFeature.DockWidgetFloatable) self.right_dock_widget.setMinimumSize(self.screen_resolution.width() // 4, self.screen_resolution.height()) right_dock = QWidget(self.right_dock_widget) right_dock.setMinimumSize(self.screen_resolution.width() // 4, self.screen_resolution.height()) right_dock.setLayout(self.right_dock_layout) template_label = QLabel("Templates") template_label.setMinimumSize(50, 25) self.right_dock_layout.addWidget(template_label) self.filter_template_edit = QLineEdit() self.filter_template_edit.setPlaceholderText("Filter (Ctr + Alt + f)") template_label.setMinimumSize(90, 25) self.filter_template_edit.setStyleSheet( "background-image: url(../image_difference/icons/searchIcon.png); background-repeat: no-repeat; background-position: right;") self.right_dock_layout.addWidget(self.filter_template_edit) self.file_system_model = QFileSystemModel() self.file_system_model.setFilter(QDir.Filter.AllDirs | QDir.Filter.NoDotAndDotDot | QDir.Filter.AllEntries) self.file_system_model.setRootPath(QDir.currentPath()) self.directory_tree_view = QTreeView() self.directory_tree_view.setModel(self.file_system_model) self.directory_tree_view.setMinimumSize(200, 100) self.directory_tree_view.hideColumn(1) self.directory_tree_view.hideColumn(2) self.directory_tree_view.hideColumn(3) # self.directory_tree_view.sortByColumn(0) self.directory_tree_view.setSortingEnabled(True) self.directory_tree_view.doubleClicked.connect(self.load_template) self.directory_tree_view.setRootIndex(self.file_system_model.index("../image_difference/")) self.right_dock_layout.addWidget(self.directory_tree_view) self.load_template_button = QPushButton("Select Template") self.load_template_button.setMaximumSize(self.screen_resolution.width() // 4 - 30, 30) self.load_template_button.clicked.connect(self.load_template) self.right_dock_layout.addWidget(self.load_template_button) self.create_template_button = QPushButton("Create Template") self.create_template_button.setMaximumSize(self.screen_resolution.width() // 4 - 30, 30) self.create_template_button.clicked.connect(self.create_template) self.right_dock_layout.addWidget(self.create_template_button) self.template_image_widget = QWidget() self.template_image_widget.setMinimumSize(self.screen_resolution.width() // 4 - 20, self.screen_resolution.width() // 4 - 10) self.template_image_back = QLabel(self.template_image_widget) self.template_image_back.resize(self.screen_resolution.width() // 4 - 20, self.screen_resolution.width() // 4 - 10) pix = QPixmap(self.template_image_back.size()) pix.fill(Qt.lightGray) rect = QRectF(0.0, 0.0, self.template_image_back.size().width(), self.template_image_back.size().height()) painter = QPainter() painter.begin(pix) painter.setRenderHints(QPainter.Antialiasing, True) path = QPainterPath() path.addRoundedRect(rect, 5.0, 5.0) painter.drawPath(path) painter.end() self.template_image_back.setPixmap(pix) self.template_image = QLabel(self.template_image_widget) self.template_image.move(5, 5) self.template_image.resize(self.screen_resolution.width() // 4 - 30, self.screen_resolution.width() // 4 - 30) self.template_image_text = QLabel(self.template_image_widget, text="Current Template") self.template_image_text.setStyleSheet("font-weight: bold") self.template_image_text.move(self.screen_resolution.width() // 8 - 65, 20) self.right_dock_layout.addWidget(self.template_image_widget) self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.right_dock_widget) ### creating bottom dock self.bottom_dock_layout = QGridLayout() self.bottom_dock_layout.setSpacing(10) self.bottom_dock_widget = QDockWidget() self.bottom_dock_widget.setMinimumSize(self.screen_resolution.width() // 4 * 3 - 10, self.screen_resolution.height() // 4 - 10) bottom_dock = QWidget(self.bottom_dock_widget) bottom_dock.setMinimumSize(self.screen_resolution.width() // 4 * 3 - 20, self.screen_resolution.height() // 4 - 20) bottom_dock.move(10, 10) bottom_dock.setLayout(self.bottom_dock_layout) settings_label = QLabel("Settings:") self.bottom_dock_layout.addWidget(settings_label, 0, 0, 1, 2, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop) countour_tresh_label = QLabel("Countour Tresh:") self.bottom_dock_layout.addWidget(countour_tresh_label, 1, 0, 1, 1, Qt.AlignmentFlag.AlignTop) self.countour_tresh_slider = QSlider(Qt.Orientation.Horizontal) self.countour_tresh_slider.setTickPosition(QSlider.TickPosition.TicksBelow) self.countour_tresh_slider.setRange(self._countour_min_tresh, self._countour_max_tresh) self.countour_tresh_slider.setValue(2) self.bottom_dock_layout.addWidget(self.countour_tresh_slider, 1, 1, 1, 1, Qt.AlignmentFlag.AlignTop) transparency_weight_label = QLabel("Transparency:") self.bottom_dock_layout.addWidget(transparency_weight_label, 2, 0, 1, 1, Qt.AlignmentFlag.AlignTop) self.transparency_weight_slider = QSlider(Qt.Orientation.Horizontal) self.transparency_weight_slider.setTickPosition(QSlider.TickPosition.TicksBelow) self.transparency_weight_slider.setValue(6) self.transparency_weight_slider.setRange(self._transparency_min, self._transparency_max) self.bottom_dock_layout.addWidget(self.transparency_weight_slider, 2, 1, 1, 1, Qt.AlignmentFlag.AlignTop) countour_gamma_label = QLabel("Countour Gamma:") self.bottom_dock_layout.addWidget(countour_gamma_label, 3, 0, 1, 1, Qt.AlignmentFlag.AlignTop) self.countour_gamma_slider = QSlider(Qt.Orientation.Horizontal) self.countour_gamma_slider.setTickPosition(QSlider.TickPosition.TicksBelow) self.countour_gamma_slider.setValue(8) self.countour_gamma_slider.setRange(self._countour_gamma_min, self._countour_gamma_max) self.bottom_dock_layout.addWidget(self.countour_gamma_slider, 3, 1, 1, 1, Qt.AlignmentFlag.AlignTop) ### right side of settings countour_color_label = QLabel("Countour Color:") self.bottom_dock_layout.addWidget(countour_color_label, 0, 2, 1, 2, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop) r_color_label = QLabel("R:") self.bottom_dock_layout.addWidget(r_color_label, 1, 2, 1, 1, Qt.AlignmentFlag.AlignTop) self.r_color_slider = QSlider(Qt.Orientation.Horizontal) self.r_color_slider.setTickPosition(QSlider.TickPosition.TicksBelow) self.r_color_slider.setRange(self._color_min, self._color_max) self.r_color_slider.setValue(255) self.bottom_dock_layout.addWidget(self.r_color_slider, 1, 3, 1, 1, Qt.AlignmentFlag.AlignTop) g_color_label = QLabel("G:") self.bottom_dock_layout.addWidget(g_color_label, 2, 2, 1, 1, Qt.AlignmentFlag.AlignTop) self.g_color_slider = QSlider(Qt.Orientation.Horizontal) self.g_color_slider.setTickPosition(QSlider.TickPosition.TicksBelow) self.g_color_slider.setRange(self._color_min, self._color_max) self.bottom_dock_layout.addWidget(self.g_color_slider, 2, 3, 1, 1, Qt.AlignmentFlag.AlignTop) b_color_label = QLabel("B:") self.bottom_dock_layout.addWidget(b_color_label, 3, 2, 1, 1, Qt.AlignmentFlag.AlignTop) self.b_color_slider = QSlider(Qt.Orientation.Horizontal) self.b_color_slider.setTickPosition(QSlider.TickPosition.TicksBelow) self.b_color_slider.setRange(self._color_min, self._color_max) self.bottom_dock_layout.addWidget(self.b_color_slider, 3, 3, 1, 1, Qt.AlignmentFlag.AlignTop) self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.bottom_dock_widget) self.setCorner(Qt.Corner.BottomRightCorner, Qt.DockWidgetArea.RightDockWidgetArea) def init_image_difference(self): self.image_difference_thread = imageDifference() self.get_template_filename.connect(self.image_difference_thread.set_template_image) self.countour_tresh_slider.valueChanged.connect(self.image_difference_thread.set_countour_tresh_value) self.transparency_weight_slider.valueChanged.connect(self.image_difference_thread.set_transparency_weight_value) self.countour_gamma_slider.valueChanged.connect(self.image_difference_thread.set_countour_gamma_value) self.r_color_slider.valueChanged.connect(self.image_difference_thread.set_countour_color_r) self.g_color_slider.valueChanged.connect(self.image_difference_thread.set_countour_color_g) self.b_color_slider.valueChanged.connect(self.image_difference_thread.set_countour_color_b) self.image_difference_thread.output_image_defference.connect(self.mat2qimage) self.image_difference_thread.set_template_picture.connect(self.set_template_picture) self.image_difference_thread.start() def detect_webcam_devices(self, combo_box): _video_capture = cv2.VideoCapture() _dev_id = 0 while (_dev_id < 3): if _video_capture.open(_dev_id): combo_box.addItem("Device #" + str(_dev_id + 1), _dev_id) _dev_id += 1 else: _dev_id += 1 _video_capture.release() def load_template(self): index = self.directory_tree_view.selectedIndexes()[0] if not QFileInfo(self.file_system_model.filePath(index)).isDir(): # print("load template, path:", self.file_system_model.filePath(index)) self.get_template_filename.emit(self.file_system_model.filePath(index)) def create_template(self): if self.stream is not None: template_to_save = self.stream.get_current_frame() cv2.imwrite("../image_difference/examples/template.jpg", template_to_save) print("create template") pyqtSlot(np.ndarray) def mat2qimage(self, image): rgbImage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) rgbImage = cv2.resize(rgbImage, (self.output_picture.size().width(), self.output_picture.size().height())) # rgbImage = imutils.resize(rgbImage, height=self.output_picture.height()) h, w, ch = rgbImage.shape bytesPerLine = ch * w result_image = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888) self.output_picture.setPixmap(QPixmap.fromImage(result_image)) pyqtSlot(np.ndarray) def set_template_picture(self, image): rgbImage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # rgbImage = cv2.resize(rgbImage, (self.template_image.size().width(), # self.template_image.size().height())) rgbImage = imutils.resize(rgbImage, self.template_image.size().width()) h, w, ch = rgbImage.shape bytesPerLine = ch * w result_image = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888) self.template_image.setPixmap(QPixmap.fromImage(result_image)) if not self.template_set: self.template_set = True self.stream.getframe.disconnect(self.mat2qimage) self.stream.getframe.connect(self.image_difference_thread.get_image) self.image_difference_thread.output_image_defference.connect(self.mat2qimage) def camera_switcher_index_changed(self, index): self.camera_changed.emit(self.webcam_switcher.itemData(index)) print("current index:", index) print("item data:", self.webcam_switcher.itemData(index)) def closeEvent(self, event): self.exit_program.emit() event.accept()
class ProductRepositoryModule(QWidget, Ui_Form): def __init__(self, parent=None): super(ProductRepositoryModule, self).__init__(parent) self.setupUi(self) if '42' not in user.powers: self.close() if user.powers['42'] == 0: self.close() self.power = '{:03b}'.format(user.powers['42']) self.WC = WarehouseController() self.LC = LabrecordsController() self.PC = ProductController() self.current_button = self.radioButton_batchno self.get_product_list() def get_product_list(self): if self.current_button == self.radioButton_batchno: self.treeWidget_productbatchnolist.setVisible(True) self.treeWidget_productkindlist.setVisible(False) current_tree = self.treeWidget_productbatchnolist current_tree.hideColumn(0) elif self.current_button == self.radioButton_kind: self.treeWidget_productbatchnolist.setVisible(False) self.treeWidget_productkindlist.setVisible(True) current_tree = self.treeWidget_productkindlist else: return current_tree.clear() key_dict = {'stockamount__gt': 0} product_list = self.WC.get_productrepository( False, **key_dict ) if not len(product_list): return if current_tree == self.treeWidget_productbatchnolist: self.set_batchno_tree(current_tree, product_list) for i in range(1, 15): current_tree.resizeColumnToContents(i) elif current_tree == self.treeWidget_productkindlist: self.set_kind_tree(current_tree, product_list) for i in range(0, 6): current_tree.resizeColumnToContents(i) else: return def set_batchno_tree(self, current_tree, product_list): p_list = product_list.values(*VALUES_TUPLE_BATCHNO) """ .extra( select={ 'prodid': 'prodid', 'prodname': 'prodname', 'spec': 'spec', 'commonname': 'commonname', 'batchno': 'batchno', 'package': 'package', 'spunit': 'spunit', 'makedate': 'makedate', 'expireddates': 'expireddates' }, tables=['producingplan'], where=['producingplan.autoid=ppid'] ) """ for item in p_list: qtreeitem = QTreeWidgetItem(current_tree) qtreeitem.setText(0, str(item['autoid'])) qtreeitem.setText(1, SOURCE[item['pisource']]) qtreeitem.setText(2, item['prodid'] + ' ' + item['prodname']) qtreeitem.setText(3, item['commonname']) if item['pisource'] == 2: key_dict = {'autoid': item['hxid']} hx_batchno_list = self.PC.get_producingplan( True, *VALUES_TUPLE_PRODUCINGPLAN, **key_dict ) hx_batchno = '' if len(hx_batchno_list): hx_batchno = hx_batchno_list[0] qtreeitem.setText(4, item['batchno'] + ' ' + hx_batchno) qtreeitem.setText( 7, to_str((item['piamount'] - item[ 'hxamount'])) + '+' + to_str(item['hxamount']) ) qtreeitem.setText( 8, to_str(item['stockamount'] - item[ 'hxstockamount']) + '+' + to_str(item['hxstockamount']) ) else: qtreeitem.setText(4, item['batchno']) qtreeitem.setText(7, str(item['piamount'])) qtreeitem.setText(8, str(item['stockamount'])) qtreeitem.setText(5, item['spec']) qtreeitem.setText(6, item['package']) qtreeitem.setText(9, item['spunit']) qtreeitem.setText(10, item['position']) qtreeitem.setText(11, str(item['indate'])) if type(item['makedate']) is datetime.date: qtreeitem.setText(12, str(item['makedate'])) qtreeitem.setText(13, str(item['expireddate'])) qtreeitem.setText( 14, item['warehousemanid'] + item['warehousemanname'] ) def set_kind_tree(self, current_tree, product_list): kind_list = product_list.values(*VALUES_TUPLE_KIND).annotate( stockamount=Sum('stockamount'), piamount=Sum('piamount') ) """ .extra( select={ 'prodid': 'prodid', 'prodname': 'prodname', 'spec': 'spec', 'commonname': 'commonname', 'package': 'package', 'spunit': 'spunit' }, tables=['producingplan'], where=['producingplan.autoid=ppid'] ). \ """ for item in kind_list: qtreeitem = QTreeWidgetItem(current_tree) qtreeitem.setText(0, item['prodid'] + item['prodname']) qtreeitem.setText(1, item['commonname']) qtreeitem.setText(2, item['spec']) qtreeitem.setText(3, item['package']) qtreeitem.setText(4, to_str(item['piamount'])) qtreeitem.setText(5, to_str(item['stockamount'])) qtreeitem.setText(6, item['spunit']) pyqtSlot(bool) def on_radioButton_batchno_toggled(self, p_bool): if p_bool: self.current_button = self.radioButton_batchno self.get_product_list() pyqtSlot(bool) def on_radioButton_kind_toggled(self, p_bool): if p_bool: self.current_button = self.radioButton_kind self.get_product_list() @pyqtSlot(QPoint) def on_treeWidget_productbatchnolist_customContextMenuRequested(self, pos): if self.power[1] == '0': return id = 0 batchno = '' sender_widget = self.sender() current_item = sender_widget.currentItem() if current_item is None: return id = int(current_item.text(0)) prodid, stuffname = current_item.text(2).split(' ') batchno = current_item.text(4) menu = QMenu() button1 = menu.addAction("查看检验报告") global_pos = sender_widget.mapToGlobal(pos) action = menu.exec(global_pos) if action == button1: detail = FindCheckReportModule(prodid, batchno, self) detail.show()