wenjun99 commited on
Commit
8f00286
·
verified ·
1 Parent(s): ff7c33d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +207 -30
app.py CHANGED
@@ -388,12 +388,161 @@ def get_well_position(sample_index):
388
  col_number = ((sample_index - 1) % 12) + 1
389
  return f"{row_letter}{col_number}"
390
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  # Tab 5: Binary → String
392
  with tab5:
393
  st.header("Decode Binary Labels to String")
394
 
395
  # Utility: Track source volumes and update if exceeds limit
396
- def track_and_replace_source(source_list, robot_script, volume_limit=180):
397
  source_volumes = {}
398
  adjusted_sources = []
399
 
@@ -441,13 +590,12 @@ with tab5:
441
  d_source_volumes[current_d_well] = 0
442
 
443
  d_source_volumes[current_d_well] += fixed_volume
444
- tool = 'TS_10' if fixed_volume < 10 else 'TS_50'
445
 
446
  d_source_script.append({
447
  'Source': current_d_well,
448
  'Destination': dest,
449
  'Volume': fixed_volume,
450
- 'Tool': tool
451
  })
452
 
453
  return d_source_script, d_source_volumes
@@ -461,38 +609,51 @@ with tab5:
461
  wells.append(f"{row}{col}")
462
  return wells
463
 
464
- st.subheader("Binary per Row")
465
- st.write("Upload CSV with any number of columns (0 or 1), no headers, from EF Binary format or enter manually below.")
 
466
 
467
- binary32_file = st.file_uploader("Upload Binary CSV", type=["csv"], key="binary_any")
468
 
469
  st.subheader("Optional Metadata (Optional)")
470
  barcode_id_input = st.text_input("Barcode ID (applied to all rows, optional)", value="")
471
  labware_source_input = st.text_input("Labware for Source (optional, default = 1)", value="1")
472
  labware_dest_input = st.text_input("Labware for Destination (optional, default = 1)", value="1")
473
  name_input = st.text_input("Name field (optional, default = blank)", value="")
 
474
 
475
  if binary32_file:
476
  df_32 = pd.read_csv(binary32_file, header=None)
477
- df_32.columns = [str(h) for h in range(1, len(df_32.columns)+1)]
478
  else:
479
  df_32 = st.data_editor(
480
- pd.DataFrame(columns=[str(h) for h in range(1, 33)]),
481
  num_rows="dynamic",
482
- key="manual_any_input"
483
  )
484
 
485
  if not df_32.empty:
486
- st.subheader("Binary Labels (Uploaded)")
487
- st.dataframe(df_32.style.applymap(lambda v: "background-color: lightgreen" if v == 1 else "background-color: lightcoral"))
488
- st.download_button("Download CSV", df_32.to_csv(index=False), "decoded_binary_uploaded.csv", key="download_csv_uploaded")
 
489
 
490
- decoded = binary_labels_to_string(df_32.values.flatten().astype(int).tolist())
491
- st.subheader("Decoded String")
492
- st.write(decoded)
493
- st.download_button("Download Concatenated Output", decoded, "decoded_binary_string.txt", key="download_txt_any")
 
 
 
 
 
494
 
495
- st.subheader("Robot Preparation Script from Binary")
 
 
 
 
 
496
 
497
  df_32_robot = df_32.copy()
498
  df_32_robot.insert(0, 'Sample', range(1, len(df_32_robot)+1))
@@ -501,24 +662,40 @@ with tab5:
501
 
502
  robot_script_32 = []
503
  source_wells_32 = generate_source_wells(df_32.shape[1])
 
504
 
505
  for i, col in enumerate(df_32.columns):
506
  for row_idx, sample in df_32_robot.iterrows():
507
  if int(sample[col]) == 1:
508
  source = source_wells_32[i]
509
  dest = get_well_position(int(sample['Sample']))
 
510
  vol = round(sample['volume donors (µl)'], 2)
