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
TableJSON 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 }); }