audrey06100 commited on
Commit
4463626
·
1 Parent(s): 6ad8262
Files changed (2) hide show
  1. app.py +72 -84
  2. 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
- # Run model
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.inputByName[channel].css_position[0];
93
- bottom = channel_info.inputByName[channel].css_position[1];
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.templateByName[channel].css_position[0];
109
- bottom = channel_info.templateByName[channel].css_position[1];
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.inputByName[channel].css_position[0];
154
- bottom = channel_info.inputByName[channel].css_position[1];
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.templateByName[channel].css_position[0];
172
- bottom = channel_info.templateByName[channel].css_position[1];
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;">(...)</p>
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="Imputation", #......
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["inputByName"][channel]["index"] for channel in app_state["stage1UnassignedInputs"]]
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["inputByIndex"])
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 is finished!')
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["templateByIndex"]
422
- if channel_info["templateByName"][channel]["matched"]==False]
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["templateByIndex"]
454
- if channel_info["templateByName"][channel]["matched"]==False]
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["templateByName"][prev_target_name]["index"]
475
  if selected_radio == []:
476
  app_state["stage1NewOrder"][prev_target_idx] = []
477
  else:
478
- selected_idx = channel_info["inputByName"][selected_radio]["index"]
479
  app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
480
 
481
- channel_info["templateByName"][prev_target_name]["matched"] = True
482
- channel_info["inputByName"][selected_radio]["assigned"] = True
483
  print(prev_target_name, '<-', selected_radio)
484
 
485
  app_state.update({
486
- "stage1UnassignedInputs" : [channel for channel in channel_info["inputByIndex"]
487
- if channel_info["inputByName"][channel]["assigned"]==False],
488
- "missingTemplates" : [channel for channel in channel_info["templateByIndex"]
489
- if channel_info["templateByName"][channel]["matched"]==False]
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 is finished!')
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["templateByName"][prev_target_name]["index"]
528
  if selected_chkbox == []:
529
  app_state["stage1NewOrder"][prev_target_idx] = []
530
  else:
531
- selected_idx = [channel_info["inputByName"][channel]["index"] for channel in selected_chkbox]
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 is finished!')
536
  app_state["stage1State"] = "finished"
537
  print('step3 -> Stage2')
538
 
539
- app_state["missingTemplates"] = [channel for channel in channel_info["templateByIndex"]
540
- if channel_info["templateByName"][channel]["matched"]==False]
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["templateByName"][prev_target_name]["index"]
567
  if selected == []:
568
  app_state["stage1NewOrder"][prev_target_idx] = []
569
  else:
570
- selected_idx = channel_info["inputByName"][selected]["index"]
571
  app_state["stage1NewOrder"][prev_target_idx] = [selected_idx]
572
 
573
- channel_info["templateByName"][prev_target_name]["matched"] = True
574
- channel_info["inputByName"][selected]["assigned"] = True
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["inputByIndex"]
580
- if channel_info["inputByName"][channel]["assigned"]==False]
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 is finished!')
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["templateByName"][name]["index"]
627
  value = app_state["stage1NewOrder"][idx]
628
- value = [channel_info["inputByIndex"][i] for i in value]
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["inputByIndex"],
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["inputByIndex"],
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["templateByName"][prev_target_name]["index"]
662
  if selected == []:
663
  app_state["stage1NewOrder"][prev_target_idx] = []
664
  else:
665
- selected_idx = [channel_info["inputByName"][channel]["index"] for channel in selected]
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["templateByName"][target_name]["index"]
674
 
675
  chkbox_value = app_state["stage1NewOrder"][target_idx]
676
- chkbox_value = [channel_info["inputByIndex"][i] for i in chkbox_value]
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["inputByIndex"])
717
- matched_num = len([channel for channel in channel_info["inputByIndex"]
718
- if channel_info["inputByName"][channel]["matched"]==True])
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(server_name="0.0.0.0", server_port=7860)
 
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["templateByIndex"]
42
 
43
  if app_state["runningState"] == "stage1":
44
- new_data = np.zeros((len(channel_info["inputByIndex"]), old_data.shape[1]))
45
  else:
46
  new_data = utils.read_train_data(new_filename)
47
 
@@ -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["templateByName"][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,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["templateByName"]
94
- input_dict = channel_info["inputByName"]
95
- template_order = channel_info["templateByIndex"]
96
- input_order = channel_info["inputByIndex"]
97
  matched = [channel for channel in input_order if input_dict[channel]["matched"]==True]
98
 
99
  # 2-d (for the indication of missing template channel's position when fill_mode:'mean_manual')
@@ -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
- "templateByName" : template_dict,
160
- "inputByName" : 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["templateByName"]
167
- input_dict = channel_info["inputByName"]
168
- template_order = channel_info["templateByIndex"]
169
- input_order = channel_info["inputByIndex"]
170
  #z_row_idx = channel_info["dataShape"][0]
171
  missing_channels = app_state["missingTemplates"]
172
  if missing_channels == []:
@@ -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
- "templateByName" : {k : v.__dict__ for k,v in template_dict.items()},
237
- "inputByName" : {k : v.__dict__ for k,v in input_dict.items()},
238
- "templateByIndex" : template_order,
239
- "inputByIndex" : input_order
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["templateByName"]
261
- input_dict = channel_info["inputByName"]
262
- template_order = channel_info["templateByIndex"]
263
- input_order = channel_info["inputByIndex"]
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
- "templateByName" : template_dict,
305
- "inputByName" : input_dict
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,