yashm commited on
Commit
784e4aa
·
verified ·
1 Parent(s): 626ac91

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -51
app.py CHANGED
@@ -1,63 +1,84 @@
1
  import streamlit as st
2
- import primer3
3
  from Bio import SeqIO
4
- from io import StringIO
5
-
6
- # Streamlit app layout
7
- st.title('PCR Primer Design Tool')
8
- st.write('Upload a FASTA file with your DNA sequence and specify the desired product size range for PCR primer design.')
9
 
10
- # User inputs
11
- fasta_file = st.file_uploader("Upload DNA sequence (FASTA format):", type=['fasta', 'fa'])
12
- product_size_range = st.text_input("Product Size Range (format: min-max, e.g. 150-250):", value="150-250")
13
 
14
- if st.button('Design Primers'):
15
- if fasta_file and product_size_range:
16
- # Read the sequence from the FASTA file
17
- sequence_data = StringIO(fasta_file.getvalue().decode("utf-8"))
18
- record = next(SeqIO.parse(sequence_data, "fasta"))
19
- sequence = str(record.seq).upper() # Ensure sequence is uppercase
20
 
21
- # Convert product size range from string to list of tuples
22
- size_range = [tuple(map(int, range_pair.split('-'))) for range_pair in product_size_range.split(',')]
 
 
 
 
23
 
