Skip to content

Commit

Permalink
Merge pull request #79 from LaboratoireMecaniqueLille/release/2.0.0
Browse files Browse the repository at this point in the history
Release of Crappy version 2.0.0
  • Loading branch information
WeisLeDocto authored Nov 28, 2023
2 parents 565fe7d + a225880 commit ecd7d70
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 56 deletions.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from time import gmtime, strftime
from re import match

__version__ = '2.0.0-rc.0'
__version__ = '2.0.0'

# -- Project information -----------------------------------------------------

Expand Down
24 changes: 8 additions & 16 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
extensions = []

# Now finding the extensions to install
install_camera_link = False
install_py_fgen = False
if platform.system() == "Linux":
# Find the latest runtime version of SiliconSoftware install
try:
Expand All @@ -38,16 +40,10 @@
"-l", "clsersis", "-l", "fglib5"],
include_dirs=[f'/usr/local/lib/python{py_ver}/dist-packages/numpy/'
f'core/include'])

p = popen("lsmod | grep menable")
if p.read():
if input("would you like to install CameraLink module? ([y]/n)") != "n":
print("menable kernel module found, installing CameraLink module.")
extensions.append(cl_module)
else:
print("menable kernel module found, but not installing")
else:
print("Cannot find menable kernel module, CameraLink module won't be "
"available.")
if p.read() and install_camera_link:
extensions.append(cl_module)

if platform.system() == "Windows":

Expand All @@ -61,7 +57,7 @@
library_dirs=["C:\\Program Files\\IVI Foundation\\IVI\\Lib_x64\\msc"],
extra_compile_args=["/EHsc", "/WX"])

if input("would you like to install pyFgen module? ([y]/n)") != "n":
if install_py_fgen:
extensions.append(py_fgen_module)

cl_path = "C:\\Program Files\\SiliconSoftware\\Runtime5.2.1\\"
Expand All @@ -76,11 +72,7 @@
extra_compile_args=["/EHsc", "/WX"])

p = popen('driverquery /NH | findstr "me4"')
if p.read():
if input("would you like to install CameraLink module? ([y]/n)") != "n":
extensions.append(cl_module)
else:
print("Can't find microEnable4 Device driver, clModule will not be "
"compiled")
if p.read() and install_camera_link:
extensions.append(cl_module)

setup(ext_package='crappy', ext_modules=extensions)
2 changes: 1 addition & 1 deletion src/crappy/__version__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# coding: utf-8

__version__ = '2.0.0-rc.0'
__version__ = '2.0.0'
61 changes: 61 additions & 0 deletions src/crappy/blocks/_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,67 @@
from .meta_block import Block


def recv_all(_):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method recv_all was deprecated in version "
"2.0.0, please use recv_all_data instead !")


def poll(_):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method poll was deprecated in version "
"2.0.0, please use data_available instead !")


def recv_all_last(_):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method recv_all_last was deprecated in "
"version 2.0.0, please use recv_last_data "
"instead !")


def get_last(_, *__, **___):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method get_last was deprecated in version "
"2.0.0, please use recv_last_data instead !")


def get_all_last(_, *__, **___):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method get_all_last was deprecated in "
"version 2.0.0, please use recv_all_data "
"instead !")


def recv_all_delay(_, *__, **___):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method recv_all_delay was deprecated in "
"version 2.0.0, please use recv_all_data_raw "
"instead !")


def drop(_, *__, **___):
"""Empty function for signaling a deprecated method of the Block object."""

raise NotImplementedError("The method drop was deprecated in version "
"2.0.0 !")


setattr(Block, recv_all.__name__, recv_all)
setattr(Block, poll.__name__, poll)
setattr(Block, recv_all_last.__name__, recv_all_last)
setattr(Block, get_last.__name__, get_last)
setattr(Block, get_all_last.__name__, get_all_last)
setattr(Block, recv_all_delay.__name__, recv_all_delay)
setattr(Block, drop.__name__, drop)


