Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,7 +11,26 @@ os.makedirs(temp_dir, exist_ok=True)
|
|
| 11 |
|
| 12 |
# Streamlit UI setup
|
| 13 |
st.set_page_config(page_title="PCR Primer Design", page_icon="🧬", layout="wide")
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
# Custom CSS for styling
|
| 17 |
st.markdown("""
|
|
@@ -60,52 +79,73 @@ def design_primers_for_region(sequence, product_size_range, num_to_return=10):
|
|
| 60 |
if uploaded_file is not None:
|
| 61 |
genbank_content = StringIO(uploaded_file.getvalue().decode("utf-8"))
|
| 62 |
features, record = extract_features_from_genbank(genbank_content)
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
|
|
|
| 11 |
|
| 12 |
# Streamlit UI setup
|
| 13 |
st.set_page_config(page_title="PCR Primer Design", page_icon="🧬", layout="wide")
|
| 14 |
+
|
| 15 |
+
# User Documentation
|
| 16 |
+
st.sidebar.header("User Guide")
|
| 17 |
+
st.sidebar.info(
|
| 18 |
+
"""
|
| 19 |
+
This application allows you to design PCR primers for specific features within a GenBank file.
|
| 20 |
+
Follow these steps:
|
| 21 |
+
1. Upload a GenBank file.
|
| 22 |
+
2. Select a feature type and then a specific feature.
|
| 23 |
+
3. Enter the desired PCR product size range and the minimum number of primer pairs.
|
| 24 |
+
4. Click 'Design Primers' to generate your primers.
|
| 25 |
+
"""
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
# File uploader with additional help
|
| 29 |
+
uploaded_file = st.file_uploader(
|
| 30 |
+
"Upload a GenBank file",
|
| 31 |
+
type=['gb', 'gbk'],
|
| 32 |
+
help="Upload a GenBank (.gb or .gbk) file containing the DNA sequence from which to design primers."
|
| 33 |
+
)
|
| 34 |
|
| 35 |
# Custom CSS for styling
|
| 36 |
st.markdown("""
|
|
|
|
| 79 |
if uploaded_file is not None:
|
| 80 |
genbank_content = StringIO(uploaded_file.getvalue().decode("utf-8"))
|
| 81 |
features, record = extract_features_from_genbank(genbank_content)
|
| 82 |
+
|
| 83 |
+
st.write("## Feature Selection")
|
| 84 |
+
feature_type = st.selectbox(
|
| 85 |
+
'Select feature type:',
|
| 86 |
+
['CDS', 'tRNA', 'gene'],
|
| 87 |
+
help="Choose the type of genomic feature for which you want to design primers."
|
| 88 |
+
)
|
| 89 |
|
| 90 |
+
if features[feature_type]:
|
| 91 |
+
feature_options = [f"{feature.qualifiers.get('gene', [''])[0]} ({feature.location})" for feature in features[feature_type]]
|
| 92 |
+
selected_index = st.selectbox(
|
| 93 |
+
f'Select a {feature_type}:',
|
| 94 |
+
options=range(len(feature_options)),
|
| 95 |
+
format_func=lambda x: feature_options[x],
|
| 96 |
+
help="Select a specific feature based on its gene name and location."
|
| 97 |
+
)
|
| 98 |
+
selected_feature = features[feature_type][selected_index]
|
| 99 |
|
| 100 |
+
feature_sequence = selected_feature.extract(record.seq)
|
| 101 |
+
st.write(f"Selected {feature_type} sequence (length: {len(feature_sequence)} bp):")
|
| 102 |
+
st.code(str(feature_sequence), language="text") # Display sequence in code format
|
| 103 |
|
| 104 |
+
st.write("## Primer Design Parameters")
|
| 105 |
+
product_size_range = st.text_input(
|
| 106 |
+
"Enter desired PCR product size range (e.g., 150-500):",
|
| 107 |
+
value="150-500",
|
| 108 |
+
help="Specify the range of the desired PCR product size in base pairs (e.g., 150-500)."
|
| 109 |
+
)
|
| 110 |
+
min_num_primers = st.number_input(
|
| 111 |
+
"Enter minimum number of primer pairs to return:",
|
| 112 |
+
min_value=5, value=5, step=1,
|
| 113 |
+
help="Determine the minimum number of primer pairs to generate."
|
| 114 |
+
)
|
| 115 |
|
| 116 |
+
if st.button(f'Design Primers for selected {feature_type}'):
|
| 117 |
+
with st.spinner('Designing primers...'): # Show a spinner while primers are being designed
|
| 118 |
+
primers = design_primers_for_region(feature_sequence, product_size_range, num_to_return=min_num_primers)
|
| 119 |
|
| 120 |
+
primer_data = []
|
| 121 |
+
for i in range(min_num_primers):
|
| 122 |
+
left_sequence = primers.get(f'PRIMER_LEFT_{i}_SEQUENCE', 'N/A')
|
| 123 |
+
right_sequence = primers.get(f'PRIMER_RIGHT_{i}_SEQUENCE', 'N/A')
|
| 124 |
+
if left_sequence != 'N/A' and right_sequence != 'N/A':
|
| 125 |
+
primer_info = {
|
| 126 |
+
'Primer Pair': i + 1,
|
| 127 |
+
'Left Sequence': left_sequence,
|
| 128 |
+
'Right Sequence': right_sequence,
|
| 129 |
+
'Left TM (°C)': primers.get(f'PRIMER_LEFT_{i}_TM', 'N/A'),
|
| 130 |
+
'Right TM (°C)': primers.get(f'PRIMER_RIGHT_{i}_TM', 'N/A'),
|
| 131 |
+
'Left Length': len(left_sequence),
|
| 132 |
+
'Right Length': len(right_sequence),
|
| 133 |
+
'PCR Product Size (bp)': primers.get(f'PRIMER_PAIR_{i}_PRODUCT_SIZE', 'N/A')
|
| 134 |
+
}
|
| 135 |
+
primer_data.append(primer_info)
|
| 136 |
|
| 137 |
+
if primer_data:
|
| 138 |
+
st.subheader('Designed Primers')
|
| 139 |
+
primer_df = pd.DataFrame(primer_data)
|
| 140 |
+
st.table(primer_df) # Use st.table to display the primer data
|
| 141 |
|
| 142 |
+
csv = primer_df.to_csv(index=False).encode('utf-8')
|
| 143 |
+
st.download_button(
|
| 144 |
+
"Download Primers as CSV",
|
| 145 |
+
csv,
|
| 146 |
+
"primers.csv",
|
| 147 |
+
"text/csv",
|
| 148 |
+
key='download-csv'
|
| 149 |
+
)
|
| 150 |
+
else:
|
| 151 |
+
st.error('No primers were found. Please adjust your parameters and try again.')
|