Improved flake8 results
This commit is contained in:
parent
fb606b189d
commit
3b9ef670fe
24 changed files with 256 additions and 126 deletions
|
|
@ -1 +1,3 @@
|
|||
__all__ = ['pi', 'base']
|
||||
|
||||
from . import pi, base
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import time
|
|||
import os
|
||||
import threading
|
||||
import datetime
|
||||
import yaml
|
||||
import logging
|
||||
|
||||
try:
|
||||
|
|
@ -15,7 +14,6 @@ except ImportError:
|
|||
from _thread import get_ident
|
||||
|
||||
from .capture import CaptureObject, BASE_CAPTURE_PATH, TEMP_CAPTURE_PATH
|
||||
from openflexure_microscope.config import USER_CONFIG_DIR
|
||||
from openflexure_microscope.utilities import entry_by_id
|
||||
from openflexure_microscope.lock import StrictLock
|
||||
|
||||
|
|
@ -54,7 +52,7 @@ class CameraEvent(object):
|
|||
def __init__(self):
|
||||
self.events = {}
|
||||
|
||||
def wait(self, timeout: int=5):
|
||||
def wait(self, timeout: int = 5):
|
||||
"""Wait for the next frame (invoked from each client's thread)."""
|
||||
ident = get_ident()
|
||||
if ident not in self.events:
|
||||
|
|
@ -92,32 +90,42 @@ class CameraEvent(object):
|
|||
class BaseCamera(object):
|
||||
"""
|
||||
Base implementation of StreamingCamera.
|
||||
|
||||
Attributes:
|
||||
thread: Background thread reading frames from camera
|
||||
camera: Camera object
|
||||
lock (:py:class:`openflexure_microscope.lock.StrictLock`): Strict lock controlling thread
|
||||
access to stage hardware
|
||||
frame (bytes): Current frame is stored here by background thread
|
||||
last_access (time): Time of last client access to the camera
|
||||
state (dict): Dictionary for capture state
|
||||
config (dict): Dictionary of base camera config
|
||||
paths (dict): Dictionary of capture paths
|
||||
images (list): List of image capture objects
|
||||
videos (list): List of video capture objects
|
||||
"""
|
||||
def __init__(self):
|
||||
self.thread = None #: Background thread reading frames from camera
|
||||
self.camera = None #: Camera object
|
||||
self.thread = None
|
||||
self.camera = None
|
||||
|
||||
self.lock = StrictLock(timeout=1) #: :py:class:`openflexure_microscope.lock.StrictLock`: Strict lock controlling thread access to camera hardware
|
||||
self.lock = StrictLock(timeout=1)
|
||||
|
||||
self.frame = None #: bytes: Current frame is stored here by background thread
|
||||
self.last_access = 0 #: time: Time of last client access to the camera
|
||||
self.frame = None
|
||||
self.last_access = 0
|
||||
self.event = CameraEvent()
|
||||
|
||||
self.stream_timeout = 20 #: int: Number of inactive seconds before timing out the stream
|
||||
self.stream_timeout_enabled = False #: bool: Enable or disable timing out the stream
|
||||
|
||||
self.state = {} #: dict: Dictionary for capture state
|
||||
self.config = {} #: dict: Dictionary of base camera config
|
||||
self.state = {}
|
||||
self.config = {}
|
||||
self.paths = {
|
||||
'image': BASE_CAPTURE_PATH,
|
||||
'video': BASE_CAPTURE_PATH,
|
||||
'image_tmp': TEMP_CAPTURE_PATH,
|
||||
'video_tpm': TEMP_CAPTURE_PATH
|
||||
} #: dict: Dictionary of capture paths
|
||||
}
|
||||
|
||||
# Capture data
|
||||
self.images = [] #: list: List of image capture objects
|
||||
self.videos = [] #: list: List of video recording objects
|
||||
self.images = []
|
||||
self.videos = []
|
||||
|
||||
def apply_config(self, config):
|
||||
"""Update settings from a config dictionary"""
|
||||
|
|
@ -164,7 +172,6 @@ class BaseCamera(object):
|
|||
self.last_access = time.time()
|
||||
self.stop = False
|
||||
|
||||
#if self.thread is None:
|
||||
if not self.state['stream_active']:
|
||||
# start background frame thread
|
||||
self.thread = threading.Thread(target=self._thread)
|
||||
|
|
@ -185,13 +192,11 @@ class BaseCamera(object):
|
|||
logging.debug("Stopping worker thread")
|
||||
timeout_time = time.time() + timeout
|
||||
|
||||
#if self.thread:
|
||||
if self.state['stream_active']:
|
||||
self.stop = True
|
||||
self.thread.join() # Wait for stream thread to exit
|
||||
logging.debug("Waiting for stream thread to exit.")
|
||||
|
||||
#while self.thread:
|
||||
while self.state['stream_active']:
|
||||
if time.time() > timeout_time:
|
||||
logging.debug("Timeout waiting for worker thread close.")
|
||||
|
|
@ -255,7 +260,8 @@ class BaseCamera(object):
|
|||
|
||||
Args:
|
||||
write_to_file (bool): Should the StreamObject write to a file, or an in-memory byte stream.
|
||||
temporary (bool): Should the data be deleted after session ends. Creating the capture with a content manager sets this to true.
|
||||
temporary (bool): Should the data be deleted after session ends.
|
||||
Creating the capture with a content manager sets this to true.
|
||||
filename (str): Name of the stored file. Defaults to timestamp.
|
||||
fmt (str): Format of the capture.
|
||||
"""
|
||||
|
|
@ -298,7 +304,8 @@ class BaseCamera(object):
|
|||
|
||||
Args:
|
||||
write_to_file (bool): Should the StreamObject write to a file, or an in-memory byte stream.
|
||||
temporary (bool): Should the data be deleted after session ends. Creating the capture with a content manager sets this to true.
|
||||
temporary (bool): Should the data be deleted after session ends.
|
||||
Creating the capture with a content manager sets this to true.
|
||||
filename (str): Name of the stored file. Defaults to timestamp.
|
||||
fmt (str): Format of the capture.
|
||||
"""
|
||||
|
|
@ -363,6 +370,3 @@ class BaseCamera(object):
|
|||
logging.debug("BaseCamera worker thread exiting...")
|
||||
# Set stream_activate state
|
||||
self.state['stream_active'] = False
|
||||
# Reset thread
|
||||
#self.thread = None
|
||||
logging.debug("Stream thread is None")
|
||||
|
|
|
|||
|
|
@ -11,12 +11,18 @@ import atexit
|
|||
|
||||
from openflexure_microscope.camera import piexif
|
||||
|
||||
"""
|
||||
Attributes:
|
||||
BASE_CAPTURE_PATH (str): Base path to store all captures
|
||||
TEMP_CAPTURE_PATH (str): Base path to store all temporary captures (automatically emptied)
|
||||
"""
|
||||
|
||||
PIL_FORMATS = ['JPG', 'JPEG', 'PNG', 'TIF', 'TIFF']
|
||||
EXIF_FORMATS = ['JPG', 'JPEG', 'TIF', 'TIFF']
|
||||
THUMBNAIL_SIZE = (200, 150)
|
||||
|
||||
BASE_CAPTURE_PATH = os.path.join(os.path.expanduser('~'), 'micrographs') #: str: Base path to store all captures
|
||||
TEMP_CAPTURE_PATH = os.path.join(BASE_CAPTURE_PATH, 'tmp') #: str: Base path to store all temporary captures (automatically emptied)
|
||||
BASE_CAPTURE_PATH = os.path.join(os.path.expanduser('~'), 'micrographs')
|
||||
TEMP_CAPTURE_PATH = os.path.join(BASE_CAPTURE_PATH, 'tmp')
|
||||
|
||||
|
||||
# TODO: Move these methods to a camera utilities module?
|
||||
|
|
@ -107,7 +113,20 @@ class CaptureObject(object):
|
|||
"""
|
||||
StreamObject used to store and process capture data, and metadata.
|
||||
|
||||
Note: Captures cannot be stored in a lower-level directory than BASE_CAPTURE_PATH.
|
||||
Attributes:
|
||||
timestring (str): Timestring of capture creation time
|
||||
temporary (bool): Mark the capture as temporary, to be deleted as the server closes,
|
||||
or as resources are required
|
||||
_metadata (dict): Dictionary of custom metadata to be included in metadata file
|
||||
tags (list): List of tags. Essentially just as extra custom metadata field, but useful for quick organisation
|
||||
bytestream (:py:class:`io.BytesIO`): Byte bytestream that data will be written to
|
||||
filefolder (str): Folder in which the capture file will be stored
|
||||
filename (str): Full name of the capture file
|
||||
basename (str): Filename of the capture, without a file extension
|
||||
format (str): Format of the capture data
|
||||
|
||||
Notes:
|
||||
Captures cannot be stored in a lower-level directory than BASE_CAPTURE_PATH.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
|
@ -120,10 +139,10 @@ class CaptureObject(object):
|
|||
# Store a nice ID
|
||||
self.id = uuid.uuid4().hex #: str: Unique capture ID
|
||||
logging.debug("Created StreamObject {}".format(self.id))
|
||||
self.timestring = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") #: str: Timestring of capture creation time
|
||||
self.timestring = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
# Keep on disk after close by default
|
||||
self.temporary = temporary #: bool: Mark the capture as temporary, to be deleted as the server closes, or as resources are required
|
||||
self.temporary = temporary
|
||||
|
||||
# Create file name. Default to UUID
|
||||
if not filepath:
|
||||
|
|
@ -133,13 +152,13 @@ class CaptureObject(object):
|
|||
self.split_file_path(self.file)
|
||||
|
||||
# Dictionary for storing custom metadata
|
||||
self._metadata = {} #: dict: Dictionary of custom metadata to be included in metadata file
|
||||
self._metadata = {}
|
||||
|
||||
# List for storing tags
|
||||
self.tags = [] #: list: List of tags. Essentially just as extra custom metadata field, but useful for quick organisation
|
||||
self.tags = []
|
||||
|
||||
# Byte bytestream properties
|
||||
self.bytestream = io.BytesIO() # Byte bytestream that data will be written to
|
||||
self.bytestream = io.BytesIO()
|
||||
|
||||
# Set default write target
|
||||
if not write_to_file:
|
||||
|
|
@ -182,12 +201,14 @@ class CaptureObject(object):
|
|||
def split_file_path(self, filepath):
|
||||
"""
|
||||
Take a full file path, and split it into separated class properties.
|
||||
|
||||
|
||||
Args:
|
||||
filepath (str): String of the full file path, including file format extension
|
||||
"""
|
||||
self.filefolder, self.filename = os.path.split(filepath) # Split the full file path into a folder and a filename
|
||||
self.basename = os.path.splitext(self.filename)[0] # Split the filename out from it's file extension
|
||||
# Split the full file path into a folder and a filename
|
||||
self.filefolder, self.filename = os.path.split(filepath)
|
||||
# Split the filename out from it's file extension
|
||||
self.basename = os.path.splitext(self.filename)[0]
|
||||
self.format = self.filename.split('.')[-1]
|
||||
|
||||
# Create folder and file
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ class StreamingCamera(BaseCamera):
|
|||
logging.info("Starting the GPU preview")
|
||||
|
||||
# TODO: Commented out as I honestly can't remember why this was here. May need to put back?
|
||||
#self.start_stream_recording()
|
||||
# self.start_stream_recording()
|
||||
|
||||
try:
|
||||
if not self.camera.preview:
|
||||
|
|
@ -365,7 +365,8 @@ class StreamingCamera(BaseCamera):
|
|||
|
||||
Args:
|
||||
splitter_port (int): Splitter port to start recording on
|
||||
resolution ((int, int)): Resolution to set the camera to, before starting recording. Defaults to `self.config['stream_resolution']`.
|
||||
resolution ((int, int)): Resolution to set the camera to, before starting recording.
|
||||
Defaults to `self.config['stream_resolution']`.
|
||||
"""
|
||||
with self.lock:
|
||||
# If stream object was destroyed
|
||||
|
|
@ -392,7 +393,7 @@ class StreamingCamera(BaseCamera):
|
|||
self.stream,
|
||||
format='mjpeg',
|
||||
quality=self.config['jpeg_quality'],
|
||||
bitrate=-1, # RWB: disable bitrate control
|
||||
bitrate=-1, # RWB: disable bitrate control
|
||||
# (bitrate control makes JPEG size less good as a focus
|
||||
# metric)
|
||||
splitter_port=splitter_port)
|
||||
|
|
|
|||
|
|
@ -19,11 +19,16 @@ def set_gain(camera, gain, value):
|
|||
"""
|
||||
if gain not in [MMAL_PARAMETER_ANALOG_GAIN, MMAL_PARAMETER_DIGITAL_GAIN]:
|
||||
raise ValueError("The gain parameter was not valid")
|
||||
ret = mmal.mmal_port_parameter_set_rational(camera._camera.control._port,
|
||||
gain,
|
||||
to_rational(value))
|
||||
ret = mmal.mmal_port_parameter_set_rational(
|
||||
camera._camera.control._port,
|
||||
gain,
|
||||
to_rational(value)
|
||||
)
|
||||
if ret == 4:
|
||||
raise exc.PiCameraMMALError(ret, "Are you running the latest version of the userland libraries? Gain setting was introduced in late 2017.")
|
||||
raise exc.PiCameraMMALError(
|
||||
ret,
|
||||
"Are you running the latest version of the userland libraries? Gain setting was introduced in late 2017."
|
||||
)
|
||||
elif ret != 0:
|
||||
raise exc.PiCameraMMALError(ret)
|
||||
|
||||
|
|
@ -40,7 +45,7 @@ def set_digital_gain(camera, value):
|
|||
|
||||
if __name__ == "__main__":
|
||||
with picamera.PiCamera() as cam:
|
||||
cam.start_preview(fullscreen=False, window=(0,50,640,480))
|
||||
cam.start_preview(fullscreen=False, window=(0, 50, 640, 480))
|
||||
time.sleep(2)
|
||||
|
||||
# fix the auto white balance gains at their current values
|
||||
|
|
@ -58,10 +63,10 @@ if __name__ == "__main__":
|
|||
logging.info("Attempting to set digital gain to 1")
|
||||
set_digital_gain(cam, 1)
|
||||
# The old code is left in here in case it is a useful example...
|
||||
#ret = mmal.mmal_port_parameter_set_rational(cam._camera.control._port,
|
||||
# ret = mmal.mmal_port_parameter_set_rational(cam._camera.control._port,
|
||||
# MMAL_PARAMETER_DIGITAL_GAIN,
|
||||
# to_rational(1))
|
||||
#print("Return code: {}".format(ret))
|
||||
# print("Return code: {}".format(ret))
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
|
@ -69,5 +74,3 @@ if __name__ == "__main__":
|
|||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
logging.info("Stopping...")
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue