Reimplemented serialising LST

This commit is contained in:
Joel Collins 2020-02-06 13:35:05 +00:00
parent ccd5e9b891
commit cf66359559
5 changed files with 48 additions and 67 deletions

View file

@ -146,10 +146,6 @@ class BaseCamera(metaclass=ABCMeta):
"""Return the current settings as a dictionary""" """Return the current settings as a dictionary"""
return {"paths": self.paths} return {"paths": self.paths}
def save_settings(self):
"""(Optional) Save any settings to disk that need to be stored"""
return
def __enter__(self): def __enter__(self):
"""Create camera on context enter.""" """Create camera on context enter."""
return self return self

View file

@ -47,7 +47,11 @@ from .base import BaseCamera, CaptureObject
from .set_picamera_gain import set_analog_gain, set_digital_gain from .set_picamera_gain import set_analog_gain, set_digital_gain
from openflexure_microscope.paths import settings_file_path from openflexure_microscope.paths import settings_file_path
from openflexure_microscope.utilities import serialise_array_b64 from openflexure_microscope.utilities import (
serialise_array_b64,
ndarray_to_json,
json_to_ndarray,
)
# MAIN CLASS # MAIN CLASS
@ -154,9 +158,6 @@ class PiCameraStreamer(BaseCamera):
"image_resolution": self.image_resolution, "image_resolution": self.image_resolution,
"numpy_resolution": self.numpy_resolution, "numpy_resolution": self.numpy_resolution,
"jpeg_quality": self.jpeg_quality, "jpeg_quality": self.jpeg_quality,
"picamera_lst_path": self.picamera_lst_path
if (self.picamera_lst_path and os.path.isfile(self.picamera_lst_path))
else None,
"picamera": {}, "picamera": {},
} }
) )
@ -170,12 +171,16 @@ class PiCameraStreamer(BaseCamera):
except AttributeError: except AttributeError:
logging.debug("Unable to read PiCamera attribute {}".format(key)) logging.debug("Unable to read PiCamera attribute {}".format(key))
return conf_dict # Include a serialised lens shading table
if (
hasattr(self.camera, "lens_shading_table")
and getattr(self.camera, "lens_shading_table") is not None
):
conf_dict["picamera"]["lens_shading_table"] = ndarray_to_json(
getattr(self.camera, "lens_shading_table")
)
def save_settings(self): return conf_dict
"""Save lens-shading table to disk"""
logging.info("Saving picamera_lst to {}".format(self.picamera_lst_path))
self.save_lens_shading_table()
def update_settings(self, config: dict): def update_settings(self, config: dict):
""" """
@ -209,22 +214,23 @@ class PiCameraStreamer(BaseCamera):
config["picamera"], pause_for_effect=True config["picamera"], pause_for_effect=True
) )
# Handle lens shading if camera supports it
if (
hasattr(self.camera, "lens_shading_table")
and "lens_shading_table" in config["picamera"]
):
try:
self.camera.lens_shading_table = json_to_ndarray(
config["picamera"].get("lens_shading_table")
)
except KeyError as e:
logging.error(e)
# PiCameraStreamer parameters # PiCameraStreamer parameters
for key, value in config.items(): # For each provided setting for key, value in config.items(): # For each provided setting
if (key != "picamera") and hasattr(self, key): if (key != "picamera") and hasattr(self, key):
setattr(self, key, value) setattr(self, key, value)
# Handle lens shading if camera supports it
if ("picamera_lst_path" in config) and hasattr(
self.camera, "lens_shading_table"
):
logging.debug(
"Applying lens_shading_table from file: {}".format(
config["picamera_lst_path"]
)
)
self.apply_lens_shading_table(config["picamera_lst_path"])
# If stream was paused to update config, unpause # If stream was paused to update config, unpause
if paused_stream: if paused_stream:
logging.info("Resuming stream.") logging.info("Resuming stream.")
@ -293,41 +299,6 @@ class PiCameraStreamer(BaseCamera):
if pause_for_effect: if pause_for_effect:
time.sleep(0.2) time.sleep(0.2)
def read_lens_shading_table(self):
"""
Read the current lens shading table as a numpy array, if it exists. Return None otherwise.
"""
if hasattr(self.camera, "lens_shading_table"):
return self.camera.lens_shading_table
else:
return None
def save_lens_shading_table(self):
"""
Save the current lens shading table to an .npy file, if it exists.
"""
logging.debug(self.read_lens_shading_table())
if self.read_lens_shading_table() is not None:
np.save(self.picamera_lst_path, self.read_lens_shading_table())
else:
logging.warning("Unable to save a nonexistant lens shading table")
def apply_lens_shading_table(self, lst_array_or_path):
"""
Apply a lens shading table from an .npy file, or numpy array.
Args:
lst_array_or_path: Numpy array, or path to .npy file, describing the lens-shading table
"""
if isinstance(lst_array_or_path, np.ndarray):
self.camera.lens_shading_table = lst_array_or_path
elif (type(lst_array_or_path) == str) and os.path.isfile(lst_array_or_path):
self.camera.lens_shading_table = np.load(lst_array_or_path)
else:
logging.error(
"Unsupported or missing data for camera lens_shading_table. Must be numpy ndarray, or .npy file path string. Skipping."
)
def set_zoom(self, zoom_value: float = 1.0) -> None: def set_zoom(self, zoom_value: float = 1.0) -> None:
""" """
Change the camera zoom, handling re-centering and scaling. Change the camera zoom, handling re-centering and scaling.

View file

@ -205,10 +205,6 @@ class Microscope:
# Read curent config # Read curent config
current_config = self.read_settings() current_config = self.read_settings()
# Save config to file # Save config to file
if self.camera:
self.camera.save_settings()
if self.stage:
self.stage.save_settings()
self.settings_file.save(current_config, backup=True) self.settings_file.save(current_config, backup=True)
@property @property

View file

@ -23,10 +23,6 @@ class BaseStage(metaclass=ABCMeta):
"""Return the current settings as a dictionary""" """Return the current settings as a dictionary"""
pass pass
def save_settings(self):
"""(Optional) Save any settings to disk that need to be stored"""
return
@property @property
@abstractmethod @abstractmethod
def state(self): def state(self):

View file

@ -4,6 +4,7 @@ import operator
import base64 import base64
from uuid import UUID from uuid import UUID
import numpy as np import numpy as np
import logging
from collections import abc from collections import abc
from functools import reduce from functools import reduce
from contextlib import contextmanager from contextlib import contextmanager
@ -21,6 +22,27 @@ def serialise_array_b64(npy_arr):
return b64_string, dtype, shape return b64_string, dtype, shape
def ndarray_to_json(arr: np.ndarray):
b64_string, dtype, shape = serialise_array_b64(arr)
return {
"@type": "ndarray",
"dtype": dtype,
"shape": shape,
"base64": b64_string
}
def json_to_ndarray(json_dict: dict):
if not json_dict.get("@type") != "ndarray":
logging.warning("No valid @type attribute found. Conversion may fail.")
for required_param in ("dtype", "shape", "base64"):
if not json_dict.get(required_param):
raise KeyError(f"Missing required key {required_param}")
return deserialise_array_b64(json_dict.get("base64"), json_dict.get("dtype"), json_dict.get("shape"))
@contextmanager @contextmanager
def set_properties(obj, **kwargs): def set_properties(obj, **kwargs):
"""A context manager to set, then reset, certain properties of an object. """A context manager to set, then reset, certain properties of an object.