511
- tool = 'TS_10' if vol < 10 else 'TS_50'
512
- robot_script_32.append({
513
- 'Source': source,
514
- 'Destination': dest,
515
- 'Volume': vol,
516
- 'Tool': tool
517
- })
518
-
519
- robot_script_32, source_volumes_32 = track_and_replace_source(source_wells_32, robot_script_32)
520
-
521
- d_script, d_volumes = generate_fixed_d_source_instructions_to_all_samples(len(df_32_robot))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
  full_robot_script = robot_script_32 + d_script
523
 
524
  robot_script_32_df = pd.DataFrame(full_robot_script)
@@ -529,10 +706,10 @@ with tab5:
529
  robot_script_32_df = robot_script_32_df[['Barcode ID', 'Labware_Source', 'Source', 'Labware_Destination', 'Destination', 'Volume', 'Tool', 'Name']]
530
 
531
  st.dataframe(robot_script_32_df)
532
- st.download_button("Download Robot Script", robot_script_32_df.to_csv(index=False), "robot_script.csv", key="download_robot_any")
533
 
534
  st.subheader("Total Volume Used Per Source")
535
  combined_volumes = {**source_volumes_32, **d_volumes}
536
  source_volume_df = pd.DataFrame(list(combined_volumes.items()), columns=['Source', 'Total Volume (µl)'])
537
  st.dataframe(source_volume_df)
538
- st.download_button("Download Source Volumes", source_volume_df.to_csv(index=False), "source_total_volumes.csv", key="download_volume_any")
 
388
  col_number = ((sample_index - 1) % 12) + 1
389
  return f"{row_letter}{col_number}"
390
 
