audrey06100 commited on
Commit
2cb93fb
·
1 Parent(s): 3166abf
Files changed (2) hide show
  1. app.py +34 -23
  2. app_utils.py +1 -2
app.py CHANGED
@@ -20,14 +20,14 @@ The following steps will guide you through the process of mapping your EEG chann
20
 
21
  ### Step1: Initial Matching and Scaling
22
  After clicking on ``Mapping`` 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**.
23
- - If your data includes all the 30 template channels, you will see the **Mapping Results**.
24
  - 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**.
25
  - If all your channels are included in our template but you have fewer than 30 channels, you will be directed to **Step3**.
26
 
27
  ### Step2: Forwarding Unmatched Channels
28
  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.
29
  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.
30
- - If all empty template channels are filled by your selections, you will see the **Mapping Results**.
31
  - If there are still empty template channels remaining, you will be directed to **Step3**.
32
 
33
  ### Step3: Filling Remaining Template Channels
@@ -35,11 +35,12 @@ To run the models successfully, we need to ensure that all 30 template channels
35
  - **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.
36
  - **Zero** method: All empty template channels are filled with zeros.
37
  Choose the method that best suits your needs, considering that the model's performance may vary depending on the method used.
38
- Once all template channels are filled, you will see the **Mapping Results**.
39
 
40
  ### Mapping Results
41
- After completing the previous steps, your channels will be aligned with the template channels required by our models. In case there are still some channels that haven't been mapped, we will automatically batch and optimally assign them to the template.
42
- Once the channel mapping process is completed, a **JSON file** containing the mapping results will be generated. This file is necessary only if you plan to run the models using the source code; otherwise, you can ignore it.
 
43
 
44
  ## 2. Decode data
45
  After clicking the ``Run`` button, we will process your EEG data based on the mapping results. If necessary, your data will be devided into batches and run the models on each batch sequentially, ensuring that all channels are properly processed.
@@ -57,16 +58,14 @@ init_js = """
57
  channel_info = JSON.parse(JSON.stringify(channel_info));
58
  stage1_info = app_info.stage1
59
 
60
- let selector, attribute; //, classname;
61
  let channel, left, bottom;
62
 
63
  if(stage1_info.state == "step2-selecting"){
64
  selector = "#radio-group > div:nth-of-type(2)";
65
- //classname = "radio";
66
  attribute = "value";
67
  }else if(stage1_info.state == "step3-2-selecting"){
68
  selector = "#chkbox-group > div:nth-of-type(2)";
69
- //classname = "chkbox";
70
  attribute = "name";
71
  }else return;
72
 
@@ -90,7 +89,7 @@ init_js = """
90
  bottom = channel_info.inputDict[channel].css_position[1];
91
 
92
  item.style.cssText = `position: absolute; left: ${left}; bottom: ${bottom};`;
93
- item.className = ""; //classname;
94
  item.querySelector(":scope > span").innerText = "";
95
  });
96
 
@@ -252,7 +251,7 @@ with gr.Blocks() as demo:
252
  fillmode_btn = gr.Button("OK", visible=False, scale=1)
253
  chkbox_group = gr.CheckboxGroup(elem_id="chkbox-group", visible=False)
254
  # step4 : mapping results
255
- out_json_file = gr.File(label="Mapping result", visible=False)
256
  res_md = gr.Markdown("""
257
  (Download this file if you plan to run the models using the source code.)
258
  """, visible=False)
@@ -386,7 +385,7 @@ with gr.Blocks() as demo:
386
  if stage1_info["state"] == "step1-initializing":
387
  yield {desc_md : gr.Markdown("Mapping...", visible=True)}
388
 
389
- # match the names of in_channels and tpl_channels
390
  stage1_info, channel_info, tpl_montage, in_montage = app_utils.match_names(stage1_info, channel_info)
391
  # scale the coordinates
392
  channel_info = app_utils.align_coords(channel_info, tpl_montage, in_montage)
@@ -429,17 +428,20 @@ with gr.Blocks() as demo:
429
  # step1 to step4
430
  # the in_channels has all the 30 tpl_channels (in_num>=30)
431
  if matched_num == 30:
 
 
 
 
432
  # finalize and save the mapping results
433
  filename = filepath+"mapping_result.json"
434
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
435
  stage1_info, stage2_info, channel_info, filename)
