From 1050c503769828b9861fc42ee6552b85da06948e Mon Sep 17 00:00:00 2001 From: Anak Empawi Date: Thu, 25 Jun 2026 00:14:12 -0400 Subject: [PATCH] Update twas_ctwas.ipynb: clarify titles and fix run commands --- code/SoS/pecotmr_integration/twas_ctwas.ipynb | 319 +++++++++++++++++- 1 file changed, 301 insertions(+), 18 deletions(-) diff --git a/code/SoS/pecotmr_integration/twas_ctwas.ipynb b/code/SoS/pecotmr_integration/twas_ctwas.ipynb index 63e36095..4640fefc 100644 --- a/code/SoS/pecotmr_integration/twas_ctwas.ipynb +++ b/code/SoS/pecotmr_integration/twas_ctwas.ipynb @@ -57,6 +57,115 @@ "```\n" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "raw", + "metadata": { + "kernel": "SoS" + }, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "kernel": "SoS" + }, + "outputs": [], + "source": [ + "sos run pipeline/twas_ctwas.ipynb twas \\\n", + " --cwd output --name protocol_example \\\n", + " --gwas_meta_data input/twas/protocol_example.twas.gwas_meta.tsv \\\n", + " --xqtl_meta_data input/twas/protocol_example.twas.xqtl_meta.tsv \\\n", + " --ld_meta_data input/ld_reference/protocol_example.ld_meta_file.tsv \\\n", + " --ld_reference_sample_size 17000 \\\n", + " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed \\\n", + " --xqtl_type_table input/twas/protocol_example.twas.data_type_table.txt \\\n", + " --rsq_pval_cutoff 0.05 --rsq_cutoff 0.01 \\\n", + " --region-name chr22_10000000_19000000" + ] + }, { "cell_type": "markdown", "metadata": { @@ -93,9 +202,7 @@ "kernel": "SoS" }, "source": [ - "## Step 3: Quantile TWAS\n", - "\n", - "Use pre-computed TWAS weights for quantile-specific testing: for each quantile level, cluster and integrate by fixed and dynamic region groups, extract the relevant GWAS z-scores and LD matrix for the region, and perform quantile region-specific association tests, identifying variants whose effects vary across different quantile regions of the phenotype distribution. Use `--region-name` (formatted as `chr_start_stop`) to focus on specific blocks, or `--region` to analyze a selected list of regions.\n" + "#### cTWAS Step 1: Assemble region data" ] }, { @@ -106,18 +213,26 @@ }, "outputs": [], "source": [ - "sos run pipeline/twas_ctwas.ipynb twas \\\n", + "sos run pipeline/twas_ctwas.ipynb ctwas \\\n", " --cwd output --name protocol_example \\\n", + " --thin 1 --prior_var_structure shared_all \\\n", " --gwas_meta_data input/twas/protocol_example.twas.gwas_meta.tsv \\\n", " --xqtl_meta_data input/twas/protocol_example.twas.xqtl_meta.tsv \\\n", " --ld_meta_data input/ld_reference/protocol_example.ld_meta_file.tsv \\\n", - " --ld_reference_sample_size 17000 \\\n", " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed \\\n", - " --xqtl_type_table input/twas/protocol_example.twas.data_type_table.txt \\\n", - " --rsq_pval_cutoff 0.05 --rsq_cutoff 0.01 \\\n", + " --twas_weight_cutoff 0 \\\n", " --region-name chr22_10000000_19000000" ] }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [ + "#### cTWAS Step 2: Estimate global parameters" + ] + }, { "cell_type": "code", "execution_count": null, @@ -127,14 +242,22 @@ "outputs": [], "source": [ "sos run pipeline/twas_ctwas.ipynb ctwas \\\n", + " --run_param_est --skip_assembly --thin 1 \\\n", + " --prior_var_structure shared_all \\\n", " --cwd output --name protocol_example \\\n", - " --thin 1 --prior_var_structure shared_all \\\n", " --gwas_meta_data input/twas/protocol_example.twas.gwas_meta.tsv \\\n", " --xqtl_meta_data input/twas/protocol_example.twas.xqtl_meta.tsv \\\n", " --ld_meta_data input/ld_reference/protocol_example.ld_meta_file.tsv \\\n", - " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed \\\n", - " --twas_weight_cutoff 0 \\\n", - " --region-name chr22_10000000_19000000" + " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [ + "#### cTWAS Step 3: Fine-map causal genes and SNPs" ] }, { @@ -146,13 +269,24 @@ "outputs": [], "source": [ "sos run pipeline/twas_ctwas.ipynb ctwas \\\n", - " --run_param_est --skip_assembly --thin 1 \\\n", + " --run_finemapping --skip_assembly \\\n", " --prior_var_structure shared_all \\\n", " --cwd output --name protocol_example \\\n", " --gwas_meta_data input/twas/protocol_example.twas.gwas_meta.tsv \\\n", " --xqtl_meta_data input/twas/protocol_example.twas.xqtl_meta.tsv \\\n", " --ld_meta_data input/ld_reference/protocol_example.ld_meta_file.tsv \\\n", - " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed" + " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed \\\n", + " --region-name chr22_10000000_19000000" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "kernel": "SoS" + }, + "source": [ + "## Step 3: Quantile TWAS\n", + "Use pre-computed TWAS weights for quantile-specific testing: for each quantile level, cluster and integrate by fixed and dynamic region groups, extract the relevant GWAS z-scores and LD matrix for the region, and perform quantile region-specific association tests, identifying variants whose effects vary across different quantile regions of the phenotype distribution. Use `--region-name` (formatted as `chr_start_stop`) to focus on specific blocks, or `--region` to analyze a selected list of regions.\n" ] }, { @@ -163,14 +297,14 @@ }, "outputs": [], "source": [ - "sos run pipeline/twas_ctwas.ipynb ctwas \\\n", - " --run_finemapping --skip_assembly \\\n", - " --prior_var_structure shared_all \\\n", + "sos run pipeline/twas_ctwas.ipynb quantile_twas \\\n", " --cwd output --name protocol_example \\\n", " --gwas_meta_data input/twas/protocol_example.twas.gwas_meta.tsv \\\n", " --xqtl_meta_data input/twas/protocol_example.twas.xqtl_meta.tsv \\\n", " --ld_meta_data input/ld_reference/protocol_example.ld_meta_file.tsv \\\n", + " --ld_reference_sample_size 17000 \\\n", " --regions input/twas/protocol_example.twas.LD_blocks.chr22.bed \\\n", + " --xqtl_type_table input/twas/protocol_example.twas.data_type_table.txt \\\n", " --region-name chr22_10000000_19000000" ] }, @@ -280,7 +414,156 @@ }, "outputs": [], "source": [ - "[get_analysis_regions: shared = [\"filtered_region_info\", \"filtered_regional_xqtl_files\", \"regional_data\"]]\nfrom collections import OrderedDict\n\ndef check_required_columns(df, required_columns):\n \"\"\"Check if the required columns are present in the dataframe.\"\"\"\n missing_columns = [col for col in required_columns if col not in list(df.columns)]\n if missing_columns:\n raise ValueError(f\"Missing required columns: {', '.join(missing_columns)}\")\n\ndef extract_regional_data(gwas_meta_data, xqtl_meta_data, regions, region_name, gwas_name, gwas_data, column_mapping):\n \"\"\"\n Extracts data from GWAS and xQTL metadata files and additional GWAS data provided. \n\n Args:\n - gwas_meta_data (str): File path to the GWAS metadata file.\n - xqtl_meta_data (str): File path to the xQTL weight metadata file.\n - gwas_name (list): vector of GWAS study names.\n - gwas_data (list): vector of GWAS data.\n - column_mapping (list, optional): vector of column mapping files.\n\n Returns:\n - Tuple of two dictionaries:\n - GWAS Dictionary: Maps study IDs to a list containing chromosome number, \n GWAS file path, and optional column mapping file path.\n - xQTL Dictionary: Nested dictionary with region IDs as keys.\n\n Raises:\n - FileNotFoundError: If any specified file path does not exist.\n - ValueError: If required columns are missing in the input files or vector lengths mismatch.\n \"\"\"\n # Check vector lengths\n if len(gwas_name) != len(gwas_data):\n raise ValueError(\"gwas_name and gwas_data must be of equal length\")\n \n if len(column_mapping)>0 and len(column_mapping) != len(gwas_name):\n raise ValueError(\"If column_mapping is provided, it must be of the same length as gwas_name and gwas_data\")\n\n # Required columns for each file type\n required_gwas_columns = ['study_id', 'chrom', 'file_path']\n required_xqtl_columns = ['region_id', '#chr', 'start', 'end', \"TSS\", 'original_data'] #region_id here is gene name\n required_ld_columns = ['chr', 'start', 'stop']\n \n # Reading the GWAS metadata file\n gwas_df = pd.read_csv(gwas_meta_data, sep=\"\\t\")\n check_required_columns(gwas_df, required_gwas_columns)\n gwas_dict = OrderedDict()\n \n # Reading LD regions info\n # Initialize empty DataFrame for regions\n regions_df = pd.DataFrame(columns=['chr', 'start', 'stop'])\n\n # Check if regions file exists and read it\n if os.path.isfile(regions):\n file_regions_df = pd.read_csv(regions, sep=\"\\t\", skipinitialspace=True)\n file_regions_df.columns = [col.strip() for col in file_regions_df.columns] # Strip spaces from column names\n file_regions_df['chr'] = file_regions_df['chr'].str.strip()\n check_required_columns(file_regions_df, required_ld_columns)\n regions_df = pd.concat([regions_df, file_regions_df])\n # Process region_name if provided: \n # fomat: region_name = [\"chr1_16103_2888443\", \"chr1_4320284_5853833\"]\n if len(region_name) > 0:\n # Split region_name entries into chr, start, and stop columns\n extra_regions = [name.split(\"_\") for name in region_name]\n extra_regions_df = pd.DataFrame(extra_regions, columns=['chr', 'start', 'stop'])\n extra_regions_df['start'] = extra_regions_df['start'].astype(int)\n extra_regions_df['stop'] = extra_regions_df['stop'].astype(int)\n # Add extra regions to regions_df\n regions_df = extra_regions_df\n # Remove duplicates and reset index\n regions_df = regions_df.drop_duplicates().reset_index(drop=True)\n regions_dict = OrderedDict()\n\n # Reading the xQTL weight metadata file\n xqtl_df = pd.read_csv(xqtl_meta_data, sep=\"\\t\")\n check_required_columns(xqtl_df, required_xqtl_columns)\n xqtl_dict = OrderedDict()\n\n # Process additional GWAS data from R vectors\n for name, data, mapping in zip(gwas_name, gwas_data, column_mapping or [None]*len(gwas_name)):\n gwas_dict[name] = {0: [data, mapping]}\n\n for _, row in gwas_df.iterrows():\n file_path = row['file_path']\n mapping_file = row.get('column_mapping_file')\n \n # Adjust paths if necessary\n file_path = adapt_file_path(file_path, gwas_meta_data)\n if mapping_file:\n mapping_file = adapt_file_path(mapping_file, gwas_meta_data)\n\n # Create or update the entry for the study_id\n if row['study_id'] not in gwas_dict:\n gwas_dict[row['study_id']] = {}\n\n # Expand chrom 0 to chrom 1-22 or use the specified chrom\n chrom_range = range(1, 23) if row['chrom'] == 0 else [row['chrom']]\n for chrom in chrom_range:\n if chrom in gwas_dict[row['study_id']]:\n existing_entry = gwas_dict[row['study_id']][f'chr{chrom}']\n raise ValueError(f\"Duplicate chromosome specification for study_id {row['study_id']}, chrom {chrom}. \"\n f\"Conflicting entries: {existing_entry} and {[file_path, mapping_file]}\")\n gwas_dict[row['study_id']][f'chr{chrom}'] = [file_path, mapping_file]\n \n for _, row in regions_df.iterrows():\n LD_region_id = f\"{row['chr']}_{row['start']}_{row['stop']}\"\n overlapping_xqtls = xqtl_df[(xqtl_df['#chr'] == row['chr']) & \n (xqtl_df['TSS'] <= row['stop']) & \n (xqtl_df['TSS'] >= (row['start']))]\n file_paths = []\n mapped_genes = []\n # Collect file paths for xQTLs overlapping this region\n for _, xqtl_row in overlapping_xqtls.iterrows():\n original_data = xqtl_row['original_data']\n file_list = original_data.split(',') if ',' in original_data else [original_data]\n file_paths.extend([adapt_file_path(fp.strip(), xqtl_meta_data) for fp in file_list])\n mapped_genes.extend([xqtl_row['region_id']] * len(file_list))\n\n # Store metadata and files in the dictionary\n regions_dict[LD_region_id] = {\n \"meta_info\": [row['chr'], row['start'], row['stop'], LD_region_id, mapped_genes],\n \"files\": file_paths\n }\n \n for _, row in xqtl_df.iterrows():\n file_paths = [adapt_file_path(fp.strip(), xqtl_meta_data) for fp in row['original_data'].split(',')] # Splitting and stripping file paths\n xqtl_dict[row['region_id']] = {\"meta_info\": [row['#chr'], row['start'], row['end'], row['region_id'], row['contexts']],\n \"files\": file_paths}\n return gwas_dict, xqtl_dict, regions_dict\n\n\ngwas_dict, xqtl_dict, regions_dict = extract_regional_data(gwas_meta_data, xqtl_meta_data,regions,region_name,gwas_name, gwas_data, column_mapping)\nregional_data = dict([(\"GWAS\", gwas_dict), (\"xQTL\", xqtl_dict), (\"Regions\", regions_dict)])\n\n\n# get regions data \nregion_info = [x[\"meta_info\"] for x in regional_data['Regions'].values()]\nregional_xqtl_files = [x[\"files\"] for x in regional_data['Regions'].values()]\n\n# Filter out empty xQTL file paths\nfiltered_region_info = []\nfiltered_regional_xqtl_files = []\nskipped_regions =[]\n\nfor region, files in zip(region_info, regional_xqtl_files):\n if files:\n filtered_region_info.append(region)\n filtered_regional_xqtl_files.append(files)\n else:\n skipped_regions.append(region)\nprint(f\"Skipping {len(skipped_regions)} out of {len(regional_xqtl_files)} regions, no overlapping xQTL weights found. \")" + "[get_analysis_regions: shared = [\"filtered_region_info\", \"filtered_regional_xqtl_files\", \"regional_data\"]]\n", + "from collections import OrderedDict\n", + "\n", + "def check_required_columns(df, required_columns):\n", + " \"\"\"Check if the required columns are present in the dataframe.\"\"\"\n", + " missing_columns = [col for col in required_columns if col not in list(df.columns)]\n", + " if missing_columns:\n", + " raise ValueError(f\"Missing required columns: {', '.join(missing_columns)}\")\n", + "\n", + "def extract_regional_data(gwas_meta_data, xqtl_meta_data, regions, region_name, gwas_name, gwas_data, column_mapping):\n", + " \"\"\"\n", + " Extracts data from GWAS and xQTL metadata files and additional GWAS data provided. \n", + "\n", + " Args:\n", + " - gwas_meta_data (str): File path to the GWAS metadata file.\n", + " - xqtl_meta_data (str): File path to the xQTL weight metadata file.\n", + " - gwas_name (list): vector of GWAS study names.\n", + " - gwas_data (list): vector of GWAS data.\n", + " - column_mapping (list, optional): vector of column mapping files.\n", + "\n", + " Returns:\n", + " - Tuple of two dictionaries:\n", + " - GWAS Dictionary: Maps study IDs to a list containing chromosome number, \n", + " GWAS file path, and optional column mapping file path.\n", + " - xQTL Dictionary: Nested dictionary with region IDs as keys.\n", + "\n", + " Raises:\n", + " - FileNotFoundError: If any specified file path does not exist.\n", + " - ValueError: If required columns are missing in the input files or vector lengths mismatch.\n", + " \"\"\"\n", + " # Check vector lengths\n", + " if len(gwas_name) != len(gwas_data):\n", + " raise ValueError(\"gwas_name and gwas_data must be of equal length\")\n", + " \n", + " if len(column_mapping)>0 and len(column_mapping) != len(gwas_name):\n", + " raise ValueError(\"If column_mapping is provided, it must be of the same length as gwas_name and gwas_data\")\n", + "\n", + " # Required columns for each file type\n", + " required_gwas_columns = ['study_id', 'chrom', 'file_path']\n", + " required_xqtl_columns = ['region_id', '#chr', 'start', 'end', \"TSS\", 'original_data'] #region_id here is gene name\n", + " required_ld_columns = ['chr', 'start', 'stop']\n", + " \n", + " # Reading the GWAS metadata file\n", + " gwas_df = pd.read_csv(gwas_meta_data, sep=\"\\t\")\n", + " check_required_columns(gwas_df, required_gwas_columns)\n", + " gwas_dict = OrderedDict()\n", + " \n", + " # Reading LD regions info\n", + " # Initialize empty DataFrame for regions\n", + " regions_df = pd.DataFrame(columns=['chr', 'start', 'stop'])\n", + "\n", + " # Check if regions file exists and read it\n", + " if os.path.isfile(regions):\n", + " file_regions_df = pd.read_csv(regions, sep=\"\\t\", skipinitialspace=True)\n", + " file_regions_df.columns = [col.strip() for col in file_regions_df.columns] # Strip spaces from column names\n", + " file_regions_df['chr'] = file_regions_df['chr'].str.strip()\n", + " check_required_columns(file_regions_df, required_ld_columns)\n", + " regions_df = pd.concat([regions_df, file_regions_df])\n", + " # Process region_name if provided: \n", + " # fomat: region_name = [\"chr1_16103_2888443\", \"chr1_4320284_5853833\"]\n", + " if len(region_name) > 0:\n", + " # Split region_name entries into chr, start, and stop columns\n", + " extra_regions = [name.split(\"_\") for name in region_name]\n", + " extra_regions_df = pd.DataFrame(extra_regions, columns=['chr', 'start', 'stop'])\n", + " extra_regions_df['start'] = extra_regions_df['start'].astype(int)\n", + " extra_regions_df['stop'] = extra_regions_df['stop'].astype(int)\n", + " # Add extra regions to regions_df\n", + " regions_df = extra_regions_df\n", + " # Remove duplicates and reset index\n", + " regions_df = regions_df.drop_duplicates().reset_index(drop=True)\n", + " regions_dict = OrderedDict()\n", + "\n", + " # Reading the xQTL weight metadata file\n", + " xqtl_df = pd.read_csv(xqtl_meta_data, sep=\"\\t\")\n", + " check_required_columns(xqtl_df, required_xqtl_columns)\n", + " xqtl_dict = OrderedDict()\n", + "\n", + " # Process additional GWAS data from R vectors\n", + " for name, data, mapping in zip(gwas_name, gwas_data, column_mapping or [None]*len(gwas_name)):\n", + " gwas_dict[name] = {0: [data, mapping]}\n", + "\n", + " for _, row in gwas_df.iterrows():\n", + " file_path = row['file_path']\n", + " mapping_file = row.get('column_mapping_file')\n", + " \n", + " # Adjust paths if necessary\n", + " file_path = adapt_file_path(file_path, gwas_meta_data)\n", + " if mapping_file:\n", + " mapping_file = adapt_file_path(mapping_file, gwas_meta_data)\n", + "\n", + " # Create or update the entry for the study_id\n", + " if row['study_id'] not in gwas_dict:\n", + " gwas_dict[row['study_id']] = {}\n", + "\n", + " # Expand chrom 0 to chrom 1-22 or use the specified chrom\n", + " chrom_range = range(1, 23) if row['chrom'] == 0 else [row['chrom']]\n", + " for chrom in chrom_range:\n", + " if chrom in gwas_dict[row['study_id']]:\n", + " existing_entry = gwas_dict[row['study_id']][f'chr{chrom}']\n", + " raise ValueError(f\"Duplicate chromosome specification for study_id {row['study_id']}, chrom {chrom}. \"\n", + " f\"Conflicting entries: {existing_entry} and {[file_path, mapping_file]}\")\n", + " gwas_dict[row['study_id']][f'chr{chrom}'] = [file_path, mapping_file]\n", + " \n", + " for _, row in regions_df.iterrows():\n", + " LD_region_id = f\"{row['chr']}_{row['start']}_{row['stop']}\"\n", + " overlapping_xqtls = xqtl_df[(xqtl_df['#chr'] == row['chr']) & \n", + " (xqtl_df['TSS'] <= row['stop']) & \n", + " (xqtl_df['TSS'] >= (row['start']))]\n", + " file_paths = []\n", + " mapped_genes = []\n", + " # Collect file paths for xQTLs overlapping this region\n", + " for _, xqtl_row in overlapping_xqtls.iterrows():\n", + " original_data = xqtl_row['original_data']\n", + " file_list = original_data.split(',') if ',' in original_data else [original_data]\n", + " file_paths.extend([adapt_file_path(fp.strip(), xqtl_meta_data) for fp in file_list])\n", + " mapped_genes.extend([xqtl_row['region_id']] * len(file_list))\n", + "\n", + " # Store metadata and files in the dictionary\n", + " regions_dict[LD_region_id] = {\n", + " \"meta_info\": [row['chr'], row['start'], row['stop'], LD_region_id, mapped_genes],\n", + " \"files\": file_paths\n", + " }\n", + " \n", + " for _, row in xqtl_df.iterrows():\n", + " file_paths = [adapt_file_path(fp.strip(), xqtl_meta_data) for fp in row['original_data'].split(',')] # Splitting and stripping file paths\n", + " xqtl_dict[row['region_id']] = {\"meta_info\": [row['#chr'], row['start'], row['end'], row['region_id'], row['contexts']],\n", + " \"files\": file_paths}\n", + " return gwas_dict, xqtl_dict, regions_dict\n", + "\n", + "\n", + "gwas_dict, xqtl_dict, regions_dict = extract_regional_data(gwas_meta_data, xqtl_meta_data,regions,region_name,gwas_name, gwas_data, column_mapping)\n", + "regional_data = dict([(\"GWAS\", gwas_dict), (\"xQTL\", xqtl_dict), (\"Regions\", regions_dict)])\n", + "\n", + "\n", + "# get regions data \n", + "region_info = [x[\"meta_info\"] for x in regional_data['Regions'].values()]\n", + "regional_xqtl_files = [x[\"files\"] for x in regional_data['Regions'].values()]\n", + "\n", + "# Filter out empty xQTL file paths\n", + "filtered_region_info = []\n", + "filtered_regional_xqtl_files = []\n", + "skipped_regions =[]\n", + "\n", + "for region, files in zip(region_info, regional_xqtl_files):\n", + " if files:\n", + " filtered_region_info.append(region)\n", + " filtered_regional_xqtl_files.append(files)\n", + " else:\n", + " skipped_regions.append(region)\n", + "print(f\"Skipping {len(skipped_regions)} out of {len(regional_xqtl_files)} regions, no overlapping xQTL weights found. \")" ] }, { @@ -735,7 +1018,7 @@ "kernels": [ [ "Bash", - "bash", + "calysto_bash", "Bash", "#E6EEFF", "shell"