391
+ # # Tab 5: Binary → String
392
+ # with tab5:
393
+ # st.header("Decode Binary Labels to String")
394
+
395
+ # # Utility: Track source volumes and update if exceeds limit
396
+ # def track_and_replace_source(source_list, robot_script, volume_limit=180):
397
+ # source_volumes = {}
398
+ # adjusted_sources = []
399
+
400
+ # for entry in robot_script:
401
+ # src = entry['Source']
402
+ # vol = entry['Volume']
403
+
404
+ # if src not in source_volumes:
405
+ # source_volumes[src] = 0
406
+
407
+ # source_volumes[src] += vol
408
+
409
+ # if source_volumes[src] > volume_limit:
410
+ # row_letter = src[0]
411
+ # col_number = src[1:]
412
+ # new_row_letter = chr(ord(row_letter) + 4)
413
+ # new_src = f"{new_row_letter}{col_number}"
414
+ # entry['Source'] = new_src
415
+
416
+ # if new_src not in source_volumes:
417
+ # source_volumes[new_src] = 0
418
+ # source_volumes[new_src] += vol
419
+ # source_volumes[src] -= vol
420
+
421
+ # adjusted_sources.append(entry)
422
+
423
+ # return adjusted_sources, source_volumes
424
+
425
+ # # Utility: Generate fixed-volume D source to all sample wells
426
+ # def generate_fixed_d_source_instructions_to_all_samples(n_samples, fixed_volume=16, volume_limit=170):
427
+ # d_source_volumes = {}
428
+ # d_source_script = []
429
+ # current_d_index = 1
430
+
431
+ # for i in range(n_samples):
432
+ # dest = get_well_position(i + 1)
433
+ # current_d_well = f"D{current_d_index}"
434
+
435
+ # if current_d_well not in d_source_volumes:
436
+ # d_source_volumes[current_d_well] = 0
437
+
438
+ # if d_source_volumes[current_d_well] + fixed_volume > volume_limit:
439
+ # current_d_index += 1
440
+ # current_d_well = f"D{current_d_index}"
441
+ # d_source_volumes[current_d_well] = 0
442
+
443
+ # d_source_volumes[current_d_well] += fixed_volume
444
+ # tool = 'TS_10' if fixed_volume < 10 else 'TS_50'
445
+
446
+ # d_source_script.append({
447
+ # 'Source': current_d_well,
448
+ # 'Destination': dest,
449
+ # 'Volume': fixed_volume,
450
+ # 'Tool': tool
451
+ # })
452
+
453
+ # return d_source_script, d_source_volumes
454
+
455
+ # def generate_source_wells(n):
456
+ # wells = []
457
+ # rows = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
458
+ # for i in range(n):
459
+ # row = rows[i // 12] # cycle through A, B, C...
460
+ # col = (i % 12) + 1 # 1 to 12
461
+ # wells.append(f"{row}{col}")
462
+ # return wells
463
+
464
+ # st.subheader("Binary per Row")
465
+ # st.write("Upload CSV with any number of columns (0 or 1), no headers, from EF Binary format or enter manually below.")
466
+
467
+ # binary32_file = st.file_uploader("Upload Binary CSV", type=["csv"], key="binary_any")
468
+
469
+ # st.subheader("Optional Metadata (Optional)")
470
+ # barcode_id_input = st.text_input("Barcode ID (applied to all rows, optional)", value="")
471
+ # labware_source_input = st.text_input("Labware for Source (optional, default = 1)", value="1")
472
+ # labware_dest_input = st.text_input("Labware for Destination (optional, default = 1)", value="1")
473
+ # name_input = st.text_input("Name field (optional, default = blank)", value="")
474
+
475
+ # if binary32_file:
476
+ # df_32 = pd.read_csv(binary32_file, header=None)
477
+ # df_32.columns = [str(h) for h in range(1, len(df_32.columns)+1)]
478
+ # else:
479
+ # df_32 = st.data_editor(
480
+ # pd.DataFrame(columns=[str(h) for h in range(1, 33)]),
481
+ # num_rows="dynamic",
482
+ # key="manual_any_input"
483
+ # )
484
+
485
+ # if not df_32.empty:
486
+ # st.subheader("Binary Labels (Uploaded)")
487
+ # st.dataframe(df_32.style.applymap(lambda v: "background-color: lightgreen" if v == 1 else "background-color: lightcoral"))
488
+ # st.download_button("Download CSV", df_32.to_csv(index=False), "decoded_binary_uploaded.csv", key="download_csv_uploaded")
489
+
490
+ # decoded = binary_labels_to_string(df_32.values.flatten().astype(int).tolist())
491
+ # st.subheader("Decoded String")
492
+ # st.write(decoded)
493
+ # st.download_button("Download Concatenated Output", decoded, "decoded_binary_string.txt", key="download_txt_any")
494
+
495
+ # st.subheader("Robot Preparation Script from Binary")
496
+
497
+ # df_32_robot = df_32.copy()
498
+ # df_32_robot.insert(0, 'Sample', range(1, len(df_32_robot)+1))
499
+ # df_32_robot['# donors'] = df_32_robot.iloc[:, 1:].astype(int).sum(axis=1)
500
+ # df_32_robot['volume donors (µl)'] = 64 / df_32_robot['# donors']
501
+
502
+ # robot_script_32 = []
503
+ # source_wells_32 = generate_source_wells(df_32.shape[1])
504
+
505
+ # for i, col in enumerate(df_32.columns):
506
+ # for row_idx, sample in df_32_robot.iterrows():
507
+ # if int(sample[col]) == 1:
508
+ # source = source_wells_32[i]
509
+ # dest = get_well_position(int(sample['Sample']))
510
+ # vol = round(sample['volume donors (µl)'], 2)
511
+ # tool = 'TS_10' if vol < 10 else 'TS_50'
512
+ # robot_script_32.append({
513
+ # 'Source': source,
514
+ # 'Destination': dest,
515
+ # 'Volume': vol,
516
+ # 'Tool': tool
517
+ # })
518
+
519
+ # robot_script_32, source_volumes_32 = track_and_replace_source(source_wells_32, robot_script_32)
520
+
521
+ # d_script, d_volumes = generate_fixed_d_source_instructions_to_all_samples(len(df_32_robot))
522
+ # full_robot_script = robot_script_32 + d_script
523
+
524
+ # robot_script_32_df = pd.DataFrame(full_robot_script)
525
+ # robot_script_32_df.insert(0, 'Barcode ID', barcode_id_input)
526
+ # robot_script_32_df.insert(1, 'Labware_Source', labware_source_input)
527
+ # robot_script_32_df.insert(3, 'Labware_Destination', labware_dest_input)
528
+ # robot_script_32_df['Name'] = name_input
529
+ # robot_script_32_df = robot_script_32_df[['Barcode ID', 'Labware_Source', 'Source', 'Labware_Destination', 'Destination', 'Volume', 'Tool', 'Name']]
530
+
531
+ # st.dataframe(robot_script_32_df)
532
+ # st.download_button("Download Robot Script", robot_script_32_df.to_csv(index=False), "robot_script.csv", key="download_robot_any")
533
+
534
+ # st.subheader("Total Volume Used Per Source")
535
+ # combined_volumes = {**source_volumes_32, **d_volumes}
536
+ # source_volume_df = pd.DataFrame(list(combined_volumes.items()), columns=['Source', 'Total Volume (µl)'])
537
+ # st.dataframe(source_volume_df)
538
+ # st.download_button("Download Source Volumes", source_volume_df.to_csv(index=False), "source_total_volumes.csv", key="download_volume_any")
539
+
540
  # Tab 5: Binary → String
