diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..865cb3e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,31 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. macOS Catalina, Windows 10 1903, Ubuntu 19.10]
+ - Python Video Annotator Version [e.g. 3.306]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..bbcbbe7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.gitmodules b/.gitmodules
index 60a15e4..ed580eb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,69 +1,73 @@
[submodule "base/pythonvideoannotator-models"]
path = base/pythonvideoannotator-models
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-models.git
+ url = https://github.com/video-annotator/pythonvideoannotator-models.git
[submodule "base/pythonvideoannotator-models-gui"]
path = base/pythonvideoannotator-models-gui
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-models-gui.git
+ url = https://github.com/video-annotator/pythonvideoannotator-models-gui.git
[submodule "plugins/pythonvideoannotator-module-backgroundfinder"]
path = plugins/pythonvideoannotator-module-backgroundfinder
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-backgroundfinder.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-backgroundfinder.git
[submodule "libraries/mcv-api"]
path = libraries/mcv-api
- url = https://bitbucket.org/fchampalimaud/mcv-api.git
+ url = https://github.com/video-annotator/mcv-api.git
[submodule "libraries/mcv-gui"]
path = libraries/mcv-gui
- url = https://bitbucket.org/fchampalimaud/mcv-gui.git
-[submodule "libraries/mcv-gui-editor"]
- path = libraries/mcv-gui-editor
- url = https://bitbucket.org/fchampalimaud/mcv-gui-editor.git
+ url = https://github.com/video-annotator/mcv-gui.git
+[submodule "libraries/confapp"]
+ path = libraries/confapp
+ url = https://github.com/UmSenhorQualquer/confapp.git
[submodule "plugins/pythonvideoannotator-module-contoursimages"]
path = plugins/pythonvideoannotator-module-contoursimages
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-contoursimages.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-contoursimages.git
[submodule "plugins/pythonvideoannotator-module-createpaths"]
path = plugins/pythonvideoannotator-module-createpaths
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-createpaths.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-createpaths.git
[submodule "plugins/pythonvideoannotator-module-distances"]
path = plugins/pythonvideoannotator-module-distances
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-distances.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-distances.git
[submodule "plugins/pythonvideoannotator-module-eventsstats"]
path = plugins/pythonvideoannotator-module-eventsstats
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-eventsstats.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-eventsstats.git
[submodule "plugins/pythonvideoannotator-module-findorientation"]
path = plugins/pythonvideoannotator-module-findorientation
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-findorientation.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-findorientation.git
[submodule "plugins/pythonvideoannotator-module-importexport"]
path = plugins/pythonvideoannotator-module-importexport
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-importexport.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-importexport.git
[submodule "plugins/pythonvideoannotator-module-motioncounter"]
path = plugins/pythonvideoannotator-module-motioncounter
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-motioncounter.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-motioncounter.git
[submodule "plugins/pythonvideoannotator-module-patheditor"]
path = plugins/pythonvideoannotator-module-patheditor
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-patheditor.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-patheditor.git
[submodule "plugins/pythonvideoannotator-module-regionsfilter"]
path = plugins/pythonvideoannotator-module-regionsfilter
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-regionsfilter.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-regionsfilter.git
[submodule "plugins/pythonvideoannotator-module-smoothpaths"]
path = plugins/pythonvideoannotator-module-smoothpaths
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-smoothpaths.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-smoothpaths.git
[submodule "plugins/pythonvideoannotator-module-timeline"]
path = plugins/pythonvideoannotator-module-timeline
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-timeline.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-timeline.git
[submodule "plugins/pythonvideoannotator-module-tracking"]
path = plugins/pythonvideoannotator-module-tracking
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-tracking.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-tracking.git
[submodule "plugins/pythonvideoannotator-module-virtualobjectgenerator"]
path = plugins/pythonvideoannotator-module-virtualobjectgenerator
- url = https://bitbucket.org/fchampalimaud/pythonvideoannotator-module-virtualobjectgenerator.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-virtualobjectgenerator.git
[submodule "libraries/pyforms-gui"]
path = libraries/pyforms-gui
url = https://github.com/UmSenhorQualquer/pyforms-gui.git
[submodule "libraries/geometry-designer"]
path = libraries/geometry-designer
- url = https://bitbucket.org/fchampalimaud/geometry-designer.git
+ url = https://github.com/video-annotator/geometry-designer.git
[submodule "plugins/pythonvideoannotator-module-pathmap"]
path = plugins/pythonvideoannotator-module-pathmap
- url = https://UmSenhorQualquer@bitbucket.org/fchampalimaud/pythonvideoannotator-module-pathmap.git
+ url = https://github.com/video-annotator/pythonvideoannotator-module-pathmap.git
[submodule "plugins/pythonvideoannotator-module-deeplab"]
path = plugins/pythonvideoannotator-module-deeplab
- url = https://manuelmanso@bitbucket.org/fchampalimaud/pythonvideoannotator-module-deeplab.git
\ No newline at end of file
+ url = https://github.com/video-annotator/pythonvideoannotator-module-deeplab.git
+[submodule "plugins/pythonvideoannotator-module-idtrackerai"]
+ path = plugins/pythonvideoannotator-module-idtrackerai
+ url = https://github.com/video-annotator/pythonvideoannotator-module-idtrackerai.git
+
diff --git a/README.md b/README.md
index 11e30ac..ab11bf7 100644
--- a/README.md
+++ b/README.md
@@ -14,40 +14,74 @@ Features:
[](https://www.youtube.com/watch?v=9C4Zr8fhqFo&t=63s)
+
-### Developers
+## Installation & Running
-* Ricardo Ribeiro - collaborator of the [Scientific Software Platform](http://neuro.fchampalimaud.org/en/research/platforms/staff/Scientific%20Software/) of the [Champalimaud Foundation](http://fchampalimaud.org).
-* Hugo Cachitas working - collaborator of the [Innate Behavior Lab](http://neuro.fchampalimaud.org/en/research/investigators/research-groups/group/Vasconcelos/) of the [Champalimaud Foundation](http://fchampalimaud.org).
-* Carlos Mão de Ferro - collaborator of the [Scientific Software Platform](http://neuro.fchampalimaud.org/en/research/platforms/staff/Scientific%20Software/) of the [Champalimaud Foundation](http://fchampalimaud.org).
+How to install:
+1. Create a Virtual Environment (highly recommended) on your preferred Python distribution with Python 3.6:
+ * example with Anaconda in Anaconda Prompt
-
+ ```bash
+ conda create -n videoannotator python=3.6
-## Installation & Running
+ ...
-How to install:
+ conda activate videoannotator
+ ```
+
+2. Make sure you are in the just created virtual environment and install PythonVideoAnnotator with pip:
+
+ ```bash
+ pip install python-video-annotator
+ ```
+
+If you are having issues (e.g., MacOS Catalina):
-1. Install Python 3.6 from [python.org](https://www.python.org/)
+1. Start with a fresh Virtual Environment (highly recommended) on your preferred Python distribution with Python 3.6:
+ * example with Anaconda in Anaconda Prompt
-2. Install pypi from [pypi.org](https://pypi.org/)
+ ```bash
+ conda create -n videoannotator python=3.6
-3. Install PythonVideoAnnotator from Pypi:
-```
-pip install python-video-annotator
-```
+ ...
+
+ conta activate videoannotator
+ ```
+
+2. Install some of the dependencies that might present issues as:
+
+ ```bash
+ pip install opencv-python-headless pyqt5==5.14.1 pyqtwebengine==5.14.0
+ ```
+
+3. Install Python Video Annotator
+
+ ```bash
+ pip install python-video-annotator
+ ```
How to run:
-```
-start-video-annotator
-```
+1. After the installation completes, you can start Python Video Annotator with:
+
+ ```bash
+ start-video-annotator
+ ```
-### For developers:
+### For developers
-[Follow the steps described here](https://pythonvideoannotator.readthedocs.io/en/master/user-docs/install_and_run/install_and_run.html#for-developers)
+[Follow the steps described here](https://pythonvideoannotator.readthedocs.io/en/master/user-docs/install_and_run/index.html#for-developers)
+## Developers
+
+* Ricardo Ribeiro - collaborator of the [Scientific Software Platform](http://neuro.fchampalimaud.org/en/research/platforms/staff/Scientific%20Software/) of the [Champalimaud Foundation](http://fchampalimaud.org).
+* Hugo Cachitas working - collaborator of the [Innate Behavior Lab](http://neuro.fchampalimaud.org/en/research/investigators/research-groups/group/Vasconcelos/) of the [Champalimaud Foundation](http://fchampalimaud.org).
+* Carlos Mão de Ferro - collaborator of the [Scientific Software Platform](http://neuro.fchampalimaud.org/en/research/platforms/staff/Scientific%20Software/) of the [Champalimaud Foundation](http://fchampalimaud.org).
+* Luís Teixeira - collaborator of the [Scientific Software Platform](http://neuro.fchampalimaud.org/en/research/platforms/staff/Scientific%20Software/) of the [Champalimaud Foundation](http://fchampalimaud.org).
+
## Collaboration
This project was initially developed in collaboration with the [Innate Behavior Lab](http://neuro.fchampalimaud.org/en/research/investigators/research-groups/group/Vasconcelos/) to correct the result of a Computer Vision software to track flies in an arena
diff --git a/base/pythonvideoannotator-models b/base/pythonvideoannotator-models
index 56b6c06..8d56ca0 160000
--- a/base/pythonvideoannotator-models
+++ b/base/pythonvideoannotator-models
@@ -1 +1 @@
-Subproject commit 56b6c0617809d4027ef30631c602dcdf3a67cbfd
+Subproject commit 8d56ca075432a880105086fd1950a35a3f0b4ad4
diff --git a/base/pythonvideoannotator-models-gui b/base/pythonvideoannotator-models-gui
index ce800e3..6e0d5b6 160000
--- a/base/pythonvideoannotator-models-gui
+++ b/base/pythonvideoannotator-models-gui
@@ -1 +1 @@
-Subproject commit ce800e37ee1142875bc4cded475ceada84d0f753
+Subproject commit 6e0d5b6acf0a96284e95ffd7a7255b91e4054ab6
diff --git a/base/pythonvideoannotator/pythonvideoannotator/__init__.py b/base/pythonvideoannotator/pythonvideoannotator/__init__.py
index 0bb7f2c..cb461bb 100755
--- a/base/pythonvideoannotator/pythonvideoannotator/__init__.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/__init__.py
@@ -1,7 +1,7 @@
# !/usr/bin/python3
# -*- coding: utf-8 -*-
-__version__ = "3.118"
+__version__ = "3.306"
__author__ = ["Ricardo Ribeiro", "Carlos Mao de Ferro", "Hugo Cachitas"]
__credits__ = ["Ricardo Ribeiro", "Carlos Mao de Ferro", "Hugo Cachitas"]
__license__ = "Attribution-NonCommercial-ShareAlike 4.0 International"
@@ -10,3 +10,18 @@
__status__ = "Development"
from confapp import conf; conf += 'pythonvideoannotator.settings'
+
+
+import logging
+
+logger = logging.getLogger(__name__)
+logger.setLevel(conf.APP_LOG_HANDLER_LEVEL)
+
+if conf.APP_LOG_HANDLER_FILE:
+ logger = logging.getLogger()
+ loggers_formatter = logging.Formatter(conf.PYFORMS_LOG_FORMAT)
+
+ fh = logging.FileHandler(conf.APP_LOG_HANDLER_FILE)
+ fh.setLevel(conf.APP_LOG_HANDLER_FILE_LEVEL)
+ fh.setFormatter(loggers_formatter)
+ logger.addHandler(fh)
diff --git a/base/pythonvideoannotator/pythonvideoannotator/__main__.py b/base/pythonvideoannotator/pythonvideoannotator/__main__.py
index 3330a43..56e7ce6 100755
--- a/base/pythonvideoannotator/pythonvideoannotator/__main__.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/__main__.py
@@ -1,26 +1,29 @@
# !/usr/bin/python2
# -*- coding: utf-8 -*-
+from confapp import conf
import logging, traceback, pythonvideoannotator, sys, platform
-from confapp import conf
from urllib.parse import urlencode
-from uuid import getnode as get_mac
+from uuid import getnode as get_mac
from AnyQt.QtWidgets import QMessageBox
-from urllib.request import Request, urlopen
+from urllib.request import Request, urlopen
from AnyQt.QtWidgets import QApplication
+logger = logging.getLogger(__name__)
+
try:
import pyforms
except ImportError as err:
- logging.getLogger().critical(str(err), exc_info=True)
+ logger.critical(str(err), exc_info=True)
exit("Could not load pyforms! Is it installed?")
try:
from confapp import conf
except ImportError as err:
- logging.getLogger().critical(str(err), exc_info=True)
- exit("Could not load pyforms! Is it installed?")
+ logger.critical(str(err), exc_info=True)
+ exit("Could not load confapp! Is it installed?")
+
from pythonvideoannotator.base_module import BaseModule
@@ -48,6 +51,7 @@ def start(parent_win=None):
return res
except Exception as e:
+ logger.error(e, exc_info=True)
report = traceback.format_exc()
app = QApplication(sys.argv)
diff --git a/base/pythonvideoannotator/pythonvideoannotator/base_module/base.py b/base/pythonvideoannotator/pythonvideoannotator/base_module/base.py
index 1582ba6..10dfe8e 100644
--- a/base/pythonvideoannotator/pythonvideoannotator/base_module/base.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/base_module/base.py
@@ -62,6 +62,8 @@ def __init__(self):
self._player.double_click_event = self.on_player_double_click_event
self._player.drag_event = self.on_player_drag_event
self._player.end_drag_event = self.on_player_end_drag_event
+
+ # ignore these controls key release event
self._time.key_release_event = lambda x: x
self._player.key_release_event = lambda x: x
diff --git a/base/pythonvideoannotator/pythonvideoannotator/base_module/base_io.py b/base/pythonvideoannotator/pythonvideoannotator/base_module/base_io.py
index 9d0fbda..cacf2d2 100644
--- a/base/pythonvideoannotator/pythonvideoannotator/base_module/base_io.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/base_module/base_io.py
@@ -20,13 +20,15 @@ def save(self, data, project_path=None):
def load(self, data, project_path=None):
try:
self._project.load(data, project_path)
- except FileNotFoundError as e:
+ except Exception as e:
QMessageBox.critical(self, "Error", str(e))
def save_project(self, project_path=None):
try:
if project_path is None:
- project_path = QFileDialog.getExistingDirectory(self, "Select the project directory")
+ dialog = QFileDialog()
+ dialog.setLabelText(QFileDialog.Accept, 'Save')
+ project_path = dialog.getExistingDirectory(self, caption="Select the project directory to save")
if project_path is not None and str(project_path) != '':
project_path = str(project_path)
@@ -37,7 +39,7 @@ def save_project(self, project_path=None):
def load_project(self, project_path=None):
if project_path is None:
- project_path = QFileDialog.getExistingDirectory(self, "Select the project directory")
+ project_path = QFileDialog.getExistingDirectory(self, caption="Select the project directory to open")
if project_path is not None and str(project_path) != '':
self.load({}, str(project_path))
diff --git a/base/pythonvideoannotator/pythonvideoannotator/base_module/base_keys_events.py b/base/pythonvideoannotator/pythonvideoannotator/base_module/base_keys_events.py
index 51d86f2..94f099a 100644
--- a/base/pythonvideoannotator/pythonvideoannotator/base_module/base_keys_events.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/base_module/base_keys_events.py
@@ -1,4 +1,7 @@
+import logging
+
from AnyQt.QtGui import QKeySequence
+from AnyQt.QtCore import Qt
from pythonvideoannotator_models_gui.models.video.objects.object2d.datasets.path import Path
from .base_io import BaseIO
@@ -7,6 +10,7 @@
if conf.PYFORMS_MODE == 'GUI':
from AnyQt import QtCore
+logger = logging.getLogger(__name__)
class BaseKeysEvents(BaseIO):
@@ -29,18 +33,18 @@ def mark_point(self):
def keyReleaseEvent(self, event):
- event.ignore()
+ selected = self.project.tree.selected_item
+
+ if selected is not None:
+ selected.win.key_release_event(event)
- modifier = event.modifiers()
+ key = QKeySequence( event.modifiers() | event.key()).toString().encode("ascii", "ignore").decode()
+ logger.debug(key)
######################################################################################
#### TIMELINE SHORTCUTS ##############################################################
######################################################################################
- key = QKeySequence(event.modifiers() | event.key()).toString()
-
- print(key.encode("ascii", "ignore"))
-
# Move the end of the selected event to the left.
if key == conf.SHORT_KEYS['Move the end of the selected event to the left.']:
self.timeline.move_selected_event_end_left()
@@ -106,19 +110,19 @@ def keyReleaseEvent(self, event):
######################################################################################
# Go to the next event and then click the mark the point button.
- elif key == conf.SHORT_KEYS['Go to the next event and then click the mark the point button.']:
+ elif key == conf.SHORT_KEYS.get('Go to the next event and then click the mark the point button.', None):
if self.timeline.timeline_widget.selected is not None and \
self.timeline.timeline_widget.selected != self.timeline.timeline_widget.pointer:
self.move_to_next_event()
self.mark_point()
# Select the path of the next object and click the mark the point button.
- elif key == conf.SHORT_KEYS['Select the path of the next object and click the mark the point button.']:
+ elif key == conf.SHORT_KEYS.get('Select the path of the next object and click the mark the point button.', None):
self.select_next_path()
self.mark_point()
# "Click" the Mark Point button in the current Path.
- elif key == conf.SHORT_KEYS['"Click" the Mark Point button in the current Path.']:
+ elif key == conf.SHORT_KEYS.get('"Click" the Mark Point button in the current Path.', None):
self.mark_point()
######################################################################################
@@ -127,22 +131,27 @@ def keyReleaseEvent(self, event):
# Play or pause the video.
elif key == conf.SHORT_KEYS['Play or pause the video.']:
+ logger.debug('Play or pause the video')
self.player.toggle_playing()
# Jumps 1 frame backwards.
elif key == conf.SHORT_KEYS['Jumps 1 frame backward.']:
+ logger.debug('Jumps 1 frame backward.')
self.player.back_one_frame()
# Jumps 1 frame forward.
elif key == conf.SHORT_KEYS['Jumps 1 frame forward.']:
+ logger.debug('Jumps 1 frame forward.')
self.player.forward_one_frame()
# Jumps 20 seconds backward.
elif key == conf.SHORT_KEYS['Jumps 20 seconds backward.']:
+ logger.debug('Jumps 20 seconds backward.')
self.player.jump_backward()
# Jumps 20 seconds forward.
elif key == conf.SHORT_KEYS['Jumps 20 seconds forward.']:
+ logger.debug('Jumps 20 seconds forward.')
self.player.jump_forward()
# Set player speed to 1x.
diff --git a/base/pythonvideoannotator/pythonvideoannotator/settings.py b/base/pythonvideoannotator/pythonvideoannotator/settings.py
index 2adc8ed..5c354c5 100644
--- a/base/pythonvideoannotator/pythonvideoannotator/settings.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/settings.py
@@ -2,19 +2,15 @@
# -*- coding: utf-8 -*-
SETTINGS_PRIORITY = 10
-import logging, os
+import os
from pyforms_gui.utils.plugins_finder import PluginsFinder
-
-
-APP_LOG_FILENAME = 'pythonvideoannotator.log'
-APP_LOG_HANDLER_FILE_LEVEL = logging.DEBUG
-APP_LOG_HANDLER_CONSOLE_LEVEL = logging.INFO
-
-PYFORMS_LOG_HANDLER_FILE_LEVEL = logging.DEBUG
-PYFORMS_LOG_HANDLER_CONSOLE_LEVEL = logging.INFO
-
-PYFORMS_SILENT_PLUGINS_FINDER = False
+# LOGGING CONFIGURATION #################################
+import logging
+APP_LOG_HANDLER_LEVEL = logging.INFO
+APP_LOG_HANDLER_FILE = 'video-annotator.log'
+APP_LOG_HANDLER_FILE_LEVEL = logging.INFO
+#########################################################
VIDEO_FILE_PATH = None
CHART_FILE_PATH = None
@@ -30,7 +26,7 @@
SAVED_GRAPH_FILE_PATH = ""
SAVED_BONSAI_FILE_PATH = ""
-MAIN_WINDOW_GEOMETRY = 0, 0, 1000, 800
+MAIN_WINDOW_GEOMETRY = 0, 50, 1000, 800
#MAIN_WINDOW_GEOMETRY = 1700, 50, 1400, 1000
#VIDEO_FILE_PATH = '/home/ricardo/Downloads/fc2_save_2013-10-29-124117-0001.avi'
@@ -61,7 +57,7 @@
MODULES += 'pythonvideoannotator_module_patheditor'
MODULES += 'pythonvideoannotator_module_pathmap'
MODULES += 'pythonvideoannotator_module_deeplab'
-#MODULES += 'pythonvideoannotator_module_idtrackerai'
+MODULES += 'pythonvideoannotator_module_idtrackerai'
@@ -85,23 +81,26 @@
'Select the previous event.': 'Alt+A',
# PLAYER
- 'Play or pause the video.': 'Meta+Space',
- 'Jumps 1 frame backward.': 'Meta+Alt+Num+Left',
- 'Jumps 1 frame forward.': 'Meta+Alt+Num+Right',
- 'Jumps 20 seconds backward.': 'Meta+Shift+Num+Left',
- 'Jumps 20 seconds forward.': 'Meta+Shift+Num+Right',
- 'Set player speed to 1x.': 'Meta+1',
- 'Set player speed to 2x.': 'Meta+2',
- 'Set player speed to 3x.': 'Meta+3',
- 'Set player speed to 4x.': 'Meta+4',
- 'Set player speed to 5x.': 'Meta+5',
- 'Set player speed to 6x.': 'Meta+6',
- 'Set player speed to 7x.': 'Meta+7',
- 'Set player speed to 8x.': 'Meta+8',
- 'Set player speed to 9x.': 'Meta+9',
+ 'Play or pause the video.': 'Ctrl+P',
+ 'Jumps 1 frame backward.': 'Ctrl+I',
+ 'Jumps 1 frame forward.': 'Ctrl+O',
+ 'Jumps 20 seconds backward.': 'Ctrl+K',
+ 'Jumps 20 seconds forward.': 'Ctrl+L',
+ 'Set player speed to 1x.': 'Ctrl+1',
+ 'Set player speed to 2x.': 'Ctrl+2',
+ 'Set player speed to 3x.': 'Ctrl+3',
+ 'Set player speed to 4x.': 'Ctrl+4',
+ 'Set player speed to 5x.': 'Ctrl+5',
+ 'Set player speed to 6x.': 'Ctrl+6',
+ 'Set player speed to 7x.': 'Ctrl+7',
+ 'Set player speed to 8x.': 'Ctrl+8',
+ 'Set player speed to 9x.': 'Ctrl+9',
# SPECIAL KEYS
- 'Go to the next event and then click the mark the point button.': 'Ctrl+I',
- 'Select the path of the next object and click the mark the point button.': 'Ctrl+U',
- '"Click" the Mark Point button in the current Path.': 'Ctrl+O'
-}
\ No newline at end of file
+ #'Go to the next event and then click the mark the point button.': 'Ctrl+I',
+ #'Select the path of the next object and click the mark the point button.': 'Ctrl+U',
+ #'"Click" the Mark Point button in the current Path.': 'Ctrl++'
+}
+
+from AnyQt.QtWidgets import QColorDialog, QFileDialog
+PYFORMS_COLORDIALOGS_OPTIONS = QColorDialog.ShowAlphaChannel
\ No newline at end of file
diff --git a/base/pythonvideoannotator/pythonvideoannotator/userstats.py b/base/pythonvideoannotator/pythonvideoannotator/userstats.py
index b187a99..521223a 100644
--- a/base/pythonvideoannotator/pythonvideoannotator/userstats.py
+++ b/base/pythonvideoannotator/pythonvideoannotator/userstats.py
@@ -91,6 +91,6 @@ def register_access():
data = {'app-id': app_id, 'reg-id': reg_id, 'os-name' : os_name ,'version': version}
url = "{}/register".format(conf.USERSTATS_URL)
request = Request(url, urlencode(data).encode())
- urlopen(request).read().decode()
+ urlopen(request, timeout=1).read().decode()
except Exception as e:
print("Could not register new access", e)
diff --git a/base/pythonvideoannotator/setup.py b/base/pythonvideoannotator/setup.py
index bc12937..107bd6d 100644
--- a/base/pythonvideoannotator/setup.py
+++ b/base/pythonvideoannotator/setup.py
@@ -2,42 +2,44 @@
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
-import re
+import re, os
-with open('pythonvideoannotator/__init__.py', 'r') as fd:
+
+PACKAGE_PATH = os.path.dirname(os.path.realpath(__file__))
+
+with open(os.path.join(PACKAGE_PATH, 'pythonvideoannotator','__init__.py'), 'r') as fd:
content = fd.read()
version = re.search(
r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', content, re.MULTILINE).group(1)
-with open('../../README.md', 'r') as fd:
+with open(os.path.join(PACKAGE_PATH, '..','..','README.md'), 'r') as fd:
long_description = fd.read()
# REQUIREMENTS BEGIN
REQUIREMENTS = [
- "modular-computer-vision-api==0.2",
- "geometry_designer==0.3",
- "mcv-gui==0.1",
- "pyforms-gui==4.901",
- "modular-computer-vision-api-gui==0.2",
- "python-video-annotator-models==0.5",
- "python-video-annotator-models-gui==0.5",
- "python-video-annotator-module-timeline==0.4",
- "python-video-annotator-module-tracking==0.4",
- "python-video-annotator-module-eventstats==0.3",
- "python-video-annotator-module-create-paths==0.3",
- "python-video-annotator-module-motion-counter==0.3",
- "python-video-annotator-module-path-map==0.4",
- "python-video-annotator-module-import-export==0.3",
- "python-video-annotator-module-smooth-paths==0.3",
- "python-video-annotator-module-distances==0.3",
- "python-video-annotator-module-path-editor==0.3",
- "python-video-annotator-module-virtual-object-generator==0.4",
- "python-video-annotator-module-regions-filter==0.3",
- "python-video-annotator-module-contours-images==0.3",
- "python-video-annotator-module-deeplab==0.9",
- "python-video-annotator-module-background-finder==0.3",
- "python-video-annotator-module-find-orientation==0.3"
+ "geometry_designer==0.4.38",
+ "modular-computer-vision-api-gui==0.3.31",
+ "pyforms-gui==4.904.152",
+ "modular-computer-vision-api==0.3.29",
+ "python-video-annotator-models-gui==0.7.63",
+ "python-video-annotator-models==0.8.82",
+ "python-video-annotator-module-timeline==0.6.26",
+ "python-video-annotator-module-eventstats==0.5.15",
+ "python-video-annotator-module-virtual-object-generator==0.6.26",
+ "python-video-annotator-module-deeplab==0.902.21",
+ "python-video-annotator-module-contours-images==0.5.28",
+ "python-video-annotator-module-tracking==0.6.38",
+ "python-video-annotator-module-smooth-paths==0.5.19",
+ "python-video-annotator-module-distances==0.5.18",
+ "python-video-annotator-module-path-map==0.6.16",
+ "python-video-annotator-module-motion-counter==0.5.26",
+ "python-video-annotator-module-create-paths==0.5.15",
+ "python-video-annotator-module-regions-filter==0.5.18",
+ "python-video-annotator-module-import-export==0.5.23",
+ "python-video-annotator-module-background-finder==0.5.21",
+ "python-video-annotator-module-find-orientation==0.5.18",
+ "python-video-annotator-module-path-editor==0.5.28"
]
# REQUIREMENTS END
diff --git a/docs/source/_static/modules/idtrackerai_1_select_obj.png b/docs/source/_static/modules/idtrackerai_1_select_obj.png
new file mode 100644
index 0000000..a3f6cc4
Binary files /dev/null and b/docs/source/_static/modules/idtrackerai_1_select_obj.png differ
diff --git a/docs/source/_static/modules/idtrackerai_2_select_centroid.png b/docs/source/_static/modules/idtrackerai_2_select_centroid.png
new file mode 100644
index 0000000..b6ff94b
Binary files /dev/null and b/docs/source/_static/modules/idtrackerai_2_select_centroid.png differ
diff --git a/docs/source/index.rst b/docs/source/index.rst
index c7ae542..f822090 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -29,6 +29,7 @@
:includehidden:
:caption: Modules \ Plugins
+ modules/idtrackerai
modules/label-deeplabcut
modules/path-map
modules/tracking
@@ -73,11 +74,12 @@ What is the Python Video Annotator?
------------------------------------
|
-| The **PythonVideoAnnotator** is a graphical application written in python, to analyse videos and create notes for events in the video. It was developed with the aim of helping neuroscience and ethology researchers indentify animals' behaviours based on the information extracted from the video.
+| The **PythonVideoAnnotator** is a graphical application written in python, to analyze videos and create notes for events in the video. It was developed with the aim of helping neuroscience and ethology researchers identify animals’ behaviors based on the information extracted from the video.
|
-| Paths, contours and outputs of external devices, like accelerometers, sound recorders, pokes, pressure devices and other sensors can be combined to find classes of events to identify behaviours.
+| Paths, contours and outputs of external devices, like accelerometers, sound recorders, pokes, pressure devices and other sensors can be combined to find classes of events to identify behaviors.
|
+
|
.. image:: _static/index/project.png
diff --git a/docs/source/modules/idtrackerai.rst b/docs/source/modules/idtrackerai.rst
new file mode 100644
index 0000000..2c196ba
--- /dev/null
+++ b/docs/source/modules/idtrackerai.rst
@@ -0,0 +1,151 @@
+idtracker.ai validator
+======================
+
+This plugin has been developed with the de Polavieja Lab at the Champalimaud Foundation
+and it is part of `idtracker.ai `_ project. If you are using
+idtracker.ai to track your videos or this plugin to correct trajectories, please cite:
+
+ `Romero-Ferrero, F., Bergomi, M.G., Hinz, R.C., Heras, F.J.H., de Polavieja, G.G., Nature Methods, 2019.
+ idtracker.ai: tracking all individuals in small or large collectives of unmarked animals `_
+
+.. code-block:: bibtex
+
+ @article{romero2019idtracker,
+ title={idtracker.ai: tracking all individuals in small or large collectives of unmarked animals},
+ author={Romero-Ferrero, Francisco and Bergomi, Mattia G and Hinz, Robert C and Heras, Francisco JH and de Polavieja, Gonzalo G},
+ journal={Nature methods},
+ volume={16},
+ number={2},
+ pages={179},
+ year={2019},
+ publisher={Nature Publishing Group}
+ }
+
+-------------------------------------
+A plugin to correct idtracker.ai trajectories
+-------------------------------------
+
+Under good `video condtions ` idtracker.ai typically gives very high accurate trajectories. However, due to not so good video conditions some animals might be badly identified for in some parts of the video. Also, during crossings, the interpolation algorithm might place the centroid of the animal in a place different to the center of mass of the animal.
+
+This plugin allows to correct wrongly identified animals in the video and also to modify the position of the centroids so that they are closer to the center of mass of the corresponding animal.
+
+In the following sections we explain how to load a tracking session into the video annotator, how to correct trajectories, and how to save the results to get new and updated trajectories files.
+
+--------------------------------------
+Load an idtracker.ai tracking session
+--------------------------------------
+
+If you finished tracking a video using the GUI from `idtracker.ai `_, you can press the **Validate trajectories** button on the bottom right corner to open the validation GUI. The current tracking session will be automatically loaded into the video annotator. Note that depending on the length of the video and the number of animals the process of loading the data can take some time.
+
+To load an idtracker.ai session from scratch you have two options. Both require to open a terminal (Anaconda Powershell Prompt in Windows) and run a command inside of the virtual environment where you installed idtracker.ai.
+
+1. Open idtracker.ai by running the command:
+
+.. code-block:: bash
+
+ idtrackerai
+
+In the GUI, click the button "Open" and select the video for which you want to validate the trajectories. In the text box "Session", add the name of the session that you want to open. Remember that if the session folder is "session_test", the name of the tracking session will be "test". If the name is correct the button "Validate trajectories" in the bottom right corner will activate. Click that button and the validation GUI will open.
+
+2. Run the video annotator (see :doc:`../_static/install_and_run/index`), press the button **Open** and open the session folder you want to load. This will automatically read the necessary files from the session folder and create an "Idtrackerai object".
+
+
+--------------------
+Validate the trajectories
+--------------------
+
+To visualize the trajectories and start validating them, make sure that an "Idtrackerai object" is selected (high-lighted in blue in the "Video list" panel).
+
+.. image:: /_static/modules/idtrackerai_1_select_obj.png
+
+In the video preview, the centroids of animals that belong to a blob classified by the algorithm as a single animal, will show a number. The centroids of animals that belong to a blob classified by the algorithm as a crossing, will show a number with the prefix 'c-'. The centroids of any animal for which the user modified its identity or the position of the centroid, will show a number with the prefix 'u-'.
+
+*********************************
+Change the identity of a centroid
+*********************************
+
+To change the identity of a centroid, double click on top of a centroid. A window "New identity" will pop up. You can type the new identity and press "Ok". The identity will be propagated to the previous and next frames until the next crossing or until the animal disappears.
+
+
+*********************************
+Move a centroid to a different position
+*********************************
+
+To move a centroid to a different position, click on it, drag it and drop it wherever you want its new position to be.
+
+*********************************
+Add a new centroid to a blob
+*********************************
+
+To add a new centroid to an existing blob. Click on a centroid of the giving blob. In the "Details" panel on the right, check the box "Add centroid to selected blob" (or press "Ctrl+C"). Then click again on the blob. This will open a window in which you will need to introduce the identity of the centroid to be added. Enter a valid identity and press "Ok". A new centroid will be created. If you see a gray ring in the cursor just click anywhere in the frame and it will disappear.
+
+*********************************
+Delete a centroid from a blob
+*********************************
+
+To delete a centroid, click on it and press the button "Delete centroid" in the "Details" panel on the right (or press "Ctrl+D").
+
+Only centroids of duplicated identities and centroids of blobs with multiple centroids can be deleted. To delete a centroid of a unique identity first create a new centroid for that identity.
+
+
+*********************************
+Add a blob
+*********************************
+
+Animals that where not detected following the preprocessing parameters won't have a centroid (blob). To assign a centroid to a non-segmented animal, press anywhere in the image where there is not a centroid. In de "Details" panel on the right, check the box "Add blob" (or press "Ctrl+B"). Then double click anywhere in the frame. A window will pop-up where you can introduce the identity of the new centroid generated. Note that blob generated by the user cannot be deleted using any button. They can be cleared using the "Clear user updates" functions as described below.
+
+*********************************
+Clear all user updates
+*********************************
+
+If you want to recover the original identities assigned by the algorithm for a particular part of the video (both centroids and blobs), click on the button "Clear user updates for all identities" in the "Details" panel on the right. This will show a window where you can indicate the starting and ending point to define the interval where the identities will be reset.
+
+
+*********************************
+Clear user updates for a given identity
+*********************************
+
+To clear the user updates for a given identity, select a centroid of the identity X that you want to reset. Then, on the "Details" panel on the right, click the button "Clear user updates for X". This will show a window where you can indicate the starting and ending point to define the interval where the identities will be reset.
+
+*********************************
+Local interpolation
+*********************************
+
+In some situations, you might want to modify the position of the centroid for a given identity for multiple frames in a row. This can be very time consuming. To facilitate the work, we implemented a "Local interpolation for X" button. This will interpolate the positions for a given identity between two user generated centroids. Note that this runs a linear interpolation, so we recommend to add user generated centroids when the animal changes direction.
+
+To interpolate the positions for a given identity follow these steps.
+
+1. Modify the centroid of a given identity for a set of frames. You do not need to modify it for all the frame, just when the animals is changing direction.
+2. Make sure that the identity is unique for the interval where you want to interpolate the centroids.
+3. Click the button "Local interpolation for X".
+4. Add the initial and ending frames of the interval where you want the interplation to run. Note that the first and last frame must include a user generated centroid (i.e. a centroid with the prefix 'u-').
+
+
+*********************************
+Global interpolation
+*********************************
+
+Click the button "Global interpolation" to run the idtracker.ai interpolation algorithm that assigns the centroids to the blobs that correspond to multiple animals. This is particularly useful when you are only modifying identities before and after crosings. The algorithm might work if you have also modified the positions the centroids in the blobs corresponding to crossings. However, we haven't test it deeply, so we recommend to only used if you only modified identities and not centroids.
+
+--------------------
+Save the results
+--------------------
+
+To save the results of your validation, press the button "Save updated identities" on the "Details" pannel. This will update the "blobs_collection_no_gaps.npy" file in the preprocessing folder insider of the session folder. Also it will generate two new "trajectories_TIMESTAMP.npy" and "trajectories_wo_gaps_TIMESTAMP.npy" files in the folders "trajectories" and "trajectories_wo_gaps" respectively. Note that this proces can take a few minutes if your video is very long or it has many animals. We recommend saving the updated identities regularly.
+
+
+-----------
+Keys events
+-----------
+
+A part form the :doc:`../user-docs/shortcuts/index` of the video annotator, we added two new shortcuts to automatically advance to the next and previous crossings (or frames where an animal is missing).
+
+========================================================================== =================================
+EVENT SHORT KEYS
+========================================================================== =================================
+Go to next crossing Ctrl+S
+Go to previous crossing Ctrl+A
+Check/Uncheck add centroid Ctrl+C
+Check/Uncheck add blob Ctrl+B
+Delete centroid Ctrl+D
+========================================================================== =================================
diff --git a/docs/source/modules/label-deeplabcut.rst b/docs/source/modules/label-deeplabcut.rst
index eab2f6c..594489b 100644
--- a/docs/source/modules/label-deeplabcut.rst
+++ b/docs/source/modules/label-deeplabcut.rst
@@ -134,3 +134,35 @@ Result
The result will be a csv file for each labeled video. The csv file will look like this:
.. image:: /_static/modules/deeplabcut-csv-result.png
+
+
+
+
+
+*******************
+Install DeepLabCut
+*******************
+
+**for windows and mac:**
+
+Run the following commands:
+
+.. code-block:: bash
+
+ pip install deeplabcut
+ pip install -U wxPython
+ pip install --ignore-installed tensorflow==1.10
+
+**for linux:**
+
+| Go to this link: https://extras.wxpython.org/wxPython4/extras/linux/gtk3/.
+| There you will have to choose your linux distribution and the wheel for Python 3.6.
+| Then run the commands under, but replace the middle command with whatever fits your linux distribution.
+|
+| For example, if you have ubuntu 18.04, you will have to run the following commands:
+
+.. code-block:: bash
+
+ pip install deeplabcut
+ pip install https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04/wxPython-4.0.4-cp36-cp36m-linux_x86_64.whl
+ pip install --ignore-installed tensorflow==1.10
\ No newline at end of file
diff --git a/docs/source/user-docs/install_and_run/index.rst b/docs/source/user-docs/install_and_run/index.rst
index 36f026e..0e6f29d 100644
--- a/docs/source/user-docs/install_and_run/index.rst
+++ b/docs/source/user-docs/install_and_run/index.rst
@@ -14,7 +14,7 @@ Installing
-----------
-1. Install Python 3.6 from [python.org](https://www.python.org/)
+1. Install Python 3.6 from [python.org](https://www.python.org/) or use the Anaconda [Anaconda](https://www.anaconda.com/) Python version.
2. Install pypi from [pypi.org](https://pypi.org/)
@@ -43,53 +43,15 @@ ______________
Installing
-----------
-
-| 1. Download & install [Anaconda](https://www.anaconda.com/download/) or [Miniconda](https://conda.io/miniconda.html).
-|
-| 2. Download & install the environment configuration file:
-
-**for ubuntu:**
-
-.. code-block:: bash
-
- conda install wget
- wget https://raw.githubusercontent.com/UmSenhorQualquer/pythonVideoAnnotator/master/utils/environment-ubuntu17.yml --no-check-certificate
- conda env create -f environment-ubuntu17.yml
- source activate videoannotator
-
-**for mac:**
-
-.. code-block:: bash
-
- conda install wget
- wget https://raw.githubusercontent.com/UmSenhorQualquer/pythonVideoAnnotator/master/utils/environment-macosx.yml --no-check-certificate
- conda env create -f environment-macosx.yml
- source activate videoannotator
-
-
-**for windows:**
-
-.. note ::
-
- Make sure you are using the Anaconda prompt to execute the next commands.
-
-.. code-block:: bash
-
- conda install -c menpo wget
- wget https://raw.githubusercontent.com/UmSenhorQualquer/pythonVideoAnnotator/master/utils/environment-windows.yml --no-check-certificate
- conda env create -f environment-windows.yml
- conda activate videoannotator
-
-|
-| 3. Activate the environment, download the source code and install it:
+Download the source code and install it:
**for ubuntu, mac and windows:**
.. code-block:: bash
git clone --recursive https://github.com/UmSenhorQualquer/pythonVideoAnnotator.git
- cd pythonVideoAnnotator/utils
- python install.py
+ cd pythonVideoAnnotator
+ python utils/install.py
|
@@ -110,35 +72,3 @@ Or these commands:
source activate videoannotator
python -m pythonvideoannotator
-
-
-
-
-
-*******************
-Install DeepLabCut
-*******************
-
-**for windows and mac:**
-
-Run the following commands:
-
-.. code-block:: bash
-
- pip install deeplabcut
- pip install -U wxPython
- pip install --ignore-installed tensorflow==1.10
-
-**for linux:**
-
-| Go to this link: https://extras.wxpython.org/wxPython4/extras/linux/gtk3/.
-| There you will have to choose your linux distribution and the wheel for Python 3.6.
-| Then run the commands under, but replace the middle command with whatever fits your linux distribution.
-|
-| For example, if you have ubuntu 18.04, you will have to run the following commands:
-
-.. code-block:: bash
-
- pip install deeplabcut
- pip install https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04/wxPython-4.0.4-cp36-cp36m-linux_x86_64.whl
- pip install --ignore-installed tensorflow==1.10
\ No newline at end of file
diff --git a/docs/source/user-docs/shortcuts/index.rst b/docs/source/user-docs/shortcuts/index.rst
index a58f463..a874236 100644
--- a/docs/source/user-docs/shortcuts/index.rst
+++ b/docs/source/user-docs/shortcuts/index.rst
@@ -38,30 +38,19 @@ ________
========================================================================== =================================
EVENT SHORT KEYS
========================================================================== =================================
-Play or pause the video. Meta+Space
-Jumps 1 frame backward. Meta+Alt+Num+Left
-Jumps 1 frame forward. Meta+Alt+Num+Right
-Jumps 20 seconds backward. Meta+Shift+Num+Left
-Jumps 20 seconds forward. Meta+Shift+Num+Right
-Set player speed to 1x. Meta+1
-Set player speed to 2x. Meta+2
-Set player speed to 3x. Meta+3
-Set player speed to 4x. Meta+4
-Set player speed to 5x. Meta+5
-Set player speed to 6x. Meta+6
-Set player speed to 7x. Meta+7
-Set player speed to 8x. Meta+8
-Set player speed to 9x. Meta+9
+Play or pause the video. Ctrl+P
+Jumps 1 frame backward. Ctrl+I
+Jumps 1 frame forward. Ctrl+O
+Jumps 20 seconds backward. Ctrl+K
+Jumps 20 seconds forward. Ctrl+L
+Set player speed to 1x. Ctrl+1
+Set player speed to 2x. Ctrl+2
+Set player speed to 3x. Ctrl+3
+Set player speed to 4x. Ctrl+4
+Set player speed to 5x. Ctrl+5
+Set player speed to 6x. Ctrl+6
+Set player speed to 7x. Ctrl+7
+Set player speed to 8x. Ctrl+8
+Set player speed to 9x. Ctrl+9
========================================================================== =================================
-
-SPECIAL KEYS
-______________
-
-========================================================================== =================================
- EVENT SHORT KEYS
-========================================================================== =================================
-Go to the next event and then click the mark the point button. Ctrl+I
-Select the path of the next object and click the mark the point button. Ctrl+U
-"Click" the Mark Point button in the current Path. Ctrl+O
-========================================================================== =================================
diff --git a/libraries/confapp b/libraries/confapp
new file mode 160000
index 0000000..a1356ee
--- /dev/null
+++ b/libraries/confapp
@@ -0,0 +1 @@
+Subproject commit a1356ee118430f79e4ec6ae21625de924d7045c8
diff --git a/libraries/geometry-designer b/libraries/geometry-designer
index 9d74aae..c040c0e 160000
--- a/libraries/geometry-designer
+++ b/libraries/geometry-designer
@@ -1 +1 @@
-Subproject commit 9d74aae615d612a289b398812e693b29d985e460
+Subproject commit c040c0e9ca4ef1d17b26453f01958a640001c321
diff --git a/libraries/mcv-api b/libraries/mcv-api
index 38ed39b..b4e2e85 160000
--- a/libraries/mcv-api
+++ b/libraries/mcv-api
@@ -1 +1 @@
-Subproject commit 38ed39bc19ef141c2d3eb0f731c5b89739da4774
+Subproject commit b4e2e8580fa2383de2cd9e18f5610cd48adf3f85
diff --git a/libraries/mcv-gui b/libraries/mcv-gui
index 4464500..01ba1aa 160000
--- a/libraries/mcv-gui
+++ b/libraries/mcv-gui
@@ -1 +1 @@
-Subproject commit 446450089eefef8bd6f4b2de2f109a3f22e99b18
+Subproject commit 01ba1aa039c2ba88b8f9540056193ad34e400425
diff --git a/libraries/mcv-gui-editor b/libraries/mcv-gui-editor
deleted file mode 160000
index ddd626a..0000000
--- a/libraries/mcv-gui-editor
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ddd626afa16a713b1e4fe2d4b9d6ae46369b5d01
diff --git a/libraries/pyforms-gui b/libraries/pyforms-gui
index 20c8aa6..5bb69b4 160000
--- a/libraries/pyforms-gui
+++ b/libraries/pyforms-gui
@@ -1 +1 @@
-Subproject commit 20c8aa618c5631b1d5a416c5ff8952c4481f6a32
+Subproject commit 5bb69b4f9ec5695f507d5f9accc7884d6f0d3b82
diff --git a/plugins/pythonvideoannotator-module-backgroundfinder b/plugins/pythonvideoannotator-module-backgroundfinder
index e3803e7..1186cd8 160000
--- a/plugins/pythonvideoannotator-module-backgroundfinder
+++ b/plugins/pythonvideoannotator-module-backgroundfinder
@@ -1 +1 @@
-Subproject commit e3803e7544182444b703a2cb0ea91568a06698da
+Subproject commit 1186cd877a7d459a075764adff2bcea97716d1ba
diff --git a/plugins/pythonvideoannotator-module-contoursimages b/plugins/pythonvideoannotator-module-contoursimages
index 93a3732..dd419ce 160000
--- a/plugins/pythonvideoannotator-module-contoursimages
+++ b/plugins/pythonvideoannotator-module-contoursimages
@@ -1 +1 @@
-Subproject commit 93a373284a4b5e18bc80dadaa42a19c85f0dad75
+Subproject commit dd419ce7794fcfe368f1098be84ebf03584ab232
diff --git a/plugins/pythonvideoannotator-module-createpaths b/plugins/pythonvideoannotator-module-createpaths
index 51b14a7..d6ab5d7 160000
--- a/plugins/pythonvideoannotator-module-createpaths
+++ b/plugins/pythonvideoannotator-module-createpaths
@@ -1 +1 @@
-Subproject commit 51b14a7bc0c3c0ea3875d314723e1520a40e8412
+Subproject commit d6ab5d7bd3d9ec98585b5658fd475c0a92ff98f8
diff --git a/plugins/pythonvideoannotator-module-deeplab b/plugins/pythonvideoannotator-module-deeplab
index 61bf318..fa6c315 160000
--- a/plugins/pythonvideoannotator-module-deeplab
+++ b/plugins/pythonvideoannotator-module-deeplab
@@ -1 +1 @@
-Subproject commit 61bf318b200f7e30e022cc918e590fdd15e19971
+Subproject commit fa6c3156ccc38fe1d6737d3b3fdef10adf832edf
diff --git a/plugins/pythonvideoannotator-module-distances b/plugins/pythonvideoannotator-module-distances
index 1fe1373..f6c4afb 160000
--- a/plugins/pythonvideoannotator-module-distances
+++ b/plugins/pythonvideoannotator-module-distances
@@ -1 +1 @@
-Subproject commit 1fe13738924ecdd6fcc9331309bba99e46d84117
+Subproject commit f6c4afb89d4eac5c70602f349422046d757e4ac8
diff --git a/plugins/pythonvideoannotator-module-eventsstats b/plugins/pythonvideoannotator-module-eventsstats
index 06fbb40..e2dc5ee 160000
--- a/plugins/pythonvideoannotator-module-eventsstats
+++ b/plugins/pythonvideoannotator-module-eventsstats
@@ -1 +1 @@
-Subproject commit 06fbb401a192aaac82fb9de005374938997cba40
+Subproject commit e2dc5ee50f3d2a36c9cb8b81202e318022b35650
diff --git a/plugins/pythonvideoannotator-module-findorientation b/plugins/pythonvideoannotator-module-findorientation
index bc3ab2a..3e94c06 160000
--- a/plugins/pythonvideoannotator-module-findorientation
+++ b/plugins/pythonvideoannotator-module-findorientation
@@ -1 +1 @@
-Subproject commit bc3ab2a16e52f1d237aa8d77f3442a97ced02884
+Subproject commit 3e94c06ebf8466eb9e39ab35ae4556930ee11380
diff --git a/plugins/pythonvideoannotator-module-idtrackerai b/plugins/pythonvideoannotator-module-idtrackerai
new file mode 160000
index 0000000..9e46a5d
--- /dev/null
+++ b/plugins/pythonvideoannotator-module-idtrackerai
@@ -0,0 +1 @@
+Subproject commit 9e46a5db723a86beaa5e04c1653a3dd1e6672e36
diff --git a/plugins/pythonvideoannotator-module-importexport b/plugins/pythonvideoannotator-module-importexport
index 9e3de71..eaca485 160000
--- a/plugins/pythonvideoannotator-module-importexport
+++ b/plugins/pythonvideoannotator-module-importexport
@@ -1 +1 @@
-Subproject commit 9e3de71ee0503c2346d5ccb70850847259b7c8fb
+Subproject commit eaca48576daa482eab0576a7f8ad7da17ab51725
diff --git a/plugins/pythonvideoannotator-module-motioncounter b/plugins/pythonvideoannotator-module-motioncounter
index fa6b7df..0fe282d 160000
--- a/plugins/pythonvideoannotator-module-motioncounter
+++ b/plugins/pythonvideoannotator-module-motioncounter
@@ -1 +1 @@
-Subproject commit fa6b7df4d7509a76bc0079d3bc6ac8a2e493bdf4
+Subproject commit 0fe282d202ccf88b2d74d8153b80170ce69d3dc4
diff --git a/plugins/pythonvideoannotator-module-patheditor b/plugins/pythonvideoannotator-module-patheditor
index 16993ef..31612ea 160000
--- a/plugins/pythonvideoannotator-module-patheditor
+++ b/plugins/pythonvideoannotator-module-patheditor
@@ -1 +1 @@
-Subproject commit 16993ef78dde056501c49e7d86d93d08910b4e35
+Subproject commit 31612ea9620c2c247c22c55a93fb13f8a0834691
diff --git a/plugins/pythonvideoannotator-module-pathmap b/plugins/pythonvideoannotator-module-pathmap
index a244aab..623ee14 160000
--- a/plugins/pythonvideoannotator-module-pathmap
+++ b/plugins/pythonvideoannotator-module-pathmap
@@ -1 +1 @@
-Subproject commit a244aab13734893fbc40ddb5877b5f74a7980c66
+Subproject commit 623ee143ea1a676738c558e2ae5da4be5ed1f9eb
diff --git a/plugins/pythonvideoannotator-module-regionsfilter b/plugins/pythonvideoannotator-module-regionsfilter
index bf97366..5ae9e34 160000
--- a/plugins/pythonvideoannotator-module-regionsfilter
+++ b/plugins/pythonvideoannotator-module-regionsfilter
@@ -1 +1 @@
-Subproject commit bf97366554d75404cede80b8beaa707e9a402b62
+Subproject commit 5ae9e3462f09a47effaebaa329434dd19afb559a
diff --git a/plugins/pythonvideoannotator-module-smoothpaths b/plugins/pythonvideoannotator-module-smoothpaths
index aca630a..f5fc615 160000
--- a/plugins/pythonvideoannotator-module-smoothpaths
+++ b/plugins/pythonvideoannotator-module-smoothpaths
@@ -1 +1 @@
-Subproject commit aca630a82128e83f823afe15b1e3a883fea2b544
+Subproject commit f5fc615a7b030beb17f4df50eb590e170a6ba0dc
diff --git a/plugins/pythonvideoannotator-module-timeline b/plugins/pythonvideoannotator-module-timeline
index 7ebef1c..d197d94 160000
--- a/plugins/pythonvideoannotator-module-timeline
+++ b/plugins/pythonvideoannotator-module-timeline
@@ -1 +1 @@
-Subproject commit 7ebef1c2e80bf190137a358a75a1e3c2c0eb19b3
+Subproject commit d197d94f4a72b70704d0a8e7e1ed4cf8da078f35
diff --git a/plugins/pythonvideoannotator-module-tracking b/plugins/pythonvideoannotator-module-tracking
index 5e3e247..dfca3f7 160000
--- a/plugins/pythonvideoannotator-module-tracking
+++ b/plugins/pythonvideoannotator-module-tracking
@@ -1 +1 @@
-Subproject commit 5e3e2478764a085477adae09ccab1db93d142ade
+Subproject commit dfca3f7e8af653de092c2fc204bf223cfc8259e8
diff --git a/plugins/pythonvideoannotator-module-virtualobjectgenerator b/plugins/pythonvideoannotator-module-virtualobjectgenerator
index 39b39a0..d2fd9b5 160000
--- a/plugins/pythonvideoannotator-module-virtualobjectgenerator
+++ b/plugins/pythonvideoannotator-module-virtualobjectgenerator
@@ -1 +1 @@
-Subproject commit 39b39a0c577597ba0ce1e1c4cc62ffe78a503e58
+Subproject commit d2fd9b56b206b7531610f01bfeacb1b498cd7056
diff --git a/utils/deploy-pypi.py b/utils/deploy-pypi.py
index 52b9598..ba24356 100644
--- a/utils/deploy-pypi.py
+++ b/utils/deploy-pypi.py
@@ -1,57 +1,110 @@
-import os
+import os, shutil
import xmlrpc.client
from subprocess import Popen, PIPE
-import shutil
-
+from setuptools import find_packages
+from natsort import natsorted
+
+###### CONFIGURATIONS #############################
+HEADER = '\033[95m'
+OKBLUE = '\033[94m'
+OKGREEN = '\033[92m'
+WARNING = '\033[93m'
+FAIL = '\033[91m'
+ENDC = '\033[0m'
+BOLD = '\033[1m'
+UNDERLINE = '\033[4m'
+
+DEBUG = False
+DEPLOY = True
+
+if DEBUG:
+ PYPI_URL = 'https://test.pypi.org'
+else:
+ PYPI_URL = 'https://pypi.org'
+
+# Dictionary with the correspondence of the libraries and folders.
+PACKAGES = { 'pyforms-gui': 'pyforms_gui' }
+PACKAGES_TO_IGNORE = [
+ 'confapp'
+]
-pypi = xmlrpc.client.ServerProxy('https://pypi.org')
+PACKAGES_TO_IGNORE_FOR_REQUIREMENTS = [
+ 'confapp',
+ 'python-video-annotator-module-idtrackerai'
+]
-MAIN_NAME = 'pythonvideoannotator'
-MAIN_PATH = os.path.join('base', MAIN_NAME)
-MAIN_REPO = 'python-video-annotator'
+# sub packages directories to look for updates
DIRECTORIES_TO_SEARCH_FORM = [
os.path.join('libraries'),
os.path.join('base'),
os.path.join('plugins'),
]
-CURRENT_DIRECTORY = os.getcwd()
+MAIN_NAME = 'pythonvideoannotator' # main package name
+MAIN_PATH = os.path.join('base', MAIN_NAME) # main package path
+MAIN_REPO = 'python-video-annotator' # name of the main package on pypi
+APP_DIRECTORY = os.getcwd() # current directory
-Popen(['pip','install','--upgrade','setuptools','wheel','twine'])
+####################################################
+
+pypi = xmlrpc.client.ServerProxy(PYPI_URL)
+
+# make sure all the packages required to deploy to pypi are installed
+Popen(['pip','install','--upgrade','setuptools','wheel','twine']).communicate()
def version_compare(a, b):
- try:
- a = float(a)
- b = float(b)
- except:
- return -1
"""
- a = a.split('.')
- b = b.split('.')
- for a_value, b_value in zip(a, b):
- a_value = int(a_value)
- b_value = int(b_value)
-
- if a_value>b_value:
- return -1
- elif a_valuelen(b):
- return -1
- elif len(a)b, returns -1 if b>a
+ """
+ if a == b: return 0
+ versions = natsorted([a, b])
+ if a==versions[-1]: return -1
+ if b==versions[-1]: return 1
+ raise Exception('Error when comparing versions')
+
+
+
+def update_package_version(package_name, setup_path, new_version):
+ """
+ Update the version of the package
+
+ :param str package_name: Package name.
+ :param str setup_path: Path of the setup.py file.
+ :param str new_version: The new version to update.
+ :return:
"""
- if a==b: return 0
- if ab: return -1
+ if package_name in PACKAGES:
+ package = PACKAGES[package_name]
+ else:
+ packages = find_packages(where=setup_path)
+ package = packages[0]
+
+ package_path = os.path.join(setup_path, package)
+ init_path = os.path.join(package_path, '__init__.py')
+
+ with open(init_path) as infile: text = infile.read()
+ try:
+ begin = text.index('__version__')
+ end = text.index('\n', begin)
+ text = text.replace( text[begin:end], f'__version__ = "{new_version}"')
+ except ValueError:
+ text = text + f'\n__version__ = "{new_version}"'
+
+ with open(init_path, 'w') as outfile: outfile.write(text)
+
+
def check_version_and_upload(dir_path):
+ """
+ Check the package version and decide if should be updated or not.
+ :param str dir_path: Path of the package.
+ """
os.chdir(dir_path)
try:
@@ -67,42 +120,79 @@ def check_version_and_upload(dir_path):
except Exception as e:
print(e)
- version = Popen(["python", 'setup.py', '--version'], stdout=PIPE).stdout.read()
- version = version.strip().decode()
+ local_version = Popen(["python", 'setup.py', '--version'], stdout=PIPE).stdout.read()
+ local_version = local_version.strip().decode().strip()
package_name = Popen(["python", 'setup.py', '--name'], stdout=PIPE).stdout.read()
package_name = package_name.strip().decode().replace(' ', '-')
package_name = package_name.replace('---', '-').lower()
- remote_version = pypi.package_releases(package_name)
+ if package_name in PACKAGES_TO_IGNORE:
+ os.chdir(APP_DIRECTORY)
+ return False, package_name, local_version
- print(
- "{:<65} {:<10} {:<10}".format(package_name, version, remote_version[0])
- )
+ tmp = pypi.package_releases(package_name)
+ remote_version = tmp[0] if tmp else 'None'
+
+ tagged_version = Popen(["git", "describe", "--tags"], stdout=PIPE).stdout.read()
+ tagged_version = tagged_version.strip().decode().split('-')
+ tagged_version = tagged_version[0]
+
+ print(f"{OKGREEN}{package_name:<65} {local_version:<25} {tagged_version:<25} {remote_version:<25}{ENDC}")
+
+ #git_tag = Popen(["git", 'tag'], stdout=PIPE).stdout.read()
+ #if git_tag == f'v{new_version}':
+ # return
updated = False
- if len(remote_version) == 0 or version_compare(version, remote_version[0]) < 0:
- print('----- UPLOADING PYPI -----', package_name)
+ if remote_version=='None' or version_compare(tagged_version, remote_version) < 0:
+ print(OKBLUE+f'\tUPLOADING TO PYPI\t\t[{package_name}]', ENDC)
+
+ update_package_version(package_name, dir_path, tagged_version)
if os.path.isdir('./dist'): shutil.rmtree('./dist')
+
Popen(['python', 'setup.py', 'sdist', 'bdist_wheel'], stdout=PIPE).communicate()
- Popen(['twine', 'upload', os.path.join('dist','*')]).communicate()
+
+ ######################################################################################
+ # DEPLOY TO PYPI #####################################################################
+ ######################################################################################
+ if DEPLOY:
+ if not DEBUG:
+ Popen(['twine', 'upload', os.path.join('dist','*')]).communicate()
+ else:
+ Popen(['twine', 'upload', '--repository', 'pypitest', os.path.join('dist', '*'), '--verbose']).communicate()
+ ######################################################################################
+
+ """
+ remote_version = pypi.package_releases(package_name)
+ if version_compare(new_version, remote_version[0])==0:
+ Popen(['git', 'add', '--all']).communicate()
+ Popen(['git', 'commit', '-m', '"upload to pypi"']).communicate()
+ Popen(['git', 'tag', '-a', f'v{new_version}', '-m', 'generated with deploy-pypi.py script']).communicate()
+ """
updated = True
- os.chdir(CURRENT_DIRECTORY)
+ os.chdir(APP_DIRECTORY)
- return updated, package_name, version
+ remote_version = pypi.package_releases(package_name)
+ remote_version_str = remote_version[0] if remote_version else 'None'
+ return updated, package_name, tagged_version
-requirements = []
-should_update = False
+# List of requirements
+requirements = []
for search_dir in DIRECTORIES_TO_SEARCH_FORM:
+ print(
+ BOLD+HEADER+"\n{:<65} {:<25} {:<25} {:<25}".format('PACKAGE', 'LOCAL', 'TAGGED VERSION', 'REMOTE')+ENDC
+ )
+
for dir_name in os.listdir(search_dir):
- dir_path = os.path.abspath(os.path.join(search_dir, dir_name))
+ dir_path = os.path.abspath(os.path.join(search_dir, dir_name))
# is not a directory or is the main repository
if not os.path.isdir(dir_path) or MAIN_NAME==dir_name: continue
@@ -112,44 +202,22 @@ def check_version_and_upload(dir_path):
updated, package_name, version = check_version_and_upload(dir_path)
- if updated:
- should_update = True
-
- if package_name != MAIN_REPO:
+ if package_name != MAIN_REPO and package_name not in PACKAGES_TO_IGNORE_FOR_REQUIREMENTS:
requirements.append("{module}=={version}".format(module=package_name, version=version))
-with open( os.path.join(MAIN_PATH, 'setup.py') ) as infile:
- text = infile.read()
-
-begin = text.index('# REQUIREMENTS BEGIN')
-end = text.index('# REQUIREMENTS END', begin)+len('# REQUIREMENTS END')
+#### UPDATE REQUIREMENTS IN THE MAIN SETUP.PY ##################
+with open( os.path.join(MAIN_PATH, 'setup.py') ) as infile: text = infile.read()
+begin = text.index('# REQUIREMENTS BEGIN')
+end = text.index('# REQUIREMENTS END', begin)+len('# REQUIREMENTS END')
new_text = """# REQUIREMENTS BEGIN
REQUIREMENTS = [
"{}"
]
# REQUIREMENTS END""".format('",\n\t"'.join(requirements))
-
text = text.replace(text[begin:end], new_text)
+with open( os.path.join(MAIN_PATH, 'setup.py'), 'w' ) as outfile: outfile.write(text)
+#### END UPDATE REQUIREMENTS ###################################
-with open( os.path.join(MAIN_PATH, 'setup.py'), 'w' ) as outfile:
- outfile.write(text)
-
-with open( os.path.join(MAIN_PATH, MAIN_NAME, '__init__.py') ) as infile:
- text = infile.read()
-
-if should_update:
- os.chdir(MAIN_PATH)
- version = Popen(["python", 'setup.py', '--version'], stdout=PIPE).stdout.read()
- version = float(version.strip().decode())
- os.chdir(CURRENT_DIRECTORY)
-
- begin = text.index('__version__')
- end = text.index('\n', begin)
- text = text.replace(text[begin:end], '__version__ = "{0}"'.format(round(version + 0.001, 3)))
-
-with open( os.path.join(MAIN_PATH, MAIN_NAME, '__init__.py'), 'w' ) as outfile:
- outfile.write(text)
-
-
-updated, package_name, version = check_version_and_upload(MAIN_PATH)
\ No newline at end of file
+#### UPDATE THE MAIN PACKAGE ##################
+updated, package_name, version = check_version_and_upload(os.path.abspath(MAIN_PATH))
\ No newline at end of file
diff --git a/utils/install.py b/utils/install.py
index 5e9564b..cdaa52e 100644
--- a/utils/install.py
+++ b/utils/install.py
@@ -1,40 +1,40 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
-import pip, os
+import os
from subprocess import call
SUBMODULES_FOLDERS = [
- os.path.join('..', 'libraries', 'geometry-designer'),
- os.path.join('..', 'libraries', 'mcv-api'),
- os.path.join('..', 'libraries', 'mcv-gui'),
- os.path.join('..', 'libraries', 'mcv-gui-editor'),
- os.path.join('..', 'libraries', 'pyforms-gui'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-backgroundfinder'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-contoursimages'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-createpaths'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-distances'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-eventsstats'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-findorientation'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-importexport'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-motioncounter'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-patheditor'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-regionsfilter'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-smoothpaths'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-timeline'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-tracking'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-virtualobjectgenerator'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-pathmap'),
- os.path.join('..', 'plugins', 'pythonvideoannotator-module-deeplab'),
- os.path.join('..', 'base', 'pythonvideoannotator'),
- os.path.join('..', 'base', 'pythonvideoannotator-models'),
- os.path.join('..', 'base', 'pythonvideoannotator-models-gui'),
+ os.path.join('libraries', 'geometry-designer'),
+ os.path.join('libraries', 'mcv-api'),
+ os.path.join('libraries', 'mcv-gui'),
+ os.path.join('libraries', 'mcv-gui-editor'),
+ os.path.join('libraries', 'pyforms-gui'),
+ os.path.join('plugins', 'pythonvideoannotator-module-backgroundfinder'),
+ os.path.join('plugins', 'pythonvideoannotator-module-contoursimages'),
+ os.path.join('plugins', 'pythonvideoannotator-module-createpaths'),
+ os.path.join('plugins', 'pythonvideoannotator-module-distances'),
+ os.path.join('plugins', 'pythonvideoannotator-module-eventsstats'),
+ os.path.join('plugins', 'pythonvideoannotator-module-findorientation'),
+ os.path.join('plugins', 'pythonvideoannotator-module-importexport'),
+ os.path.join('plugins', 'pythonvideoannotator-module-motioncounter'),
+ os.path.join('plugins', 'pythonvideoannotator-module-patheditor'),
+ os.path.join('plugins', 'pythonvideoannotator-module-regionsfilter'),
+ os.path.join('plugins', 'pythonvideoannotator-module-smoothpaths'),
+ os.path.join('plugins', 'pythonvideoannotator-module-timeline'),
+ os.path.join('plugins', 'pythonvideoannotator-module-tracking'),
+ os.path.join('plugins', 'pythonvideoannotator-module-virtualobjectgenerator'),
+ os.path.join('plugins', 'pythonvideoannotator-module-pathmap'),
+ os.path.join('plugins', 'pythonvideoannotator-module-deeplab'),
+ os.path.join('base', 'pythonvideoannotator'),
+ os.path.join('base', 'pythonvideoannotator-models'),
+ os.path.join('base', 'pythonvideoannotator-models-gui'),
]
def install():
- for submodule in SUBVIDEOANNOTATOR_MODULES_FOLDERS:
+ for submodule in SUBMODULES_FOLDERS:
call(['pip', 'install', '-e', os.path.join(submodule,'.')])
if __name__=='__main__':