Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -392,12 +392,87 @@ def get_well_position(sample_index):
|
|
392 |
with tab5:
|
393 |
st.header("Decode Binary Labels to String")
|
394 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
# ========== 32-BIT DECODING ==========
|
396 |
st.subheader("32-bit Binary per Row")
|
397 |
st.write("Upload CSV with 32 columns (0 or 1), no headers, from EF Binary format or enter manually below.")
|
398 |
|
399 |
binary32_file = st.file_uploader("Upload 32-bit Binary CSV", type=["csv"], key="binary_32")
|
400 |
|
|
|
|
|
|
|
|
|
|
|
|
|
401 |
if binary32_file:
|
402 |
df_32 = pd.read_csv(binary32_file, header=None)
|
403 |
df_32.columns = [str(h) for h in mutation_site_headers_actual_3614]
|
@@ -429,10 +504,7 @@ with tab5:
|
|
429 |
st.write(decoded_asc)
|
430 |
st.download_button("Download Concatenated Output", decoded_asc, "decoded_32bit_string_ascending.txt", key="download_txt_tab5_32_asc")
|
431 |
|
432 |
-
# === Robot Preparation Script from 32-bit Binary ===
|
433 |
st.subheader("Robot Preparation Script from 32-bit Binary")
|
434 |
-
robot_template_32 = pd.read_csv("/home/user/app/Robot2.csv", skiprows=3)
|
435 |
-
robot_template_32.columns = ['Labware', 'Source', 'Labware_2', 'Destination', 'Volume', 'Tool', 'Name']
|
436 |
|
437 |
df_32_robot = df_32.copy()
|
438 |
df_32_robot.insert(0, 'Sample', range(1, len(df_32_robot)+1))
|
@@ -440,23 +512,45 @@ with tab5:
|
|
440 |
df_32_robot['volume donors (µl)'] = 64 / df_32_robot['# donors']
|
441 |
|
442 |
robot_script_32 = []
|
443 |
-
source_wells_32 =
|
444 |
-
|
445 |
-
source_wells_32 += [f"Fake{i}" for i in range(df_32.shape[1] - len(source_wells_32))]
|
446 |
-
source_wells_32 = source_wells_32[:df_32.shape[1]]
|
447 |
|
448 |
for i, col in enumerate(df_32.columns):
|
449 |
for row_idx, sample in df_32_robot.iterrows():
|
450 |
if int(sample[col]) == 1:
|
451 |
source = source_wells_32[i]
|
452 |
dest = get_well_position(int(sample['Sample']))
|
|
|
453 |
vol = round(sample['volume donors (µl)'], 2)
|
454 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
|
456 |
-
robot_script_32_df = pd.DataFrame(robot_script_32)
|
457 |
st.dataframe(robot_script_32_df)
|
458 |
st.download_button("Download Robot Script (32-bit)", robot_script_32_df.to_csv(index=False), "robot_script_32bit.csv", key="download_robot_32")
|
459 |
|
|
|
|
|
|
|
|
|
|
|
|
|
460 |
st.markdown("---")
|
461 |
|
462 |
# ========== 31-BIT DECODING ==========
|
|
|
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=170):
|
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 |
# ========== 32-BIT DECODING ==========
|
465 |
st.subheader("32-bit Binary per Row")
|
466 |
st.write("Upload CSV with 32 columns (0 or 1), no headers, from EF Binary format or enter manually below.")
|
467 |
|
468 |
binary32_file = st.file_uploader("Upload 32-bit Binary CSV", type=["csv"], key="binary_32")
|
469 |
|
470 |
+
st.subheader("Optional Metadata (Optional)")
|
471 |
+
barcode_id_input = st.text_input("Barcode ID (applied to all rows, optional)", value="")
|
472 |
+
labware_source_input = st.text_input("Labware for Source (optional, default = 1)", value="1")
|
473 |
+
labware_dest_input = st.text_input("Labware for Destination (optional, default = 1)", value="1")
|
474 |
+
name_input = st.text_input("Name field (optional, default = blank)", value="")
|
475 |
+
|
476 |
if binary32_file:
|
477 |
df_32 = pd.read_csv(binary32_file, header=None)
|
478 |
df_32.columns = [str(h) for h in mutation_site_headers_actual_3614]
|
|
|
504 |
st.write(decoded_asc)
|
505 |
st.download_button("Download Concatenated Output", decoded_asc, "decoded_32bit_string_ascending.txt", key="download_txt_tab5_32_asc")
|
506 |
|
|
|
507 |
st.subheader("Robot Preparation Script from 32-bit Binary")
|
|
|
|
|
508 |
|
509 |
df_32_robot = df_32.copy()
|
510 |
df_32_robot.insert(0, 'Sample', range(1, len(df_32_robot)+1))
|
|
|
512 |
df_32_robot['volume donors (µl)'] = 64 / df_32_robot['# donors']
|
513 |
|
514 |
robot_script_32 = []
|
515 |
+
source_wells_32 = generate_source_wells(df_32.shape[1])
|
516 |
+
used_destinations = set()
|
|
|
|
|
517 |
|
518 |
for i, col in enumerate(df_32.columns):
|
519 |
for row_idx, sample in df_32_robot.iterrows():
|
520 |
if int(sample[col]) == 1:
|
521 |
source = source_wells_32[i]
|
522 |
dest = get_well_position(int(sample['Sample']))
|
523 |
+
used_destinations.add(dest)
|
524 |
vol = round(sample['volume donors (µl)'], 2)
|
525 |
+
tool = 'TS_10' if vol < 10 else 'TS_50'
|
526 |
+
robot_script_32.append({
|
527 |
+
'Source': source,
|
528 |
+
'Destination': dest,
|
529 |
+
'Volume': vol,
|
530 |
+
'Tool': tool
|
531 |
+
})
|
532 |
+
|
533 |
+
robot_script_32, source_volumes_32 = track_and_replace_source(source_wells_32, robot_script_32)
|
534 |
+
|
535 |
+
d_script, d_volumes = generate_fixed_d_source_instructions_to_all_samples(len(df_32_robot))
|
536 |
+
full_robot_script = robot_script_32 + d_script
|
537 |
+
|
538 |
+
robot_script_32_df = pd.DataFrame(full_robot_script)
|
539 |
+
robot_script_32_df.insert(0, 'Barcode ID', barcode_id_input)
|
540 |
+
robot_script_32_df.insert(1, 'Labware_Source', labware_source_input)
|
541 |
+
robot_script_32_df.insert(3, 'Labware_Destination', labware_dest_input)
|
542 |
+
robot_script_32_df['Name'] = name_input
|
543 |
+
robot_script_32_df = robot_script_32_df[['Barcode ID', 'Labware_Source', 'Source', 'Labware_Destination', 'Destination', 'Volume', 'Tool', 'Name']]
|
544 |
|
|
|
545 |
st.dataframe(robot_script_32_df)
|
546 |
st.download_button("Download Robot Script (32-bit)", robot_script_32_df.to_csv(index=False), "robot_script_32bit.csv", key="download_robot_32")
|
547 |
|
548 |
+
st.subheader("Total Volume Used Per Source")
|
549 |
+
combined_volumes = {**source_volumes_32, **d_volumes}
|
550 |
+
source_volume_df = pd.DataFrame(list(combined_volumes.items()), columns=['Source', 'Total Volume (µl)'])
|
551 |
+
st.dataframe(source_volume_df)
|
552 |
+
st.download_button("Download Source Volumes", source_volume_df.to_csv(index=False), "source_total_volumes.csv", key="download_volume_32")
|
553 |
+
|
554 |
st.markdown("---")
|
555 |
|
556 |
# ========== 31-BIT DECODING ==========
|