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})
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()
Esempio n. 3
0
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()	
Esempio n. 4
0
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
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]
Esempio n. 6
0
class OTModuleConvertColors(OTModulePlugin, TypeColorVideoPipe):
    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",
        ]

    def newVideoInputChoosen(self):
        ModuleConnection.changed_event(self._video)
        value = self._video.value
        if value:
            self.open(value)
            self._player.value = value

    def processFrame(self, frame):

        return cv2.cvtColor(frame, self._colorDomain.value)
Esempio n. 7
0
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()
Esempio n. 8
0
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 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()
Esempio n. 10
0
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 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'))
Esempio n. 12
0
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)
    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