Skip to content

Commit 732b0e2

Browse files
authored
Merge pull request #27 from ESA-PhiLab/extend-help-menu
Extend help menu
2 parents 9bf3eb4 + e959414 commit 732b0e2

11 files changed

Lines changed: 377 additions & 98 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,6 @@ dmypy.json
123123

124124
# Pyre type checker
125125
.pyre/
126+
127+
# Our stuff
128+
/projects/

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
### Bugs (please suggest more if found)
44

55
- [ ] Time spent is not logged or reported
6-
- [ ] Contrast/Inversion buttons toggle on but do not toggle off via mouseclick
6+
- [x] Contrast/Inversion buttons toggle on but do not toggle off via mouseclick
77
- [x] User "admin" can revoke their admin status, this should not be possible
88
- [x] Prompt to create password for user "admin" accepts blank strings, making it impossible to then log in
99

demo/cloud-segmentation.json

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,11 @@
3838
"name": "Cloud Shadows",
3939
"description": "All pixels contaminated by cloud shadows (not terrain shadows).",
4040
"colour": [255, 0, 0, 70]
41-
},
42-
{
43-
"name": "No data",
44-
"description": "Reserved for no data pixels, e.g. pixels outside of the satellite's swath.",
45-
"colour": [50, 50, 255, 70]
4641
}
4742
],
4843
"views": {
4944
"Cirrus": {
50-
"description": "Cirrus and high clouds are red.",
45+
"description": "Cirrus band. High clouds are often picked up as red.",
5146
"type": "image",
5247
"data": "$Sentinel2.B11**0.8*5",
5348
"cmap": "jet"
@@ -65,7 +60,7 @@
6560
"clip": "1"
6661
},
6762
"NRGB": {
68-
"description": "Near-Infrared RGB image.",
63+
"description": "Near-Infrared+GB image.",
6964
"type": "image",
7065
"data": ["$Sentinel2.B5*1.5", "$Sentinel2.B3*1.5", "$Sentinel2.B2*1.5"]
7166
},
@@ -97,7 +92,7 @@
9792
}
9893
},
9994
"view_groups": {
100-
"default": ["Cirrus", "RGB", "Snow"],
95+
"default": ["RGB", "Snow", "Cirrus"],
10196
"radar": ["Sentinel-1"]
10297
}
10398
}

iris/help/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,4 @@ def index():
1717
return flask.render_template(
1818
'help.html',
1919
hotkeys=data.get('hotkeys', False),
20-
page=data.get('page', False),
21-
page_content=flask.Markup(flask.render_template(data['page_content']))
2220
)

iris/help/templates/help.html

Lines changed: 226 additions & 6 deletions
Large diffs are not rendered by default.

iris/segmentation/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,8 @@ def predict_mask(image_id):
323323

324324
# Select only the masking area:
325325
mask_area = (
326-
slice(config['mask_area'][0], config['mask_area'][2]),
327326
slice(config['mask_area'][1], config['mask_area'][3]),
327+
slice(config['mask_area'][0], config['mask_area'][2]),
328328
slice(None, None, None)
329329
)
330330
mask_size = config['mask_shape'][0] * config['mask_shape'][1]

iris/segmentation/static/javascripts/segmentation.js

Lines changed: 87 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,82 +4,107 @@ reasons, i.e. array_2d[y][x] is going to be array_1d[y*row_length+x]*/
44

