Spaces:
Sleeping
Sleeping
Commit
·
83b7c6a
1
Parent(s):
ef20573
update
Browse files- app.py +176 -102
- channel_mapping.py +21 -19
app.py
CHANGED
@@ -44,14 +44,24 @@ icunet = """
|
|
44 |
Electroencephalography (EEG) signals are often contaminated with artifacts. It is imperative to develop a practical and reliable artifact removal method to prevent the misinterpretation of neural signals and the underperformance of brain–computer interfaces. Based on the U-Net architecture, we developed a new artifact removal model, IC-U-Net, for removing pervasive EEG artifacts and reconstructing brain signals. IC-U-Net was trained using mixtures of brain and non-brain components decomposed by independent component analysis. It uses an ensemble of loss functions to model complex signal fluctuations in EEG recordings. The effectiveness of the proposed method in recovering brain activities and removing various artifacts (e.g., eye blinks/movements, muscle activities, and line/channel noise) was demonstrated in a simulation study and four real-world EEG experiments. IC-U-Net can reconstruct a multi-channel EEG signal and is applicable to most artifact types, offering a promising end-to-end solution for automatically removing artifacts from EEG recordings. It also meets the increasing need to image natural brain dynamics in a mobile setting.
|
45 |
"""
|
46 |
|
47 |
-
|
48 |
(app_state, channel_info) => {
|
49 |
app_state = JSON.parse(JSON.stringify(app_state));
|
50 |
channel_info = JSON.parse(JSON.stringify(channel_info));
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
// add figure of in_montage
|
54 |
-
document.querySelector(
|
55 |
position: relative;
|
56 |
width: 560px;
|
57 |
height: 560px;
|
@@ -59,13 +69,31 @@ chkbox_js = """
|
|
59 |
`;
|
60 |
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
// add indication for the missing channels
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
|
67 |
let rule = `
|
68 |
-
|
69 |
content: '';
|
70 |
position: absolute;
|
71 |
background-color: red;
|
@@ -81,35 +109,15 @@ chkbox_js = """
|
|
81 |
let exist = 0;
|
82 |
const styleSheet = document.styleSheets[0];
|
83 |
for(let i=0; i<styleSheet.cssRules.length; i++){
|
84 |
-
if(styleSheet.cssRules[i].selectorText == "
|
85 |
exist = 1;
|
86 |
-
console.log('exist!');
|
87 |
styleSheet.deleteRule(i);
|
88 |
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
89 |
break;
|
90 |
}
|
91 |
}
|
92 |
if(exist == 0) styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
93 |
-
|
94 |
-
|
95 |
-
// move the checkboxes
|
96 |
-
let all_chkbox = document.querySelectorAll("#chkbox-group> div:nth-of-type(2)> label");
|
97 |
-
//all_chkbox = Array.apply(null, all_chkbox);
|
98 |
-
|
99 |
-
Array.from(all_chkbox).forEach((item, index) => {
|
100 |
-
channel = channel_info.inputByIndex[index];
|
101 |
-
left = channel_info.inputByName[channel].css_position[0];
|
102 |
-
bottom = channel_info.inputByName[channel].css_position[1];
|
103 |
-
console.log(`left: ${left}, bottom: ${bottom}`);
|
104 |
-
|
105 |
-
item.style.cssText = `
|
106 |
-
position: absolute;
|
107 |
-
left: ${left};
|
108 |
-
bottom: ${bottom};
|
109 |
-
`;
|
110 |
-
item.className = "";
|
111 |
-
item.querySelector(":scope> span").innerText = "";
|
112 |
-
});
|
113 |
}
|
114 |
"""
|
115 |
|
@@ -117,14 +125,40 @@ indication_js = """
|
|
117 |
(app_state, channel_info) => {
|
118 |
app_state = JSON.parse(JSON.stringify(app_state));
|
119 |
channel_info = JSON.parse(JSON.stringify(channel_info));
|
120 |
-
if(app_state.state == "finished") return;
|
121 |
|
122 |
-
let
|
123 |
-
let left
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
let rule = `
|
127 |
-
|
128 |
content: '';
|
129 |
position: absolute;
|
130 |
background-color: red;
|
@@ -140,9 +174,9 @@ indication_js = """
|
|
140 |
let exist = 0;
|
141 |
const styleSheet = document.styleSheets[0];
|
142 |
for(let i=0; i<styleSheet.cssRules.length; i++){
|
143 |
-
if(styleSheet.cssRules[i].selectorText == "
|
144 |
exist = 1;
|
145 |
-
console.log('exist!');
|
146 |
styleSheet.deleteRule(i);
|
147 |
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
148 |
break;
|
@@ -310,8 +344,8 @@ with gr.Blocks() as demo:
|
|
310 |
#### determine the next step ####
|
311 |
#################################
|
312 |
|
313 |
-
in_num = len(channel_info["
|
314 |
-
matched_num = 30 - len(
|
315 |
|
316 |
# if the input channels(>=30) has all the 30 template channels
|
317 |
# -> Stage2.decode data
|
@@ -360,23 +394,20 @@ with gr.Blocks() as demo:
|
|
360 |
|
361 |
def init_next_step(app_state, channel_info, selected_radio, selected_chkbox):
|
362 |
|
363 |
-
channel_info["missingChannels"] = [channel for channel in channel_info["templateByName"]
|
364 |
-
if channel_info["templateByName"][channel]["matched"]==False]
|
365 |
-
app_state.update({
|
366 |
-
"fillingCount" : 1,
|
367 |
-
"totalFillingNum" : len(channel_info["missingChannels"])
|
368 |
-
})
|
369 |
-
|
370 |
# step1 -> step2
|
371 |
if app_state["state"] == "step2-initializing":
|
372 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
373 |
|
374 |
-
name =
|
375 |
label = name+' (1/'+str(app_state["totalFillingNum"])+')'
|
376 |
-
|
377 |
-
unassigned = [channel for channel in channel_info["inputByName"]
|
378 |
-
if channel_info["inputByName"][channel]["assigned"]==False]
|
379 |
-
if len(unassigned)==1 or app_state["totalFillingNum"]==1:
|
380 |
btn_label = "Next step"
|
381 |
else:
|
382 |
btn_label = "Next"
|
@@ -386,14 +417,22 @@ with gr.Blocks() as demo:
|
|
386 |
desc_md : gr.Markdown("### step2"),
|
387 |
tpl_montage : gr.Image(visible=False),
|
388 |
map_montage : gr.Image(visible=False),
|
389 |
-
radio : gr.Radio(choices=
|
390 |
step2_btn : gr.Button(btn_label, visible=True),
|
391 |
next_btn : gr.Button(visible=False)}
|
392 |
|
393 |
# step1 -> step3
|
394 |
elif app_state["state"] == "step3-initializing":
|
395 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
return {app_state_json : app_state,
|
|
|
397 |
desc_md : gr.Markdown("### step3"),
|
398 |
tpl_montage : gr.Image(visible=False),
|
399 |
map_montage : gr.Image(visible=False),
|
@@ -405,22 +444,31 @@ with gr.Blocks() as demo:
|
|
405 |
elif app_state["state"] == "step2-selecting":
|
406 |
|
407 |
# save info before clicking on next_btn
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
|
|
412 |
selected_idx = channel_info["inputByName"][selected_radio]["index"]
|
413 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
414 |
|
415 |
channel_info["templateByName"][prev_target_name]["matched"] = True
|
416 |
-
channel_info["inputByName"][selected_radio]["assigned"] = True
|
417 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
|
419 |
# if all the unmatched template channels were filled by input channels
|
420 |
# -> Stage2
|
421 |
-
if app_state["
|
422 |
-
|
423 |
gr.Info('The mapping process is finished!')
|
|
|
424 |
|
425 |
return {app_state_json : app_state,
|
426 |
channel_info_json : channel_info,
|
@@ -431,8 +479,12 @@ with gr.Blocks() as demo:
|
|
431 |
|
432 |
# -> step3
|
433 |
else:
|
434 |
-
|
435 |
-
|
|
|
|
|
|
|
|
|
436 |
return {app_state_json : app_state,
|
437 |
channel_info_json : channel_info,
|
438 |
desc_md : gr.Markdown("### step3"),
|
@@ -443,18 +495,23 @@ with gr.Blocks() as demo:
|
|
443 |
|
444 |
# step3 -> Stage2.decode data
|
445 |
elif app_state["state"] == "step3-selecting":
|
446 |
-
app_state["state"] = "finished"
|
447 |
-
gr.Info('The mapping process is finished!')
|
448 |
|
449 |
# save info before clicking on next_btn
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
|
|
454 |
selected_idx = [channel_info["inputByName"][channel]["index"] for channel in selected_chkbox]
|
455 |
-
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
456 |
-
|
457 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
458 |
|
459 |
return {app_state_json : app_state,
|
460 |
desc_md : gr.Markdown(visible=False),
|
@@ -469,7 +526,7 @@ with gr.Blocks() as demo:
|
|
469 |
chkbox_group, fillmode_btn, step2_btn, next_btn, run_btn]
|
470 |
).success(
|
471 |
fn = None,
|
472 |
-
js =
|
473 |
inputs = [app_state_json, channel_info_json],
|
474 |
outputs = []
|
475 |
)
|
@@ -479,36 +536,36 @@ with gr.Blocks() as demo:
|
|
479 |
def update_radio(app_state, channel_info, selected):
|
480 |
|
481 |
# save info before clicking on next_btn
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
|
|
486 |
selected_idx = channel_info["inputByName"][selected]["index"]
|
487 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
488 |
|
489 |
channel_info["templateByName"][prev_target_name]["matched"] = True
|
490 |
channel_info["inputByName"][selected]["assigned"] = True
|
491 |
-
|
492 |
|
493 |
# update the current round
|
494 |
app_state["fillingCount"] += 1
|
495 |
-
|
496 |
-
|
497 |
|
498 |
-
target_name =
|
499 |
-
|
500 |
radio_label = target_name+' ('+str(app_state["fillingCount"])+'/'+str(app_state["totalFillingNum"])+')'
|
501 |
|
502 |
-
if len(
|
503 |
return {app_state_json : app_state,
|
504 |
channel_info_json : channel_info,
|
505 |
-
radio : gr.Radio(choices=
|
506 |
step2_btn : gr.Button(visible=False),
|
507 |
next_btn : gr.Button("Next step", visible=True)}
|
508 |
else:
|
509 |
return {app_state_json : app_state,
|
510 |
channel_info_json : channel_info,
|
511 |
-
radio : gr.Radio(choices=
|
512 |
|
513 |
step2_btn.click(
|
514 |
fn = update_radio,
|
@@ -523,8 +580,6 @@ with gr.Blocks() as demo:
|
|
523 |
)
|
524 |
|
525 |
# step3
|
526 |
-
@fillmode_btn.click(inputs = [app_state_json, channel_info_json, in_fill_mode],
|
527 |
-
outputs = [app_state_json, in_fill_mode, fillmode_btn, chkbox_group, step3_btn, run_btn])
|
528 |
def fill_value(app_state, channel_info, fill_mode):
|
529 |
|
530 |
if fill_mode == 'zero':
|
@@ -541,7 +596,7 @@ with gr.Blocks() as demo:
|
|
541 |
app_state["state"] = "step3-selecting"
|
542 |
app_state = find_neighbors(app_state, channel_info, fill_mode)
|
543 |
|
544 |
-
name =
|
545 |
idx = channel_info["templateByName"][name]["index"]
|
546 |
value = app_state["stage1NewOrder"][idx]
|
547 |
value = [channel_info["inputByIndex"][i] for i in value]
|
@@ -554,22 +609,33 @@ with gr.Blocks() as demo:
|
|
554 |
value=value, label=label, visible=True),
|
555 |
step3_btn : gr.Button(visible=True)}
|
556 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
def update_chkbox(app_state, channel_info, selected):
|
558 |
|
559 |
# save info before clicking on next_btn
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
|
|
564 |
selected_idx = [channel_info["inputByName"][channel]["index"] for channel in selected]
|
565 |
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
566 |
-
|
567 |
-
#print('Selection for missing channel "{}"({}): {}'.format(prev_target_name, prev_target_idx, selected))
|
568 |
|
569 |
-
# update
|
570 |
app_state["fillingCount"] += 1
|
571 |
|
572 |
-
target_name =
|
573 |
target_idx = channel_info["templateByName"][target_name]["index"]
|
574 |
|
575 |
chkbox_value = app_state["stage1NewOrder"][target_idx]
|
@@ -606,11 +672,14 @@ with gr.Blocks() as demo:
|
|
606 |
|
607 |
def reset_run(app_state, channel_info, raw_data, model_name):
|
608 |
filepath = app_state["filepath"]
|
|
|
|
|
|
|
609 |
input_name = os.path.basename(str(raw_data))
|
610 |
output_name = os.path.splitext(input_name)[0]+'_'+model_name+'.csv'
|
611 |
|
612 |
-
in_num = len(channel_info["
|
613 |
-
matched_num = len([channel for channel in channel_info["
|
614 |
if channel_info["inputByName"][channel]["matched"]==True])
|
615 |
batch_num = math.ceil((in_num-matched_num)/30) + 1
|
616 |
|
@@ -619,12 +688,16 @@ with gr.Blocks() as demo:
|
|
619 |
"runnigState" : "stage1",
|
620 |
"batchCount" : 1,
|
621 |
"totalBatchNum" : batch_num,
|
622 |
-
"
|
|
|
623 |
})
|
624 |
|
625 |
-
|
626 |
-
|
|
|
|
|
627 |
return {app_state_json : app_state,
|
|
|
628 |
run_btn : gr.Button(interactive=False),
|
629 |
batch_md : gr.Markdown(visible=False),
|
630 |
out_denoised_data : gr.File(visible=False)}
|
@@ -644,6 +717,7 @@ with gr.Blocks() as demo:
|
|
644 |
if app_state["batchCount"] > 1:
|
645 |
app_state, channel_info = mapping_stage2(app_state, channel_info, fill_mode)
|
646 |
if app_state["runnigState"] == "finished":
|
|
|
647 |
break
|
648 |
|
649 |
reorder_to_template(app_state, raw_data)
|
@@ -669,7 +743,7 @@ with gr.Blocks() as demo:
|
|
669 |
run_btn.click(
|
670 |
fn = reset_run,
|
671 |
inputs = [app_state_json, channel_info_json, in_raw_data, in_model_name],
|
672 |
-
outputs = [app_state_json, run_btn, batch_md, out_denoised_data]
|
673 |
|
674 |
).success(
|
675 |
fn = run_model,
|
|
|
44 |
Electroencephalography (EEG) signals are often contaminated with artifacts. It is imperative to develop a practical and reliable artifact removal method to prevent the misinterpretation of neural signals and the underperformance of brain–computer interfaces. Based on the U-Net architecture, we developed a new artifact removal model, IC-U-Net, for removing pervasive EEG artifacts and reconstructing brain signals. IC-U-Net was trained using mixtures of brain and non-brain components decomposed by independent component analysis. It uses an ensemble of loss functions to model complex signal fluctuations in EEG recordings. The effectiveness of the proposed method in recovering brain activities and removing various artifacts (e.g., eye blinks/movements, muscle activities, and line/channel noise) was demonstrated in a simulation study and four real-world EEG experiments. IC-U-Net can reconstruct a multi-channel EEG signal and is applicable to most artifact types, offering a promising end-to-end solution for automatically removing artifacts from EEG recordings. It also meets the increasing need to image natural brain dynamics in a mobile setting.
|
45 |
"""
|
46 |
|
47 |
+
init_js = """
|
48 |
(app_state, channel_info) => {
|
49 |
app_state = JSON.parse(JSON.stringify(app_state));
|
50 |
channel_info = JSON.parse(JSON.stringify(channel_info));
|
51 |
+
|
52 |
+
let selector, attribute;
|
53 |
+
let channel, left, bottom;
|
54 |
+
|
55 |
+
if(app_state.state == "step2-selecting"){
|
56 |
+
selector = "#radio> div:nth-of-type(2)";
|
57 |
+
attribute = "value";
|
58 |
+
}else if(app_state.state == "step3-selecting"){
|
59 |
+
selector = "#chkbox-group> div:nth-of-type(2)";
|
60 |
+
attribute = "name";
|
61 |
+
}else return;
|
62 |
|
63 |
// add figure of in_montage
|
64 |
+
document.querySelector(selector).style.cssText = `
|
65 |
position: relative;
|
66 |
width: 560px;
|
67 |
height: 560px;
|
|
|
69 |
`;
|
70 |
|
71 |
|
72 |
+
// move the radios/checkboxes
|
73 |
+
let all_elem = document.querySelectorAll(selector+"> label");
|
74 |
+
Array.from(all_elem).forEach((item) => {
|
75 |
+
channel = item.querySelector("input").getAttribute(attribute);
|
76 |
+
left = channel_info.inputByName[channel].css_position[0];
|
77 |
+
bottom = channel_info.inputByName[channel].css_position[1];
|
78 |
+
//console.log(`channel: ${channel}, left: ${left}, bottom: ${bottom}`);
|
79 |
+
|
80 |
+
item.style.cssText = `
|
81 |
+
position: absolute;
|
82 |
+
left: ${left};
|
83 |
+
bottom: ${bottom};
|
84 |
+
`;
|
85 |
+
item.className = "";
|
86 |
+
item.querySelector(":scope> span").innerText = "";
|
87 |
+
});
|
88 |
+
|
89 |
+
|
90 |
// add indication for the missing channels
|
91 |
+
channel = app_state.missingTemplates[0]
|
92 |
+
left = channel_info.templateByName[channel].css_position[0];
|
93 |
+
bottom = channel_info.templateByName[channel].css_position[1];
|
94 |
|
95 |
let rule = `
|
96 |
+
${selector}::after{
|
97 |
content: '';
|
98 |
position: absolute;
|
99 |
background-color: red;
|
|
|
109 |
let exist = 0;
|
110 |
const styleSheet = document.styleSheets[0];
|
111 |
for(let i=0; i<styleSheet.cssRules.length; i++){
|
112 |
+
if(styleSheet.cssRules[i].selectorText == selector+"::after"){
|
113 |
exist = 1;
|
114 |
+
//console.log('exist!');
|
115 |
styleSheet.deleteRule(i);
|
116 |
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
117 |
break;
|
118 |
}
|
119 |
}
|
120 |
if(exist == 0) styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
"""
|
123 |
|
|
|
125 |
(app_state, channel_info) => {
|
126 |
app_state = JSON.parse(JSON.stringify(app_state));
|
127 |
channel_info = JSON.parse(JSON.stringify(channel_info));
|
|
|
128 |
|
129 |
+
let selector;
|
130 |
+
let channel, left, bottom;
|
131 |
+
|
132 |
+
if(app_state.state == "step2-selecting"){
|
133 |
+
selector = "#radio> div:nth-of-type(2)";
|
134 |
+
|
135 |
+
// update the radios
|
136 |
+
let all_elem = document.querySelectorAll(selector+"> label");
|
137 |
+
Array.from(all_elem).forEach((item) => {
|
138 |
+
channel = item.querySelector("input").value;
|
139 |
+
left = channel_info.inputByName[channel].css_position[0];
|
140 |
+
bottom = channel_info.inputByName[channel].css_position[1];
|
141 |
+
//console.log(`channel: ${channel}, left: ${left}, bottom: ${bottom}`);
|
142 |
+
|
143 |
+
item.style.cssText = `
|
144 |
+
position: absolute;
|
145 |
+
left: ${left};
|
146 |
+
bottom: ${bottom};
|
147 |
+
`;
|
148 |
+
item.className = "";
|
149 |
+
item.querySelector(":scope> span").innerText = "";
|
150 |
+
});
|
151 |
+
}else if(app_state.state == "step3-selecting"){
|
152 |
+
selector = "#chkbox-group> div:nth-of-type(2)";
|
153 |
+
}else return;
|
154 |
+
|
155 |
+
// update indication
|
156 |
+
channel = app_state.missingTemplates[app_state["fillingCount"]-1]
|
157 |
+
left = channel_info.templateByName[channel].css_position[0];
|
158 |
+
bottom = channel_info.templateByName[channel].css_position[1];
|
159 |
|
160 |
let rule = `
|
161 |
+
${selector}::after{
|
162 |
content: '';
|
163 |
position: absolute;
|
164 |
background-color: red;
|
|
|
174 |
let exist = 0;
|
175 |
const styleSheet = document.styleSheets[0];
|
176 |
for(let i=0; i<styleSheet.cssRules.length; i++){
|
177 |
+
if(styleSheet.cssRules[i].selectorText == selector+"::after"){
|
178 |
exist = 1;
|
179 |
+
//console.log('exist!');
|
180 |
styleSheet.deleteRule(i);
|
181 |
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
182 |
break;
|
|
|
344 |
#### determine the next step ####
|
345 |
#################################
|
346 |
|
347 |
+
in_num = len(channel_info["inputByIndex"])
|
348 |
+
matched_num = 30 - len(app_state["missingTemplates"])
|
349 |
|
350 |
# if the input channels(>=30) has all the 30 template channels
|
351 |
# -> Stage2.decode data
|
|
|
394 |
|
395 |
def init_next_step(app_state, channel_info, selected_radio, selected_chkbox):
|
396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
397 |
# step1 -> step2
|
398 |
if app_state["state"] == "step2-initializing":
|
399 |
+
print('step1 -> step2')
|
400 |
+
app_state["missingTemplates"] = [channel for channel in channel_info["templateByIndex"]
|
401 |
+
if channel_info["templateByName"][channel]["matched"]==False]
|
402 |
+
app_state.update({
|
403 |
+
"state" : "step2-selecting",
|
404 |
+
"fillingCount" : 1,
|
405 |
+
"totalFillingNum" : len(app_state["missingTemplates"])
|
406 |
+
})
|
407 |
|
408 |
+
name = app_state["missingTemplates"][0]
|
409 |
label = name+' (1/'+str(app_state["totalFillingNum"])+')'
|
410 |
+
if len(app_state["stage1UnassignedInputs"])==1 or app_state["totalFillingNum"]==1:
|
|
|
|
|
|
|
411 |
btn_label = "Next step"
|
412 |
else:
|
413 |
btn_label = "Next"
|
|
|
417 |
desc_md : gr.Markdown("### step2"),
|
418 |
tpl_montage : gr.Image(visible=False),
|
419 |
map_montage : gr.Image(visible=False),
|
420 |
+
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=label, visible=True),
|
421 |
step2_btn : gr.Button(btn_label, visible=True),
|
422 |
next_btn : gr.Button(visible=False)}
|
423 |
|
424 |
# step1 -> step3
|
425 |
elif app_state["state"] == "step3-initializing":
|
426 |
+
print('step1 -> step3')
|
427 |
+
app_state["missingTemplates"] = [channel for channel in channel_info["templateByIndex"]
|
428 |
+
if channel_info["templateByName"][channel]["matched"]==False]
|
429 |
+
app_state.update({
|
430 |
+
"state" : "step3-initializing",
|
431 |
+
"fillingCount" : 1,
|
432 |
+
"totalFillingNum" : len(app_state["missingTemplates"])
|
433 |
+
})
|
434 |
return {app_state_json : app_state,
|
435 |
+
channel_info_json : channel_info,
|
436 |
desc_md : gr.Markdown("### step3"),
|
437 |
tpl_montage : gr.Image(visible=False),
|
438 |
map_montage : gr.Image(visible=False),
|
|
|
444 |
elif app_state["state"] == "step2-selecting":
|
445 |
|
446 |
# save info before clicking on next_btn
|
447 |
+
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
448 |
+
prev_target_idx = channel_info["templateByName"][prev_target_name]["index"]
|
449 |
+
if selected_radio == []:
|
450 |
+
app_state["stage1NewOrder"][prev_target_idx] = []
|
451 |
+
else:
|
452 |
selected_idx = channel_info["inputByName"][selected_radio]["index"]
|
453 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
454 |
|
455 |
channel_info["templateByName"][prev_target_name]["matched"] = True
|
456 |
+
channel_info["inputByName"][selected_radio]["assigned"] = True
|
457 |
+
print(prev_target_name, '<-', selected_radio)
|
458 |
+
|
459 |
+
app_state.update({
|
460 |
+
"stage1UnassignedInputs" : [channel for channel in channel_info["inputByIndex"]
|
461 |
+
if channel_info["inputByName"][channel]["assigned"]==False],
|
462 |
+
"missingTemplates" : [channel for channel in channel_info["templateByIndex"]
|
463 |
+
if channel_info["templateByName"][channel]["matched"]==False]
|
464 |
+
})
|
465 |
|
466 |
# if all the unmatched template channels were filled by input channels
|
467 |
# -> Stage2
|
468 |
+
if len(app_state["missingTemplates"]) == 0:
|
469 |
+
print('step2 -> Stage2')
|
470 |
gr.Info('The mapping process is finished!')
|
471 |
+
app_state["state"] = "finished"
|
472 |
|
473 |
return {app_state_json : app_state,
|
474 |
channel_info_json : channel_info,
|
|
|
479 |
|
480 |
# -> step3
|
481 |
else:
|
482 |
+
print('step2 -> step3')
|
483 |
+
app_state.update({
|
484 |
+
"state" : "step3-initializing",
|
485 |
+
"fillingCount" : 1,
|
486 |
+
"totalFillingNum" : len(app_state["missingTemplates"])
|
487 |
+
})
|
488 |
return {app_state_json : app_state,
|
489 |
channel_info_json : channel_info,
|
490 |
desc_md : gr.Markdown("### step3"),
|
|
|
495 |
|
496 |
# step3 -> Stage2.decode data
|
497 |
elif app_state["state"] == "step3-selecting":
|
|
|
|
|
498 |
|
499 |
# save info before clicking on next_btn
|
500 |
+
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
501 |
+
prev_target_idx = channel_info["templateByName"][prev_target_name]["index"]
|
502 |
+
if selected_chkbox == []:
|
503 |
+
app_state["stage1NewOrder"][prev_target_idx] = []
|
504 |
+
else:
|
505 |
selected_idx = [channel_info["inputByName"][channel]["index"] for channel in selected_chkbox]
|
506 |
+
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
507 |
+
#print(f'{prev_target_name}({prev_target_idx}): {selected_chkbox}')
|
508 |
+
|
509 |
+
gr.Info('The mapping process is finished!')
|
510 |
+
app_state["state"] = "finished"
|
511 |
+
print('step3 -> Stage2')
|
512 |
+
|
513 |
+
app_state["missingTemplates"] = [channel for channel in channel_info["templateByIndex"]
|
514 |
+
if channel_info["templateByName"][channel]["matched"]==False]
|
515 |
|
516 |
return {app_state_json : app_state,
|
517 |
desc_md : gr.Markdown(visible=False),
|
|
|
526 |
chkbox_group, fillmode_btn, step2_btn, next_btn, run_btn]
|
527 |
).success(
|
528 |
fn = None,
|
529 |
+
js = init_js,
|
530 |
inputs = [app_state_json, channel_info_json],
|
531 |
outputs = []
|
532 |
)
|
|
|
536 |
def update_radio(app_state, channel_info, selected):
|
537 |
|
538 |
# save info before clicking on next_btn
|
539 |
+
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
540 |
+
prev_target_idx = channel_info["templateByName"][prev_target_name]["index"]
|
541 |
+
if selected == []:
|
542 |
+
app_state["stage1NewOrder"][prev_target_idx] = []
|
543 |
+
else:
|
544 |
selected_idx = channel_info["inputByName"][selected]["index"]
|
545 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
546 |
|
547 |
channel_info["templateByName"][prev_target_name]["matched"] = True
|
548 |
channel_info["inputByName"][selected]["assigned"] = True
|
549 |
+
print(prev_target_name, '<-', selected)
|
550 |
|
551 |
# update the current round
|
552 |
app_state["fillingCount"] += 1
|
553 |
+
app_state["stage1UnassignedInputs"] = [channel for channel in channel_info["inputByIndex"]
|
554 |
+
if channel_info["inputByName"][channel]["assigned"]==False]
|
555 |
|
556 |
+
target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
|
|
557 |
radio_label = target_name+' ('+str(app_state["fillingCount"])+'/'+str(app_state["totalFillingNum"])+')'
|
558 |
|
559 |
+
if len(app_state["stage1UnassignedInputs"])==1 or app_state["fillingCount"]==app_state["totalFillingNum"]:
|
560 |
return {app_state_json : app_state,
|
561 |
channel_info_json : channel_info,
|
562 |
+
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=radio_label),
|
563 |
step2_btn : gr.Button(visible=False),
|
564 |
next_btn : gr.Button("Next step", visible=True)}
|
565 |
else:
|
566 |
return {app_state_json : app_state,
|
567 |
channel_info_json : channel_info,
|
568 |
+
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=radio_label)}
|
569 |
|
570 |
step2_btn.click(
|
571 |
fn = update_radio,
|
|
|
580 |
)
|
581 |
|
582 |
# step3
|
|
|
|
|
583 |
def fill_value(app_state, channel_info, fill_mode):
|
584 |
|
585 |
if fill_mode == 'zero':
|
|
|
596 |
app_state["state"] = "step3-selecting"
|
597 |
app_state = find_neighbors(app_state, channel_info, fill_mode)
|
598 |
|
599 |
+
name = app_state["missingTemplates"][0]
|
600 |
idx = channel_info["templateByName"][name]["index"]
|
601 |
value = app_state["stage1NewOrder"][idx]
|
602 |
value = [channel_info["inputByIndex"][i] for i in value]
|
|
|
609 |
value=value, label=label, visible=True),
|
610 |
step3_btn : gr.Button(visible=True)}
|
611 |
|
612 |
+
fillmode_btn.click(
|
613 |
+
fn = fill_value,
|
614 |
+
inputs = [app_state_json, channel_info_json, in_fill_mode],
|
615 |
+
outputs = [app_state_json, in_fill_mode, fillmode_btn, chkbox_group, step3_btn, run_btn]
|
616 |
+
).success(
|
617 |
+
fn = None,
|
618 |
+
js = init_js,
|
619 |
+
inputs = [app_state_json, channel_info_json],
|
620 |
+
outputs = []
|
621 |
+
)
|
622 |
+
|
623 |
def update_chkbox(app_state, channel_info, selected):
|
624 |
|
625 |
# save info before clicking on next_btn
|
626 |
+
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
627 |
+
prev_target_idx = channel_info["templateByName"][prev_target_name]["index"]
|
628 |
+
if selected == []:
|
629 |
+
app_state["stage1NewOrder"][prev_target_idx] = []
|
630 |
+
else:
|
631 |
selected_idx = [channel_info["inputByName"][channel]["index"] for channel in selected]
|
632 |
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
633 |
+
#print('Selection for missing channel "{}"({}): {}'.format(prev_target_name, prev_target_idx, selected))
|
|
|
634 |
|
635 |
+
# update the current round
|
636 |
app_state["fillingCount"] += 1
|
637 |
|
638 |
+
target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
639 |
target_idx = channel_info["templateByName"][target_name]["index"]
|
640 |
|
641 |
chkbox_value = app_state["stage1NewOrder"][target_idx]
|
|
|
672 |
|
673 |
def reset_run(app_state, channel_info, raw_data, model_name):
|
674 |
filepath = app_state["filepath"]
|
675 |
+
delete_file(filepath+'mapped.csv')
|
676 |
+
delete_file(filepath+'denoised.csv')
|
677 |
+
|
678 |
input_name = os.path.basename(str(raw_data))
|
679 |
output_name = os.path.splitext(input_name)[0]+'_'+model_name+'.csv'
|
680 |
|
681 |
+
in_num = len(channel_info["inputByIndex"])
|
682 |
+
matched_num = len([channel for channel in channel_info["inputByIndex"]
|
683 |
if channel_info["inputByName"][channel]["matched"]==True])
|
684 |
batch_num = math.ceil((in_num-matched_num)/30) + 1
|
685 |
|
|
|
688 |
"runnigState" : "stage1",
|
689 |
"batchCount" : 1,
|
690 |
"totalBatchNum" : batch_num,
|
691 |
+
"stage2UnassignedInputs" : app_state["stage1UnassignedInputs"],
|
692 |
+
"stage2NewOrder" : [[]]*30,
|
693 |
})
|
694 |
|
695 |
+
# reset in.assigned back to the state after Stage1
|
696 |
+
for channel in app_state["stage1UnassignedInputs"]:
|
697 |
+
channel_info["inputByName"][channel]["assigned"] = False
|
698 |
+
|
699 |
return {app_state_json : app_state,
|
700 |
+
channel_info_json : channel_info,
|
701 |
run_btn : gr.Button(interactive=False),
|
702 |
batch_md : gr.Markdown(visible=False),
|
703 |
out_denoised_data : gr.File(visible=False)}
|
|
|
717 |
if app_state["batchCount"] > 1:
|
718 |
app_state, channel_info = mapping_stage2(app_state, channel_info, fill_mode)
|
719 |
if app_state["runnigState"] == "finished":
|
720 |
+
#yield {batch_md : gr.Markdown("error", visible=True)}
|
721 |
break
|
722 |
|
723 |
reorder_to_template(app_state, raw_data)
|
|
|
743 |
run_btn.click(
|
744 |
fn = reset_run,
|
745 |
inputs = [app_state_json, channel_info_json, in_raw_data, in_model_name],
|
746 |
+
outputs = [app_state_json, channel_info_json, run_btn, batch_md, out_denoised_data]
|
747 |
|
748 |
).success(
|
749 |
fn = run_model,
|
channel_mapping.py
CHANGED
@@ -15,8 +15,8 @@ def reorder_to_template(app_state, filename):
|
|
15 |
old_data = utils.read_train_data(filename) # original raw data
|
16 |
new_data = np.zeros((30, old_data.shape[1])) # reordered raw data
|
17 |
new_filename = app_state["filepath"]+'mapped.csv'
|
18 |
-
print('new order 1:', app_state["stage1NewOrder"])
|
19 |
-
print('new order 2:', app_state["stage2NewOrder"])
|
20 |
|
21 |
zero_arr = np.zeros((1, old_data.shape[1]))
|
22 |
old_data = np.concatenate((old_data, zero_arr), axis=0)
|
@@ -41,7 +41,7 @@ def reorder_to_origin(app_state, channel_info, filename, new_filename):
|
|
41 |
template_order = channel_info["templateByIndex"]
|
42 |
|
43 |
if app_state["runnigState"] == "stage1":
|
44 |
-
new_data = np.zeros((len(channel_info["
|
45 |
else:
|
46 |
new_data = utils.read_train_data(new_filename)
|
47 |
|
@@ -94,7 +94,7 @@ def align_coords(channel_info, template_montage, input_montage):
|
|
94 |
input_dict = channel_info["inputByName"]
|
95 |
template_order = channel_info["templateByIndex"]
|
96 |
input_order = channel_info["inputByIndex"]
|
97 |
-
matched = [channel for channel in
|
98 |
|
99 |
# 2-d (for the indication of missing template channel's position when fill_mode:'mean_manual')
|
100 |
fig = [template_montage.plot(), input_montage.plot()]
|
@@ -168,8 +168,8 @@ def find_neighbors(app_state, channel_info, fill_mode):
|
|
168 |
template_order = channel_info["templateByIndex"]
|
169 |
input_order = channel_info["inputByIndex"]
|
170 |
#z_row_idx = channel_info["dataShape"][0]
|
171 |
-
|
172 |
-
if
|
173 |
return app_state # change mothing
|
174 |
|
175 |
|
@@ -177,11 +177,11 @@ def find_neighbors(app_state, channel_info, fill_mode):
|
|
177 |
in_coords = np.array([in_coords[i] for i in range(len(in_coords))])
|
178 |
|
179 |
# use KNN to choose k nearest channels
|
180 |
-
k = 4 if len(
|
181 |
knn = NearestNeighbors(n_neighbors=k, metric='euclidean')
|
182 |
knn.fit(in_coords)
|
183 |
|
184 |
-
for channel in
|
185 |
distances, indices = knn.kneighbors(np.array(template_dict[channel]["coord"]).reshape(1,-1))
|
186 |
selected = [input_order[i] for i in indices[0]]
|
187 |
print(channel, ':', selected)
|
@@ -202,8 +202,8 @@ def mapping_stage1(app_state, channel_info, loc_file):
|
|
202 |
|
203 |
template_montage, input_montage, template_dict, input_dict = read_montage_data(loc_file)
|
204 |
template_order = template_montage.ch_names
|
|
|
205 |
new_idx = [[]]*30
|
206 |
-
missing_channels = []
|
207 |
alias = {
|
208 |
'T3': 'T7',
|
209 |
'T4': 'T8',
|
@@ -227,19 +227,18 @@ def mapping_stage1(app_state, channel_info, loc_file):
|
|
227 |
template_dict[channel].matched = True
|
228 |
input_dict[channel].matched = True
|
229 |
input_dict[channel].assigned = True
|
230 |
-
else:
|
231 |
-
missing_channels.append(channel)
|
232 |
|
233 |
channel_info.update({
|
234 |
-
"missingChannels" : missing_channels,
|
235 |
"templateByName" : {k : v.__dict__ for k,v in template_dict.items()},
|
236 |
"inputByName" : {k : v.__dict__ for k,v in input_dict.items()},
|
237 |
-
"templateByIndex" :
|
238 |
-
"inputByIndex" :
|
239 |
})
|
240 |
app_state.update({
|
241 |
"stage1NewOrder" : new_idx,
|
242 |
-
"runnigState" : "stage1"
|
|
|
|
|
243 |
})
|
244 |
|
245 |
# align input, template's coordinates
|
@@ -257,7 +256,8 @@ def mapping_stage2(app_state, channel_info, fill_mode):
|
|
257 |
template_dict = channel_info["templateByName"]
|
258 |
input_dict = channel_info["inputByName"]
|
259 |
template_order = channel_info["templateByIndex"]
|
260 |
-
|
|
|
261 |
if unassigned == []:
|
262 |
app_state["runnigState"] = "finished"
|
263 |
return app_state, channel_info
|
@@ -265,7 +265,7 @@ def mapping_stage2(app_state, channel_info, fill_mode):
|
|
265 |
tpl_coords = np.array([template_dict[channel]["coord"] for channel in template_order])
|
266 |
unassigned_coords = np.array([input_dict[channel]["coord"] for channel in unassigned])
|
267 |
|
268 |
-
#
|
269 |
for channel in template_dict:
|
270 |
template_dict[channel]["matched"] = False
|
271 |
|
@@ -302,10 +302,12 @@ def mapping_stage2(app_state, channel_info, fill_mode):
|
|
302 |
})
|
303 |
app_state.update({
|
304 |
"stage2NewOrder" : new_idx,
|
305 |
-
"runnigState" : "stage2"
|
|
|
|
|
306 |
})
|
307 |
|
308 |
-
# fill the
|
309 |
app_state = find_neighbors(app_state, channel_info, fill_mode)
|
310 |
|
311 |
second2 = time.time()
|
|
|
15 |
old_data = utils.read_train_data(filename) # original raw data
|
16 |
new_data = np.zeros((30, old_data.shape[1])) # reordered raw data
|
17 |
new_filename = app_state["filepath"]+'mapped.csv'
|
18 |
+
#print('new order 1:', app_state["stage1NewOrder"])
|
19 |
+
#print('new order 2:', app_state["stage2NewOrder"])
|
20 |
|
21 |
zero_arr = np.zeros((1, old_data.shape[1]))
|
22 |
old_data = np.concatenate((old_data, zero_arr), axis=0)
|
|
|
41 |
template_order = channel_info["templateByIndex"]
|
42 |
|
43 |
if app_state["runnigState"] == "stage1":
|
44 |
+
new_data = np.zeros((len(channel_info["inputByIndex"]), old_data.shape[1]))
|
45 |
else:
|
46 |
new_data = utils.read_train_data(new_filename)
|
47 |
|
|
|
94 |
input_dict = channel_info["inputByName"]
|
95 |
template_order = channel_info["templateByIndex"]
|
96 |
input_order = channel_info["inputByIndex"]
|
97 |
+
matched = [channel for channel in input_order if input_dict[channel]["matched"]==True]
|
98 |
|
99 |
# 2-d (for the indication of missing template channel's position when fill_mode:'mean_manual')
|
100 |
fig = [template_montage.plot(), input_montage.plot()]
|
|
|
168 |
template_order = channel_info["templateByIndex"]
|
169 |
input_order = channel_info["inputByIndex"]
|
170 |
#z_row_idx = channel_info["dataShape"][0]
|
171 |
+
missing_channels = app_state["missingTemplates"]
|
172 |
+
if missing_channels == []:
|
173 |
return app_state # change mothing
|
174 |
|
175 |
|
|
|
177 |
in_coords = np.array([in_coords[i] for i in range(len(in_coords))])
|
178 |
|
179 |
# use KNN to choose k nearest channels
|
180 |
+
k = 4 if len(input_order)>4 else len(input_order)
|
181 |
knn = NearestNeighbors(n_neighbors=k, metric='euclidean')
|
182 |
knn.fit(in_coords)
|
183 |
|
184 |
+
for channel in missing_channels:
|
185 |
distances, indices = knn.kneighbors(np.array(template_dict[channel]["coord"]).reshape(1,-1))
|
186 |
selected = [input_order[i] for i in indices[0]]
|
187 |
print(channel, ':', selected)
|
|
|
202 |
|
203 |
template_montage, input_montage, template_dict, input_dict = read_montage_data(loc_file)
|
204 |
template_order = template_montage.ch_names
|
205 |
+
input_order = input_montage.ch_names
|
206 |
new_idx = [[]]*30
|
|
|
207 |
alias = {
|
208 |
'T3': 'T7',
|
209 |
'T4': 'T8',
|
|
|
227 |
template_dict[channel].matched = True
|
228 |
input_dict[channel].matched = True
|
229 |
input_dict[channel].assigned = True
|
|
|
|
|
230 |
|
231 |
channel_info.update({
|
|
|
232 |
"templateByName" : {k : v.__dict__ for k,v in template_dict.items()},
|
233 |
"inputByName" : {k : v.__dict__ for k,v in input_dict.items()},
|
234 |
+
"templateByIndex" : template_order,
|
235 |
+
"inputByIndex" : input_order
|
236 |
})
|
237 |
app_state.update({
|
238 |
"stage1NewOrder" : new_idx,
|
239 |
+
"runnigState" : "stage1",
|
240 |
+
"stage1UnassignedInputs" : [channel for channel in input_order if input_dict[channel].assigned==False],
|
241 |
+
"missingTemplates" : [channel for channel in template_order if template_dict[channel].matched==False]
|
242 |
})
|
243 |
|
244 |
# align input, template's coordinates
|
|
|
256 |
template_dict = channel_info["templateByName"]
|
257 |
input_dict = channel_info["inputByName"]
|
258 |
template_order = channel_info["templateByIndex"]
|
259 |
+
input_order = channel_info["inputByIndex"]
|
260 |
+
unassigned = app_state["stage2UnassignedInputs"]
|
261 |
if unassigned == []:
|
262 |
app_state["runnigState"] = "finished"
|
263 |
return app_state, channel_info
|
|
|
265 |
tpl_coords = np.array([template_dict[channel]["coord"] for channel in template_order])
|
266 |
unassigned_coords = np.array([input_dict[channel]["coord"] for channel in unassigned])
|
267 |
|
268 |
+
# reset all tpl.matched to False
|
269 |
for channel in template_dict:
|
270 |
template_dict[channel]["matched"] = False
|
271 |
|
|
|
302 |
})
|
303 |
app_state.update({
|
304 |
"stage2NewOrder" : new_idx,
|
305 |
+
"runnigState" : "stage2",
|
306 |
+
"stage2UnassignedInputs" : [channel for channel in input_order if input_dict[channel]["assigned"]==False],
|
307 |
+
"missingTemplates" : [channel for channel in template_order if template_dict[channel]["matched"]==False]
|
308 |
})
|
309 |
|
310 |
+
# fill the missing_channels channels
|
311 |
app_state = find_neighbors(app_state, channel_info, fill_mode)
|
312 |
|
313 |
second2 = time.time()
|