Handle captures as an OrderedDict. Fixes file deletion
This commit is contained in:
parent
7235445cf2
commit
60c6ae72f8
4 changed files with 34 additions and 24 deletions
|
|
@ -81,8 +81,7 @@ class ZipManager:
|
||||||
|
|
||||||
# Get array of captures from IDs
|
# Get array of captures from IDs
|
||||||
capture_list = [
|
capture_list = [
|
||||||
microscope.camera.image_from_id(capture_id)
|
microscope.camera.images.get(capture_id) for capture_id in capture_id_list
|
||||||
for capture_id in capture_id_list
|
|
||||||
]
|
]
|
||||||
# Remove Nones from list (missing/invalid captures)
|
# Remove Nones from list (missing/invalid captures)
|
||||||
capture_list = [capture for capture in capture_list if capture]
|
capture_list = [capture for capture in capture_list if capture]
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class InstrumentSchema(Schema):
|
||||||
settings = fields.Dict()
|
settings = fields.Dict()
|
||||||
state = fields.Dict()
|
state = fields.Dict()
|
||||||
|
|
||||||
|
|
||||||
class CaptureMetadataImageSchema(Schema):
|
class CaptureMetadataImageSchema(Schema):
|
||||||
id = fields.UUID()
|
id = fields.UUID()
|
||||||
acquisitionDate = fields.String(format="date")
|
acquisitionDate = fields.String(format="date")
|
||||||
|
|
@ -36,6 +37,7 @@ class CaptureMetadataSchema(Schema):
|
||||||
image = fields.Nested(CaptureMetadataImageSchema())
|
image = fields.Nested(CaptureMetadataImageSchema())
|
||||||
instrument = fields.Nested(InstrumentSchema())
|
instrument = fields.Nested(InstrumentSchema())
|
||||||
|
|
||||||
|
|
||||||
class CaptureSchema(Schema):
|
class CaptureSchema(Schema):
|
||||||
id = fields.String()
|
id = fields.String()
|
||||||
file = fields.String(
|
file = fields.String(
|
||||||
|
|
@ -98,7 +100,7 @@ class CaptureList(View):
|
||||||
List all image captures
|
List all image captures
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
image_list = microscope.camera.images
|
image_list = microscope.camera.images.values()
|
||||||
return image_list
|
return image_list
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -110,7 +112,7 @@ class CaptureView(View):
|
||||||
Description of a single image capture
|
Description of a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
@ -122,12 +124,15 @@ class CaptureView(View):
|
||||||
Delete a single image capture
|
Delete a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
||||||
|
# Delete the capture file
|
||||||
capture_obj.delete()
|
capture_obj.delete()
|
||||||
|
# Delete from capture list
|
||||||
|
del microscope.camera.images[id]
|
||||||
|
|
||||||
return "", 204
|
return "", 204
|
||||||
|
|
||||||
|
|
@ -140,7 +145,7 @@ class CaptureDownload(View):
|
||||||
Image data for a single image capture
|
Image data for a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
@ -175,7 +180,7 @@ class CaptureTags(View):
|
||||||
Get tags associated with a single image capture
|
Get tags associated with a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
@ -187,7 +192,7 @@ class CaptureTags(View):
|
||||||
Add tags to a single image capture
|
Add tags to a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
@ -207,7 +212,7 @@ class CaptureTags(View):
|
||||||
Delete tags from a single image capture
|
Delete tags from a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
@ -230,7 +235,7 @@ class CaptureAnnotations(View):
|
||||||
Get annotations associated with a single image capture
|
Get annotations associated with a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
@ -242,7 +247,7 @@ class CaptureAnnotations(View):
|
||||||
Update metadata for a single image capture
|
Update metadata for a single image capture
|
||||||
"""
|
"""
|
||||||
microscope = find_component("org.openflexure.microscope")
|
microscope = find_component("org.openflexure.microscope")
|
||||||
capture_obj = microscope.camera.image_from_id(id)
|
capture_obj = microscope.camera.images.get(id)
|
||||||
|
|
||||||
if not capture_obj:
|
if not capture_obj:
|
||||||
return abort(404) # 404 Not Found
|
return abort(404) # 404 Not Found
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from .capture import CaptureObject, build_captures_from_exif
|
from .capture import CaptureObject, build_captures_from_exif
|
||||||
from openflexure_microscope.utilities import entry_by_uuid
|
from openflexure_microscope.utilities import entry_by_uuid
|
||||||
|
|
@ -113,8 +114,8 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
self.paths = {"default": BASE_CAPTURE_PATH, "temp": TEMP_CAPTURE_PATH}
|
self.paths = {"default": BASE_CAPTURE_PATH, "temp": TEMP_CAPTURE_PATH}
|
||||||
|
|
||||||
# Capture data
|
# Capture data
|
||||||
self.images = []
|
self.images = OrderedDict()
|
||||||
self.videos = []
|
self.videos = OrderedDict()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|
@ -158,7 +159,7 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
"""Close the BaseCamera and all attached StreamObjects."""
|
"""Close the BaseCamera and all attached StreamObjects."""
|
||||||
logging.info("Closing {}".format(self))
|
logging.info("Closing {}".format(self))
|
||||||
# Close all StreamObjects
|
# Close all StreamObjects
|
||||||
for capture_list in [self.images, self.videos]:
|
for capture_list in [self.images.values(), self.videos.values()]:
|
||||||
for stream_object in capture_list:
|
for stream_object in capture_list:
|
||||||
stream_object.close()
|
stream_object.close()
|
||||||
# Empty temp directory
|
# Empty temp directory
|
||||||
|
|
@ -244,20 +245,22 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
@property
|
@property
|
||||||
def image(self):
|
def image(self):
|
||||||
"""Return the latest captured image."""
|
"""Return the latest captured image."""
|
||||||
return last_entry(self.images)
|
return last_entry(self.images.values())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def video(self):
|
def video(self):
|
||||||
"""Return the latest recorded video."""
|
"""Return the latest recorded video."""
|
||||||
return last_entry(self.videos)
|
return last_entry(self.videos.values())
|
||||||
|
|
||||||
def image_from_id(self, image_id):
|
def image_from_id(self, image_id):
|
||||||
"""Return an image StreamObject with a matching ID."""
|
"""Return an image StreamObject with a matching ID."""
|
||||||
return entry_by_uuid(image_id, self.images)
|
logging.warning("image_from_id is deprecated. Access captures as a dictionary.")
|
||||||
|
return entry_by_uuid(image_id, self.images.values())
|
||||||
|
|
||||||
def video_from_id(self, video_id):
|
def video_from_id(self, video_id):
|
||||||
"""Return a video StreamObject with a matching ID."""
|
"""Return a video StreamObject with a matching ID."""
|
||||||
return entry_by_uuid(video_id, self.videos)
|
logging.warning("video_from_id is deprecated. Access captures as a dictionary.")
|
||||||
|
return entry_by_uuid(video_id, self.videos.values())
|
||||||
|
|
||||||
# CREATING NEW CAPTURES
|
# CREATING NEW CAPTURES
|
||||||
|
|
||||||
|
|
@ -282,7 +285,7 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
|
|
||||||
# Generate file name
|
# Generate file name
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = generate_numbered_basename(self.images)
|
filename = generate_numbered_basename(self.images.values())
|
||||||
logging.debug(filename)
|
logging.debug(filename)
|
||||||
filename = "{}.{}".format(filename, fmt)
|
filename = "{}.{}".format(filename, fmt)
|
||||||
|
|
||||||
|
|
@ -300,7 +303,7 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
output.put_tags(["temporary"])
|
output.put_tags(["temporary"])
|
||||||
|
|
||||||
# Update capture list
|
# Update capture list
|
||||||
self.images.append(output)
|
self.images[output.id] = output
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
@ -322,10 +325,11 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
folder (str): Name of the folder in which to store the capture.
|
folder (str): Name of the folder in which to store the capture.
|
||||||
fmt (str): Format of the capture.
|
fmt (str): Format of the capture.
|
||||||
"""
|
"""
|
||||||
|
# TODO: Remove the redundancy here
|
||||||
|
|
||||||
# Generate file name
|
# Generate file name
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = generate_numbered_basename(self.videos)
|
filename = generate_numbered_basename(self.videos.values())
|
||||||
logging.debug(filename)
|
logging.debug(filename)
|
||||||
filename = "{}.{}".format(filename, fmt)
|
filename = "{}.{}".format(filename, fmt)
|
||||||
|
|
||||||
|
|
@ -343,7 +347,7 @@ class BaseCamera(metaclass=ABCMeta):
|
||||||
output.put_tags(["temporary"])
|
output.put_tags(["temporary"])
|
||||||
|
|
||||||
# Update capture list
|
# Update capture list
|
||||||
self.videos.append(output)
|
self.videos[output.id] = output
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ from PIL import Image
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
import atexit
|
import atexit
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from openflexure_microscope.camera import piexif
|
from openflexure_microscope.camera import piexif
|
||||||
from openflexure_microscope.camera.piexif._exceptions import InvalidImageDataError
|
from openflexure_microscope.camera.piexif._exceptions import InvalidImageDataError
|
||||||
from openflexure_microscope.config import JSONEncoder
|
from openflexure_microscope.config import JSONEncoder
|
||||||
|
|
@ -58,7 +60,7 @@ def build_captures_from_exif(capture_path):
|
||||||
|
|
||||||
logging.debug("Reloading captures from {}...".format(capture_path))
|
logging.debug("Reloading captures from {}...".format(capture_path))
|
||||||
files = make_file_list(capture_path, EXIF_FORMATS)
|
files = make_file_list(capture_path, EXIF_FORMATS)
|
||||||
captures = []
|
captures = OrderedDict()
|
||||||
|
|
||||||
for f in files:
|
for f in files:
|
||||||
logging.debug("Reloading capture {}...".format(f))
|
logging.debug("Reloading capture {}...".format(f))
|
||||||
|
|
@ -66,7 +68,7 @@ def build_captures_from_exif(capture_path):
|
||||||
if exif:
|
if exif:
|
||||||
capture = capture_from_exif(f, exif)
|
capture = capture_from_exif(f, exif)
|
||||||
if capture:
|
if capture:
|
||||||
captures.append(capture)
|
captures[capture.id] = capture
|
||||||
else:
|
else:
|
||||||
logging.error("Invalid data at {}. Skipping.".format(f))
|
logging.error("Invalid data at {}. Skipping.".format(f))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue