From 5d20f2140bd2fe98440fe8a0b43b85cd9510382a Mon Sep 17 00:00:00 2001 From: ssnn-airr Date: Fri, 13 Mar 2026 13:23:41 +0100 Subject: [PATCH] default ref databases tried will be airrc-imgt then imgt --- bin/AssignGenes.py | 26 +++++++++------- changeo/Applications.py | 66 ++++++++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/bin/AssignGenes.py b/bin/AssignGenes.py index 9b0218c..ab67b2a 100755 --- a/bin/AssignGenes.py +++ b/bin/AssignGenes.py @@ -201,21 +201,24 @@ def getArgParser(): choices=choices_loci, help='The receptor type.') group_igblast.add_argument('--vdb', action='store', dest='vdb', default=None, help='''Name of the custom V reference in the IgBLAST database folder. - If not specified, then a default database name with the form - imgt___v will be used.''') + If not specified, the database folder is searched for a file + matching airrc-imgt___v first, then imgt___v. + If neither is found, --vdb must be specified explicitly.''') group_igblast.add_argument('--ddb', action='store', dest='ddb', default=None, help='''Name of the custom D reference in the IgBLAST database folder. - If not specified, then a default database name with the form - imgt___d will be used.''') + If not specified, the database folder is searched for a file + matching airrc-imgt___d first, then imgt___d. + If neither is found, --ddb must be specified explicitly.''') group_igblast.add_argument('--jdb', action='store', dest='jdb', default=None, help='''Name of the custom J reference in the IgBLAST database folder. - If not specified, then a default database name with the form - imgt___j will be used.''') + If not specified, the database folder is searched for a file + matching airrc-imgt___j first, then imgt___j. + If neither is found, --jdb must be specified explicitly.''') group_igblast.add_argument('--cdb', action='store', dest='cdb', default=None, help='''Name of the custom C reference in the IgBLAST database folder. - If not specified, then a default database name with the form - imgt___c will be used. Note, this argument will be - ignored for IgBLAST versions below 1.18.0.''') + If not specified, the database folder is searched for a file + matching airrc-imgt___c first, then imgt___c. + Note, this argument will be ignored for IgBLAST versions below 1.18.0.''') group_igblast.add_argument('--format', action='store', dest='format', default=default_format, choices=choices_format, help='''Specify the output format. The "blast" will result in @@ -243,8 +246,9 @@ def getArgParser(): choices=choices_loci, help='The receptor type.') group_igblast_aa.add_argument('--vdb', action='store', dest='vdb', default=None, help='''Name of the custom V reference in the IgBLAST database folder. - If not specified, then a default database name with the form - imgt_aa___v will be used.''') + If not specified, the database folder is searched for a file + matching airrc-imgt_aa___v first, then imgt_aa___v. + If neither is found, --vdb must be specified explicitly.''') group_igblast_aa.add_argument('--exec', action='store', dest='igblast_exec', default=default_igblastp_exec, help='Path to the igblastp executable.') diff --git a/changeo/Applications.py b/changeo/Applications.py index 93b20ad..d47a02e 100644 --- a/changeo/Applications.py +++ b/changeo/Applications.py @@ -6,6 +6,7 @@ __author__ = 'Jason Anthony Vander Heiden' # Imports +import glob import os import re from packaging.version import parse as parse_version @@ -20,6 +21,38 @@ default_igblast_output = 'legacy' +def _resolve_db(igdata, segment, organism, loci, explicit=None, aa=False): + """ + Resolve an IgBLAST database path by probing the filesystem. + + Tries the 'airrc-imgt' prefix first, then 'imgt'. Returns None if neither is + found and no explicit name was given. + + Arguments: + igdata (str): path to the IgBLAST database directory. + segment (str): gene segment; one of 'v', 'd', 'j', or 'c'. + organism (str): species name. + loci (str): receptor type; one of 'ig' or 'tr'. + explicit (str): explicit database name, bypassing prefix resolution. + aa (bool): if True, use the amino acid infix ('airrc-imgt_aa_' / 'imgt_aa_'). + + Returns: + str: full path to the database, or None if not found. + """ + if explicit is not None: + return os.path.join(igdata, 'database', explicit) + + infix = '_aa_' if aa else '_' + db_dir = os.path.join(igdata, 'database') + for prefix in ('airrc-imgt', 'imgt'): + name = '%s%s%s_%s_%s' % (prefix, infix, organism, loci, segment) + path = os.path.join(db_dir, name) + if glob.glob(path + '.*') or os.path.isfile(path): + return path + + return None + + def runASN(fasta, template=None, exec=default_tbl2asn_exec): """ Executes tbl2asn to generate Sequin files @@ -157,17 +190,26 @@ def runIgBLASTN(fasta, igdata, loci='ig', organism='human', vdb=None, ddb=None, # Set auxiliary data auxiliary = os.path.join(igdata, 'optional_file', '%s_gl.aux' % organism) # Set V database - if vdb is not None: v_germ = os.path.join(igdata, 'database', vdb) - else: v_germ = os.path.join(igdata, 'database', 'imgt_%s_%s_v' % (organism, loci)) + v_germ = _resolve_db(igdata, 'v', organism, loci, explicit=vdb) + if v_germ is None: + printError('No V database found for organism "%s" and loci "%s" with "airrc-imgt" or "imgt" prefix. ' + 'Specify --vdb, --ddb and --jdb explicitly.' % (organism, loci)) # Set D database - if ddb is not None: d_germ = os.path.join(igdata, 'database', ddb) - else: d_germ = os.path.join(igdata, 'database', 'imgt_%s_%s_d' % (organism, loci)) + d_germ = _resolve_db(igdata, 'd', organism, loci, explicit=ddb) + if d_germ is None: + printError('No D database found for organism "%s" and loci "%s" with "airrc-imgt" or "imgt" prefix. ' + 'Specify --vdb, --ddb and --jdb explicitly.' % (organism, loci)) # Set J database - if jdb is not None: j_germ = os.path.join(igdata, 'database', jdb) - else: j_germ = os.path.join(igdata, 'database', 'imgt_%s_%s_j' % (organism, loci)) - # Set C database - if cdb is not None: c_germ = os.path.join(igdata, 'database', cdb) - else: c_germ = os.path.join(igdata, 'database', 'imgt_%s_%s_c' % (organism, loci)) + j_germ = _resolve_db(igdata, 'j', organism, loci, explicit=jdb) + if j_germ is None: + printError('No J database found for organism "%s" and loci "%s" with "airrc-imgt" or "imgt" prefix. ' + 'Specify --vdb, --ddb and --jdb explicitly.' % (organism, loci)) + # Set C database (optional; warn if not found rather than error) + c_germ = _resolve_db(igdata, 'c', organism, loci, explicit=cdb) + if c_germ is None: + printWarning('No C database found for organism "%s" and loci "%s" with "airrc-imgt" or "imgt" prefix. ' + 'Specify --cdb explicitly if C-region annotation is required.' % (organism, loci)) + c_germ = os.path.join(igdata, 'database', 'imgt_%s_%s_c' % (organism, loci)) # Define IgBLAST command cmd = [exec, @@ -234,8 +276,10 @@ def runIgBLASTP(fasta, igdata, loci='ig', organism='human', vdb=None, output=Non printError('Invalid receptor type %s.' % loci) # Set V database - if vdb is not None: v_germ = os.path.join(igdata, 'database', vdb) - else: v_germ = os.path.join(igdata, 'database', 'imgt_aa_%s_%s_v' % (organism, loci)) + v_germ = _resolve_db(igdata, 'v', organism, loci, explicit=vdb, aa=True) + if v_germ is None: + printError('No V database found for organism "%s" and loci "%s" with "airrc-imgt_aa" or "imgt_aa" prefix. ' + 'Specify --vdb explicitly.' % (organism, loci)) # Define IgBLAST command cmd = [exec,