Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,66 +7,71 @@ from io import StringIO
|
|
| 7 |
st.title('PCR Primer Design Tool')
|
| 8 |
st.write('Upload a FASTA file with your DNA sequence to design PCR primers.')
|
| 9 |
|
| 10 |
-
# User
|
| 11 |
fasta_file = st.file_uploader("Upload DNA sequence (FASTA format):", type=['fasta', 'fa'])
|
| 12 |
-
|
| 13 |
-
# Input for target region
|
| 14 |
target_start = st.number_input("Target start position:", min_value=0, value=0, step=1)
|
| 15 |
-
target_length = st.number_input("Target length:", min_value=
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
if st.button('Design Primers'):
|
| 18 |
-
if fasta_file
|
| 19 |
# Read the sequence from the FASTA file
|
| 20 |
sequence_data = StringIO(fasta_file.getvalue().decode("utf-8"))
|
| 21 |
record = next(SeqIO.parse(sequence_data, "fasta"))
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
# Remove non-sequence characters (e.g., spaces, line breaks)
|
| 25 |
-
clean_sequence = ''.join(user_sequence.split())
|
| 26 |
-
|
| 27 |
-
# Validate DNA sequence
|
| 28 |
-
if not all(nucleotide in 'ATCG' for nucleotide in clean_sequence):
|
| 29 |
-
st.error('Invalid DNA sequence: please ensure it contains only A, T, C, and G.')
|
| 30 |
-
else:
|
| 31 |
-
# Define target region based on user input
|
| 32 |
-
target = [(target_start, target_length)]
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
'PRIMER_MAX_SIZE': 25,
|
| 41 |
-
'PRIMER_OPT_TM': 60.0,
|
| 42 |
-
'PRIMER_MIN_TM': 57.0,
|
| 43 |
-
'PRIMER_MAX_TM': 63.0,
|
| 44 |
-
'PRIMER_MIN_GC': 20.0,
|
| 45 |
-
'PRIMER_MAX_GC': 80.0,
|
| 46 |
-
}
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
st.write(f"
|
| 67 |
-
st.write(f"Left Primer
|
| 68 |
-
st.write(f"Right Primer
|
| 69 |
-
|
| 70 |
-
st.
|
|
|
|
|
|
|
| 71 |
else:
|
| 72 |
-
st.error('Please upload a valid FASTA file
|
|
|
|
| 7 |
st.title('PCR Primer Design Tool')
|
| 8 |
st.write('Upload a FASTA file with your DNA sequence to design PCR primers.')
|
| 9 |
|
| 10 |
+
# User inputs
|
| 11 |
fasta_file = st.file_uploader("Upload DNA sequence (FASTA format):", type=['fasta', 'fa'])
|
| 12 |
+
sequence_id = st.text_input("Sequence ID:", value="")
|
|
|
|
| 13 |
target_start = st.number_input("Target start position:", min_value=0, value=0, step=1)
|
| 14 |
+
target_length = st.number_input("Target length:", min_value=0, value=100, step=1)
|
| 15 |
+
excluded_regions = st.text_input("Excluded Regions (format: start,length start,length ...):", value="")
|
| 16 |
+
included_region_start = st.number_input("Included Region Start:", min_value=0, value=20, step=1)
|
| 17 |
+
included_region_length = st.number_input("Included Region Length:", min_value=0, value=400, step=1)
|
| 18 |
+
primer_num_return = st.number_input("Number of Primer Pairs to Return:", min_value=1, value=5, step=1)
|
| 19 |
|
| 20 |
if st.button('Design Primers'):
|
| 21 |
+
if fasta_file:
|
| 22 |
# Read the sequence from the FASTA file
|
| 23 |
sequence_data = StringIO(fasta_file.getvalue().decode("utf-8"))
|
| 24 |
record = next(SeqIO.parse(sequence_data, "fasta"))
|
| 25 |
+
sequence = str(record.seq).upper() # Ensure sequence is uppercase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
+
# Prepare excluded regions format for Primer3
|
| 28 |
+
excluded_regions_list = excluded_regions.split()
|
| 29 |
+
excluded_regions_formatted = []
|
| 30 |
+
for region in excluded_regions_list:
|
| 31 |
+
start, length = region.split(',')
|
| 32 |
+
excluded_regions_formatted.append((int(start), int(length)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
+
# Design primers using Primer3
|
| 35 |
+
try:
|
| 36 |
+
primers = primer3.bindings.designPrimers(
|
| 37 |
+
{
|
| 38 |
+
'SEQUENCE_ID': sequence_id,
|
| 39 |
+
'SEQUENCE_TEMPLATE': sequence,
|
| 40 |
+
'SEQUENCE_TARGET': [(target_start, target_length)],
|
| 41 |
+
'SEQUENCE_EXCLUDED_REGION': excluded_regions_formatted,
|
| 42 |
+
'SEQUENCE_INCLUDED_REGION': (included_region_start, included_region_length),
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
'PRIMER_TASK': 'generic',
|
| 46 |
+
'PRIMER_PICK_LEFT_PRIMER': 1,
|
| 47 |
+
'PRIMER_PICK_INTERNAL_OLIGO': 0,
|
| 48 |
+
'PRIMER_PICK_RIGHT_PRIMER': 1,
|
| 49 |
+
'PRIMER_OPT_SIZE': 20,
|
| 50 |
+
'PRIMER_MIN_SIZE': 18,
|
| 51 |
+
'PRIMER_MAX_SIZE': 23,
|
| 52 |
+
'PRIMER_OPT_TM': 59.0,
|
| 53 |
+
'PRIMER_MIN_TM': 57.0,
|
| 54 |
+
'PRIMER_MAX_TM': 62.0,
|
| 55 |
+
'PRIMER_MIN_GC': 30.0,
|
| 56 |
+
'PRIMER_MAX_GC': 70.0,
|
| 57 |
+
'PRIMER_MAX_POLY_X': 4,
|
| 58 |
+
'PRIMER_SALT_MONOVALENT': 50.0,
|
| 59 |
+
'PRIMER_SALT_DIVALENT': 1.5,
|
| 60 |
+
'PRIMER_DNTP_CONC': 0.6,
|
| 61 |
+
'PRIMER_NUM_RETURN': primer_num_return,
|
| 62 |
+
'PRIMER_PRODUCT_SIZE_RANGE': [[150,250], [100,300], [301,400], [401,500], [501,600], [601,700], [701,850], [851,1000]],
|
| 63 |
+
}
|
| 64 |
+
)
|
| 65 |
|
| 66 |
+
# Display the results
|
| 67 |
+
st.subheader('Designed Primers:')
|
| 68 |
+
for i in range(primer_num_return):
|
| 69 |
+
st.write(f"Primer Pair {i+1}:")
|
| 70 |
+
st.write(f"Left Primer (5'-3'): {primers.get(f'PRIMER_LEFT_{i}_SEQUENCE', 'Not available')}")
|
| 71 |
+
st.write(f"Right Primer (5'-3'): {primers.get(f'PRIMER_RIGHT_{i}_SEQUENCE', 'Not available')}")
|
| 72 |
+
st.write(f"Left Primer Tm: {primers.get(f'PRIMER_LEFT_{i}_TM', 'Not available')}")
|
| 73 |
+
st.write(f"Right Primer Tm: {primers.get(f'PRIMER_RIGHT_{i}_TM', 'Not available')}")
|
| 74 |
+
except Exception as e:
|
| 75 |
+
st.error(f"An error occurred while designing primers: {e}")
|
| 76 |
else:
|
| 77 |
+
st.error('Please upload a valid FASTA file.')
|