wenjun99 commited on
Commit
d6e7437
·
verified ·
1 Parent(s): d0c9af8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -18
app.py CHANGED
@@ -739,7 +739,7 @@ voyager_table = {
739
  }
740
  reverse_voyager_table = {v: k for k, v in voyager_table.items()}
741
 
742
- # === Binary String conversion ===
743
  def binary_labels_to_string(bits: list[int]) -> str:
744
  chars = []
745
  for i in range(0, len(bits), 6):
@@ -752,10 +752,16 @@ def binary_labels_to_string(bits: list[int]) -> str:
752
 
753
  # === Well mapping ===
754
  def get_well_position(sample_index):
755
- row_letter = chr(65 + (sample_index - 1) // 12)
756
- col_number = ((sample_index - 1) % 12) + 1
 
757
  return f"{row_letter}{col_number}"
758
 
 
 
 
 
 
759
  # === Track and replace source if volume exceeded ===
760
  def track_and_replace_source(source_list, robot_script, volume_limit=150):
761
  source_volumes = {}
@@ -782,28 +788,24 @@ def generate_fixed_d_source_instructions_to_all_samples(n_samples, fixed_volume=
782
  current_d_index = 1
783
  for i in range(n_samples):
784
  dest = get_well_position(i + 1)
 
785
  current_d_well = f"D{current_d_index}"
786
  d_source_volumes.setdefault(current_d_well, 0)
787
-
788
  if d_source_volumes[current_d_well] + fixed_volume > volume_limit:
789
  current_d_index += 1
790
  current_d_well = f"D{current_d_index}"
791
  d_source_volumes[current_d_well] = 0
792
-
793
  d_source_volumes[current_d_well] += fixed_volume
794
-
795
- # ✅ Updated: use TS_50 if volume >10 µL, else TS_10
796
  tool = 'TS_50' if fixed_volume > 10 else 'TS_10'
797
  d_source_script.append({
 
798
  'Source': current_d_well,
799
  'Destination': dest,
800
  'Volume': fixed_volume,
801
  'Tool': tool
802
  })
803
-
804
  return d_source_script, d_source_volumes
805
 
806
- # === Source well generation ===
807
  def generate_source_wells(n):
808
  wells, rows = [], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
809
  for i in range(n):
@@ -813,7 +815,6 @@ def generate_source_wells(n):
813
 
814
  # === Main UI ===
815
  st.header("Upload Binary Data (0/1)")
816
-
817
  binary_file = st.file_uploader("Upload Binary CSV", type=["csv"])
818
  st.divider()
819
 
@@ -831,7 +832,7 @@ if binary_file:
831
  else:
832
  st.info("No file uploaded — manually enter binary data below.")
833
  df_binary = st.data_editor(
834
- pd.DataFrame([str(i) for i in range(1, 20)]),
835
  num_rows="dynamic", key="manual_input"
836
  )
837
 
@@ -861,19 +862,24 @@ if not df_binary.empty:
861
  for i, col in enumerate(df_robot.columns[1:]):
862
  for _, sample in df_robot.iterrows():
863
  if int(sample[col]) == 1:
 
 
864
  source = source_wells[i]
865
- dest = get_well_position(int(sample['Sample']))
866
  vol = round(sample['volume donors (µL)'], 2)
867
-
868
- # ✅ Updated: use TS_50 for volumes >10 µL, TS_10 otherwise
869
  tool = 'TS_50' if vol > 10 else 'TS_10'
870
- robot_script.append({'Source': source, 'Destination': dest, 'Volume': vol, 'Tool': tool})
 
 
 
 
 
 
871
 
872
  robot_script, source_volumes = track_and_replace_source(source_wells, robot_script, volume_limit=volume_limit_input)
873
  d_script, d_volumes = generate_fixed_d_source_instructions_to_all_samples(
874
  len(df_robot), fixed_volume=16, volume_limit=volume_limit_input
875
  )
876
-
877
  full_script = robot_script + d_script
878
 
879
  robot_script_df = pd.DataFrame(full_script)
@@ -881,8 +887,9 @@ if not df_binary.empty:
881
  robot_script_df.insert(1, 'Labware_Source', labware_source_input)
882
  robot_script_df.insert(3, 'Labware_Destination', labware_dest_input)
883
  robot_script_df['Name'] = name_input
884
- robot_script_df = robot_script_df[['Barcode ID', 'Labware_Source', 'Source',
885
- 'Labware_Destination', 'Destination', 'Volume', 'Tool', 'Name']]
 
886
 
887
  st.dataframe(robot_script_df)
888
  st.download_button("⬇️ Download Robot Script", robot_script_df.to_csv(index=False), "robot_script.csv")
 
739
  }
740
  reverse_voyager_table = {v: k for k, v in voyager_table.items()}
741
 
742
+ # === Binary String conversion ===
743
  def binary_labels_to_string(bits: list[int]) -> str:
744
  chars = []
745
  for i in range(0, len(bits), 6):
 
752
 
753
  # === Well mapping ===
754
  def get_well_position(sample_index):
755
+ """Convert sample index (1-based) into A1–H12 pattern within its plate"""
756
+ row_letter = chr(65 + ((sample_index - 1) % 96) // 12) # 8 rows (A–H)
757
+ col_number = ((sample_index - 1) % 12) + 1 # 12 columns
758
  return f"{row_letter}{col_number}"
759
 
760
+ def get_plate_id(sample_index):
761
+ """Return Plate number based on 96 samples per plate"""
762
+ plate_number = math.ceil(sample_index / 96)
763
+ return f"Plate {plate_number}"
764
+
765
  # === Track and replace source if volume exceeded ===
766
  def track_and_replace_source(source_list, robot_script, volume_limit=150):
767
  source_volumes = {}
 
788
  current_d_index = 1
789
  for i in range(n_samples):
790
  dest = get_well_position(i + 1)
791
+ plate = get_plate_id(i + 1)
792
  current_d_well = f"D{current_d_index}"
793
  d_source_volumes.setdefault(current_d_well, 0)
 
794
  if d_source_volumes[current_d_well] + fixed_volume > volume_limit:
795
  current_d_index += 1
796
  current_d_well = f"D{current_d_index}"
797
  d_source_volumes[current_d_well] = 0
 
798
  d_source_volumes[current_d_well] += fixed_volume
 
 
799
  tool = 'TS_50' if fixed_volume > 10 else 'TS_10'
800
  d_source_script.append({
801
+ 'Plate': plate,
802
  'Source': current_d_well,
803
  'Destination': dest,
804
  'Volume': fixed_volume,
805
  'Tool': tool
806
  })
 
807
  return d_source_script, d_source_volumes
808
 
 
809
  def generate_source_wells(n):
810
  wells, rows = [], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
811
  for i in range(n):
 
815
 
816
  # === Main UI ===
817
  st.header("Upload Binary Data (0/1)")
 
818
  binary_file = st.file_uploader("Upload Binary CSV", type=["csv"])
819
  st.divider()
820
 
 
832
  else:
833
  st.info("No file uploaded — manually enter binary data below.")
834
  df_binary = st.data_editor(
835
+ pd.DataFrame(columns=[str(i) for i in range(1, 33)]),
836
  num_rows="dynamic", key="manual_input"
837
  )
838
 
 
862
  for i, col in enumerate(df_robot.columns[1:]):
863
  for _, sample in df_robot.iterrows():
864
  if int(sample[col]) == 1:
865
+ sample_id = int(sample['Sample'])
866
+ plate = get_plate_id(sample_id)
867
  source = source_wells[i]
868
+ dest = get_well_position(sample_id)
869
  vol = round(sample['volume donors (µL)'], 2)
 
 
870
  tool = 'TS_50' if vol > 10 else 'TS_10'
871
+ robot_script.append({
872
+ 'Plate': plate, # ✅ New Column
873
+ 'Source': source,
874
+ 'Destination': dest,
875
+ 'Volume': vol,
876
+ 'Tool': tool
877
+ })
878
 
879
  robot_script, source_volumes = track_and_replace_source(source_wells, robot_script, volume_limit=volume_limit_input)
880
  d_script, d_volumes = generate_fixed_d_source_instructions_to_all_samples(
881
  len(df_robot), fixed_volume=16, volume_limit=volume_limit_input
882
  )
 
883
  full_script = robot_script + d_script
884
 
885
  robot_script_df = pd.DataFrame(full_script)
 
887
  robot_script_df.insert(1, 'Labware_Source', labware_source_input)
888
  robot_script_df.insert(3, 'Labware_Destination', labware_dest_input)
889
  robot_script_df['Name'] = name_input
890
+ robot_script_df = robot_script_df[['Barcode ID', 'Labware_Source', 'Plate',
891
+ 'Source', 'Labware_Destination', 'Destination',
892
+ 'Volume', 'Tool', 'Name']]
893
 
894
  st.dataframe(robot_script_df)
895
  st.download_button("⬇️ Download Robot Script", robot_script_df.to_csv(index=False), "robot_script.csv")