Commit de7f4f6d authored by Joel Collins's avatar Joel Collins
Browse files

Drafted integrated slide scan

parent 2ce58f2a
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -55,6 +55,15 @@
      >
        <i class="material-icons">camera_alt</i>
      </tabIcon>
      <tabIcon
        id="slidescan-tab-icon"
        tab-i-d="slidescan"
        :require-connection="true"
        :current-tab="currentTab"
        @set-tab="setTab"
      >
        <i class="material-icons">camera_alt</i>
      </tabIcon>
      <tabIcon
        id="settings-tab-icon"
        tab-i-d="settings"
@@ -125,6 +134,13 @@
      >
        <captureContent />
      </tabContent>
      <tabContent
        tab-i-d="slidescan"
        :require-connection="true"
        :current-tab="currentTab"
      >
        <slideScanContent />
      </tabContent>
      <tabContent
        tab-i-d="settings"
        :require-connection="false"
@@ -170,6 +186,7 @@ import tabContent from "./genericComponents/tabContent";
// Import new content components
import navigateContent from "./tabContentComponents/navigateContent.vue";
import captureContent from "./tabContentComponents/captureContent.vue";
import slideScanContent from "./tabContentComponents/slideScanContent.vue";
import viewContent from "./tabContentComponents/viewContent.vue";
import settingsContent from "./tabContentComponents/settingsContent.vue";
import galleryContent from "./tabContentComponents/galleryContent.vue";
+312 −0
Original line number Diff line number Diff line
<template>
  <div class="medscan">
    <div v-show="!scanUri">No scan extension found</div>
    <div v-show="scanUri">
      <h1>Sample Scan Wizard</h1>

      <form v-on:submit.prevent v-on:keyup.enter="increment()">
        <div id="step-user" v-show="stepValue==0">
          <h2>User information (1/4)</h2>

          <label for="username">Your name:</label>
          <input type="text" id="username" name="username" v-model="username" required />
          <br />
          <label for="currentTime">Current time (check this is correct):</label>
          <input
            type="datetime-local"
            id="currentTime"
            name="currentTime"
            v-model="currentTimeForm"
          />
        </div>

        <div id="step-patient" v-show="stepValue==1">
          <h2>Patient information (2/4)</h2>

          <label for="patientID">Patient ID:</label>
          <input type="text" id="patientID" name="patientID" v-model="patientID" required />
          <br />
        </div>

        <div id="step-sample" v-show="stepValue==2">
          <h2>Sample information (3/4)</h2>

          <label>Sample type:</label>
          <br />
          <input type="radio" id="typeThin" value="thin" v-model="sampleType" />
          <label for="typeThin">Thin smear</label>
          <br />
          <input type="radio" id="typeThick" value="thick" v-model="sampleType" />
          <label for="typeThick">Thick smear</label>
          <br />
        </div>

        <div id="step-scan" v-show="stepValue==3">
          <h2>Start scan (4/4)</h2>

          <label>Check details:</label>
          <p>
            <b>Your name:</b>
            {{ username }}
          </p>
          <p>
            <b>Patient ID:</b>
            {{ patientID }}
          </p>
          <p>
            <b>Sample type:</b>
            {{ sampleType }}
          </p>
        </div>
      </form>

      <div id="form-stepper">
        <p class="warning">{{ message }}</p>
          <taskSubmitter
            v-if="scanUri"
            v-show="stepValue == 3"
            :base-url="baseURL"
            :submit-url="scanUri"
            :submit-data="payload"
            submit-label="Start scan"
            @submit="scanRunning=true"
            @response="scanRunning=false"
            @error="scanRunning=false"
          ></taskSubmitter>
        <br />

        <div class="grid-container">
          <button
            :disabled="stepValue <= 0 || scanRunning"
            type="button"
            v-on:click="decrement()"
          >Previous</button>
          <button
            :disabled="stepValue >= 3 || scanRunning"
            type="button"
            v-on:click="increment()"
          >Next</button>
        </div>
        <p>
          <button
            v-show="stepValue == 3"
            :disabled="scanRunning"
            type="button"
            v-on:click="restart()"
          >Restart</button>
        </p>
      </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import taskSubmitter from "../genericComponents/taskSubmitter";