class AutoDrive(Block):
"""Empty class for signaling an object of version 1.5 whose name changed in
version 2.0 and is now deprecated.
Expand Down
27 changes: 16 additions & 11 deletions src/crappy/blocks/client_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
try:
import paho.mqtt.client as mqtt
except (ModuleNotFoundError, ImportError):
mqtt = OptionalModule("paho.mqtt.client")
mqtt = OptionalModule("paho-mqtt")

TopicsType = Iterable[Union[str, Iterable[str]]]

Expand Down Expand Up @@ -229,15 +229,8 @@ def __init__(self,
self._port = port
self._spam = spam
self._init_output = init_output if init_output is not None else dict()
self._reader = Thread(target=self._output_reader)

self._stop_mosquitto = False

# Instantiating the client
self._client = mqtt.Client(str(time()))
self._client.on_connect = self._on_connect
self._client.on_message = self._on_message
self._client.reconnect_delay_set(max_delay=10)

# These attributes may be set later
self._topics: Optional[List[Tuple[str, ...]]] = None
Expand All @@ -259,9 +252,6 @@ def __init__(self,
# The last out vals are given for each label, not each topic
self._last_out_val = {label: None for label in chain(*self._topics)}

# The buffer for received data is a dictionary of queues
self._buffer_output = {topic: Queue() for topic in self._topics}

# Preparing for publishing data
if cmd_labels is not None:
# Replacing strings with tuples
Expand Down Expand Up @@ -292,16 +282,31 @@ def prepare(self) -> None:
if self._cmd_labels is not None and not self.inputs:
raise ValueError("cmd_labels are specified but there's no input link !")

# Setting the buffer here because Queue objects cannot be set during
# __init__ in spawn multiprocessing mode
if self._topics is not None:
# The buffer for received data is a dictionary of queues
self._buffer_output = {topic: Queue() for topic in self._topics}

# Starting the broker
if self._broker:
self.log(logging.INFO, f"Starting the Mosquitto broker on port "
f"{self._port}")
self._launch_mosquitto()
# Creating and starting a Thread reading the stdout of the broker
self._reader = Thread(target=self._output_reader)
self._reader.start()
sleep(2)
self.log(logging.INFO, "Waiting for Mosquitto to start")
sleep(2)

# Instantiating the client here as it cannot be set during __init__ in
# spawn multiprocessing mode
self._client = mqtt.Client(str(time()))
self._client.on_connect = self._on_connect
self._client.on_message = self._on_message
self._client.reconnect_delay_set(max_delay=10)

# Connecting to the broker
try_count = 15
while True:
Expand Down
2 changes: 1 addition & 1 deletion src/crappy/blocks/pid.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def loop(self) -> None:
# Calculating the three PID terms
p_term = self._kp * error
self._i_term += self._ki * error * delta_t
d_term = - self._kd * d_input / delta_t
d_term = - self._kd * d_input / delta_t if delta_t > 0 else 0

self._prev_t = t
self._last_input = input_
Expand Down
11 changes: 9 additions & 2 deletions src/crappy/blocks/stop_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,15 @@ def __init__(self,
criteria = (criteria,)
criteria = tuple(criteria)

# Ultimately, all the criteria are converted to Callables
self._criteria = tuple(map(self._parse_criterion, criteria))
self._raw_crit = criteria
self._criteria = None

def prepare(self) -> None:
"""Converts all the given criteria to :ref:`collections.abc.Callable`."""

# This operation cannot be performed during __init__ due to limitations of
# the spawn start method of multiprocessing
self._criteria = tuple(map(self._parse_criterion, self._raw_crit))

def loop(self) -> None:
"""Receives data from upstream Blocks, checks if this data meets the
Expand Down
2 changes: 1 addition & 1 deletion src/crappy/camera/gstreamer_camera_v4l2.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def open(self,
else:
self.log(logging.ERROR, f'The type {param.type} is not yet'
f' implemented. Only int, bool and menu '
f'type are implemented. ')
f'type are implemented.')
raise NotImplementedError

# No need to add the channels setting if there's only one channel
Expand Down
2 changes: 2 additions & 0 deletions src/crappy/modifier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@
from .trig_on_change import TrigOnChange
from .trig_on_value import TrigOnValue

from ._deprecated import Moving_avg, Moving_med, Trig_on_change, Trig_on_value

modifier_dict: Dict[str, Type[Modifier]] = MetaModifier.classes
71 changes: 71 additions & 0 deletions src/crappy/modifier/_deprecated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# coding: utf-8

from .meta_modifier import Modifier


class Moving_avg(Modifier):
"""Empty class for signaling an object of version 1.5 whose name changed in
version 2.0 and is now deprecated.
The new name of the correct object to use is given.
"""

