diff --git a/diagnosis_service/svc/database_connection.py b/diagnosis_service/svc/database_connection.py
index 4b64b94df2b4249e2af34da7d1d60c71de01fa60..d35f338e806e419c36dc4d61c33bb918b0db3d21 100644
--- a/diagnosis_service/svc/database_connection.py
+++ b/diagnosis_service/svc/database_connection.py
@@ -143,3 +143,21 @@ class DigpathDatabase:
}
return results
+
+ def get_requests(self):
+ cursor = self._db.cursor().execute('SELECT * FROM requests')
+ results = []
+ for i in cursor.fetchall():
+ item = {
+ 'request_id': i[0],
+ 'file': i[1],
+ 'diagnosis': i[2],
+ 'total_chips': i[3],
+ 'mild': i[4],
+ 'moderate': i[5],
+ 'severe': i[6],
+ 'status': i[7],
+ 'timestamp': i[8]
+ }
+ results.append(item)
+ return results
diff --git a/diagnosis_service/svc/run.py b/diagnosis_service/svc/run.py
index af895e47af6ed5b50b91171101f87c84dead9e3b..6c9a16803ea480eeb7e2448476fa091a7c7d0430 100644
--- a/diagnosis_service/svc/run.py
+++ b/diagnosis_service/svc/run.py
@@ -2,7 +2,6 @@ import json
import uuid
import boto3
-import mysql.connector
from flask import Flask, request, jsonify
from database_connection import DigpathDatabase
@@ -40,7 +39,7 @@ def get_slice_percentage(slice_num):
return start, stop
-@app.route('/diagnose')
+@app.route('/diagnose', methods=['POST'])
def diagnoseEndpoint():
request_id = str(uuid.uuid4())
@@ -73,14 +72,15 @@ def diagnoseEndpoint():
}
return jsonify(response)
-@app.route('/request_info')
-def getDiagnosisEndpoint():
-
- content = request.json
- print(f"Getting info for: {content}")
+@app.route('/request_info/<string:request_id>')
+def getDiagnosisEndpoint(request_id):
+ request_info = DIGPATH_DB.get_request_info(request_id)
+ return jsonify(request_info)
- request_info = DIGPATH_DB.get_request_info(content['request_id'])
+@app.route('/request_info')
+def getDiagnoses():
+ request_info = DIGPATH_DB.get_requests()
return jsonify(request_info)
if __name__ == '__main__':
- app.run(host='0.0.0.0')
+ app.run(host='0.0.0.0', debug=True)
diff --git a/front_end/dpath.py b/front_end/dpath.py
index d3957eaeba0484dcbd756e11dd48d276c30a6a2a..86907dd86b4672c1c4f4eabe0b0989bea570da24 100644
--- a/front_end/dpath.py
+++ b/front_end/dpath.py
@@ -1,4 +1,4 @@
-from flask import Flask, render_template, url_for, flash, redirect, request
+from flask import Flask, render_template, url_for, flash, redirect, request, send_file
import requests
from werkzeug.utils import secure_filename
@@ -6,7 +6,7 @@ from werkzeug.utils import secure_filename
app = Flask(__name__)
UPLOAD_FOLDER = 'static/uploads/'
-REPORTS_SERVICE_URL = 'http://127.0.0.1:5000'
+REPORTS_SERVICE_URL = 'http://127.0.0.1:5001'
app.secret_key = "secret key"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@@ -16,10 +16,6 @@ ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif', 'tif'])
BASE_URL = 'dpath'
-def allowed_file(filename):
- return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
-
-
@app.route(f'/{BASE_URL}/')
def home():
return render_template('home.html')
@@ -34,13 +30,14 @@ def term2():
@app.route(f'/{BASE_URL}/reports')
def reports():
reports = requests.get(f'{REPORTS_SERVICE_URL}/dpath/report').json()
+ print(reports)
return render_template('reports.html', reports=reports)
@app.route(f'/{BASE_URL}/reports/<string:report_id>')
def get_report(report_id):
report = requests.get(f'{REPORTS_SERVICE_URL}/dpath/report/{report_id}').json()
- return render_template('reportDetail.html', report=report)
-
+ images = requests.get(f'{REPORTS_SERVICE_URL}/dpath/report/{report_id}/images').json()
+ return render_template('reportDetail.html', report=report, images=images, image_name=image_name, upload_service_url=upload_service_url)
@app.route('/', methods=['GET', "POST"])
def upload_image():
@@ -54,17 +51,28 @@ def upload_image():
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
report = post_file(request)
- return render_template('reportDetail.html', report=report)
+ return get_report(report['request_id'])
else:
flash('Allowed image types are - png, jpg, jpeg, gif, tif')
return redirect(request.url)
-
@app.route('/display/<filename>')
def display_image(filename):
return redirect(url_for('static', filename='uploads/' + filename), code=301)
+def allowed_file(filename):
+ return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
+
+
def post_file(request) :
response = requests.post(f'{REPORTS_SERVICE_URL}/{BASE_URL}/report/image', files=request.files).json()
- return response
\ No newline at end of file
+ return response
+
+def image_name(image_url) :
+ image_name = image_url.split('/')[-1]
+ return image_name
+
+def upload_service_url(image_url) :
+ return image_url.replace('..', REPORTS_SERVICE_URL)
+
\ No newline at end of file
diff --git a/front_end/static/js/popup.js b/front_end/static/js/popup.js
new file mode 100644
index 0000000000000000000000000000000000000000..a37245225376a8b6ba33bd38c5af54a3633c0784
--- /dev/null
+++ b/front_end/static/js/popup.js
@@ -0,0 +1,40 @@
+function showImage(imageUrl) {
+ dialog = document.getElementById("imageDialog");
+ image = createImage(imageUrl);
+ dialog.appendChild(image);
+ buttonWrapper = document.createElement("div");
+ buttonWrapper.classList.add('dialog-button-wrapper');
+ buttonWrapper.appendChild(createCloseButton());
+ buttonWrapper.appendChild(createNewTabLink(imageUrl));
+ dialog.appendChild(buttonWrapper);
+ dialog.showModal();
+}
+
+function createImage(imageUrl) {
+ image = document.createElement('img');
+ image.src = imageUrl;
+ return image
+}
+
+function createCloseButton() {
+ closeButton = document.createElement('button');
+ closeButton.classList.add("dialog-button");
+ closeButton.onclick = function() {
+ dialog.close();
+ while (dialog.hasChildNodes()) {
+ dialog.removeChild(dialog.firstChild);
+ }
+ }
+ closeButton.textContent = 'Close';
+ return closeButton;
+}
+
+function createNewTabLink(imageUrl) {
+ button = document.createElement('button');
+ button.onclick = function() {
+ window.open(imageUrl);
+ }
+ button.textContent = 'View in New Tab';
+ button.classList.add('dialog-button');
+ return button;
+}
\ No newline at end of file
diff --git a/front_end/static/styles/style.css b/front_end/static/styles/style.css
index 5bc2f3b2c2a8ea0a247f0e569b0dc31717e6c002..0dbd5e317a92aff96dc789810ca6fb0272ca26ad 100644
--- a/front_end/static/styles/style.css
+++ b/front_end/static/styles/style.css
@@ -1,10 +1,42 @@
body {
width: 100%;
+ background-color: #FAF9F6;
+}
+
+title {
+ display: block;
+}
+
+.title-wrapper {
+ width: 100%;
+ text-align: center;
+ display:block;
}
.container {
width: 100%;
text-align: center;
+ margin-top: 20px;
+ display: flex;
+}
+
+.nav-link {
+ color: white;
+ font-weight: bold;
+}
+
+.navbar-brand {
+ color: white;
+ font-weight: bold;
+}
+
+.bg-primary {
+ color: white;
+}
+
+.navbar {
+ background-color: #e3f2fd;
+ padding-left: 10px;
}
.report-table {
@@ -17,10 +49,15 @@ th {
background-color: lightskyblue;
}
+tr {
+ transition-duration: .2s;
+}
+
tr:hover {
background-color: lightgray;
}
+
td {
padding-left: 5px;
padding-right: 5px;
@@ -32,4 +69,76 @@ td {
.right {
text-align: right;
+}
+
+.table-link {
+ text-decoration: none;
+}
+
+#imageDisplay {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ background-color: blue;
+ text-align: center;
+ top: 0;
+}
+
+img {
+ max-width: 100%;
+ max-height: 100%;
+}
+
+.hidden {
+ display: none;
+}
+
+.dialog-button {
+ border: 2px solid white;
+ border-color: white;
+ border-radius: 15px;
+ box-shadow: none;
+ background-color: #0d6efd;
+ color: white;
+ font-weight: bold;
+ padding: 10px;
+}
+
+.dialog-button-wrapper {
+ width: 100%;
+ margin-top: 20px;
+ display: flex;
+ text-align: center;
+}
+
+dialog {
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ border-radius: 15px;
+ border-color: lightgray;
+}
+
+.left-panel {
+ width: 40%;
+}
+
+.right-panel {
+ width: 60%;
+}
+
+.image-table {
+ margin-left: 30px;
+}
+
+.report-detail-table {
+ width: 100%;
+}
+
+.detail-left {
+ width: 30%;
+}
+
+.detail-right {
+ width: 70%;
}
\ No newline at end of file
diff --git a/front_end/templates/home.html b/front_end/templates/home.html
index e40bed638318b3a1e5b6fa97e22aa99f65deb3a9..3c1259c54c90aa0bee7f01a7ab863fca21976d2f 100644
--- a/front_end/templates/home.html
+++ b/front_end/templates/home.html
@@ -1,14 +1,16 @@
<!doctype html>
<html lang="en">
-<center>
+
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slide Analyzer</title>
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
+ {% include 'includes/stylesload.html' %}
</head>
+<center>
<body>
{% include 'includes/navbar.html' %}
+ <div class="">
<h1>Welcome to the Digital Pathology Slide Analyzer.</h1>
<br>
<h2>Please select a file to upload.</h2>
@@ -32,7 +34,7 @@
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
- <br>
+ <!-- <br>
<h2>
Sample id: c1471950-71a5-11ed-9ddb-1267f16e00ed
</h2>
@@ -46,8 +48,9 @@
Chip Predictions:
Mild: 806
Severe: 846
- </h2>
+ </h2> -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
+ </div>
</body>
</center>
</html>
\ No newline at end of file
diff --git a/front_end/templates/includes/imageList.html b/front_end/templates/includes/imageList.html
new file mode 100644
index 0000000000000000000000000000000000000000..0f5dac2ee6a84729c25d33570b88d389d65049ec
--- /dev/null
+++ b/front_end/templates/includes/imageList.html
@@ -0,0 +1,12 @@
+<div>
+ <table class="image-table">
+ <th class="left bg-primary">Chips</th>
+ {% for image in images %}
+ <tr>
+ <td class="left">
+ <a class="table-link" href="javascript:showImage('{{ upload_service_url(image) }}')" name="{{ image }}">{{ image_name(image) }}</a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+</div>
\ No newline at end of file
diff --git a/front_end/templates/includes/imagePopup.html b/front_end/templates/includes/imagePopup.html
new file mode 100644
index 0000000000000000000000000000000000000000..eeefd3553555ee7c1f30704b640ba4b720acbb0e
--- /dev/null
+++ b/front_end/templates/includes/imagePopup.html
@@ -0,0 +1,3 @@
+<div id="imageDisplay" class="hidden">
+ <img src="http://127.0.0.1:5001/dpath/report/1939b367-0c4d-4689-8f39-8fdad55226c4/image/reportimage123.png">
+</div>
\ No newline at end of file
diff --git a/front_end/templates/includes/navbar.html b/front_end/templates/includes/navbar.html
index a9474ccb0ba4e90cb08c85df624400180d17f2f4..08f05266cd9254f67d697196a873416113e750bb 100644
--- a/front_end/templates/includes/navbar.html
+++ b/front_end/templates/includes/navbar.html
@@ -1,8 +1,8 @@
-<nav class="navbar navbar-expand-lg navbar-light bg-light">
+<nav class="navbar navbar-expand-lg bg-primary">
<a class="navbar-brand" href="#">Digital Pathology</a>
<ul class="navbar-nav mr-auto">
<li class="nav-item">
- <a class="nav-link" href="{{ url_for('home')}}">Home</a>
+ <a class="nav-link" href="{{ url_for('home')}}">Upload</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('reports')}}">Reports</a>
diff --git a/front_end/templates/includes/reportDetail.html b/front_end/templates/includes/reportDetail.html
index a1e0ffb4fcb74921ef2d87e8c60a80a99f65c96e..99b24670b078a1331e427136b10af7e54c5d11ae 100644
--- a/front_end/templates/includes/reportDetail.html
+++ b/front_end/templates/includes/reportDetail.html
@@ -1,28 +1,36 @@
{% block content %}
-<table class="report-detail-table">
- <th class="left">Details</th>
- <tr>
- <td>Id</td>
- <td>{{ report.id }}</td>
- </tr>
- <tr>
- <td>Report Date</td>
- <td>{{ report.report.runDate }}</td>
- </tr>
- <tr>
- <td>Report Status</td>
- <td>Todo</td>
- </tr>
- <tr>
- <td>Diagnosis</td>
- <td>{{ report.report.diagnosis }}</td>
- </tr>
- <tr>
- <td>Mild Chips</td>
- <td>{{ report.report.chipPredictions.mild}}</td>
- </tr>
- <tr>
- <td>Severe Chips</td>
- <td>{{ report.report.chipPredictions.severe}}</td>
- </tr>
+<div class="panel panel-default">
+ <table class="report-detail-table ">
+ <th class="left bg-primary detail-left">Details</th>
+ <th class="left bg-primary detail-right"></th>
+ <tr>
+ <td>Id</td>
+ <td>{{ report.request_id }}</td>
+ </tr>
+ <tr>
+ <td>Report Date</td>
+ <td>{{ report.timestamp }}</td>
+ </tr>
+ <tr>
+ <td>Report Status</td>
+ <td>{{ report.status }}</td>
+ </tr>
+ <tr>
+ <td>Diagnosis</td>
+ <td>{{ report.diagnosis }}</td>
+ </tr>
+ <tr>
+ <td>Mild Chips</td>
+ <td>{{ report.mild}}</td>
+ </tr>
+ <tr>
+ <td>Moderate Chips</td>
+ <td>{{ report.moderate}}</td>
+ </tr>
+ <tr>
+ <td>Severe Chips</td>
+ <td>{{ report.severe}}</td>
+ </tr>
+ </table>
+</div>
{% endblock %}
\ No newline at end of file
diff --git a/front_end/templates/includes/reports.html b/front_end/templates/includes/reports.html
index 2186ea15abd8af6c2ca9c080a16fbccfdc580f54..7a798f37e8473443d1dd07eb7088520837b664ba 100644
--- a/front_end/templates/includes/reports.html
+++ b/front_end/templates/includes/reports.html
@@ -1,17 +1,19 @@
{% block content %}
-<h1>{% block title %} Reports {% endblock %}</h1>
+<!-- <div class="title-wrapper">
+ <h1>Reports</h1>
+</div> -->
<table class="report-table">
- <th class="left">Id</th>
- <th class="left">Status</th>
- <th class="right">Run Date</th>
+ <th class="left bg-primary">Id</th>
+ <th class="left bg-primary">Status</th>
+ <th class="right bg-primary">Run Date</th>
{% for report in reports %}
<tr>
<td class="left">
- <a href="{{ url_for('get_report', report_id=report.id)}}">{{ report.id }}</a>
+ <a class="table-link" href="{{ url_for('get_report', report_id=report.request_id)}}">{{ report.request_id }}</a>
</td>
- <td class="left">Completed</td>
- <td class="right">{{ report.report.runDate }}</td>
+ <td class="left">{{ report.status }}</td>
+ <td class="right">{{ report.timestamp }}</td>
</tr>
{% endfor %}
</table>
diff --git a/front_end/templates/includes/scriptsload.html b/front_end/templates/includes/scriptsload.html
new file mode 100644
index 0000000000000000000000000000000000000000..830e21f2ce2be86346aee6c7fa4343c547b56833
--- /dev/null
+++ b/front_end/templates/includes/scriptsload.html
@@ -0,0 +1 @@
+<script src="{{ url_for('static', filename='js/popup.js') }}"></script>
\ No newline at end of file
diff --git a/front_end/templates/reportDetail.html b/front_end/templates/reportDetail.html
index cbe840b1fbfd4a3e88386000a5fcf72f6fbd3256..c3cad108d56931e24970a4b3c5b05548cdcff6e1 100644
--- a/front_end/templates/reportDetail.html
+++ b/front_end/templates/reportDetail.html
@@ -5,9 +5,17 @@
{% include 'includes/stylesload.html' %}
</head>
+{% include 'includes/scriptsload.html' %}
+
<body>
{% include 'includes/navbar.html' %}
<div class="container">
- {% include 'includes/reportDetail.html' %}
+ <div class="left-panel">
+ {% include 'includes/reportDetail.html' %}
+ </div>
+ <div class="right-panel">
+ {% include 'includes/imageList.html' %}
+ </div>
+ <dialog id="imageDialog"></dialog>
</div>
</body>
\ No newline at end of file
diff --git a/front_end/templates/reports.html b/front_end/templates/reports.html
index b579b6b5d15bc5ede0e53864f887b7130ea004b1..d45f0a3340063983a478d3a56d6e7194bc9d2767 100644
--- a/front_end/templates/reports.html
+++ b/front_end/templates/reports.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Reports</title>
+ <title>Reports</title>
{% include 'includes/stylesload.html' %}
</head>
diff --git a/upload_service/app.py b/upload_service/app.py
index c1e35219258c75ed31bcf2c42a816fb4ae15e6f6..136f07fd68add22d635f00a2104c81d5a5472360 100644
--- a/upload_service/app.py
+++ b/upload_service/app.py
@@ -1,8 +1,9 @@
from flask import Flask
from flask import jsonify
from flask import request
+from flask import send_file
# from s3_provider import Provider
-from test_report_provider import Provider
+from diagnosis_provider import Provider
from fake_model import LearningModel as Model
import uuid
@@ -30,19 +31,32 @@ def get_reports() :
response.status_code = 200
return response
+@app.route(f'/{PREFIX}/report/<string:report_id>/images', methods=['GET'])
+def get_images(report_id) :
+ provider = Provider()
+ response = jsonify(provider.get_images(report_id))
+ response.status_code = 200
+ return response
+
+@app.route(f'/{PREFIX}/report/<string:report_id>/image/<string:file_name>', methods=['GET'])
+def get_image(report_id, file_name) :
+ provider = Provider()
+ path = provider.get_image_path(file_name)
+ return send_file(
+ path,
+ download_name=file_name,
+ mimetype='image/png'
+ )
+
@app.route(f'/{PREFIX}/report/image', methods=['POST'])
def upload_image():
- print("reached")
response = validate_request(request)
if response.status_code == 400:
return response
provider = Provider()
id = uuid.uuid1()
- response = jsonify(provider.create_report(""))
- # response = jsonify(Model(id).start())
- response.status_code = 201
- return response
+ return jsonify(provider.save_binary(request.files['file']))
def validate_request(request):
response = jsonify({'message' : 'File successfully uploaded'})
@@ -52,12 +66,9 @@ def validate_request(request):
response = jsonify({'message' : 'No file part in the request'})
response.status_code = 400
return response
+
+ file = request.files['file']
- file = file = request.files['file']
- # if invalid_extension(file.filename.rsplit('.', 1)[1].lower()):
- # response = jsonify({'message' : 'Allowed file types are png, tiff'})
- # response.status_code = 400
- # return response
if invalid_filename(file):
response = jsonify({'message' : 'No file selected for uploading'})
response.status_code = 400
diff --git a/upload_service/diagnosis_provider.py b/upload_service/diagnosis_provider.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c37d44fe6807c21c09e9e1c6bd4ede81575ed41
--- /dev/null
+++ b/upload_service/diagnosis_provider.py
@@ -0,0 +1,40 @@
+import requests
+from PIL import Image
+import os
+from base64 import b64encode
+
+BASE_URL = 'http://127.0.0.1:5000'
+SAVE_DIRECTORY = 'C:\\Users\\Dave\\OneDrive\\Documents\\Capstone\\data\\'
+
+
+class Provider:
+
+ def save_binary(self, data):
+ url = BASE_URL + '/diagnose'
+ file_name = self.__save_local_file(data)
+ request = {'file': file_name}
+ return requests.post(url, json=request).json()
+
+ def get_report(self, id):
+ url = BASE_URL + '/request_info/' + id
+ return requests.get(url).json()
+
+ def get_reports(self):
+ url = BASE_URL + '/request_info'
+ return requests.get(url).json()
+
+ def get_images(self, report_id):
+ response = []
+ for _ in range(50) :
+ response.append(f'../dpath/report/{report_id}/image/reportimage123.png')
+ return response
+
+ def get_image_path(self, image_name):
+ return SAVE_DIRECTORY + image_name
+
+ def __save_local_file(self, file):
+ file_name = 'reportimage123.png'
+ new_file = open(SAVE_DIRECTORY + file_name, 'wb')
+ new_file.write(file.stream.read())
+ new_file.close()
+ return file_name
\ No newline at end of file