export default {
  components: {
    taskSubmitter
  },

  data: function() {
    return {
      scanUri: null,
      stepValue: 0,
      hostDeviceName: null,
      message: null,
      username: "",
      currentTime: this.getLocalDatetimeString(),
      patientID: "",
      sampleType: "thin",
      scanRunning: false,
      baseURL: `${window.location.origin}/api/v2`
    };
  },

  watch: {
    baseURL: function (val) {
      if (this.baseURL) {
        this.updateScanUri();
      } else {
        this.message = "No baseURL given";
      }
    },
  },

  mounted: function() {
    if (this.baseURL) {
      this.updateScanUri();
    } else {
      this.message = "No baseURL given";
    }
  },

  methods: {
    updateScanUri: function() {
      axios
        .get(this.pluginsUri) // Get a list of plugins
        .then(response => {
          console.log(response);
          var plugins = response.data;
          var foundExtension = plugins.find(
            e => e.title === "org.openflexure.scan"
          );
          // if ScanPlugin is enabled
          if (foundExtension) {
            // Get plugin action link
            this.scanUri = foundExtension.links.tile.href;
          }
        })
        .catch(error => {
          console.log(error); // Let mixin handle error
        });
    },

    decrement: function() {
      if (this.stepValue > 0) {
        this.stepValue = this.stepValue - 1;
      }
    },

    increment: function() {
      // Validate sections
      if (this.stepValue == 0) {
        if (!this.username) {
          this.message = "Please enter your name";
          return false;
        }
      }
      if (this.stepValue == 1) {
        if (!this.patientID) {
          this.message = "Please enter a patient ID";
          return false;
        }
      }
      // Upper bound on section number
      if (this.stepValue < 3) {
        this.stepValue = this.stepValue + 1;
        this.message = "";
        return true;
      }
    },

    restart: function() {
      this.stepValue = 0;
      this.patientID = "";
      this.currentTime = this.getLocalDatetimeString();
    },

    getLocalDatetimeString: function() {
      var dt = new Date();
      var tzo = -dt.getTimezoneOffset(),
        dif = tzo >= 0 ? "+" : "-",
        pad = function(num) {
          var norm = Math.floor(Math.abs(num));
          return (norm < 10 ? "0" : "") + norm;
        };
      return (
        dt.getFullYear() +
        "-" +
        pad(dt.getMonth() + 1) +
        "-" +
        pad(dt.getDate()) +
        "T" +
        pad(dt.getHours()) +
        ":" +
        pad(dt.getMinutes()) +
        ":" +
        pad(dt.getSeconds()) +
        dif +
        pad(tzo / 60) +
        ":" +
        pad(tzo % 60)
      );
    }
  },

  computed: {
    pluginsUri: function() {
      return `${this.baseURL}/extensions`;
    },

    currentTimeForm: {
      get() {
        // Chop the timezone information from the end
        return this.currentTime.substr(0, 19);
      },
      set(val) {
        console.log(val);
        // Get timezone
        var dt = new Date();
        var tzo = -dt.getTimezoneOffset(),
          dif = tzo >= 0 ? "+" : "-",
          pad = function(num) {
            var norm = Math.floor(Math.abs(num));
            return (norm < 10 ? "0" : "") + norm;
          };
        // Stick to the end of the new timestring from the form
        this.currentTime = val + dif + pad(tzo / 60) + ":" + pad(tzo % 60);
      }
    },

    payload: {
      get() {
        return {
          filename: `${this.patientID}_${this.sampleType}`,
          temporary: false,
          bayer: false,
          grid: [10, 10, 9],
          stride_size: [800, 600, 10],
          fast_autofocus: true,
          autofocus_dz: 2000,
          use_video_port: false,
          annotations: {
            patientID: this.patientID,
            username: this.username,
            clientDatetime: this.currentTime
          },
          tags: ["medscan"]
        };
      }
    }
  }
};
</script>

<style>
.medscan {
  font-family: sans-serif;
  color: #444;
  text-align: left;
}

input[type="text"],
input[type="datetime-local"] {
  display: block;
  margin: 0 10px 0 0;
  width: 100%;
  height: 25px;
}

button {
  display: inline-block;
  box-sizing: border-box;
  margin: 0 10px 0 0;
  width: 100%;
  height: 25px;
  min-width: 100px;
}

.grid-container {
  display: grid;
  grid-template-columns: auto auto;
  grid-column-gap: 10px;
}

.warning {
  color: #c11;
  font-weight: bold;
  text-align: center;
}
</style>
 No newline at end of file
+25 −0
Original line number Diff line number Diff line
<template>
  <!-- Grid managing tab content -->
  <div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove">
    <div class="control-component">
      <paneSlideScan />
    </div>
    <div class="view-component uk-width-expand">
      <streamDisplay />
    </div>
  </div>
</template>

<script>
import paneSlideScan from "../controlComponents/paneSlideScan";
import streamDisplay from "../viewComponents/streamDisplay.vue";

export default {
  name: "NavigateContent",

  components: {
    paneSlideScan,
    streamDisplay
  }
};
</script>
+7 −7
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ webargs = "^6.0.0"
zeroconf = ">=0.24.5,<0.29.0"

