Spaces:
Sleeping
Sleeping
Commit
·
4463626
1
Parent(s):
6ad8262
update
Browse files- app.py +72 -84
- channel_mapping.py +24 -24
app.py
CHANGED
@@ -20,6 +20,7 @@ Upload your data's channel locations in `.loc` format, which can be obtained usi
|
|
20 |
>If you cannot obtain it, we recommend you to download the standard montage <a href="">here</a>. If the channels in those files doesn't match yours, you can use **EEGLAB** to modify them to your needed montage.
|
21 |
|
22 |
## Mapping
|
|
|
23 |
|
24 |
### Step1: Mapping result
|
25 |
After clicking the mapping button, the **template montage** and the **input montage** will be displayed, with the unmatched input channels highlighted in red.
|
@@ -27,30 +28,20 @@ After clicking the mapping button, the **template montage** and the **input mont
|
|
27 |
- If some of your channels didn't match the template, you will be guided to **Step2**.
|
28 |
- If all of your channels can find corresponding template channels, but the number of channels is less then 30, you will be guided to **Step3**.
|
29 |
|
30 |
-
### Step2:
|
31 |
In this step, the template channels that didn't match yours will be displyed sequentially. You will then have the option to choose whether to fill some of your unmatched channels into them.
|
32 |
-
- If you
|
33 |
-
-
|
34 |
-
### Step3:
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
### Imputation
|
40 |
-
The models was trained using the EEG signals of 30 channels, including: `Fp1, Fp2, F7, F3, Fz, F4, F8, FT7, FC3, FCz, FC4, FT8, T7, C3, Cz, C4, T8, TP7, CP3, CPz, CP4, TP8, P7, P3, Pz, P4, P8, O1, Oz, O2`.
|
41 |
-
We expect your input data to include these channels as well.
|
42 |
-
If your data doesn't contain all of the mentioned channels, there are 3 imputation ways you can choose from:
|
43 |
-
|
44 |
-
- **zero**: fill the missing channels with zeros.
|
45 |
-
- **mean(auto)**: select 4 neareat channels for each missing channels, and we will average their values.
|
46 |
-
- **mean(manual)**: select the channels you wish to use for imputing the required one, and we will average their values. If you select nothing, zeros will be imputed. For example, you didn't have **FCZ** and you choose **FC1, FC2, FZ, CZ** to impute it(depending on the channels you have), we will compute the mean of these 4 channels and assign this new value to **FCZ**.
|
47 |
-
|
48 |
-
### Mapping result
|
49 |
-
Once the mapping process is finished, the **template montage** and the **input montage**(with the matched channels displaying their names) will be shown.
|
50 |
-
|
51 |
-
### Model
|
52 |
-
Select the model you want to use.
|
53 |
-
The detailed description of the models can be found in other pages.
|
54 |
|
55 |
"""
|
56 |
|
@@ -89,8 +80,8 @@ init_js = """
|
|
89 |
let all_elem = document.querySelectorAll(selector+" > label");
|
90 |
Array.from(all_elem).forEach((item) => {
|
91 |
channel = item.querySelector("input").getAttribute(attribute);
|
92 |
-
left = channel_info.
|
93 |
-
bottom = channel_info.
|
94 |
//console.log(`channel: ${channel}, left: ${left}, bottom: ${bottom}`);
|
95 |
|
96 |
item.style.cssText = `
|
@@ -105,8 +96,8 @@ init_js = """
|
|
105 |
|
106 |
// add indication for the missing channels
|
107 |
channel = app_state.missingTemplates[0]
|
108 |
-
left = channel_info.
|
109 |
-
bottom = channel_info.
|
110 |
|
111 |
let rule = `
|
112 |
${selector}::after{
|
@@ -150,8 +141,8 @@ update_js = """
|
|
150 |
let all_elem = document.querySelectorAll(selector+" > label");
|
151 |
Array.from(all_elem).forEach((item) => {
|
152 |
channel = item.querySelector("input").value;
|
153 |
-
left = channel_info.
|
154 |
-
bottom = channel_info.
|
155 |
//console.log(`channel: ${channel}, left: ${left}, bottom: ${bottom}`);
|
156 |
|
157 |
item.style.cssText = `
|
@@ -168,8 +159,8 @@ update_js = """
|
|
168 |
|
169 |
// update indication
|
170 |
channel = app_state.missingTemplates[app_state["fillingCount"]-1]
|
171 |
-
left = channel_info.
|
172 |
-
bottom = channel_info.
|
173 |
|
174 |
let rule = `
|
175 |
${selector}::after{
|
@@ -207,7 +198,7 @@ with gr.Blocks() as demo:
|
|
207 |
with gr.Row():
|
208 |
gr.Markdown(
|
209 |
"""
|
210 |
-
<p style="text-align: center;"
|
211 |
"""
|
212 |
)
|
213 |
with gr.Row():
|
@@ -239,7 +230,7 @@ with gr.Blocks() as demo:
|
|
239 |
with gr.Row():
|
240 |
in_fill_mode = gr.Dropdown(choices=["mean", "zero"],
|
241 |
value="mean",
|
242 |
-
label="
|
243 |
visible=False,
|
244 |
scale=2)
|
245 |
fillmode_btn = gr.Button("OK", visible=False, scale=1)
|
@@ -258,9 +249,7 @@ with gr.Blocks() as demo:
|
|
258 |
("ART", "EEGART"),
|
259 |
("IC-U-Net", "ICUNet"),
|
260 |
("IC-U-Net++", "UNetpp"),
|
261 |
-
("IC-U-Net-Attn", "AttUnet"),
|
262 |
-
"(mapped data)",
|
263 |
-
"(denoised data)"],
|
264 |
value="EEGART",
|
265 |
label="Model",
|
266 |
scale=2)
|
@@ -359,20 +348,20 @@ with gr.Blocks() as demo:
|
|
359 |
# plot red dots on unmatched input channels
|
360 |
ax = raw_fig.axes[0]
|
361 |
coords = ax.collections[0].get_offsets().data
|
362 |
-
idx = [channel_info["
|
363 |
ax.scatter(coords[idx,0]-0.0001, coords[idx,1]+0.0001, color='red')
|
364 |
raw_fig.savefig(filename2, pad_inches=0)
|
365 |
|
366 |
# ------------------determine the next step-----------------------
|
367 |
|
368 |
-
in_num = len(channel_info["
|
369 |
matched_num = 30 - len(app_state["missingTemplates"])
|
370 |
|
371 |
# if the input channels(>=30) has all the 30 template channels
|
372 |
# -> Stage2.decode data
|
373 |
if matched_num == 30:
|
374 |
app_state["stage1State"] = "finished"
|
375 |
-
gr.Info('The mapping process
|
376 |
|
377 |
return {app_state_json : app_state,
|
378 |
desc_md : gr.Markdown("### Mapping result", visible=True),
|
@@ -418,8 +407,8 @@ with gr.Blocks() as demo:
|
|
418 |
# stage1-1 -> stage1-2
|
419 |
if app_state["stage1State"] == "step2-initializing":
|
420 |
print('step1 -> step2')
|
421 |
-
app_state["missingTemplates"] = [channel for channel in channel_info["
|
422 |
-
if channel_info["
|
423 |
app_state.update({
|
424 |
"stage1State" : "step2-selecting",
|
425 |
"fillingCount" : 1,
|
@@ -432,7 +421,7 @@ with gr.Blocks() as demo:
|
|
432 |
if len(app_state["stage1UnassignedInputs"])==1 or app_state["totalFillingNum"]==1:
|
433 |
return {app_state_json : app_state,
|
434 |
channel_info_json : channel_info,
|
435 |
-
desc_md : gr.Markdown("### Step2"),
|
436 |
tpl_montage : gr.Image(visible=False),
|
437 |
in_montage : gr.Image(visible=False),
|
438 |
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=label, visible=True),
|
@@ -440,7 +429,7 @@ with gr.Blocks() as demo:
|
|
440 |
else:
|
441 |
return {app_state_json : app_state,
|
442 |
channel_info_json : channel_info,
|
443 |
-
desc_md : gr.Markdown("### Step2"),
|
444 |
tpl_montage : gr.Image(visible=False),
|
445 |
in_montage : gr.Image(visible=False),
|
446 |
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=label, visible=True),
|
@@ -450,8 +439,8 @@ with gr.Blocks() as demo:
|
|
450 |
# stage1-1 -> stage1-3
|
451 |
elif app_state["stage1State"] == "step3-initializing":
|
452 |
print('step1 -> step3')
|
453 |
-
app_state["missingTemplates"] = [channel for channel in channel_info["
|
454 |
-
if channel_info["
|
455 |
app_state.update({
|
456 |
"stage1State" : "step3-initializing",
|
457 |
"fillingCount" : 1,
|
@@ -459,7 +448,7 @@ with gr.Blocks() as demo:
|
|
459 |
})
|
460 |
return {app_state_json : app_state,
|
461 |
channel_info_json : channel_info,
|
462 |
-
desc_md : gr.Markdown("### Step3"),
|
463 |
tpl_montage : gr.Image(visible=False),
|
464 |
in_montage : gr.Image(visible=False),
|
465 |
in_fill_mode : gr.Dropdown(visible=True),
|
@@ -471,29 +460,29 @@ with gr.Blocks() as demo:
|
|
471 |
|
472 |
# save info before clicking on next_btn
|
473 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
474 |
-
prev_target_idx = channel_info["
|
475 |
if selected_radio == []:
|
476 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
477 |
else:
|
478 |
-
selected_idx = channel_info["
|
479 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
480 |
|
481 |
-
channel_info["
|
482 |
-
channel_info["
|
483 |
print(prev_target_name, '<-', selected_radio)
|
484 |
|
485 |
app_state.update({
|
486 |
-
"stage1UnassignedInputs" : [channel for channel in channel_info["
|
487 |
-
if channel_info["
|
488 |
-
"missingTemplates" : [channel for channel in channel_info["
|
489 |
-
if channel_info["
|
490 |
})
|
491 |
|
492 |
# if all the unmatched template channels were filled by input channels
|
493 |
# -> stage2
|
494 |
if len(app_state["missingTemplates"]) == 0:
|
495 |
print('step2 -> Stage2')
|
496 |
-
gr.Info('The mapping process
|
497 |
app_state["stage1State"] = "finished"
|
498 |
|
499 |
return {app_state_json : app_state,
|
@@ -513,7 +502,7 @@ with gr.Blocks() as demo:
|
|
513 |
})
|
514 |
return {app_state_json : app_state,
|
515 |
channel_info_json : channel_info,
|
516 |
-
desc_md : gr.Markdown("### Step3"),
|
517 |
radio : gr.Radio(visible=False),
|
518 |
in_fill_mode : gr.Dropdown(visible=True),
|
519 |
fillmode_btn : gr.Button(visible=True),
|
@@ -524,20 +513,20 @@ with gr.Blocks() as demo:
|
|
524 |
|
525 |
# save info before clicking on next_btn
|
526 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
527 |
-
prev_target_idx = channel_info["
|
528 |
if selected_chkbox == []:
|
529 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
530 |
else:
|
531 |
-
selected_idx = [channel_info["
|
532 |
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
533 |
#print(f'{prev_target_name}({prev_target_idx}): {selected_chkbox}')
|
534 |
|
535 |
-
gr.Info('The mapping process
|
536 |
app_state["stage1State"] = "finished"
|
537 |
print('step3 -> Stage2')
|
538 |
|
539 |
-
app_state["missingTemplates"] = [channel for channel in channel_info["
|
540 |
-
if channel_info["
|
541 |
|
542 |
return {app_state_json : app_state,
|
543 |
desc_md : gr.Markdown(visible=False),
|
@@ -563,21 +552,21 @@ with gr.Blocks() as demo:
|
|
563 |
|
564 |
# save info before clicking on next_btn
|
565 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
566 |
-
prev_target_idx = channel_info["
|
567 |
if selected == []:
|
568 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
569 |
else:
|
570 |
-
selected_idx = channel_info["
|
571 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
572 |
|
573 |
-
channel_info["
|
574 |
-
channel_info["
|
575 |
print(prev_target_name, '<-', selected)
|
576 |
|
577 |
# update the current round
|
578 |
app_state["fillingCount"] += 1
|
579 |
-
app_state["stage1UnassignedInputs"] = [channel for channel in channel_info["
|
580 |
-
if channel_info["
|
581 |
|
582 |
target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
583 |
radio_label = target_name+' ('+str(app_state["fillingCount"])+'/'+str(app_state["totalFillingNum"])+')'
|
@@ -610,7 +599,7 @@ with gr.Blocks() as demo:
|
|
610 |
|
611 |
if fill_mode == 'zero':
|
612 |
app_state["stage1State"] = "finished"
|
613 |
-
gr.Info('The mapping process
|
614 |
|
615 |
return {app_state_json : app_state,
|
616 |
desc_md : gr.Markdown(visible=False),
|
@@ -623,23 +612,23 @@ with gr.Blocks() as demo:
|
|
623 |
app_state = find_neighbors(app_state, channel_info, fill_mode)
|
624 |
|
625 |
name = app_state["missingTemplates"][0]
|
626 |
-
idx = channel_info["
|
627 |
value = app_state["stage1NewOrder"][idx]
|
628 |
-
value = [channel_info["
|
629 |
label = name+' (1/'+str(app_state["totalFillingNum"])+')'
|
630 |
|
631 |
if app_state["totalFillingNum"] == 1:
|
632 |
return {app_state_json : app_state,
|
633 |
in_fill_mode : gr.Dropdown(visible=False),
|
634 |
fillmode_btn : gr.Button(visible=False),
|
635 |
-
chkbox_group : gr.CheckboxGroup(choices=channel_info["
|
636 |
value=value, label=label, visible=True),
|
637 |
next_btn : gr.Button(visible=True)}
|
638 |
else:
|
639 |
return {app_state_json : app_state,
|
640 |
in_fill_mode : gr.Dropdown(visible=False),
|
641 |
fillmode_btn : gr.Button(visible=False),
|
642 |
-
chkbox_group : gr.CheckboxGroup(choices=channel_info["
|
643 |
value=value, label=label, visible=True),
|
644 |
step3_btn : gr.Button(visible=True)}
|
645 |
|
@@ -658,11 +647,11 @@ with gr.Blocks() as demo:
|
|
658 |
|
659 |
# save info before clicking on next_btn
|
660 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
661 |
-
prev_target_idx = channel_info["
|
662 |
if selected == []:
|
663 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
664 |
else:
|
665 |
-
selected_idx = [channel_info["
|
666 |
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
667 |
#print('Selection for missing channel "{}"({}): {}'.format(prev_target_name, prev_target_idx, selected))
|
668 |
|
@@ -670,10 +659,10 @@ with gr.Blocks() as demo:
|
|
670 |
app_state["fillingCount"] += 1
|
671 |
|
672 |
target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
673 |
-
target_idx = channel_info["
|
674 |
|
675 |
chkbox_value = app_state["stage1NewOrder"][target_idx]
|
676 |
-
chkbox_value = [channel_info["
|
677 |
chkbox_label = target_name+' ('+str(app_state["fillingCount"])+'/'+str(app_state["totalFillingNum"])+')'
|
678 |
|
679 |
if app_state["fillingCount"] == app_state["totalFillingNum"]:
|
@@ -706,6 +695,11 @@ with gr.Blocks() as demo:
|
|
706 |
|
707 |
# stage2
|
708 |
def reset_run(app_state, channel_info, raw_data, model_name):
|
|
|
|
|
|
|
|
|
|
|
709 |
filepath = app_state["filepath"]
|
710 |
delete_file(filepath+'mapped.csv')
|
711 |
delete_file(filepath+'denoised.csv')
|
@@ -713,10 +707,9 @@ with gr.Blocks() as demo:
|
|
713 |
input_name = os.path.basename(str(raw_data))
|
714 |
output_name = os.path.splitext(input_name)[0]+'_'+model_name+'.csv'
|
715 |
|
716 |
-
in_num = len(channel_info["
|
717 |
-
|
718 |
-
|
719 |
-
batch_num = math.ceil((in_num-matched_num)/30) + 1
|
720 |
|
721 |
app_state["filenames"]["denoised"] = filepath + output_name
|
722 |
app_state.update({
|
@@ -726,11 +719,6 @@ with gr.Blocks() as demo:
|
|
726 |
"stage2UnassignedInputs" : app_state["stage1UnassignedInputs"],
|
727 |
"stage2NewOrder" : [[]]*30,
|
728 |
})
|
729 |
-
|
730 |
-
# reset in.assigned back to the state after Stage1
|
731 |
-
for channel in app_state["stage1UnassignedInputs"]:
|
732 |
-
channel_info["inputByName"][channel]["assigned"] = False
|
733 |
-
|
734 |
return {app_state_json : app_state,
|
735 |
channel_info_json : channel_info,
|
736 |
run_btn : gr.Button(interactive=False),
|
@@ -787,4 +775,4 @@ with gr.Blocks() as demo:
|
|
787 |
)
|
788 |
|
789 |
if __name__ == "__main__":
|
790 |
-
demo.launch(
|
|
|
20 |
>If you cannot obtain it, we recommend you to download the standard montage <a href="">here</a>. If the channels in those files doesn't match yours, you can use **EEGLAB** to modify them to your needed montage.
|
21 |
|
22 |
## Mapping
|
23 |
+
...
|
24 |
|
25 |
### Step1: Mapping result
|
26 |
After clicking the mapping button, the **template montage** and the **input montage** will be displayed, with the unmatched input channels highlighted in red.
|
|
|
28 |
- If some of your channels didn't match the template, you will be guided to **Step2**.
|
29 |
- If all of your channels can find corresponding template channels, but the number of channels is less then 30, you will be guided to **Step3**.
|
30 |
|
31 |
+
### Step2: Assign unmatched input channels into some template channels
|
32 |
In this step, the template channels that didn't match yours will be displyed sequentially. You will then have the option to choose whether to fill some of your unmatched channels into them.
|
33 |
+
- If you filled all the template channels with your unmatched channels, you can then proceed to **run the model**.
|
34 |
+
- If there're still some template channels that have not been filled with your unmatched channels, you will be guided to **Step3**.
|
|
|
35 |
|
36 |
+
### Step3: Fill the remaining template channels
|
37 |
+
The purpose of this step is to select a method to fill the unmatched template channels that were not filled in Step2.
|
38 |
+
There're two methods you can choose from:
|
39 |
+
- Mean : The remaining template channels will be displyed sequentially, and you can choose to fill them using multiple input channels. For each remaining template channels, the average value of the selected input channels will be assigned to it. By default, the 4 nearest input channels to each remaining template channels will be pre-selected, but you can choose whether to modify this selection. (If you uncheck the 4 selections, zeros will be filled to that channel.)
|
40 |
+
- Zero : Zeros will be filled into all the remaining template channels.
|
41 |
+
After filling all the template channels, you can then proceed to **run the model**.
|
42 |
|
43 |
+
## Run model
|
44 |
+
...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
"""
|
47 |
|
|
|
80 |
let all_elem = document.querySelectorAll(selector+" > label");
|
81 |
Array.from(all_elem).forEach((item) => {
|
82 |
channel = item.querySelector("input").getAttribute(attribute);
|
83 |
+
left = channel_info.inputDict[channel].css_position[0];
|
84 |
+
bottom = channel_info.inputDict[channel].css_position[1];
|
85 |
//console.log(`channel: ${channel}, left: ${left}, bottom: ${bottom}`);
|
86 |
|
87 |
item.style.cssText = `
|
|
|
96 |
|
97 |
// add indication for the missing channels
|
98 |
channel = app_state.missingTemplates[0]
|
99 |
+
left = channel_info.templateDict[channel].css_position[0];
|
100 |
+
bottom = channel_info.templateDict[channel].css_position[1];
|
101 |
|
102 |
let rule = `
|
103 |
${selector}::after{
|
|
|
141 |
let all_elem = document.querySelectorAll(selector+" > label");
|
142 |
Array.from(all_elem).forEach((item) => {
|
143 |
channel = item.querySelector("input").value;
|
144 |
+
left = channel_info.inputDict[channel].css_position[0];
|
145 |
+
bottom = channel_info.inputDict[channel].css_position[1];
|
146 |
//console.log(`channel: ${channel}, left: ${left}, bottom: ${bottom}`);
|
147 |
|
148 |
item.style.cssText = `
|
|
|
159 |
|
160 |
// update indication
|
161 |
channel = app_state.missingTemplates[app_state["fillingCount"]-1]
|
162 |
+
left = channel_info.templateDict[channel].css_position[0];
|
163 |
+
bottom = channel_info.templateDict[channel].css_position[1];
|
164 |
|
165 |
let rule = `
|
166 |
${selector}::after{
|
|
|
198 |
with gr.Row():
|
199 |
gr.Markdown(
|
200 |
"""
|
201 |
+
<p style="text-align: center;">...</p>
|
202 |
"""
|
203 |
)
|
204 |
with gr.Row():
|
|
|
230 |
with gr.Row():
|
231 |
in_fill_mode = gr.Dropdown(choices=["mean", "zero"],
|
232 |
value="mean",
|
233 |
+
label="Filling method",
|
234 |
visible=False,
|
235 |
scale=2)
|
236 |
fillmode_btn = gr.Button("OK", visible=False, scale=1)
|
|
|
249 |
("ART", "EEGART"),
|
250 |
("IC-U-Net", "ICUNet"),
|
251 |
("IC-U-Net++", "UNetpp"),
|
252 |
+
("IC-U-Net-Attn", "AttUnet")],
|
|
|
|
|
253 |
value="EEGART",
|
254 |
label="Model",
|
255 |
scale=2)
|
|
|
348 |
# plot red dots on unmatched input channels
|
349 |
ax = raw_fig.axes[0]
|
350 |
coords = ax.collections[0].get_offsets().data
|
351 |
+
idx = [channel_info["inputDict"][channel]["index"] for channel in app_state["stage1UnassignedInputs"]]
|
352 |
ax.scatter(coords[idx,0]-0.0001, coords[idx,1]+0.0001, color='red')
|
353 |
raw_fig.savefig(filename2, pad_inches=0)
|
354 |
|
355 |
# ------------------determine the next step-----------------------
|
356 |
|
357 |
+
in_num = len(channel_info["inputOrder"])
|
358 |
matched_num = 30 - len(app_state["missingTemplates"])
|
359 |
|
360 |
# if the input channels(>=30) has all the 30 template channels
|
361 |
# -> Stage2.decode data
|
362 |
if matched_num == 30:
|
363 |
app_state["stage1State"] = "finished"
|
364 |
+
gr.Info('The mapping process has been finished.')
|
365 |
|
366 |
return {app_state_json : app_state,
|
367 |
desc_md : gr.Markdown("### Mapping result", visible=True),
|
|
|
407 |
# stage1-1 -> stage1-2
|
408 |
if app_state["stage1State"] == "step2-initializing":
|
409 |
print('step1 -> step2')
|
410 |
+
app_state["missingTemplates"] = [channel for channel in channel_info["templateOrder"]
|
411 |
+
if channel_info["templateDict"][channel]["matched"]==False]
|
412 |
app_state.update({
|
413 |
"stage1State" : "step2-selecting",
|
414 |
"fillingCount" : 1,
|
|
|
421 |
if len(app_state["stage1UnassignedInputs"])==1 or app_state["totalFillingNum"]==1:
|
422 |
return {app_state_json : app_state,
|
423 |
channel_info_json : channel_info,
|
424 |
+
desc_md : gr.Markdown("### Step2: Assign unmatched input channels"),
|
425 |
tpl_montage : gr.Image(visible=False),
|
426 |
in_montage : gr.Image(visible=False),
|
427 |
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=label, visible=True),
|
|
|
429 |
else:
|
430 |
return {app_state_json : app_state,
|
431 |
channel_info_json : channel_info,
|
432 |
+
desc_md : gr.Markdown("### Step2: Assign unmatched input channels"),
|
433 |
tpl_montage : gr.Image(visible=False),
|
434 |
in_montage : gr.Image(visible=False),
|
435 |
radio : gr.Radio(choices=app_state["stage1UnassignedInputs"], value=[], label=label, visible=True),
|
|
|
439 |
# stage1-1 -> stage1-3
|
440 |
elif app_state["stage1State"] == "step3-initializing":
|
441 |
print('step1 -> step3')
|
442 |
+
app_state["missingTemplates"] = [channel for channel in channel_info["templateOrder"]
|
443 |
+
if channel_info["templateDict"][channel]["matched"]==False]
|
444 |
app_state.update({
|
445 |
"stage1State" : "step3-initializing",
|
446 |
"fillingCount" : 1,
|
|
|
448 |
})
|
449 |
return {app_state_json : app_state,
|
450 |
channel_info_json : channel_info,
|
451 |
+
desc_md : gr.Markdown("### Step3: Fill the remaining template channels"),
|
452 |
tpl_montage : gr.Image(visible=False),
|
453 |
in_montage : gr.Image(visible=False),
|
454 |
in_fill_mode : gr.Dropdown(visible=True),
|
|
|
460 |
|
461 |
# save info before clicking on next_btn
|
462 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
463 |
+
prev_target_idx = channel_info["templateDict"][prev_target_name]["index"]
|
464 |
if selected_radio == []:
|
465 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
466 |
else:
|
467 |
+
selected_idx = channel_info["inputDict"][selected_radio]["index"]
|
468 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
469 |
|
470 |
+
channel_info["templateDict"][prev_target_name]["matched"] = True
|
471 |
+
channel_info["inputDict"][selected_radio]["assigned"] = True
|
472 |
print(prev_target_name, '<-', selected_radio)
|
473 |
|
474 |
app_state.update({
|
475 |
+
"stage1UnassignedInputs" : [channel for channel in channel_info["inputOrder"]
|
476 |
+
if channel_info["inputDict"][channel]["assigned"]==False],
|
477 |
+
"missingTemplates" : [channel for channel in channel_info["templateOrder"]
|
478 |
+
if channel_info["templateDict"][channel]["matched"]==False]
|
479 |
})
|
480 |
|
481 |
# if all the unmatched template channels were filled by input channels
|
482 |
# -> stage2
|
483 |
if len(app_state["missingTemplates"]) == 0:
|
484 |
print('step2 -> Stage2')
|
485 |
+
gr.Info('The mapping process has been finished.')
|
486 |
app_state["stage1State"] = "finished"
|
487 |
|
488 |
return {app_state_json : app_state,
|
|
|
502 |
})
|
503 |
return {app_state_json : app_state,
|
504 |
channel_info_json : channel_info,
|
505 |
+
desc_md : gr.Markdown("### Step3: Fill the remaining template channels"),
|
506 |
radio : gr.Radio(visible=False),
|
507 |
in_fill_mode : gr.Dropdown(visible=True),
|
508 |
fillmode_btn : gr.Button(visible=True),
|
|
|
513 |
|
514 |
# save info before clicking on next_btn
|
515 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
516 |
+
prev_target_idx = channel_info["templateDict"][prev_target_name]["index"]
|
517 |
if selected_chkbox == []:
|
518 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
519 |
else:
|
520 |
+
selected_idx = [channel_info["inputDict"][channel]["index"] for channel in selected_chkbox]
|
521 |
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
522 |
#print(f'{prev_target_name}({prev_target_idx}): {selected_chkbox}')
|
523 |
|
524 |
+
gr.Info('The mapping process has been finished.')
|
525 |
app_state["stage1State"] = "finished"
|
526 |
print('step3 -> Stage2')
|
527 |
|
528 |
+
app_state["missingTemplates"] = [channel for channel in channel_info["templateOrder"]
|
529 |
+
if channel_info["templateDict"][channel]["matched"]==False]
|
530 |
|
531 |
return {app_state_json : app_state,
|
532 |
desc_md : gr.Markdown(visible=False),
|
|
|
552 |
|
553 |
# save info before clicking on next_btn
|
554 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
555 |
+
prev_target_idx = channel_info["templateDict"][prev_target_name]["index"]
|
556 |
if selected == []:
|
557 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
558 |
else:
|
559 |
+
selected_idx = channel_info["inputDict"][selected]["index"]
|
560 |
app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
|
561 |
|
562 |
+
channel_info["templateDict"][prev_target_name]["matched"] = True
|
563 |
+
channel_info["inputDict"][selected]["assigned"] = True
|
564 |
print(prev_target_name, '<-', selected)
|
565 |
|
566 |
# update the current round
|
567 |
app_state["fillingCount"] += 1
|
568 |
+
app_state["stage1UnassignedInputs"] = [channel for channel in channel_info["inputOrder"]
|
569 |
+
if channel_info["inputDict"][channel]["assigned"]==False]
|
570 |
|
571 |
target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
572 |
radio_label = target_name+' ('+str(app_state["fillingCount"])+'/'+str(app_state["totalFillingNum"])+')'
|
|
|
599 |
|
600 |
if fill_mode == 'zero':
|
601 |
app_state["stage1State"] = "finished"
|
602 |
+
gr.Info('The mapping process has been finished.')
|
603 |
|
604 |
return {app_state_json : app_state,
|
605 |
desc_md : gr.Markdown(visible=False),
|
|
|
612 |
app_state = find_neighbors(app_state, channel_info, fill_mode)
|
613 |
|
614 |
name = app_state["missingTemplates"][0]
|
615 |
+
idx = channel_info["templateDict"][name]["index"]
|
616 |
value = app_state["stage1NewOrder"][idx]
|
617 |
+
value = [channel_info["inputOrder"][i] for i in value]
|
618 |
label = name+' (1/'+str(app_state["totalFillingNum"])+')'
|
619 |
|
620 |
if app_state["totalFillingNum"] == 1:
|
621 |
return {app_state_json : app_state,
|
622 |
in_fill_mode : gr.Dropdown(visible=False),
|
623 |
fillmode_btn : gr.Button(visible=False),
|
624 |
+
chkbox_group : gr.CheckboxGroup(choices=channel_info["inputOrder"],
|
625 |
value=value, label=label, visible=True),
|
626 |
next_btn : gr.Button(visible=True)}
|
627 |
else:
|
628 |
return {app_state_json : app_state,
|
629 |
in_fill_mode : gr.Dropdown(visible=False),
|
630 |
fillmode_btn : gr.Button(visible=False),
|
631 |
+
chkbox_group : gr.CheckboxGroup(choices=channel_info["inputOrder"],
|
632 |
value=value, label=label, visible=True),
|
633 |
step3_btn : gr.Button(visible=True)}
|
634 |
|
|
|
647 |
|
648 |
# save info before clicking on next_btn
|
649 |
prev_target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
650 |
+
prev_target_idx = channel_info["templateDict"][prev_target_name]["index"]
|
651 |
if selected == []:
|
652 |
app_state["stage1NewOrder"][prev_target_idx] = []
|
653 |
else:
|
654 |
+
selected_idx = [channel_info["inputDict"][channel]["index"] for channel in selected]
|
655 |
app_state["stage1NewOrder"][prev_target_idx] = selected_idx
|
656 |
#print('Selection for missing channel "{}"({}): {}'.format(prev_target_name, prev_target_idx, selected))
|
657 |
|
|
|
659 |
app_state["fillingCount"] += 1
|
660 |
|
661 |
target_name = app_state["missingTemplates"][app_state["fillingCount"]-1]
|
662 |
+
target_idx = channel_info["templateDict"][target_name]["index"]
|
663 |
|
664 |
chkbox_value = app_state["stage1NewOrder"][target_idx]
|
665 |
+
chkbox_value = [channel_info["inputOrder"][i] for i in chkbox_value]
|
666 |
chkbox_label = target_name+' ('+str(app_state["fillingCount"])+'/'+str(app_state["totalFillingNum"])+')'
|
667 |
|
668 |
if app_state["fillingCount"] == app_state["totalFillingNum"]:
|
|
|
695 |
|
696 |
# stage2
|
697 |
def reset_run(app_state, channel_info, raw_data, model_name):
|
698 |
+
|
699 |
+
# reset in.assigned back to the state after Stage1
|
700 |
+
for channel in app_state["stage1UnassignedInputs"]:
|
701 |
+
channel_info["inputDict"][channel]["assigned"] = False
|
702 |
+
|
703 |
filepath = app_state["filepath"]
|
704 |
delete_file(filepath+'mapped.csv')
|
705 |
delete_file(filepath+'denoised.csv')
|
|
|
707 |
input_name = os.path.basename(str(raw_data))
|
708 |
output_name = os.path.splitext(input_name)[0]+'_'+model_name+'.csv'
|
709 |
|
710 |
+
in_num = len(channel_info["inputOrder"])
|
711 |
+
assigned_num = len(app_state["stage1UnassignedInputs"])
|
712 |
+
batch_num = math.ceil((in_num-assigned_num)/30) + 1
|
|
|
713 |
|
714 |
app_state["filenames"]["denoised"] = filepath + output_name
|
715 |
app_state.update({
|
|
|
719 |
"stage2UnassignedInputs" : app_state["stage1UnassignedInputs"],
|
720 |
"stage2NewOrder" : [[]]*30,
|
721 |
})
|
|
|
|
|
|
|
|
|
|
|
722 |
return {app_state_json : app_state,
|
723 |
channel_info_json : channel_info,
|
724 |
run_btn : gr.Button(interactive=False),
|
|
|
775 |
)
|
776 |
|
777 |
if __name__ == "__main__":
|
778 |
+
demo.launch()
|
channel_mapping.py
CHANGED
@@ -38,10 +38,10 @@ def reorder_to_template(app_state, filename):
|
|
38 |
def reorder_to_origin(app_state, channel_info, filename, new_filename):
|
39 |
old_idx = app_state["stage1NewOrder"] if app_state["runningState"]=="stage1" else app_state["stage2NewOrder"]
|
40 |
old_data = utils.read_train_data(filename) # denoised data
|
41 |
-
template_order = channel_info["
|
42 |
|
43 |
if app_state["runningState"] == "stage1":
|
44 |
-
new_data = np.zeros((len(channel_info["
|
45 |
else:
|
46 |
new_data = utils.read_train_data(new_filename)
|
47 |
|
@@ -49,7 +49,7 @@ def reorder_to_origin(app_state, channel_info, filename, new_filename):
|
|
49 |
idx_set = old_idx[i]
|
50 |
|
51 |
# ignore if this channel doesn't exist
|
52 |
-
if len(idx_set)==1 and channel_info["
|
53 |
new_data[idx_set[0], :] = old_data[i, :]
|
54 |
|
55 |
print('old.shape, new.shape: ', old_data.shape, new_data.shape)
|
@@ -90,10 +90,10 @@ def read_montage_data(loc_file):
|
|
90 |
|
91 |
def align_coords(channel_info, template_montage, input_montage):
|
92 |
|
93 |
-
template_dict = channel_info["
|
94 |
-
input_dict = channel_info["
|
95 |
-
template_order = channel_info["
|
96 |
-
input_order = channel_info["
|
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')
|
@@ -156,17 +156,17 @@ def align_coords(channel_info, template_montage, input_montage):
|
|
156 |
input_dict[channel]["coord"] = transformed_in[i].tolist()
|
157 |
|
158 |
channel_info.update({
|
159 |
-
"
|
160 |
-
"
|
161 |
})
|
162 |
return channel_info
|
163 |
|
164 |
def find_neighbors(app_state, channel_info, fill_mode):
|
165 |
new_idx = app_state["stage1NewOrder"] if app_state["runningState"]=="stage1" else app_state["stage2NewOrder"]
|
166 |
-
template_dict = channel_info["
|
167 |
-
input_dict = channel_info["
|
168 |
-
template_order = channel_info["
|
169 |
-
input_order = channel_info["
|
170 |
#z_row_idx = channel_info["dataShape"][0]
|
171 |
missing_channels = app_state["missingTemplates"]
|
172 |
if missing_channels == []:
|
@@ -184,7 +184,7 @@ def find_neighbors(app_state, channel_info, fill_mode):
|
|
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)
|
188 |
|
189 |
idx = template_dict[channel]["index"]
|
190 |
new_idx[idx] = indices[0].tolist()
|
@@ -233,10 +233,10 @@ def mapping_stage1(app_state, channel_info, loc_file):
|
|
233 |
input_order = input_montage.ch_names
|
234 |
|
235 |
channel_info.update({
|
236 |
-
"
|
237 |
-
"
|
238 |
-
"
|
239 |
-
"
|
240 |
})
|
241 |
app_state.update({
|
242 |
"stage1NewOrder" : new_idx,
|
@@ -257,10 +257,10 @@ def mapping_stage1(app_state, channel_info, loc_file):
|
|
257 |
def mapping_stage2(app_state, channel_info, fill_mode):
|
258 |
second1 = time.time()
|
259 |
|
260 |
-
template_dict = channel_info["
|
261 |
-
input_dict = channel_info["
|
262 |
-
template_order = channel_info["
|
263 |
-
input_order = channel_info["
|
264 |
unassigned = app_state["stage2UnassignedInputs"]
|
265 |
if unassigned == []:
|
266 |
app_state["runningState"] = "finished"
|
@@ -301,8 +301,8 @@ def mapping_stage2(app_state, channel_info, fill_mode):
|
|
301 |
print(template_order[row_idx[i]], '<-', unassigned[col_idx[i]])
|
302 |
|
303 |
channel_info.update({
|
304 |
-
"
|
305 |
-
"
|
306 |
})
|
307 |
app_state.update({
|
308 |
"stage2NewOrder" : new_idx,
|
|
|
38 |
def reorder_to_origin(app_state, channel_info, filename, new_filename):
|
39 |
old_idx = app_state["stage1NewOrder"] if app_state["runningState"]=="stage1" else app_state["stage2NewOrder"]
|
40 |
old_data = utils.read_train_data(filename) # denoised data
|
41 |
+
template_order = channel_info["templateOrder"]
|
42 |
|
43 |
if app_state["runningState"] == "stage1":
|
44 |
+
new_data = np.zeros((len(channel_info["inputOrder"]), old_data.shape[1]))
|
45 |
else:
|
46 |
new_data = utils.read_train_data(new_filename)
|
47 |
|
|
|
49 |
idx_set = old_idx[i]
|
50 |
|
51 |
# ignore if this channel doesn't exist
|
52 |
+
if len(idx_set)==1 and channel_info["templateDict"][channel]["matched"]==True:
|
53 |
new_data[idx_set[0], :] = old_data[i, :]
|
54 |
|
55 |
print('old.shape, new.shape: ', old_data.shape, new_data.shape)
|
|
|
90 |
|
91 |
def align_coords(channel_info, template_montage, input_montage):
|
92 |
|
93 |
+
template_dict = channel_info["templateDict"]
|
94 |
+
input_dict = channel_info["inputDict"]
|
95 |
+
template_order = channel_info["templateOrder"]
|
96 |
+
input_order = channel_info["inputOrder"]
|
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')
|
|
|
156 |
input_dict[channel]["coord"] = transformed_in[i].tolist()
|
157 |
|
158 |
channel_info.update({
|
159 |
+
"templateDict" : template_dict,
|
160 |
+
"inputDict" : input_dict,
|
161 |
})
|
162 |
return channel_info
|
163 |
|
164 |
def find_neighbors(app_state, channel_info, fill_mode):
|
165 |
new_idx = app_state["stage1NewOrder"] if app_state["runningState"]=="stage1" else app_state["stage2NewOrder"]
|
166 |
+
template_dict = channel_info["templateDict"]
|
167 |
+
input_dict = channel_info["inputDict"]
|
168 |
+
template_order = channel_info["templateOrder"]
|
169 |
+
input_order = channel_info["inputOrder"]
|
170 |
#z_row_idx = channel_info["dataShape"][0]
|
171 |
missing_channels = app_state["missingTemplates"]
|
172 |
if missing_channels == []:
|
|
|
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)
|
188 |
|
189 |
idx = template_dict[channel]["index"]
|
190 |
new_idx[idx] = indices[0].tolist()
|
|
|
233 |
input_order = input_montage.ch_names
|
234 |
|
235 |
channel_info.update({
|
236 |
+
"templateDict" : {k : v.__dict__ for k,v in template_dict.items()},
|
237 |
+
"inputDict" : {k : v.__dict__ for k,v in input_dict.items()},
|
238 |
+
"templateOrder" : template_order,
|
239 |
+
"inputOrder" : input_order
|
240 |
})
|
241 |
app_state.update({
|
242 |
"stage1NewOrder" : new_idx,
|
|
|
257 |
def mapping_stage2(app_state, channel_info, fill_mode):
|
258 |
second1 = time.time()
|
259 |
|
260 |
+
template_dict = channel_info["templateDict"]
|
261 |
+
input_dict = channel_info["inputDict"]
|
262 |
+
template_order = channel_info["templateOrder"]
|
263 |
+
input_order = channel_info["inputOrder"]
|
264 |
unassigned = app_state["stage2UnassignedInputs"]
|
265 |
if unassigned == []:
|
266 |
app_state["runningState"] = "finished"
|
|
|
301 |
print(template_order[row_idx[i]], '<-', unassigned[col_idx[i]])
|
302 |
|
303 |
channel_info.update({
|
304 |
+
"templateDict" : template_dict,
|
305 |
+
"inputDict" : input_dict
|
306 |
})
|
307 |
app_state.update({
|
308 |
"stage2NewOrder" : new_idx,
|