gene-fetch 1.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Dan Parsons
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.3
2
+ Name: gene-fetch
3
+ Version: 1.0.6
4
+ Summary: Gene Fetch: High-throughput NCBI Sequence Retrieval Tool
5
+ License: MIT
6
+ Keywords: bioinformatics,ncbi,sequence,genomics,taxonomy,barcodes
7
+ Author: D. Parsons
8
+ Author-email: d.parsons@nhm.ac.uk>, B. Price <b.price@nhm.ac.uk
9
+ Requires-Python: >=3.9
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
20
+ Requires-Dist: biopython (>=1.80)
21
+ Requires-Dist: ratelimit (>=2.2.1)
22
+ Project-URL: Bug Tracker, https://github.com/bge-barcoding/gene_fetch/issues
23
+ Project-URL: Homepage, https://github.com/bge-barcoding/gene_fetch
24
+ Project-URL: Repository, https://github.com/bge-barcoding/gene_fetch
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Gene Fetch
28
+ Gene Fetch enables high-throughput retreival of sequence data from NCBI databases based on taxonomy IDs (taxids) or taxonomic heirarchies. It can retrieve both protein and/or nucleotide sequences for various genes, including protein-coding genes (e.g., cox1, cytb, rbcl, matk) and rRNA genes (e.g., 16S, 18S).
29
+
30
+ ## Installation:
31
+ Install from PyPI
32
+ ```bash
33
+ pip install gene-fetch
34
+ ```
35
+
36
+ ## Post-instllation testing:
37
+ - The Gene Fetch package includes comprehensive tests - Testing is divided into basic tests (which don't require external API access) and integration tests (which may require NCBI API credentials).
38
+ Install pytest:
39
+ ```bash
40
+ pip install pytest
41
+ ```
42
+ Run basic tests:
43
+ ```bash
44
+ pytest
45
+ ```
46
+ * This will take a few minutes to run 65 tests, consisting of 8 test modules (tests/test_*.py). You will get 1 warning regarding API credentials as these are not provided in the basic tests.
47
+
48
+ ## Usage:
49
+ ```bash
50
+ python gene_fetch.py -g/--gene <gene_name> --type <sequence_type> -i/--in <samples.csv> -o/--out <output_directory>
51
+ ```
52
+ `--h/--help`: Show help and exit.
53
+
54
+ ### Required arguments:
55
+ `-g/--gene`: Name of gene to search for in NCBI GenBank database (e.g., cox1/16s/rbcl).
56
+ `--type`: Sequence type to fetch; 'protein', 'nucleotide', or 'both' ('both' will initially search and fetch a protein sequence, and then fetches the corresponding nucleotide CDS for that protein sequence).
57
+ `-i/--in`: Path to input CSV file containing sample IDs and TaxIDs (see [Input](#input) section below).
58
+ `i2/--in2`: Path to alternative input CSV file containing sample IDs and taxonomic information for each sample (see [Input](#input) section below).
59
+ `o/--out`: Path to output directory. The directory will be created if it does not exist.
60
+ `e/--email` and `-k/--api-key`: Email address and associated API key for NCBI account. An NCBI account is required to run this tool (due to otherwise strict API limitations) - information on how to create an NCBI account and find your API key can be found [here](https://support.nlm.nih.gov/kbArticle/?pn=KA-05317).
61
+ ### Optional arguments:
62
+ `--protein-size`: Minimum protein sequence length filter. Applicable to mode 'batch' and 'single' search modes (default: 500).
63
+ `--nucleotide-size`: Minimum nucleotide sequence length filter. Applicable to mode 'batch' and 'single' search modes (default: 1500).
64
+ `s/--single`: Taxonomic ID for 'single' sequence search mode (`-i` and `-i2` are ignored when run with `-s` mode). 'single' mode will fetch all (or N if specifying `--max-sequences`) target gene or protein sequences on GenBank for a specific taxonomic ID.
65
+ `--max-sequences`: Maximum number of sequences to fetch for a specific taxonomic ID (only applies when run in 'single' mode).
66
+ `-b/--genbank`: Saves genbank (.gb) files for fetched nucleotide and/or protein sequences to `genbank/` (applies when run in 'batch' or 'single' mode).
67
+
68
+
69
+ ## Input:
70
+ **Example 'samples.csv' input file (-i/--in)**
71
+ | ID | taxid |
72
+ | --- | --- |
73
+ | sample-1 | 177658 |
74
+ | sample-2 | 177627 |
75
+ | sample-3 | 3084599 |
76
+
77
+ **Example 'samples_taxonomy.csv' input file (-i2/--in2)**
78
+ | ID | phylum | class | order | family | genus | species |
79
+ | --- | --- | --- | --- | --- | --- | --- |
80
+ | sample-1 | Arthropoda | Insecta | Diptera | Acroceridae | Astomella | |
81
+ | sample-2 | Arthropoda | Insecta | Hemiptera | Cicadellidae | Psammotettix | Psammotettix sabulicola |
82
+ | sample-3 | Arthropoda | Insecta | Trichoptera | Limnephilidae | Dicosmoecus | Dicosmoecus palatus |
83
+ * Leave blank if taxonomic information not known/needed
84
+
85
+
86
+ Authored by Dan Parsons and Ben Price @ NHMUK (2025).
87
+
@@ -0,0 +1,60 @@
1
+ # Gene Fetch
2
+ Gene Fetch enables high-throughput retreival of sequence data from NCBI databases based on taxonomy IDs (taxids) or taxonomic heirarchies. It can retrieve both protein and/or nucleotide sequences for various genes, including protein-coding genes (e.g., cox1, cytb, rbcl, matk) and rRNA genes (e.g., 16S, 18S).
3
+
4
+ ## Installation:
5
+ Install from PyPI
6
+ ```bash
7
+ pip install gene-fetch
8
+ ```
9
+
10
+ ## Post-instllation testing:
11
+ - The Gene Fetch package includes comprehensive tests - Testing is divided into basic tests (which don't require external API access) and integration tests (which may require NCBI API credentials).
12
+ Install pytest:
13
+ ```bash
14
+ pip install pytest
15
+ ```
16
+ Run basic tests:
17
+ ```bash
18
+ pytest
19
+ ```
20
+ * This will take a few minutes to run 65 tests, consisting of 8 test modules (tests/test_*.py). You will get 1 warning regarding API credentials as these are not provided in the basic tests.
21
+
22
+ ## Usage:
23
+ ```bash
24
+ python gene_fetch.py -g/--gene <gene_name> --type <sequence_type> -i/--in <samples.csv> -o/--out <output_directory>
25
+ ```
26
+ `--h/--help`: Show help and exit.
27
+
28
+ ### Required arguments:
29
+ `-g/--gene`: Name of gene to search for in NCBI GenBank database (e.g., cox1/16s/rbcl).
30
+ `--type`: Sequence type to fetch; 'protein', 'nucleotide', or 'both' ('both' will initially search and fetch a protein sequence, and then fetches the corresponding nucleotide CDS for that protein sequence).
31
+ `-i/--in`: Path to input CSV file containing sample IDs and TaxIDs (see [Input](#input) section below).
32
+ `i2/--in2`: Path to alternative input CSV file containing sample IDs and taxonomic information for each sample (see [Input](#input) section below).
33
+ `o/--out`: Path to output directory. The directory will be created if it does not exist.
34
+ `e/--email` and `-k/--api-key`: Email address and associated API key for NCBI account. An NCBI account is required to run this tool (due to otherwise strict API limitations) - information on how to create an NCBI account and find your API key can be found [here](https://support.nlm.nih.gov/kbArticle/?pn=KA-05317).
35
+ ### Optional arguments:
36
+ `--protein-size`: Minimum protein sequence length filter. Applicable to mode 'batch' and 'single' search modes (default: 500).
37
+ `--nucleotide-size`: Minimum nucleotide sequence length filter. Applicable to mode 'batch' and 'single' search modes (default: 1500).
38
+ `s/--single`: Taxonomic ID for 'single' sequence search mode (`-i` and `-i2` are ignored when run with `-s` mode). 'single' mode will fetch all (or N if specifying `--max-sequences`) target gene or protein sequences on GenBank for a specific taxonomic ID.
39
+ `--max-sequences`: Maximum number of sequences to fetch for a specific taxonomic ID (only applies when run in 'single' mode).
40
+ `-b/--genbank`: Saves genbank (.gb) files for fetched nucleotide and/or protein sequences to `genbank/` (applies when run in 'batch' or 'single' mode).
41
+
42
+
43
+ ## Input:
44
+ **Example 'samples.csv' input file (-i/--in)**
45
+ | ID | taxid |
46
+ | --- | --- |
47
+ | sample-1 | 177658 |
48
+ | sample-2 | 177627 |
49
+ | sample-3 | 3084599 |
50
+
51
+ **Example 'samples_taxonomy.csv' input file (-i2/--in2)**
52
+ | ID | phylum | class | order | family | genus | species |
53
+ | --- | --- | --- | --- | --- | --- | --- |
54
+ | sample-1 | Arthropoda | Insecta | Diptera | Acroceridae | Astomella | |
55
+ | sample-2 | Arthropoda | Insecta | Hemiptera | Cicadellidae | Psammotettix | Psammotettix sabulicola |
56
+ | sample-3 | Arthropoda | Insecta | Trichoptera | Limnephilidae | Dicosmoecus | Dicosmoecus palatus |
57
+ * Leave blank if taxonomic information not known/needed
58
+
59
+
60
+ Authored by Dan Parsons and Ben Price @ NHMUK (2025).
@@ -0,0 +1,45 @@
1
+ [tool.poetry]
2
+ name = "gene-fetch"
3
+ version = "1.0.6"
4
+ description = "Gene Fetch: High-throughput NCBI Sequence Retrieval Tool"
5
+ authors = ["D. Parsons <d.parsons@nhm.ac.uk>, B. Price <b.price@nhm.ac.uk>"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ packages = [{include = "gene_fetch", from = "src"}]
9
+ include = ["tests/*"]
10
+ repository = "https://github.com/bge-barcoding/gene_fetch"
11
+ keywords = ["bioinformatics", "ncbi", "sequence", "genomics", "taxonomy", "barcodes"]
12
+ classifiers = [
13
+ "Development Status :: 5 - Production/Stable",
14
+ "Intended Audience :: Science/Research",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.9",
18
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
19
+ ]
20
+
21
+ [tool.poetry.dependencies]
22
+ python = ">=3.9"
23
+ biopython = ">=1.80"
24
+ ratelimit = ">=2.2.1"
25
+
26
+ [tool.poetry.group.dev.dependencies]
27
+ pytest = "^7.0"
28
+ black = "^23.0"
29
+ flake8 = "^6.0"
30
+ pytest-cov = "^6.1.1"
31
+
32
+ [build-system]
33
+ requires = ["poetry-core>=1.0.0"]
34
+ build-backend = "poetry.core.masonry.api"
35
+
36
+ [tool.pytest.ini_options]
37
+ testpaths = ["tests"]
38
+ python_files = "test_*.py"
39
+
40
+ [tool.poetry.scripts]
41
+ gene-fetch = "gene_fetch.main:main"
42
+
43
+ [tool.poetry.urls]
44
+ "Homepage" = "https://github.com/bge-barcoding/gene_fetch"
45
+ "Bug Tracker" = "https://github.com/bge-barcoding/gene_fetch/issues"
@@ -0,0 +1,16 @@
1
+ """
2
+ Gene Fetch - NCBI Sequence Retrieval Tool
3
+
4
+ This package fetches sequence data from NCBI databases
5
+ using sample taxonomic information.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+
10
+ from .core import Config
11
+ from .entrez_handler import EntrezHandler
12
+ from .sequence_processor import SequenceProcessor
13
+ from .output_manager import OutputManager, save_genbank_file
14
+
15
+ # Expose main entry point for usage
16
+ from .main import main
@@ -0,0 +1,410 @@
1
+ # src/gene_fetch/core.py
2
+ """
3
+ Core functionality for Gene Fetch.
4
+ Contains Config class and basic utility functions.
5
+ """
6
+
7
+ import logging
8
+ import sys
9
+ from dataclasses import dataclass
10
+ from pathlib import Path
11
+ from typing import Optional, Set, Dict, List, Any, FrozenSet
12
+
13
+ logger = logging.getLogger("gene_fetch")
14
+
15
+ def make_out_dir(path: Path) -> None:
16
+ """Ensure output directory exists and create if it doesn't."""
17
+ path.mkdir(parents=True, exist_ok=True)
18
+
19
+ def setup_logging(output_dir: Path) -> logging.Logger:
20
+ """Setup logging with both file and console handlers."""
21
+ make_out_dir(output_dir)
22
+
23
+ # Clear existing handlers
24
+ logger.handlers.clear()
25
+ logger.setLevel(logging.INFO)
26
+
27
+ formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
28
+
29
+ console_handler = logging.StreamHandler(sys.stdout)
30
+ console_handler.setFormatter(formatter)
31
+ logger.addHandler(console_handler)
32
+
33
+ log_path = output_dir / "gene_fetch.log"
34
+ file_handler = logging.FileHandler(log_path)
35
+ file_handler.setFormatter(formatter)
36
+ logger.addHandler(file_handler)
37
+
38
+ logger.info(f"Logging initialised. Log file: {log_path}")
39
+ return logger
40
+
41
+ def log_progress(current: int, total: int, interval: int = 10) -> None:
42
+ """Log progress at specified intervals."""
43
+ if current == 0:
44
+ logger.info("")
45
+ logger.info(f"Starting processing: 0/{total} samples processed (0%)")
46
+ elif current == total:
47
+ logger.info(f"Processed: {total}/{total} samples processed (100%)")
48
+ elif current % interval == 0:
49
+ percentage = (current / total) * 100
50
+ logger.info(
51
+ f"===== Progress: {current}/{total} samples processed "
52
+ f"({percentage:.2f}%)"
53
+ )
54
+
55
+ def get_process_id_column(header):
56
+ """Identify the ID column from possible variations."""
57
+ # Print what's in the header
58
+ logger.info("")
59
+ logger.info(f"CSV header detected: {header}")
60
+
61
+ valid_names = [
62
+ "ID",
63
+ "process_id",
64
+ "Process ID",
65
+ "process id",
66
+ "Process id",
67
+ "PROCESS ID",
68
+ "sample",
69
+ "SAMPLE",
70
+ "Sample",
71
+ ]
72
+
73
+ # Print repr of each header item to see any hidden chars
74
+ for i, col in enumerate(header):
75
+ logger.info(f"Header column {i}: {repr(col)}")
76
+
77
+ # Try direct comparison first
78
+ for col in header:
79
+ if col in valid_names:
80
+ logger.info(f"Found matching column: {col}")
81
+ return col
82
+
83
+ # Try trimming whitespace (in case of spaces)
84
+ for col in header:
85
+ trimmed = col.strip()
86
+ if trimmed in valid_names:
87
+ logger.info(f"Found matching column after trimming: {trimmed}")
88
+ return col
89
+
90
+ # Try case-insensitive comparison as last attempt
91
+ for col in header:
92
+ if col.upper() in [name.upper() for name in valid_names]:
93
+ logger.info(f"Found matching column case-insensitive: {col}")
94
+ return col
95
+
96
+ logger.error(f"No matching column found in {header}")
97
+ return None
98
+
99
+
100
+ # =============================================================================
101
+ # Configuration
102
+ # =============================================================================
103
+ @dataclass
104
+ class Config:
105
+ """Configuration class for Gene Fetch, containing all runtime settings."""
106
+ def __init__(self, email, api_key):
107
+ # Email and API key required
108
+ if not email:
109
+ raise ValueError(
110
+ "Email address required for NCBI API requests. Use -e/--email "
111
+ "to provide your email."
112
+ )
113
+ if not api_key:
114
+ raise ValueError(
115
+ "API key required for NCBI API requests. Use -k/--api-key "
116
+ "to provide your API key."
117
+ )
118
+
119
+
120
+ # Set run parameters
121
+ self.email = email
122
+ self.api_key = api_key
123
+
124
+ # With an API key, 10 requests per second can be made
125
+ self.max_calls_per_second = 10
126
+
127
+ # Default batch size for fetching sequences
128
+ self.fetch_batch_size = 200
129
+
130
+ # Delay between batches (seconds) - uniform random delay between 1-2 seconds
131
+ self.batch_delay = (1, 2)
132
+
133
+ # Set search 'type'
134
+ self.valid_sequence_types = frozenset({"protein", "nucleotide", "both"})
135
+
136
+ # Minimum nucleotide and protein lengths for 'batch' mode
137
+ self.protein_length_threshold = 500
138
+ self.nucleotide_length_threshold = 1000
139
+
140
+ # Minimum nucleotide and protein lengths for 'single' mode
141
+ self.min_nucleotide_size_single_mode = 200
142
+ self.min_protein_size_single_mode = 100
143
+
144
+ self.gene_search_term = ""
145
+
146
+ # Define gene type categories
147
+ self._rRNA_genes = {
148
+ "16s": [
149
+ "16S ribosomal RNA[Gene]",
150
+ "16S rRNA[Gene]",
151
+ "rrs[Gene]",
152
+ "rrn16[Gene]",
153
+ "16S ribosomal RNA[Title] NOT methylase[Title] NOT "
154
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
155
+ "synthase[Title]",
156
+ "16S rRNA[Title] NOT methylase[Title] NOT "
157
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
158
+ "synthase[Title]",
159
+ "16S[Title] NOT methylase[Title] NOT methyltransferase[Title] "
160
+ "NOT pseudouridylate[Title] NOT synthase[Title]",
161
+ "16S ribosomal RNA[All Fields]",
162
+ "rrs[All Fields]",
163
+ "rrn16[All Fields]",
164
+ ],
165
+ "18s": [
166
+ "18S ribosomal RNA[Gene]",
167
+ "18S rRNA[Gene]",
168
+ "rrn18[Gene]",
169
+ "SSU rRNA[Gene]",
170
+ "18S ribosomal RNA[Title] NOT methylase[Title] NOT "
171
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
172
+ "synthase[Title]",
173
+ "18S rRNA[Title] NOT methylase[Title] NOT "
174
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
175
+ "synthase[Title]",
176
+ "18S[Title] NOT methylase[Title] NOT methyltransferase[Title] "
177
+ "NOT pseudouridylate[Title] NOT synthase[Title]",
178
+ "18S ribosomal RNA[rRNA]",
179
+ "SSU rRNA[rRNA]",
180
+ "rrn18[rRNA]",
181
+ ],
182
+ "23s": [
183
+ "23S ribosomal RNA[Gene]",
184
+ "23S rRNA[Gene]",
185
+ "rrl[Gene]",
186
+ "rrn23[Gene]",
187
+ "23S ribosomal RNA[Title] NOT methylase[Title] NOT "
188
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
189
+ "synthase[Title]",
190
+ "23S rRNA[Title] NOT methylase[Title] NOT "
191
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
192
+ "synthase[Title]",
193
+ "23S[Title] NOT methylase[Title] NOT methyltransferase[Title] "
194
+ "NOT pseudouridylate[Title] NOT synthase[Title]",
195
+ "23S ribosomal RNA[rRNA]",
196
+ "rrl[rRNA]",
197
+ "rrn23[rRNA]",
198
+ ],
199
+ "28s": [
200
+ "28S ribosomal RNA[Gene]",
201
+ "28S rRNA[Gene]",
202
+ "rrn28[Gene]",
203
+ "LSU rRNA[Gene]",
204
+ "28S ribosomal RNA[Title] NOT methylase[Title] NOT "
205
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
206
+ "synthase[Title]",
207
+ "28S rRNA[Title] NOT methylase[Title] NOT "
208
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
209
+ "synthase[Title]",
210
+ "28S[Title] NOT methylase[Title] NOT methyltransferase[Title] "
211
+ "NOT pseudouridylate[Title] NOT synthase[Title]",
212
+ "28S ribosomal RNA[rRNA]",
213
+ "LSU rRNA[rRNA]",
214
+ "rrn28[rRNA]",
215
+ ],
216
+ "12s": [
217
+ "12S ribosomal RNA[Gene]",
218
+ "12S rRNA[Gene]",
219
+ "mt-rrn1[Gene]",
220
+ "mt 12S rRNA[Gene]",
221
+ "12S ribosomal RNA[Title] NOT methylase[Title] NOT "
222
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
223
+ "synthase[Title]",
224
+ "12S rRNA[Title] NOT methylase[Title] NOT "
225
+ "methyltransferase[Title] NOT pseudouridylate[Title] NOT "
226
+ "synthase[Title]",
227
+ "12S[Title] NOT methylase[Title] NOT methyltransferase[Title] "
228
+ "NOT pseudouridylate[Title] NOT synthase[Title]",
229
+ "12S ribosomal RNA[rRNA]",
230
+ "mt-rrn1[rRNA]",
231
+ "mt 12S rRNA[rRNA]",
232
+ ],
233
+ "its1": [
234
+ "ITS1[Title]",
235
+ "internal transcribed spacer 1[Title]",
236
+ "ITS-1[Title]",
237
+ "ITS 1[Title]",
238
+ "ITS1 ribosomal DNA[Title]",
239
+ "ITS1 rDNA[Title]",
240
+ ],
241
+ "its2": [
242
+ "ITS2[Title]",
243
+ "internal transcribed spacer 2[Title]",
244
+ "ITS-2[Title]",
245
+ "ITS 2[Title]",
246
+ "ITS2 ribosomal DNA[Title]",
247
+ "ITS2 rDNA[Title]",
248
+ ],
249
+ "its": [
250
+ "ITS[Title]",
251
+ "internal transcribed spacer[Title]",
252
+ "ITS region[Title]",
253
+ "ITS1-5.8S-ITS2[Title]",
254
+ "ribosomal ITS[Title]",
255
+ "rDNA ITS[Title]",
256
+ ],
257
+ "trnl": [
258
+ "trnL[Title]",
259
+ "trnL gene[Title]",
260
+ "tRNA-Leu[Title]",
261
+ "tRNA-Leucine[Title]",
262
+ "trnL-trnF[Title]",
263
+ "trnL-F[Title]",
264
+ "chloroplast trnL[Title]",
265
+ "cp trnL[Title]",
266
+ "trnL intron[Title]",
267
+ "trnL-UAA[Title]",
268
+ '"trnL gene"[Gene]',
269
+ ],
270
+ }
271
+
272
+ self._protein_coding_genes = {
273
+ "cox1": [
274
+ "cox1[Gene]",
275
+ "COI[Gene]",
276
+ '"cytochrome c oxidase subunit 1"[Protein Name]',
277
+ '"cytochrome oxidase subunit 1"[Protein Name]',
278
+ '"cytochrome c oxidase subunit I"[Protein Name]',
279
+ '"COX1"[Protein Name]',
280
+ '"COXI"[Protein Name]',
281
+ ],
282
+ "cox2": [
283
+ "cox2[Gene]",
284
+ "COII[Gene]",
285
+ '"cytochrome c oxidase subunit 2"[Protein Name]',
286
+ '"cytochrome oxidase subunit 2"[Protein Name]',
287
+ '"cytochrome c oxidase subunit II"[Protein Name]',
288
+ '"COX2"[Protein Name]',
289
+ '"COXII"[Protein Name]',
290
+ ],
291
+ "cox3": [
292
+ "cox3[Gene]",
293
+ "COIII[Gene]",
294
+ '"cytochrome c oxidase subunit 3"[Protein Name]',
295
+ '"cytochrome oxidase subunit 3"[Protein Name]',
296
+ '"cytochrome c oxidase subunit III"[Protein Name]',
297
+ '"COX3"[Protein Name]',
298
+ '"COXIII"[Protein Name]',
299
+ ],
300
+ "cytb": [
301
+ "cytb[Gene]",
302
+ "cob[Gene]",
303
+ '"cytochrome b"[Protein Name]',
304
+ '"cytochrome b"[Gene]',
305
+ '"CYTB"[Protein Name]',
306
+ ],
307
+ "nd1": [
308
+ "nd1[Gene]",
309
+ "NAD1[Gene]",
310
+ '"NADH dehydrogenase subunit 1"[Protein Name]',
311
+ '"ND1"[Protein Name]',
312
+ ],
313
+ "nd2": [
314
+ "nd2[Gene]",
315
+ "NAD2[Gene]",
316
+ '"NADH dehydrogenase subunit 2"[Protein Name]',
317
+ '"ND2"[Protein Name]',
318
+ ],
319
+ "rbcl": [
320
+ "rbcL[Gene]",
321
+ "RBCL[Gene]",
322
+ '"ribulose-1,5-bisphosphate carboxylase/oxygenase large '
323
+ 'subunit"[Protein Name]',
324
+ '"ribulose 1,5-bisphosphate carboxylase/oxygenase large '
325
+ 'subunit"[Protein Name]',
326
+ '"ribulose bisphosphate carboxylase large chain"[Protein Name]',
327
+ '"RuBisCO large subunit"[Protein Name]',
328
+ '"ribulose-1,5-bisphosphate carboxylase/oxygenase small '
329
+ 'subunit"[Protein Name]',
330
+ '"ribulose 1,5-bisphosphate carboxylase/oxygenase small '
331
+ 'subunit"[Protein Name]',
332
+ '"ribulose-1,5-bisphosphate carboxylase/oxygenase small '
333
+ 'chain"[Protein Name]',
334
+ '"RuBisCO small subunit"[Protein Name]',
335
+ '"Ribulose bisphosphate carboxylase/oxygenase ' 'activase"[Gene]',
336
+ '"rbcL gene"[Gene]',
337
+ '"RBCL gene"[Gene]',
338
+ "rbcL[Title]",
339
+ "RBCL[Title]",
340
+ ],
341
+ "matk": [
342
+ "matK[Gene]",
343
+ "MATK[Gene]",
344
+ '"maturase K"[Protein Name]',
345
+ '"maturase K"[Gene]',
346
+ '"maturase-K"[Protein Name]',
347
+ '"maturase-K"[Gene]',
348
+ '"Maturase K"[Protein Name]',
349
+ '"Maturase K"[Gene]',
350
+ '"matK gene"[Gene]',
351
+ '"MATK gene"[Gene]',
352
+ '"trnK-matK"[Gene]',
353
+ '"maturase type II intron splicing factor"[Protein Name]',
354
+ '"chloroplast group II intron splicing factor maturase '
355
+ 'K"[Protein Name]',
356
+ '"type II intron maturase K"[Protein Name]',
357
+ '"tRNA-lysine maturase K"[Protein Name]',
358
+ ],
359
+ "psba": [
360
+ "psbA[Gene]",
361
+ "PSBA[Gene]",
362
+ '"photosystem II protein D1"[Protein Name]',
363
+ '"photosystem II protein D1"[Gene]',
364
+ '"PSII D1 protein"[Protein Name]',
365
+ '"PSII D1 protein"[Gene]',
366
+ '"photosystem II reaction center protein D1"[Protein Name]',
367
+ '"photosystem II reaction center protein D1"[Gene]',
368
+ '"photosystem Q(B) protein"[Protein Name]',
369
+ '"32 kDa thylakoid membrane protein"[Protein Name]',
370
+ '"psbA gene"[Gene]',
371
+ '"PSBA gene"[Gene]',
372
+ "psbA[Title]",
373
+ "PSBA[Title]",
374
+ '"trnH-psbA"[Title]',
375
+ '"psbA-trnH"[Title]',
376
+ ],
377
+ }
378
+
379
+ # Update sequence length thresholds
380
+ def update_thresholds(self, protein_size: int, nucleotide_size: int):
381
+ """Update the sequence length thresholds."""
382
+ self.protein_length_threshold = protein_size
383
+ self.nucleotide_length_threshold = nucleotide_size
384
+
385
+ # Set search term based on gene name and type
386
+ def set_gene_search_term(self, gene_name: str) -> str:
387
+ """Set the gene search term based on the gene name and type."""
388
+ gene_name = gene_name.lower()
389
+
390
+ # Check if rRNA
391
+ if gene_name in self._rRNA_genes:
392
+ self.gene_search_term = "(" + " OR ".join(self._rRNA_genes[gene_name]) + ")"
393
+ search_type = "rRNA"
394
+
395
+ # Check if protein-coding
396
+ elif gene_name in self._protein_coding_genes:
397
+ self.gene_search_term = (
398
+ "(" + " OR ".join(self._protein_coding_genes[gene_name]) + ")"
399
+ )
400
+ search_type = "protein-coding"
401
+
402
+ else:
403
+ # Generic search term for non-listed genes
404
+ self.gene_search_term = (
405
+ f"({gene_name}[Title] OR {gene_name}[Gene] OR "
406
+ f'"{gene_name}"[Text Word])'
407
+ )
408
+ search_type = "generic"
409
+
410
+ return search_type # Return the type for logging purposes