Skip to content

Commit

Permalink
Merge pull request #99 from yupidevs/develop
Browse files Browse the repository at this point in the history
Remove PyQt5 dependency and minor improvements
  • Loading branch information
jmorgadov authored Apr 17, 2022
2 parents 8fbd0f7 + 531cceb commit 372ac89
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 62 deletions.
86 changes: 86 additions & 0 deletions docs/source/GS/FAQ.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
Frequently Asked Questions
==========================

1. Why are plots not showing up? (Qt core dumped error)
-------------------------------------------------------

If you get an error similar to this::

QObject::moveToThread: Current thread (0x5632706342d0) is not the object's thread (0x5632
706194c0).
Cannot move to target thread (0x5632706342d0)
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/USERNAME/.local/lib/p
ython/site-packages/cv2/qt/plugins" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Rein
stalling the application may fix this problem.
Available platform plugins are: xcb, eglfs, linuxfb, minimal, minimalegl, offscreen, vnc,
wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl.
[1] 1498499 IOT instruction (core dumped) python example.py

it's proably because you have **PyQt5** and **opencv-python** packages
installed in the same python enviroment. This is due to a known incompatibility
between **PyQt5** and **opencv-python** in Linux systems.

Solutions
+++++++++

Removing **PyQt5**
******************

If you don't need **PyQt5** in the current enviroment (globally by default) you
can remove it by simply running:

.. code-block:: bash
$ pip uninstall PyQt5
Runing **yupi** in a separated virtual enviroment
*************************************************

If you don't want to remove **PyQt5** globally, you can create a separated
enviroment with **yupi**. This can be achieved in an easy way by using the
`venv` tool provided by python. You can visit `here
<https://docs.python.org/3/library/venv.html#module-venv>`_ the section
dedicated to this tool in the Python Docs which contains a guide for the
enviroment creation and activation.

Once the enviroment is created and activated you can install **yupi** (and all
the dependencies you might need) using the `pip` command.

.. code-block:: bash
$ pip install yupi
.. note::

The last solutions assume that **PyQt5** is not required for your project.
If **PyQt5** is one of your project dependencies the next solution shows
a way to use it along with **yupi**.

Install opencv from a linux repository
**************************************

If **PyQt5** is also needed along with **yupi** a known solution is to install
**opencv** from a linux repository. First you need to remove the current
**opencv** instalation with `pip`:

.. code-block:: bash
$ pip uninstall opencv-python
Then install **opencv** from a linux repository using your current package
manager. For example, if you are using `apt` (for Debian/Ubuntu based systems)
you can install it by running:

.. code-block:: bash
$ sudo apt install python3-opencv
.. note::

The name of the package may vary. For example, in Arch repositories
it is called **python-opencv**.

2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
author = 'Gustavo Viera-López, Alfredo Reyes, Jorge Morgado, Ernesto Altshuler'

# The full version, including alpha/beta/rc tags
release = '0.9.1'
release = '0.9.2'


# -- General configuration ---------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Standing for Yet Underused Path Instruments, **yupi** is a set of tools designed
Getting Support <GS/Support>
GS/Contributing
GS/About
GS/FAQ

.. toctree::
:maxdepth: 2
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "yupi"
version = "0.9.1"
version = "0.9.2"
description = "A package for tracking and analysing objects trajectories"
authors = [
"Gustavo Viera-López <gvieralopez@gmail.com>",
Expand All @@ -17,7 +17,6 @@ opencv-python = ">=4.4.0"
numpy = ">=1.16.5"
nudged = ">=0.3.1"
matplotlib = ">=3.2.0"
PyQt5 = "^5.15.3"

[tool.poetry.dev-dependencies]
pytest = "^6.2.2"
Expand Down
2 changes: 1 addition & 1 deletion yupi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@
'WindowType',
]