def __init__(self, *_, **__) -> None:
"""Simply raises the exception when instantiating the object."""

super().__init__()

raise NotImplementedError(f"The {type(self).__name__} Modifier was "
f"renamed to MovingAvg in version 2.0.0 ! "
f"Check the documentation for more information.")


class Moving_med(Modifier):
"""Empty class for signaling an object of version 1.5 whose name changed in
version 2.0 and is now deprecated.
The new name of the correct object to use is given.
"""

def __init__(self, *_, **__) -> None:
"""Simply raises the exception when instantiating the object."""

super().__init__()

raise NotImplementedError(f"The {type(self).__name__} Modifier was "
f"renamed to MovingMed in version 2.0.0 ! "
f"Check the documentation for more information.")


class Trig_on_change(Modifier):
"""Empty class for signaling an object of version 1.5 whose name changed in
version 2.0 and is now deprecated.
The new name of the correct object to use is given.
"""

def __init__(self, *_, **__) -> None:
"""Simply raises the exception when instantiating the object."""

super().__init__()

raise NotImplementedError(f"The {type(self).__name__} Modifier was "
f"renamed to TrigOnChange in version 2.0.0 ! "
f"Check the documentation for more information.")


class Trig_on_value(Modifier):
"""Empty class for signaling an object of version 1.5 whose name changed in
version 2.0 and is now deprecated.
The new name of the correct object to use is given.
"""

def __init__(self, *_, **__) -> None:
"""Simply raises the exception when instantiating the object."""

super().__init__()

raise NotImplementedError(f"The {type(self).__name__} Modifier was "
f"renamed to TrigOnValue in version 2.0.0 ! "
f"Check the documentation for more information.")
24 changes: 12 additions & 12 deletions src/crappy/tool/camera_config/camera_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from pkg_resources import resource_string
from io import BytesIO
import logging
from multiprocessing import current_process, Event, Pipe
from multiprocessing.queues import Queue
from multiprocessing import current_process, Event, Queue
from multiprocessing.queues import Queue as MPQueue

from .config_tools import Zoom, HistogramProcess
from ...camera.meta_camera.camera_setting import CameraBoolSetting, \
Expand Down Expand Up @@ -58,7 +58,7 @@ class CameraConfig(tk.Tk):

def __init__(self,
camera: Camera,
log_queue: Queue,
log_queue: MPQueue,
log_level: Optional[int],
max_freq: Optional[float]) -> None:
"""Initializes the interface and displays it.
Expand Down Expand Up @@ -86,11 +86,11 @@ def __init__(self,
# Instantiating objects for the process managing the histogram calculation
self._stop_event = Event()
self._processing_event = Event()
self._img_in, img_in_proc = Pipe()
img_out_proc, self._img_out = Pipe()
self._img_in = Queue(maxsize=0)
self._img_out = Queue(maxsize=0)
self._histogram_process = HistogramProcess(
stop_event=self._stop_event, processing_event=self._processing_event,
img_in=img_in_proc, img_out=img_out_proc, log_level=log_level,
img_in=self._img_in, img_out=self._img_out, log_level=log_level,
log_queue=log_queue)

# Attributes containing the several images and histograms
Expand Down Expand Up @@ -142,8 +142,8 @@ def main(self) -> None:

while self._run:
# Remaining below the max allowed frequency
if self._max_freq is None or \
self._n_loops / (time() - start_time) < self._max_freq:
if self._max_freq is None or (self._n_loops <
self._max_freq * (time() - start_time)):
# Update the image, the histogram and the information
self._update_img()

Expand Down Expand Up @@ -967,12 +967,12 @@ def _calc_hist(self) -> None:

# Sending the image to the histogram process
self.log(logging.DEBUG, "Sending image for histogram calculation")
self._img_in.send((hist_img, self._auto_range.get(),
self._low_thresh, self._high_thresh))
self._img_in.put_nowait((hist_img, self._auto_range.get(),
self._low_thresh, self._high_thresh))

# Checking if a histogram is available for display
while self._img_out.poll():
self._hist = self._img_out.recv()
while not self._img_out.empty():
self._hist = self._img_out.get_nowait()
self.log(logging.DEBUG, "Received histogram from histogram process")

def _resize_hist(self) -> None:
Expand Down
Loading

0 comments on commit ecd7d70

Please sign in to comment.