-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebapp_annotations.py
84 lines (78 loc) · 3.96 KB
/
webapp_annotations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python
# Annotate samples functions
from flask import Blueprint, redirect, request, render_template
import db
import json
from bson.objectid import ObjectId
from webapp_base import set_error, pop_last_error, error_redirect
from webapp_users import get_current_user_id
annotations = Blueprint('annotations', __name__, template_folder='templates')
# Annotation page
@annotations.route('/annotate/<sid>', methods=['GET', 'POST'])
def annotate(sid):
# Query info from DB
sample_id = ObjectId(sid)
sample_entry = db.get_sample_by_id(sample_id)
dataset_id = sample_entry['dataset_id']
name = sample_entry['name']
readonly = db.is_readonly_dataset_id(dataset_id)
sample_index, sample_count, prev_sample_id, next_sample_id = db.get_sample_index(dataset_id, sample_id)
# Unknown entry?
if sample_entry is None:
return error_redirect('Unknown entry: "%s".' % str(sample_id))
# Determine data
image_filename = 'images/' + sample_entry['filename']
info_string = ''
# Differential? Then load machine annotations, unless there are human annotations already
annotations = db.get_human_annotations(sample_id)
is_differential = request.args.get('differential')
if is_differential and not annotations:
annotations = db.get_machine_annotations(sample_id)
if len(annotations):
annotations_json = annotations[0]['positions']
# Machine annotations are in a different format
if len(annotations_json) and isinstance(annotations_json[0], list):
annotations_json = [{'x': a[0], 'y': a[1]} for a in annotations_json]
else:
annotations_json = []
return render_template("annotate.html", id=sid, image_filename=image_filename, info_string=info_string,
error=pop_last_error(), height=sample_entry['size'][1], width=sample_entry['size'][0],
annotations=annotations_json, margin=96, dataset_id=str(dataset_id),
sample_index=sample_index, sample_count=sample_count, prev_id=str(prev_sample_id),
next_id=str(next_sample_id), is_differential=is_differential, readonly=readonly,
name=name)
# Save annotations
@annotations.route('/save_annotations/<sid>', methods=['GET', 'POST'])
def save_annotations(sid):
sample_id = ObjectId(sid)
sample_entry = db.get_sample_by_id(sample_id)
# Caution: Load dataset id from DB (not from form), for security of the readonly check!
# dataset_id = ObjectId(request.form['dataset_id'].strip())
dataset_id = sample_entry['dataset_id']
readonly = db.is_readonly_dataset_id(dataset_id)
if readonly:
set_error('Dataset is protected.')
return redirect('/dataset/' + str(dataset_id))
is_differential = request.args.get('differential')
if is_differential:
base_annotations = db.get_machine_annotations(sample_id)
redirect_params = '?differential=1'
else:
base_annotations = None
redirect_params = ''
# Save annotations for sample
annotations = json.loads(request.form['annotations'].strip())
margin = int(request.form['margin'].strip())
print('Saving annotations.', sid, margin, annotations)
db.set_human_annotation(sample_id, get_current_user_id(), annotations, margin, base_annotations=base_annotations)
# Forward either to info page or to annotation of next un-annotated entry in DB if found
annotate_next = ("save_and_continue" in request.form)
if annotate_next:
next_sample_id = db.get_next_sample_id(dataset_id, sample_id, annotated=False)
if next_sample_id is not None:
return redirect('/annotate/' + str(next_sample_id) + redirect_params, 200)
else:
set_error('No more samples to annotate.')
return redirect('/dataset/' + str(dataset_id), 200)
# Nothing
return redirect('/info/' + sid, 200)