__version__ = '0.9.1'
__version__ = '0.9.2'
152 changes: 99 additions & 53 deletions yupi/graphics/_trajs_plots.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import itertools
import logging
import matplotlib.pyplot as plt
from typing import List, Union
from typing import List, Union, Optional
from yupi import Trajectory
from yupi.graphics._style import YUPI_COLORS, LINE



def plot_2D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
title: str = None, legend: bool = True, show: bool = True,
connected: bool = False, units: str = 'm', color = None, **kwargs):
def plot_2D(
trajs: Union[List[Trajectory], Trajectory],
line_style: str = LINE,
title: Optional[str] = None,
legend: bool = True,
show: bool = True,
connected: bool = False,
units: str = "m",
color=None,
**kwargs,
):
"""
Plot all the points of trajectories from ``trajs`` in a 2D plane.
Expand Down Expand Up @@ -47,14 +54,14 @@ def plot_2D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
if isinstance(trajs, Trajectory):
trajs = [trajs]

units = '' if units is None else f' [{units}]'
units = "" if units is None else f" [{units}]"

cycle = itertools.cycle(YUPI_COLORS)
colors = [cycle.__next__() for _ in trajs]

if color is not None:
if isinstance(color, (str, tuple)):
kwargs['color'] = color
kwargs["color"] = color
elif isinstance(color, list):
colors = color

Expand All @@ -63,7 +70,7 @@ def plot_2D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
min_len = min(lengths)
max_len = max(lengths)
if min_len != max_len:
logging.warning('Not all the trajectories have the same length.')
logging.warning("Not all the trajectories have the same length.")
for i in range(min_len):
traj_points = [t[i] for t in trajs]
traj_points.append(traj_points[0])
Expand All @@ -72,46 +79,69 @@ def plot_2D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
ys = [tp1.r[1], tp2.r[1]]
plt.plot(xs, ys, color=(0.2, 0.2, 0.2), linewidth=0.5)

for i, t in enumerate(trajs):
for i, traj in enumerate(trajs):

if t.dim != 2:
logging.warning(f'Using plot_2D with a trajectory of {t.dim} '
f' dimensions. Trajectory No. {i} with id'
f' {t.traj_id})')
if traj.dim != 2:
logging.warning(
f"Using plot_2D with a trajectory of {traj.dim} "
f" dimensions. Trajectory No. {i} with id"
f" {traj.traj_id})"
)

# Plotting
x, y = t.r.x, t.r.y
x, y = traj.r.x, traj.r.y
if colors is not None:
if i < len(colors):
kwargs['color'] = colors[i]
kwargs["color"] = colors[i]
else:
kwargs.pop('color')
kwargs.pop("color")
traj_plot = plt.plot(x, y, line_style, **kwargs)
color = traj_plot[-1].get_color()
plt.plot(x[0], y[0], 'o', mfc='white', zorder=2,
label=f'{t.traj_id} initial position', color=color)
plt.plot(x[-1], y[-1], 'o', mfc='white', zorder=2, color=color)
plt.plot(x[-1], y[-1], 'o', alpha=.5,
label=f'{t.traj_id} final position', color=color)
traj_id = traj.traj_id if traj.traj_id is not None else f"traj {i}"
plt.plot(
x[0],
y[0],
"o",
mfc="white",
zorder=2,
label=f"{traj_id} initial position",
color=color,
)
plt.plot(x[-1], y[-1], "o", mfc="white", zorder=2, color=color)
plt.plot(
x[-1],
y[-1],
"o",
alpha=0.5,
label=f"{traj_id} final position",
color=color,
)

if legend:
plt.legend()

plt.title(title)
plt.tick_params(direction='in')
plt.axis('equal')
plt.tick_params(direction="in")
plt.axis("equal")
plt.grid(True)
plt.xlabel(f'x{units}')
plt.ylabel(f'y{units}')
plt.xlabel(f"x{units}")
plt.ylabel(f"y{units}")

if show:
plt.show()



def plot_3D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
title: str = None, legend: bool = True, show: bool = True,
connected: bool = False, units: str = 'm', color = None, **kwargs):
def plot_3D(
trajs: Union[List[Trajectory], Trajectory],
line_style: str = LINE,
title: Optional[str] = None,
legend: bool = True,
show: bool = True,
connected: bool = False,
units: str = "m",
color=None,
**kwargs,
):
"""
Plot all the points of trajectories from ``trajs`` in a 3D space.
Expand Down Expand Up @@ -149,26 +179,25 @@ def plot_3D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
if isinstance(trajs, Trajectory):
trajs = [trajs]