24
- # Set basic primer design parameters (based on defaults provided)
25
- primer_params = {
26
- 'PRIMER_TASK': 'generic',
 
 
 
 
 
 
 
 
 
27
  'PRIMER_OPT_SIZE': 20,
28
  'PRIMER_MIN_SIZE': 18,
29
  'PRIMER_MAX_SIZE': 23,
 
30
  'PRIMER_MIN_TM': 57.0,
31
- 'PRIMER_OPT_TM': 59.0,
32
- 'PRIMER_MAX_TM': 62.0,
33
- 'PRIMER_MIN_GC': 30.0,
34
- 'PRIMER_OPT_GC_PERCENT': 50.0,
35
- 'PRIMER_MAX_GC': 70.0,
36
- 'PRIMER_MAX_POLY_X': 4,
37
- 'PRIMER_SALT_MONOVALENT': 50.0,
38
- 'PRIMER_SALT_DIVALENT': 1.5,
39
- 'PRIMER_DNTP_CONC': 0.6,
40
- 'PRIMER_NUM_RETURN': 5,
41
- 'PRIMER_PRODUCT_SIZE_RANGE': size_range
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- # Design primers using Primer3
45
- try:
46
- primers = primer3.bindings.designPrimers(
47
- {'SEQUENCE_ID': record.id, 'SEQUENCE_TEMPLATE': sequence},
48
- primer_params
49
- )
50
-
51
- # Display the results
52
- st.subheader('Designed Primers:')
53
- for i in range(primer_params['PRIMER_NUM_RETURN']):
54
- st.write(f"Primer Pair {i+1}:")
55
- st.write(f"Left Primer (5'-3'): {primers.get(f'PRIMER_LEFT_{i}_SEQUENCE', 'Not available')}")
56
- st.write(f"Right Primer (5'-3'): {primers.get(f'PRIMER_RIGHT_{i}_SEQUENCE', 'Not available')}")
57
- st.write(f"Left Primer Tm: {primers.get(f'PRIMER_LEFT_{i}_TM', 'Not available')}")
58
- st.write(f"Right Primer Tm: {primers.get(f'PRIMER_RIGHT_{i}_TM', 'Not available')}")
59
- st.write(f"Product Size: {primers.get(f'PRIMER_PAIR_{i}_PRODUCT_SIZE', 'Not available')}")
60
- except Exception as e:
61
- st.error(f"An error occurred while designing primers: {e}")
62
- else:
63
- st.error('Please upload a valid FASTA file and specify a product size range.')
 
1
  import streamlit as st
2
+ import pandas as pd
3
  from Bio import SeqIO
4
+ from Bio.SeqFeature import SeqFeature, FeatureLocation
5
+ import primer3
6
+ import os
7
+ from collections import Counter
 
8
 
9
+ # Ensure the 'temp' directory exists for saving temporary files
10
+ temp_dir = "temp"
11
+ os.makedirs(temp_dir, exist_ok=True)
12
 
13
+ # Streamlit UI setup
14
+ st.set_page_config(page_title="PCR Primer Design", page_icon="🧬", layout="wide")
15
+ uploaded_file = st.file_uploader("Upload a GenBank file", type=['gb', 'gbk'])
 
 
 
16
 
17
+ def extract_features(genbank_path, feature_type='CDS'):
18
+ """Extracts features from a GenBank file."""
19
+ with open(genbank_path, 'r') as file:
20
+ record = SeqIO.read(file, "genbank")
21
+ features = [feature for feature in record.features if feature.type == feature_type]
22
+ return features, record
23
 
24
+ def design_primers_for_feature(feature, sequence, num_to_return=5):
25
+ """Design primers for a specific feature."""
26
+ start, end = int(feature.location.start), int(feature.location.end)
27
+ sequence_template = str(sequence)
28
+ target = [start, end - start]
29
+ primer_design_results = primer3.bindings.designPrimers(
30
+ {
31
+ 'SEQUENCE_ID': feature.qualifiers.get('gene', [''])[0],
32
+ 'SEQUENCE_TEMPLATE': sequence_template,
33
+ 'SEQUENCE_TARGET': target,
34
+ },
35
+ {
36
  'PRIMER_OPT_SIZE': 20,
37
  'PRIMER_MIN_SIZE': 18,
38
  'PRIMER_MAX_SIZE': 23,
39
+ 'PRIMER_OPT_TM': 60.0,
40
  'PRIMER_MIN_TM': 57.0,
41
+ 'PRIMER_MAX_TM': 63.0,
42
+ 'PRIMER_MIN_GC': 20.0,
43
+ 'PRIMER_MAX_GC': 80.0,
44
+ 'PRIMER_NUM_RETURN': num_to_return,
 
 
 
 
 
 
 
45
  }
46
+ )
47
+ return primer_design_results
48
+
49
+ if uploaded_file is not None:
50
+ temp_gb_path = os.path.join(temp_dir, uploaded_file.name)
51
+ with open(temp_gb_path, 'wb') as f:
52
+ f.write(uploaded_file.getvalue())
53
+
54
+ features, record = extract_features(temp_gb_path)
55
+ gene_names = [feature.qualifiers.get('gene', ['N/A'])[0] for feature in features]
56
+ selected_gene = st.selectbox('Select a gene to design primers for:', gene_names)
57
+
58
+ if st.button('Design Primers'):
59
+ selected_feature = next(feature for feature in features if feature.qualifiers.get('gene', [''])[0] == selected_gene)
60
+ primers = design_primers_for_feature(selected_feature, record.seq)
61
+ primer_df = pd.DataFrame({
62
+ 'Primer': ['Left Primer', 'Right Primer'] * len(primers) // 2,
63
+ 'Sequence': [primers[f'PRIMER_LEFT_{i}_SEQUENCE'] for i in range(len(primers) // 2)] +
64
+ [primers[f'PRIMER_RIGHT_{i}_SEQUENCE'] for i in range(len(primers) // 2)],
65
+ 'Tm (°C)': [primers[f'PRIMER_LEFT_{i}_TM'] for i in range(len(primers) // 2)] +
66
+ [primers[f'PRIMER_RIGHT_{i}_TM'] for i in range(len(primers) // 2)],
67
+ 'Length': [primers[f'PRIMER_LEFT_{i}_SIZE'] for i in range(len(primers) // 2)] +
68
+ [primers[f'PRIMER_RIGHT_{i}_SIZE'] for i in range(len(primers) // 2)],
69
+ 'GC%': [primers[f'PRIMER_LEFT_{i}_GC_PERCENT'] for i in range(len(primers) // 2)] +
70
+ [primers[f'PRIMER_RIGHT_{i}_GC_PERCENT'] for i in range(len(primers) // 2)],
71
+ })
72
 
73
+ st.write('### Designed Primers')
74
+ st.dataframe(primer_df)
75
+ csv = primer_df.to_csv(index=False).encode('utf-8')
76
+ st.download_button(
77
+ "Download Primers as CSV",
78
+ csv,
79
+ "primers.csv",
80
+ "text/csv",
81
+ key='download-csv'
82
+ )
83
+ else:
84
+ st.warning("Please upload a GenBank file.")