File size: 6,323 Bytes
b0f8787
784e4aa
 
1a77f6d
784e4aa
d3184b9
b0f8787
017a644
784e4aa
 
 
b0f8787
784e4aa
 
4cc12fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b0f8787
f36f859
 
 
 
 
 
 
 
 
 
 
 
626ac91
3e07321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784e4aa
 
23cbe89
 
4cc12fd
 
 
 
 
 
 
1a77f6d
4cc12fd
 
 
 
 
 
 
 
 
1a77f6d
4cc12fd
 
 
784e4aa
4cc12fd
 
 
 
 
 
 
 
 
 
 
467d1e3
4cc12fd
 
 
f36f859
4cc12fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b0f8787
4cc12fd
 
 
 
f36f859
4cc12fd
 
 
 
 
 
 
 
 
 
bd3f684
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import streamlit as st
import pandas as pd
import primer3
from Bio import SeqIO
import os
from io import StringIO


# Ensure the 'temp' directory exists for saving temporary files
temp_dir = "temp"
os.makedirs(temp_dir, exist_ok=True)

# Streamlit UI setup
st.set_page_config(page_title="PCR Primer Design", page_icon="🧬", layout="wide")

# User Documentation
st.sidebar.header("User Guide")
st.sidebar.info(
    """
    This application allows you to design PCR primers for specific features within a GenBank file. 
    Follow these steps:
    1. Upload a GenBank file.
    2. Select a feature type and then a specific feature.
    3. Enter the desired PCR product size range and the minimum number of primer pairs.
    4. Click 'Design Primers' to generate your primers.
    """
)

# File uploader with additional help
uploaded_file = st.file_uploader(
    "Upload a GenBank file", 
    type=['gb', 'gbk'],
    help="Upload a GenBank (.gb or .gbk) file containing the DNA sequence from which to design primers."
)

# Custom CSS for styling
st.markdown("""
<style>
h1, h2, h3 {
    color: #1f77b4;
    font-weight: bold;
}
.stProgress {
    margin-top: 20px;
}
</style>
""", unsafe_allow_html=True)

def extract_features_from_genbank(genbank_content, feature_types=['CDS', 'tRNA', 'gene']):
    """Extracts specified features from GenBank content."""
    text_stream = StringIO(genbank_content.decode("utf-8")) if isinstance(genbank_content, bytes) else genbank_content
    record = SeqIO.read(text_stream, "genbank")
    features = {ftype: [] for ftype in feature_types}
    for feature in record.features:
        if feature.type in feature_types:
            features[feature.type].append(feature)
    return features, record

def design_primers_for_region(sequence, product_size_range, num_to_return=10):
    """Design primers for a specific sequence."""
    size_min, size_max = map(int, product_size_range.split('-'))
    return primer3.bindings.designPrimers(
        {
            'SEQUENCE_TEMPLATE': str(sequence),
            'PRIMER_PRODUCT_SIZE_RANGE': [[size_min, size_max]]
        },
        {
            'PRIMER_OPT_SIZE': 20,
            'PRIMER_MIN_SIZE': 18,
            'PRIMER_MAX_SIZE': 23,
            'PRIMER_OPT_TM': 60.0,
            'PRIMER_MIN_TM': 57.0,
            'PRIMER_MAX_TM': 63.0,
            'PRIMER_MIN_GC': 20.0,
            'PRIMER_MAX_GC': 80.0,
            'PRIMER_NUM_RETURN': num_to_return,
        }
    )

if uploaded_file is not None:
    genbank_content = StringIO(uploaded_file.getvalue().decode("utf-8"))
    features, record = extract_features_from_genbank(genbank_content)
    
    st.write("## Feature Selection")
    feature_type = st.selectbox(
        'Select feature type:', 
        ['CDS', 'tRNA', 'gene'],
        help="Choose the type of genomic feature for which you want to design primers."
    )

    if features[feature_type]:
        feature_options = [f"{feature.qualifiers.get('gene', [''])[0]} ({feature.location})" for feature in features[feature_type]]
        selected_index = st.selectbox(
            f'Select a {feature_type}:', 
            options=range(len(feature_options)), 
            format_func=lambda x: feature_options[x],
            help="Select a specific feature based on its gene name and location."
        )
        selected_feature = features[feature_type][selected_index]

        feature_sequence = selected_feature.extract(record.seq)
        st.write(f"Selected {feature_type} sequence (length: {len(feature_sequence)} bp):")
        st.code(str(feature_sequence), language="text")  # Display sequence in code format

        st.write("## Primer Design Parameters")
        product_size_range = st.text_input(
            "Enter desired PCR product size range (e.g., 150-500):", 
            value="150-500",
            help="Specify the range of the desired PCR product size in base pairs (e.g., 150-500)."
        )
        min_num_primers = st.number_input(
            "Enter minimum number of primer pairs to return:", 
            min_value=5, value=5, step=1,
            help="Determine the minimum number of primer pairs to generate."
        )

        if st.button(f'Design Primers for selected {feature_type}'):
            with st.spinner('Designing primers...'):  # Show a spinner while primers are being designed
                primers = design_primers_for_region(feature_sequence, product_size_range, num_to_return=min_num_primers)

            primer_data = []
            for i in range(min_num_primers):
                left_sequence = primers.get(f'PRIMER_LEFT_{i}_SEQUENCE', 'N/A')
                right_sequence = primers.get(f'PRIMER_RIGHT_{i}_SEQUENCE', 'N/A')
                if left_sequence != 'N/A' and right_sequence != 'N/A':
                    primer_info = {
                        'Primer Pair': i + 1,
                        'Left Sequence': left_sequence,
                        'Right Sequence': right_sequence,
                        'Left TM (°C)': primers.get(f'PRIMER_LEFT_{i}_TM', 'N/A'),
                        'Right TM (°C)': primers.get(f'PRIMER_RIGHT_{i}_TM', 'N/A'),
                        'Left Length': len(left_sequence),
                        'Right Length': len(right_sequence),
                        'PCR Product Size (bp)': primers.get(f'PRIMER_PAIR_{i}_PRODUCT_SIZE', 'N/A')
                    }
                    primer_data.append(primer_info)

            if primer_data:
                st.subheader('Designed Primers')
                primer_df = pd.DataFrame(primer_data)
                st.table(primer_df)  # Use st.table to display the primer data

                csv = primer_df.to_csv(index=False).encode('utf-8')
                st.download_button(
                    "Download Primers as CSV",
                    csv,
                    "primers.csv",
                    "text/csv",
                    key='download-csv'
                )
            else:
                st.error('No primers were found. Please adjust your parameters and try again.')


# Add copyright information section at the end of the main page
st.markdown("""
---
**Copyright Notice**: © 2024 Yash Munnalal Gupta. All rights reserved.

For inquiries or permissions, contact: [yash.610@live.com](mailto:yash.610@live.com)
""", unsafe_allow_html=True)