units = '' if units is None else f' [{units}]'
units = "" if units is None else f" [{units}]"

cycle = itertools.cycle(YUPI_COLORS)
colors = [cycle.__next__() for _ in trajs]

if color is not None:
if isinstance(color, (str, tuple)):
kwargs['color'] = color
kwargs["color"] = color
elif isinstance(color, list):
colors = color


ax = plt.axes(projection='3d')
ax = plt.axes(projection="3d")

if connected:
lengths = list(map(len, trajs))
min_len = min(lengths)
max_len = max(lengths)
if min_len != max_len:
logging.warning('Not all the trajectories have the same length.')
logging.warning("Not all the trajectories have the same length.")
for i in range(min_len):
traj_points = [t[i] for t in trajs]
traj_points.append(traj_points[0])
Expand All @@ -178,40 +207,57 @@ def plot_3D(trajs: Union[List[Trajectory], Trajectory], line_style: str = LINE,
zs = [tp1.r[2], tp2.r[2]]
ax.plot(xs, ys, zs, color=(0.2, 0.2, 0.2), linewidth=0.5)

for i, t in enumerate(trajs):
for i, traj in enumerate(trajs):

if t.dim != 3:
logging.warning(f'Using plot_3D with a trajectory of {t.dim} '
f' dimensions. Trajectory No. {i} with id'
f' {t.traj_id})')
if traj.dim != 3:
logging.warning(
f"Using plot_3D with a trajectory of {traj.dim} "
f" dimensions. Trajectory No. {i} with id"
f" {traj.traj_id})"
)

# Plotting
x, y, z = t.r.x, t.r.y, t.r.z
x, y, z = traj.r.x, traj.r.y, traj.r.z

if colors is not None:
if i < len(colors):
kwargs['color'] = colors[i]
kwargs["color"] = colors[i]
else:
kwargs.pop('color')
kwargs.pop("color")
traj_plot = ax.plot(x, y, z, line_style, **kwargs)
color = traj_plot[-1].get_color()

ax.plot(x[0], y[0], z[0], 'o', mfc='white',
label=f'{t.traj_id} initial position', color=color)

ax.plot(x[-1], y[-1], z[-1], 'o', mfc='white', color=color)
ax.plot(x[-1], y[-1], z[-1], 'o', alpha=.5,
label=f'{t.traj_id} final position', color=color)
traj_id = traj.traj_id if traj.traj_id is not None else f"traj {i}"

ax.plot(
x[0],
y[0],
z[0],
"o",
mfc="white",
label=f"{traj_id} initial position",
color=color,
)

ax.plot(x[-1], y[-1], z[-1], "o", mfc="white", color=color)
ax.plot(
x[-1],
y[-1],
z[-1],
"o",
alpha=0.5,
label=f"{traj_id} final position",
color=color,
)

if legend:
plt.legend()

plt.title(title)
plt.tick_params(direction='in')
plt.tick_params(direction="in")
plt.grid(True)
ax.set_xlabel(f'x{units}')
ax.set_ylabel(f'y{units}')
ax.set_zlabel(f'z{units}')
ax.set_xlabel(f"x{units}")
ax.set_ylabel(f"y{units}")
ax.set_zlabel(f"z{units}")

if show:
plt.show()
Loading

0 comments on commit 372ac89

Please sign in to comment.