From 26041e565c1ba490a9eb12e3871f2136d8765a3b Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Thu, 25 Jun 2020 10:01:08 +0100 Subject: [PATCH 01/14] Version bump CSM plugin The new version includes timing information, so we can calibrate the stage move times. --- poetry.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 39019e00..b2da5946 100644 --- a/poetry.lock +++ b/poetry.lock @@ -95,7 +95,7 @@ description = "" name = "camera-stage-mapping" optional = false python-versions = "^3.6" -version = "0.1.0" +version = "0.1.1" [package.dependencies] numpy = "^1.17" @@ -107,7 +107,7 @@ ipython = [] ofmclient = [] [package.source] -reference = "9133e9781157e7d8be2ca0cbeefa7fca0c7dfbe0" +reference = "0352e59fdfc9154652914a4c9373a741e10dfa25" type = "git" url = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git" [[package]] From 3500dd54edab1920f3746cfaf55ce196fe533da7 Mon Sep 17 00:00:00 2001 From: Joel Collins <2579603-jtc42@users.noreply.gitlab.com> Date: Mon, 29 Jun 2020 16:08:29 +0000 Subject: [PATCH 02/14] 2.2.4 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ea51fa64..f231fdbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.masonry.api" [tool.poetry] name = "openflexure-microscope-server" -version = "2.2.3" +version = "2.2.4" description = "Python module, and Flask-based web API, to run the OpenFlexure Microscope." authors = [ From 0101a5b91ed92ff286a50784a23d70b3bc0946c0 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 15:34:53 +0100 Subject: [PATCH 03/14] Added expiringdict --- poetry.lock | 18 +++++++++++++++++- pyproject.toml | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 9dd9b4b5..38fd30ac 100644 --- a/poetry.lock +++ b/poetry.lock @@ -110,6 +110,7 @@ ofmclient = [] reference = "87a66aadbbea211b260dc279c0f009a8a2b8de51" type = "git" url = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git" + [[package]] category = "main" description = "Pure Python CBOR (de)serializer with extensive tag support" @@ -174,6 +175,17 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" version = "0.16" +[[package]] +category = "main" +description = "Dictionary with auto-expiring values for caching purposes" +name = "expiringdict" +optional = false +python-versions = "*" +version = "1.2.1" + +[package.extras] +tests = ["dill", "coverage", "coveralls", "mock", "nose"] + [[package]] category = "main" description = "A simple framework for building complex web applications." @@ -433,6 +445,7 @@ test = ["coverage", "pytest", "mock", "pillow", "numpy"] reference = "" type = "url" url = "https://github.com/rwb27/picamera/releases/download/v1.13.2b0/picamera-1.13.2b0-py3-none-any.whl" + [[package]] category = "main" description = "Python Imaging Library (Fork)" @@ -835,7 +848,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] rpi = ["RPi.GPIO"] [metadata] -content-hash = "ae04fc9fc87b8a1dd96e9fe8b442fb6261d2ded29aef1385dcb35beac5d8f467" +content-hash = "bcc3ee50dba0c2795a5798de24aaaf2cfa7951076bed417236e7b0e51925ebc5" python-versions = "^3.6" [metadata.files] @@ -921,6 +934,9 @@ docutils = [ {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, ] +expiringdict = [ + {file = "expiringdict-1.2.1.tar.gz", hash = "sha256:fe2ba427220425c3c8a3d29f6d2e2985bcee323f8bcd4021e68ebefbd90d8250"}, +] flask = [ {file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"}, {file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"}, diff --git a/pyproject.toml b/pyproject.toml index f231fdbe..43ded713 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ pynpm = "^0.1.2" camera-stage-mapping = {git = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git"} sangaboard = "^0.2" gevent = "20.6.0" # Pinned version to guarantee piwheels wheel +expiringdict = "^1.2.1" [tool.poetry.extras] rpi = ["RPi.GPIO"] From 1cba4205a6446da2fbd831d1cd96e6e566e11ca7 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 15:35:21 +0100 Subject: [PATCH 04/14] Removed async metadata. Added metadata cache. --- openflexure_microscope/microscope.py | 75 ++++++++++++++++++---------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/openflexure_microscope/microscope.py b/openflexure_microscope/microscope.py index 6672c4cb..6151e2de 100644 --- a/openflexure_microscope/microscope.py +++ b/openflexure_microscope/microscope.py @@ -6,6 +6,7 @@ import logging import pkg_resources import uuid from typing import Tuple +from expiringdict import ExpiringDict import gevent @@ -61,6 +62,10 @@ class Microscope: # Apply settings loaded from file self.update_settings(self.settings_file.load()) + # Data cache + self.configuration_cache = ExpiringDict(max_len=100, max_age_seconds=3600) + self.metadata_cache = ExpiringDict(max_len=100, max_age_seconds=3600) + def __enter__(self): """Create microscope on context enter.""" return self @@ -252,8 +257,7 @@ class Microscope: # Save config to file self.settings_file.save(current_config, backup=True) - @property - def configuration(self): + def force_get_configuration(self): with self.lock: initial_configuration = self.configuration_file.load() @@ -277,17 +281,28 @@ class Microscope: initial_configuration.update(current_configuration) return initial_configuration + def get_configuration(self, cache_key=None): + if cache_key: + cached_config = self.configuration_cache.get(cache_key, None) + if cached_config: + return cached_config + else: + full_config = self.force_get_configuration() + self.configuration_cache[cache_key] = full_config + return full_config + return self.force_get_configuration() + @property - def metadata(self): + def configuration(self): + return self.get_configuration() + + def force_get_metadata(self): """ Microscope system metadata, to be applied to basically all captures """ - with Timer("Reading settings:"): - settings = self.read_settings(full=False) - with Timer("Reading state:"): - state = self.state - with Timer("Reading configuration:"): - configuration = self.configuration + settings = self.read_settings(full=False) + state = self.state + configuration = self.configuration system_metadata = { "id": self.id, "settings": settings, @@ -297,17 +312,23 @@ class Microscope: return system_metadata - def add_metadata_to_capture(self, output, metadata, annotations, tags): - logging.debug(f"Waiting for {output.file}") - # Wait for the file to be written to disk - with Timer("Waiting for file:"): - output.file_ready.wait() - - with Timer("Building metadata"): - full_metadata = {"instrument": self.metadata, **metadata} - with Timer("Writing metadata to file"): - output.put_and_save(tags, annotations, full_metadata) - logging.info(f"Finished injecting EXIF data into {output.file}") + def get_metadata(self, cache_key=None): + logging.debug(f"Looking for cache key {cache_key}") + if cache_key: + cached_metadata = self.metadata_cache.get(cache_key, None) + if cached_metadata: + logging.debug(f"Reusing cached microscope metadata: {cache_key}") + return cached_metadata + else: + full_metadata = self.force_get_metadata() + self.metadata_cache[cache_key] = full_metadata + return full_metadata + logging.debug("Generating full microscope metadata") + return self.force_get_metadata() + + @property + def metadata(self): + return self.get_metadata() def capture( self, @@ -321,6 +342,7 @@ class Microscope: annotations: dict = None, tags: list = None, metadata: dict = None, + cache_key: str = None ): logging.debug(f"Microscope capturing to {filename}") if not annotations: @@ -337,7 +359,7 @@ class Microscope: ) # Capture to output object - logging.info("Starting microscope capture...") + logging.info(f"Starting microscope capture {filename}") self.camera.capture( output, use_video_port=use_video_port, @@ -347,10 +369,13 @@ class Microscope: ) # Gether metadata from hardware in a greenlet - #gevent.get_hub().threadpool.spawn(self.add_metadata_to_capture, output, metadata, annotations, tags) - gevent.spawn(self.add_metadata_to_capture, output, metadata, annotations, tags) - #self.add_metadata_to_capture(output, metadata, annotations, tags) + logging.debug(f"Waiting for {output.file}") + # Wait for the file to be written to disk + output.file_ready.wait() + full_metadata = {"instrument": self.get_metadata(cache_key), **metadata} + output.put_and_save(tags, annotations, full_metadata) + logging.debug(f"Finished adding EXIF data to {output.file}") - logging.info(f"Finished capture to {output.file}") + logging.debug(f"Finished capture to {output.file}") return output From 6c0017be5a36b0b62e6256320e4604431b427237 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 15:35:31 +0100 Subject: [PATCH 05/14] Added metadata cache key --- openflexure_microscope/api/default_extensions/scan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openflexure_microscope/api/default_extensions/scan.py b/openflexure_microscope/api/default_extensions/scan.py index 65db21b9..b7eb0b94 100644 --- a/openflexure_microscope/api/default_extensions/scan.py +++ b/openflexure_microscope/api/default_extensions/scan.py @@ -84,6 +84,7 @@ def capture( annotations=annotations, tags=tags, metadata=metadata, + cache_key=folder ) From d9fd00b25563ff62cda9c9d8c4e48651bfa8c03c Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 15:50:31 +0100 Subject: [PATCH 06/14] Never cache microscope state --- openflexure_microscope/microscope.py | 44 ++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/openflexure_microscope/microscope.py b/openflexure_microscope/microscope.py index 6151e2de..9d090ee0 100644 --- a/openflexure_microscope/microscope.py +++ b/openflexure_microscope/microscope.py @@ -298,33 +298,41 @@ class Microscope: def force_get_metadata(self): """ - Microscope system metadata, to be applied to basically all captures + Read cachable bits of microscope metadata. + Currently ID, settings, and configuration can be cached """ - settings = self.read_settings(full=False) - state = self.state - configuration = self.configuration system_metadata = { "id": self.id, - "settings": settings, - "state": state, - "configuration": configuration, + "settings": self.read_settings(full=False), + "configuration": self.get_configuration(), } return system_metadata def get_metadata(self, cache_key=None): - logging.debug(f"Looking for cache key {cache_key}") + """ + Read microscope metadata, with partial caching + """ + metadata = {} + + # Load cached bits of metadata if cache_key: - cached_metadata = self.metadata_cache.get(cache_key, None) - if cached_metadata: - logging.debug(f"Reusing cached microscope metadata: {cache_key}") - return cached_metadata - else: - full_metadata = self.force_get_metadata() - self.metadata_cache[cache_key] = full_metadata - return full_metadata - logging.debug("Generating full microscope metadata") - return self.force_get_metadata() + logging.debug(f"Reading cached microscope metadata: {cache_key}") + metadata = self.metadata_cache.get(cache_key, None) + if not metadata: + logging.debug(f"Building and caching microscope metadata: {cache_key}") + metadata = self.force_get_metadata() + self.metadata_cache[cache_key] = metadata + else: + logging.debug(f"Building microscope metadata: {cache_key}") + metadata = self.force_get_metadata() + + # Keys that should never be cached + metadata.update({ + "state": self.state, + }) + + return metadata @property def metadata(self): From 78d0345239b802cf2e4901a31af663f7239b6e77 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 15:58:18 +0100 Subject: [PATCH 07/14] Spawn metadata IO in greenlets --- openflexure_microscope/microscope.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openflexure_microscope/microscope.py b/openflexure_microscope/microscope.py index 9d090ee0..3df77eb1 100644 --- a/openflexure_microscope/microscope.py +++ b/openflexure_microscope/microscope.py @@ -360,6 +360,10 @@ class Microscope: if not tags: tags = [] + # Read metadata for capture + full_metadata = {"instrument": self.get_metadata(cache_key), **metadata} + + # Do capture with self.camera.lock: # Create output object output = self.captures.new_image( @@ -376,14 +380,7 @@ class Microscope: fmt=fmt, ) - # Gether metadata from hardware in a greenlet - logging.debug(f"Waiting for {output.file}") - # Wait for the file to be written to disk - output.file_ready.wait() - full_metadata = {"instrument": self.get_metadata(cache_key), **metadata} output.put_and_save(tags, annotations, full_metadata) - logging.debug(f"Finished adding EXIF data to {output.file}") - logging.debug(f"Finished capture to {output.file}") return output From 0e78d7be82631923fba13904960605a988c40f86 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 15:58:31 +0100 Subject: [PATCH 08/14] Spawn metadata IO in greenlets --- openflexure_microscope/captures/capture.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openflexure_microscope/captures/capture.py b/openflexure_microscope/captures/capture.py index 57db09d5..04b63dd1 100644 --- a/openflexure_microscope/captures/capture.py +++ b/openflexure_microscope/captures/capture.py @@ -210,7 +210,7 @@ class CaptureObject(object): if tag not in self.tags: self.tags.append(tag) - self.save_metadata() + gevent.spawn(self.save_metadata) def delete_tag(self, tag: str): """ @@ -222,7 +222,7 @@ class CaptureObject(object): if tag in self.tags: self.tags = [new_tag for new_tag in self.tags if new_tag != tag] - self.save_metadata() + gevent.spawn(self.save_metadata) # HANDLE METADATA @@ -234,7 +234,7 @@ class CaptureObject(object): data (dict): Dictionary of metadata to be added """ self.annotations.update(data) - self.save_metadata() + gevent.spawn(self.save_metadata) def put_metadata(self, data: dict) -> None: """ @@ -244,7 +244,7 @@ class CaptureObject(object): data (dict): Dictionary of metadata to be added """ self._metadata.update(data) - self.save_metadata() + gevent.spawn(self.save_metadata) def put_and_save(self, tags: list = None, annotations: dict = None, metadata: dict = None): """ @@ -266,7 +266,7 @@ class CaptureObject(object): # Metadata self._metadata.update(metadata) - self.save_metadata() + gevent.spawn(self.save_metadata) def save_metadata(self) -> None: """ From 38cdecd39a53014e9654a445606c3bbe95795d19 Mon Sep 17 00:00:00 2001 From: Joel Collins <2579603-jtc42@users.noreply.gitlab.com> Date: Wed, 1 Jul 2020 15:05:43 +0000 Subject: [PATCH 09/14] Revert "Spawn metadata IO in greenlets" This reverts commit 0e78d7be82631923fba13904960605a988c40f86 --- openflexure_microscope/captures/capture.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openflexure_microscope/captures/capture.py b/openflexure_microscope/captures/capture.py index 04b63dd1..57db09d5 100644 --- a/openflexure_microscope/captures/capture.py +++ b/openflexure_microscope/captures/capture.py @@ -210,7 +210,7 @@ class CaptureObject(object): if tag not in self.tags: self.tags.append(tag) - gevent.spawn(self.save_metadata) + self.save_metadata() def delete_tag(self, tag: str): """ @@ -222,7 +222,7 @@ class CaptureObject(object): if tag in self.tags: self.tags = [new_tag for new_tag in self.tags if new_tag != tag] - gevent.spawn(self.save_metadata) + self.save_metadata() # HANDLE METADATA @@ -234,7 +234,7 @@ class CaptureObject(object): data (dict): Dictionary of metadata to be added """ self.annotations.update(data) - gevent.spawn(self.save_metadata) + self.save_metadata() def put_metadata(self, data: dict) -> None: """ @@ -244,7 +244,7 @@ class CaptureObject(object): data (dict): Dictionary of metadata to be added """ self._metadata.update(data) - gevent.spawn(self.save_metadata) + self.save_metadata() def put_and_save(self, tags: list = None, annotations: dict = None, metadata: dict = None): """ @@ -266,7 +266,7 @@ class CaptureObject(object): # Metadata self._metadata.update(metadata) - gevent.spawn(self.save_metadata) + self.save_metadata() def save_metadata(self) -> None: """ From bbd64a811786c8e326824d3c44225928da0791da Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Wed, 1 Jul 2020 16:08:01 +0100 Subject: [PATCH 10/14] 2.2.5 --- poetry.lock | 4 +--- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 38fd30ac..ca0036cb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -107,10 +107,9 @@ ipython = [] ofmclient = [] [package.source] -reference = "87a66aadbbea211b260dc279c0f009a8a2b8de51" +reference = "20d25b498ebfc0fdbe17f8afc810ac48a69b7179" type = "git" url = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git" - [[package]] category = "main" description = "Pure Python CBOR (de)serializer with extensive tag support" @@ -445,7 +444,6 @@ test = ["coverage", "pytest", "mock", "pillow", "numpy"] reference = "" type = "url" url = "https://github.com/rwb27/picamera/releases/download/v1.13.2b0/picamera-1.13.2b0-py3-none-any.whl" - [[package]] category = "main" description = "Python Imaging Library (Fork)" diff --git a/pyproject.toml b/pyproject.toml index 43ded713..669d4787 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.masonry.api" [tool.poetry] name = "openflexure-microscope-server" -version = "2.2.4" +version = "2.2.5" description = "Python module, and Flask-based web API, to run the OpenFlexure Microscope." authors = [ From 489b81f34b8664612702de5518ea5c3db84e14aa Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Thu, 2 Jul 2020 23:41:28 +0100 Subject: [PATCH 11/14] Removed some unused gevent imports --- openflexure_microscope/camera/mock.py | 3 +-- openflexure_microscope/microscope.py | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/openflexure_microscope/camera/mock.py b/openflexure_microscope/camera/mock.py index ec61bc7e..0b858cda 100644 --- a/openflexure_microscope/camera/mock.py +++ b/openflexure_microscope/camera/mock.py @@ -10,7 +10,6 @@ import time import numpy as np from PIL import Image, ImageFont, ImageDraw from datetime import datetime -import gevent import logging @@ -221,7 +220,7 @@ class MissingCamera(BaseCamera): # While the iterator is not closed try: while True: - gevent.sleep(1) # Only serve frames at 1fps + time.sleep(1) # Only serve frames at 1fps # Reset stream self.stream.seek(0) self.stream.truncate() diff --git a/openflexure_microscope/microscope.py b/openflexure_microscope/microscope.py index 3df77eb1..1c55ac39 100644 --- a/openflexure_microscope/microscope.py +++ b/openflexure_microscope/microscope.py @@ -8,8 +8,6 @@ import uuid from typing import Tuple from expiringdict import ExpiringDict -import gevent - from openflexure_microscope.captures import CaptureManager from openflexure_microscope.stage.mock import MissingStage From 44cbc874165fd585f5f0374c9a5a2afc0ad10a24 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Fri, 3 Jul 2020 15:05:53 +0100 Subject: [PATCH 12/14] Re-synchronised capture IO --- openflexure_microscope/captures/capture.py | 50 ++++++++-------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/openflexure_microscope/captures/capture.py b/openflexure_microscope/captures/capture.py index 57db09d5..00777442 100644 --- a/openflexure_microscope/captures/capture.py +++ b/openflexure_microscope/captures/capture.py @@ -10,9 +10,6 @@ from PIL import Image import dateutil.parser import atexit -from gevent.fileobject import FileObjectThread -import gevent - from collections import OrderedDict from openflexure_microscope.camera import piexif @@ -129,10 +126,6 @@ class CaptureObject(object): """Create a new StreamObject, to manage capture data.""" # Stream for buffering capture data self.stream = io.BytesIO() - # Event to notify when the stream has finished writing to disk - self.file_ready = gevent.event.Event() - # Access lock for the disk file - self.lock = gevent.lock.BoundedSemaphore() # Store a nice ID self.id = uuid.uuid4() #: str: Unique capture ID @@ -160,19 +153,12 @@ class CaptureObject(object): def write(self, s): self.stream.write(s) - def _stream_to_file(self): - with self.lock: - logging.info(f"Writing to disk {self.file}") - with FileObjectThread(open(self.file, "wb"), 'wb') as outfile: - outfile.write(self.stream.getbuffer()) - self.stream.close() - self.file_ready.set() - logging.info(f"Finished writing to disk {self.file}") - def flush(self): - logging.debug(f"Flushing {self.file}") - gevent.spawn(self._stream_to_file) - logging.debug(f"Returning flushing {self.file}") + logging.info(f"Writing to disk {self.file}") + with open(self.file, "wb") as outfile: + outfile.write(self.stream.getbuffer()) + self.stream.close() + logging.info(f"Finished writing to disk {self.file}") def open(self, mode): return open(self.file, mode) @@ -275,20 +261,18 @@ class CaptureObject(object): global EXIF_FORMATS if self.format.upper() in EXIF_FORMATS and self.exists: - self.file_ready.wait() - with self.lock: - logging.debug("Writing exif data to capture file") - # Extract current Exif data - exif_dict = piexif.load(self.file) - # Serialize metadata - metadata_string = json.dumps(self.metadata, cls=JSONEncoder) - logging.debug(f"Saving metadata string to file: {metadata_string}") - # Insert metadata into exif_dict - exif_dict["Exif"][piexif.ExifIFD.UserComment] = metadata_string.encode() - # Convert new exif dict to exif bytes - exif_bytes = piexif.dump(exif_dict) - # Insert exif into file - piexif.insert(exif_bytes, self.file) + logging.debug("Writing exif data to capture file") + # Extract current Exif data + exif_dict = piexif.load(self.file) + # Serialize metadata + metadata_string = json.dumps(self.metadata, cls=JSONEncoder) + logging.debug(f"Saving metadata string to file: {metadata_string}") + # Insert metadata into exif_dict + exif_dict["Exif"][piexif.ExifIFD.UserComment] = metadata_string.encode() + # Convert new exif dict to exif bytes + exif_bytes = piexif.dump(exif_dict) + # Insert exif into file + piexif.insert(exif_bytes, self.file) logging.info(f"Finished saving metadata to {self.file}") @property From 94dcf6b0269241e73607d4267fae97ee3e9b6a8f Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Fri, 3 Jul 2020 15:24:22 +0100 Subject: [PATCH 13/14] Switch to labthings monkey alias --- openflexure_microscope/api/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openflexure_microscope/api/app.py b/openflexure_microscope/api/app.py index b603b666..7868a714 100644 --- a/openflexure_microscope/api/app.py +++ b/openflexure_microscope/api/app.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from gevent import monkey +from labthings.server import monkey monkey.patch_all() From ce3fba56c35385d8808465b500f889ae196bb5dd Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Fri, 3 Jul 2020 15:24:30 +0100 Subject: [PATCH 14/14] Switch to PyPI CSM distribution --- poetry.lock | 84 ++++++++++++++++++++++++++------------------------ pyproject.toml | 3 +- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/poetry.lock b/poetry.lock index ca0036cb..18605b9c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -91,25 +91,19 @@ d = ["aiohttp (>=3.3.2)"] [[package]] category = "main" -description = "" +description = "Calibration and mapping between stage and camera coordinates in a microscope" name = "camera-stage-mapping" optional = false -python-versions = "^3.6" -version = "0.1.1" +python-versions = ">=3.6,<4.0" +version = "0.1.2" [package.dependencies] -numpy = "^1.17" +numpy = ">=1.17,<2.0" [package.extras] -all = ["opencv-python-headless (^4.1)", "scipy (^1.4)"] -correlation = ["opencv-python-headless (^4.1)", "scipy (^1.4)"] -ipython = [] -ofmclient = [] +all = ["opencv-python-headless (>=4.1,<5.0)", "scipy (>=1.4,<2.0)"] +correlation = ["opencv-python-headless (>=4.1,<5.0)", "scipy (>=1.4,<2.0)"] -[package.source] -reference = "20d25b498ebfc0fdbe17f8afc810ac48a69b7179" -type = "git" -url = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git" [[package]] category = "main" description = "Pure Python CBOR (de)serializer with extensive tag support" @@ -230,7 +224,7 @@ description = "Coroutine-based network library" name = "gevent" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "20.6.0" +version = "20.6.2" [package.dependencies] cffi = ">=1.12.2" @@ -242,9 +236,9 @@ setuptools = "*" [package.extras] dnspython = ["dnspython (>=1.16.0)", "idna"] docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput"] -monitor = ["psutil (>=5.6.1)", "psutil (5.6.3)"] -recommended = ["dnspython (>=1.16.0)", "idna", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)", "selectors2", "backports.socketpair"] -test = ["dnspython (>=1.16.0)", "idna", "requests", "objgraph", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)", "selectors2", "futures", "mock", "backports.socketpair", "contextvars (2.4)", "coverage (<5.0)", "coveralls (>=1.7.0)"] +monitor = ["psutil (>=5.7.0)"] +recommended = ["dnspython (>=1.16.0)", "idna", "cffi (>=1.12.2)", "selectors2", "backports.socketpair", "psutil (>=5.7.0)"] +test = ["dnspython (>=1.16.0)", "idna", "requests", "objgraph", "cffi (>=1.12.2)", "selectors2", "futures", "mock", "backports.socketpair", "contextvars (2.4)", "coverage (<5.0)", "coveralls (>=1.7.0)", "psutil (>=5.7.0)"] [[package]] category = "main" @@ -444,6 +438,7 @@ test = ["coverage", "pytest", "mock", "pillow", "numpy"] reference = "" type = "url" url = "https://github.com/rwb27/picamera/releases/download/v1.13.2b0/picamera-1.13.2b0-py3-none-any.whl" + [[package]] category = "main" description = "Python Imaging Library (Fork)" @@ -846,7 +841,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] rpi = ["RPi.GPIO"] [metadata] -content-hash = "bcc3ee50dba0c2795a5798de24aaaf2cfa7951076bed417236e7b0e51925ebc5" +content-hash = "94e35da71817800c617a54e54dc937df62953fa95caa2e2e05f69b1163582c4c" python-versions = "^3.6" [metadata.files] @@ -878,7 +873,10 @@ black = [ {file = "black-18.9b0-py36-none-any.whl", hash = "sha256:817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739"}, {file = "black-18.9b0.tar.gz", hash = "sha256:e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"}, ] -camera-stage-mapping = [] +camera-stage-mapping = [ + {file = "camera-stage-mapping-0.1.2.tar.gz", hash = "sha256:0d1a6f93b3a60054bc8057359464adbb40488b4daeb93c672b90e4fe525e7b69"}, + {file = "camera_stage_mapping-0.1.2-py3-none-any.whl", hash = "sha256:3f3da3e95792e811e6808173c368be67ebb00e6f7d7e37d68cb36fa765d13da9"}, +] cbor2 = [ {file = "cbor2-5.1.0.tar.gz", hash = "sha256:43ce11e8c2fe4971d386d1a60cf83bfa0a4a667b97668ba76acbf5e6398821aa"}, ] @@ -947,28 +945,34 @@ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] gevent = [ - {file = "gevent-20.6.0-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:ccac571d5bb7a85be736c0c5e241a5263a36904b358edc2dcceaa3b54a18eb25"}, - {file = "gevent-20.6.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:eb74efa2486b8c2576eaf2ef6a3a782b1a38fe414390a4a3ab411efca91e54f5"}, - {file = "gevent-20.6.0-cp27-cp27m-win32.whl", hash = "sha256:2701ac60993fb74f1f548348641c78160215aa9707b08e37caf10fe63712f5d9"}, - {file = "gevent-20.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:1a449ab1390fd48cc509d846a62d867e7c548f8f9d5632ca012af2741c97e6d6"}, - {file = "gevent-20.6.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:e963584dd93b8268764297b13d6d99e24d9f1d63d921d5260286b3cde92f2851"}, - {file = "gevent-20.6.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:56f2949b068e922bce3695e80bbf484115536901ad77e833b0e1ac7e4d996654"}, - {file = "gevent-20.6.0-cp35-cp35m-win32.whl", hash = "sha256:d4376e9d8f6ecf68de182fed99eb7d7f255b15170edb0bc7d06720552f541c6f"}, - {file = "gevent-20.6.0-cp35-cp35m-win_amd64.whl", hash = "sha256:6d172744705aa401b0014142343e866f98668bd86fc5ba070ace22f4e98f76dd"}, - {file = "gevent-20.6.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:664f061993e1104f901801dc7b305824389f5c05936e7daeabee56bf76837726"}, - {file = "gevent-20.6.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f9521f4721f50f7e1ade81bf61c17387d2cd901de65701038e74c5e87e2785cc"}, - {file = "gevent-20.6.0-cp36-cp36m-win32.whl", hash = "sha256:779ab592efc30550879546bfe83ee6cb42538080fcd495817868ed7b7b17c3ff"}, - {file = "gevent-20.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:94241c8e962b5eab49d5459b319454161bdb1a0c53ffe883a94a9952ab916345"}, - {file = "gevent-20.6.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:77d9237d17a64054e1a03883d3265d27fe98e49f41cf1dd22b42ee3206f99b53"}, - {file = "gevent-20.6.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:5520e72522906483559bd12eacabf72f130972dabe8e05d159e227eca97cbcf9"}, - {file = "gevent-20.6.0-cp37-cp37m-win32.whl", hash = "sha256:8625256ec3acc9b095050d15c256ad9ce3f8bac833982bd712af14a83991b067"}, - {file = "gevent-20.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e5e1f2024fbf753549703cde287f6cc940248d860f617d657c3b3ea0638035f0"}, - {file = "gevent-20.6.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:3165510ed37f8ea38345a8a2464d5c700f7cc8828194612889f6c583e2889ff1"}, - {file = "gevent-20.6.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b5f73ef6442e72774359afcf892c47cbdcb0811a4577fc1b4b11191aa362e353"}, - {file = "gevent-20.6.0-cp38-cp38-win32.whl", hash = "sha256:6e232e1870dfd2e32aaa26083488c116492e9378d288dffca0e38c1521ba502d"}, - {file = "gevent-20.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:dffc2d2bb815a6ab0370e3e478094e0c43f610a3466e241bc150af21293763db"}, - {file = "gevent-20.6.0-pp27-pypy_73-win32.whl", hash = "sha256:ea79e58f7927939ac60d3c73aa9e5d6186c3fea77e4414d768d658e1f58ef7a3"}, - {file = "gevent-20.6.0.tar.gz", hash = "sha256:51cab8f792961a75da39452586bb3474eaa1607ab2c83398745ef1b9ba09cb92"}, + {file = "gevent-20.6.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b03890bbddbae5667f5baad517417056496ff5e92c3c7945b27cc08f55a9fcb2"}, + {file = "gevent-20.6.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1ea0d34cb78cdf37870be3bfb9330ebda89197bed9e048c14f4a90dec19a33e0"}, + {file = "gevent-20.6.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:73eb4cf3114fbb5dd801bd0b93941adfa2fa6d99e91976c20a121ea14b8b39b9"}, + {file = "gevent-20.6.2-cp27-cp27m-win32.whl", hash = "sha256:f41cc8e853ac2252bc58f6feabd74b8aae613e2d19097c5373463122f4dc08f0"}, + {file = "gevent-20.6.2-cp27-cp27m-win_amd64.whl", hash = "sha256:d3baff87d935a5eeffb0e4f7cd5ffe258d2430cd62aeee2e5396f85da07df435"}, + {file = "gevent-20.6.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:7d8408854ce892f987305a0e9bf5c051f4ea29453665454396d6afb620c719b6"}, + {file = "gevent-20.6.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:ea2e4584950186b71d648bde6af40dae4d4c6f43db25a732ec056b27a7a83afe"}, + {file = "gevent-20.6.2-cp35-cp35m-win32.whl", hash = "sha256:c0f4340e40e0f9dfe93a52a12ddf5b1eeda9bbc89b99bf3b9b23acab0dfae0a4"}, + {file = "gevent-20.6.2-cp35-cp35m-win_amd64.whl", hash = "sha256:13c74d6784ef5ada2666abf2bb310d27a1d14291f7cac46148f336b19f714d40"}, + {file = "gevent-20.6.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:78bd94f6f2ac366155169df3507068f6381f2ad77625633189ce183f86a57597"}, + {file = "gevent-20.6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0b16dd85eddaf6acdad373ce90ed4da09ef466cbc5e0ee5932d13f099929e844"}, + {file = "gevent-20.6.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a47556cac07e31b3cef8fd701599b3b1365961fe3736471f41807ffa27c5c848"}, + {file = "gevent-20.6.2-cp36-cp36m-win32.whl", hash = "sha256:bef18b8bd3b728240b9bbd699737216b793d6c97b482431f69dcbe328ad73692"}, + {file = "gevent-20.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d0a67a20ce325f6a2068e0bd9fbf83db8a5f5ced972ed8ac5c20079a7d98c7d1"}, + {file = "gevent-20.6.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:b17915b65b49a425115ddc3087484c81b1e47ce38c931d18bb14e453753e4d06"}, + {file = "gevent-20.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ebb8a545112110e3a6edf905ae1556b0538fc148c743aa7d8cfaebbbc23de31d"}, + {file = "gevent-20.6.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6c864b5604166ac8351e3128a1135b883b9e978fd24afbd75a249dcb42bc8ab5"}, + {file = "gevent-20.6.2-cp37-cp37m-win32.whl", hash = "sha256:e5ca5ee80a9d9e697c9fc22b4bbce9ad06870f83fc8e7774e5504892ef702476"}, + {file = "gevent-20.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f2a02d9004ccb18edd9eaf6f25da9a7763de41a69754d5e4d872a8cbf8bd0b72"}, + {file = "gevent-20.6.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:354f932c284fa45826b32f42927d892096cce05671b50b3ff59528230217ad47"}, + {file = "gevent-20.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:67776cb33b638a3c61a0351d9d1e8f33a46b47de619e249de1159892f9ff035c"}, + {file = "gevent-20.6.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:68764aca061bbbbade43727e797f9c28042f6d90cca5fb6514ef726d43ab00ca"}, + {file = "gevent-20.6.2-cp38-cp38-win32.whl", hash = "sha256:0f3fbb1703b10609856e5dffb0e358bf5edf57e52dc7cd7226e3f8674fdc0a0f"}, + {file = "gevent-20.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:a18d8dd9bfa994a22f30adfa0563d80f0809140045c34f85535f422813d25855"}, + {file = "gevent-20.6.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9527087984f1659be899b3300d5d61c7c5b01d8beae106aff5160316da8bc56f"}, + {file = "gevent-20.6.2-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:76ef4c6e3332e6f7278142d791b28695adfce39735900fccef2a0f1d894f6b36"}, + {file = "gevent-20.6.2-pp27-pypy_73-win32.whl", hash = "sha256:3cb2f6978615d52e4e4e667b035c11a7272bb68b14d119faf1b138164b2f354f"}, + {file = "gevent-20.6.2.tar.gz", hash = "sha256:a23c2abf08e851c988723f6a2996d495f513a2c0dc70f9956af03af8debdb5d1"}, ] gevent-websocket = [ {file = "gevent-websocket-0.10.1.tar.gz", hash = "sha256:7eaef32968290c9121f7c35b973e2cc302ffb076d018c9068d2f5ca8b2d85fb0"}, diff --git a/pyproject.toml b/pyproject.toml index 669d4787..a97d67f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,10 +44,9 @@ opencv-python-headless = [ ] labthings = "0.6.7" pynpm = "^0.1.2" -camera-stage-mapping = {git = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git"} sangaboard = "^0.2" -gevent = "20.6.0" # Pinned version to guarantee piwheels wheel expiringdict = "^1.2.1" +camera-stage-mapping = "^0.1.2" [tool.poetry.extras] rpi = ["RPi.GPIO"]