2dda14f9c5394e1d6fa30f3da69e74b8e8b84413 lrnassar Tue Jun 30 15:34:05 2026 -0700 Fix panelApp otto crash when reading Ensembl gene locations. The script hardcoded the Ensembl release sub-key (GRch37/82, GRch38/90) when pulling gene coordinates, but PanelApp Australia moved to releases 87/115. Every Australia gene then failed both assembly lookups, leaving the dataframes empty and raising a column-count ValueError. Added an ensemblBuild() helper that selects whichever release key the API returns, and routed all gene/STR coordinate and ensembl_id lookups through it. England (still on 82/90) is unaffected. No RM, refs otto diff --git src/hg/utils/otto/panelApp/doPanelApp.py src/hg/utils/otto/panelApp/doPanelApp.py index 98794cade96..97d999c4613 100755 --- src/hg/utils/otto/panelApp/doPanelApp.py +++ src/hg/utils/otto/panelApp/doPanelApp.py @@ -107,30 +107,37 @@ try: jData = requests_get_with_retry(url) # If jData is empty create, else append if "error" in jData.keys() or not "results" in jData.keys(): raise Exception("Error in keys when downloading %s" % url) if "count" in jData and not "page" in url: print("API says that there are %d results for url %s" % (jData["count"], url)) results.extend(jData["results"]) if "next" in jData and jData["next"] is not None: # need to get next URL return getAllPages(jData["next"], results) except Exception as e: raise Exception("Error when downloading %s: %s" % (url, str(e))) return results +def ensemblBuild(ensembl_genes, assembly): + """Return the newest Ensembl-release dict for an assembly. The release-number sub-key varies + by PanelApp instance (England GRch37/82, GRch38/90; Australia GRch37/87, GRch38/115).""" + releases = ensembl_genes[assembly] + relKey = sorted(releases.keys(), key=int)[-1] + return releases[relKey] + def downloadCnvs(url): Error = True continuous_count=0 res = getAllPages(url, results=[]) num_gene_data = len(res) print("Got %d CNVs" % num_gene_data) count = 0 continuous_count = 0 hg19_dict = dict() hg38_dict = dict() for geneCount, cnvData in enumerate(res): temp_attribute_dictionary = dict() string_dict_key = 'gene_{}'.format(geneCount) @@ -310,59 +317,59 @@ chromosome = res[count]['chromosome'] chromosome = 'chr{}'.format(chromosome) confidence_level = res[count]['confidence_level'] entity_name = res[count]['entity_name'] entity_type = res[count]['entity_type'] evidence = ' '.join(res[count]['evidence']) gene_data = res[count]['gene_data'] if gene_data: alias = ' '.join(gene_data.get('alias', [])) biotype = gene_data['biotype'] else: alias = "" biotype = "" try: - ensembl_id_37 = gene_data['ensembl_genes']['GRch37']['82']['ensembl_id'] + ensembl_id_37 = ensemblBuild(gene_data['ensembl_genes'], 'GRch37')['ensembl_id'] except: ensembl_id_37 = "None" try: - ensembl_id_38 = gene_data['ensembl_genes']['GRch38']['90']['ensembl_id'] + ensembl_id_38 = ensemblBuild(gene_data['ensembl_genes'], 'GRch38')['ensembl_id'] except: ensembl_id_38 = "None" gene_name = gene_data['gene_name'] #gene_symbol = gene_data['gene_symbol'] #hgnc_date_symbol_changed = gene_data['hgnc_date_symbol_changed'] hgnc_id = gene_data['hgnc_id'] hgnc_symbol = gene_data['hgnc_symbol'] if str(gene_data['omim_gene']) == "None": omim_gene = "None" else: omim_gene = ' '.join(gene_data['omim_gene']) grch37_coordinates = res[count]['grch37_coordinates'] if grch37_coordinates == None: - coordinates = gene_data['ensembl_genes']['GRch37']['82']['location'] + coordinates = ensemblBuild(gene_data['ensembl_genes'], 'GRch37')['location'] location = coordinates.split(':') grch37_coordinates = location[1].split('-') chromStart_19 = int(grch37_coordinates[0]) chromEnd_19 = int(grch37_coordinates[1]) # hg38 grch38_coordinates = res[count]['grch38_coordinates'] if grch38_coordinates == None: - coordinates = gene_data['ensembl_genes']['GRch38']['90']['location'] + coordinates = ensemblBuild(gene_data['ensembl_genes'], 'GRch38')['location'] location = coordinates.split(':') grch38_coordinates = location[1].split('-') mode_of_inheritance = res[count]['mode_of_inheritance'] normal_repeats = res[count]['normal_repeats'] chromStart_38 = int(grch38_coordinates[0]) chromEnd_38 = int(grch38_coordinates[1]) panel = res[count]['panel'] disease_group = panel['disease_group'] disease_sub_group = panel['disease_sub_group'] hash_id = panel['hash_id'] idd = panel['id'] panel_name = panel['name'] relevant_disorders = ' '.join(panel['relevant_disorders']) @@ -609,40 +616,40 @@ #filter by onlyPanels early, if specified if onlyPanels is not None: res = [entry for entry in res if entry.get('panel', {}).get('id') in onlyPanels] num_gene_variant = len(res) count = 0 while count != num_gene_variant: temp_attribute_dictionary = dict() string_dict_key = 'gene_{}'.format(continuous_count) gene_range_37 = None gene_range_38 = None try: - ensembl_genes_GRch37_82_location = res[count]['gene_data']['ensembl_genes']['GRch37']['82']['location'] + ensembl_genes_GRch37_82_location = ensemblBuild(res[count]['gene_data']['ensembl_genes'], 'GRch37')['location'] location_37 = ensembl_genes_GRch37_82_location.split(':') chromo_37 = 'chr'+location_37[0] gene_range_37 = location_37[1].split('-') # on hg19, we have added a chrMT sequence later. except: genes_missing_info.append(res[count]['gene_data']['gene_symbol']+"/hg19") try: - ensembl_genes_GRch38_90_location = res[count]['gene_data']['ensembl_genes']['GRch38']['90']['location'] + ensembl_genes_GRch38_90_location = ensemblBuild(res[count]['gene_data']['ensembl_genes'], 'GRch38')['location'] location_38 = ensembl_genes_GRch38_90_location.split(':') chromo_38 = 'chr'+location_38[0] # Change mitochondrial chromosomal suffix from MT -> M for hg38 only if chromo_38 == "chrMT": chromo_38 = "chrM" gene_range_38 = location_38[1].split('-') except: genes_missing_info.append(res[count]['gene_data']['gene_symbol']+"/hg38") if gene_range_37 is None and gene_range_38 is None: #print("gene without location on any assembly: %s" % res[count]) genes_no_location.append(res[count]['gene_data']) count+=1 continue @@ -693,32 +700,32 @@ try: biotype = res[count]['gene_data']['biotype'] if biotype == 'protein_coding': biotype = 'Protein Coding' temp_attribute_dictionary['biotype'] = biotype if biotype == None: temp_attribute_dictionary['biotype'] = '' except: temp_attribute_dictionary['biotype'] = '' #----------------------------------------------------------------------------------------------------------- try: - ensembl_genes_GRch37_82_ensembl_id = res[count]['gene_data']['ensembl_genes']['GRch37']['82']['ensembl_id'] - ensembl_genes_GRch38_90_ensembl_id = res[count]['gene_data']['ensembl_genes']['GRch38']['90']['ensembl_id'] + ensembl_genes_GRch37_82_ensembl_id = ensemblBuild(res[count]['gene_data']['ensembl_genes'], 'GRch37')['ensembl_id'] + ensembl_genes_GRch38_90_ensembl_id = ensemblBuild(res[count]['gene_data']['ensembl_genes'], 'GRch38')['ensembl_id'] except: ensembl_genes_GRch37_82_ensembl_id = '' #----------------------------------------------------------------------------------------------------------- gene_type_list = ['confidence_level', 'phenotypes', 'mode_of_inheritance', 'tags'] for attribute in gene_type_list: try: x = res[count][attribute] if not x: temp_attribute_dictionary[attribute] = '' else: pre = ' '.join(res[count][attribute])