get_differential_expression
Compare gene expression levels between different tissue groups using GTEx data to identify significant differences in biological samples.
Instructions
Get differential gene expression between tissue groups
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| gencodeId | Yes | GENCODE gene ID (e.g., ENSG00000223972.5) | |
| comparisonGroups | Yes | Array of tissue groups to compare | |
| datasetId | No | GTEx dataset ID (default: gtex_v8) | gtex_v8 |
Implementation Reference
- Implements the core logic for get_differential_expression tool: validates inputs, fetches median gene expression data via API client, groups tissues by comparison categories, computes mean expression and fold changes between groups, generates formatted output with statistics.
async getDifferentialExpression(args: any) { if (!args.geneId || typeof args.geneId !== 'string') { throw new Error('geneId parameter is required and must be a gene ID'); } if (!args.comparisonGroups || !Array.isArray(args.comparisonGroups) || args.comparisonGroups.length < 2) { throw new Error('comparisonGroups parameter is required and must contain at least 2 tissue groups'); } // Get median expression for the gene const result = await this.apiClient.getMedianGeneExpression( [args.geneId], args.datasetId || 'gtex_v8' ); if (result.error) { return { content: [{ type: "text", text: `Error retrieving differential expression data: ${result.error}` }], isError: true }; } const expressions = result.data || []; if (expressions.length === 0) { return { content: [{ type: "text", text: `No expression data found for gene: ${args.geneId}` }] }; } const geneName = expressions[0].geneSymbol; // Group tissues by comparison groups (simplified - using tissue name matching) const groupData: { [group: string]: any[] } = {}; expressions.forEach(expr => { const tissueName = expr.tissueSiteDetailId.toLowerCase(); // Simple matching logic for common tissue groups for (const group of args.comparisonGroups) { const groupLower = group.toLowerCase(); if (tissueName.includes(groupLower) || (groupLower === 'brain' && tissueName.includes('brain')) || (groupLower === 'heart' && tissueName.includes('heart')) || (groupLower === 'muscle' && tissueName.includes('muscle')) || (groupLower === 'skin' && tissueName.includes('skin'))) { if (!groupData[group]) { groupData[group] = []; } groupData[group].push(expr); break; } } }); let output = `**Differential Expression Analysis**\n`; output += `Gene: **${geneName}** (${args.geneId})\n`; output += `Dataset: ${expressions[0].datasetId}\n`; output += `Comparison Groups: ${args.comparisonGroups.join(' vs ')}\n\n`; // Show results for each group const groupStats: { [group: string]: { mean: number, count: number, tissues: string[] } } = {}; Object.entries(groupData).forEach(([group, groupExpressions]) => { if (groupExpressions.length === 0) { output += `**${group}**: No matching tissues found\n`; return; } const values = groupExpressions.map(e => e.median); const mean = values.reduce((sum, val) => sum + val, 0) / values.length; const tissues = groupExpressions.map(e => this.getTissueDisplayName(e.tissueSiteDetailId)); groupStats[group] = { mean, count: values.length, tissues }; output += `**${group} (${values.length} tissues)**:\n`; output += ` • Mean expression: ${mean.toFixed(3)} TPM\n`; output += ` • Range: ${Math.min(...values).toFixed(3)} - ${Math.max(...values).toFixed(3)} TPM\n`; output += ` • Tissues: ${tissues.join(', ')}\n\n`; }); // Calculate fold changes between groups const groups = Object.keys(groupStats); if (groups.length >= 2) { output += `**Differential Analysis:**\n`; for (let i = 0; i < groups.length; i++) { for (let j = i + 1; j < groups.length; j++) { const group1 = groups[i]; const group2 = groups[j]; const foldChange = groupStats[group1].mean / groupStats[group2].mean; const logFC = Math.log2(foldChange); output += `• **${group1} vs ${group2}**:\n`; output += ` - Fold change: ${foldChange.toFixed(3)}x\n`; output += ` - Log2(FC): ${logFC.toFixed(3)}\n`; output += ` - Direction: ${foldChange > 1 ? `Higher in ${group1}` : `Higher in ${group2}`}\n`; } } } output += `\n**Note**: This is a simplified differential analysis using median values. `; output += `Proper differential expression requires statistical testing with sample-level data.\n`; return { content: [{ type: "text", text: output }] }; } - src/index.ts:193-214 (schema)Defines the tool schema including name, description, and input schema with required parameters gencodeId and comparisonGroups.
name: "get_differential_expression", description: "Get differential gene expression between tissue groups", inputSchema: { type: "object", properties: { gencodeId: { type: "string", description: "GENCODE gene ID (e.g., ENSG00000223972.5)" }, comparisonGroups: { type: "array", items: { type: "string" }, description: "Array of tissue groups to compare" }, datasetId: { type: "string", description: "GTEx dataset ID (default: gtex_v8)", default: "gtex_v8" } }, required: ["gencodeId", "comparisonGroups"] } - src/index.ts:663-669 (registration)Registers the tool by dispatching calls to the expressionHandlers.getDifferentialExpression method in the central tool request handler.
if (name === "get_differential_expression") { return await expressionHandlers.getDifferentialExpression({ gencodeId: args?.gencodeId, comparisonGroups: args?.comparisonGroups || [], datasetId: args?.datasetId }); }