--- title: "Cancer Variant Interpretation - Detailed Analysis Procedures" task: "" lineage_type: import upstream_source: https://github.com/mims-harvard/ToolUniverse/blob/e2520a96/skills/tooluniverse-cancer-variant-interpretation/ANALYSIS_DETAILS.md upstream_sha: e2520a96 imported_at: 2026-06-26 prompt_class: prompt upstream_changes: accepted author: upstream validated: false --- # Cancer Variant Interpretation - Detailed Analysis Procedures ## Phase 1: Gene Disambiguation & ID Resolution ### 1.1 MyGene ID Resolution (PRIMARY) ```python def resolve_gene_ids(tu, gene_symbol): """Resolve gene symbol to Ensembl, Entrez, UniProt IDs.""" result = tu.tools.MyGene_query_genes(query=gene_symbol, species='human') hits = result.get('hits', []) # Take the top hit where symbol matches exactly gene_hit = None for hit in hits: if hit.get('symbol', '').upper() == gene_symbol.upper(): gene_hit = hit break if not gene_hit and hits: gene_hit = hits[0] ids = { 'symbol': gene_hit.get('symbol'), 'entrez_id': gene_hit.get('entrezgene'), 'ensembl_id': gene_hit.get('ensembl', {}).get('gene'), 'name': gene_hit.get('name'), } return ids ``` **Response structure**: `{took, total, max_score, hits: [{_id, _score, ensembl: {gene}, entrezgene, name, symbol}]}` ### 1.2 UniProt Accession ```python def get_uniprot_id(tu, gene_symbol): """Get UniProt accession for gene.""" result = tu.tools.UniProt_search(query=f'gene:{gene_symbol}', organism='human', limit=3) # Response: {total_results, returned, results: [{accession, id, protein_name, gene_names, organism, length}]} results = result.get('results', []) if results: return results[0].get('accession') return None ``` ### 1.3 OpenTargets Target Resolution ```python def get_opentargets_info(tu, gene_symbol): """Resolve gene to OpenTargets ensemblId and description.""" result = tu.tools.OpenTargets_get_target_id_description_by_name(targetName=gene_symbol) # Response: {data: {search: {hits: [{id (ensemblId), name, description}]}}} hits = result.get('data', {}).get('search', {}).get('hits', []) for hit in hits: if hit.get('name', '').upper() == gene_symbol.upper(): return hit return hits[0] if hits else None ``` ### 1.4 Cancer Type EFO Resolution (if cancer type provided) ```python def resolve_cancer_type(tu, cancer_type): """Resolve cancer type to EFO ID for OpenTargets queries.""" result = tu.tools.OpenTargets_get_disease_id_description_by_name(diseaseName=cancer_type) hits = result.get('data', {}).get('search', {}).get('hits', []) return hits[0] if hits else None ``` ### 1.5 Gene Function Context ```python def get_gene_function(tu, uniprot_accession): """Get protein function from UniProt. NOTE: Returns a list of function description strings, NOT a dict. """ result = tu.tools.UniProt_get_function_by_accession(accession=uniprot_accession) return result ``` ### 1.6 CIViC Gene ID Resolution **IMPORTANT**: The `civic_search_genes` tool does NOT support name filtering in its GraphQL query. To find a gene in CIViC, either: 1. Paginate through results (inefficient, genes sorted alphabetically) 2. Use the Entrez ID from MyGene to construct a CIViC gene lookup **Workaround**: Use `civic_search_genes` with `limit=100` and search the results client-side. **Known CIViC Gene IDs** (for common cancer genes): | Gene | CIViC Gene ID | Entrez ID | |------|--------------|-----------| | BRAF | 5 | 673 | | ABL1 | 4 | 25 | | ALK | 1 | 238 | --- ## Phase 2: Clinical Variant Evidence (CIViC) ### 2.1 Get Gene Variants from CIViC ```python def get_civic_variants(tu, civic_gene_id): """Get all variants for a gene in CIViC.""" result = tu.tools.civic_get_variants_by_gene(gene_id=civic_gene_id, limit=200) variants = result.get('data', {}).get('gene', {}).get('variants', {}).get('nodes', []) return variants ``` ### 2.2 Match Specific Variant ```python def find_variant_in_civic(variants, variant_name): """Find the specific variant in CIViC results.""" normalized = variant_name.replace('p.', '').strip() for v in variants: if v.get('name', '').upper() == normalized.upper(): return v for v in variants: if normalized.upper() in v.get('name', '').upper(): return v return None ``` ### 2.3 Get Variant Details ```python def get_variant_details(tu, variant_id): """Get detailed variant information from CIViC.""" result = tu.tools.civic_get_variant(variant_id=variant_id) return result.get('data', {}).get('variant', {}) ``` ### 2.4 Get Molecular Profile Evidence ```python def get_molecular_profile(tu, molecular_profile_id): """Get molecular profile details (for evidence items).""" result = tu.tools.civic_get_molecular_profile(molecular_profile_id=molecular_profile_id) return result.get('data', {}).get('molecularProfile', {}) ``` ### 2.5 CIViC Evidence Limitations and Fallback The current CIViC tools return limited field sets from GraphQL. If CIViC data is sparse: - **Fallback to literature**: Use PubMed to search for "{gene} {variant} clinical significance cancer" - **Fallback to OpenTargets**: Use `OpenTargets_target_disease_evidence` for target-disease evidence --- ## Phase 3: Mutation Prevalence (cBioPortal) ### 3.1 Find Relevant Studies ```python def find_cancer_studies(tu, cancer_keyword=None): """Find relevant cBioPortal studies.""" result = tu.tools.cBioPortal_get_cancer_studies(limit=50) studies = result if isinstance(result, list) else result.get('data', []) if cancer_keyword: filtered = [s for s in studies if cancer_keyword.lower() in str(s.get('name', '')).lower() or cancer_keyword.lower() in str(s.get('cancerTypeId', '')).lower()] return filtered return studies ``` ### 3.2 Get Mutation Data ```python def get_mutation_prevalence(tu, gene_symbol, study_id): """Get mutation data for a gene in a specific study.""" result = tu.tools.cBioPortal_get_mutations(study_id=study_id, gene_list=gene_symbol) if isinstance(result, list): mutations = result elif isinstance(result, dict): mutations = result.get('data', []) if result.get('status') == 'success' else [] else: mutations = [] return mutations ``` ### 3.3 Analyze Mutation Distribution ```python def analyze_mutation_distribution(mutations, target_variant): """Count how many samples have the target variant vs. others.""" from collections import Counter protein_changes = [m.get('proteinChange', '') for m in mutations] counts = Counter(protein_changes) total_mutated = len(mutations) target_count = sum(1 for m in mutations if target_variant.upper() in str(m.get('proteinChange', '')).upper()) return { 'total_mutated_samples': total_mutated, 'target_variant_count': target_count, 'target_variant_frequency': target_count / total_mutated if total_mutated > 0 else 0, 'top_variants': counts.most_common(10), } ``` ### Key cBioPortal Studies for Common Cancer Types | Cancer Type | Study ID | Description | |-------------|----------|-------------| | Lung adenocarcinoma | luad_tcga | TCGA Lung Adenocarcinoma | | Breast cancer | brca_tcga | TCGA Breast Cancer | | Colorectal cancer | coadread_tcga | TCGA Colorectal | | Melanoma | skcm_tcga | TCGA Melanoma | | Pancreatic cancer | paad_tcga | TCGA Pancreatic | | Glioblastoma | gbm_tcga | TCGA Glioblastoma | | Prostate cancer | prad_tcga | TCGA Prostate | | Ovarian cancer | ov_tcga | TCGA Ovarian | --- ## Phase 4: Therapeutic Associations ### 4.1 OpenTargets Drug-Target Associations (PRIMARY) ```python def get_target_drugs(tu, ensembl_id, size=50): """Get all drugs associated with a target from OpenTargets.""" result = tu.tools.OpenTargets_get_associated_drugs_by_target_ensemblID( ensemblId=ensembl_id, size=size ) drugs = result.get('data', {}).get('target', {}).get('knownDrugs', {}) rows = drugs.get('rows', []) approved = [r for r in rows if r.get('drug', {}).get('isApproved')] phase3 = [r for r in rows if r.get('phase') == 3 and not r.get('drug', {}).get('isApproved')] phase2 = [r for r in rows if r.get('phase') == 2] return { 'total': drugs.get('count', 0), 'approved': approved, 'phase3': phase3, 'phase2': phase2, 'all_rows': rows } ``` ### 4.2 OpenTargets Drug Mechanisms ```python def get_drug_mechanism(tu, chembl_id): """Get mechanism of action for a drug.""" result = tu.tools.OpenTargets_get_drug_mechanisms_of_action_by_chemblId(chemblId=chembl_id) return result ``` ### 4.3 FDA Label Information ```python def get_fda_label(tu, drug_name): """Get FDA-approved indications and label info.""" indications = tu.tools.FDA_get_indications_by_drug_name(drug_name=drug_name, limit=3) warnings = tu.tools.FDA_get_boxed_warning_info_by_drug_name(drug_name=drug_name, limit=3) moa = tu.tools.FDA_get_mechanism_of_action_by_drug_name(drug_name=drug_name, limit=3) return {'indications': indications, 'warnings': warnings, 'mechanism': moa} ``` ### 4.4 DrugBank Drug Information ```python def get_drugbank_info(tu, drug_name): """Get drug information from DrugBank.""" result = tu.tools.drugbank_get_drug_basic_info_by_drug_name_or_id( query=drug_name, case_sensitive=False, exact_match=False, limit=3 ) return result ``` ### 4.5 ChEMBL Drug Mechanism ```python def get_chembl_mechanism(tu, chembl_drug_id): """Get drug mechanism from ChEMBL.""" result = tu.tools.ChEMBL_get_drug_mechanisms(drug_chembl_id__exact=chembl_drug_id, limit=10) return result ``` ### 4.6 Disease-Specific Drug Filtering ```python def get_disease_specific_drugs(tu, efo_id, size=30): """Get drugs associated with a specific disease/cancer type.""" result = tu.tools.OpenTargets_get_associated_drugs_by_disease_efoId(efoId=efo_id, size=size) return result ``` --- ## Phase 5: Resistance Mechanisms ### 5.1 CIViC Resistance Evidence Search CIViC for variants with resistance significance for the target gene. Get all variants and look for those with "Resistance" in the name or description. ### 5.2 Literature-Based Resistance Search ```python def search_resistance_literature(tu, gene_symbol, drug_name): """Search PubMed for resistance mechanisms. NOTE: PubMed returns a plain list of article dicts, NOT {articles: [...]}. """ result = tu.tools.PubMed_search_articles( query=f'"{gene_symbol}" AND "{drug_name}" AND resistance AND mechanism', limit=15, include_abstract=True ) articles = result if isinstance(result, list) else result.get('articles', []) if isinstance(result, dict) else [] return articles ``` ### 5.3 Pathway-Based Bypass Resistance ```python def get_bypass_pathways(tu, uniprot_id): """Get pathways that could mediate bypass resistance.""" result = tu.tools.Reactome_map_uniprot_to_pathways(id=uniprot_id) return result ``` ### Known Resistance Patterns (Reference) | Primary Target | Primary Drug | Resistance Mutation | Mechanism | Strategy | |---------------|-------------|-------------------|-----------|----------| | EGFR L858R | Erlotinib/Gefitinib | T790M | Steric hindrance | Osimertinib (3rd-gen TKI) | | EGFR T790M | Osimertinib | C797S | Covalent bond loss | 4th-gen TKI trials | | BRAF V600E | Vemurafenib | Splice variants | Paradoxical activation | BRAF+MEK combination | | ALK fusion | Crizotinib | L1196M, G1269A | Kinase domain mutations | Alectinib, Lorlatinib | | KRAS G12C | Sotorasib | Y96D, R68S | Drug binding loss | KRAS G12C combo trials | --- ## Phase 6: Clinical Trials ### 6.1 Search Strategy ```python def find_clinical_trials(tu, gene_symbol, variant_name, cancer_type=None): """Find clinical trials for this mutation.""" query1 = f'{gene_symbol} {variant_name}' result1 = tu.tools.search_clinical_trials( query_term=query1, condition=cancer_type or 'cancer', pageSize=20 ) result2 = tu.tools.search_clinical_trials( query_term=f'{gene_symbol} mutation', condition=cancer_type or 'cancer', pageSize=20 ) return {'variant_specific': result1, 'gene_level': result2} ``` **Response structure**: `{studies: [{NCT ID, brief_title, brief_summary, overall_status, condition, phase}], nextPageToken, total_count}` ### 6.2 Trial Filtering Prioritize trials that: 1. Are **RECRUITING** or **NOT_YET_RECRUITING** status 2. Match the specific variant (not just gene) 3. Are Phase 2 or 3 (closer to approval) 4. Have the right cancer type --- ## Phase 7: Prognostic Impact & Pathway Context ### 7.1 Literature Evidence ```python def get_prognostic_literature(tu, gene_symbol, variant_name, cancer_type=None): """Search for prognostic associations.""" query = f'"{gene_symbol}" "{variant_name}" prognosis survival' if cancer_type: query += f' "{cancer_type}"' result = tu.tools.PubMed_search_articles(query=query, limit=10, include_abstract=True) return result ``` ### 7.2 Pathway Context (Reactome) ```python def get_pathway_context(tu, uniprot_id): """Get pathway context from Reactome.""" result = tu.tools.Reactome_map_uniprot_to_pathways(id=uniprot_id) return result ``` ### 7.3 Gene Expression (GTEx) ```python def get_expression_context(tu, ensembl_id): """Get tissue expression data from GTEx.""" gene_info = tu.tools.ensembl_lookup_gene(gene_id=ensembl_id, species='homo_sapiens') data = gene_info.get('data', gene_info) if isinstance(gene_info, dict) else {} version = data.get('version', 1) versioned_id = f"{ensembl_id}.{version}" result = tu.tools.GTEx_get_median_gene_expression( gencode_id=versioned_id, operation='median' ) return result ``` ### 7.4 UniProt Disease Variants ```python def get_known_disease_variants(tu, uniprot_accession): """Get known disease-associated variants from UniProt.""" result = tu.tools.UniProt_get_disease_variants_by_accession(accession=uniprot_accession) return result ```