示例#1
0
    def __init__(self, parent_win=None):
        BaseWidget.__init__(self,
                            'Videos and intervals selector',
                            parent_win=parent_win)

        self._panel = ControlEmptyWidget(default=VideosSelectorDialog(
            parent_win=self))
        self._interval = ControlBoundingSlider('Interval', horizontal=True)

        self.formset = ['_panel', '_interval']

        self._intervals = {}

        self._panel.value.video_selection_changed_event = self.__video_selection_changed_event
        self._interval.changed_event = self.__update_intervals_event
示例#2
0
    def __init__(self, title=''):
        super(BaseApp, self).__init__(title)

        self._progress = ControlProgress('Processing')
        self._boundings = ControlBoundingSlider('Ranges', horizontal=True)

        #Only creates the variable if didn't exists yet.
        if not hasattr(self, '_modules_tabs'): self._modules_tabs = {}

        self.formset = [(' ', 'Frames bounding', ' '), '_boundings',
                        self._modules_tabs, '_progress']

        #Controls organization definition
        self.mainmenu = [{
            'File': [{
                'Open csv file': self.__open_tracking_file
            }, '-', {
                'Export data': self.export_tracking_file
            }, '-', {
                'Exit': exit
            }]
        }]

        self._data = None

        #Events definition
        self._csvParser = CsvParserDialog()
        self._csvParser.load_file_event = self.load_tracking_file
        self._boundings.changed = self.frames_boundings_changed
    def __init__(self):
        super(Example1, self).__init__('dir examples')
        self.parent = None
        self._directory = ControlDir('Choose a directory')
        self._file = ControlFile('Choose a file')
        self._filetree = ControlFilesTree('Choose a file')
        self._image = ControlImage('Image')
        self._boundaries = ControlBoundingSlider('Bounding', horizontal=True)
        self._button = ControlButton('Click')

        self._button.value = self.onButtonClick
        # self._directory.value=self.onButtonClick

        self._checkbox = ControlCheckBox('Choose a directory')
        self._checkboxList = ControlCheckBoxList('Choose a file')
        self._player = ControlPlayer('Choose a file')
        self._slider = ControlSlider('Slider')
        self._player.show()
        self._checkboxList.value = [('Item 1', True), ('Item 2', False), ('Item 3', True)]

        self._combobox = ControlCombo('Choose a item')
        self._list = ControlList('List label')
        self._progress = ControlProgress('Progress bar')
        self._visvisVolume = ControlVisVisVolume('Visvis')
        self._timeline = ControlEventTimeline('Timeline')

        self._combobox.add_item('Item 1', 'Value 1')
        self._combobox.add_item('Item 2', 'Value 2')
        self._combobox.add_item('Item 3', 'Value 3')
        self._combobox.add_item('Item 4')

        self._list.value = [('Item1', 'Item2', 'Item3',), ('Item3', 'Item4', 'Item5',)]
        imageWithVolume = np.zeros((100, 100, 100), np.uint8)
        imageWithVolume[30:40, 30:50, :] = 255
        imageWithVolume[30:40, 70:72, :] = 255
        self._visvisVolume.value = imageWithVolume

        self._visvis = ControlVisVis('Visvis')
        values1 = [(i, random.random(), random.random()) for i in range(130)]
        values2 = [(i, random.random(), random.random()) for i in range(130)]
        self._visvis.value = [values1, values2]

        self.formset = [
            '_visvis'
            , '_directory'
            , '_button'
            , '_file'
            , '_boundaries'
            , '_filetree'
            , '_image'
            , '_slider'
            , ('_checkboxList', '_player')
            , ('_checkbox', ' ')
            , ('_combobox', ' ')
            , '_progress'
            , '='
            , ('_visvisVolume', '||', '_list')
            , '_timeline'
        ]
    def __init__(self, parent_win=None):
        BaseWidget.__init__(self, 'Datasets', parent_win=parent_win)

        self._panel = ControlEmptyWidget(default=DatasetsSelectorDialog(
            parent_win=self))
        self._interval = ControlBoundingSlider('Interval', horizontal=True)
        self._apply_btn = ControlButton('Apply')

        self.formset = [
            '_panel',
            '_interval',
            '_apply_btn',
        ]

        self._intervals = {}

        self._panel.value.video_selection_changed_event = self.__video_selection_changed_event
        self._interval.changed_event = self.__update_intervals_event
        self._apply_btn.hide()
