Improved flake8 results

This commit is contained in:
Joel Collins 2019-05-24 16:32:20 +01:00
parent fb606b189d
commit 3b9ef670fe
24 changed files with 256 additions and 126 deletions

View file

@ -1 +1,3 @@
__all__ = ['pi', 'base']
from . import pi, base

View file

@ -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")

View file

@ -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

View 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)

View file

@ -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...")