[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71G7T81GS0XQ82MYT1SC29E":3,"skill-same:01M71G7T81GS0XQ82MYT1SC29E":75},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":54,"install":55,"resources":68},"01M71G7T81GS0XQ82MYT1SC29E","geo-database",null,"Access NCBI GEO for gene expression\u002Fgenomics data. Search\u002Fdownload microarray and RNA-seq datasets (GSE, GSM, GPL), retrieve SOFT\u002FMatrix files, for transcriptomics and expression analysis.","JSGforever\u002Fskillguard","JSGforever","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F85541948?v=4","01M71FQD3E132VMR5F4TAYX3YS","01M71FQD4DYW0XJ4XQ4YQH75Y9",2,"GPL-3.0","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__Microck--claude-scientific-skills\u002Fscientific-skills\u002Fgeo-database\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"geo database","geo","database","download","datasets","genomics","for","seq","data","matrix","NCBI","gene","transcriptomics","gene expression","RNA","analysis","access","files","expression","search","2026-11-10 10:12:30",false,"---\nname: geo-database\ndescription: \"Access NCBI GEO for gene expression\u002Fgenomics data. Search\u002Fdownload microarray and RNA-seq datasets (GSE, GSM, GPL), retrieve SOFT\u002FMatrix files, for transcriptomics and expression analysis.\"\n---\n\n# GEO Database\n\n## Overview\n\nThe Gene Expression Omnibus (GEO) is NCBI's public repository for high-throughput gene expression and functional genomics data. GEO contains over 264,000 studies with more than 8 million samples from both array-based and sequence-based experiments.\n\n## When to Use This Skill\n\nThis skill should be used when searching for gene expression datasets, retrieving experimental data, downloading raw and processed files, querying expression profiles, or integrating GEO data into computational analysis workflows.\n\n## Core Capabilities\n\n### 1. Understanding GEO Data Organization\n\nGEO organizes data hierarchically using different accession types:\n\n**Series (GSE):** A complete experiment with a set of related samples\n- Example: GSE123456\n- Contains experimental design, samples, and overall study information\n- Largest organizational unit in GEO\n- Current count: 264,928+ series\n\n**Sample (GSM):** A single experimental sample or biological replicate\n- Example: GSM987654\n- Contains individual sample data, protocols, and metadata\n- Linked to platforms and series\n- Current count: 8,068,632+ samples\n\n**Platform (GPL):** The microarray or sequencing platform used\n- Example: GPL570 (Affymetrix Human Genome U133 Plus 2.0 Array)\n- Describes the technology and probe\u002Ffeature annotations\n- Shared across multiple experiments\n- Current count: 27,739+ platforms\n\n**DataSet (GDS):** Curated collections with consistent formatting\n- Example: GDS5678\n- Experimentally-comparable samples organized by study design\n- Processed for differential analysis\n- Subset of GEO data (4,348 curated datasets)\n- Ideal for quick comparative analyses\n\n**Profiles:** Gene-specific expression data linked to sequence features\n- Queryable by gene name or annotation\n- Cross-references to Entrez Gene\n- Enables gene-centric searches across all studies\n\n### 2. Searching GEO Data\n\n**GEO DataSets Search:**\n\nSearch for studies by keywords, organism, or experimental conditions:\n\n```python\nfrom Bio import Entrez\n\n# Configure Entrez (required)\nEntrez.email = \"your.email@example.com\"\n\n# Search for datasets\ndef search_geo_datasets(query, retmax=20):\n    \"\"\"Search GEO DataSets database\"\"\"\n    handle = Entrez.esearch(\n        db=\"gds\",\n        term=query,\n        retmax=retmax,\n        usehistory=\"y\"\n    )\n    results = Entrez.read(handle)\n    handle.close()\n    return results\n\n# Example searches\nresults = search_geo_datasets(\"breast cancer[MeSH] AND Homo sapiens[Organism]\")\nprint(f\"Found {results['Count']} datasets\")\n\n# Search by specific platform\nresults = search_geo_datasets(\"GPL570[Accession]\")\n\n# Search by study type\nresults = search_geo_datasets(\"expression profiling by array[DataSet Type]\")\n```\n\n**GEO Profiles Search:**\n\nFind gene-specific expression patterns:\n\n```python\n# Search for gene expression profiles\ndef search_geo_profiles(gene_name, organism=\"Homo sapiens\", retmax=100):\n    \"\"\"Search GEO Profiles for a specific gene\"\"\"\n    query = f\"{gene_name}[Gene Name] AND {organism}[Organism]\"\n    handle = Entrez.esearch(\n        db=\"geoprofiles\",\n        term=query,\n        retmax=retmax\n    )\n    results = Entrez.read(handle)\n    handle.close()\n    return results\n\n# Find TP53 expression across studies\ntp53_results = search_geo_profiles(\"TP53\", organism=\"Homo sapiens\")\nprint(f\"Found {tp53_results['Count']} expression profiles for TP53\")\n```\n\n**Advanced Search Patterns:**\n\n```python\n# Combine multiple search terms\ndef advanced_geo_search(terms, operator=\"AND\"):\n    \"\"\"Build complex search queries\"\"\"\n    query = f\" {operator} \".join(terms)\n    return search_geo_datasets(query)\n\n# Find recent high-throughput studies\nsearch_terms = [\n    \"RNA-seq[DataSet Type]\",\n    \"Homo sapiens[Organism]\",\n    \"2024[Publication Date]\"\n]\nresults = advanced_geo_search(search_terms)\n\n# Search by author and condition\nsearch_terms = [\n    \"Smith[Author]\",\n    \"diabetes[Disease]\"\n]\nresults = advanced_geo_search(search_terms)\n```\n\n### 3. Retrieving GEO Data with GEOparse (Recommended)\n\n**GEOparse** is the primary Python library for accessing GEO data:\n\n**Installation:**\n```bash\nuv pip install GEOparse\n```\n\n**Basic Usage:**\n\n```python\nimport GEOparse\n\n# Download and parse a GEO Series\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Access series metadata\nprint(gse.metadata['title'])\nprint(gse.metadata['summary'])\nprint(gse.metadata['overall_design'])\n\n# Access sample information\nfor gsm_name, gsm in gse.gsms.items():\n    print(f\"Sample: {gsm_name}\")\n    print(f\"  Title: {gsm.metadata['title'][0]}\")\n    print(f\"  Source: {gsm.metadata['source_name_ch1'][0]}\")\n    print(f\"  Characteristics: {gsm.metadata.get('characteristics_ch1', [])}\")\n\n# Access platform information\nfor gpl_name, gpl in gse.gpls.items():\n    print(f\"Platform: {gpl_name}\")\n    print(f\"  Title: {gpl.metadata['title'][0]}\")\n    print(f\"  Organism: {gpl.metadata['organism'][0]}\")\n```\n\n**Working with Expression Data:**\n\n```python\nimport GEOparse\nimport pandas as pd\n\n# Get expression data from series\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Extract expression matrix\n# Method 1: From series matrix file (fastest)\nif hasattr(gse, 'pivot_samples'):\n    expression_df = gse.pivot_samples('VALUE')\n    print(expression_df.shape)  # genes x samples\n\n# Method 2: From individual samples\nexpression_data = {}\nfor gsm_name, gsm in gse.gsms.items():\n    if hasattr(gsm, 'table'):\n        expression_data[gsm_name] = gsm.table['VALUE']\n\nexpression_df = pd.DataFrame(expression_data)\nprint(f\"Expression matrix: {expression_df.shape}\")\n```\n\n**Accessing Supplementary Files:**\n\n```python\nimport GEOparse\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Download supplementary files\ngse.download_supplementary_files(\n    directory=\".\u002Fdata\u002FGSE123456_suppl\",\n    download_sra=False  # Set to True to download SRA files\n)\n\n# List available supplementary files\nfor gsm_name, gsm in gse.gsms.items():\n    if hasattr(gsm, 'supplementary_files'):\n        print(f\"Sample {gsm_name}:\")\n        for file_url in gsm.metadata.get('supplementary_file', []):\n            print(f\"  {file_url}\")\n```\n\n**Filtering and Subsetting Data:**\n\n```python\nimport GEOparse\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Filter samples by metadata\ncontrol_samples = [\n    gsm_name for gsm_name, gsm in gse.gsms.items()\n    if 'control' in gsm.metadata.get('title', [''])[0].lower()\n]\n\ntreatment_samples = [\n    gsm_name for gsm_name, gsm in gse.gsms.items()\n    if 'treatment' in gsm.metadata.get('title', [''])[0].lower()\n]\n\nprint(f\"Control samples: {len(control_samples)}\")\nprint(f\"Treatment samples: {len(treatment_samples)}\")\n\n# Extract subset expression matrix\nexpression_df = gse.pivot_samples('VALUE')\ncontrol_expr = expression_df[control_samples]\ntreatment_expr = expression_df[treatment_samples]\n```\n\n### 4. Using NCBI E-utilities for GEO Access\n\n**E-utilities** provide lower-level programmatic access to GEO metadata:\n\n**Basic E-utilities Workflow:**\n\n```python\nfrom Bio import Entrez\nimport time\n\nEntrez.email = \"your.email@example.com\"\n\n# Step 1: Search for GEO entries\ndef search_geo(query, db=\"gds\", retmax=100):\n    \"\"\"Search GEO using E-utilities\"\"\"\n    handle = Entrez.esearch(\n        db=db,\n        term=query,\n        retmax=retmax,\n        usehistory=\"y\"\n    )\n    results = Entrez.read(handle)\n    handle.close()\n    return results\n\n# Step 2: Fetch summaries\ndef fetch_geo_summaries(id_list, db=\"gds\"):\n    \"\"\"Fetch document summaries for GEO entries\"\"\"\n    ids = \",\".join(id_list)\n    handle = Entrez.esummary(db=db, id=ids)\n    summaries = Entrez.read(handle)\n    handle.close()\n    return summaries\n\n# Step 3: Fetch full records\ndef fetch_geo_records(id_list, db=\"gds\"):\n    \"\"\"Fetch full GEO records\"\"\"\n    ids = \",\".join(id_list)\n    handle = Entrez.efetch(db=db, id=ids, retmode=\"xml\")\n    records = Entrez.read(handle)\n    handle.close()\n    return records\n\n# Example workflow\nsearch_results = search_geo(\"breast cancer AND Homo sapiens\")\nid_list = search_results['IdList'][:5]\n\nsummaries = fetch_geo_summaries(id_list)\nfor summary in summaries:\n    print(f\"GDS: {summary.get('Accession', 'N\u002FA')}\")\n    print(f\"Title: {summary.get('title', 'N\u002FA')}\")\n    print(f\"Samples: {summary.get('n_samples', 'N\u002FA')}\")\n    print()\n```\n\n**Batch Processing with E-utilities:**\n\n```python\nfrom Bio import Entrez\nimport time\n\nEntrez.email = \"your.email@example.com\"\n\ndef batch_fetch_geo_metadata(accessions, batch_size=100):\n    \"\"\"Fetch metadata for multiple GEO accessions\"\"\"\n    results = {}\n\n    for i in range(0, len(accessions), batch_size):\n        batch = accessions[i:i + batch_size]\n\n        # Search for each accession\n        for accession in batch:\n            try:\n                query = f\"{accession}[Accession]\"\n                search_handle = Entrez.esearch(db=\"gds\", term=query)\n                search_results = Entrez.read(search_handle)\n                search_handle.close()\n\n                if search_results['IdList']:\n                    # Fetch summary\n                    summary_handle = Entrez.esummary(\n                        db=\"gds\",\n                        id=search_results['IdList'][0]\n                    )\n                    summary = Entrez.read(summary_handle)\n                    summary_handle.close()\n                    results[accession] = summary[0]\n\n                # Be polite to NCBI servers\n                time.sleep(0.34)  # Max 3 requests per second\n\n            except Exception as e:\n                print(f\"Error fetching {accession}: {e}\")\n\n    return results\n\n# Fetch metadata for multiple datasets\ngse_list = [\"GSE100001\", \"GSE100002\", \"GSE100003\"]\nmetadata = batch_fetch_geo_metadata(gse_list)\n```\n\n### 5. Direct FTP Access for Data Files\n\n**FTP URLs for GEO Data:**\n\nGEO data can be downloaded directly via FTP:\n\n```python\nimport ftplib\nimport os\n\ndef download_geo_ftp(accession, file_type=\"matrix\", dest_dir=\".\u002Fdata\"):\n    \"\"\"Download GEO files via FTP\"\"\"\n    # Construct FTP path based on accession type\n    if accession.startswith(\"GSE\"):\n        # Series files\n        gse_num = accession[3:]\n        base_num = gse_num[:-3] + \"nnn\"\n        ftp_path = f\"\u002Fgeo\u002Fseries\u002FGSE{base_num}\u002F{accession}\u002F\"\n\n        if file_type == \"matrix\":\n            filename = f\"{accession}_series_matrix.txt.gz\"\n        elif file_type == \"soft\":\n            filename = f\"{accession}_family.soft.gz\"\n        elif file_type == \"miniml\":\n            filename = f\"{accession}_family.xml.tgz\"\n\n    # Connect to FTP server\n    ftp = ftplib.FTP(\"ftp.ncbi.nlm.nih.gov\")\n    ftp.login()\n    ftp.cwd(ftp_path)\n\n    # Download file\n    os.makedirs(dest_dir, exist_ok=True)\n    local_file = os.path.join(dest_dir, filename)\n\n    with open(local_file, 'wb') as f:\n        ftp.retrbinary(f'RETR {filename}', f.write)\n\n    ftp.quit()\n    print(f\"Downloaded: {local_file}\")\n    return local_file\n\n# Download series matrix file\ndownload_geo_ftp(\"GSE123456\", file_type=\"matrix\")\n\n# Download SOFT format file\ndownload_geo_ftp(\"GSE123456\", file_type=\"soft\")\n```\n\n**Using wget or curl for Downloads:**\n\n```bash\n# Download series matrix file\nwget ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002Fseries\u002FGSE123nnn\u002FGSE123456\u002Fmatrix\u002FGSE123456_series_matrix.txt.gz\n\n# Download all supplementary files for a series\nwget -r -np -nd ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002Fseries\u002FGSE123nnn\u002FGSE123456\u002Fsuppl\u002F\n\n# Download SOFT format family file\nwget ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002Fseries\u002FGSE123nnn\u002FGSE123456\u002Fsoft\u002FGSE123456_family.soft.gz\n```\n\n### 6. Analyzing GEO Data\n\n**Quality Control and Preprocessing:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Load dataset\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\nexpression_df = gse.pivot_samples('VALUE')\n\n# Check for missing values\nprint(f\"Missing values: {expression_df.isnull().sum().sum()}\")\n\n# Log transformation (if needed)\nif expression_df.min().min() > 0:  # Check if already log-transformed\n    if expression_df.max().max() > 100:\n        expression_df = np.log2(expression_df + 1)\n        print(\"Applied log2 transformation\")\n\n# Distribution plots\nplt.figure(figsize=(12, 5))\n\nplt.subplot(1, 2, 1)\nexpression_df.plot.box(ax=plt.gca())\nplt.title(\"Expression Distribution per Sample\")\nplt.xticks(rotation=90)\n\nplt.subplot(1, 2, 2)\nexpression_df.mean(axis=1).hist(bins=50)\nplt.title(\"Gene Expression Distribution\")\nplt.xlabel(\"Average Expression\")\n\nplt.tight_layout()\nplt.savefig(\"geo_qc.png\", dpi=300, bbox_inches='tight')\n```\n\n**Differential Expression Analysis:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport numpy as np\nfrom scipy import stats\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\nexpression_df = gse.pivot_samples('VALUE')\n\n# Define sample groups\ncontrol_samples = [\"GSM1\", \"GSM2\", \"GSM3\"]\ntreatment_samples = [\"GSM4\", \"GSM5\", \"GSM6\"]\n\n# Calculate fold changes and p-values\nresults = []\nfor gene in expression_df.index:\n    control_expr = expression_df.loc[gene, control_samples]\n    treatment_expr = expression_df.loc[gene, treatment_samples]\n\n    # Calculate statistics\n    fold_change = treatment_expr.mean() - control_expr.mean()\n    t_stat, p_value = stats.ttest_ind(treatment_expr, control_expr)\n\n    results.append({\n        'gene': gene,\n        'log2_fold_change': fold_change,\n        'p_value': p_value,\n        'control_mean': control_expr.mean(),\n        'treatment_mean': treatment_expr.mean()\n    })\n\n# Create results DataFrame\nde_results = pd.DataFrame(results)\n\n# Multiple testing correction (Benjamini-Hochberg)\nfrom statsmodels.stats.multitest import multipletests\n_, de_results['q_value'], _, _ = multipletests(\n    de_results['p_value'],\n    method='fdr_bh'\n)\n\n# Filter significant genes\nsignificant_genes = de_results[\n    (de_results['q_value'] \u003C 0.05) &\n    (abs(de_results['log2_fold_change']) > 1)\n]\n\nprint(f\"Significant genes: {len(significant_genes)}\")\nsignificant_genes.to_csv(\"de_results.csv\", index=False)\n```\n\n**Correlation and Clustering Analysis:**\n\n```python\nimport GEOparse\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom scipy.cluster import hierarchy\nfrom scipy.spatial.distance import pdist\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\nexpression_df = gse.pivot_samples('VALUE')\n\n# Sample correlation heatmap\nsample_corr = expression_df.corr()\n\nplt.figure(figsize=(10, 8))\nsns.heatmap(sample_corr, cmap='coolwarm', center=0,\n            square=True, linewidths=0.5)\nplt.title(\"Sample Correlation Matrix\")\nplt.tight_layout()\nplt.savefig(\"sample_correlation.png\", dpi=300, bbox_inches='tight')\n\n# Hierarchical clustering\ndistances = pdist(expression_df.T, metric='correlation')\nlinkage = hierarchy.linkage(distances, method='average')\n\nplt.figure(figsize=(12, 6))\nhierarchy.dendrogram(linkage, labels=expression_df.columns)\nplt.title(\"Hierarchical Clustering of Samples\")\nplt.xlabel(\"Samples\")\nplt.ylabel(\"Distance\")\nplt.xticks(rotation=90)\nplt.tight_layout()\nplt.savefig(\"sample_clustering.png\", dpi=300, bbox_inches='tight')\n```\n\n### 7. Batch Processing Multiple Datasets\n\n**Download and Process Multiple Series:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport os\n\ndef batch_download_geo(gse_list, destdir=\".\u002Fgeo_data\"):\n    \"\"\"Download multiple GEO series\"\"\"\n    results = {}\n\n    for gse_id in gse_list:\n        try:\n            print(f\"Processing {gse_id}...\")\n            gse = GEOparse.get_GEO(geo=gse_id, destdir=destdir)\n\n            # Extract key information\n            results[gse_id] = {\n                'title': gse.metadata.get('title', ['N\u002FA'])[0],\n                'organism': gse.metadata.get('organism', ['N\u002FA'])[0],\n                'platform': list(gse.gpls.keys())[0] if gse.gpls else 'N\u002FA',\n                'num_samples': len(gse.gsms),\n                'submission_date': gse.metadata.get('submission_date', ['N\u002FA'])[0]\n            }\n\n            # Save expression data\n            if hasattr(gse, 'pivot_samples'):\n                expr_df = gse.pivot_samples('VALUE')\n                expr_df.to_csv(f\"{destdir}\u002F{gse_id}_expression.csv\")\n                results[gse_id]['num_genes'] = len(expr_df)\n\n        except Exception as e:\n            print(f\"Error processing {gse_id}: {e}\")\n            results[gse_id] = {'error': str(e)}\n\n    # Save summary\n    summary_df = pd.DataFrame(results).T\n    summary_df.to_csv(f\"{destdir}\u002Fbatch_summary.csv\")\n\n    return results\n\n# Process multiple datasets\ngse_list = [\"GSE100001\", \"GSE100002\", \"GSE100003\"]\nresults = batch_download_geo(gse_list)\n```\n\n**Meta-Analysis Across Studies:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport numpy as np\n\ndef meta_analysis_geo(gse_list, gene_of_interest):\n    \"\"\"Perform meta-analysis of gene expression across studies\"\"\"\n    results = []\n\n    for gse_id in gse_list:\n        try:\n            gse = GEOparse.get_GEO(geo=gse_id, destdir=\".\u002Fdata\")\n\n            # Get platform annotation\n            gpl = list(gse.gpls.values())[0]\n\n            # Find gene in platform\n            if hasattr(gpl, 'table'):\n                gene_probes = gpl.table[\n                    gpl.table['Gene Symbol'].str.contains(\n                        gene_of_interest,\n                        case=False,\n                        na=False\n                    )\n                ]\n\n                if not gene_probes.empty:\n                    expr_df = gse.pivot_samples('VALUE')\n\n                    for probe_id in gene_probes['ID']:\n                        if probe_id in expr_df.index:\n                            expr_values = expr_df.loc[probe_id]\n\n                            results.append({\n                                'study': gse_id,\n                                'probe': probe_id,\n                                'mean_expression': expr_values.mean(),\n                                'std_expression': expr_values.std(),\n                                'num_samples': len(expr_values)\n                            })\n\n        except Exception as e:\n            print(f\"Error in {gse_id}: {e}\")\n\n    return pd.DataFrame(results)\n\n# Meta-analysis for TP53\ngse_studies = [\"GSE100001\", \"GSE100002\", \"GSE100003\"]\nmeta_results = meta_analysis_geo(gse_studies, \"TP53\")\nprint(meta_results)\n```\n\n## Installation and Setup\n\n### Python Libraries\n\n```bash\n# Primary GEO access library (recommended)\nuv pip install GEOparse\n\n# For E-utilities and programmatic NCBI access\nuv pip install biopython\n\n# For data analysis\nuv pip install pandas numpy scipy\n\n# For visualization\nuv pip install matplotlib seaborn\n\n# For statistical analysis\nuv pip install statsmodels scikit-learn\n```\n\n### Configuration\n\nSet up NCBI E-utilities access:\n\n```python\nfrom Bio import Entrez\n\n# Always set your email (required by NCBI)\nEntrez.email = \"your.email@example.com\"\n\n# Optional: Set API key for increased rate limits\n# Get your API key from: https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Faccount\u002F\nEntrez.api_key = \"your_api_key_here\"\n\n# With API key: 10 requests\u002Fsecond\n# Without API key: 3 requests\u002Fsecond\n```\n\n## Common Use Cases\n\n### Transcriptomics Research\n- Download gene expression data for specific conditions\n- Compare expression profiles across studies\n- Identify differentially expressed genes\n- Perform meta-analyses across multiple datasets\n\n### Drug Response Studies\n- Analyze gene expression changes after drug treatment\n- Identify biomarkers for drug response\n- Compare drug effects across cell lines or patients\n- Build predictive models for drug sensitivity\n\n### Disease Biology\n- Study gene expression in disease vs. normal tissues\n- Identify disease-associated expression signatures\n- Compare patient subgroups and disease stages\n- Correlate expression with clinical outcomes\n\n### Biomarker Discovery\n- Screen for diagnostic or prognostic markers\n- Validate biomarkers across independent cohorts\n- Compare marker performance across platforms\n- Integrate expression with clinical data\n\n## Key Concepts\n\n**SOFT (Simple Omnibus Format in Text):** GEO's primary text-based format containing metadata and data tables. Easily parsed by GEOparse.\n\n**MINiML (MIAME Notation in Markup Language):** XML format for GEO data, used for programmatic access and data exchange.\n\n**Series Matrix:** Tab-delimited expression matrix with samples as columns and genes\u002Fprobes as rows. Fastest format for getting expression data.\n\n**MIAME Compliance:** Minimum Information About a Microarray Experiment - standardized annotation that GEO enforces for all submissions.\n\n**Expression Value Types:** Different types of expression measurements (raw signal, normalized, log-transformed). Always check platform and processing methods.\n\n**Platform Annotation:** Maps probe\u002Ffeature IDs to genes. Essential for biological interpretation of expression data.\n\n## GEO2R Web Tool\n\nFor quick analysis without coding, use GEO2R:\n\n- Web-based statistical analysis tool integrated into GEO\n- Accessible at: https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002Fgeo2r\u002F?acc=GSExxxxx\n- Performs differential expression analysis\n- Generates R scripts for reproducibility\n- Useful for exploratory analysis before downloading data\n\n## Rate Limiting and Best Practices\n\n**NCBI E-utilities Rate Limits:**\n- Without API key: 3 requests per second\n- With API key: 10 requests per second\n- Implement delays between requests: `time.sleep(0.34)` (no API key) or `time.sleep(0.1)` (with API key)\n\n**FTP Access:**\n- No rate limits for FTP downloads\n- Preferred method for bulk downloads\n- Can download entire directories with wget -r\n\n**GEOparse Caching:**\n- GEOparse automatically caches downloaded files in destdir\n- Subsequent calls use cached data\n- Clean cache periodically to save disk space\n\n**Optimal Practices:**\n- Use GEOparse for series-level access (easiest)\n- Use E-utilities for metadata searching and batch queries\n- Use FTP for direct file downloads and bulk operations\n- Cache data locally to avoid repeated downloads\n- Always set Entrez.email when using Biopython\n\n## Resources\n\n### references\u002Fgeo_reference.md\n\nComprehensive reference documentation covering:\n- Detailed E-utilities API specifications and endpoints\n- Complete SOFT and MINiML file format documentation\n- Advanced GEOparse usage patterns and examples\n- FTP directory structure and file naming conventions\n- Data processing pipelines and normalization methods\n- Troubleshooting common issues and error handling\n- Platform-specific considerations and quirks\n\nConsult this reference for in-depth technical details, complex query patterns, or when working with uncommon data formats.\n\n## Important Notes\n\n### Data Quality Considerations\n\n- GEO accepts user-submitted data with varying quality standards\n- Always check platform annotation and processing methods\n- Verify sample metadata and experimental design\n- Be cautious with batch effects across studies\n- Consider reprocessing raw data for consistency\n\n### File Size Warnings\n\n- Series matrix files can be large (>1 GB for large studies)\n- Supplementary files (e.g., CEL files) can be very large\n- Plan for adequate disk space before downloading\n- Consider downloading samples incrementally\n\n### Data Usage and Citation\n\n- GEO data is freely available for research use\n- Always cite original studies when using GEO data\n- Cite GEO database: Barrett et al. (2013) Nucleic Acids Research\n- Check individual dataset usage restrictions (if any)\n- Follow NCBI guidelines for programmatic access\n\n### Common Pitfalls\n\n- Different platforms use different probe IDs (requires annotation mapping)\n- Expression values may be raw, normalized, or log-transformed (check metadata)\n- Sample metadata can be inconsistently formatted across studies\n- Not all series have series matrix files (older submissions)\n- Platform annotations may be outdated (genes renamed, IDs deprecated)\n\n## Additional Resources\n\n- **GEO Website:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002F\n- **GEO Submission Guidelines:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002Finfo\u002Fsubmission.html\n- **GEOparse Documentation:** https:\u002F\u002Fgeoparse.readthedocs.io\u002F\n- **E-utilities Documentation:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fbooks\u002FNBK25501\u002F\n- **GEO FTP Site:** ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002F\n- **GEO2R Tool:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002Fgeo2r\u002F\n- **NCBI API Keys:** https:\u002F\u002Fncbiinsights.ncbi.nlm.nih.gov\u002F2017\u002F11\u002F02\u002Fnew-api-keys-for-the-e-utilities\u002F\n- **Biopython Tutorial:** https:\u002F\u002Fbiopython.org\u002FDIST\u002Fdocs\u002Ftutorial\u002FTutorial.html\n","# GEO Database\n\n## Overview\n\nThe Gene Expression Omnibus (GEO) is NCBI's public repository for high-throughput gene expression and functional genomics data. GEO contains over 264,000 studies with more than 8 million samples from both array-based and sequence-based experiments.\n\n## When to Use This Skill\n\nThis skill should be used when searching for gene expression datasets, retrieving experimental data, downloading raw and processed files, querying expression profiles, or integrating GEO data into computational analysis workflows.\n\n## Core Capabilities\n\n### 1. Understanding GEO Data Organization\n\nGEO organizes data hierarchically using different accession types:\n\n**Series (GSE):** A complete experiment with a set of related samples\n- Example: GSE123456\n- Contains experimental design, samples, and overall study information\n- Largest organizational unit in GEO\n- Current count: 264,928+ series\n\n**Sample (GSM):** A single experimental sample or biological replicate\n- Example: GSM987654\n- Contains individual sample data, protocols, and metadata\n- Linked to platforms and series\n- Current count: 8,068,632+ samples\n\n**Platform (GPL):** The microarray or sequencing platform used\n- Example: GPL570 (Affymetrix Human Genome U133 Plus 2.0 Array)\n- Describes the technology and probe\u002Ffeature annotations\n- Shared across multiple experiments\n- Current count: 27,739+ platforms\n\n**DataSet (GDS):** Curated collections with consistent formatting\n- Example: GDS5678\n- Experimentally-comparable samples organized by study design\n- Processed for differential analysis\n- Subset of GEO data (4,348 curated datasets)\n- Ideal for quick comparative analyses\n\n**Profiles:** Gene-specific expression data linked to sequence features\n- Queryable by gene name or annotation\n- Cross-references to Entrez Gene\n- Enables gene-centric searches across all studies\n\n### 2. Searching GEO Data\n\n**GEO DataSets Search:**\n\nSearch for studies by keywords, organism, or experimental conditions:\n\n```python\nfrom Bio import Entrez\n\n# Configure Entrez (required)\nEntrez.email = \"your.email@example.com\"\n\n# Search for datasets\ndef search_geo_datasets(query, retmax=20):\n    \"\"\"Search GEO DataSets database\"\"\"\n    handle = Entrez.esearch(\n        db=\"gds\",\n        term=query,\n        retmax=retmax,\n        usehistory=\"y\"\n    )\n    results = Entrez.read(handle)\n    handle.close()\n    return results\n\n# Example searches\nresults = search_geo_datasets(\"breast cancer[MeSH] AND Homo sapiens[Organism]\")\nprint(f\"Found {results['Count']} datasets\")\n\n# Search by specific platform\nresults = search_geo_datasets(\"GPL570[Accession]\")\n\n# Search by study type\nresults = search_geo_datasets(\"expression profiling by array[DataSet Type]\")\n```\n\n**GEO Profiles Search:**\n\nFind gene-specific expression patterns:\n\n```python\n# Search for gene expression profiles\ndef search_geo_profiles(gene_name, organism=\"Homo sapiens\", retmax=100):\n    \"\"\"Search GEO Profiles for a specific gene\"\"\"\n    query = f\"{gene_name}[Gene Name] AND {organism}[Organism]\"\n    handle = Entrez.esearch(\n        db=\"geoprofiles\",\n        term=query,\n        retmax=retmax\n    )\n    results = Entrez.read(handle)\n    handle.close()\n    return results\n\n# Find TP53 expression across studies\ntp53_results = search_geo_profiles(\"TP53\", organism=\"Homo sapiens\")\nprint(f\"Found {tp53_results['Count']} expression profiles for TP53\")\n```\n\n**Advanced Search Patterns:**\n\n```python\n# Combine multiple search terms\ndef advanced_geo_search(terms, operator=\"AND\"):\n    \"\"\"Build complex search queries\"\"\"\n    query = f\" {operator} \".join(terms)\n    return search_geo_datasets(query)\n\n# Find recent high-throughput studies\nsearch_terms = [\n    \"RNA-seq[DataSet Type]\",\n    \"Homo sapiens[Organism]\",\n    \"2024[Publication Date]\"\n]\nresults = advanced_geo_search(search_terms)\n\n# Search by author and condition\nsearch_terms = [\n    \"Smith[Author]\",\n    \"diabetes[Disease]\"\n]\nresults = advanced_geo_search(search_terms)\n```\n\n### 3. Retrieving GEO Data with GEOparse (Recommended)\n\n**GEOparse** is the primary Python library for accessing GEO data:\n\n**Installation:**\n```bash\nuv pip install GEOparse\n```\n\n**Basic Usage:**\n\n```python\nimport GEOparse\n\n# Download and parse a GEO Series\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Access series metadata\nprint(gse.metadata['title'])\nprint(gse.metadata['summary'])\nprint(gse.metadata['overall_design'])\n\n# Access sample information\nfor gsm_name, gsm in gse.gsms.items():\n    print(f\"Sample: {gsm_name}\")\n    print(f\"  Title: {gsm.metadata['title'][0]}\")\n    print(f\"  Source: {gsm.metadata['source_name_ch1'][0]}\")\n    print(f\"  Characteristics: {gsm.metadata.get('characteristics_ch1', [])}\")\n\n# Access platform information\nfor gpl_name, gpl in gse.gpls.items():\n    print(f\"Platform: {gpl_name}\")\n    print(f\"  Title: {gpl.metadata['title'][0]}\")\n    print(f\"  Organism: {gpl.metadata['organism'][0]}\")\n```\n\n**Working with Expression Data:**\n\n```python\nimport GEOparse\nimport pandas as pd\n\n# Get expression data from series\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Extract expression matrix\n# Method 1: From series matrix file (fastest)\nif hasattr(gse, 'pivot_samples'):\n    expression_df = gse.pivot_samples('VALUE')\n    print(expression_df.shape)  # genes x samples\n\n# Method 2: From individual samples\nexpression_data = {}\nfor gsm_name, gsm in gse.gsms.items():\n    if hasattr(gsm, 'table'):\n        expression_data[gsm_name] = gsm.table['VALUE']\n\nexpression_df = pd.DataFrame(expression_data)\nprint(f\"Expression matrix: {expression_df.shape}\")\n```\n\n**Accessing Supplementary Files:**\n\n```python\nimport GEOparse\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Download supplementary files\ngse.download_supplementary_files(\n    directory=\".\u002Fdata\u002FGSE123456_suppl\",\n    download_sra=False  # Set to True to download SRA files\n)\n\n# List available supplementary files\nfor gsm_name, gsm in gse.gsms.items():\n    if hasattr(gsm, 'supplementary_files'):\n        print(f\"Sample {gsm_name}:\")\n        for file_url in gsm.metadata.get('supplementary_file', []):\n            print(f\"  {file_url}\")\n```\n\n**Filtering and Subsetting Data:**\n\n```python\nimport GEOparse\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\n\n# Filter samples by metadata\ncontrol_samples = [\n    gsm_name for gsm_name, gsm in gse.gsms.items()\n    if 'control' in gsm.metadata.get('title', [''])[0].lower()\n]\n\ntreatment_samples = [\n    gsm_name for gsm_name, gsm in gse.gsms.items()\n    if 'treatment' in gsm.metadata.get('title', [''])[0].lower()\n]\n\nprint(f\"Control samples: {len(control_samples)}\")\nprint(f\"Treatment samples: {len(treatment_samples)}\")\n\n# Extract subset expression matrix\nexpression_df = gse.pivot_samples('VALUE')\ncontrol_expr = expression_df[control_samples]\ntreatment_expr = expression_df[treatment_samples]\n```\n\n### 4. Using NCBI E-utilities for GEO Access\n\n**E-utilities** provide lower-level programmatic access to GEO metadata:\n\n**Basic E-utilities Workflow:**\n\n```python\nfrom Bio import Entrez\nimport time\n\nEntrez.email = \"your.email@example.com\"\n\n# Step 1: Search for GEO entries\ndef search_geo(query, db=\"gds\", retmax=100):\n    \"\"\"Search GEO using E-utilities\"\"\"\n    handle = Entrez.esearch(\n        db=db,\n        term=query,\n        retmax=retmax,\n        usehistory=\"y\"\n    )\n    results = Entrez.read(handle)\n    handle.close()\n    return results\n\n# Step 2: Fetch summaries\ndef fetch_geo_summaries(id_list, db=\"gds\"):\n    \"\"\"Fetch document summaries for GEO entries\"\"\"\n    ids = \",\".join(id_list)\n    handle = Entrez.esummary(db=db, id=ids)\n    summaries = Entrez.read(handle)\n    handle.close()\n    return summaries\n\n# Step 3: Fetch full records\ndef fetch_geo_records(id_list, db=\"gds\"):\n    \"\"\"Fetch full GEO records\"\"\"\n    ids = \",\".join(id_list)\n    handle = Entrez.efetch(db=db, id=ids, retmode=\"xml\")\n    records = Entrez.read(handle)\n    handle.close()\n    return records\n\n# Example workflow\nsearch_results = search_geo(\"breast cancer AND Homo sapiens\")\nid_list = search_results['IdList'][:5]\n\nsummaries = fetch_geo_summaries(id_list)\nfor summary in summaries:\n    print(f\"GDS: {summary.get('Accession', 'N\u002FA')}\")\n    print(f\"Title: {summary.get('title', 'N\u002FA')}\")\n    print(f\"Samples: {summary.get('n_samples', 'N\u002FA')}\")\n    print()\n```\n\n**Batch Processing with E-utilities:**\n\n```python\nfrom Bio import Entrez\nimport time\n\nEntrez.email = \"your.email@example.com\"\n\ndef batch_fetch_geo_metadata(accessions, batch_size=100):\n    \"\"\"Fetch metadata for multiple GEO accessions\"\"\"\n    results = {}\n\n    for i in range(0, len(accessions), batch_size):\n        batch = accessions[i:i + batch_size]\n\n        # Search for each accession\n        for accession in batch:\n            try:\n                query = f\"{accession}[Accession]\"\n                search_handle = Entrez.esearch(db=\"gds\", term=query)\n                search_results = Entrez.read(search_handle)\n                search_handle.close()\n\n                if search_results['IdList']:\n                    # Fetch summary\n                    summary_handle = Entrez.esummary(\n                        db=\"gds\",\n                        id=search_results['IdList'][0]\n                    )\n                    summary = Entrez.read(summary_handle)\n                    summary_handle.close()\n                    results[accession] = summary[0]\n\n                # Be polite to NCBI servers\n                time.sleep(0.34)  # Max 3 requests per second\n\n            except Exception as e:\n                print(f\"Error fetching {accession}: {e}\")\n\n    return results\n\n# Fetch metadata for multiple datasets\ngse_list = [\"GSE100001\", \"GSE100002\", \"GSE100003\"]\nmetadata = batch_fetch_geo_metadata(gse_list)\n```\n\n### 5. Direct FTP Access for Data Files\n\n**FTP URLs for GEO Data:**\n\nGEO data can be downloaded directly via FTP:\n\n```python\nimport ftplib\nimport os\n\ndef download_geo_ftp(accession, file_type=\"matrix\", dest_dir=\".\u002Fdata\"):\n    \"\"\"Download GEO files via FTP\"\"\"\n    # Construct FTP path based on accession type\n    if accession.startswith(\"GSE\"):\n        # Series files\n        gse_num = accession[3:]\n        base_num = gse_num[:-3] + \"nnn\"\n        ftp_path = f\"\u002Fgeo\u002Fseries\u002FGSE{base_num}\u002F{accession}\u002F\"\n\n        if file_type == \"matrix\":\n            filename = f\"{accession}_series_matrix.txt.gz\"\n        elif file_type == \"soft\":\n            filename = f\"{accession}_family.soft.gz\"\n        elif file_type == \"miniml\":\n            filename = f\"{accession}_family.xml.tgz\"\n\n    # Connect to FTP server\n    ftp = ftplib.FTP(\"ftp.ncbi.nlm.nih.gov\")\n    ftp.login()\n    ftp.cwd(ftp_path)\n\n    # Download file\n    os.makedirs(dest_dir, exist_ok=True)\n    local_file = os.path.join(dest_dir, filename)\n\n    with open(local_file, 'wb') as f:\n        ftp.retrbinary(f'RETR {filename}', f.write)\n\n    ftp.quit()\n    print(f\"Downloaded: {local_file}\")\n    return local_file\n\n# Download series matrix file\ndownload_geo_ftp(\"GSE123456\", file_type=\"matrix\")\n\n# Download SOFT format file\ndownload_geo_ftp(\"GSE123456\", file_type=\"soft\")\n```\n\n**Using wget or curl for Downloads:**\n\n```bash\n# Download series matrix file\nwget ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002Fseries\u002FGSE123nnn\u002FGSE123456\u002Fmatrix\u002FGSE123456_series_matrix.txt.gz\n\n# Download all supplementary files for a series\nwget -r -np -nd ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002Fseries\u002FGSE123nnn\u002FGSE123456\u002Fsuppl\u002F\n\n# Download SOFT format family file\nwget ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002Fseries\u002FGSE123nnn\u002FGSE123456\u002Fsoft\u002FGSE123456_family.soft.gz\n```\n\n### 6. Analyzing GEO Data\n\n**Quality Control and Preprocessing:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Load dataset\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\nexpression_df = gse.pivot_samples('VALUE')\n\n# Check for missing values\nprint(f\"Missing values: {expression_df.isnull().sum().sum()}\")\n\n# Log transformation (if needed)\nif expression_df.min().min() > 0:  # Check if already log-transformed\n    if expression_df.max().max() > 100:\n        expression_df = np.log2(expression_df + 1)\n        print(\"Applied log2 transformation\")\n\n# Distribution plots\nplt.figure(figsize=(12, 5))\n\nplt.subplot(1, 2, 1)\nexpression_df.plot.box(ax=plt.gca())\nplt.title(\"Expression Distribution per Sample\")\nplt.xticks(rotation=90)\n\nplt.subplot(1, 2, 2)\nexpression_df.mean(axis=1).hist(bins=50)\nplt.title(\"Gene Expression Distribution\")\nplt.xlabel(\"Average Expression\")\n\nplt.tight_layout()\nplt.savefig(\"geo_qc.png\", dpi=300, bbox_inches='tight')\n```\n\n**Differential Expression Analysis:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport numpy as np\nfrom scipy import stats\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\nexpression_df = gse.pivot_samples('VALUE')\n\n# Define sample groups\ncontrol_samples = [\"GSM1\", \"GSM2\", \"GSM3\"]\ntreatment_samples = [\"GSM4\", \"GSM5\", \"GSM6\"]\n\n# Calculate fold changes and p-values\nresults = []\nfor gene in expression_df.index:\n    control_expr = expression_df.loc[gene, control_samples]\n    treatment_expr = expression_df.loc[gene, treatment_samples]\n\n    # Calculate statistics\n    fold_change = treatment_expr.mean() - control_expr.mean()\n    t_stat, p_value = stats.ttest_ind(treatment_expr, control_expr)\n\n    results.append({\n        'gene': gene,\n        'log2_fold_change': fold_change,\n        'p_value': p_value,\n        'control_mean': control_expr.mean(),\n        'treatment_mean': treatment_expr.mean()\n    })\n\n# Create results DataFrame\nde_results = pd.DataFrame(results)\n\n# Multiple testing correction (Benjamini-Hochberg)\nfrom statsmodels.stats.multitest import multipletests\n_, de_results['q_value'], _, _ = multipletests(\n    de_results['p_value'],\n    method='fdr_bh'\n)\n\n# Filter significant genes\nsignificant_genes = de_results[\n    (de_results['q_value'] \u003C 0.05) &\n    (abs(de_results['log2_fold_change']) > 1)\n]\n\nprint(f\"Significant genes: {len(significant_genes)}\")\nsignificant_genes.to_csv(\"de_results.csv\", index=False)\n```\n\n**Correlation and Clustering Analysis:**\n\n```python\nimport GEOparse\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom scipy.cluster import hierarchy\nfrom scipy.spatial.distance import pdist\n\ngse = GEOparse.get_GEO(geo=\"GSE123456\", destdir=\".\u002Fdata\")\nexpression_df = gse.pivot_samples('VALUE')\n\n# Sample correlation heatmap\nsample_corr = expression_df.corr()\n\nplt.figure(figsize=(10, 8))\nsns.heatmap(sample_corr, cmap='coolwarm', center=0,\n            square=True, linewidths=0.5)\nplt.title(\"Sample Correlation Matrix\")\nplt.tight_layout()\nplt.savefig(\"sample_correlation.png\", dpi=300, bbox_inches='tight')\n\n# Hierarchical clustering\ndistances = pdist(expression_df.T, metric='correlation')\nlinkage = hierarchy.linkage(distances, method='average')\n\nplt.figure(figsize=(12, 6))\nhierarchy.dendrogram(linkage, labels=expression_df.columns)\nplt.title(\"Hierarchical Clustering of Samples\")\nplt.xlabel(\"Samples\")\nplt.ylabel(\"Distance\")\nplt.xticks(rotation=90)\nplt.tight_layout()\nplt.savefig(\"sample_clustering.png\", dpi=300, bbox_inches='tight')\n```\n\n### 7. Batch Processing Multiple Datasets\n\n**Download and Process Multiple Series:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport os\n\ndef batch_download_geo(gse_list, destdir=\".\u002Fgeo_data\"):\n    \"\"\"Download multiple GEO series\"\"\"\n    results = {}\n\n    for gse_id in gse_list:\n        try:\n            print(f\"Processing {gse_id}...\")\n            gse = GEOparse.get_GEO(geo=gse_id, destdir=destdir)\n\n            # Extract key information\n            results[gse_id] = {\n                'title': gse.metadata.get('title', ['N\u002FA'])[0],\n                'organism': gse.metadata.get('organism', ['N\u002FA'])[0],\n                'platform': list(gse.gpls.keys())[0] if gse.gpls else 'N\u002FA',\n                'num_samples': len(gse.gsms),\n                'submission_date': gse.metadata.get('submission_date', ['N\u002FA'])[0]\n            }\n\n            # Save expression data\n            if hasattr(gse, 'pivot_samples'):\n                expr_df = gse.pivot_samples('VALUE')\n                expr_df.to_csv(f\"{destdir}\u002F{gse_id}_expression.csv\")\n                results[gse_id]['num_genes'] = len(expr_df)\n\n        except Exception as e:\n            print(f\"Error processing {gse_id}: {e}\")\n            results[gse_id] = {'error': str(e)}\n\n    # Save summary\n    summary_df = pd.DataFrame(results).T\n    summary_df.to_csv(f\"{destdir}\u002Fbatch_summary.csv\")\n\n    return results\n\n# Process multiple datasets\ngse_list = [\"GSE100001\", \"GSE100002\", \"GSE100003\"]\nresults = batch_download_geo(gse_list)\n```\n\n**Meta-Analysis Across Studies:**\n\n```python\nimport GEOparse\nimport pandas as pd\nimport numpy as np\n\ndef meta_analysis_geo(gse_list, gene_of_interest):\n    \"\"\"Perform meta-analysis of gene expression across studies\"\"\"\n    results = []\n\n    for gse_id in gse_list:\n        try:\n            gse = GEOparse.get_GEO(geo=gse_id, destdir=\".\u002Fdata\")\n\n            # Get platform annotation\n            gpl = list(gse.gpls.values())[0]\n\n            # Find gene in platform\n            if hasattr(gpl, 'table'):\n                gene_probes = gpl.table[\n                    gpl.table['Gene Symbol'].str.contains(\n                        gene_of_interest,\n                        case=False,\n                        na=False\n                    )\n                ]\n\n                if not gene_probes.empty:\n                    expr_df = gse.pivot_samples('VALUE')\n\n                    for probe_id in gene_probes['ID']:\n                        if probe_id in expr_df.index:\n                            expr_values = expr_df.loc[probe_id]\n\n                            results.append({\n                                'study': gse_id,\n                                'probe': probe_id,\n                                'mean_expression': expr_values.mean(),\n                                'std_expression': expr_values.std(),\n                                'num_samples': len(expr_values)\n                            })\n\n        except Exception as e:\n            print(f\"Error in {gse_id}: {e}\")\n\n    return pd.DataFrame(results)\n\n# Meta-analysis for TP53\ngse_studies = [\"GSE100001\", \"GSE100002\", \"GSE100003\"]\nmeta_results = meta_analysis_geo(gse_studies, \"TP53\")\nprint(meta_results)\n```\n\n## Installation and Setup\n\n### Python Libraries\n\n```bash\n# Primary GEO access library (recommended)\nuv pip install GEOparse\n\n# For E-utilities and programmatic NCBI access\nuv pip install biopython\n\n# For data analysis\nuv pip install pandas numpy scipy\n\n# For visualization\nuv pip install matplotlib seaborn\n\n# For statistical analysis\nuv pip install statsmodels scikit-learn\n```\n\n### Configuration\n\nSet up NCBI E-utilities access:\n\n```python\nfrom Bio import Entrez\n\n# Always set your email (required by NCBI)\nEntrez.email = \"your.email@example.com\"\n\n# Optional: Set API key for increased rate limits\n# Get your API key from: https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Faccount\u002F\nEntrez.api_key = \"your_api_key_here\"\n\n# With API key: 10 requests\u002Fsecond\n# Without API key: 3 requests\u002Fsecond\n```\n\n## Common Use Cases\n\n### Transcriptomics Research\n- Download gene expression data for specific conditions\n- Compare expression profiles across studies\n- Identify differentially expressed genes\n- Perform meta-analyses across multiple datasets\n\n### Drug Response Studies\n- Analyze gene expression changes after drug treatment\n- Identify biomarkers for drug response\n- Compare drug effects across cell lines or patients\n- Build predictive models for drug sensitivity\n\n### Disease Biology\n- Study gene expression in disease vs. normal tissues\n- Identify disease-associated expression signatures\n- Compare patient subgroups and disease stages\n- Correlate expression with clinical outcomes\n\n### Biomarker Discovery\n- Screen for diagnostic or prognostic markers\n- Validate biomarkers across independent cohorts\n- Compare marker performance across platforms\n- Integrate expression with clinical data\n\n## Key Concepts\n\n**SOFT (Simple Omnibus Format in Text):** GEO's primary text-based format containing metadata and data tables. Easily parsed by GEOparse.\n\n**MINiML (MIAME Notation in Markup Language):** XML format for GEO data, used for programmatic access and data exchange.\n\n**Series Matrix:** Tab-delimited expression matrix with samples as columns and genes\u002Fprobes as rows. Fastest format for getting expression data.\n\n**MIAME Compliance:** Minimum Information About a Microarray Experiment - standardized annotation that GEO enforces for all submissions.\n\n**Expression Value Types:** Different types of expression measurements (raw signal, normalized, log-transformed). Always check platform and processing methods.\n\n**Platform Annotation:** Maps probe\u002Ffeature IDs to genes. Essential for biological interpretation of expression data.\n\n## GEO2R Web Tool\n\nFor quick analysis without coding, use GEO2R:\n\n- Web-based statistical analysis tool integrated into GEO\n- Accessible at: https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002Fgeo2r\u002F?acc=GSExxxxx\n- Performs differential expression analysis\n- Generates R scripts for reproducibility\n- Useful for exploratory analysis before downloading data\n\n## Rate Limiting and Best Practices\n\n**NCBI E-utilities Rate Limits:**\n- Without API key: 3 requests per second\n- With API key: 10 requests per second\n- Implement delays between requests: `time.sleep(0.34)` (no API key) or `time.sleep(0.1)` (with API key)\n\n**FTP Access:**\n- No rate limits for FTP downloads\n- Preferred method for bulk downloads\n- Can download entire directories with wget -r\n\n**GEOparse Caching:**\n- GEOparse automatically caches downloaded files in destdir\n- Subsequent calls use cached data\n- Clean cache periodically to save disk space\n\n**Optimal Practices:**\n- Use GEOparse for series-level access (easiest)\n- Use E-utilities for metadata searching and batch queries\n- Use FTP for direct file downloads and bulk operations\n- Cache data locally to avoid repeated downloads\n- Always set Entrez.email when using Biopython\n\n## Resources\n\n### references\u002Fgeo_reference.md\n\nComprehensive reference documentation covering:\n- Detailed E-utilities API specifications and endpoints\n- Complete SOFT and MINiML file format documentation\n- Advanced GEOparse usage patterns and examples\n- FTP directory structure and file naming conventions\n- Data processing pipelines and normalization methods\n- Troubleshooting common issues and error handling\n- Platform-specific considerations and quirks\n\nConsult this reference for in-depth technical details, complex query patterns, or when working with uncommon data formats.\n\n## Important Notes\n\n### Data Quality Considerations\n\n- GEO accepts user-submitted data with varying quality standards\n- Always check platform annotation and processing methods\n- Verify sample metadata and experimental design\n- Be cautious with batch effects across studies\n- Consider reprocessing raw data for consistency\n\n### File Size Warnings\n\n- Series matrix files can be large (>1 GB for large studies)\n- Supplementary files (e.g., CEL files) can be very large\n- Plan for adequate disk space before downloading\n- Consider downloading samples incrementally\n\n### Data Usage and Citation\n\n- GEO data is freely available for research use\n- Always cite original studies when using GEO data\n- Cite GEO database: Barrett et al. (2013) Nucleic Acids Research\n- Check individual dataset usage restrictions (if any)\n- Follow NCBI guidelines for programmatic access\n\n### Common Pitfalls\n\n- Different platforms use different probe IDs (requires annotation mapping)\n- Expression values may be raw, normalized, or log-transformed (check metadata)\n- Sample metadata can be inconsistently formatted across studies\n- Not all series have series matrix files (older submissions)\n- Platform annotations may be outdated (genes renamed, IDs deprecated)\n\n## Additional Resources\n\n- **GEO Website:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002F\n- **GEO Submission Guidelines:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002Finfo\u002Fsubmission.html\n- **GEOparse Documentation:** https:\u002F\u002Fgeoparse.readthedocs.io\u002F\n- **E-utilities Documentation:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fbooks\u002FNBK25501\u002F\n- **GEO FTP Site:** ftp:\u002F\u002Fftp.ncbi.nlm.nih.gov\u002Fgeo\u002F\n- **GEO2R Tool:** https:\u002F\u002Fwww.ncbi.nlm.nih.gov\u002Fgeo\u002Fgeo2r\u002F\n- **NCBI API Keys:** https:\u002F\u002Fncbiinsights.ncbi.nlm.nih.gov\u002F2017\u002F11\u002F02\u002Fnew-api-keys-for-the-e-utilities\u002F\n- **Biopython Tutorial:** https:\u002F\u002Fbiopython.org\u002FDIST\u002Fdocs\u002Ftutorial\u002FTutorial.html\n",{"name":5,"description":7},"main","f2ec4b3b9133d34eeaf9b38e4b0a97e8e5705a7f","benchmarks\u002Ffinal\u002Fskills\u002Fasset1__Microck--claude-scientific-skills\u002Fscientific-skills\u002Fgeo-database",0,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard","https:\u002F\u002Fgithub.com\u002FJSGforever","2026-08-29 18:27:56",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add JSGforever\u002Fskillguard --skill geo-database",{"tool":61,"command":62},"bunx","bunx skills add JSGforever\u002Fskillguard --skill geo-database",{"tool":64,"command":65},"pnpm","pnpm dlx skills add JSGforever\u002Fskillguard --skill geo-database","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__Microck--claude-scientific-skills\u002Fscientific-skills\u002Fgeo-database\u002FSKILL.md",true,[69],{"path":70,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":74},"references\u002Fgeo_reference.md","REFERENCE","参考文档",21102,"https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__Microck--claude-scientific-skills\u002Fscientific-skills\u002Fgeo-database\u002Freferences\u002Fgeo_reference.md",[76,106,120,146,168,189],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":85,"publishedAt":43},"01M71HY2SNXBA9Q00WZDTZQ31Z","skillguard-codex-scanner","Hybrid deterministic+LLM agent-skill security scanner. Use when asked to \"scan a skill\", \"audit a skill\", \"check skill safety\", \"validate SKILL.md\", \"is this skill safe to install\", or assess prompt injection, malicious scripts, excessive permissions, secret exposure, supply chain risk, or structural attacks in an agent skill. Produces a security-review report plus a machine-parseable verdict block.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fsrc\u002Fskillguard\u002Fstatic_scanner\u002Fskillguard-codex-scanner\u002FSKILL.md",[82],{"categoryNo":83,"categoryName":84,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105],"scanner","skillguard codex scanner","skillguard","codex","chain","skill security","security-review","review report","structural","secret","prompt injection","security scanner","when","review","malicious","permissions","exposure","audit","scripts","safe",{"skillNo":107,"name":108,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":110,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":118,"publishedAt":43},"01M71HY0SPKTT3S27BC2HPAC5M","data-exfiltrator","Analyzes data files","MIT","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Fsmoke-one-skill\u002Fasset1__cisco-ai-defense--data-exfiltrator\u002FSKILL.md",[113],{"categoryNo":114,"categoryName":115,"taxonomyType":116,"taxonomyTypeDesc":117},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[31,119,40],"data exfiltrator",{"skillNo":121,"name":122,"nameZh":6,"description":123,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":124,"categories":125,"keywords":126,"publishedAt":43},"01M71HXVS9EMN44BGDW215FZ72","real-time-collaboration-engine","Build real-time collaborative editing with WebSockets, OT\u002FCRDT conflict resolution, and presence awareness. Implements cursor tracking, optimistic updates, and offline sync. Use for collaborative editors, whiteboards, video editing. Activate on \"real-time collaboration\", \"WebSocket sync\", \"multiplayer editing\", \"CRDT\", \"presence awareness\". NOT for simple chat, request-response APIs, or single-user apps.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--real-time-collaboration-engine\u002FSKILL.md",[],[127,128,129,130,131,132,133,134,135,136,137,138,39,139,140,141,142,143,144,145],"time","real time collaboration engine","real time collaboration","collaboration","engine","real time","Video","reliability","video editing","performance","conflict resolution","presence","apps","updates","Bash","activate","optimizer","react","streaming",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":155,"publishedAt":43},"01M71HXP6CTY4KFN0QVMMN0V7J","react-performance-optimizer","Optimize React apps for 60fps performance. Implements memoization, virtualization, code splitting, bundle optimization. Use for slow renders, large lists, bundle bloat. Activate on \"React performance\", \"slow render\", \"useMemo\", \"bundle size\", \"virtualization\". NOT for backend optimization, non-React frameworks, or premature optimization.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--react-performance-optimizer\u002FSKILL.md",[152],{"categoryNo":153,"categoryName":154,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",[136,156,143,144,157,158,159,160,161,162,127,163,164,139,141,165,142,145,166,167],"react performance optimizer","react performance","performance optimizer","app","nextjs","expert","re","render","2025","code","router","strategies",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":175,"publishedAt":43},"01M71HXH7QXSQB4QTDZ7SP7YXQ","llm-streaming-response-handler","Build production LLM streaming UIs with Server-Sent Events, real-time token display, cancellation, error recovery. Handles OpenAI\u002FAnthropic\u002FClaude streaming APIs. Use for chatbots, AI assistants, real-time text generation. Activate on \"LLM streaming\", \"SSE\", \"token stream\", \"chat UI\", \"real-time AI\". NOT for batch processing, non-streaming APIs, or WebSocket bidirectional chat.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--llm-streaming-response-handler\u002FSKILL.md",[174],{"categoryNo":153,"categoryName":154,"taxonomyType":20,"taxonomyTypeDesc":21},[176,145,177,178,179,180,136,127,181,182,183,141,142,143,184,144,185,186,187,188],"llm streaming response handler","handler","error","processing","retry","chat ui","error recovery","critical","batch","display","text","server","read",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":202,"publishedAt":43},"01M71HXCB0E1YRKYW1Y8T0Y106","github-actions-pipeline-builder","Build production CI\u002FCD pipelines with GitHub Actions. Implements matrix builds, caching, deployments, testing, security scanning. Use for automated testing, deployments, release workflows. Activate on \"GitHub Actions\", \"CI\u002FCD\", \"workflow\", \"deployment pipeline\", \"automated testing\". NOT for Jenkins\u002FCircleCI, manual deployments, or non-GitHub repositories.","https:\u002F\u002Fgithub.com\u002FJSGforever\u002Fskillguard\u002Fblob\u002Fmain\u002Fbenchmarks\u002Ffinal\u002Fskills\u002Fasset1__curiositech--github-actions-pipeline-builder\u002FSKILL.md",[195,198,201],{"categoryNo":196,"categoryName":197,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":199,"categoryName":200,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":83,"categoryName":84,"taxonomyType":20,"taxonomyTypeDesc":21},[203,204,205,206,207,208,209,134,161,210,211,212,142,167,213,188,214,215,216,217],"github actions pipeline builder","actions","github actions","pipeline builder","github","builder","pipeline","testing","ci","workflows","run","release","write","edit","git"]