55
let commands = {
66
"previous_image": {
7-
"key": "Backspace", "description": "Save this image and open previous one",
7+
"key": "Backspace",
8+
"description": "Save this image and open previous one"
89
},
910
"next_image": {
10-
"key": "Return", "description": "Save this image and open next one",
11+
"key": "Return",
12+
"description": "Save this image and open next one"
1113
},
1214
"save_mask": {
13-
"key": "S", "description": "Save this mask",
15+
"key": "S",
16+
"description": "Save this mask"
1417
},
1518
"undo": {
16-
"key": "U", "description": "Undo last modification",
19+
"key": "U",
20+
"description": "Undo last modification"
1721
},
1822
"redo": {
19-
"key": "R", "description": "Redo modification",
23+
"key": "R",
24+
"description": "Redo modification"
2025
},
21-
'select_class': {
22-
"key": "1 .. 9", "description": "Select class for drawing",
26+
"select_class": {
27+
"key": "1 .. 9",
28+
"description": "Select class for drawing"
2329
},
24-
'tool_move': {
25-
"key": "W", "description": "Pan your current view by dragging and moving the cursor",
30+
"tool_move": {
31+
"key": "W",
32+
"description": "Pan your current view by dragging and moving the cursor"
2633
},
27-
'tool_reset_views': {
28-
"key": "Z", "description": "Reset the view in the canvases",
34+
"tool_reset_views": {
35+
"key": "Z",
36+
"description": "Reset the view in the canvases"
2937
},
30-
'tool_draw': {
31-
"key": "D", "description": "Draw pixels on the mask",
38+
"tool_draw": {
39+
"key": "D",
40+
"description": "Draw pixels on the mask"
3241
},
33-
'tool_eraser': {
34-
"key": "E", "description": "Erase previously drawn pixels",
42+
"tool_eraser": {
43+
"key": "E",
44+
"description": "Erase previously drawn pixels"
3545
},
3646
"reset_mask": {
37-
"key": "N", "description": "Clear the whole mask",
47+
"key": "N",
48+
"description": "Clear the whole mask"
3849
},
3950
"predict_mask": {
40-
"key": "A", "description": "Use the AI to help you filling out the mask",
51+
"key": "A",
52+
"description": "Use the AI to help you filling out the mask"
4153
},
4254
"toogle_mask": {
43-
"key": "Space", "description": "Toggle mask on/off",
55+
"key": "Space",
56+
"description": "Toggle mask on/off"
4457
},
4558
"mask_final": {
46-
"key": "F", "description": "Show the final mask combined from your pixels and the predictions by the AI",
59+
"key": "F",
60+
"description": "Show the final mask combined from your pixels and the predictions by the AI"
4761
},
4862
"mask_user": {
49-
"key": "G", "description": "Show your drawn pixels only",
63+
"key": "G",
64+
"description": "Show your drawn pixels only"
5065
},
5166
"mask_errors": {
52-
"key": "H", "description": "Show where the AI failed to predict correctly",
67+
"key": "H",
68+
"description": "Show where the AI failed to predict correctly"
5369
},
5470
// "mask_highlight_edges": {
5571
// "key": "B", "description": "Highlight edges on the masks",
5672
// },
5773
"toggle_contrast": {
58-
"key": "C", "description": "Toggle contrast on/off",
74+
"key": "C",
75+
"description": "Toggle contrast on/off"
5976
},
6077
"toggle_invert": {
61-
"key": "I", "description": "Toggle inversion on/off",
78+
"key": "I",
79+
"description": "Toggle inversion on/off"
6280
},
6381
"brightness_up": {
64-
"key": "Arrow-Up", "description": "Increase brightness (+10%)",
82+
"key": "Arrow-Up",
83+
"description": "Increase brightness (+10%)"
6584
},
6685
"brightness_down": {
67-
"key": "Arrow-Down", "description": "Decrease brightness (-10%)",
86+
"key": "Arrow-Down",
87+
"description": "Decrease brightness (-10%)"
6888
},
6989
"saturation_up": {
70-
"key": "Arrow-Right", "description": "Increase saturation (+50%)",
90+
"key": "Arrow-Right",
91+
"description": "Increase saturation (+50%)"
7192
},
7293
"saturation_down": {
73-
"key": "Arrow-Left", "description": "Decrease saturation (-50%)",
94+
"key": "Arrow-Left",
95+
"description": "Decrease saturation (-50%)"
7496
},
7597
"reset_filters": {
76-
"key": "X", "description": "Reset all image filters",
98+
"key": "X",
99+
"description": "Reset all image filters"
77100
},
78101
"show_view_controls": {
79-
"key": "V", "description": "Toogle display of view controls on/off"
102+
"key": "V",
103+
"description":"Toogle display of view controls on/off"
80104
},
81105
"next_view_group": {
82-
"key": "B", "description": "Switch to next group view"
106+
"key": "B",
107+
"description": "Switch to next group view"
83108
}
84109
};
85110

@@ -91,23 +116,32 @@ function init_segmentation(){
91116
fetch_server_update(update_config=true);
92117
}
93118

94-
async function init_views(){
119+
function newuser_help_popup(){
120+
// Open the help menu if the user is new (no saved masks):
121+
if (vars.user.segmentation.n_masks == 0 && vars.just_logged_in == true){
122+
dialogue_help();
123+
vars.just_logged_in = false;
124+
}
125+
}
126+
127+
function init_views(){
95128
show_loader("Loading views...");
96129
vars.vm = new ViewManager(
97130
get_object('views-container'),
98131
vars.config.views, vars.config.view_groups,
99-
vars.url.main+"image/"
132+
vars.url.main+"image/",
133+
image_aspect_ratio=vars.image_shape[0]/vars.image_shape[1]
100134
);
101135

102136
// Add standard layers to all view ports if the view type is not "bingmap":
103137
vars.vm.addStandardLayer(
104138
MaskLayer,
105139
(view) => view.type != "bingmap"
106-
)
140+
);
107141
vars.vm.addStandardLayer(
108142
PreviewLayer,
109143
(view) => view.type != "bingmap"
110-
)
144+
);
111145

112146
// It much faster to change some pixel values on a sprite and draw it then
113147
// to the canvas once than redrawing each pixel to the canvas directly.
@@ -138,6 +172,7 @@ async function init_views(){
138172

139173
get_object("toolbar").style.visibility = "visible";
140174
get_object("statusbar").style.visibility = "visible";
175+
newuser_help_popup();
141176
}
142177

143178
function init_events(){
@@ -428,7 +463,7 @@ function constrain_view(ctx, scale, dx, dy){
428463
// it to the default view
429464

430465
transforms.a = ctx.canvas.width / vars.image_shape[0];
431-
transforms.d = ctx.canvas.width / vars.image_shape[0];
466+
transforms.d = ctx.canvas.height / vars.image_shape[1];
432467
transforms.b = 0;
433468
transforms.c = 0;
434469
transforms.e = 0;
@@ -882,6 +917,7 @@ async function fetch_server_update(update_config=true){
882917
let response = await fetch(vars.url.user+"get/current");
883918
if (response.status == 403) {
884919
dialogue_login();
920+
vars.just_logged_in=true;
885921
return;
886922
}
887923
let user = await response.json();
@@ -1069,9 +1105,7 @@ async function dialogue_help(){
10691105
vars.url.help, {
10701106
method: "POST",
10711107
body: JSON.stringify({
1072-
"hotkeys": hotkeys,
1073-
"page": "Segmentation",
1074-
"page_content": "segmentation/help.html"
1108+
"hotkeys": hotkeys
10751109
})
10761110
}
10771111
);
@@ -1318,6 +1352,7 @@ async function predict_mask(){
13181352
// We need to keep track of how many pixels we already have sampled.
13191353
// Furthermore, we keep also a ratio of pixels as testing dataset:
13201354
let n_samples = {};
1355+
let test_n_samples = {};
13211356
for (let user_class of user_classes){
13221357
// Set the current number of samples (0) and the maximum
13231358
n_samples[user_class] = {
@@ -1327,22 +1362,30 @@ async function predict_mask(){
13271362
vars.config.segmentation.ai_model.max_train_pixels
13281363
)
13291364
};
1365+
test_n_samples[user_class] = {
1366+
"current": 0,
1367+
"max": Infinity
1368+
};
13301369
}
13311370

13321371
// Here we decide whether we send a pixel for training to the server or keep
13331372
// it here as testing dataset:
13341373
let test_indices = new Array();
13351374
let train_user_pixels = new Array();
13361375
let train_user_labels = new Array();
1376+
let test_user_pixels = new Array();
1377+
let test_user_labels = new Array();
13371378
for (let i of all_indices){
13381379
let class_id = all_user_labels[i];
13391380
if (n_samples[class_id].current < n_samples[class_id].max){
13401381
train_user_pixels.push(all_user_pixels[i]);
13411382
train_user_labels.push(class_id);
13421383
n_samples[class_id].current += 1;
13431384
} else {
1344-
// We will remember that we need these pixels later for testing:
13451385
test_indices.push(i);
1386+
test_user_pixels.push(all_user_pixels[i]);
1387+
test_user_labels.push(class_id);
1388+
test_n_samples[class_id].current += 1;
13461389
}
13471390
}
13481391

@@ -1353,7 +1396,7 @@ async function predict_mask(){
13531396
method: "POST",
13541397
body: JSON.stringify({
13551398
"user_pixels": train_user_pixels,
1356-
"user_labels": train_user_labels,
1399+
"user_labels": train_user_labels
13571400
})
13581401
}
13591402
);
@@ -1380,15 +1423,15 @@ async function predict_mask(){
13801423
for (let user_class of user_classes){
13811424
tp[user_class] = 0;
13821425
}
1383-
for (let i of all_indices){
1426+
1427+
for (let i of test_indices){
13841428
let mask_index = all_user_pixels[i];
13851429
cm[all_user_labels[i]][results.data[mask_index]] += 1;
1386-
13871430
if (all_user_labels[i] == results.data[mask_index]){
13881431
tp[all_user_labels[i]] += 1;
13891432

13901433
// Correct:
1391-
// vars.errors_mask[mask_index] = 1;
1434+
vars.errors_mask[mask_index] = 1;
13921435
} else {
13931436
// Incorrect:
13941437
vars.errors_mask[mask_index] = 2;
@@ -1397,7 +1440,7 @@ async function predict_mask(){
13971440
let acc_prod = user_classes.length;
13981441
let acc_sum = 0;
13991442
for (let label of user_classes){
1400-
let acc = tp[label] / (vars.n_user_pixels[label]);
1443+
let acc = tp[label] / test_n_samples[label].current;
14011444
acc_prod *= acc;
14021445
acc_sum += acc;
14031446
}

iris/segmentation/templates/segmentation.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,10 @@
138138
<li class="toolbutton icon_button" id='tb_saturation_down' onclick="change_saturation(up=false);">
139139
<img src={{url_for('segmentation.static', filename='icons/saturation_down.png')}} class="icon" />
140140
</li>
141-
<li class="toolbutton icon_button" id='tb_toggle_contrast' onclick="set_contrast(!vars.contrast);">
141+
<li class="toolbutton icon_button" id='tb_toggle_contrast' onclick="set_contrast(!vars.vm.filters.contrast);">
142142
<img src={{url_for('segmentation.static', filename='icons/contrast.png')}} class="icon" />
143143
</li>
144-
<li class="toolbutton icon_button" id='tb_toggle_invert' onclick="set_invert(!vars.invert);">
144+
<li class="toolbutton icon_button" id='tb_toggle_invert' onclick="set_invert(!vars.vm.filters.invert);">
145145
<img src={{url_for('segmentation.static', filename='icons/invert.png')}} class="icon" />
146146
</li>
147147
<li class="toolbutton icon_button" id="tb_reset_filters" onclick='reset_filters();'>

iris/segmentation/templates/segmentation/help.html

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)