{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Regulome Explorer Notebook 2.X\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from google.cloud import bigquery" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Import Python libraries" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import seaborn as sns\n", "from scipy.stats import ttest_ind" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Python convenience functions\n", "\n", "We define two convenience functions here:\n", "\n", "- **`runQuery`**: a relatively generic BigQuery query-execution wrapper function which can be used to run a query in \"dry-run\" mode or not: the call to the `query()` function itself is inside a `try/except` block and if it fails we return `None`; otherwise a \"dry\" will return an empty dataframe, and a \"live\" run will return the query results as a dataframe\n", "\n", "- **`checkQueryResults`**: a generic function that makes sure that what was returned is a dataframe, and checks how many rows are in the returned dataframe" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def runQuery ( client, qString, ParameterList, dryRun=False ):\n", " \n", " print ( \"\\n in runQuery ... \" )\n", " if ( dryRun ):\n", " print ( \" dry-run only \" )\n", " \n", " ## set up QueryJobConfig object\n", " job_config = bigquery.QueryJobConfig()\n", " \n", " query_params = [\n", " bigquery.ArrayQueryParameter('GENENAMES', 'STRING', ParameterList ) \n", " ]\n", " job_config.query_parameters = query_params \n", " \n", " job_config.dry_run = dryRun\n", " job_config.use_query_cache = True\n", " job_config.use_legacy_sql = False\n", " \n", " ## run the query\n", " try:\n", " query_job = client.query ( qString, job_config=job_config )\n", " ## print ( \" query job state: \", query_job.state )\n", " except:\n", " print ( \" FATAL ERROR: query execution failed \" )\n", " return ( None )\n", " \n", " ## return results as a dataframe (or an empty dataframe for a dry-run) \n", " if ( not dryRun ):\n", " try:\n", " df = query_job.to_dataframe()\n", " if ( query_job.total_bytes_processed==0 ):\n", " print ( \" the results for this query were previously cached \" )\n", " else:\n", " print ( \" this query processed {} bytes \".format(query_job.total_bytes_processed) )\n", " if ( len(df) < 1 ):\n", " print ( \" WARNING: this query returned NO results \")\n", " return ( df )\n", " except:\n", " print ( \" FATAL ERROR: query execution failed \" )\n", " return ( None )\n", " \n", " else:\n", " print ( \" if not cached, this query will process {} bytes \".format(query_job.total_bytes_processed) )\n", " ## return an empty dataframe\n", " return ( pd.DataFrame() )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### SQL Building Functions\n", "- **`build_cohort`**: create a table of SampleBarcodes from user defined Study \n", "\n", "- **`group1_cohort`**: create a set of samples with mutations in a user defined Gene " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def build_cohort ( study ):\n", " qString = \"\"\"\n", " WITH\n", " --\n", " -- samples with at least one mutation and gene expression in __study__\n", " --\n", " cohort AS (\n", " SELECT\n", " Tumor_SampleBarcode as sample_barcode\n", " FROM\n", " `pancancer-atlas.Filtered.MC3_MAF_V5_one_per_tumor_sample` \n", " WHERE\n", " ( study = '__study__' )\n", " GROUP BY\n", " 1\n", " ),\n", " sampleGroup AS (\n", " SELECT\n", " SampleBarcode as sample_barcode\n", " FROM\n", " `pancancer-atlas.Filtered.EBpp_AdjustPANCAN_IlluminaHiSeq_RNASeqV2_genExp_filtered`\n", " WHERE\n", " study = '__study__'\n", " AND SampleBarcode IN\n", " (select sample_barcode from cohort)\n", " GROUP BY\n", " 1 \n", " )\n", " \"\"\".replace('__study__',study)\n", " return(qString)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def group1_cohort( GeneName ):\n", " qString = \"\"\"\n", " --\n", " -- The first group has mutations in __Symbol__\n", " --\n", " grp1 AS (\n", " SELECT\n", " Tumor_SampleBarcode AS sample_barcode\n", " FROM\n", " `pancancer-atlas.Filtered.MC3_MAF_V5_one_per_tumor_sample`\n", " WHERE\n", " Hugo_Symbol = '__Symbol__'\n", " AND Tumor_SampleBarcode IN (\n", " SELECT\n", " sample_barcode\n", " FROM\n", " sampleGroup )\n", " GROUP BY sample_barcode\n", " )\n", " \"\"\".replace('__Symbol__',GeneName)\n", " return(qString)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Start the analysis" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Start by getting authorized.\n", "bqclient = bigquery.Client()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Select variables to analyze" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "study = 'UCEC' # Select Tumor type \n", "gene_mutation = 'PARP1' # Name of gene with potential mutation \n", "gene_expresion = 'IGF2' # Name of gene for differential gene expression analysis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Obtain data from biquery\n", "We first will retrieve the gene expression data of a user defined gene (gene_expresion) for each sample in the cohort " ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " in runQuery ... \n", " the results for this query were previously cached \n" ] } ], "source": [ "# Build the sql code\n", "sql = (\n", " build_cohort( study ) + '\\n' +\n", " \"\"\"\n", " SELECT \n", " SampleBarcode as sample_barcode,\n", " LOG10( normalized_count + 1 ) as genexp\n", " FROM \n", " `pancancer-atlas.Filtered.EBpp_AdjustPANCAN_IlluminaHiSeq_RNASeqV2_genExp_filtered`\n", " WHERE\n", " Symbol = '__Symbol__' \n", " AND SampleBarcode IN (SELECT sample_barcode FROM sampleGroup )\n", " \"\"\".replace('__Symbol__', gene_expresion )\n", ")\n", "# bigquery \n", "res0 = runQuery ( bqclient, sql, [], dryRun=False )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We then select the sample codes with mutation in the used defined gene (gene_mutation)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " in runQuery ... \n", " the results for this query were previously cached \n" ] } ], "source": [ "# Build the sql code\n", "sql = (\n", " build_cohort( study ) + ',\\n' +\n", " group1_cohort( gene_mutation ) + '\\n' +\n", " \"\"\"\n", " SELECT * FROM grp1 \n", " \"\"\"\n", ")\n", "res1 = runQuery ( bqclient, sql, [], dryRun=False )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Analyze the results\n", "We then merge the two dataframes (res0 and res1 ) created from bigquey data. \n", "res1 contain a list of samples with mutation in gene_mutation. We will create a new column (named 'Mutation') on res1 to mark these samples by the letter 'T' which indicate that the sample contains a mutation in gene_mutation.\n", "After merging the tables, the samples with no mutation will be labeled by 'F' in the colum 'Mutation'." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Merge the two query results \n", "res1['Mutation'] = 'T'\n", "mydf = pd.merge(res0,res1,on=\"sample_barcode\", how='outer')\n", "# samples with no mutation will be labeled F\n", "mydf.fillna('F',inplace=True)\n", "\n", "# violin plot of gene expression cobsidering the two groups (mutated and no mutated) in 'Mutation' column \n", "sns.violinplot( x=mydf[\"Mutation\"], y=mydf[\"genexp\"], palette=\"Blues\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can compute the average of gene expression for the two groups." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
genexp
Mutation
F3.172452
T2.747706
\n", "
" ], "text/plain": [ " genexp\n", "Mutation \n", "F 3.172452\n", "T 2.747706" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mydf.groupby('Mutation').mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can also perform a t-test to determine if the difference between the mean of the two groups is statistically significant" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Ttest_indResult(statistic=3.892136471894355, pvalue=0.0003816227439487523)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Set1 = mydf[mydf['Mutation']=='F']\n", "Set2 = mydf[mydf['Mutation']=='T']\n", "ttest_ind(Set1['genexp'], Set2['genexp'], equal_var=False )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.1" } }, "nbformat": 4, "nbformat_minor": 2 }