Skip to content

Commit

Permalink
added socketio, logging etc. Added old frontend for further modificat…
Browse files Browse the repository at this point in the history
…ions.
  • Loading branch information
lext committed Nov 23, 2019
1 parent b5ad69e commit 0faf132
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 29 deletions.
1 change: 1 addition & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ fi
if [ ! -d "snapshots_knee_grading" ]; then
sh ./fetch_snapshots.sh
fi
mkdir -p logs

docker-compose -f ./docker/docker-compose-$1.yml down
docker-compose -f ./docker/docker-compose-$1.yml build
Expand Down
13 changes: 10 additions & 3 deletions docker/docker-compose-cpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ services:
source: ../snapshots_release_kneel # The snapshots are stored in the root directory
target: /snapshots/
read_only: true
- type: bind
source: ../logs
target: /logs/
entrypoint: ["python", "-u", "-m", "kneel.inference.app",
"--lc_snapshot_path", "/snapshots/lext-devbox_2019_07_14_16_04_41",
"--hc_snapshot_path", "/snapshots/lext-devbox_2019_07_14_19_25_40",
"--refine", "True", "--mean_std_path", "/snapshots/mean_std.npy",
"--deploy", "True", "--device", "cpu", "--port", "5000"]
"--deploy", "True", "--device", "cpu", "--port", "5000", "--logs", "/logs/kneel-cpu.log"]
deepknee-backend:
depends_on:
- kneel
Expand All @@ -27,8 +30,12 @@ services:
source: ../snapshots_knee_grading/ # The snapshots are stored in the root directory
target: /snapshots/
read_only: true
- type: bind
source: ../logs
target: /logs/
environment:
- KNEEL_ADDR=http://kneel:5000
entrypoint: ["python", "-m", "ouludeepknee.inference.app",
"--snapshots_path", "/snapshots/",
"--device", "cpu", "--deploy", "True"]
"--snapshots_path", "/snapshots/", "--device", "cpu", "--deploy", "True",
"--port", "5001",
"--logs", "/logs/deepknee-cpu.log"]
8 changes: 6 additions & 2 deletions docker/docker-compose-gpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ services:
source: ../snapshots_release_kneel # The snapshots are stored in the root directory
target: /snapshots/
read_only: true
- type: bind
source: ../logs
target: /logs/
entrypoint: ["python", "-u", "-m", "kneel.inference.app",
"--lc_snapshot_path", "/snapshots/lext-devbox_2019_07_14_16_04_41",
"--hc_snapshot_path", "/snapshots/lext-devbox_2019_07_14_19_25_40",
"--refine", "True", "--mean_std_path", "/snapshots/mean_std.npy",
"--deploy", "True", "--device", "cuda", "--port", "5000"]
"--deploy", "True", "--device", "cuda", "--port", "5000", "--logs", "/logs/kneel-gpu.log"]
deepknee-backend:
runtime: nvidia
depends_on:
Expand All @@ -33,4 +36,5 @@ services:
- KNEEL_ADDR=http://kneel:5000
entrypoint: ["python", "-m", "ouludeepknee.inference.app",
"--snapshots_path", "/snapshots/",
"--device", "cuda", "--deploy", "True"]
"--device", "cuda", "--deploy", "True",
"--port", "5001", "--logs", "/logs/deepknee-cpu.log"]
58 changes: 41 additions & 17 deletions ouludeepknee/inference/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,26 @@
from flask import Flask, request
from flask import jsonify, make_response
from gevent.pywsgi import WSGIServer
import socketio
import eventlet

import logging
from ouludeepknee.inference.pipeline import KneeNetEnsemble

app = Flask(__name__)
# Wrap Flask application with socketio's middleware
sio = socketio.Server(ping_timeout=120, ping_interval=120)


def numpy2base64(img):
_, buffer = cv2.imencode('.png', cv2.cvtColor(img, cv2.COLOR_RGB2BGR))
return 'data:image/png;base64,' + base64.b64encode(buffer).decode('ascii')


# curl -F dicom=@01 -X POST http://127.0.0.1:5001/predict/bilateral
@app.route('/predict/bilateral', methods=['POST'])
def analyze_knee():
if os.environ['KNEEL_ADDR'] == '':
return make_response(jsonify({'msg': 'KNEEL microservice is not defined'}), 500)
dicom_raw = request.files['dicom'].read()
def call_pipeline(dicom_raw, landmarks=None):
# Localization of ROIs and their conversion into 8-bit 140x140mm images
res_bilateral = net.predict_draw_bilateral(dicom_raw, args.sizemm, args.pad)
res_bilateral = net.predict_draw_bilateral(dicom_raw, args.sizemm, args.pad,
kneel_addr=os.environ['KNEEL_ADDR'], landmarks=landmarks)
if res_bilateral is None:
return make_response(jsonify({'msg': 'Could not localize the landmarks'}), 400)

Expand All @@ -46,38 +47,61 @@ def analyze_knee():
'preds_bar': numpy2base64(preds_bar_r),
'kl': str(pred_r)},
'msg': 'Finished!'}
return response

