From 13229d9b995bc02d63e50713cf23f46677ead912 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Thu, 2 Nov 2023 10:39:37 +0000 Subject: [PATCH 01/46] Command to run the server interactively It's sometimes helpful to run the server as openflexure-ws, there's now a command in the readme that matches (for now) the service definition. --- README.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 78777586..15734630 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The "server" is the main component of the OpenFlexure Microscope's software. It is responsible for controlling microscope hardware, data management, and allowing it to be controlled locally and over a network. This repository now includes the web client, which is served from the root of the Python web server. -This software runs on [Python-LabThings](https://github.com/labthings/python-labthings/), and so most non-microscope functionality is handled by that library. +This software runs on [LabThings-FastAPI](https://github.com/rwb27/labthings-fastapi/), and so most non-microscope functionality is handled by that library. ## Getting started @@ -62,18 +62,19 @@ To set up a development version of the software (most likely using emulated came * `cd openflexure-microscope-server` ### Set up the Python environment and run a test server -* (Optional) Set local Python version to match what is available on the Pi - * `pyenv init` (this may or may not be required, depending on how you installed `pyenv`) - * `pyenv install 3.7.3` - * `pyenv local 3.7.3` +* (Optional) Set local Python version to 3.11 * Create a virtual environment and activate it: * `python -m venv .venv` * `source .venv/bin/activate` (on Linux) or `.venv/Scripts/activate` (on Windows) - * `pip install --upgrade pip wheel pipenv` - * `pipenv install --dev` (This will install development dependencies. If you don't need these, `pipenv install` will get you just the dependencies needed to run the server, which takes about half the time.) -* Finally, run the server: - * You can use `ofm serve` or `ofm restart` on the Raspberry Pi to manage the server. - * To run the server locally, with dummy hardware, you can use `python -m openflexure_microscope.api.app` to start a development-mode Flask server on `localhost:5000` + * `pip install -e .[dev]` (This will install development dependencies. If you don't need these, there is probably a simpler way to run the server than cloning this repo.) +* Finally, run the server: currently you can do this with `sudo systemctl start openflexure-microscope-server` if it's pre-installed on a Raspberry Pi, or `uvicorn --port 5000 openflexure_microscope_server.server:app` to run locally. + +### Run the server manually on a Raspberry Pi +``` +cd /var/openflexure +sudo -u openflexure-ws PATH="/var/openflexure/application/openflexure-microscope-server/.venv/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" /var/openflexure/application/openflexure-microscope-server/.venv/bin/uvicorn --reload --reload-dir=./application --host 0.0.0.0 --port 5000 openflexure_microscope_server.server:app +``` + ### Set up the Javascript environment and build * The Flask web application, written in Python, serves a web application written in `Vue.js`. This is distributed as part of the built version of the server, hosted on our [build server](https://build.openflexure.org/openflexure-microscope-server/). From 79752a2a4cf09ce48c6ff693bdeb247d9402d3c6 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Thu, 2 Nov 2023 16:54:22 +0000 Subject: [PATCH 02/46] Camera settings for labthings-picamera2 I've updated URLs and tidied things a bit, so that we can now adjust the key camera settings with the new camera drivers. --- .../multiNumericSettingLine.vue | 121 +++++++++ .../numericArraySettingLine.vue | 127 +++++++++ .../genericComponents/numericSettingLine.vue | 125 +++++++++ .../settingsComponents/cameraSettings.vue | 248 +++--------------- .../cameraCalibrationSettings.vue | 116 ++++---- 5 files changed, 460 insertions(+), 277 deletions(-) create mode 100644 webapp/src/components/genericComponents/multiNumericSettingLine.vue create mode 100644 webapp/src/components/genericComponents/numericArraySettingLine.vue create mode 100644 webapp/src/components/genericComponents/numericSettingLine.vue diff --git a/webapp/src/components/genericComponents/multiNumericSettingLine.vue b/webapp/src/components/genericComponents/multiNumericSettingLine.vue new file mode 100644 index 00000000..4039b334 --- /dev/null +++ b/webapp/src/components/genericComponents/multiNumericSettingLine.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/webapp/src/components/genericComponents/numericArraySettingLine.vue b/webapp/src/components/genericComponents/numericArraySettingLine.vue new file mode 100644 index 00000000..348693d4 --- /dev/null +++ b/webapp/src/components/genericComponents/numericArraySettingLine.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/webapp/src/components/genericComponents/numericSettingLine.vue b/webapp/src/components/genericComponents/numericSettingLine.vue new file mode 100644 index 00000000..d06c55e6 --- /dev/null +++ b/webapp/src/components/genericComponents/numericSettingLine.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue b/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue index d161049a..277e0ae0 100644 --- a/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue +++ b/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue @@ -2,6 +2,9 @@
+

Automatic calibration

+ +

Manual camera settings

@@ -9,139 +12,42 @@
  • Pi Camera Settings
    -
    - -
    - -
    -
    - -
    - -
    - -
    -
    - -
    - -
    - -
    -
    - -
    - -
    - - - - -
    -
    + + +
  • -
  • Image Quality
    -
    -
    - -
    - -
    -
    - -
    - - -
    -
    + +
  • +
    - -
    - -

    Automatic calibration

    -
    @@ -197,9 +90,10 @@ @@ -109,7 +111,7 @@ methods: { } .numeric-setting-line-input { display: table-cell; - width:100%; + width: 100%; } .button-next-to-input { display: table-cell; diff --git a/webapp/src/components/genericComponents/numericArraySettingLine.vue b/webapp/src/components/genericComponents/numericArraySettingLine.vue index 348693d4..54ea22ae 100644 --- a/webapp/src/components/genericComponents/numericArraySettingLine.vue +++ b/webapp/src/components/genericComponents/numericArraySettingLine.vue @@ -4,10 +4,10 @@
    - + @@ -112,10 +114,10 @@ methods: { width: 100%; } .numeric-setting-line-input { - flex-grow: 1; - margin-left: 5px; - margin-right: 5px; - width: 6em; + flex-grow: 1; + margin-left: 5px; + margin-right: 5px; + width: 6em; } .button-next-to-input { flex-grow: 0; diff --git a/webapp/src/components/genericComponents/numericSettingLine.vue b/webapp/src/components/genericComponents/numericSettingLine.vue index d06c55e6..a4c8d553 100644 --- a/webapp/src/components/genericComponents/numericSettingLine.vue +++ b/webapp/src/components/genericComponents/numericSettingLine.vue @@ -3,9 +3,9 @@
    - + @@ -110,10 +112,10 @@ methods: { width: 100%; } .numeric-setting-line-input { - flex-grow: 1; - margin-left: 5px; - margin-right: 5px; - width: 6em; + flex-grow: 1; + margin-left: 5px; + margin-right: 5px; + width: 6em; } .button-next-to-input { flex-grow: 0; diff --git a/webapp/src/components/genericComponents/taskSubmitter.vue b/webapp/src/components/genericComponents/taskSubmitter.vue index 0c7ae4d2..ca316568 100644 --- a/webapp/src/components/genericComponents/taskSubmitter.vue +++ b/webapp/src/components/genericComponents/taskSubmitter.vue @@ -142,7 +142,10 @@ export default { if (task.status == "pending" || task.status == "running") { this.taskStarted = true; this.$emit("taskStarted", this.taskId); - this.startPolling(task.id, task.links.find(t => t.rel==self).href); + this.startPolling( + task.id, + task.links.find(t => t.rel == self).href + ); } } }); @@ -219,33 +222,32 @@ export default { var checkCondition = (resolve, reject) => { // If the condition is met, we're done! - axios.get( - this.taskUrl, - {baseURL: this.$store.getters.baseUri} - ).then(response => { - var result = response.data.status; - // If the task ends with success - if (result == "completed") { - resolve(response.data); - } - // If task ends with an error - else if (result == "error") { - // Pass the error string back with reject + axios + .get(this.taskUrl, { baseURL: this.$store.getters.baseUri }) + .then(response => { + var result = response.data.status; + // If the task ends with success + if (result == "completed") { + resolve(response.data); + } + // If task ends with an error + else if (result == "error") { + // Pass the error string back with reject - reject(new Error(response.data.output)); - } - // If task ends with termination - else if (result == "cancelled") { - // Pass a generic termination error back with reject + reject(new Error(response.data.output)); + } + // If task ends with termination + else if (result == "cancelled") { + // Pass a generic termination error back with reject - reject(new Error("Task cancelled")); - } else { - // Since the task is still running, we can update the progress bar - this.progress = response.data.progress; - // Check again after timeout - setTimeout(checkCondition, interval, resolve, reject); - } - }); + reject(new Error("Task cancelled")); + } else { + // Since the task is still running, we can update the progress bar + this.progress = response.data.progress; + // Check again after timeout + setTimeout(checkCondition, interval, resolve, reject); + } + }); }; return new Promise(checkCondition); diff --git a/webapp/src/components/tabContentComponents/captureComponents/paneCapture.vue b/webapp/src/components/tabContentComponents/captureComponents/paneCapture.vue index e1881c1c..7636ac00 100644 --- a/webapp/src/components/tabContentComponents/captureComponents/paneCapture.vue +++ b/webapp/src/components/tabContentComponents/captureComponents/paneCapture.vue @@ -221,7 +221,10 @@
    -
    +