示例#5
0
    def __init__(self, **kwargs):
        BaseWidget.__init__(self, 'Find blobs')
        Class.__init__(self, **kwargs)

        try:
            self.layout().setContentsMargins(10, 5, 10, 5)
            self.setMinimumHeight(55)
        except:
            pass
        self._area_range = ControlBoundingSlider('Filter by area',
                                                 default=[100, 90000],
                                                 mininum=0,
                                                 maximum=100000,
                                                 horizontal=True)
        self._formset = ['_area_range']

        self._area_range.changed_event = self.__area_range_changed_event
示例#6
0
    def __init__(self, parent=None, parent_win=None):
        BaseWidget.__init__(self, 'Events stats', parent_win=parent_win)
        self._parent = parent

        self._bounds = ControlBoundingSlider('Frames range',
                                             1,
                                             100,
                                             horizontal=True)
        self._nframes = ControlNumber('Merge in a group of', 1800)
        self._videofsp = ControlNumber('FPS', 30.0)
        self._analyseButton = ControlButton('Calculate graphs')
        self._events = ControlCheckBoxList()
        self._graph = ControlVisVis('Graph')
        self._showTotalCounts = ControlCheckBox('Show total events counting')
        self._showEvtsCounts = ControlCheckBox('Show events counting', True)
        self._progress = ControlProgress()
        self._exportDurations = ControlButton('Export durations')
        self._exportTotals = ControlButton('Export totals')

        self._formset = [(' ', '_showEvtsCounts', '|', '_showTotalCounts', '|',
                          '_nframes', '_videofsp', '_analyseButton',
                          '_exportDurations', '_exportTotals'), '_bounds', {
                              'a:Graph': ['_graph'],
                              'c:Events selection': ['_events']
                          }, '_progress']

        self._analyseButton.value = self.__generate_graph
        self._exportDurations.value = self.__export_durations
        self._exportTotals.value = self.__export_totals
        self._progress.hide()

        self.__load_events()

        self.set_margin(5)

        self.setMinimumWidth(800)
        self.setMinimumHeight(600)