436
- #gr.Info('The mapping process has been finished.')
437
  stage1_info["state"] = "finished"
438
  app_info["stage1"] = stage1_info
439
  app_info["stage2"] = stage2_info
440
  yield {app_info_json : app_info,
441
  channel_info_json : channel_info,
442
- desc_md : gr.Markdown(visible=False),
443
  tpl_img : gr.Image(visible=False),
444
  mapped_img : gr.Image(visible=False),
445
  next_btn : gr.Button(visible=False),
@@ -455,7 +457,7 @@ with gr.Blocks() as demo:
455
  Select one of your unmatched channels to forward its data to the empty template channel
456
  currently indicated in red.
457
  """
458
- # initialize the progress indication label for step2
459
  stage1_info.update({
460
  "fillingCount" : 1,
461
  "totalFillingNum" : len(stage1_info["missingTemplates"])
@@ -528,19 +530,22 @@ with gr.Blocks() as demo:
528
 
529
  # -----------------------------determine the next step------------------------------
530
  # step2 to step4
531
- # all the unmatched tpl_channels were filled by in_channels
532
  if len(stage1_info["missingTemplates"]) == 0:
 
 
 
 
533
  # finalize and save the mapping results
534
  filename = filepath+"mapping_result.json"
535
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
536
  stage1_info, stage2_info, channel_info, filename)
537
- #gr.Info('The mapping process has been finished.')
538
  stage1_info["state"] = "finished"
539
  app_info["stage1"] = stage1_info
540
  app_info["stage2"] = stage2_info
541
  yield {app_info_json : app_info,
542
  channel_info_json : channel_info,
543
- desc_md : gr.Markdown(visible=False),
544
  radio_group : gr.Radio(visible=False),
545
  out_json_file : gr.File(filename, visible=True),
546
  res_md : gr.Markdown(visible=True),
@@ -571,17 +576,20 @@ with gr.Blocks() as demo:
571
 
572
  # step3-1 to step4
573
  if fillmode == "zero":
 
 
 
 
574
  # finalize and save the mapping results
575
  filename = filepath+"mapping_result.json"
576
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
577
  stage1_info, stage2_info, channel_info, filename)
578
- #gr.Info('The mapping process has been finished.')
579
  stage1_info["state"] = "finished"
580
  app_info["stage1"] = stage1_info
581
  app_info["stage2"] = stage2_info
582
  yield {app_info_json : app_info,
583
  channel_info_json : channel_info,
584
- desc_md : gr.Markdown(visible=False),
585
  in_fillmode : gr.Dropdown(visible=False),
586
  fillmode_btn : gr.Button(visible=False),
587
  out_json_file : gr.File(filename, visible=True),
@@ -645,17 +653,20 @@ with gr.Blocks() as demo:
645
  stage1_info["mappingData"][0]["newOrder"][prev_target_idx] = selected_indices
646
  #print(f'{prev_target_name}({prev_target_idx}): {selected_indices}')
647
  # ----------------------------------------------------------------------------------
 
 
 
 
648
  # finalize and save the mapping results
649
  filename = filepath+"mapping_result.json"
650
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
651
  stage1_info, stage2_info, channel_info, filename)
652
- #gr.Info('The mapping process has been finished.')
653
  stage1_info["state"] = "finished"
654
  app_info["stage1"] = stage1_info
655
  app_info["stage2"] = stage2_info
656
  yield {app_info_json : app_info,
657
  channel_info_json : channel_info,
658
- desc_md : gr.Markdown(visible=False),
659
  chkbox_group : gr.CheckboxGroup(visible=False),
660
  next_btn : gr.Button(visible=False),
661
  out_json_file : gr.File(filename, visible=True),
@@ -874,8 +885,8 @@ with gr.Blocks() as demo:
874
  #utils.dataDelete(filepath+"temp_data/")
875
  #os.mkdir(filepath+"temp_data/")
876
  except FileNotFoundError:
877
- print('break1!!')
878
  break_flag = True
 
879
  break
880
  except OSError as e:
881
  print(e)
@@ -898,8 +909,8 @@ with gr.Blocks() as demo:
898
  # step4: Restore original order
899
  app_utils.restore_order(i, data_shape, new_idx, fill_flags, filepath+"temp_data/denoised.csv", new_filename)
900
  except FileNotFoundError:
901
- print('break2!!')
902
  break_flag = True
 
903
  break
904
  # ----------------------------------------------------------------------------------
905
  utils.dataDelete(filepath+"temp_data/")
 
20
 
21
  ### Step1: Initial Matching and Scaling
22
  After clicking on ``Mapping`` 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**.
23
+ - If your data includes all the 30 template channels, you will be directed to **Mapping Results**.
24
  - 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**.
25
  - If all your channels are included in our template but you have fewer than 30 channels, you will be directed to **Step3**.
26
 
27
  ### Step2: Forwarding Unmatched Channels
28
  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.
29
  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.
30
+ - If all empty template channels are filled by your selections, you will be directed to **Mapping Results**.
31
  - If there are still empty template channels remaining, you will be directed to **Step3**.
32
 
33
  ### Step3: Filling Remaining Template Channels
 
35
  - **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.
36
  - **Zero** method: All empty template channels are filled with zeros.
37
  Choose the method that best suits your needs, considering that the model's performance may vary depending on the method used.
38
+ Once all template channels are filled, you will be directed to **Mapping Results**.
39
 
40
  ### Mapping Results
41
+ After completing the previous steps, your channels will be aligned with the template channels required by our models.
42
+ - 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 results.
43
+ - Once the channel mapping process is completed, a **JSON file** containing the mapping results will be generated. This file is necessary only if you plan to run the models using the source code; otherwise, you can ignore it.
44
 
45
  ## 2. Decode data
46
  After clicking the ``Run`` button, we will process your EEG data based on the mapping results. If necessary, your data will be devided into batches and run the models on each batch sequentially, ensuring that all channels are properly processed.
 
58
  channel_info = JSON.parse(JSON.stringify(channel_info));
59
  stage1_info = app_info.stage1
60
 
61
+ let selector, attribute;
62
  let channel, left, bottom;
63
 
64
  if(stage1_info.state == "step2-selecting"){
65
  selector = "#radio-group > div:nth-of-type(2)";
 
66
  attribute = "value";
67
  }else if(stage1_info.state == "step3-2-selecting"){
68
  selector = "#chkbox-group > div:nth-of-type(2)";
 
69
  attribute = "name";
70
  }else return;
71
 
 
89
  bottom = channel_info.inputDict[channel].css_position[1];
90
 
91
  item.style.cssText = `position: absolute; left: ${left}; bottom: ${bottom};`;
92
+ item.className = "";
93
  item.querySelector(":scope > span").innerText = "";
94
  });
95
 
 
251
  fillmode_btn = gr.Button("OK", visible=False, scale=1)
252
  chkbox_group = gr.CheckboxGroup(elem_id="chkbox-group", visible=False)
253
  # step4 : mapping results
254
+ out_json_file = gr.File(visible=False)
255
  res_md = gr.Markdown("""
256
  (Download this file if you plan to run the models using the source code.)
257
  """, visible=False)
 
385
  if stage1_info["state"] == "step1-initializing":
386
  yield {desc_md : gr.Markdown("Mapping...", visible=True)}
387
 
388
+ # match the names
389
  stage1_info, channel_info, tpl_montage, in_montage = app_utils.match_names(stage1_info, channel_info)
390
  # scale the coordinates
391
  channel_info = app_utils.align_coords(channel_info, tpl_montage, in_montage)
 
428
  # step1 to step4
429
  # the in_channels has all the 30 tpl_channels (in_num>=30)
430
  if matched_num == 30:
431
+ md = """
432
+ ### Mapping Results
433
+ The mapping process has been finished.
434
+ """
435
  # finalize and save the mapping results
436
  filename = filepath+"mapping_result.json"
437
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
438
  stage1_info, stage2_info, channel_info, filename)
 
439
  stage1_info["state"] = "finished"
440
  app_info["stage1"] = stage1_info
441
  app_info["stage2"] = stage2_info
442
  yield {app_info_json : app_info,
443
  channel_info_json : channel_info,
444
+ desc_md : gr.Markdown(md),
445
  tpl_img : gr.Image(visible=False),
446
  mapped_img : gr.Image(visible=False),
447
  next_btn : gr.Button(visible=False),
 
457
  Select one of your unmatched channels to forward its data to the empty template channel
458
  currently indicated in red.
459
  """
460
+ # initialize the progress indication label
461
  stage1_info.update({
462
  "fillingCount" : 1,
463
  "totalFillingNum" : len(stage1_info["missingTemplates"])
 
530
 
531
  # -----------------------------determine the next step------------------------------
532
  # step2 to step4
533
+ # all the unmatched tpl_channels were filled
534
  if len(stage1_info["missingTemplates"]) == 0:
535
+ md = """
536
+ ### Mapping Results
537
+ The mapping process has been finished.
538
+ """
539
  # finalize and save the mapping results
540
  filename = filepath+"mapping_result.json"
541
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
542
  stage1_info, stage2_info, channel_info, filename)
 
543
  stage1_info["state"] = "finished"
544
  app_info["stage1"] = stage1_info
545
  app_info["stage2"] = stage2_info
546
  yield {app_info_json : app_info,
547
  channel_info_json : channel_info,
548
+ desc_md : gr.Markdown(md),
549
  radio_group : gr.Radio(visible=False),
550
  out_json_file : gr.File(filename, visible=True),
551
  res_md : gr.Markdown(visible=True),
 
576
 
577
  # step3-1 to step4
578
  if fillmode == "zero":
579
+ md = """
580
+ ### Mapping Results
581
+ The mapping process has been finished.
582
+ """
583
  # finalize and save the mapping results
584
  filename = filepath+"mapping_result.json"
585
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
586
  stage1_info, stage2_info, channel_info, filename)
 
587
  stage1_info["state"] = "finished"
588
  app_info["stage1"] = stage1_info
589
  app_info["stage2"] = stage2_info
590
  yield {app_info_json : app_info,
591
  channel_info_json : channel_info,
592
+ desc_md : gr.Markdown(md),
593
  in_fillmode : gr.Dropdown(visible=False),
594
  fillmode_btn : gr.Button(visible=False),
595
  out_json_file : gr.File(filename, visible=True),
 
653
  stage1_info["mappingData"][0]["newOrder"][prev_target_idx] = selected_indices
654
  #print(f'{prev_target_name}({prev_target_idx}): {selected_indices}')
655
  # ----------------------------------------------------------------------------------
656
+ md = """
657
+ ### Mapping Results
658
+ The mapping process has been finished.
659
+ """
660
  # finalize and save the mapping results
661
  filename = filepath+"mapping_result.json"
662
  stage1_info, stage2_info, channel_info = app_utils.mapping_result(
663
  stage1_info, stage2_info, channel_info, filename)
 
664
  stage1_info["state"] = "finished"
665
  app_info["stage1"] = stage1_info
666
  app_info["stage2"] = stage2_info
667
  yield {app_info_json : app_info,
668
  channel_info_json : channel_info,
669
+ desc_md : gr.Markdown(md),
670
  chkbox_group : gr.CheckboxGroup(visible=False),
671
  next_btn : gr.Button(visible=False),
672
  out_json_file : gr.File(filename, visible=True),
 
885
  #utils.dataDelete(filepath+"temp_data/")
886
  #os.mkdir(filepath+"temp_data/")
887
  except FileNotFoundError:
 
888
  break_flag = True
889
+ print(e)
890
  break
891
  except OSError as e:
892
  print(e)
 
909
  # step4: Restore original order
910
  app_utils.restore_order(i, data_shape, new_idx, fill_flags, filepath+"temp_data/denoised.csv", new_filename)
911
  except FileNotFoundError:
 
912
  break_flag = True
913
+ print(e)
914
  break
915
  # ----------------------------------------------------------------------------------
916
  utils.dataDelete(filepath+"temp_data/")
app_utils.py CHANGED
@@ -1,6 +1,5 @@
1
  import utils
2
  import os
3
- import time
4
  import math
5
  import json
6
  import numpy as np
@@ -355,7 +354,7 @@ def mapping_result(stage1_info, stage2_info, channel_info, filename):
355
  }
356
  with open(filename, 'w') as jsonfile:
357
  jsonfile.write(json.dumps(new_dict))
358
-
359
  stage2_info["totalBatchNum"] = batch_num
360
  return stage1_info, stage2_info, channel_info
361
 
 
1
  import utils
2
  import os
 
3
  import math
4
  import json
5
  import numpy as np
 
354
  }
355
  with open(filename, 'w') as jsonfile:
356
  jsonfile.write(json.dumps(new_dict))
357
+
358
  stage2_info["totalBatchNum"] = batch_num
359
  return stage1_info, stage2_info, channel_info
360