Spaces:
Sleeping
Sleeping
Commit
·
84cd80a
1
Parent(s):
d796428
update
Browse files- app.py +107 -120
- app_utils.py +68 -42
app.py
CHANGED
@@ -22,14 +22,14 @@ The following steps will guide you through the process of mapping your EEG chann
|
|
22 |
|
23 |
### Step1: Initial Matching and Scaling
|
24 |
After clicking on ``Map`` button, we will first match your channels to our template channels by their names. Using the matched channels as reference points, we will apply Thin Plate Spline (TPS) transformation to scale your montage to align with our template's dimensions. The template montage and your scaled montage will be displayed side by side for comparison. Channels that do not have a match in our template will be **highlighted in red**.
|
25 |
-
- If your data includes all the 30 template channels, you will be directed to **Mapping
|
26 |
- If your data doesn't include all the 30 template channels and you have some channels that do not match the template, you will be directed to **Step2**.
|
27 |
- If all your channels are included in our template but you have fewer than 30 channels, you will be directed to **Step3**.
|
28 |
|
29 |
### Step2: Forwarding Unmatched Channels
|
30 |
In this step, you will handle the channels that didn't have a direct match with our template, by manually assigning them to the template channels that are still empty, ensuring the most efficient use of your data.
|
31 |
Your unmatched channels, previously highlighted in red, will be shown on your montage with a radio button displayed above each. You can choose to forward the data from these unmatched channels to the empty template channels. The interface will display each empty template channel in sequence, allowing you to select which of your unmatched channels to forward.
|
32 |
-
- If all empty template channels are filled by your selections, you will be directed to **Mapping
|
33 |
- If there are still empty template channels remaining, you will be directed to **Step3**.
|
34 |
|
35 |
### Step3: Filling Remaining Template Channels
|
@@ -37,15 +37,15 @@ To run the models successfully, we need to ensure that all 30 template channels
|
|
37 |
- **Mean** method: Each empty template channel is filled with the average value of data from the nearest input channels. By default, the 4 closest input channels (determined after aligning your montage to the template's scale using TPS) are selected for this averaging process. On the interface, you will see checkboxes displayed above each of your channel. The 4 nearest channels are pre-selected by default for each empty template channels, but you can modify these selections as needed. If you uncheck all the checkboxes for a particular template channel, it will be filled with zeros.
|
38 |
- **Zero** method: All empty template channels are filled with zeros.
|
39 |
Choose the method that best suits your needs, considering that the model's performance may vary depending on the method used.
|
40 |
-
Once all template channels are filled, you will be directed to **Mapping
|
41 |
|
42 |
-
### Mapping
|
43 |
After completing the previous steps, your channels will be aligned with the template channels required by our models.
|
44 |
-
- In case there are still some channels that haven't been mapped, we will automatically batch and optimally assign them to the template. This ensures that even channels not initially mapped will still be included in the final
|
45 |
-
- Once the mapping process is completed, a JSON file containing the mapping
|
46 |
|
47 |
## 2. Decode data
|
48 |
-
After clicking on ``Run`` button, we will process your EEG data based on the mapping
|
49 |
"""
|
50 |
|
51 |
icunet = """
|
@@ -75,8 +75,6 @@ init_js = """
|
|
75 |
position: relative;
|
76 |
width: 100%;
|
77 |
aspect-ratio: 1;
|
78 |
-
//width: 560px;
|
79 |
-
//height: 560px;
|
80 |
background: url("file=${stage1_info.fileNames.inputMontage}");
|
81 |
background-size: contain;
|
82 |
`;
|
@@ -213,8 +211,8 @@ update_js = """
|
|
213 |
|
214 |
with gr.Blocks() as demo:
|
215 |
stage1_json = gr.JSON({}, visible=False)
|
216 |
-
stage2_json = gr.JSON(visible=False)
|
217 |
-
channel_json = gr.JSON(visible=False)
|
218 |
|
219 |
gr.Markdown(intro)
|
220 |
with gr.Row():
|
@@ -232,7 +230,7 @@ with gr.Blocks() as demo:
|
|
232 |
# step1
|
233 |
with gr.Row():
|
234 |
tpl_img = gr.Image("./template_montage.png", label="Template montage", visible=False)
|
235 |
-
mapped_img = gr.Image(label="Matching
|
236 |
# step2
|
237 |
radio_group = gr.Radio(elem_id="radio-group", visible=False)
|
238 |
# step3
|
@@ -295,7 +293,7 @@ with gr.Blocks() as demo:
|
|
295 |
return {stage1_json : stage1_info}
|
296 |
|
297 |
# stop Stage2
|
298 |
-
if stage2_info
|
299 |
utils.dataDelete(stage2_info["filePath"])
|
300 |
|
301 |
rootpath = os.path.dirname(str(in_loc))
|
@@ -331,7 +329,7 @@ with gr.Blocks() as demo:
|
|
331 |
"unassignedInputs" : None,
|
332 |
"emptyTemplates" : None,
|
333 |
"batchNum" : None,
|
334 |
-
"
|
335 |
{
|
336 |
"newOrder" : None,
|
337 |
"isOriginalData" : None
|
@@ -339,25 +337,25 @@ with gr.Blocks() as demo:
|
|
339 |
}
|
340 |
]
|
341 |
}
|
342 |
-
stage2_info =
|
343 |
-
channel_info =
|
344 |
return {stage1_json : stage1_info,
|
345 |
stage2_json : stage2_info,
|
346 |
channel_json : channel_info,
|
347 |
# --------------------Stage1-------------------------
|
348 |
map_btn : gr.Button(interactive=False),
|
349 |
-
desc_md : gr.Markdown("", visible=
|
350 |
-
|
351 |
tpl_img : gr.Image(visible=False),
|
352 |
mapped_img : gr.Image(value=None, visible=False),
|
353 |
radio_group : gr.Radio(choices=[], value=[], label="", visible=False),
|
354 |
-
clear_btn : gr.Button(visible=False),
|
355 |
-
step2_btn : gr.Button(visible=False),
|
356 |
in_fillmode : gr.Dropdown(value="mean", visible=False),
|
357 |
fillmode_btn : gr.Button(visible=False),
|
358 |
chkbox_group : gr.CheckboxGroup(choices=[], value=[], label='', visible=False),
|
|
|
|
|
359 |
step3_btn : gr.Button(visible=False),
|
360 |
-
|
361 |
# --------------------Stage2-------------------------
|
362 |
in_data_file : gr.File(value=None),
|
363 |
in_samplerate : gr.Textbox(value=None),
|
@@ -373,13 +371,11 @@ with gr.Blocks() as demo:
|
|
373 |
def init_next_step(stage1_info, channel_info, fillmode, sel_radio, sel_chkbox):
|
374 |
if stage1_info["errorFlag"] == True:
|
375 |
stage1_info["errorFlag"] = False
|
376 |
-
|
377 |
|
378 |
# ========================================step0=========================================
|
379 |
# step0 to step1
|
380 |
-
|
381 |
-
yield {desc_md : gr.Markdown("Mapping...", visible=True)}
|
382 |
-
|
383 |
# match the names
|
384 |
stage1_info, channel_info, tpl_montage, in_montage = app_utils.match_names(stage1_info)
|
385 |
# scale the coordinates
|
@@ -402,7 +398,7 @@ with gr.Blocks() as demo:
|
|
402 |
- channels highlighted in red are those that do not match any template channels.
|
403 |
"""
|
404 |
stage1_info["state"] = "step1-finished"
|
405 |
-
|
406 |
channel_json : channel_info,
|
407 |
map_btn : gr.Button(interactive=True),
|
408 |
desc_md : gr.Markdown(md),
|
@@ -418,22 +414,23 @@ with gr.Blocks() as demo:
|
|
418 |
# step1 to step4
|
419 |
if matched_num == 30:
|
420 |
md = """
|
421 |
-
### Mapping
|
422 |
The mapping process has been finished.
|
423 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
424 |
"""
|
425 |
-
# finalize and save the mapping
|
426 |
outputname = stage1_info["fileNames"]["outputResult"]
|
427 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
428 |
|
429 |
stage1_info["state"] = "finished"
|
430 |
-
|
431 |
channel_json : channel_info,
|
432 |
desc_md : gr.Markdown(md),
|
|
|
433 |
tpl_img : gr.Image(visible=False),
|
434 |
mapped_img : gr.Image(visible=False),
|
435 |
next_btn : gr.Button(visible=False),
|
436 |
-
|
437 |
# step1 to step2
|
438 |
elif in_num > matched_num:
|
439 |
md = """
|
@@ -452,14 +449,14 @@ with gr.Blocks() as demo:
|
|
452 |
stage1_info["state"] = "step2-selecting"
|
453 |
# determine which button to display
|
454 |
if stage1_info["step2"]["totalNum"] == 1:
|
455 |
-
|
456 |
desc_md : gr.Markdown(md),
|
457 |
tpl_img : gr.Image(visible=False),
|
458 |
mapped_img : gr.Image(visible=False),
|
459 |
radio_group : gr.Radio(choices=stage1_info["unassignedInputs"], value=[], label=label, visible=True),
|
460 |
clear_btn : gr.Button(visible=True)}
|
461 |
else:
|
462 |
-
|
463 |
desc_md : gr.Markdown(md),
|
464 |
tpl_img : gr.Image(visible=False),
|
465 |
mapped_img : gr.Image(visible=False),
|
@@ -474,7 +471,7 @@ with gr.Blocks() as demo:
|
|
474 |
Select one of the methods provided below to fill the remaining template channels.
|
475 |
"""
|
476 |
stage1_info["state"] = "step3-select-method"
|
477 |
-
|
478 |
desc_md : gr.Markdown(md),
|
479 |
tpl_img : gr.Image(visible=False),
|
480 |
mapped_img : gr.Image(visible=False),
|
@@ -491,8 +488,8 @@ with gr.Blocks() as demo:
|
|
491 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
492 |
sel_idx = channel_info["inputDict"][sel_radio]["index"]
|
493 |
|
494 |
-
stage1_info["
|
495 |
-
stage1_info["
|
496 |
channel_info["templateDict"][prev_tpl_name]["matched"] = True
|
497 |
channel_info["inputDict"][sel_radio]["assigned"] = True
|
498 |
#print(prev_tpl_name, '<-', sel_radio)
|
@@ -508,7 +505,7 @@ with gr.Blocks() as demo:
|
|
508 |
# step2 to step4
|
509 |
if len(stage1_info["emptyTemplates"]) == 0:
|
510 |
md = """
|
511 |
-
### Mapping
|
512 |
The mapping process has been finished.
|
513 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
514 |
"""
|
@@ -516,13 +513,14 @@ with gr.Blocks() as demo:
|
|
516 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
517 |
|
518 |
stage1_info["state"] = "finished"
|
519 |
-
|
520 |
channel_json : channel_info,
|
521 |
desc_md : gr.Markdown(md),
|
522 |
-
radio_group : gr.Radio(visible=False),
|
523 |
out_result_file : gr.File(outputname, visible=True),
|
|
|
524 |
clear_btn : gr.Button(visible=False),
|
525 |
-
next_btn : gr.Button(visible=False)
|
|
|
526 |
# step2 to step3-1
|
527 |
else:
|
528 |
md = """
|
@@ -530,7 +528,7 @@ with gr.Blocks() as demo:
|
|
530 |
Select one of the methods provided below to fill the remaining template channels.
|
531 |
"""
|
532 |
stage1_info["state"] = "step3-select-method"
|
533 |
-
|
534 |
channel_json : channel_info,
|
535 |
desc_md : gr.Markdown(md),
|
536 |
radio_group : gr.Radio(visible=False),
|
@@ -544,7 +542,7 @@ with gr.Blocks() as demo:
|
|
544 |
# step3-1 to step4
|
545 |
if fillmode == "zero":
|
546 |
md = """
|
547 |
-
### Mapping
|
548 |
The mapping process has been finished.
|
549 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
550 |
"""
|
@@ -552,12 +550,13 @@ with gr.Blocks() as demo:
|
|
552 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
553 |
|
554 |
stage1_info["state"] = "finished"
|
555 |
-
|
556 |
channel_json : channel_info,
|
557 |
desc_md : gr.Markdown(md),
|
|
|
558 |
in_fillmode : gr.Dropdown(visible=False),
|
559 |
fillmode_btn : gr.Button(visible=False),
|
560 |
-
|
561 |
# step3-1 to step3-2
|
562 |
elif fillmode == "mean":
|
563 |
md = """
|
@@ -566,10 +565,10 @@ with gr.Blocks() as demo:
|
|
566 |
value of the data from the selected channels. (By default, the 4 nearest channels are pre-selected.)
|
567 |
"""
|
568 |
# find the 4 nearest in_channels for each unmatched tpl_channels
|
569 |
-
stage1_info["
|
570 |
channel_info,
|
571 |
stage1_info["emptyTemplates"],
|
572 |
-
stage1_info["
|
573 |
# initialize the progress indication label
|
574 |
stage1_info["step3"] = {
|
575 |
"count" : 1,
|
@@ -579,13 +578,13 @@ with gr.Blocks() as demo:
|
|
579 |
label = '{} (1/{})'.format(tpl_name, stage1_info["step3"]["totalNum"])
|
580 |
|
581 |
tpl_idx = channel_info["templateDict"][tpl_name]["index"]
|
582 |
-
value = stage1_info["
|
583 |
value = [channel_info["inputNames"][i] for i in value]
|
584 |
|
585 |
stage1_info["state"] = "step3-2-selecting"
|
586 |
# determine which button to display
|
587 |
if stage1_info["step3"]["totalNum"] == 1:
|
588 |
-
|
589 |
desc_md : gr.Markdown(md),
|
590 |
in_fillmode : gr.Dropdown(visible=False),
|
591 |
fillmode_btn : gr.Button(visible=False),
|
@@ -593,7 +592,7 @@ with gr.Blocks() as demo:
|
|
593 |
value=value, label=label, visible=True),
|
594 |
next_btn : gr.Button(visible=True)}
|
595 |
else:
|
596 |
-
|
597 |
desc_md : gr.Markdown(md),
|
598 |
in_fillmode : gr.Dropdown(visible=False),
|
599 |
fillmode_btn : gr.Button(visible=False),
|
@@ -608,11 +607,11 @@ with gr.Blocks() as demo:
|
|
608 |
prev_tpl_name = stage1_info["emptyTemplates"][stage1_info["step3"]["count"]-1]
|
609 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
610 |
sel_idx = [channel_info["inputDict"][name]["index"] for name in sel_chkbox]
|
611 |
-
stage1_info["
|
612 |
#print(prev_tpl_name, '<-', sel_chkbox)
|
613 |
# ----------------------------------------------------------------------------------
|
614 |
md = """
|
615 |
-
### Mapping
|
616 |
The mapping process has been finished.
|
617 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
618 |
"""
|
@@ -620,18 +619,19 @@ with gr.Blocks() as demo:
|
|
620 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
621 |
|
622 |
stage1_info["state"] = "finished"
|
623 |
-
|
624 |
channel_json : channel_info,
|
625 |
desc_md : gr.Markdown(md),
|
|
|
626 |
chkbox_group : gr.CheckboxGroup(visible=False),
|
627 |
next_btn : gr.Button(visible=False),
|
628 |
-
|
629 |
|
630 |
next_btn.click(
|
631 |
fn = init_next_step,
|
632 |
inputs = [stage1_json, channel_json, in_fillmode, radio_group, chkbox_group],
|
633 |
-
outputs = [stage1_json, channel_json, desc_md, tpl_img, mapped_img, radio_group,
|
634 |
-
in_fillmode, fillmode_btn, chkbox_group, step3_btn,
|
635 |
).success(
|
636 |
fn = None,
|
637 |
js = init_js,
|
@@ -646,9 +646,9 @@ with gr.Blocks() as demo:
|
|
646 |
map_btn.click(
|
647 |
fn = reset_all,
|
648 |
inputs = [stage1_json, stage2_json, in_loc_file],
|
649 |
-
outputs = [stage1_json, stage2_json, channel_json, map_btn, desc_md,
|
650 |
-
radio_group,
|
651 |
-
|
652 |
).success(
|
653 |
fn = init_next_step,
|
654 |
inputs = [stage1_json, channel_json, in_fillmode, radio_group, chkbox_group],
|
@@ -686,8 +686,8 @@ with gr.Blocks() as demo:
|
|
686 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
687 |
sel_idx = channel_info["inputDict"][sel_name]["index"]
|
688 |
|
689 |
-
stage1_info["
|
690 |
-
stage1_info["
|
691 |
channel_info["templateDict"][prev_tpl_name]["matched"] = True
|
692 |
channel_info["inputDict"][sel_name]["assigned"] = True
|
693 |
#print(prev_tpl_name, '<-', sel_name)
|
@@ -736,7 +736,7 @@ with gr.Blocks() as demo:
|
|
736 |
prev_tpl_name = stage1_info["emptyTemplates"][step3["count"]-1]
|
737 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
738 |
sel_idx = [channel_info["inputDict"][name]["index"] for name in sel_name]
|
739 |
-
stage1_info["
|
740 |
#print(prev_tpl_name, '<-', sel_name)
|
741 |
|
742 |
# ---------------------------------update the new round---------------------------------
|
@@ -746,7 +746,7 @@ with gr.Blocks() as demo:
|
|
746 |
label = '{} ({}/{})'.format(tpl_name, step3["count"], step3["totalNum"])
|
747 |
|
748 |
tpl_idx = channel_info["templateDict"][tpl_name]["index"]
|
749 |
-
value = stage1_info["
|
750 |
value = [channel_info["inputNames"][i] for i in value]
|
751 |
|
752 |
stage1_info["step3"] = step3
|
@@ -763,8 +763,8 @@ with gr.Blocks() as demo:
|
|
763 |
fillmode_btn.click(
|
764 |
fn = init_next_step,
|
765 |
inputs = [stage1_json, channel_json, in_fillmode, radio_group, chkbox_group],
|
766 |
-
outputs = [stage1_json, channel_json, desc_md, in_fillmode, fillmode_btn,
|
767 |
-
|
768 |
).success(
|
769 |
fn = None,
|
770 |
js = init_js,
|
@@ -786,22 +786,19 @@ with gr.Blocks() as demo:
|
|
786 |
|
787 |
# +========================================================================================+
|
788 |
# | Stage2: decode data |
|
789 |
-
# +========================================================================================+
|
790 |
-
@gr.on(triggers = [in_data_file.upload, in_data_file.clear, in_samplerate.input, out_result_file.change],
|
791 |
-
inputs = [stage1_json, in_data_file, in_samplerate], outputs = run_btn)
|
792 |
-
def check_input(stage1_info, in_data, samplerate):
|
793 |
-
if stage1_info["state"]=="finished" and in_data!=None and samplerate!="":
|
794 |
-
return gr.Button(interactive=True)
|
795 |
-
else:
|
796 |
-
return gr.Button(interactive=False)
|
797 |
-
|
798 |
@cancel_btn.click(inputs = stage2_json, outputs = [stage2_json, cancel_btn, batch_md])
|
799 |
def stop_stage2(stage2_info):
|
800 |
utils.dataDelete(stage2_info["filePath"])
|
801 |
stage2_info["state"] = "stopped"
|
802 |
return stage2_info, gr.Button(interactive=False), gr.Markdown(visible=False)
|
803 |
|
804 |
-
def reset_stage2(in_data, samplerate, modelname):
|
|
|
|
|
|
|
|
|
|
|
805 |
rootpath = os.path.dirname(str(in_data))
|
806 |
# delete the previous folder(s) of Stage2
|
807 |
folders = [ f.path for f in os.scandir(rootpath) if f.is_dir()]
|
@@ -821,7 +818,7 @@ with gr.Blocks() as demo:
|
|
821 |
"outputData" : rootpath+'/'+stage2_id+'/'+outputname
|
822 |
},
|
823 |
"state" : "running",
|
824 |
-
"
|
825 |
}
|
826 |
return {stage2_json : stage2_info,
|
827 |
run_btn : gr.Button(visible=False),
|
@@ -829,61 +826,51 @@ with gr.Blocks() as demo:
|
|
829 |
batch_md : gr.Markdown("", visible=True),
|
830 |
out_data_file : gr.File(value=None, visible=False)}
|
831 |
|
832 |
-
def
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
filepath = stage2_info["filePath"]
|
837 |
-
inputname = stage2_info["fileNames"]["inputData"]
|
838 |
-
outputname = stage2_info["fileNames"]["outputData"]
|
839 |
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
|
846 |
-
|
847 |
-
|
848 |
-
m_filename = 'mapped_{:02d}.csv'.format(i+1)
|
849 |
-
d_filename = '{}_{:02d}.csv'.format(out_basename, i+1)
|
850 |
-
try:
|
851 |
-
# establish a temp folder
|
852 |
-
os.mkdir(filepath+'temp_data/')
|
853 |
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
break_flag
|
865 |
-
|
|
|
|
|
|
|
|
|
866 |
else:
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
stage2_info["state"] = "finished"
|
874 |
-
yield {stage2_json : stage2_info,
|
875 |
-
run_btn : gr.Button(visible=True),
|
876 |
-
cancel_btn : gr.Button(visible=False),
|
877 |
-
batch_md : gr.Markdown(visible=False),
|
878 |
-
out_data_file : gr.File(outputname, visible=True)}
|
879 |
|
880 |
run_btn.click(
|
881 |
fn = reset_stage2,
|
882 |
-
inputs = [in_data_file, in_samplerate, in_modelname],
|
883 |
outputs = [stage2_json, run_btn, cancel_btn, batch_md, out_data_file]
|
884 |
).success(
|
885 |
-
fn =
|
886 |
-
inputs = [stage1_json, stage2_json, in_modelname],
|
887 |
outputs = [stage2_json, run_btn, cancel_btn, batch_md, out_data_file]
|
888 |
)
|
889 |
|
|
|
22 |
|
23 |
### Step1: Initial Matching and Scaling
|
24 |
After clicking on ``Map`` button, we will first match your channels to our template channels by their names. Using the matched channels as reference points, we will apply Thin Plate Spline (TPS) transformation to scale your montage to align with our template's dimensions. The template montage and your scaled montage will be displayed side by side for comparison. Channels that do not have a match in our template will be **highlighted in red**.
|
25 |
+
- If your data includes all the 30 template channels, you will be directed to **Mapping Result**.
|
26 |
- If your data doesn't include all the 30 template channels and you have some channels that do not match the template, you will be directed to **Step2**.
|
27 |
- If all your channels are included in our template but you have fewer than 30 channels, you will be directed to **Step3**.
|
28 |
|
29 |
### Step2: Forwarding Unmatched Channels
|
30 |
In this step, you will handle the channels that didn't have a direct match with our template, by manually assigning them to the template channels that are still empty, ensuring the most efficient use of your data.
|
31 |
Your unmatched channels, previously highlighted in red, will be shown on your montage with a radio button displayed above each. You can choose to forward the data from these unmatched channels to the empty template channels. The interface will display each empty template channel in sequence, allowing you to select which of your unmatched channels to forward.
|
32 |
+
- If all empty template channels are filled by your selections, you will be directed to **Mapping Result**.
|
33 |
- If there are still empty template channels remaining, you will be directed to **Step3**.
|
34 |
|
35 |
### Step3: Filling Remaining Template Channels
|
|
|
37 |
- **Mean** method: Each empty template channel is filled with the average value of data from the nearest input channels. By default, the 4 closest input channels (determined after aligning your montage to the template's scale using TPS) are selected for this averaging process. On the interface, you will see checkboxes displayed above each of your channel. The 4 nearest channels are pre-selected by default for each empty template channels, but you can modify these selections as needed. If you uncheck all the checkboxes for a particular template channel, it will be filled with zeros.
|
38 |
- **Zero** method: All empty template channels are filled with zeros.
|
39 |
Choose the method that best suits your needs, considering that the model's performance may vary depending on the method used.
|
40 |
+
Once all template channels are filled, you will be directed to **Mapping Result**.
|
41 |
|
42 |
+
### Mapping Result
|
43 |
After completing the previous steps, your channels will be aligned with the template channels required by our models.
|
44 |
+
- In case there are still some channels that haven't been mapped, we will automatically batch and optimally assign them to the template. This ensures that even channels not initially mapped will still be included in the final result.
|
45 |
+
- Once the mapping process is completed, a JSON file containing the mapping result will be generated. This file is necessary only if you plan to run the models using the <a href="">source code</a>; otherwise, you can ignore it.
|
46 |
|
47 |
## 2. Decode data
|
48 |
+
After clicking on ``Run`` button, we will process your EEG data based on the mapping result. If necessary, your data will be divided into batches and run the models on each batch sequentially, ensuring that all channels are properly processed.
|
49 |
"""
|
50 |
|
51 |
icunet = """
|
|
|
75 |
position: relative;
|
76 |
width: 100%;
|
77 |
aspect-ratio: 1;
|
|
|
|
|
78 |
background: url("file=${stage1_info.fileNames.inputMontage}");
|
79 |
background-size: contain;
|
80 |
`;
|
|
|
211 |
|
212 |
with gr.Blocks() as demo:
|
213 |
stage1_json = gr.JSON({}, visible=False)
|
214 |
+
stage2_json = gr.JSON({}, visible=False)
|
215 |
+
channel_json = gr.JSON({}, visible=False)
|
216 |
|
217 |
gr.Markdown(intro)
|
218 |
with gr.Row():
|
|
|
230 |
# step1
|
231 |
with gr.Row():
|
232 |
tpl_img = gr.Image("./template_montage.png", label="Template montage", visible=False)
|
233 |
+
mapped_img = gr.Image(label="Matching result", visible=False)
|
234 |
# step2
|
235 |
radio_group = gr.Radio(elem_id="radio-group", visible=False)
|
236 |
# step3
|
|
|
293 |
return {stage1_json : stage1_info}
|
294 |
|
295 |
# stop Stage2
|
296 |
+
if "state" in stage2_info and stage2_info["state"]=="running":
|
297 |
utils.dataDelete(stage2_info["filePath"])
|
298 |
|
299 |
rootpath = os.path.dirname(str(in_loc))
|
|
|
329 |
"unassignedInputs" : None,
|
330 |
"emptyTemplates" : None,
|
331 |
"batchNum" : None,
|
332 |
+
"mappingResult" : [
|
333 |
{
|
334 |
"newOrder" : None,
|
335 |
"isOriginalData" : None
|
|
|
337 |
}
|
338 |
]
|
339 |
}
|
340 |
+
stage2_info = {}
|
341 |
+
channel_info = {}
|
342 |
return {stage1_json : stage1_info,
|
343 |
stage2_json : stage2_info,
|
344 |
channel_json : channel_info,
|
345 |
# --------------------Stage1-------------------------
|
346 |
map_btn : gr.Button(interactive=False),
|
347 |
+
desc_md : gr.Markdown("", visible=True),
|
348 |
+
out_result_file : gr.File(value=None, visible=False),
|
349 |
tpl_img : gr.Image(visible=False),
|
350 |
mapped_img : gr.Image(value=None, visible=False),
|
351 |
radio_group : gr.Radio(choices=[], value=[], label="", visible=False),
|
|
|
|
|
352 |
in_fillmode : gr.Dropdown(value="mean", visible=False),
|
353 |
fillmode_btn : gr.Button(visible=False),
|
354 |
chkbox_group : gr.CheckboxGroup(choices=[], value=[], label='', visible=False),
|
355 |
+
clear_btn : gr.Button(visible=False),
|
356 |
+
step2_btn : gr.Button(visible=False),
|
357 |
step3_btn : gr.Button(visible=False),
|
358 |
+
next_btn : gr.Button(visible=False),
|
359 |
# --------------------Stage2-------------------------
|
360 |
in_data_file : gr.File(value=None),
|
361 |
in_samplerate : gr.Textbox(value=None),
|
|
|
371 |
def init_next_step(stage1_info, channel_info, fillmode, sel_radio, sel_chkbox):
|
372 |
if stage1_info["errorFlag"] == True:
|
373 |
stage1_info["errorFlag"] = False
|
374 |
+
return {stage1_json : stage1_info}
|
375 |
|
376 |
# ========================================step0=========================================
|
377 |
# step0 to step1
|
378 |
+
if stage1_info["state"] == "step1-initializing":
|
|
|
|
|
379 |
# match the names
|
380 |
stage1_info, channel_info, tpl_montage, in_montage = app_utils.match_names(stage1_info)
|
381 |
# scale the coordinates
|
|
|
398 |
- channels highlighted in red are those that do not match any template channels.
|
399 |
"""
|
400 |
stage1_info["state"] = "step1-finished"
|
401 |
+
return {stage1_json : stage1_info,
|
402 |
channel_json : channel_info,
|
403 |
map_btn : gr.Button(interactive=True),
|
404 |
desc_md : gr.Markdown(md),
|
|
|
414 |
# step1 to step4
|
415 |
if matched_num == 30:
|
416 |
md = """
|
417 |
+
### Mapping Result
|
418 |
The mapping process has been finished.
|
419 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
420 |
"""
|
421 |
+
# finalize and save the mapping result
|
422 |
outputname = stage1_info["fileNames"]["outputResult"]
|
423 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
424 |
|
425 |
stage1_info["state"] = "finished"
|
426 |
+
return {stage1_json : stage1_info,
|
427 |
channel_json : channel_info,
|
428 |
desc_md : gr.Markdown(md),
|
429 |
+
out_result_file : gr.File(outputname, visible=True),
|
430 |
tpl_img : gr.Image(visible=False),
|
431 |
mapped_img : gr.Image(visible=False),
|
432 |
next_btn : gr.Button(visible=False),
|
433 |
+
run_btn : gr.Button(interactive=True)}
|
434 |
# step1 to step2
|
435 |
elif in_num > matched_num:
|
436 |
md = """
|
|
|
449 |
stage1_info["state"] = "step2-selecting"
|
450 |
# determine which button to display
|
451 |
if stage1_info["step2"]["totalNum"] == 1:
|
452 |
+
return {stage1_json : stage1_info,
|
453 |
desc_md : gr.Markdown(md),
|
454 |
tpl_img : gr.Image(visible=False),
|
455 |
mapped_img : gr.Image(visible=False),
|
456 |
radio_group : gr.Radio(choices=stage1_info["unassignedInputs"], value=[], label=label, visible=True),
|
457 |
clear_btn : gr.Button(visible=True)}
|
458 |
else:
|
459 |
+
return {stage1_json : stage1_info,
|
460 |
desc_md : gr.Markdown(md),
|
461 |
tpl_img : gr.Image(visible=False),
|
462 |
mapped_img : gr.Image(visible=False),
|
|
|
471 |
Select one of the methods provided below to fill the remaining template channels.
|
472 |
"""
|
473 |
stage1_info["state"] = "step3-select-method"
|
474 |
+
return {stage1_json : stage1_info,
|
475 |
desc_md : gr.Markdown(md),
|
476 |
tpl_img : gr.Image(visible=False),
|
477 |
mapped_img : gr.Image(visible=False),
|
|
|
488 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
489 |
sel_idx = channel_info["inputDict"][sel_radio]["index"]
|
490 |
|
491 |
+
stage1_info["mappingResult"][0]["newOrder"][prev_tpl_idx] = [sel_idx]
|
492 |
+
stage1_info["mappingResult"][0]["isOriginalData"][prev_tpl_idx] = True
|
493 |
channel_info["templateDict"][prev_tpl_name]["matched"] = True
|
494 |
channel_info["inputDict"][sel_radio]["assigned"] = True
|
495 |
#print(prev_tpl_name, '<-', sel_radio)
|
|
|
505 |
# step2 to step4
|
506 |
if len(stage1_info["emptyTemplates"]) == 0:
|
507 |
md = """
|
508 |
+
### Mapping Result
|
509 |
The mapping process has been finished.
|
510 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
511 |
"""
|
|
|
513 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
514 |
|
515 |
stage1_info["state"] = "finished"
|
516 |
+
return {stage1_json : stage1_info,
|
517 |
channel_json : channel_info,
|
518 |
desc_md : gr.Markdown(md),
|
|
|
519 |
out_result_file : gr.File(outputname, visible=True),
|
520 |
+
radio_group : gr.Radio(visible=False),
|
521 |
clear_btn : gr.Button(visible=False),
|
522 |
+
next_btn : gr.Button(visible=False),
|
523 |
+
run_btn : gr.Button(interactive=True)}
|
524 |
# step2 to step3-1
|
525 |
else:
|
526 |
md = """
|
|
|
528 |
Select one of the methods provided below to fill the remaining template channels.
|
529 |
"""
|
530 |
stage1_info["state"] = "step3-select-method"
|
531 |
+
return {stage1_json : stage1_info,
|
532 |
channel_json : channel_info,
|
533 |
desc_md : gr.Markdown(md),
|
534 |
radio_group : gr.Radio(visible=False),
|
|
|
542 |
# step3-1 to step4
|
543 |
if fillmode == "zero":
|
544 |
md = """
|
545 |
+
### Mapping Result
|
546 |
The mapping process has been finished.
|
547 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
548 |
"""
|
|
|
550 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
551 |
|
552 |
stage1_info["state"] = "finished"
|
553 |
+
return {stage1_json : stage1_info,
|
554 |
channel_json : channel_info,
|
555 |
desc_md : gr.Markdown(md),
|
556 |
+
out_result_file : gr.File(outputname, visible=True),
|
557 |
in_fillmode : gr.Dropdown(visible=False),
|
558 |
fillmode_btn : gr.Button(visible=False),
|
559 |
+
run_btn : gr.Button(interactive=True)}
|
560 |
# step3-1 to step3-2
|
561 |
elif fillmode == "mean":
|
562 |
md = """
|
|
|
565 |
value of the data from the selected channels. (By default, the 4 nearest channels are pre-selected.)
|
566 |
"""
|
567 |
# find the 4 nearest in_channels for each unmatched tpl_channels
|
568 |
+
stage1_info["mappingResult"][0]["newOrder"] = app_utils.find_neighbors(
|
569 |
channel_info,
|
570 |
stage1_info["emptyTemplates"],
|
571 |
+
stage1_info["mappingResult"][0]["newOrder"])
|
572 |
# initialize the progress indication label
|
573 |
stage1_info["step3"] = {
|
574 |
"count" : 1,
|
|
|
578 |
label = '{} (1/{})'.format(tpl_name, stage1_info["step3"]["totalNum"])
|
579 |
|
580 |
tpl_idx = channel_info["templateDict"][tpl_name]["index"]
|
581 |
+
value = stage1_info["mappingResult"][0]["newOrder"][tpl_idx]
|
582 |
value = [channel_info["inputNames"][i] for i in value]
|
583 |
|
584 |
stage1_info["state"] = "step3-2-selecting"
|
585 |
# determine which button to display
|
586 |
if stage1_info["step3"]["totalNum"] == 1:
|
587 |
+
return {stage1_json : stage1_info,
|
588 |
desc_md : gr.Markdown(md),
|
589 |
in_fillmode : gr.Dropdown(visible=False),
|
590 |
fillmode_btn : gr.Button(visible=False),
|
|
|
592 |
value=value, label=label, visible=True),
|
593 |
next_btn : gr.Button(visible=True)}
|
594 |
else:
|
595 |
+
return {stage1_json : stage1_info,
|
596 |
desc_md : gr.Markdown(md),
|
597 |
in_fillmode : gr.Dropdown(visible=False),
|
598 |
fillmode_btn : gr.Button(visible=False),
|
|
|
607 |
prev_tpl_name = stage1_info["emptyTemplates"][stage1_info["step3"]["count"]-1]
|
608 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
609 |
sel_idx = [channel_info["inputDict"][name]["index"] for name in sel_chkbox]
|
610 |
+
stage1_info["mappingResult"][0]["newOrder"][prev_tpl_idx] = sel_idx if sel_idx!=[] else [None]
|
611 |
#print(prev_tpl_name, '<-', sel_chkbox)
|
612 |
# ----------------------------------------------------------------------------------
|
613 |
md = """
|
614 |
+
### Mapping Result
|
615 |
The mapping process has been finished.
|
616 |
Download the file below if you plan to run the models using the <a href="">source code</a>.
|
617 |
"""
|
|
|
619 |
stage1_info, channel_info = app_utils.mapping_result(stage1_info, channel_info, outputname)
|
620 |
|
621 |
stage1_info["state"] = "finished"
|
622 |
+
return {stage1_json : stage1_info,
|
623 |
channel_json : channel_info,
|
624 |
desc_md : gr.Markdown(md),
|
625 |
+
out_result_file : gr.File(outputname, visible=True),
|
626 |
chkbox_group : gr.CheckboxGroup(visible=False),
|
627 |
next_btn : gr.Button(visible=False),
|
628 |
+
run_btn : gr.Button(interactive=True)}
|
629 |
|
630 |
next_btn.click(
|
631 |
fn = init_next_step,
|
632 |
inputs = [stage1_json, channel_json, in_fillmode, radio_group, chkbox_group],
|
633 |
+
outputs = [stage1_json, channel_json, desc_md, out_result_file, tpl_img, mapped_img, radio_group,
|
634 |
+
in_fillmode, fillmode_btn, chkbox_group, clear_btn, step2_btn, step3_btn, next_btn, run_btn]
|
635 |
).success(
|
636 |
fn = None,
|
637 |
js = init_js,
|
|
|
646 |
map_btn.click(
|
647 |
fn = reset_all,
|
648 |
inputs = [stage1_json, stage2_json, in_loc_file],
|
649 |
+
outputs = [stage1_json, stage2_json, channel_json, map_btn, desc_md, out_result_file, tpl_img, mapped_img,
|
650 |
+
radio_group, in_fillmode, fillmode_btn, chkbox_group, clear_btn, step2_btn, step3_btn, next_btn,
|
651 |
+
in_data_file, in_samplerate, run_btn, cancel_btn, batch_md, out_data_file]
|
652 |
).success(
|
653 |
fn = init_next_step,
|
654 |
inputs = [stage1_json, channel_json, in_fillmode, radio_group, chkbox_group],
|
|
|
686 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
687 |
sel_idx = channel_info["inputDict"][sel_name]["index"]
|
688 |
|
689 |
+
stage1_info["mappingResult"][0]["newOrder"][prev_tpl_idx] = [sel_idx]
|
690 |
+
stage1_info["mappingResult"][0]["isOriginalData"][prev_tpl_idx] = True
|
691 |
channel_info["templateDict"][prev_tpl_name]["matched"] = True
|
692 |
channel_info["inputDict"][sel_name]["assigned"] = True
|
693 |
#print(prev_tpl_name, '<-', sel_name)
|
|
|
736 |
prev_tpl_name = stage1_info["emptyTemplates"][step3["count"]-1]
|
737 |
prev_tpl_idx = channel_info["templateDict"][prev_tpl_name]["index"]
|
738 |
sel_idx = [channel_info["inputDict"][name]["index"] for name in sel_name]
|
739 |
+
stage1_info["mappingResult"][0]["newOrder"][prev_tpl_idx] = sel_idx if sel_idx!=[] else [None]
|
740 |
#print(prev_tpl_name, '<-', sel_name)
|
741 |
|
742 |
# ---------------------------------update the new round---------------------------------
|
|
|
746 |
label = '{} ({}/{})'.format(tpl_name, step3["count"], step3["totalNum"])
|
747 |
|
748 |
tpl_idx = channel_info["templateDict"][tpl_name]["index"]
|
749 |
+
value = stage1_info["mappingResult"][0]["newOrder"][tpl_idx]
|
750 |
value = [channel_info["inputNames"][i] for i in value]
|
751 |
|
752 |
stage1_info["step3"] = step3
|
|
|
763 |
fillmode_btn.click(
|
764 |
fn = init_next_step,
|
765 |
inputs = [stage1_json, channel_json, in_fillmode, radio_group, chkbox_group],
|
766 |
+
outputs = [stage1_json, channel_json, desc_md, out_result_file, in_fillmode, fillmode_btn,
|
767 |
+
chkbox_group, step3_btn, next_btn, run_btn]
|
768 |
).success(
|
769 |
fn = None,
|
770 |
js = init_js,
|
|
|
786 |
|
787 |
# +========================================================================================+
|
788 |
# | Stage2: decode data |
|
789 |
+
# +========================================================================================+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
790 |
@cancel_btn.click(inputs = stage2_json, outputs = [stage2_json, cancel_btn, batch_md])
|
791 |
def stop_stage2(stage2_info):
|
792 |
utils.dataDelete(stage2_info["filePath"])
|
793 |
stage2_info["state"] = "stopped"
|
794 |
return stage2_info, gr.Button(interactive=False), gr.Markdown(visible=False)
|
795 |
|
796 |
+
def reset_stage2(stage2_info, in_data, samplerate, modelname):
|
797 |
+
if in_data==None or samplerate=="":
|
798 |
+
gr.Warning("Please upload a file and enter the sampling rate.")
|
799 |
+
stage2_info["errorFlag"] = True
|
800 |
+
return {stage2_json : stage2_info}
|
801 |
+
|
802 |
rootpath = os.path.dirname(str(in_data))
|
803 |
# delete the previous folder(s) of Stage2
|
804 |
folders = [ f.path for f in os.scandir(rootpath) if f.is_dir()]
|
|
|
818 |
"outputData" : rootpath+'/'+stage2_id+'/'+outputname
|
819 |
},
|
820 |
"state" : "running",
|
821 |
+
"errorFlag" : False
|
822 |
}
|
823 |
return {stage2_json : stage2_info,
|
824 |
run_btn : gr.Button(visible=False),
|
|
|
826 |
batch_md : gr.Markdown("", visible=True),
|
827 |
out_data_file : gr.File(value=None, visible=False)}
|
828 |
|
829 |
+
def run_stage2(stage1_info, stage2_info, samplerate, modelname):
|
830 |
+
if stage2_info["errorFlag"] == True:
|
831 |
+
stage2_info["errorFlag"] = False
|
832 |
+
yield {stage2_json : stage2_info}
|
|
|
|
|
|
|
833 |
|
834 |
+
else:
|
835 |
+
inputname = stage2_info["fileNames"]["inputData"]
|
836 |
+
outputname = stage2_info["fileNames"]["outputData"]
|
837 |
+
out_basename = os.path.basename(str(outputname))
|
838 |
+
out_basename = os.path.splitext(out_basename)[0]
|
839 |
|
840 |
+
for i in range(stage1_info["batchNum"]):
|
841 |
+
yield {batch_md : gr.Markdown('Running model({}/{})...'.format(i+1, stage1_info["batchNum"]))}
|
|
|
|
|
|
|
|
|
|
|
842 |
|
843 |
+
break_flag = app_utils.run_model(modelname = modelname,
|
844 |
+
filepath = stage2_info["filePath"],
|
845 |
+
inputname = inputname,
|
846 |
+
m_filename = 'mapped_{:02d}.csv'.format(i+1),
|
847 |
+
d_filename = '{}_{:02d}.csv'.format(out_basename, i+1),
|
848 |
+
outputname = outputname,
|
849 |
+
samplerate = int(samplerate),
|
850 |
+
batch_cnt = i,
|
851 |
+
new_idx = stage1_info["mappingResult"][i]["newOrder"],
|
852 |
+
orig_flags = stage1_info["mappingResult"][i]["isOriginalData"])
|
853 |
+
if break_flag == True:
|
854 |
+
break
|
855 |
+
|
856 |
+
if break_flag == True:
|
857 |
+
yield {run_btn : gr.Button(visible=True),
|
858 |
+
cancel_btn : gr.Button(visible=False)}
|
859 |
else:
|
860 |
+
stage2_info["state"] = "finished"
|
861 |
+
yield {stage2_json : stage2_info,
|
862 |
+
run_btn : gr.Button(visible=True),
|
863 |
+
cancel_btn : gr.Button(visible=False),
|
864 |
+
batch_md : gr.Markdown(visible=False),
|
865 |
+
out_data_file : gr.File(outputname, visible=True)}
|
|
|
|
|
|
|
|
|
|
|
|
|
866 |
|
867 |
run_btn.click(
|
868 |
fn = reset_stage2,
|
869 |
+
inputs = [stage2_json, in_data_file, in_samplerate, in_modelname],
|
870 |
outputs = [stage2_json, run_btn, cancel_btn, batch_md, out_data_file]
|
871 |
).success(
|
872 |
+
fn = run_stage2,
|
873 |
+
inputs = [stage1_json, stage2_json, in_samplerate, in_modelname],
|
874 |
outputs = [stage2_json, run_btn, cancel_btn, batch_md, out_data_file]
|
875 |
)
|
876 |
|
app_utils.py
CHANGED
@@ -11,41 +11,6 @@ from scipy.interpolate import Rbf
|
|
11 |
from scipy.optimize import linear_sum_assignment
|
12 |
from sklearn.neighbors import NearestNeighbors
|
13 |
|
14 |
-
def reorder_data(idx_order, orig_flags, inputname, filename):
|
15 |
-
# read the input data
|
16 |
-
raw_data = utils.read_train_data(inputname)
|
17 |
-
#print(raw_data.shape)
|
18 |
-
new_data = np.zeros((30, raw_data.shape[1]))
|
19 |
-
|
20 |
-
zero_arr = np.zeros((1, raw_data.shape[1]))
|
21 |
-
for i, (idx_set, flag) in enumerate(zip(idx_order, orig_flags)):
|
22 |
-
if flag == True:
|
23 |
-
new_data[i, :] = raw_data[idx_set[0], :]
|
24 |
-
elif idx_set == [None]:
|
25 |
-
new_data[i, :] = zero_arr
|
26 |
-
else:
|
27 |
-
tmp_data = [raw_data[j, :] for j in idx_set]
|
28 |
-
new_data[i, :] = np.mean(tmp_data, axis=0)
|
29 |
-
|
30 |
-
utils.save_data(new_data, filename)
|
31 |
-
return raw_data.shape
|
32 |
-
|
33 |
-
def restore_order(batch_cnt, raw_data_shape, idx_order, orig_flags, filename, outputname):
|
34 |
-
# read the denoised data
|
35 |
-
d_data = utils.read_train_data(filename)
|
36 |
-
if batch_cnt == 0:
|
37 |
-
new_data = np.zeros((raw_data_shape[0], d_data.shape[1]))
|
38 |
-
#print(new_data.shape)
|
39 |
-
else:
|
40 |
-
new_data = utils.read_train_data(outputname)
|
41 |
-
|
42 |
-
for i, (idx_set, flag) in enumerate(zip(idx_order, orig_flags)):
|
43 |
-
if flag == True:
|
44 |
-
new_data[idx_set[0], :] = d_data[i, :]
|
45 |
-
|
46 |
-
utils.save_data(new_data, outputname)
|
47 |
-
return
|
48 |
-
|
49 |
def get_matched(tpl_names, tpl_dict):
|
50 |
return [name for name in tpl_names if tpl_dict[name]["matched"]==True]
|
51 |
|
@@ -261,7 +226,7 @@ def match_names(stage1_info):
|
|
261 |
stage1_info.update({
|
262 |
"unassignedInputs" : get_unassigned_inputs(in_names, in_dict),
|
263 |
"emptyTemplates" : get_empty_templates(tpl_names, tpl_dict),
|
264 |
-
"
|
265 |
{
|
266 |
"newOrder" : new_idx,
|
267 |
"isOriginalData" : orig_flags
|
@@ -303,7 +268,7 @@ def optimal_mapping(channel_info):
|
|
303 |
# by minimizing the total distances between their positions.
|
304 |
row_idx, col_idx = linear_sum_assignment(cost_matrix)
|
305 |
|
306 |
-
# store the mapping
|
307 |
new_idx = [[None]]*30
|
308 |
orig_flags = [False]*30
|
309 |
for i, j in zip(row_idx, col_idx):
|
@@ -337,7 +302,7 @@ def mapping_result(stage1_info, channel_info, filename):
|
|
337 |
batch_num = math.ceil(unassigned_num/30) + 1
|
338 |
|
339 |
# map the remaining in_channels
|
340 |
-
results = stage1_info["
|
341 |
for i in range(1, batch_num):
|
342 |
# optimally select 30 in_channels to map to the tpl_channels based on proximity
|
343 |
result, channel_info = optimal_mapping(channel_info)
|
@@ -347,17 +312,78 @@ def mapping_result(stage1_info, channel_info, filename):
|
|
347 |
#"templateNames" : channel_info["templateNames"],
|
348 |
#"inputNames" : channel_info["inputNames"],
|
349 |
"batchNum" : batch_num,
|
350 |
-
"
|
351 |
}
|
352 |
options = jsbeautifier.default_options()
|
353 |
options.indent_size = 4
|
354 |
-
|
355 |
with open(filename, 'w') as jsonfile:
|
356 |
-
jsonfile.write(
|
357 |
|
358 |
stage1_info.update({
|
359 |
"batchNum" : batch_num,
|
360 |
-
"
|
361 |
})
|
362 |
return stage1_info, channel_info
|
363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
from scipy.optimize import linear_sum_assignment
|
12 |
from sklearn.neighbors import NearestNeighbors
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
def get_matched(tpl_names, tpl_dict):
|
15 |
return [name for name in tpl_names if tpl_dict[name]["matched"]==True]
|
16 |
|
|
|
226 |
stage1_info.update({
|
227 |
"unassignedInputs" : get_unassigned_inputs(in_names, in_dict),
|
228 |
"emptyTemplates" : get_empty_templates(tpl_names, tpl_dict),
|
229 |
+
"mappingResult" : [
|
230 |
{
|
231 |
"newOrder" : new_idx,
|
232 |
"isOriginalData" : orig_flags
|
|
|
268 |
# by minimizing the total distances between their positions.
|
269 |
row_idx, col_idx = linear_sum_assignment(cost_matrix)
|
270 |
|
271 |
+
# store the mapping result
|
272 |
new_idx = [[None]]*30
|
273 |
orig_flags = [False]*30
|
274 |
for i, j in zip(row_idx, col_idx):
|
|
|
302 |
batch_num = math.ceil(unassigned_num/30) + 1
|
303 |
|
304 |
# map the remaining in_channels
|
305 |
+
results = stage1_info["mappingResult"]
|
306 |
for i in range(1, batch_num):
|
307 |
# optimally select 30 in_channels to map to the tpl_channels based on proximity
|
308 |
result, channel_info = optimal_mapping(channel_info)
|
|
|
312 |
#"templateNames" : channel_info["templateNames"],
|
313 |
#"inputNames" : channel_info["inputNames"],
|
314 |
"batchNum" : batch_num,
|
315 |
+
"mappingResult" : results
|
316 |
}
|
317 |
options = jsbeautifier.default_options()
|
318 |
options.indent_size = 4
|
319 |
+
json_data = jsbeautifier.beautify(json.dumps(data), options)
|
320 |
with open(filename, 'w') as jsonfile:
|
321 |
+
jsonfile.write(json_data)
|
322 |
|
323 |
stage1_info.update({
|
324 |
"batchNum" : batch_num,
|
325 |
+
"mappingResult" : results
|
326 |
})
|
327 |
return stage1_info, channel_info
|
328 |
|
329 |
+
|
330 |
+
def reorder_data(idx_order, orig_flags, inputname, filename):
|
331 |
+
# read the input data
|
332 |
+
raw_data = utils.read_train_data(inputname)
|
333 |
+
#print(raw_data.shape)
|
334 |
+
new_data = np.zeros((30, raw_data.shape[1]))
|
335 |
+
|
336 |
+
zero_arr = np.zeros((1, raw_data.shape[1]))
|
337 |
+
for i, (idx_set, flag) in enumerate(zip(idx_order, orig_flags)):
|
338 |
+
if flag == True:
|
339 |
+
new_data[i, :] = raw_data[idx_set[0], :]
|
340 |
+
elif idx_set == [None]:
|
341 |
+
new_data[i, :] = zero_arr
|
342 |
+
else:
|
343 |
+
tmp_data = [raw_data[j, :] for j in idx_set]
|
344 |
+
new_data[i, :] = np.mean(tmp_data, axis=0)
|
345 |
+
|
346 |
+
utils.save_data(new_data, filename)
|
347 |
+
return raw_data.shape
|
348 |
+
|
349 |
+
def restore_order(batch_cnt, raw_data_shape, idx_order, orig_flags, filename, outputname):
|
350 |
+
# read the denoised data
|
351 |
+
d_data = utils.read_train_data(filename)
|
352 |
+
if batch_cnt == 0:
|
353 |
+
new_data = np.zeros((raw_data_shape[0], d_data.shape[1]))
|
354 |
+
#print(new_data.shape)
|
355 |
+
else:
|
356 |
+
new_data = utils.read_train_data(outputname)
|
357 |
+
|
358 |
+
for i, (idx_set, flag) in enumerate(zip(idx_order, orig_flags)):
|
359 |
+
if flag == True:
|
360 |
+
new_data[idx_set[0], :] = d_data[i, :]
|
361 |
+
|
362 |
+
utils.save_data(new_data, outputname)
|
363 |
+
return
|
364 |
+
|
365 |
+
def run_model(modelname, filepath, inputname, m_filename, d_filename, outputname, samplerate, batch_cnt, new_idx, orig_flags):
|
366 |
+
try:
|
367 |
+
# establish a temp folder
|
368 |
+
os.mkdir(filepath+'temp_data/')
|
369 |
+
|
370 |
+
# step1: Reorder input data
|
371 |
+
data_shape = reorder_data(new_idx, orig_flags, inputname, filepath+'temp_data/'+m_filename)
|
372 |
+
# step2: Data preprocessing
|
373 |
+
total_file_num = utils.preprocessing(filepath+'temp_data/', m_filename, samplerate)
|
374 |
+
# step3: Signal reconstruction
|
375 |
+
utils.reconstruct(modelname, total_file_num, filepath+'temp_data/', d_filename, samplerate)
|
376 |
+
# step4: Restore original order
|
377 |
+
restore_order(batch_cnt, data_shape, new_idx, orig_flags, filepath+'temp_data/'+d_filename, outputname)
|
378 |
+
|
379 |
+
except FileNotFoundError:
|
380 |
+
print('stop!!')
|
381 |
+
stop_flag = True
|
382 |
+
|
383 |
+
else:
|
384 |
+
utils.dataDelete(filepath+'temp_data/')
|
385 |
+
stop_flag = False
|
386 |
+
|
387 |
+
finally:
|
388 |
+
return stop_flag
|
389 |
+
|