541
  with tab5:
542
  st.header("Decode Binary Labels to String")
543
 
544
  # Utility: Track source volumes and update if exceeds limit
545
+ def track_and_replace_source(source_list, robot_script, volume_limit):
546
  source_volumes = {}
547
  adjusted_sources = []
548
 
 
590
  d_source_volumes[current_d_well] = 0
591
 
592
  d_source_volumes[current_d_well] += fixed_volume
 
593
 
594
  d_source_script.append({
595
  'Source': current_d_well,
596
  'Destination': dest,
597
  'Volume': fixed_volume,
598
+ 'Tool': 'TS_10'
599
  })
600
 
601
  return d_source_script, d_source_volumes
 
609
  wells.append(f"{row}{col}")
610
  return wells
611
 
612
+ # ========== 32-BIT DECODING ==========
613
+ st.subheader("32-bit Binary per Row")
614
+ st.write("Upload CSV with 32 columns (0 or 1), no headers, from EF Binary format or enter manually below.")
615
 
616
+ binary32_file = st.file_uploader("Upload 32-bit Binary CSV", type=["csv"], key="binary_32")
617
 
618
  st.subheader("Optional Metadata (Optional)")
619
  barcode_id_input = st.text_input("Barcode ID (applied to all rows, optional)", value="")
620
  labware_source_input = st.text_input("Labware for Source (optional, default = 1)", value="1")
621
  labware_dest_input = st.text_input("Labware for Destination (optional, default = 1)", value="1")
622
  name_input = st.text_input("Name field (optional, default = blank)", value="")
623
+ volume_limit_input = st.number_input("Volume limit per source well (µl)", min_value=1, max_value=500, value=180, step=10)
624
 
625
  if binary32_file:
626
  df_32 = pd.read_csv(binary32_file, header=None)
627
+ df_32.columns = [str(h) for h in mutation_site_headers_actual_3614]
628
  else:
629
  df_32 = st.data_editor(
630
+ pd.DataFrame(columns=[str(h) for h in mutation_site_headers_actual_3614]),
631
  num_rows="dynamic",
632
+ key="manual_32_input"
633
  )
634
 
635
  if not df_32.empty:
636
+ reordered_df_32 = df_32[[str(h) for h in mutation_site_headers_3614 if str(h) in df_32.columns]]
637
+ st.subheader("Binary Labels (Reordered 4402→3244, 4882→4455)")
638
+ st.dataframe(reordered_df_32.style.applymap(lambda v: "background-color: lightgreen" if v == 1 else "background-color: lightcoral"))
639
+ st.download_button("Download Reordered CSV", reordered_df_32.to_csv(index=False), "decoded_binary_32_reordered.csv", key="download_csv_tab5_32_reordered")
640
 