class DatasetsDialog(BaseWidget):
    def __init__(self, parent_win=None):
        BaseWidget.__init__(self, 'Datasets', parent_win=parent_win)

        self._panel = ControlEmptyWidget(default=DatasetsSelectorDialog(
            parent_win=self))
        self._interval = ControlBoundingSlider('Interval', horizontal=True)
        self._apply_btn = ControlButton('Apply')

        self.formset = [
            '_panel',
            '_interval',
            '_apply_btn',
        ]

        self._intervals = {}

        self._panel.value.video_selection_changed_event = self.__video_selection_changed_event
        self._interval.changed_event = self.__update_intervals_event
        self._apply_btn.hide()

    #####################################################################
    ### PRIVATE FUNCTIONS ###############################################
    #####################################################################

    def __update_intervals_event(self):
        self._intervals[self.selected_video] = self._interval.value

    def __video_selection_changed_event(self):
        video = self.selected_video

        if video is not None and video.video_capture is not None:
            self._interval.max = video.video_capture.get(7)
            if video not in self._intervals.keys():
                self._intervals[video] = 0, self._interval.max

            self._interval.value = self._intervals[video]
        self.video_selection_changed_event()

    #####################################################################
    ### EVENTS ##########################################################
    #####################################################################

    def video_selection_changed_event(self):
        pass

    def destroy(self, destroyWindow=True, destroySubWindows=True):
        self._panel.value.destroy(destroyWindow, destroySubWindows)
        super(DatasetsDialog, self).destroy(destroyWindow, destroySubWindows)

    #####################################################################
    ### FUNCTIONS #######################################################
    #####################################################################

    def refresh(self):
        self._panel.value.refresh()

    def clear(self):
        self._panel.value.clear()

    def __add__(self, other):
        self._panel.value += other
        return self

    def __sub__(self, other):
        self._panel.value -= other
        return self

    #####################################################################
    ### PROPERTIES ######################################################
    #####################################################################

    @property
    def videos(self):
        return self._panel.value.videos

    @property
    def datasets(self):
        return self._panel.value.datasets

    @property
    def datasets_changed_event(self):
        return self._panel.value.datasets_changed_event

    @datasets_changed_event.setter
    def datasets_changed_event(self, value):
        self._panel.value.datasets_changed_event = value

    @property
    def objects_changed_event(self):
        return self._panel.value.objects_changed_event

    @objects_changed_event.setter
    def objects_changed_event(self, value):
        self._panel.value.objects_changed_event = value

    @property
    def selected_video(self):
        return self._panel.value.selected_video

    @property
    def selected_video_range(self):
        return self._intervals.value

    @property
    def selected_data(self):
        for video, paths in self._panel.value.selected_data:
            begin, end = self._intervals.get(video,
                                             (0, video.video_capture.get(7)))
            yield video, (begin, end), paths

    @property
    def apply_event(self):
        return self._apply_btn.value

    @apply_event.setter
    def apply_event(self, value):
        if value is not None: self._apply_btn.show()
        self._apply_btn.value = value

    @property
    def interval_visible(self):
        return self._interval.visible

    @interval_visible.setter
    def interval_visible(self, value):
        if value:
            self._interval.show()
        else:
            self._interval.hide()

    @property
    def objects_filter(self):
        return self._panel.value.objects_filter

    @objects_filter.setter
    def objects_filter(self, value):
        self._panel.value.objects_filter = value

    @property
    def datasets_filter(self):
        return self._panel.value.datasets_filter

    @datasets_filter.setter
    def datasets_filter(self, value):
        self._panel.value.datasets_filter = value
    def __init__(self, parent=None):
        super(ContoursImagesWindow, self).__init__('Contour images', parent_win=parent)
        self.mainwindow = parent

        self.set_margin(5)
        

        self.setMinimumHeight(400)
        self.setMinimumWidth(800)

        self._contourspanel = ControlEmptyWidget('Contours datasets')
        self._progress      = ControlProgress('Progress', visible=False)       
        self._apply         = ControlButton('Apply', checkable=True)
        self._toolbox       = ControlToolBox('Toolbox')
        self._exportdir     = ControlDir('Export images to folder', default='images-from-contour')
        

        #### mask ######################################################
        self._usemaskimg       = ControlCheckBox('Apply a mask to the image')
        self._usemaskdilate    = ControlCheckBox('Dilate the mask and apply it to the image')
        self._maskdilatesize   = ControlSlider('Dilate size', default=0, minimum=0, maximum=100)
        self._usemaskellipse   = ControlCheckBox('Apply the min. ellipse as a mask to the image')
        self._usemaskcircular  = ControlCheckBox('Apply a circular mask to the image')
        self._maskcircularsize = ControlSlider('Circular radius', default=0, minimum=0, maximum=100)
        self._usemaskrect      = ControlCheckBox('Apply the min. rect as a mask to the image')
        ################################################################

        #### margin ####################################################
        self._margin = ControlSlider('Margin size', default=0, minimum=0, maximum=100)
        ################################################################

        #### imagesize #################################################
        self._imagesize = ControlSlider('Image size', default=0, minimum=0, maximum=400)
        ################################################################

        #### cut #######################################################
        self._usecut = ControlCheckBox('Cut image')
        self._cutx = ControlBoundingSlider('X cut', default=(10,30), minimum=0, maximum=1000)
        self._cuty = ControlBoundingSlider('Y cut', default=(10,30), minimum=0, maximum=1000)
        ################################################################
        

        #### use stretch ###############################################
        self._usestretch = ControlCheckBox('Stretch image')
        ################################################################

        #### filter per events #########################################
        self._eventslst  = ControlCheckBoxList('Events', enabled=True)
        self._reloadevts = ControlButton('Reload events', enabled=True, default=self.__reload_events_btn_evt)
        ################################################################

        #### rotation ##################################################
        self._userotup          = ControlCheckBox('Turn the contour always up')
        self._userotdown        = ControlCheckBox('Turn the contour always down')
        self._usefixedangle     = ControlCheckBox('Use a fixed orientation')
        self._fixedangle        = ControlSlider('Rotate the images using a fixed angle', enabled=True, default=0, minimum=0, maximum=360)
        self._usedatasetangle   = ControlCheckBox('Use the orientation of other contour')
        self._datasetanglepanel = ControlEmptyWidget('Datasets for the orientation', enabled=True)
        ################################################################

        #### image position ############################################
        self._useposdataset   = ControlCheckBox('Use a dataset to center the image')
        self._datasetpospanel = ControlEmptyWidget('Datasets for the image position', enabled=True)
        ################################################################

        
        self.formset = [
            '_toolbox',
            '_exportdir',
            '_apply',
            '_progress'
        ]

        self.load_order = [
            '_contourspanel','_userotup', '_userotdown',
            '_exportdir','_usemaskimg','_usemaskdilate','_usemaskellipse','_usemaskellipse',
            '_usemaskcircular', '_maskcircularsize', '_usemaskrect', '_margin', '_imagesize',
            '_usestretch', '_eventslst', '_usefixedangle', '_fixedangle', '_usedatasetangle',
            '_datasetanglepanel', '_useposdataset', '_datasetpospanel', '_usecut', '_cuty', '_cutx'
        ]

        #datasets painel
        self.datasets_dialog = DatasetsDialog(self)
        self.datasets_dialog.datasets_filter = lambda x: isinstance(x, Contours )
        self._contourspanel.value = self.datasets_dialog

        self.posdatasets_dialog = DatasetsDialog(self)
        self.posdatasets_dialog.datasets_filter = lambda x: isinstance(x, (Contours,Path) )
        self._datasetpospanel.value = self.posdatasets_dialog

        self.orientdatasets_dialog = DatasetsDialog(self)
        self.orientdatasets_dialog.datasets_filter = lambda x: isinstance(x, Contours )
        self.orientdatasets_dialog.interval_visible = False
        self._datasetanglepanel.value = self.orientdatasets_dialog


        self._apply.value       = self.__apply_event
        self._apply.icon        = conf.ANNOTATOR_ICON_PATH

        self._imagesize.changed_event = self.__image_size_changed_evt

        self._toolbox.value = [
            ('Extract from contours',(
                self.datasets_dialog,
            )),
            ('Mask',(
                self._usemaskimg,
                (self._usemaskdilate,self._maskdilatesize),
                (self._usemaskcircular,self._maskcircularsize),
                (self._usemaskellipse,self._usemaskrect),
            )),
            ('Margin, image size and stretch image',(
                self._usestretch,
                self._margin, 
                self._imagesize,
                self._usecut,
                self._cutx,
                self._cuty
            )),
            ('Rotate images',(
                (self._userotup, self._userotdown),
                (self._usefixedangle, self._fixedangle),
                self._usedatasetangle,
                self._datasetanglepanel
            )),
            ('Center images',(
                self._useposdataset,
                self._datasetpospanel,
            )),
            ('Export images per events',(
                self._reloadevts,
                self._eventslst,
            )),
        ]

        self.__reload_events_btn_evt()
        self.__image_size_changed_evt()
    def __init__(self, title='Heat map'):
        super(HeatMapApp, self).__init__(title)

        self._heatmapImg = None  #Store a numpy array with the heatmap
        self._velocities = None  #Store the velocities for each frame
        self._accelerations = None  #Store the accelarations for each frame

        ##### CONTROLS ##############################################################################
        self._heatmap = ControlVisVisVolume("Volume")
        self._toggleSphereVisibility = ControlButton('Filter by a region',
                                                     checkable=True)
        self._sphere = ControlText('Position filter (x,y,z,radius)')

        self._toggleHeatmapVars = ControlButton('Select variables',
                                                checkable=True)
        self._heatmapVarsBnds = ControlBoundingSlider('Variable bounds',
                                                      horizontal=True)
        self._heatmapHigherVarsValues = ControlCheckBox(
            'Most higher', helptext='Show only the higher values')

        self._heatmapColor = ControlCombo('Color map')
        self._apply2Heatmap = ControlButton('Apply to map')

        self._heatmapColorsBnds = ControlBoundingSlider('Colors',
                                                        horizontal=False)
        self._heatmapVarsList = ControlCombo('Variables')
        self._heatmapVars = ControlCheckBox('Map variables')

        self._heatMapMinVar = ControlText('Min vel.')
        self._heatMapMaxVar = ControlText('Max vel.')

        #############################################################################################
        self._modules_tabs.update({
            'Heat map':
            [('_heatmapColor', '   |   ', 'Filters:', '_toggleHeatmapVars',
              '_toggleSphereVisibility', '_sphere', '   |   ',
              '_apply2Heatmap', ' '),
             ('_heatmapVarsList', '_heatmapVars', '_heatmapHigherVarsValues',
              '_heatMapMinVar', '_heatmapVarsBnds', '_heatMapMaxVar'), {
                  'Map': ('_heatmap', '_heatmapColorsBnds')
              }]
        })
        #############################################################################################

        self._heatmapVarsList += 'Velocity'
        self._heatmapVarsList += 'Acceleration'

        self._heatmapColor.add_item('Bone', vv.CM_BONE)
        self._heatmapColor.add_item('Cool', vv.CM_COOL)
        self._heatmapColor.add_item('Copper', vv.CM_COPPER)
        self._heatmapColor.add_item('Gray', vv.CM_GRAY)
        self._heatmapColor.add_item('Hot', vv.CM_HOT)
        self._heatmapColor.add_item('HSV', vv.CM_HSV)
        self._heatmapColor.add_item('Jet', vv.CM_JET)
        self._heatmapColor.add_item('Pink', vv.CM_PINK)
        self._heatmapColor.add_item('Autumn', vv.CM_AUTUMN)
        self._heatmapColor.add_item('Spring', vv.CM_SPRING)
        self._heatmapColor.add_item('Summer', vv.CM_SUMMER)
        self._heatmapColor.add_item('Winter', vv.CM_WINTER)
        self._heatmapColor.value = vv.CM_HSV

        self._sphere.hide()
        self._heatmapVarsBnds.hide()
        self._heatmapVarsList.hide()
        self._heatMapMinVar.hide()
        self._heatMapMaxVar.hide()
        self._heatmapVars.hide()
        self._heatmapHigherVarsValues.hide()
        self._heatmapVarsBnds.convert_2_int = False
        self._heatmapColorsBnds.convert_2_int = False

        self._apply2Heatmap.value = self.calculate_heatmap_event
        self._heatmapColor.changed = self.changed_heatmap_color_event
        self._toggleSphereVisibility.value = self.__toggle_sphere_visiblity_event
        self._toggleHeatmapVars.value = self.__toggle_variables_visibility_event
        self._heatmapVarsList.changed = self.__changed_heatmap_variables_list_event
        self._heatMapMinVar.changed = self.__changed_heatmap_minVar_event
        self._heatMapMaxVar.changed = self.__changed_heatmap_maxVar_event
        self._heatmapColorsBnds.changed = self.changed_heatmap_colors_bounds_event
        self._heatmapVars.changed = self.__changed_heatmap_variables_event