# curl -F dicom=@01 -X POST http://127.0.0.1:5001/deepknee/predict/bilateral
@app.route('/deepknee/predict/bilateral', methods=['POST'])
def analyze_knee():
logger = logging.getLogger(f'deepknee-backend:app')
dicom_raw = request.files['dicom'].read()
logger.log(logging.INFO, f'Received DICOM')

if os.environ['KNEEL_ADDR'] == '':
return make_response(jsonify({'msg': 'KNEEL microservice is not defined'}), 500)

response = call_pipeline(dicom_raw)

return make_response(response, 200)


@app.route('/predict/single', methods=['POST'])
def analyze_single_knee():
"""
Runs prediction for a single cropped right knee X-ray.
@sio.on('dicom_submission', namespace='/deepknee/sockets')
def on_dicom_submission(sid, data):
sio.emit('dicom_received', dict(), room=sid, namespace='/deepknee/sockets')
logger.info(f'Sent a message back to {sid}')
sio.sleep(0)

"""
raise NotImplementedError
tmp = data['file_blob'].split(',', 1)[1]
response = call_pipeline(base64.b64decode(tmp))
# Send out the results
sio.emit('dicom_processed', response, room=sid, namespace='/deepknee/sockets')


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--snapshots_path', default='')
parser.add_argument('--deploy_addr', default='0.0.0.0')
parser.add_argument('--device', default='cuda')
parser.add_argument('--port', type=int, default=5001)
parser.add_argument('--sizemm', type=int, default=140)
parser.add_argument('--pad', type=int, default=300)
parser.add_argument('--deploy', type=bool, default=False)
parser.add_argument('--logs', type=str, default='/tmp/deepknee.log')
args = parser.parse_args()
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG)
logging.basicConfig(filename=args.logs, filemode='a',
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG)

logger = logging.getLogger(f'deepknee-backend:app')

net = KneeNetEnsemble(glob.glob(os.path.join(args.snapshots_path, "*", '*.pth')),
mean_std_path=os.path.join(args.snapshots_path, 'mean_std.npy'),
device=args.device)

app = socketio.WSGIApp(sio, app, socketio_path='/deepknee/sockets/socket.io')

if args.deploy:
http_server = WSGIServer((args.deploy_addr, 5001), app, log=logger)
http_server.serve_forever()
# Deploy as an eventlet WSGI server
eventlet.wsgi.server(eventlet.listen((args.deploy_addr, args.port)), app, log=logger)
# http_server = WSGIServer((args.deploy_addr, 5001), app, log=logger)
# http_server.serve_forever()
else:
app.run(host=args.deploy_addr, port=5001, debug=True)
app.run(host=args.deploy_addr, port=args.port, debug=True)
22 changes: 15 additions & 7 deletions ouludeepknee/inference/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,23 @@ def predict_draw(self, fileobj_in, nbits=16, fname_suffix=None, path_dir_out=Non
self.logger.log(logging.INFO, f'Sending the results back to the user')
return img, img_overlayed, probs_bar, probs.squeeze().argmax()

def localize_bilateral(self, dicom_raw, sizemm, pad):
files = {'dicom': dicom_raw}
def request_landmarks(self, kneel_addr, file):
self.logger.log(logging.INFO, f'Sending the image to KNEEL: {os.environ["KNEEL_ADDR"]}')
response = requests.post(f'{os.environ["KNEEL_ADDR"]}/predict/bilateral', files=files)
if kneel_addr is None:
kneel_addr = os.environ["KNEEL_ADDR"]

response = requests.post(f'{kneel_addr}/kneel/predict/bilateral', files=file)
landmarks = response.json()
return landmarks

def localize_bilateral(self, dicom_raw, sizemm, pad, kneel_addr=None, landmarks=None):
if landmarks is None:
landmarks = self.request_landmarks(kneel_addr, {'dicom': dicom_raw})

if landmarks['R'] is None:
self.logger.log(logging.INFO, f'Landmarks have not been localized. Returning None')
self.logger.log(logging.INFO, f'Landmarks are not found. Returning None')
return None

self.logger.log(logging.INFO, f'Image decoding and pre-processing started')
raw = DicomBytesIO(dicom_raw)
dicom_data = dcmread(raw)
Expand Down Expand Up @@ -373,9 +382,8 @@ def localize_bilateral(self, dicom_raw, sizemm, pad):
self.logger.log(logging.INFO, f'Returning localized left and right knees')
return img_left, img_right

def predict_draw_bilateral(self, dicom_raw, sizemm, pad):
self.logger.log(logging.INFO, f'Received DICOM')
res_landmarks = self.localize_bilateral(dicom_raw, sizemm, pad)
def predict_draw_bilateral(self, dicom_raw, sizemm, pad, kneel_addr=None, landmarks=None):
res_landmarks = self.localize_bilateral(dicom_raw, sizemm, pad, kneel_addr, landmarks)
if res_landmarks is None:
return None

Expand Down

0 comments on commit 0faf132

Please sign in to comment.