def __init__(self): super(DOE2py_Utility,self).__init__('DOE2py Utility') self._Input = ControlFile('Input file') self._Weather = ControlFile('Weather file') self._Library = ControlFile('User Library') self._Version = ControlCombo('DOE-2 Version') #self._Status_1 = ControlLabel('Simulation Status:') #self._Status_2 = ControlLabel('-') self._Run = ControlButton('Run Simulation') self._Close = ControlButton('Close') self._formset = ['',(' ','_Input',' '), ('', '_Weather', '' ), ('', '_Library', '' ), ('','_Version', '' ), ('', '_Run', '' ), ('','_Close',''),''] #('','_Status_1','','_Status_2', '' ) self._Run.value = self.__RunAction self._Close.value = self.__CloseAction with open('settings-gui.json') as data_file: data = json.load(data_file) self._Input.value = data["lastinput"] self._Weather.value = data["lastweather"] self._Library.value = data["lastlibrary"] for i in range(0,len(data["doe2versions"])): self._Version.add_item(data["doe2versions"][i])
def __init__(self, name): icon_path = tools.getFileInSameDirectory(__file__, 'iconsubbg.jpg') TypeColorVideoPipe.__init__(self) OTModulePlugin.__init__(self, name, iconFile=icon_path) self._video = ModuleConnection("Video", connecting=TypeColorVideo) self._player = ControlPlayer("Video player") self._colorDomain = ControlCombo("Color domain") self._colorDomain.add_item("XYZ", cv2.COLOR_BGR2XYZ) self._colorDomain.add_item("YCrCb", cv2.COLOR_BGR2YCR_CB) self._colorDomain.add_item("HSV", cv2.COLOR_BGR2HSV) self._colorDomain.add_item("HLS", cv2.COLOR_BGR2HLS) self._colorDomain.add_item("Lab", cv2.COLOR_BGR2LAB) self._colorDomain.add_item("Luv", cv2.COLOR_BGR2LUV) self._colorDomain.changed_event = self._player.refresh self._video.changed_event = self.newVideoInputChoosen self._player.process_frame_event = self.processFrame self._formset = [ '_video', '_colorDomain', "_player", ]
class LightSourceTab(BaseWidget): """ Tab to select the lightsource device """ _lightsource = None _update_function = None def __init__(self, update_function=None): super().__init__("Light Source Tab") self._update_function = update_function self._device_select = ControlCombo(label="Light Source") self._custom = ControlEmptyWidget() self._device_select.changed_event = self._on_device_change self._device_select.add_item('None', None) for class_type in LightSource.__subclasses__(): self._device_select.add_item(class_type.__name__, class_type) def _on_device_change(self): device = self._device_select.value if callable(device): self._lightsource = device() self._custom.value = self._lightsource.get_custom_config() else: self._lightsource = None self._custom.value = None if callable(self._update_function): self._update_function({'lightsource': self._lightsource})
def __init__(self): super(SimpleExample1, self).__init__('my_variant_api') #init clinvar self._clinvariants = ControlTextArea('rsvariants', 'rs12315123') self._clinbutton = ControlButton('Press this button') self._clinresult = ControlTextArea('result') self._clinbutton.value = self.__clinbuttonAction #init flanking site self._flancchrom = ControlText('chrom') self._flancpos = ControlText('pos') self._flancthree = ControlText('expand_3prime', 300) self._flancfive = ControlText('expand_5prime', 300) self._flancassembly = ControlCombo('assembly') self._flancassembly.add_item('GRCh37') self._flancassembly.add_item('GRCh38') self._flancbutton = ControlButton('Press this button') self._flancresult = ControlTextArea('result') self._flancbutton.value = self.__flancbuttonAction self.formset = [{ "Clinvar": ('_clinvariants', '_clinbutton', '_clinresult'), "Flanking Site": [('_flancchrom', '_flancpos', '_flancthree', '_flancfive', '_flancassembly'), '_flancbutton', '_flancresult'] }]
def __init__(self, axis): super().__init__("Aux Jog") assert isinstance(axis, ControlAxis) self._axis = axis self.label = axis.get_name() self._value_field = ControlText(label="Target", default=str(axis.get_value())) self._set_button = ControlButton(label="Go to target") self._set_button.value = self._update_value self._saved_point_field = ControlCombo(label="Saved Point") self._saved_point_button = ControlButton(label="Go to saved point") self._saved_point_button.value = self._update_saved_point self._current_field = ControlLabel( label="Current Value ({})".format(axis.get_units())) self.setFrameShape(QFrame.StyledPanel) self.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)) self.set_margin(10) self.formset = [("info:{0} ({1}):".format(axis.get_name(), axis.get_units()), '', '', '_current_field'), ('_value_field', '_set_button'), ('_saved_point_field', '_saved_point_button')]
class NewAxisWindow(BaseWidget): """ Create a new Axis """ def __init__(self, done_function): super().__init__("New Axis") self._done_function = done_function self._axis_name = ControlText(label="Name") self._axis_hw_type = ControlCombo(label="HW Type", default=None) for class_type in ControlAxis.__subclasses__(): self._axis_hw_type.add_item(class_type.__name__, class_type) self._done_button = ControlButton(label="Done") self._done_button.value = self._done def _done(self): hw_type = self._axis_hw_type.value if issubclass(hw_type, ControlAxis): name = self._axis_name.value axis = hw_type(name) self._done_function(axis) self.close()
def __init__(self, timeline=None): super(ImportWindow, self).__init__('Import file', parent_win=timeline) self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo('Please select the type of file you would like to import:') self._importButton = ControlButton('Import') self._panel = ControlEmptyWidget('Panel') self._file = ControlFile('File to import') self._panel.value = self._file self._filetype.add_item('Events file', 0) self._filetype.add_item('Graph file', 1) self._filetype.add_item('Bonsai events file', 2) self._formset = [ ('_filetype', ' '), '_panel', (' ', '_importButton'), ' '] self._filetype.changed_event = self.__fileTypeChanged self._importButton.value = self.__importData from pyforms.gui.dialogs.csv_parser import CsvParserDialog self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsaiImportDlg = BonsaiImportFileDlg()
def __init__(self): super(AdminStatsApp, self).__init__('Admin stats') self._totalExec_begin = ControlDate('Starting date', '2014-10-10') self._totalExec_end = ControlDate('Ending date', '2015-10-10') self._totalExec_btn = ControlButton('Refresh') self._totalExec_graph = ControlVisVis('Total execution time') self._apps_list = ControlCombo('Filter by application') self._totalExecApp_graph = ControlVisVis( 'Total execution time per application') self._servers_list = ControlCombo('Filter by server') self._totalExecServer_graph = ControlVisVis( 'Total execution time per server') self._formset = [ ('_totalExec_begin', '_totalExec_end', '_totalExec_btn'), 'h3:Total execution time', '_totalExec_graph', 'h3:Total execution time per application', '_apps_list', '_totalExecApp_graph', 'h3:Total execution time per server', '_servers_list', '_totalExecServer_graph' ] self._totalExec_btn.value = self.__total_exec_stats self._apps_list.addItem('--- All ---', '') for application in Algorithm.objects.all(): self._apps_list.addItem(str(application.algorithm_name), str(application.algorithm_class)) self._servers_list.addItem('--- All ---', '') for server in Server.objects.all().order_by('server_name'): self._servers_list.addItem(str(server.server_name), str(server.pk))
class DOE2py_Utility(BaseWidget): def __init__(self): super(DOE2py_Utility,self).__init__('DOE2py Utility') self._Input = ControlFile('Input file') self._Weather = ControlFile('Weather file') self._Library = ControlFile('User Library') self._Version = ControlCombo('DOE-2 Version') #self._Status_1 = ControlLabel('Simulation Status:') #self._Status_2 = ControlLabel('-') self._Run = ControlButton('Run Simulation') self._Close = ControlButton('Close') self._formset = ['',(' ','_Input',' '), ('', '_Weather', '' ), ('', '_Library', '' ), ('','_Version', '' ), ('', '_Run', '' ), ('','_Close',''),''] #('','_Status_1','','_Status_2', '' ) self._Run.value = self.__RunAction self._Close.value = self.__CloseAction with open('settings-gui.json') as data_file: data = json.load(data_file) self._Input.value = data["lastinput"] self._Weather.value = data["lastweather"] self._Library.value = data["lastlibrary"] for i in range(0,len(data["doe2versions"])): self._Version.add_item(data["doe2versions"][i]) def __RunAction(self): path = os.path.dirname(os.path.realpath(__file__)) if self._Library.value <> "": ImportLib(self._Version.value, self._Library.value, path) RunDOE2(self._Input.value[:-4], self._Weather.value, self._Version.value, path) #self._Status_2.value = "Completed!" def __CloseAction(self): with open('settings-gui.json') as data_file: data = json.load(data_file) data["lastinput"] = self._Input.value data["lastweather"] = self._Weather.value data["lastlibrary"] = self._Library.value with open('settings-gui.json','w') as data_file: json.dump(data,data_file) sys.exit()
def __init__(self, done_function): super().__init__("New Axis") self._done_function = done_function self._axis_name = ControlText(label="Name") self._axis_hw_type = ControlCombo(label="HW Type", default=None) for class_type in ControlAxis.__subclasses__(): self._axis_hw_type.add_item(class_type.__name__, class_type) self._done_button = ControlButton(label="Done") self._done_button.value = self._done
def __init__(self, update_function=None): super().__init__("Light Source Tab") self._update_function = update_function self._device_select = ControlCombo(label="Light Source") self._custom = ControlEmptyWidget() self._device_select.changed_event = self._on_device_change self._device_select.add_item('None', None) for class_type in LightSource.__subclasses__(): self._device_select.add_item(class_type.__name__, class_type)
class SimpleExample1(BaseWidget): def __init__(self): super(SimpleExample1, self).__init__('my_variant_api') #init clinvar self._clinvariants = ControlTextArea('rsvariants', 'rs12315123') self._clinbutton = ControlButton('Press this button') self._clinresult = ControlTextArea('result') self._clinbutton.value = self.__clinbuttonAction #init flanking site self._flancchrom = ControlText('chrom') self._flancpos = ControlText('pos') self._flancthree = ControlText('expand_3prime', 300) self._flancfive = ControlText('expand_5prime', 300) self._flancassembly = ControlCombo('assembly') self._flancassembly.add_item('GRCh37') self._flancassembly.add_item('GRCh38') self._flancbutton = ControlButton('Press this button') self._flancresult = ControlTextArea('result') self._flancbutton.value = self.__flancbuttonAction self.formset = [{ "Clinvar": ('_clinvariants', '_clinbutton', '_clinresult'), "Flanking Site": [('_flancchrom', '_flancpos', '_flancthree', '_flancfive', '_flancassembly'), '_flancbutton', '_flancresult'] }] def __clinbuttonAction(self): results = [] for rsid in self._clinvariants.value.split('\n'): clinsig = getClinicalSignificance(rsid) results.append(clinsig) self._clinresult.value = '\n'.join(results) def __flancbuttonAction(self): chrom = self._flancchrom.value pos = self._flancpos.value five = self._flancfive.value three = self._flancthree.value assembly = self._flancassembly.value uri = 'http://grch37.rest.ensembl.org/sequence/region/human/' + chrom + ':' + pos + '..' + pos + ':1?expand_3prime=' + three + '&expand_5prime=' + five + '&content-type=text/plain' site = getEnsemblResult(uri) fiveString = site[:int(five)] threeString = site[-int(three):] current = site[int(five):int(five) + 1] self._flancresult.value = fiveString + '\n' + current + '\n' + threeString
def __init__(self, timeline=None): super(ImportWindow, self).__init__("Import file") self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo("Please select the type of file you would like to import:") self._importButton = ControlButton("Import") self._panel = ControlEmptyWidget("Panel") self._file = ControlFile("File to import") self._panel.value = self._file self._filetype.addItem("Events file", 0) self._filetype.addItem("Graph file", 1) self._filetype.addItem("Bonsai events file", 2) self._formset = [("_filetype", " "), "_panel", (" ", "_importButton"), " "] self._filetype.changed = self.__fileTypeChanged self._importButton.value = self.__importData from pyforms.dialogs import CsvParserDialog self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsaiImportDlg = BonsaiImportFileDlg()
def get_custom_config(self): """ Gets a pyforms BaseWidget to complete configuration for LinearAxis """ if self._widget is None: widget = BaseWidget("Linear Axis Config") widget.device_list = ControlCombo(label="Device") widget.device_list += ('None', None) for device in DEVICES: widget.device_list += device if self._linear_stage is not None: widget.value = self._linear_stage.serial_number print("Stage:", self._linear_stage.serial_number) print("Widget:", widget.value) widget.device_list.current_index_changed_event = self._update_stage widget.formset = ['device_list', ''] self._widget = widget self._update_stage(0) if self._linear_stage is not None: self._linear_stage.identify() return self._widget
def __init__(self, timeline=None): super(ImportWindow, self).__init__('Import file') self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo('Please select the type of file you would like to import:') self._importButton = ControlButton('Import') self._panel = ControlEmptyWidget('Panel') self._file = ControlFile('File to import') self._panel.value = self._file self._filetype.addItem('Events file', 0) self._filetype.addItem('Graph file', 1) self._filetype.addItem('Bonsai events file', 2) self._formset = [ ('_filetype', ' '), '_panel', (' ', '_importButton'), ' '] self._filetype.changed = self.__fileTypeChanged self._importButton.value = self.__importData self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsaiImportDlg = BonsaiImportFileDlg()
def __init__(self, columns, parent=None): super(GenericCsvParserDialog, self).__init__('CSV Choose the columns', parent_win=parent) self._filename = None self._columns = columns self._columns_indexes = [] self._rownum = 0 # Definition of the forms fields self._filename = ControlFile('CSV File') self._separator = ControlCombo('Separator', default='auto') self._startingrow = ControlNumber('Starting row', default=0) for index, column in enumerate(columns): setattr( self, '_col_{0}'.format(index), ControlNumber(column, default=index, minimum=-1, maximum=1000)) self._filePreview = ControlList('Preview') self._loadButton = ControlButton('Load') form_row = ['_separator'] + [ '_col_{0}'.format(index) for index, column in enumerate(columns) ] + ['_loadButton'] self._formset = [('_filename', '_startingrow'), tuple(form_row), '_filePreview'] self._separator.changed_event = self.__refreshPreview self._filename.changed_event = self.__refreshPreview self._startingrow.changed_event = self.__refreshPreview self._loadButton.value = self.load self._load_event = None self._separator.add_item('auto', 'auto') self._separator.add_item(';', ';') self._separator.add_item(',', ',') self._separator.add_item('TAB', '\t') self._separator.add_item('Excel', csv.excel) self._separator.add_item('Excel TAB', csv.excel_tab)
def laser_custom_config(): """ Get the GUI config to configure the laser The GUI is the same for each laser axis and for the laser lightsource """ global WIDGET if WIDGET is None: widget = BaseWidget("Laser Config") widget.power_supply = ControlCombo(label="Power Supply") widget.power_supply += ('None', None) for power in DEVICES['Power Supply']: widget.power_supply += power widget.power_supply.current_index_changed_event = update_laser widget.power_channel = ControlNumber(label="Power Supply Channel", default=1, minimum=1, maximum=4) widget.signal_generator = ControlCombo(label="Signal Generator") widget.signal_generator += ('None', None) for signal in DEVICES['Signal Generator']: widget.signal_generator += signal widget.signal_generator.current_index_changed_event = update_laser widget.formset = [ "h5:Laser Using", 'power_supply', 'power_channel', 'signal_generator', "(All laser axis use the same laser)" ] WIDGET = widget return WIDGET
def __init__(self, name): icon_path = tools.getFileInSameDirectory(__file__, 'iconsubbg.jpg') TypeBWVideoPipe.__init__(self) OTModulePlugin.__init__(self, name, iconFile=icon_path) self._video = ModuleConnection("Video", connecting=TypeComponentsVideoPipe) self._player = ControlPlayer("Video player") self._colorComponent = ControlCombo("Component") self._colorComponent.add_item("A", 0) self._colorComponent.add_item("B", 1) self._colorComponent.add_item("C", 2) self._colorComponent.changed_event = self.refreshValue self._video.changed_event = self.newVideoInputChoosen self._formset = [ '_video', '_colorComponent', "_player", ]
def __init__(self, update_function=None): super().__init__("Output Tab") # The update function will be called when the selected sensor changes # to fire the 'sensor' event self._update_function = update_function self._device_select = ControlCombo(label="Sensor") self._custom = ControlEmptyWidget() self._device_select.changed_event = self._on_device_change self._device_select.add_item('None', None) self._output = ControlList() self._live = ControlCheckBox(label="Live Output") self._live.changed_event = self._on_live for class_type in Sensor.__subclasses__(): self._device_select.add_item(class_type.__name__, class_type)
class OTModuleSelectComponent(OTModulePlugin, TypeBWVideoPipe): def __init__(self, name): icon_path = tools.getFileInSameDirectory(__file__, 'iconsubbg.jpg') TypeBWVideoPipe.__init__(self) OTModulePlugin.__init__(self, name, iconFile=icon_path) self._video = ModuleConnection("Video", connecting=TypeComponentsVideoPipe) self._player = ControlPlayer("Video player") self._colorComponent = ControlCombo("Component") self._colorComponent.add_item("A", 0) self._colorComponent.add_item("B", 1) self._colorComponent.add_item("C", 2) self._colorComponent.changed_event = self.refreshValue self._video.changed_event = self.newVideoInputChoosen self._formset = [ '_video', '_colorComponent', "_player", ] def refreshValue(self, value): self._player.refresh() def newVideoInputChoosen(self): ModuleConnection.changed_event(self._video) value = self._video.value if value: self.open(value) self._player.value = self print value def read(self): res, imgs = self._video.value.read() return res, imgs[self._colorComponent.value]
def __init__(self, isCreating): Movie.__init__(self, '', '', '', '') BaseWidget.__init__(self, 'Movie') self.__isCreating = isCreating self._idField = ControlText("Id") self._titleField = ControlText("Title") self._descriptionField = ControlTextArea("Description") self._genre = ControlCombo("Genre") for i in MOVIE_GENRE: self._genre += i self._buttonField = ControlButton('Add a new movie') self._buttonField.value = self._updateAction if not isCreating: self._idField.enabled = False self._buttonField.name = "Update movie" self._label = ControlLabel("")
def get_custom_config(self): """ Gets a pyforms BaseWidget to complete configuration for RotationAxis """ if self._widget is None: widget = BaseWidget("Rotate Axis Config") widget.device_list = ControlCombo(label="Device") widget.device_list += ('None', None) for device in DEVICES: widget.device_list += device if self._rotation_stage is not None: widget.value = self._rotation_stage.serial_number widget.device_list.current_index_changed_event = self._update_stage widget.distance_field = ControlNumber( label="Distance to Surface", default=self._distance_to_surface, minimum=0, maximum=float('inf'), decimals=5) widget.distance_field.key_pressed_event = self._update_distance_to_surface widget.formset = ['device_list', 'distance_field', ''] self._widget = widget self._update_stage(0) if self._rotation_stage is not None: self._rotation_stage.identify() return self._widget
class MultipleBlobDetection(BaseWidget): def __init__(self): super(MultipleBlobDetection, self).__init__( 'Multiple Blob Detection') # Definition of the forms fields self._videofile = ControlFile('Video') self._outputfile = ControlText('Results output file') self._threshold_box = ControlCheckBox('Threshold') self._threshold = ControlSlider('Binary Threshold', 114, 0, 255) self._roi_x_min = ControlSlider('ROI x top', 0, 0, 1000) self._roi_x_max = ControlSlider('ROI x bottom', 1000, 0, 1000) self._roi_y_min = ControlSlider('ROI y left', 0, 0, 1000) self._roi_y_max = ControlSlider('ROI y right', 1000, 0, 1000) # self._blobsize = ControlSlider('Minimum blob size', 100, 100, 2000) self._player = ControlPlayer('Player') self._runbutton = ControlButton('Run') self._start_frame = ControlText('Start Frame') self._stop_frame = ControlText('Stop Frame') self._color_list = ControlCombo('Color channels') self._color_list.add_item('Red Image Channel', 2) self._color_list.add_item('Green Image Channel', 1) self._color_list.add_item('Blue Image Channel', 0) self._clahe = ControlCheckBox('CLAHE ') self._dilate = ControlCheckBox('Morphological Dilation') self._dilate_type = ControlCombo('Dilation Kernel Type') self._dilate_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._dilate_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._dilate_type.add_item('CROSS', cv2.MORPH_CROSS) self._dilate_size = ControlSlider('Dilation Kernel Size', 3, 1, 10) self._erode = ControlCheckBox('Morphological Erosion') self._erode_type = ControlCombo('Erode Kernel Type') self._erode_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._erode_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._erode_type.add_item('CROSS', cv2.MORPH_CROSS) self._erode_size = ControlSlider('Erode Kernel Size', 5, 1, 10) self._open = ControlCheckBox('Morphological Opening') self._open_type = ControlCombo('Open Kernel Type') self._open_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._open_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._open_type.add_item('CROSS', cv2.MORPH_CROSS) self._open_size = ControlSlider('Open Kernel Size', 19, 1, 40) self._close = ControlCheckBox('Morphological Closing') self._close_type = ControlCombo('Close Kernel Type') self._close_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._close_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._close_type.add_item('CROSS', cv2.MORPH_CROSS) self._close_size = ControlSlider('Close Kernel Size', 19, 1, 40) self._LoG = ControlCheckBox('LoG - Laplacian of Gaussian') self._LoG_size = ControlSlider('LoG Kernel Size', 30, 1, 60) self._progress_bar = ControlProgress('Progress Bar') # Define the function that will be called when a file is selected self._videofile.changed_event = self.__videoFileSelectionEvent # Define the event that will be called when the run button is processed self._runbutton.value = self.__runEvent # Define the event called before showing the image in the player self._player.process_frame_event = self.__processFrame # Define the organization of the Form Controls self.formset = [ ('_videofile', '_outputfile'), ('_start_frame', '_stop_frame'), ('_color_list', '_clahe', '_roi_x_min', '_roi_y_min'), ('_threshold_box', '_threshold', '_roi_x_max', '_roi_y_max'), ('_dilate', '_erode', '_open', '_close'), ('_dilate_type', '_erode_type', '_open_type', '_close_type'), ('_dilate_size', '_erode_size', '_open_size', '_close_size'), ('_LoG', '_LoG_size'), '_runbutton', '_progress_bar', '_player' ] def __videoFileSelectionEvent(self): """ When the videofile is selected instanciate the video in the player """ self._player.value = self._videofile.value def __color_channel(self, frame): """ Returns only one color channel of input frame. Output is in grayscale. """ frame = frame[:, :, self._color_list.value] return frame def __create_kernels(self): """ Creates kernels for morphological operations. Check cv2.getStructuringElement() doc for more info: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/ py_morphological_ops/py_morphological_ops.html Assumed that all kernels (except LoG kernel) are square. Example of use: open_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (19, 19)) erosion_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) dilate_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) :return: _opening_kernel, _close_kernel, _erosion_kernel, \ _dilate_kernel, _LoG_kernel """ _opening_kernel = cv2.getStructuringElement(self._open_type.value, (self._open_size.value, self._open_size.value)) _close_kernel = cv2.getStructuringElement(self._close_type.value, (self._close_size.value, self._close_size.value)) _erosion_kernel = cv2.getStructuringElement(self._erode_type.value, (self._erode_size.value, self._erode_size.value)) _dilate_kernel = cv2.getStructuringElement(self._dilate_type.value, (self._dilate_size.value, self._dilate_size.value)) _LoG_kernel = get_log_kernel(self._LoG_size.value, int(self._LoG_size.value * 0.5)) return _opening_kernel, _close_kernel, _erosion_kernel, \ _dilate_kernel, _LoG_kernel def __morphological(self, frame): """ Apply morphological operations selected by the user. :param frame: input frame of selected video. :return: preprocessed frame. """ opening_kernel, close_kernel, erosion_kernel, \ dilate_kernel, log_kernel = self.__create_kernels() # prepare image - morphological operations if self._erode.value: frame = cv2.erode(frame, erosion_kernel, iterations=1) if self._open.value: frame = cv2.morphologyEx(frame, cv2.MORPH_OPEN, opening_kernel) if self._close.value: frame = cv2.morphologyEx(frame, cv2.MORPH_CLOSE, close_kernel) if self._dilate.value: frame = cv2.dilate(frame, dilate_kernel, iterations=1) # create LoG kernel for finding local maximas if self._LoG.value: frame = cv2.filter2D(frame, cv2.CV_32F, log_kernel) frame *= 255 # remove near 0 floats frame[frame < 0] = 0 return frame def __roi(self, frame): """ Define image region of interest. """ # ROI height, width = frame.shape self._roi_x_max.min = int(height / 2) self._roi_x_max.max = height self._roi_y_max.min = int(width / 2) self._roi_y_max.max = width self._roi_x_min.min = 0 self._roi_x_min.max = int(height / 2) self._roi_y_min.min = 0 self._roi_y_min.max = int(width / 2) # x axis frame[:int(self._roi_x_min.value)][::] = 255 frame[int(self._roi_x_max.value)::][::] = 255 # y axis for m in range(height): # height for n in range(width): # width if n > self._roi_y_max.value or n < self._roi_y_min.value: frame[m][n] = 255 # frame[0::][:int(self._roi_y_min.value)] = 255 # frame[0::][int(self._roi_y_max.value):] = 255 return frame def _kalman(self, max_points, stop_frame, vid_fragment): """ Kalman Filter function. Takes measurements from video analyse function and estimates positions of detected objects. Munkres algorithm is used for assignments between estimates (states) and measurements. :param max_points: measurements. :param stop_frame: number of frames to analise :param vid_fragment: video fragment for estimates displaying :return: x_est, y_est - estimates of x and y positions in the following format: x_est[index_of_object][frame] gives x position of object with index = [index_of_object] in the frame = [frame]. The same goes with y positions. """ # font for displaying info on the image font = cv2.FONT_HERSHEY_SIMPLEX index_error = 0 value_error = 0 # step of filter dt = 1. R_var = 1 # measurements variance between x-x and y-y # Q_var = 0.1 # model variance # state covariance matrix - no initial covariances, variances only # [10^2 px, 10^2 px, ..] - P = np.diag([100, 100, 10, 10, 1, 1]) # state transition matrix for 6 state variables # (position - velocity - acceleration, # x, y) F = np.array([[1, 0, dt, 0, 0.5 * pow(dt, 2), 0], [0, 1, 0, dt, 0, 0.5 * pow(dt, 2)], [0, 0, 1, 0, dt, 0], [0, 0, 0, 1, 0, dt], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]]) # x and y coordinates only - measurements matrix H = np.array([[1., 0., 0., 0., 0., 0.], [0., 1., 0., 0., 0., 0.]]) # no initial corelation between x and y positions - variances only R = np.array( [[R_var, 0.], [0., R_var]]) # measurement covariance matrix # Q must be the same shape as P Q = np.diag([100, 100, 10, 10, 1, 1]) # model covariance matrix # create state vectors, max number of states - as much as frames x = np.zeros((stop_frame, 6)) # state initialization - initial state is equal to measurements m = 0 try: for i in range(len(max_points[0])): if max_points[0][i][0] > 0 and max_points[0][i][1] > 0: x[m] = [max_points[0][i][0], max_points[0][i][1], 0, 0, 0, 0] m += 1 # required for django runserver tests except IndexError: index_error = 1 est_number = 0 # number of estimates at the start try: for point in max_points[::][0]: if point[0] > 0 and point[1] > 0: est_number += 1 except IndexError: index_error = 1 # history of new objects appearance new_obj_hist = [[]] # difference between position of n-th object in m-1 frame and position # of the same object in m frame diff_2 = [[]] # for how many frames given object was detected frames_detected = [] # x and y posterior positions (estimates) for drawnings x_est = [[] for i in range(stop_frame)] y_est = [[] for i in range(stop_frame)] # variable for counting frames where object has no measurement striked_tracks = np.zeros(stop_frame) removed_states = [] new_detection = [] ff_nr = 0 # frame number self._progress_bar.label = '3/4: Generating position estimates..' self._progress_bar.value = 0 # kalman filter loop for frame in range(stop_frame): self._progress_bar.value = 100 * (ff_nr / stop_frame) # measurements in one frame try: frame_measurements = max_points[::][frame] except IndexError: index_error = 1 measurements = [] # make list of lists, not tuples; don't take zeros, # assuming it's image if not index_error: for meas in frame_measurements: if meas[0] > 0 and meas[1] > 0: measurements.append([meas[0], meas[1]]) # count prior for i in range(est_number): x[i][::] = dot(F, x[i][::]) P = dot(F, P).dot(F.T) + Q S = dot(H, P).dot(H.T) + R K = dot(P, H.T).dot(inv(S)) ################################################################## # prepare for update phase -> get (prior - measurement) assignment posterior_list = [] for i in range(est_number): if not np.isnan(x[i][0]) and not np.isnan(x[i][1]): posterior_list.append(i) # print(i) # print(posterior_list) # # print('state\n', x[0:est_number, 0:2]) # print('\n') # temp_matrix = np.array(x[0:est_number, 0:2]) try: temp_matrix = np.array(x[posterior_list, 0:2]) temp_matrix = np.append(temp_matrix, measurements, axis=0) except ValueError: value_error = 1 # print(temp_matrix) distance = pdist(temp_matrix, 'euclidean') # returns vector # make square matrix out of vector distance = squareform(distance) temp_distance = distance # remove elements that are repeated - (0-1), (1-0) etc. # distance = distance[est_number::, 0:est_number] distance = distance[0:len(posterior_list), len(posterior_list)::] # munkres row_index, column_index = linear_sum_assignment(distance) final_cost = distance[row_index, column_index].sum() unit_cost = [] index = [] for i in range(len(row_index)): # index(object, measurement) index.append([row_index[i], column_index[i]]) unit_cost.append(distance[row_index[i], column_index[i]]) ################################################################## # index correction - take past states into account removed_states.sort() for removed_index in removed_states: for i in range(len(index)): if index[i][0] >= removed_index: index[i][0] += 1 ################################################################## # find object to reject state_list = [index[i][0] for i in range(len(index))] reject = np.ones(len(posterior_list)) i = 0 for post_index in posterior_list: if post_index not in state_list: reject[i] = 0 i += 1 # check if distance (residual) isn't to high for assignment for i in range(len(unit_cost)): if unit_cost[i] > 20: print('cost to high, removing', i) reject[i] = 0 ################################################################## # update phase for i in range(len(index)): # find object that should get measurement next # count residual y: measurement - state if index[i][1] >= 0: y = np.array([measurements[index[i][1]] - dot(H, x[index[i][0], ::])]) # posterior x[index[i][0], ::] = x[index[i][0], ::] + dot(K, y.T).T # append new positions # if x[i][0] and x[i][1]: x_est[index[i][0]].append([x[index[i][0], 0]]) y_est[index[i][0]].append([x[index[i][0], 1]]) # posterior state covariance matrix P = dot(np.identity(6) - dot(K, H), P) print('posterior\n', x[0:est_number, 0:2]) ################################################################## # find new objects and create new states for them new_index = [] measurement_indexes = [] for i in range(len(index)): if index[i][1] >= 0.: # measurements that have assignment measurement_indexes.append(index[i][1]) for i in range(len(measurements)): if i not in measurement_indexes: # find measurements that don't have assignments new_index.append(i) new_detection.append([measurements[new_index[i]] for i in range(len(new_index))]) # for every detections in the last frame for i in range(len(new_detection[len(new_detection) - 1])): if new_detection[frame][i] and \ new_detection[frame][i][0] > 380: x[est_number, ::] = [new_detection[frame][i][0], new_detection[frame][i][1], 0, 0, 0, 0] est_number += 1 # print('state added', est_number) # print('new posterior\n', x[0:est_number, 0:2]) ################################################################## # find states without measurements and remove them no_track_list = [] for i in range(len(reject)): if not reject[i]: no_track_list.append(posterior_list[i]) # print('no_trk_list', no_track_list) for track in no_track_list: if track >= 0: striked_tracks[track] += 1 print('track/strikes', track, striked_tracks[track]) for i in range(len(striked_tracks)): if striked_tracks[i] >= 1: x[i, ::] = [None, None, None, None, None, None] if i not in removed_states: removed_states.append(i) print('state_removed', i) ff_nr += 1 # print(removed_states) # print(index) return x_est, y_est, est_number def _plot_points(self, vid_frag, max_points, x_est, y_est, est_number): self._progress_bar.label = '4/4: Plotting - measurements..' self._progress_bar.value = 0 # plot raw measurements for frame_positions in max_points: for pos in frame_positions: plt.plot(pos[0], pos[1], 'r.') # try: plt.axis([0, vid_frag[0].shape[1], vid_frag[0].shape[0], 0]) # except IndexError: # index_error = 1 plt.xlabel('width [px]') plt.ylabel('height [px]') plt.title('Objects raw measurements') ###################################################################### # image border - 10 px x_max = vid_frag[0].shape[1] - 10 y_max = vid_frag[0].shape[0] - 10 self._progress_bar.label = '4/4: Plotting - estimates..' self._progress_bar.value = 0 i = 0 # plot estimated trajectories for ind in range(est_number): self._progress_bar.value = 100 * (i / est_number) i += 1 # if estimate exists if len(x_est[ind]): for pos in range(len(x_est[ind])): # don't draw near 0 points and near max points if not np.isnan(x_est[ind][pos][0]) and \ x_est[ind][pos][0] > 10 and \ y_est[ind][pos][0] > 10 and \ x_est[ind][pos][0] < x_max - 10 and \ y_est[ind][pos][0] < y_max - 10: plt.plot(x_est[ind][pos][0], y_est[ind][pos][0], 'g.') # plt.plot(x_est[ind][::], y_est[ind][::], 'g-') # print(frame) # [xmin xmax ymin ymax] # try: plt.axis([0, vid_frag[0].shape[1], vid_frag[0].shape[0], 0]) # except IndexError: # index_error = 1 plt.xlabel('width [px]') plt.ylabel('height [px]') plt.title('Objects estimated trajectories') plt.grid() plt.show() def __processFrame(self, frame): """ Do some processing to the frame and return the result frame """ # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) frame = self.__color_channel(frame) if self._clahe.value: clahe = cv2.createCLAHE(clipLimit=8.0, tileGridSize=(8, 8)) frame = clahe.apply(frame) frame = self.__roi(frame) if self._threshold_box.value: ret, frame = cv2.threshold(frame, self._threshold.value, 255, cv2.THRESH_BINARY) frame = self.__morphological(frame) return frame def __runEvent(self): """ After setting the best parameters run the full algorithm """ if not self._start_frame.value or not self._stop_frame.value or \ self._start_frame.value >= self._stop_frame.value: raise ValueError('Wrong start or stop frame!') start_frame = int(self._start_frame.value) stop_frame = int(self._stop_frame.value) # pass cv2.VideoCapture object, not string # my_video = self._player.value video = self._player.value # self._load_bar.__init__('Processing..') vid_fragment = select_frames(video, start_frame, stop_frame) try: height = vid_fragment[0].shape[0] width = vid_fragment[0].shape[1] except IndexError: raise IndexError('No video loaded. Check video path.') i = 0 bin_frames = [] # preprocess image loop self._progress_bar.label = '1/4: Creating BW frames..' self._progress_bar.value = 0 for frame in vid_fragment: gray_frame = self.__color_channel(frame) # create a CLAHE object (Arguments are optional) if self._clahe.value: clahe = cv2.createCLAHE(clipLimit=8.0, tileGridSize=(8, 8)) gray_frame = clahe.apply(gray_frame) # ROI gray_frame = self.__roi(gray_frame) ret, th1 = cv2.threshold(gray_frame, self._threshold.value, 255, cv2.THRESH_BINARY) # frame_thresh1 = otsu_binary(cl1) bin_frames.append(th1) self._progress_bar.value = 100*(i/len(vid_fragment)) i += 1 ###################################################################### i = 0 maxima_points = [] # gather measurements loop self._progress_bar.label = '2/4: Finding local maximas..' self._progress_bar.value = 0 for frame in bin_frames: frame = self.__morphological(frame) # get local maximas of filtered image per frame maxima_points.append(local_maxima(frame)) self._progress_bar.value = 100 * (i / len(bin_frames)) i += 1 x_est, y_est, est_number = self._kalman(maxima_points, stop_frame, vid_fragment) print('\nFinal estimates number:', est_number) self._plot_points(vid_fragment, maxima_points, x_est, y_est, est_number) print('EOF - DONE')
class ImportWindow(BaseWidget): def __init__(self, timeline=None): super(ImportWindow, self).__init__('Import file', parentWindow=timeline) self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo('Please select the type of file you would like to import:') self._importButton = ControlButton('Import') self._panel = ControlEmptyWidget('Panel') self._file = ControlFile('File to import') self._panel.value = self._file self._filetype.addItem('Events file', 0) self._filetype.addItem('Graph file', 1) self._filetype.addItem('Bonsai events file', 2) self._formset = [ ('_filetype', ' '), '_panel', (' ', '_importButton'), ' '] self._filetype.changed = self.__fileTypeChanged self._importButton.value = self.__importData from pyforms.gui.dialogs.csv_parser import CsvParserDialog self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsaiImportDlg = BonsaiImportFileDlg() def __fileTypeChanged(self): if self._filetype.value == 0: self._panel.value = self._file elif self._filetype.value == 1: self._panel.value = self._graphCsvParserDlg elif self._filetype.value == 2: self._panel.value = self._bonsaiImportDlg def __importData(self): if self._filetype.value == 0: separator = ',' with open(self._file.value, 'rU') as csvfile: line = csvfile.readline() if ";" in line: separator = ';' with open(self._file.value, 'rU') as csvfile: csvfile = csv.reader(csvfile, delimiter=separator) self._timeline._time.import_csv(csvfile) elif self._filetype.value == 1: self._timeline._time.importchart_csv(self._graphCsvParserDlg) self._timeline.show_graphs_properties() elif self._filetype.value == 2: with open(self._bonsaiImportDlg._file.value, 'rU') as csvfile: values = [] pointEventValues = [] csvfile = csv.reader(csvfile, delimiter=' ') for row in csvfile: # strip Start/End word from all events names which are not PointEven try: timestr = row[1].rstrip('0') cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") except: timestr = row[1] cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() frame = int(round(self._bonsaiImportDlg._fps.value * seconds)) if row[2] == "PointEvent": eventtype = row[0] pointEventValues.append([eventtype, frame, row[2]]) else: if row[0].startswith('Start'): eventtype = row[0][len('Start'):] # strip Start word from the beginning else: eventtype = row[0][len('End'):] # strip End word from the beginning values.append([eventtype, frame, row[2]]) values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) ntracks = len(set([x[0] for x in values])) + 1 # collapse events = [] eventsTypes = {} # Events names currentTrack = 0 for index in range(0, len(pointEventValues)): pointEventValue = pointEventValues[index] eventsTypes[pointEventValue[0]] = currentTrack self._timeline.addPeriod([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], track=currentTrack) currentTrack = 1 for index in range(0, len(values), 2): row0 = values[index] row1 = values[index + 1] if row0[0] not in eventsTypes: eventsTypes[row0[0]] = currentTrack track = currentTrack currentTrack += 1 else: track = eventsTypes[row0[0]] self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) self.close() # pylint: disable=no-member def import_chart(self, filename, frame_col=0, val_col=1): self._filetype.value = 1 self._graphCsvParserDlg.filename = filename self._graphCsvParserDlg.frameColumn = frame_col self._graphCsvParserDlg.xColumn = val_col
class ImportWindow(BaseWidget): def __init__(self, timeline=None): super(ImportWindow, self).__init__('Import file') self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo('Please select the type of file you would like to import:') self._importButton = ControlButton('Import') self._panel = ControlEmptyWidget('Panel') self._file = ControlFile('File to import') self._panel.value = self._file self._filetype.addItem('Events file', 0) self._filetype.addItem('Graph file', 1) self._filetype.addItem('Bonsai events file', 2) self._formset = [ ('_filetype', ' '), '_panel', (' ', '_importButton'), ' '] self._filetype.changed = self.__fileTypeChanged self._importButton.value = self.__importData self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsaiImportDlg = BonsaiImportFileDlg() def __fileTypeChanged(self): if self._filetype.value == 0: self._panel.value = self._file elif self._filetype.value == 1: self._panel.value = self._graphCsvParserDlg elif self._filetype.value == 2: self._panel.value = self._bonsaiImportDlg def __importData(self): if self._filetype.value == 0: separator = ',' with open(self._file.value, 'rU') as csvfile: line = csvfile.readline() if ";" in line: separator = ';' with open(self._file.value, 'rU') as csvfile: csvfile = csv.reader(csvfile, delimiter=separator) self._timeline._time.import_csv(csvfile) elif self._filetype.value == 1: self._timeline._time.importchart_csv(self._graphCsvParserDlg) elif self._filetype.value == 2: with open(self._bonsaiImportDlg._file.value, 'rU') as csvfile: values = [] csvfile = csv.reader(csvfile, delimiter=' ') for row in csvfile: try: timestr = row[1].rstrip('0') cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") except: timestr = row[1] cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() frame = int(round(self._bonsaiImportDlg._fps.value * seconds)) if row[0].startswith('Start'): eventtype = row[0][5:] else: eventtype = row[0][3:] values.append([eventtype, frame, row[2]]) values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) ntracks = len(set([x[0] for x in values])) # collapse events = [] eventsTypes = {} currentTrack = 0 for index in range(0, len(values), 2): row0 = values[index] row1 = values[index + 1] if row0[0] not in eventsTypes: eventsTypes[row0[0]] = currentTrack track = currentTrack currentTrack += 1 else: track = eventsTypes[row0[0]] self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) self.close()
def __init__(self): Globals.init() # Initialize the Metronome GUI BaseWidget.__init__(self, "AutoMetronome") # Create the Settings GUI # Metronome Tab self._togglePause = ControlButton("Play/Pause", checkable=True) self._minusOne = ControlButton("-") self._addOne = ControlButton("+") self._togglePause.value = self.togglePauseAction self._minusOne.value = self.minusOneAction self._addOne.value = self.addOneAction # Settings Tab self._minTempoInput = ControlText(label="Minimum Tempo", defaultValue="30") self._maxTempoInput = ControlText(label="Maximum Tempo", defaultValue="255") self._timeSignatureNumeratorInput = ControlNumber(label="Time Signature:", defaultValue=4) self._timeSignatureDenominatorInput = ControlNumber(label="/",defaultValue=4) self._subdivisionInput = ControlNumber("Subdivisions per Beat:", defaultValue=1) self._tempoDividerSet = ControlCombo("Tempo Defined ") self._tempoDividerSet.addItem("In Full Value", value="quarter") self._tempoDividerSet.addItem("In Cut Time", value="half") self._tempoDividerSet.addItem("In One", value="one") self._tempoDividerSet.addItem("In Two", value="eighth") self._tempoDividerSet.addItem("By Dotted Eighth Note (for 6/8 or similar times)", value="eighth_dot") self._tempoDividerSet.addItem("By Dotted Quarter Note (for 6/8 or similar times)", value="quarter_dot") self._updateSettings = ControlButton("Save") self._updateSettings.value = self.updateSettingsAction # Programming Tab self._runProgram = ControlButton("Run Program") self._runProgram.value = self.runProgramAction self._loadProgram = ControlFile(label="Load Program") self._programmingPanel = ControlDockWidget() programmingWindow = Programming() programmingWindow.parent = self self._programmingPanel.value = programmingWindow # self._programmingPanel.hide() # End of UI creation global minTempo global maxTempo minTempo = int(self._minTempoInput.value) maxTempo = int(self._maxTempoInput.value) global timeSignatureNumerator global timeSignatureDenominator timeSignatureNumerator = int(self._timeSignatureNumeratorInput.value) timeSignatureDenominator = int(self._timeSignatureDenominatorInput.value) global subdivision subdivision = float(self._subdivisionInput.value) global tempoDivider global bpmMultiplier tempoDivider = self._tempoDividerSet.value bpmMultiplier = 1 self._metronomeStatusLabel = ControlLabel("Time Signature: "+str(timeSignatureNumerator)+"/"+str(timeSignatureDenominator)) self._metronomeSubdivLabel = ControlLabel("Subdivision: "+str(subdivision)) # Draw the metronome Metronome.drawMetronome(self) # Set layout self._formset = [ { 'Metronome': [('_tempoSlider', '_minusOne','_addOne'), ('_metronomeStatusLabel', '_metronomeSubdivLabel'),'=','_togglePause'], 'Settings': ['_minTempoInput', '_maxTempoInput',('_timeSignatureNumeratorInput', '_timeSignatureDenominatorInput'), '_subdivisionInput', '_tempoDividerSet','_updateSettings'], 'Programming':['_runProgram', '_loadProgram'], 'Vade Mecum':['Programming: \n The window is relatively self explanatory, \n but there are a few hidden details. If you name an Event \"STOP\", \n the program will automatically stop at the beginning of that measure.\n If you name an Event \"REPEAT\", you can put the Event number \n (first Event being \'1\') in the Beats column \n and the number of times to repeat in the BPM column. \n \n Saving/Loading: \n Saving a program happens automatically when you open a file \n in the Save Program window. There is no feedback \n to indicate this yet.'] }]
class GenericCsvParserDialog(BaseWidget): def __init__(self, columns, parent=None): super(GenericCsvParserDialog, self).__init__('CSV Choose the columns', parent_win=parent) self._filename = None self._columns = columns self._columns_indexes = [] self._rownum = 0 # Definition of the forms fields self._filename = ControlFile('CSV File') self._separator = ControlCombo('Separator', default='auto') self._startingrow = ControlNumber('Starting row', default=0) for index, column in enumerate(columns): setattr( self, '_col_{0}'.format(index), ControlNumber(column, default=index, minimum=-1, maximum=1000)) self._filePreview = ControlList('Preview') self._loadButton = ControlButton('Load') form_row = ['_separator'] + [ '_col_{0}'.format(index) for index, column in enumerate(columns) ] + ['_loadButton'] self._formset = [('_filename', '_startingrow'), tuple(form_row), '_filePreview'] self._separator.changed_event = self.__refreshPreview self._filename.changed_event = self.__refreshPreview self._startingrow.changed_event = self.__refreshPreview self._loadButton.value = self.load self._load_event = None self._separator.add_item('auto', 'auto') self._separator.add_item(';', ';') self._separator.add_item(',', ',') self._separator.add_item('TAB', '\t') self._separator.add_item('Excel', csv.excel) self._separator.add_item('Excel TAB', csv.excel_tab) @property def load_file_event(self): return self._load_event @load_file_event.setter def load_file_event(self, value): self._load_event = value def __iter__(self): if self._filename.value != None and self._filename.value != '': csvfile = open(self._filename.value, 'U') if self.delimiter in ['auto', csv.excel, csv.excel_tab]: try: dialect = csv.Sniffer().sniff(csvfile.read(1024)) csvfile.seek(0) self._spamreader = csv.reader(csvfile, dialect) except: self._spamreader = None return self else: self._spamreader = csv.reader(csvfile, delimiter=self.delimiter) for i in range(int(self._startingrow.value)): next(self._spamreader, None) # skip the headers else: self._spamreader = None return self # For compatibility with python 3 def __next__(self): return self.next() def next(self): if self._spamreader != None: row = next(self._spamreader) res = [] for col in self._columns_indexes: if col == -1: res.append(self._rownum) else: if row[col].lower() == 'nan': res.append('None') else: res.append(row[col]) self._rownum += 1 return res else: raise StopIteration() def __refreshPreview(self): if self._filename.value != None and self._filename.value != '': with open(self._filename.value, 'U') as csvfile: if self.delimiter in ['auto', csv.excel, csv.excel_tab]: try: dialect = csv.Sniffer().sniff(csvfile.read(1024)) csvfile.seek(0) spamreader = csv.reader(csvfile, dialect) except: self.message('Error when reading the file.') return else: spamreader = csv.reader(csvfile, delimiter=self.delimiter) for i in range(int(self._startingrow.value)): next(spamreader, None) # skip the headers self._filePreview.value = [] self._filePreview.horizontalHeaders = map(str, range(1000)) for i, row in enumerate(spamreader): self._filePreview += row if i >= 10: break @property def delimiter(self): return self._separator.value def load(self): self.__refreshPreview() self._columns_indexes = [] for index, column in enumerate(self._columns): self._columns_indexes.append( int(getattr(self, '_col_{0}'.format(index)).value)) if self._load_event is not None: self._load_event()
class Metronome(Programming, BaseWidget): # def global non-settings variables global playing playing = False global bpm global checkSliderThread global metronomeSoundThread global metronomeTime global timeSignatureNumerator global timeSignatureDenominator global subdivision Globals.programRunning = False # def global settings variables global minTempo global maxTempo def metronomeSound(self): global bpm global playing global metronomeTime global timeSignatureNumerator global timeSignatureDenominator global subdivision global measure measure = 0 global tempoChangeCount count = 0 global initialized initialized = False ## The numerator is the number of beats played. ## The denominator is the speed of the beats. ## If the the numerator is the same as the denominator, the the tempo should remain the same. ## If the numerator is not, the tempo should be increased by the denominator divided by four. ## TODO: Add changable beat definitions ## If the numerator is not, the numerator should be divided by the denominator divided by four. metronomeTime = (60.0 / bpm)/int(subdivision) beatOne = pyglet.media.load("sound/beatOne.wav", streaming=False) quarterBeat = pyglet.media.load("sound/quarterBeat.wav", streaming=False) offBeat = pyglet.media.load("sound/offBeat.wav", streaming=False) count = (timeSignatureNumerator*int(subdivision)) timeSigMem = timeSignatureNumerator if not Globals.programRunning: print("Metronome Clicking as metronome") while playing: # May add again later - was moved down to be universal # if metronomeTime != 60.0 / bpm : metronomeTime = 60.0 / bpm if timeSigMem != timeSignatureNumerator: measure = 1 player = beatOne.play() print("UPDATE COUNT!") count = (timeSignatureNumerator*subdivision) timeSigMem = timeSignatureNumerator else: if count%(timeSignatureNumerator*subdivision) == 0: player = beatOne.play() measure += 1 else: if count%subdivision != 0 or subdivision == 1: player = quarterBeat.play() else: player = offBeat.play() Metronome.busy_wait(self, metronomeTime) player.delete() count += 1 Globals.programRunning = False else: print("Metronome Clicking as Program") global currentEvent currentEvent = 0 global programmedBPM programmedBPM = Globals.globalEventList[0][1] global measure global repeatNumber repeatNumber = 1 global changingTempo changingTempo = False global tempoChangeCount tempoChangeCount = 0 while playing: metronomeTime = (60.0 / float(programmedBPM))/float(subdivision) subdivision = int(subdivision) # May add again later - was moved down to be universal # if metronomeTime != 60.0 / bpm : metronomeTime = 60.0 / bpm if int(count) % (int(timeSignatureNumerator)*int(subdivision)) == 0: try: if Globals.globalEventList[currentEvent][0] == "STOP" and measure == int(Globals.globalEventList[currentEvent][5]): print("Program Ended") self._runProgram.label="Run Program" playing = False Globals.programRunning = False break else: if measure == int(Globals.globalEventList[currentEvent][5])-1: print("Event Triggered: "+str(Globals.globalEventList[currentEvent][0])) if int(Globals.globalEventList[currentEvent][6]) > 1: global changingTempo changingTempo = True tempoChange = int(Globals.globalEventList[currentEvent][1]) - int(programmedBPM) global tempoPerBeat tempoPerBeat = tempoChange/int(Globals.globalEventList[currentEvent][6]) else: programmedBPM = Globals.globalEventList[currentEvent][1] global timeSignatureNumerator global timeSignatureDenominator global subdivision timeSignatureNumerator = Globals.globalEventList[currentEvent][2] timeSignatureDenominator = Globals.globalEventList[currentEvent][3] subdivision = Globals.globalEventList[currentEvent][4] programmedBPM = programmedBPM*(int(timeSignatureDenominator)/4) subdivision = int(subdivision) timeSignatureNumerator = int(timeSignatureNumerator) global count count = timeSignatureNumerator self._tempoSlider.value = programmedBPM self._metronomeStatusLabel.value = ("Time Signature: "+str(timeSignatureNumerator)+"/"+str(timeSignatureDenominator)) self._metronomeSubdivLabel.value = ("Subdivision: "+str(subdivision)) player = beatOne.play() measure += 1 try: Globals.globalEventList[currentEvent][6] except IndexError: print("Program Ended") self._runProgram.label="Run Program" playing = False Globals.programRunning = False break except IndexError: print("Program Ended") self._runProgram.label="Run Program" playing = False Globals.programRunning = False break if Globals.globalEventList[currentEvent][0] == "REPEAT" and repeatNumber > 0: global initialized if initialized: global repeatNumber repeatNumber -= 1 else: global repeatNumber repeatNumber = Globals.globalEventList[currentEvent][2] initialized = True currentEvent = int(int(Globals.globalEventList[currentEvent][1])-1) global currentEvent currentEvent = currentEvent+1 int(currentEvent) else: if Globals.globalEventList[currentEvent-1][0] == "STOP" and measure == int(Globals.globalEventList[currentEvent-1][5]): print("Program Ended") self._runProgram.label="Run Program" playing = False Globals.programRunning = False break else: if count%subdivision != 0 or subdivision == 1: player = quarterBeat.play() try: global changingTempo if changingTempo == True and tempoChangeCount <= int(Globals.globalEventList[currentEvent][6]): global programmedBPM programmedBPM = int(programmedBPM)+int(tempoPerBeat) print(programmedBPM) global tempoChangeCount tempoChangeCount += 1 print(tempoChangeCount) except IndexError: print("Program Ended") self._runProgram.label="Run Program" playing = False Globals.programRunning = False break else: player = offBeat.play() Metronome.busy_wait(self, metronomeTime) player.delete() count = int(count)+1 def drawMetronome(self): # Create the Metronome GUI self._tempoSlider = ControlSlider("Tempo", defaultValue=120, min=minTempo, max=maxTempo) self._togglePause = ControlButton("Play/Pause", checkable=True) self._minusOne = ControlButton("-") self._addOne = ControlButton("+") self._togglePause.value = self.togglePauseAction self._minusOne.value = self.minusOneAction self._addOne.value = self.addOneAction global bpm bpm = self._tempoSlider.value def __init__(self): Globals.init() # Initialize the Metronome GUI BaseWidget.__init__(self, "AutoMetronome") # Create the Settings GUI # Metronome Tab self._togglePause = ControlButton("Play/Pause", checkable=True) self._minusOne = ControlButton("-") self._addOne = ControlButton("+") self._togglePause.value = self.togglePauseAction self._minusOne.value = self.minusOneAction self._addOne.value = self.addOneAction # Settings Tab self._minTempoInput = ControlText(label="Minimum Tempo", defaultValue="30") self._maxTempoInput = ControlText(label="Maximum Tempo", defaultValue="255") self._timeSignatureNumeratorInput = ControlNumber(label="Time Signature:", defaultValue=4) self._timeSignatureDenominatorInput = ControlNumber(label="/",defaultValue=4) self._subdivisionInput = ControlNumber("Subdivisions per Beat:", defaultValue=1) self._tempoDividerSet = ControlCombo("Tempo Defined ") self._tempoDividerSet.addItem("In Full Value", value="quarter") self._tempoDividerSet.addItem("In Cut Time", value="half") self._tempoDividerSet.addItem("In One", value="one") self._tempoDividerSet.addItem("In Two", value="eighth") self._tempoDividerSet.addItem("By Dotted Eighth Note (for 6/8 or similar times)", value="eighth_dot") self._tempoDividerSet.addItem("By Dotted Quarter Note (for 6/8 or similar times)", value="quarter_dot") self._updateSettings = ControlButton("Save") self._updateSettings.value = self.updateSettingsAction # Programming Tab self._runProgram = ControlButton("Run Program") self._runProgram.value = self.runProgramAction self._loadProgram = ControlFile(label="Load Program") self._programmingPanel = ControlDockWidget() programmingWindow = Programming() programmingWindow.parent = self self._programmingPanel.value = programmingWindow # self._programmingPanel.hide() # End of UI creation global minTempo global maxTempo minTempo = int(self._minTempoInput.value) maxTempo = int(self._maxTempoInput.value) global timeSignatureNumerator global timeSignatureDenominator timeSignatureNumerator = int(self._timeSignatureNumeratorInput.value) timeSignatureDenominator = int(self._timeSignatureDenominatorInput.value) global subdivision subdivision = float(self._subdivisionInput.value) global tempoDivider global bpmMultiplier tempoDivider = self._tempoDividerSet.value bpmMultiplier = 1 self._metronomeStatusLabel = ControlLabel("Time Signature: "+str(timeSignatureNumerator)+"/"+str(timeSignatureDenominator)) self._metronomeSubdivLabel = ControlLabel("Subdivision: "+str(subdivision)) # Draw the metronome Metronome.drawMetronome(self) # Set layout self._formset = [ { 'Metronome': [('_tempoSlider', '_minusOne','_addOne'), ('_metronomeStatusLabel', '_metronomeSubdivLabel'),'=','_togglePause'], 'Settings': ['_minTempoInput', '_maxTempoInput',('_timeSignatureNumeratorInput', '_timeSignatureDenominatorInput'), '_subdivisionInput', '_tempoDividerSet','_updateSettings'], 'Programming':['_runProgram', '_loadProgram'], 'Vade Mecum':['Programming: \n The window is relatively self explanatory, \n but there are a few hidden details. If you name an Event \"STOP\", \n the program will automatically stop at the beginning of that measure.\n If you name an Event \"REPEAT\", you can put the Event number \n (first Event being \'1\') in the Beats column \n and the number of times to repeat in the BPM column. \n \n Saving/Loading: \n Saving a program happens automatically when you open a file \n in the Save Program window. There is no feedback \n to indicate this yet.'] }] # Multithreaded slider process defined here def checkSlider(self): while(playing): global bpm global bpmMultiplier global metronomeTime global subdivision if bpm != self._tempoSlider.value*float(bpmMultiplier): bpm = self._tempoSlider.value*float(bpmMultiplier) metronomeTime = (60.0/bpm)/subdivision print("BPM updated to "+str(bpm)) time.sleep(0.1) # define the Play/Pause Button action def togglePauseAction(self): global playing if playing == False: print("Playing at "+str(self._tempoSlider.value)+"bpm") playing = True global bpm bpm = self._tempoSlider.value # Start Metronome global metronomeSoundThread metronomeSoundThread = threading.Thread(name='metronomeSoundThread', target=Metronome.metronomeSound, args=(self,)) metronomeSoundThread.setDaemon(True) metronomeSoundThread.start() # Start Slider polling global checkSliderThread checkSliderThread = threading.Thread(name='checkSliderThread', target=Metronome.checkSlider, args=(self,)) checkSliderThread.setDaemon(True) checkSliderThread.start() else: print("Stopped at "+str(self._tempoSlider.value)+"bpm") playing = False # define the add/subtract bpm buttons def minusOneAction(self): self._tempoSlider.value -= 1 def addOneAction(self): self._tempoSlider.value += 1 # define the update settings button action def updateSettingsAction(self): #Save the min/max tempos global minTempo global maxTempo global timeSignatureNumerator global timeSignatureDenominator global subdivision global metronomeTime global bpm global bpmMultiplier global tempoDivider minTempo = int(float(self._minTempoInput.value)) maxTempo = int(float(self._maxTempoInput.value)) timeSignatureNumerator = int(float(self._timeSignatureNumeratorInput.value)) timeSignatureDenominator = int(float(self._timeSignatureDenominatorInput.value)) tempoDivider = self._tempoDividerSet.value # SKETCHY SUBDIVISION VALUES - CHECK HERE FOR GLITCHES # TODO: Bug testing! subdivision = int(float(self._subdivisionInput.value)) metronomeTime = (60.0/bpm)/subdivision bpm = bpm*(timeSignatureDenominator/4) # SKETCHY NEW NOTE LENGTH DEFINITIONS if tempoDivider == "quarter": bpmMultiplier = 1 elif tempoDivider == "half": bpmMultiplier = 2 elif tempoDivider == "one": bpmMultiplier = float(1/float(timeSignatureNumerator)) timeSignatureNumerator = 1 elif tempoDivider == "eighth": bpmMultiplier = 0.5 timeSignatureNumerator = timeSignatureNumerator/2 elif tempoDivider == "eighth_dot": bpmMultiplier = float(0.25*(3.0/2.0)*(timeSignatureDenominator/4)) elif tempoDivider == "quarter_dot": bpmMultiplier = float(0.5*(3.0/2.0)*(timeSignatureDenominator/4)) else: print("bpmMultiplier not recognized") bpmMultiplier = bpmMultiplier*(timeSignatureDenominator/4) # End sketchy self._tempoSlider.min = minTempo self._tempoSlider.max = maxTempo self._metronomeStatusLabel.value ="Time Signature: "+str(timeSignatureNumerator)+"/"+str(timeSignatureDenominator) self._metronomeSubdivLabel.value = "Subdivision: "+str(subdivision) # More accurate sleep, thanks to StackOverflow 17499837. Takes CPU, but that is required to be accurate. def busy_wait(self, waitTime): current_time = time.time() while (time.time() < current_time+waitTime): pass def runProgramAction(self): global playing if Globals.programRunning and playing: print("Stopping Program") Globals.programRunning = False playing = False self._runProgram.label="Run Program" else: print("Running Program") Globals.programRunning = True playing = True # Start Metronome global metronomeSoundThread metronomeSoundThread = threading.Thread(name='metronomeSoundThread', target=Metronome.metronomeSound, args=(self,)) metronomeSoundThread.setDaemon(True) metronomeSoundThread.start() self._runProgram.label="Stop Program"
def _update_shown_axis(self): index = self._axis_list.selected_row_index if not index is None: axis = self._axis[index] if not axis is None: assert isinstance(axis, ControlAxis) # Get the hardware type from the name of the class self._axis_hw_type.value = type(axis).__name__ # Update the minimum box if not self._min.visible: self._min.visible = True self._min.label = "Minimum ({})".format(axis.get_units()) self._events = False self._min.value = axis.get_min() self._events = True # Update the maximum box if not self._max.visible: self._max.visible = True self._max.label = "Maximum ({})".format(axis.get_units()) self._events = False self._max.value = axis.get_max() self._events = True # Update the norm_minimum box if not self._norm_min.visible: self._norm_min.visible = True self._norm_min.label = " 0% ({})".format(axis.get_units()) self._events = False self._norm_min.value = axis.get_norm_min() self._events = True # Update the norm_maximum box if not self._norm_max.visible: self._norm_max.visible = True self._norm_max.label = "100% ({})".format(axis.get_units()) self._events = False self._norm_max.value = axis.get_norm_max() self._events = True # Populate the special axis combo special_axis = ControlCombo(label="Special Axis") special_axis.add_item('', '') special_axis.add_item("X Axis", 'xaxis') special_axis.add_item("Y Axis", 'yaxis') if axis == self._xaxis: special_axis.value = 'xaxis' elif axis == self._yaxis: special_axis.value = 'yaxis' def axis_changed(_): """ Called when axis changed """ if special_axis.value == 'xaxis': self._xaxis = axis if self._yaxis == axis: self._yaxis = None elif special_axis.value == 'yaxis': self._yaxis = axis if self._xaxis == axis: self._xaxis = None else: if self._xaxis == axis: self._xaxis = None if self._yaxis == axis: self._yaxis = None self._send_events() print("Making Special Combo") special_axis.current_index_changed_event = axis_changed self._events = False self._special_axis.value = None self._special_axis.value = special_axis self._events = True # Update the custom config GUI self._axis_custom.value = axis.get_custom_config() self._save_button.visible = True else: self._axis_hw_type.value = '' self._min.visible = False self._max.visible = False self._norm_min.visible = False self._norm_max.visible = False self._special_axis.value = None self._axis_custom.value = None self._save_button.visible = False else: self._axis_hw_type.value = '' self._min.visible = False self._max.visible = False self._norm_min.visible = False self._norm_max.visible = False self._special_axis.value = None self._axis_custom.value = None self._save_button.visible = False
class AuxJog(BaseWidget): """ A Widget to jog aux axis """ _last_set_value = 0 label = "" def __init__(self, axis): super().__init__("Aux Jog") assert isinstance(axis, ControlAxis) self._axis = axis self.label = axis.get_name() self._value_field = ControlText(label="Target", default=str(axis.get_value())) self._set_button = ControlButton(label="Go to target") self._set_button.value = self._update_value self._saved_point_field = ControlCombo(label="Saved Point") self._saved_point_button = ControlButton(label="Go to saved point") self._saved_point_button.value = self._update_saved_point self._current_field = ControlLabel( label="Current Value ({})".format(axis.get_units())) self.setFrameShape(QFrame.StyledPanel) self.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)) self.set_margin(10) self.formset = [("info:{0} ({1}):".format(axis.get_name(), axis.get_units()), '', '', '_current_field'), ('_value_field', '_set_button'), ('_saved_point_field', '_saved_point_button')] def _update_value(self): value = self._value_field.value self._axis.goto_value(value) def _update_saved_point(self): self._axis.goto_value(self._saved_point_field.value) def update_events(self, events): #print("Aux Event:", events) if 'saved_points' in events: self._saved_point_field.clear() for key, value in events['saved_points'].items(): self._saved_point_field += (key, key) def timer_update(self): self._current_field.value = "{0:.5f}".format( self._axis.get_current_value()) if self._axis.get_string_value() != self._last_set_value: self._value_field.value = self._axis.get_string_value() self._last_set_value = self._axis.get_string_value()
class ImportWindow(BaseWidget): def __init__(self, timeline=None): super(ImportWindow, self).__init__('Import file', parent_win=timeline) self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo('Please select the type of file you would like to import:') self._importButton = ControlButton('Import') self._panel = ControlEmptyWidget('Panel') self._file = ControlFile('File to import') self._panel.value = self._file self._filetype.add_item('Events file', 0) self._filetype.add_item('Graph file', 1) self._filetype.add_item('Bonsai events file', 2) self._formset = [ ('_filetype', ' '), '_panel', (' ', '_importButton'), ' '] self._filetype.changed_event = self.__fileTypeChanged self._importButton.value = self.__importData from pyforms.gui.dialogs.csv_parser import CsvParserDialog self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsaiImportDlg = BonsaiImportFileDlg() def __fileTypeChanged(self): if self._filetype.value == 0: self._panel.value = self._file elif self._filetype.value == 1: self._panel.value = self._graphCsvParserDlg elif self._filetype.value == 2: self._panel.value = self._bonsaiImportDlg def __importData(self): if self._filetype.value == 0: separator = ',' with open(self._file.value, 'rU') as csvfile: line = csvfile.readline() if ";" in line: separator = ';' with open(self._file.value, 'rU') as csvfile: csvfile = csv.reader(csvfile, delimiter=separator) self._timeline._time.import_csv(csvfile) elif self._filetype.value == 1: self._timeline._time.importchart_csv(self._graphCsvParserDlg) self._timeline.show_graphs_properties() elif self._filetype.value == 2: with open(self._bonsaiImportDlg._file.value, 'rU') as csvfile: values = [] pointEventValues = [] csvfile = csv.reader(csvfile, delimiter=' ') for row in csvfile: # strip Start/End word from all events names which are not PointEven try: timestr = row[1].rstrip('0') cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S.%f") except: timestr = row[1] cvttime = datetime.datetime.strptime(timestr, "%H:%M:%S") seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() frame = int(round(self._bonsaiImportDlg._fps.value * seconds)) if row[2] == "PointEvent": eventtype = row[0] pointEventValues.append([eventtype, frame, row[2]]) else: if row[0].startswith('Start'): eventtype = row[0][len('Start'):] # strip Start word from the beginning else: eventtype = row[0][len('End'):] # strip End word from the beginning values.append([eventtype, frame, row[2]]) values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) ntracks = len(set([x[0] for x in values])) + 1 # collapse events = [] eventsTypes = {} # Events names currentTrack = 0 for index in range(0, len(pointEventValues)): pointEventValue = pointEventValues[index] eventsTypes[pointEventValue[0]] = currentTrack self._timeline.addPeriod([pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0]], track=currentTrack) currentTrack = 1 for index in range(0, len(values), 2): row0 = values[index] row1 = values[index + 1] if row0[0] not in eventsTypes: eventsTypes[row0[0]] = currentTrack track = currentTrack currentTrack += 1 else: track = eventsTypes[row0[0]] self._timeline.addPeriod([row0[1], row1[1], row0[0]], track=track) self._timeline.repaint() self._timeline._time.repaint() self.close() # pylint: disable=no-member def import_chart(self, filename, frame_col=0, val_col=1): self._filetype.value = 1 self._graphCsvParserDlg.filename = filename self._graphCsvParserDlg.frameColumn = frame_col self._graphCsvParserDlg.xColumn = val_col
class ImportWindow(BaseWidget): def __init__(self, timeline=None): super(ImportWindow, self).__init__('Import file', parent_win=timeline) self.setContentsMargins(10, 10, 10, 10) self._timeline = timeline # Definition of the forms fields self._filetype = ControlCombo( 'Please select the type of file you would like to import:') self._importButton = ControlButton('Import') self._panel = ControlEmptyWidget('Panel') self._file = ControlFile('File to import') self._panel.value = self._file self._filetype.add_item('Events file', 0) self._filetype.add_item('Graph file', 1) self._filetype.add_item('Bonsai events file', 2) self._filetype.add_item('Bonsai events file (old format)', 3) self._formset = [('_filetype', ' '), '_panel', (' ', '_importButton'), ' '] self._filetype.changed_event = self.__fileTypeChanged self._importButton.value = self.__importData from pyforms.gui.dialogs.csv_parser import CsvParserDialog self._graphCsvParserDlg = CsvParserDialog() self._graphCsvParserDlg.xField.label = "Value column" self._graphCsvParserDlg.yField.hide() self._graphCsvParserDlg.zField.hide() self._graphCsvParserDlg.loadButton.hide() self._bonsai_import_dlg = BonsaiImportFileDlg() def __fileTypeChanged(self): if self._filetype.value == 0: self._panel.value = self._file elif self._filetype.value == 1: self._panel.value = self._graphCsvParserDlg elif self._filetype.value in [2, 3]: self._panel.value = self._bonsai_import_dlg def __importData(self): if self._filetype.value == 0: separator = ',' with open(self._file.value, 'rU') as csvfile: line = csvfile.readline() if ";" in line: separator = ';' with open(self._file.value, 'rU') as csvfile: csvfile = csv.reader(csvfile, delimiter=separator) self._timeline._time.import_csv(csvfile) elif self._filetype.value == 1: self._timeline._time.importchart_csv(self._graphCsvParserDlg) self._timeline.show_graphs_properties() elif self._filetype.value == 2: self.__import_bonsai_events() elif self._filetype.value == 3: self.__import_bonsai_events_oldformat() self._timeline.repaint() self._timeline._time.repaint() self.close() # pylint: disable=no-member def import_chart(self, filename, frame_col=0, val_col=1): self._filetype.value = 1 self._graphCsvParserDlg.filename = filename self._graphCsvParserDlg.frameColumn = frame_col self._graphCsvParserDlg.xColumn = val_col def __import_bonsai_events(self): with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: values = [] pointEventValues = [] csvfile = csv.reader(csvfile, delimiter=' ') for row in csvfile: # strip Start/End word from all events names which are not PointEven try: timestr = row[1].rstrip('0') cvttime = datetime.datetime.strptime( timestr, "%H:%M:%S.%f") except: timestr = row[1] try: print(timestr) cvttime = datetime.datetime.strptime( timestr, "%H:%M:%S") except: timestr = timestr.replace('T', ' ') print(timestr) cvttime = dateutil.parser.parse(timestr) seconds = (cvttime - datetime.datetime(1900, 1, 1)).total_seconds() frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) if row[2] == "PointEvent": eventtype = row[0] pointEventValues.append([eventtype, frame, row[2]]) else: if row[0].startswith('Start'): eventtype = row[0][len( 'Start'):] # strip Start word from the beginning else: eventtype = row[0][len( 'End'):] # strip End word from the beginning values.append([eventtype, frame, row[2]]) values = sorted(values, key=lambda x: (x[0].capitalize(), x[1])) pointEventValues = sorted(pointEventValues, key=lambda x: (x[0].capitalize(), x[1])) ntracks = len(set([x[0] for x in values])) + 1 # collapse events = [] eventsTypes = {} # Events names currentTrack = 0 for index in range(0, len(pointEventValues)): pointEventValue = pointEventValues[index] eventsTypes[pointEventValue[0]] = currentTrack self._timeline.add_period([ pointEventValue[1], pointEventValue[1] + 50, pointEventValue[0] ], row=currentTrack) currentTrack = 1 for index in range(0, len(values), 2): row0 = values[index] row1 = values[index + 1] if row0[0] not in eventsTypes: eventsTypes[row0[0]] = currentTrack track = currentTrack currentTrack += 1 else: track = eventsTypes[row0[0]] self._timeline.add_period([row0[1], row1[1], row0[0]], row=track) def __import_bonsai_events_oldformat(self): with open(self._bonsai_import_dlg._file.value, 'rU') as csvfile: windows_events = [] points_events = [] first_date = None for row in csvfile: row = row[:-1] #remove the newline character if row.endswith('WindowClosing'): split = row.rfind(' ') #eventtype = row[-split:] eventtype = 'end' timestr = row[split - 33:split] eventname = row[4:split - 33] elif row.endswith('PointEvent'): split = row.rfind(' ') eventtype = row[split + 1:] timestr = row[split - 33:split] eventname = row[:split - 33] else: eventtype = 'start' timestr = row[-33:] eventname = row[6:-33] cvttime = dateutil.parser.parse(timestr.replace('T', ' ')) cvttime = cvttime.replace(tzinfo=None) if first_date is None: first_date = cvttime seconds = (cvttime - first_date).total_seconds() frame = int(round(self._bonsai_import_dlg._fps.value * seconds)) if eventtype == 'PointEvent': points_events.append([eventtype, frame, eventname]) else: if eventtype == 'start': windows_events.append([eventtype, frame, eventname]) elif eventtype == 'end': windows_events.append([eventtype, frame, eventname]) windows_events = sorted(windows_events, key=lambda x: (x[0][0].capitalize(), x[0][1])) points_events = sorted(points_events, key=lambda x: (x[0].capitalize(), x[1])) ntracks = len(set([x[0][1] for x in windows_events])) + 1 # collapse events = [] events_types = {} # Events names current_track = 0 for index in range(0, len(points_events)): eventtype, frame, eventname = points_events[index] events_types[eventname] = current_track self._timeline.add_period([frame, frame + 2, eventname], row=current_track) current_track = 1 for i in range(0, len(windows_events), 2): start = windows_events[i] end = windows_events[i + 1] eventtype, frame_begin, eventname = start _, frame_end, _ = end if eventname not in events_types: events_types[eventname] = current_track track = current_track current_track += 1 else: track = events_types[eventname] print('add', eventname, track, frame_begin, frame_end) self._timeline.add_period([frame_begin, frame_end, eventname], row=track)
class VehTrajAnalytics(BaseWidget): def __init__(self): super(VehTrajAnalytics, self).__init__('Vehicle Trajectory Analytics') #Definition of the forms fields self._firstname = ControlText('First name', 'Default value') self._middlename = ControlText('Middle name') self._lastname = ControlText('Lastname name') self._fullname = ControlText('Full name') self._button = ControlButton('Press this button') self._button2 = ControlButton('Press this button2') self._outputDir = ControlDir("Output Directory") self._inputFile = ControlFile("Input Trajectory File") self._load = ControlButton("Load") self._save = ControlButton("Save") self._vehicleId = ControlCombo("Vehicle id") self._time = ControlCombo("Time(sec)") self._positionX = ControlCombo("PositionX (feet)") self._positionY = ControlCombo("PositionY (feet)") # Instrumented vehicle trajectories self._radarRange = ControlCombo("Radar range (feet)") self._radarAngle = ControlCombo("Radar angle (degrees)") self._centerline = ControlFile("CenterlineFile") #all traffic stream self._lane = ControlCombo("Lane") self._vLength = ControlCombo("Vehicle Length") self._distanceAlong = ControlCombo("Distance Along Corridor") #Define the button action self._button.value = self.__buttonAction self.data = None self.outFolder = None self.formset = [[('_inputFile', '_load'), '_vehicleId', "_time", '_positionX', "_positionY", "_distanceAlong"], "=", { 'All Vehicle Trajectories': ['_lane', '_vLength'], 'Instrumented Vehicle Trajectories': ['_radarAngle', '_radarRange'] }, '=', ('_outputDir', '_save')] self._load.value = self.__loadAction self._save.value = self.__saveAction def __buttonAction(self): """Button action event""" self._fullname.value = self._firstname.value +" "+ self._middlename.value + \ " "+ self._lastname.value def __loadAction(self): fileName = self._inputFile.value if fileName.endswith("hdf"): self.data = pd.read_hdf(fileName, 'trajectories') self.vt = VTAnalytics.readModelData(fileName, start_time=start_time, end_time=end_time) else: #self.data = pd.read_csv(fileName) self.vt = VTAnalytics.readNGISIMData(fileName, start_time=start_time, end_time=end_time) self.data = self.vt.df columns = list(self.data.columns) self.__initializeBoxes2(columns) def __saveAction(self): print('done reading the data') writer = pd.ExcelWriter( os.path.join(self._outputDir.value, 'tables.xlsx')) PAGE_SIZE = (1000, 792.0) pdfReport = PdfReport( os.path.join(self._outputDir.value, 'report.pdf'), PAGE_SIZE) fig, ax = plt.subplots(figsize=(10, 8), dpi=100) self.vt.plotSpeedVsDensity(fig, ax, max_density=280) fig.savefig(os.path.join(self._outputDir.value, "SpeedVsDensity.png"), dpi=100) pdfReport.addChart2( os.path.join(self._outputDir.value, "SpeedVsDensity.png"), 'SpeedVsDensity') fig, ax = plt.subplots(figsize=(10, 8), dpi=100) self.vt.plotLCR(fig, laneChangeType='enter') fig.savefig(os.path.join(self._outputDir.value, "LCR.png"), dpi=100) pdfReport.addChart2(os.path.join(self._outputDir.value, "LCR.png"), "LaneChangeRate") fig, ax = plt.subplots(figsize=(10, 8), dpi=100) self.vt.plotSpeedVsDensityByLane(fig, plot_mean=True, dot_color='blue', alpha=0.4) out_fileName = os.path.join(self._outputDir.value, "SpeedVsDensityByLane.png") fig.savefig(out_fileName, dpi=100) pdfReport.addChart2(out_fileName, "SpeedVsDensityByLane") fig, ax = plt.subplots(figsize=(10, 8)) spdDist = self.vt.plotSpeedDistribution(ax) out_fileName = os.path.join(self._outputDir.value, "SpeedDistribution.png") fig.savefig(out_fileName, dpi=100) pdfReport.addChart2(out_fileName, "SpeedDistribution") spdDist.to_excel(writer, 'SpeedDistribution') fig, ax = plt.subplots(figsize=(10, 8)) accDist = self.vt.plotAccelerationDistribution(ax) out_fileName = os.path.join(self._outputDir.value, "AccelerationDistribution.png") fig.savefig(out_fileName, dpi=100) pdfReport.addChart2(out_fileName, "AccelerationDistribution") accDist.to_excel(writer, 'AcclerationDistribution') fig, ax = plt.subplots(figsize=(10, 8)) jerk = self.vt.getAccelerationJerk() jerkDist = self.vt.plotJerkDistribution(jerk, ax) out_fileName = os.path.join(self._outputDir.value, "AccelerationJerkDistribution.png") fig.savefig(out_fileName, dpi=100) pdfReport.addChart2(out_fileName, "AccelerationJerkDistribution") jerkDist.to_excel(writer, 'JerkDistribution') armsDist = self.vt.getARMSDistribution() fig, ax = plt.subplots(figsize=(10, 8)) self.vt.plotARMS(armsDist, ax) out_fileName = os.path.join(self._outputDir.value, "AccelerationRootMeanSquareError.png") fig.savefig(out_fileName, dpi=100) pdfReport.addChart2(out_fileName, "AccelerationRootMeanSquareError") armsDist.to_excel(writer, 'ARMS') writer.save() for i in range(1, 8): fig, ax = plt.subplots(figsize=(10, 8), dpi=100) self.vt.plotAllTrajectories(fig, ax, i, np.datetime64('2005-04-13 17:00:00'), np.datetime64('2005-04-13 17:10:00'), 0, 1000, point_size=0.5, title="All trajectories for lane %d" % i) out_fileName = os.path.join(self._outputDir.value, "All_trajectories_lane_%d.png" % i) fig.savefig(out_fileName, dpi=100) pdfReport.addChart2(out_fileName, "All trajectories for lane %d" % i) pdfReport.write() def __saveActionOLD(self): fig, ax = plt.subplots(figsize=(10, 8)) self.vt.plotSpeedVsDensity(fig, ax, max_density=280) fig.savefig(os.path.join(self._outputDir.value, "graph1.pdf"), dpi=100) fig, ax = plt.subplots(figsize=(10, 8)) self.vt.plotLCR(fig, laneChangeType='enter') fig.savefig(os.path.join(self._outputDir.value, "graph2.pdf"), dpi=100) fig, ax = plt.subplots(figsize=(10, 8)) self.vt.plotSpeedVsDensityByLane(fig, plot_mean=True, dot_color='blue', alpha=0.4) fig.savefig(os.path.join(self._outputDir.value, "graph3.pdf"), dpi=100) for i in range(1, 8): fig, ax = plt.subplots(figsize=(10, 8)) self.vt.plotAllTrajectories(fig, ax, i, np.datetime64('2005-04-13 17:00:00'), np.datetime64('2005-04-13 17:10:00'), 0, 1000, point_size=0.5) fig.savefig(os.path.join(self._outputDir.value, "graph%d.pdf" % (3 + i)), dpi=100) #file_list = [os.path.join(self._outputDir.value, "test.pdf"), # os.path.join(self._outputDir.value, "test2.pdf")] file_list = [ os.path.join(self._outputDir.value, "graph%d.pdf" % i) for i in range(1, 5) ] out_file = os.path.join(self._outputDir.value, "trajReport.pdf") combinePdfFiles(file_list, out_file) def __initializeBoxes2(self, columns): for i, col in enumerate(columns): self._vehicleId.add_item(col, i) self._time.add_item(col, i) self._positionX.add_item(col, i) self._positionY.add_item(col, i) self._lane.add_item(col, i) self._vLength.add_item(col, i) self._radarRange.add_item(col, i) self._radarAngle.add_item(col, i) self._distanceAlong.add_item(col, i) #self.__initializeBoxes() def __initializeBoxes(self): self._vehicleId.add_item("One", '1') self._vehicleId.add_item("Two", '2') self._vehicleId.add_item("Three", '3') self._time.add_item("One", '1') self._time.add_item("Two", '2') self._time.add_item("Three", '3') self._positionX.add_item("One", '1') self._positionX.add_item("Two", '2') self._positionX.add_item("Three", '3') self._positionY.add_item("One", '1') self._positionY.add_item("Two", '2') self._positionY.add_item("Three", '3') self._lane.add_item("One", '1') self._lane.add_item("Two", '2') self._lane.add_item("Three", '3') self._vLength.add_item("One", '1') self._vLength.add_item("Two", '2') self._vLength.add_item("Three", '3') def __saveResults(self): fig, ax = plt.subplots(figsize=(15, 10)) self.data.speed.hist(ax=ax, bins=np.arange(0, 71, 1), figsize=(15, 10), width=0.8, color='grey', alpha=0.5) ax.set_title("Distribution of instantaneous speeds", fontsize=18) ax.set_xlabel("speed (mph)", fontsize=16) fig.tight_layout() fig.savefig(os.path.join(self.outFolder, 'test.png'))
def __init__(self): super(VehTrajAnalytics, self).__init__('Vehicle Trajectory Analytics') #Definition of the forms fields self._firstname = ControlText('First name', 'Default value') self._middlename = ControlText('Middle name') self._lastname = ControlText('Lastname name') self._fullname = ControlText('Full name') self._button = ControlButton('Press this button') self._button2 = ControlButton('Press this button2') self._outputDir = ControlDir("Output Directory") self._inputFile = ControlFile("Input Trajectory File") self._load = ControlButton("Load") self._save = ControlButton("Save") self._vehicleId = ControlCombo("Vehicle id") self._time = ControlCombo("Time(sec)") self._positionX = ControlCombo("PositionX (feet)") self._positionY = ControlCombo("PositionY (feet)") # Instrumented vehicle trajectories self._radarRange = ControlCombo("Radar range (feet)") self._radarAngle = ControlCombo("Radar angle (degrees)") self._centerline = ControlFile("CenterlineFile") #all traffic stream self._lane = ControlCombo("Lane") self._vLength = ControlCombo("Vehicle Length") self._distanceAlong = ControlCombo("Distance Along Corridor") #Define the button action self._button.value = self.__buttonAction self.data = None self.outFolder = None self.formset = [[('_inputFile', '_load'), '_vehicleId', "_time", '_positionX', "_positionY", "_distanceAlong"], "=", { 'All Vehicle Trajectories': ['_lane', '_vLength'], 'Instrumented Vehicle Trajectories': ['_radarAngle', '_radarRange'] }, '=', ('_outputDir', '_save')] self._load.value = self.__loadAction self._save.value = self.__saveAction
class SensorTab(BaseWidget): """ Tab for sensors Shows a drop down with all subclasses of Sensor imported anywhere into this program When one is selected, it creates an instance of that sensor and shows the custom config GUI for that Sensor. """ _sensor = None _timer = QTimer() def __init__(self, update_function=None): super().__init__("Output Tab") # The update function will be called when the selected sensor changes # to fire the 'sensor' event self._update_function = update_function self._device_select = ControlCombo(label="Sensor") self._custom = ControlEmptyWidget() self._device_select.changed_event = self._on_device_change self._device_select.add_item('None', None) self._output = ControlList() self._live = ControlCheckBox(label="Live Output") self._live.changed_event = self._on_live for class_type in Sensor.__subclasses__(): self._device_select.add_item(class_type.__name__, class_type) def update_events(self, events): """ Updates the events """ if isinstance(self._sensor, Sensor): self._sensor.update_events(events) def _on_device_change(self): device = self._device_select.value if callable(device): self._sensor = device() self._custom.value = self._sensor.get_custom_config() else: self._sensor = None self._custom.value = None #print("Not Subclass") if callable(self._update_function): self._update_function({'sensor': self._sensor}) def _on_live(self): if self._live.value: if isinstance(self._sensor, Sensor): self._sensor.begin_live_data() self._output.horizontal_headers = self._sensor.get_live_headers( ) self._timer.timeout.connect(self._update_sensor) self._timer.start(100) else: self._timer.stop() if isinstance(self._sensor, Sensor): self._sensor.stop_live_data() def _update_sensor(self): if isinstance(self._sensor, Sensor): self._output += self._sensor.get_live_data() self._output.tableWidget.scrollToBottom()
def __init__(self): super(MultipleBlobDetection, self).__init__( 'Multiple Blob Detection') # Definition of the forms fields self._videofile = ControlFile('Video') self._outputfile = ControlText('Results output file') self._threshold_box = ControlCheckBox('Threshold') self._threshold = ControlSlider('Binary Threshold', 114, 0, 255) self._roi_x_min = ControlSlider('ROI x top', 0, 0, 1000) self._roi_x_max = ControlSlider('ROI x bottom', 1000, 0, 1000) self._roi_y_min = ControlSlider('ROI y left', 0, 0, 1000) self._roi_y_max = ControlSlider('ROI y right', 1000, 0, 1000) # self._blobsize = ControlSlider('Minimum blob size', 100, 100, 2000) self._player = ControlPlayer('Player') self._runbutton = ControlButton('Run') self._start_frame = ControlText('Start Frame') self._stop_frame = ControlText('Stop Frame') self._color_list = ControlCombo('Color channels') self._color_list.add_item('Red Image Channel', 2) self._color_list.add_item('Green Image Channel', 1) self._color_list.add_item('Blue Image Channel', 0) self._clahe = ControlCheckBox('CLAHE ') self._dilate = ControlCheckBox('Morphological Dilation') self._dilate_type = ControlCombo('Dilation Kernel Type') self._dilate_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._dilate_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._dilate_type.add_item('CROSS', cv2.MORPH_CROSS) self._dilate_size = ControlSlider('Dilation Kernel Size', 3, 1, 10) self._erode = ControlCheckBox('Morphological Erosion') self._erode_type = ControlCombo('Erode Kernel Type') self._erode_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._erode_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._erode_type.add_item('CROSS', cv2.MORPH_CROSS) self._erode_size = ControlSlider('Erode Kernel Size', 5, 1, 10) self._open = ControlCheckBox('Morphological Opening') self._open_type = ControlCombo('Open Kernel Type') self._open_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._open_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._open_type.add_item('CROSS', cv2.MORPH_CROSS) self._open_size = ControlSlider('Open Kernel Size', 19, 1, 40) self._close = ControlCheckBox('Morphological Closing') self._close_type = ControlCombo('Close Kernel Type') self._close_type.add_item('RECTANGLE', cv2.MORPH_RECT) self._close_type.add_item('ELLIPSE', cv2.MORPH_ELLIPSE) self._close_type.add_item('CROSS', cv2.MORPH_CROSS) self._close_size = ControlSlider('Close Kernel Size', 19, 1, 40) self._LoG = ControlCheckBox('LoG - Laplacian of Gaussian') self._LoG_size = ControlSlider('LoG Kernel Size', 30, 1, 60) self._progress_bar = ControlProgress('Progress Bar') # Define the function that will be called when a file is selected self._videofile.changed_event = self.__videoFileSelectionEvent # Define the event that will be called when the run button is processed self._runbutton.value = self.__runEvent # Define the event called before showing the image in the player self._player.process_frame_event = self.__processFrame # Define the organization of the Form Controls self.formset = [ ('_videofile', '_outputfile'), ('_start_frame', '_stop_frame'), ('_color_list', '_clahe', '_roi_x_min', '_roi_y_min'), ('_threshold_box', '_threshold', '_roi_x_max', '_roi_y_max'), ('_dilate', '_erode', '_open', '_close'), ('_dilate_type', '_erode_type', '_open_type', '_close_type'), ('_dilate_size', '_erode_size', '_open_size', '_close_size'), ('_LoG', '_LoG_size'), '_runbutton', '_progress_bar', '_player' ]