641
+ decoded_reordered = binary_labels_to_string(reordered_df_32.values.flatten().astype(int).tolist())
642
+ st.subheader("Decoded String (Reordered 4402→3244, 4882→4455)")
643
+ st.write(decoded_reordered)
644
+ st.download_button("Download Concatenated Output", decoded_reordered, "decoded_32bit_string_reordered.txt", key="download_txt_tab5_32")
645
+
646
+ df_32_asc = df_32[[str(h) for h in mutation_site_headers_actual_3614 if str(h) in df_32.columns]]
647
+ st.subheader("Binary Labels (Ascending 3244→4882)")
648
+ st.dataframe(df_32_asc.style.applymap(lambda v: "background-color: lightgreen" if v == 1 else "background-color: lightcoral"))
649
+ st.download_button("Download Ascending CSV", df_32_asc.to_csv(index=False), "decoded_binary_32_ascending.csv", key="download_csv_tab5_32_ascend")
650
 
651
+ decoded_asc = binary_labels_to_string(df_32_asc.values.flatten().astype(int).tolist())
652
+ st.subheader("Decoded String (Flattened 32-bit Ascending)")
653
+ st.write(decoded_asc)
654
+ st.download_button("Download Concatenated Output", decoded_asc, "decoded_32bit_string_ascending.txt", key="download_txt_tab5_32_asc")
655
+
656
+ st.subheader("Robot Preparation Script from 32-bit Binary")
657
 
658
  df_32_robot = df_32.copy()
659
  df_32_robot.insert(0, 'Sample', range(1, len(df_32_robot)+1))
 
662
 
663
  robot_script_32 = []
664
  source_wells_32 = generate_source_wells(df_32.shape[1])
665
+ used_destinations = set()
666
 
667
  for i, col in enumerate(df_32.columns):
668
  for row_idx, sample in df_32_robot.iterrows():
669
  if int(sample[col]) == 1:
670
  source = source_wells_32[i]
671
  dest = get_well_position(int(sample['Sample']))
672
+ used_destinations.add(dest)
673
  vol = round(sample['volume donors (µl)'], 2)
674
+ if vol > 10:
675
+ half_vol = round(vol / 2, 2)
676
+ robot_script_32.append({
677
+ 'Source': source,
678
+ 'Destination': dest,
679
+ 'Volume': half_vol,
680
+ 'Tool': 'TS_10'
681
+ })
682
+ robot_script_32.append({
683
+ 'Source': source,
684
+ 'Destination': dest,
685
+ 'Volume': vol - half_vol,
686
+ 'Tool': 'TS_10'
687
+ })
688
+ else:
689
+ robot_script_32.append({
690
+ 'Source': source,
691
+ 'Destination': dest,
692
+ 'Volume': vol,
693
+ 'Tool': 'TS_10'
694
+ })
695
+
696
+ robot_script_32, source_volumes_32 = track_and_replace_source(source_wells_32, robot_script_32, volume_limit=volume_limit_input)
697
+
698
+ d_script, d_volumes = generate_fixed_d_source_instructions_to_all_samples(len(df_32_robot), volume_limit=volume_limit_input)
699
  full_robot_script = robot_script_32 + d_script
700
 
701
  robot_script_32_df = pd.DataFrame(full_robot_script)
 
706
  robot_script_32_df = robot_script_32_df[['Barcode ID', 'Labware_Source', 'Source', 'Labware_Destination', 'Destination', 'Volume', 'Tool', 'Name']]
707
 
708
  st.dataframe(robot_script_32_df)
709
+ st.download_button("Download Robot Script (32-bit)", robot_script_32_df.to_csv(index=False), "robot_script_32bit.csv", key="download_robot_32")
710
 
711
  st.subheader("Total Volume Used Per Source")
712
  combined_volumes = {**source_volumes_32, **d_volumes}
713
  source_volume_df = pd.DataFrame(list(combined_volumes.items()), columns=['Source', 'Total Volume (µl)'])
714
  st.dataframe(source_volume_df)
715
+ st.download_button("Download Source Volumes", source_volume_df.to_csv(index=False), "source_total_volumes.csv", key="download_volume_32")