class HeatMapApp(BaseApp):
    """Application form"""
    def __init__(self, title='Heat map'):
        super(HeatMapApp, self).__init__(title)

        self._heatmapImg = None  #Store a numpy array with the heatmap
        self._velocities = None  #Store the velocities for each frame
        self._accelerations = None  #Store the accelarations for each frame

        ##### CONTROLS ##############################################################################
        self._heatmap = ControlVisVisVolume("Volume")
        self._toggleSphereVisibility = ControlButton('Filter by a region',
                                                     checkable=True)
        self._sphere = ControlText('Position filter (x,y,z,radius)')

        self._toggleHeatmapVars = ControlButton('Select variables',
                                                checkable=True)
        self._heatmapVarsBnds = ControlBoundingSlider('Variable bounds',
                                                      horizontal=True)
        self._heatmapHigherVarsValues = ControlCheckBox(
            'Most higher', helptext='Show only the higher values')

        self._heatmapColor = ControlCombo('Color map')
        self._apply2Heatmap = ControlButton('Apply to map')

        self._heatmapColorsBnds = ControlBoundingSlider('Colors',
                                                        horizontal=False)
        self._heatmapVarsList = ControlCombo('Variables')
        self._heatmapVars = ControlCheckBox('Map variables')

        self._heatMapMinVar = ControlText('Min vel.')
        self._heatMapMaxVar = ControlText('Max vel.')

        #############################################################################################
        self._modules_tabs.update({
            'Heat map':
            [('_heatmapColor', '   |   ', 'Filters:', '_toggleHeatmapVars',
              '_toggleSphereVisibility', '_sphere', '   |   ',
              '_apply2Heatmap', ' '),
             ('_heatmapVarsList', '_heatmapVars', '_heatmapHigherVarsValues',
              '_heatMapMinVar', '_heatmapVarsBnds', '_heatMapMaxVar'), {
                  'Map': ('_heatmap', '_heatmapColorsBnds')
              }]
        })
        #############################################################################################

        self._heatmapVarsList += 'Velocity'
        self._heatmapVarsList += 'Acceleration'

        self._heatmapColor.add_item('Bone', vv.CM_BONE)
        self._heatmapColor.add_item('Cool', vv.CM_COOL)
        self._heatmapColor.add_item('Copper', vv.CM_COPPER)
        self._heatmapColor.add_item('Gray', vv.CM_GRAY)
        self._heatmapColor.add_item('Hot', vv.CM_HOT)
        self._heatmapColor.add_item('HSV', vv.CM_HSV)
        self._heatmapColor.add_item('Jet', vv.CM_JET)
        self._heatmapColor.add_item('Pink', vv.CM_PINK)
        self._heatmapColor.add_item('Autumn', vv.CM_AUTUMN)
        self._heatmapColor.add_item('Spring', vv.CM_SPRING)
        self._heatmapColor.add_item('Summer', vv.CM_SUMMER)
        self._heatmapColor.add_item('Winter', vv.CM_WINTER)
        self._heatmapColor.value = vv.CM_HSV

        self._sphere.hide()
        self._heatmapVarsBnds.hide()
        self._heatmapVarsList.hide()
        self._heatMapMinVar.hide()
        self._heatMapMaxVar.hide()
        self._heatmapVars.hide()
        self._heatmapHigherVarsValues.hide()
        self._heatmapVarsBnds.convert_2_int = False
        self._heatmapColorsBnds.convert_2_int = False

        self._apply2Heatmap.value = self.calculate_heatmap_event
        self._heatmapColor.changed = self.changed_heatmap_color_event
        self._toggleSphereVisibility.value = self.__toggle_sphere_visiblity_event
        self._toggleHeatmapVars.value = self.__toggle_variables_visibility_event
        self._heatmapVarsList.changed = self.__changed_heatmap_variables_list_event
        self._heatMapMinVar.changed = self.__changed_heatmap_minVar_event
        self._heatMapMaxVar.changed = self.__changed_heatmap_maxVar_event
        self._heatmapColorsBnds.changed = self.changed_heatmap_colors_bounds_event
        self._heatmapVars.changed = self.__changed_heatmap_variables_event

    ############################################################################################
    ### AUXILIAR FUNCTIONS #####################################################################
    ############################################################################################

    def __calc_heatmap_size(self, x_diff, y_diff, z_diff, scale=None):
        """
		Calculate the heatmap size
		"""
        if scale == None: scale = self.fit_scale(x_size, y_size, z_size)
        x_scaled_size = int(round((x_diff + 1) * scale))
        y_scaled_size = int(round((y_diff + 1) * scale))
        z_scaled_size = int(round((z_diff + 1) * scale))
        return x_scaled_size, y_scaled_size, z_scaled_size

    def fit_scale(self, x_diff, y_diff, z_diff):
        """
		Calculate the scale value that should be applied to each position, so they can fit in an numpy array
		"""
        scale = 1.0
        new_scale = 1.0
        x_size, y_size, z_size = 0, 0, 0

        #The maximum allowed size for the heatmap is (2000,2000,2000)
        while x_size <= 2000.0 and y_size <= 2000.0 and z_size <= 2000.0:
            scale = new_scale
            new_scale = scale * 10.0
            x_size, y_size, z_size = self.__calc_heatmap_size(
                x_diff, y_diff, z_diff, new_scale)
        return scale

    ############################################################################################
    ### EVENTS #################################################################################
    ############################################################################################

    def __changed_heatmap_variables_event(self):
        if self._heatmapVars.value:
            self._heatmapHigherVarsValues.show()
        else:
            self._heatmapHigherVarsValues.hide()

    def __toggle_sphere_visiblity_event(self):
        if self._toggleSphereVisibility.checked:
            self._sphere.show()
        else:
            self._sphere.hide()

    def __toggle_variables_visibility_event(self):
        if self._toggleHeatmapVars.checked:
            self._heatmapVarsList.show()
            self._heatmapVarsBnds.show()
            self._heatMapMinVar.show()
            self._heatMapMaxVar.show()
            self._heatmapVars.show()
        else:
            self._heatmapVarsList.hide()
            self._heatmapVarsBnds.hide()
            self._heatMapMinVar.hide()
            self._heatMapMaxVar.hide()
            self._heatmapVars.hide()

    def changed_heatmap_colors_bounds_event(self):
        if self._heatmapImg is None or not self._heatmapImg.any(): return
        self._heatmap.colors_limits = self._heatmapColorsBnds.value

    def __changed_heatmap_minVar_event(self):
        if self._heatMapMinVar.value == '': return

        v = eval(self._heatMapMinVar.value)
        self._heatmapVarsBnds.min = v
        values = list(self._heatmapVarsBnds.value)

        if values[0] < v: values[0] = v
        self._heatmapVarsBnds.value = values

    def __changed_heatmap_maxVar_event(self):
        if self._heatMapMaxVar.value == '': return

        v = eval(self._heatMapMaxVar.value)
        self._heatmapVarsBnds.max = v
        values = list(self._heatmapVarsBnds.value)

        if values[1] > v: values[1] = v
        self._heatmapVarsBnds.value = values

    def __changed_heatmap_variables_list_event(self):

        if self._heatmapVarsList.value == 'Velocity' and self._velocities:
            lower = int(0 if self._boundings.value[0] < 0 else self._boundings.
                        value[0])
            higher = int(
                len(self._velocities) if self._boundings.value[1] >= len(
                    self._velocities) else self._boundings.value[1])
            max_val = max(self._velocities[lower:higher])
            min_val = min(self._velocities[lower:higher])
            self._heatmapVarsBnds.value = round(min_val, 2), round(max_val, 2)
            self._heatMapMinVar.value = str(
                round(min_val - (max_val - min_val) * 0.1, 2))
            self._heatMapMaxVar.value = str(
                round(max_val + (max_val - min_val) * 0.1, 2))

        if self._heatmapVarsList.value == 'Acceleration' and self._accelerations:
            lower = int(0 if self._boundings.value[0] < 0 else self._boundings.
                        value[0])
            higher = int(
                len(self._accelerations) if self._boundings.value[1] >
                (len(self._accelerations) + 1) else self._boundings.value[1])
            max_val = max(self._accelerations[lower:higher])
            min_val = min(self._accelerations[lower:higher])
            self._heatmapVarsBnds.value = round(min_val, 2), round(max_val, 2)
            self._heatMapMinVar.value = str(
                round(min_val - (max_val - min_val) * 0.1, 2))
            self._heatMapMaxVar.value = str(
                round(max_val + (max_val - min_val) * 0.1, 2))

    def changed_heatmap_color_event(self):
        self._heatmap.colorMap = self._heatmapColor.value

    ############################################################################################
    ### Map generation #########################################################################
    ############################################################################################

    def calculate_heatmap_event(self):
        #Filter for the data from a lower and upper frame
        if self._data is None: return

        self._progress.min = lower = 0 if self._boundings.value[0] < 0 else int(
            self._boundings.value[0])
        self._progress.max = higher = len(
            self._data) if self._boundings.value[1] > (
                len(self._data) + 1) else int(self._boundings.value[1])

        #Calculate the size of the map
        x_diff = self._data.xRange[1] - self._data.xRange[0]
        y_diff = self._data.yRange[1] - self._data.yRange[0]
        z_diff = self._data.zRange[1] - self._data.zRange[0]
        scale = self.fit_scale(x_diff, y_diff,
                               z_diff)  #Fit the best scale value
        x_size, y_size, z_size = self.__calc_heatmap_size(
            x_diff, y_diff, z_diff,
            scale)  #Return the best size for the map image

        try:
            sphere = sphere_x, sphere_y, sphere_z, sphere_r = eval(
                self._sphere.value)
        except:
            sphere = None
        min_var, max_var = self._heatmapVarsBnds.value
        which_var = 0 if self._heatmapVarsList.value == 'Velocity' else 1

        #Create the map image
        img = np.zeros((z_size, x_size, y_size), dtype=np.float32)

        for i in range(lower, higher):
            if (i % 3000) == 0: self._progress.value = i
            if self._data[i] != None:
                position = self._data[i].position

                #shift and scale the coordenates, to avoid negative and decimal values
                #is only possible to map in the image positive and integer coordenates
                x, y, z = position
                x += abs(self._data.xRange[0])
                y += abs(self._data.yRange[0])
                z += abs(self._data.zRange[0])
                x = int(round(x * scale))
                y = int(round(y * scale))
                z = int(round(z * scale))

                #Filter position by a defined sphere
                if sphere != None and lin_dist3d(
                    (x, y, z), (sphere_x, sphere_y, sphere_z)) > sphere_r:
                    continue

                #Use variables to construct the map, or positions
                if self._toggleHeatmapVars.checked:
                    #velocities array has less 1 element than positions array
                    if which_var == 0 and len(self._velocities) <= i: continue
                    #accelarations array has less 2 element than positions array
                    if which_var == 1 and len(self._accelerations) <= i:
                        continue

                    var = self._velocities[
                        i] if which_var == 0 else self._accelerations[i]

                    #Filter by variable boundaries
                    if not (min_var <= var <= max_var): continue

                    if self._heatmapVars.value:
                        #Map the variables
                        if self._heatmapHigherVarsValues.value:
                            tmp = img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1]
                            tmp[tmp < var] = var
                        else:
                            img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] += var
                    else:
                        #Map positions
                        img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] += 1.0
                else:
                    #Map positions
                    img[z - 1:z + 1, x - 1:x + 1, y - 1:y + 1] += 1.0

        self._progress.value = higher

        color_min = np.min(img)
        color_max = np.max(img)
        self._heatmapColorsBnds.min = color_min - (color_max - color_min) * 0.1
        self._heatmapColorsBnds.max = color_max + (color_max - color_min) * 0.1
        self._heatmapColorsBnds.value = color_min, color_max

        self._heatmap.value = np.zeros((1, 1), dtype=np.float32)
        self._heatmap.colors_limits = None
        self._heatmap.value = img
        self._heatmapImg = img

    ############################################################################################
    ### CLASS OVERRIDE FUNCTIONS ###############################################################
    ############################################################################################

    def frames_boundings_changed(self):
        super(HeatMapApp, self).frames_boundings_changed()
        self.__changed_heatmap_variables_list_event()

    def load_tracking_file(self):
        super(HeatMapApp, self).load_tracking_file()
        self.__changed_heatmap_variables_list_event()

    def export_tracking_file(self):

        filename, _ = QFileDialog.getSaveFileName(self,
                                                  'Select a file',
                                                  selectedFilter='*.csv')
        if not filename: return
        filename = str(filename)
        if not filename.lower().endswith('.csv'): filename += '.csv'

        #Export only the selected bounds
        lower = 0 if self._boundings.value[0] < 0 else self._boundings.value[0]
        higher = len(self._data) if self._boundings.value[1] > (
            len(self._data) + 1) else self._boundings.value[1]

        self._progress.min = lower
        self._progress.max = higher

        which_var = 0 if self._heatmapVarsList.value == 'Velocity' else 1
        try:
            sphere = sphere_x, sphere_y, sphere_z, sphere_r = eval(
                self._sphere.value)
        except:
            sphere = None

        min_var, max_var = self._heatmapVarsBnds.value

        #Calculate the size of the map
        x_diff = self._data.xRange[1] - self._data.xRange[0]
        y_diff = self._data.yRange[1] - self._data.yRange[0]
        z_diff = self._data.zRange[1] - self._data.zRange[0]
        scale = self.fit_scale(x_diff, y_diff,
                               z_diff)  #Fit the best scale value

        with open(filename, 'wb') as csvfile:
            spamwriter = csv.writer(csvfile, delimiter=',')

            for i in range(int(lower), int(higher)):
                self._progress.value = i

                position = self._data[i].position
                x, y, z = position
                x += abs(self._data.xRange[0])
                y += abs(self._data.yRange[0])
                z += abs(self._data.zRange[0])
                x = int(round(x * scale))
                y = int(round(y * scale))
                z = int(round(z * scale))

                if sphere != None and lin_dist3d(
                    (x, y, z), (sphere_x, sphere_y, sphere_z)) > sphere_r:
                    continue

                if self._toggleHeatmapVars.checked:
                    var = self._velocities[
                        i] if which_var == 0 else self._accelerations[i]
                    if not (min_var <= var <= max_var): continue

                if self._data[i] == None: continue

                row2save = self._data[i].row
                if i > lower: row2save = row2save + [self._velocities[i]]
                if (i + 1) > lower:
                    row2save = row2save + [self._accelerations[i]]
                spamwriter.writerow(row2save)