[package.source]
reference = "c79e6f28d5ffbd61dcfe7fc94130db604cdb4e2d"
reference = "bf41b5009e8e0e465222399f38c0cd2104dbd0b7"
type = "git"
url = "https://github.com/labthings/python-labthings.git"
[[package]]
@@ -718,16 +718,16 @@ description = "Declarative parsing and validation of HTTP request objects, with
name = "webargs"
optional = false
python-versions = ">=3.5"
version = "6.1.0"
version = "6.1.1"

[package.dependencies]
marshmallow = ">=2.15.2"

[package.extras]
dev = ["pytest", "webtest (2.0.35)", "webtest-aiohttp (2.0.0)", "pytest-aiohttp (>=0.3.0)", "Flask (>=0.12.2)", "Django (>=1.11.16)", "bottle (>=0.12.13)", "tornado (>=4.5.2)", "pyramid (>=1.9.1)", "webapp2 (>=3.0.0b1)", "falcon (>=2.0.0)", "aiohttp (>=3.0.0)", "mypy (0.770)", "flake8 (3.7.9)", "flake8-bugbear (20.1.4)", "pre-commit (>=1.20,<3.0)", "tox", "mock"]
docs = ["Sphinx (3.0.3)", "sphinx-issues (1.2.0)", "sphinx-typlog-theme (0.8.0)", "Flask (>=0.12.2)", "Django (>=1.11.16)", "bottle (>=0.12.13)", "tornado (>=4.5.2)", "pyramid (>=1.9.1)", "webapp2 (>=3.0.0b1)", "falcon (>=2.0.0)", "aiohttp (>=3.0.0)"]
dev = ["pytest", "webtest (2.0.35)", "webtest-aiohttp (2.0.0)", "pytest-aiohttp (>=0.3.0)", "Flask (>=0.12.2)", "Django (>=1.11.16)", "bottle (>=0.12.13)", "tornado (>=4.5.2)", "pyramid (>=1.9.1)", "webapp2 (>=3.0.0b1)", "falcon (>=2.0.0)", "aiohttp (>=3.0.0)", "mypy (0.782)", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox", "mock"]
docs = ["Sphinx (3.2.1)", "sphinx-issues (1.2.0)", "sphinx-typlog-theme (0.8.0)", "Flask (>=0.12.2)", "Django (>=1.11.16)", "bottle (>=0.12.13)", "tornado (>=4.5.2)", "pyramid (>=1.9.1)", "webapp2 (>=3.0.0b1)", "falcon (>=2.0.0)", "aiohttp (>=3.0.0)"]
frameworks = ["Flask (>=0.12.2)", "Django (>=1.11.16)", "bottle (>=0.12.13)", "tornado (>=4.5.2)", "pyramid (>=1.9.1)", "webapp2 (>=3.0.0b1)", "falcon (>=2.0.0)", "aiohttp (>=3.0.0)"]
lint = ["mypy (0.770)", "flake8 (3.7.9)", "flake8-bugbear (20.1.4)", "pre-commit (>=1.20,<3.0)"]
lint = ["mypy (0.782)", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"]
tests = ["pytest", "webtest (2.0.35)", "webtest-aiohttp (2.0.0)", "pytest-aiohttp (>=0.3.0)", "Flask (>=0.12.2)", "Django (>=1.11.16)", "bottle (>=0.12.13)", "tornado (>=4.5.2)", "pyramid (>=1.9.1)", "webapp2 (>=3.0.0b1)", "falcon (>=2.0.0)", "aiohttp (>=3.0.0)", "mock"]

[[package]]
@@ -1220,8 +1220,8 @@ urllib3 = [
    {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
]
webargs = [
    {file = "webargs-6.1.0-py2.py3-none-any.whl", hash = "sha256:cf0b5e2fdfb81f28b9332fce15621069d3fbc910a01c7ca8a5e166371699927b"},
    {file = "webargs-6.1.0.tar.gz", hash = "sha256:ebb47fb35c3c4fc764213a17d1686e82fec54759ebed2b0715907d566668bb3f"},
    {file = "webargs-6.1.1-py2.py3-none-any.whl", hash = "sha256:2ead6ce38559152043ab4ada4d389aef6c804b0c169482e7c92b3f498f690b2c"},
    {file = "webargs-6.1.1.tar.gz", hash = "sha256:412ecadd977afdea0ed6fa5f5b65ddd13a099269e622ec537f9c74c443ce4d0b"},
]
werkzeug = [
    {file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"},
+1 −1

File changed.

Contains only whitespace changes.