Skip to content
Back to skills

Aind Infrastructure

ASecurity

Knowledge about AIND data infrastructure including MongoDB/DocumentDB access patterns, S3 asset storage, collection schemas, and query patterns. Use when working with AIND analysis results, querying metadata, or accessing stored assets.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 27, 2026
devopspythongoawsapidatabase

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 27, 2026

npx -y skills add David-Li0406/meta-skill-evloving --skill aind-infrastructure --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Aind Infrastructure?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Aind Infrastructure
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/david-li0406-aind-infrastructure/badge)](https://www.skillsdirectory.com/skills/david-li0406-aind-infrastructure)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: aind-infrastructure
description: Knowledge about AIND data infrastructure including MongoDB/DocumentDB access patterns, S3 asset storage, collection schemas, and query patterns. Use when working with AIND analysis results, querying metadata, or accessing stored assets.
---

# AIND Analysis Infrastructure

This skill captures knowledge about the Allen Institute for Neural Dynamics (AIND) data infrastructure for analysis results.

## Overview

AIND stores analysis results in a two-tier system:
1. **MongoDB (DocumentDB)**: Metadata and pointers to S3 assets
2. **S3**: Actual result files (figures, tables, videos)

## MongoDB Access

### Connection Pattern

Use `aind-data-access-api` for DocumentDB access:

```python
from aind_data_access_api.document_db import MetadataDbClient

client = MetadataDbClient(
    host="api.allenneuraldynamics.org",  # Public API endpoint
    database="analysis",                  # Analysis database
    collection="<collection-name>",       # Project-specific collection
)
```

### One Collection Per Project

Each analysis project has its own collection. Examples:
- `dynamic-foraging-model-fitting` - Foraging behavior MLE fitting
- Other projects follow same pattern

### Query Patterns

```python
# Basic query - old format only
records = client.retrieve_docdb_records(
    filter_query={"status": "success"},
    projection={"_id": 1, "subject_id": 1, "s3_location": 1},
    paginate=False,  # Set True for large queries
)

# Query for new format
records = client.retrieve_docdb_records(
    filter_query={"processing.data_processes.output_parameters.additional_info": "success"},
    projection={"_id": 1, "location": 1},
    paginate=False,
)
```

**Note:** Due to the two different formats, it's recommended to use `aind-analysis-arch-result-access` which handles both formats automatically.

### Two Pipeline Formats

AIND has two analysis pipeline formats with different document structures:

#### 1. Prototype Pipeline (older format)

Flat structure with fields at root level:

```json
{
  "_id": "fe96ff6c9e7b...",  // SHA256 hash
  "subject_id": "744040",
  "session_date": "2024-12-09",
  "status": "success",
  "s3_location": "s3://aind-dynamic-foraging-analysis-prod-o5171v/fe96ff6c...",
  "analysis_datetime": "2025-01-18T05:14:46.722265",
  "nwb_name": "744040_2024-12-09_13-30-23.nwb",
  "analysis_spec": {
    "analysis_name": "MLE fitting",
    "analysis_args": { ... }
  },
  "analysis_results": {
    "fit_settings": { "agent_alias": "QLearning_L1F1_CK1_softmax", ... },
    "params": { ... },
    "log_likelihood": -144.83,
    "AIC": 299.67,
    "BIC": 319.50,
    "n_trials": 390,
    "prediction_accuracy": 0.807,
    "cross_validation": { ... }
  }
}
```

**Key paths:**
- `subject_id` → root level
- `session_date` → root level
- `status` → root level
- S3 location → `s3_location`
- Fitting results → `analysis_results.*`
- Agent alias → `analysis_results.fit_settings.agent_alias`

#### 2. AIND Analysis Framework (new format)

Nested structure following `aind-data-schema`:

```json
{
  "_id": "d2a652c73ee8420a...",  // Shorter UUID
  "object_type": "Metadata",
  "name": "7d9b907880012b65...",
  "location": "s3://aind-analysis-prod-o5171v/dynamic-foraging-model-fitting/7d9b...",
  "processing": {
    "data_processes": [
      {
        "name": "han_df_mle_aind-analysis-wrapper",
        "start_date_time": "2026-01-10T04:07:11",
        "output_parameters": {
          "additional_info": "success",
          "subject_id": "781575",
          "session_date": "2025-07-14",
          "nwb_name": "behavior_781575_2025-07-14_21-41-11.nwb",
          "fitting_results": {
            "fit_settings": { "agent_alias": "ForagingCompareThreshold", ... },
            "params": { ... },
            "log_likelihood": -272.10,
            "AIC": 552.20,
            "BIC": 569.34,
            "n_trials": 536,
            "prediction_accuracy": 0.783,
            "cross_validation": { ... }
          }
        }
      }
    ]
  }
}
```

**Key paths:**
- `subject_id` → `processing.data_processes[0].output_parameters.subject_id`
- `session_date` → `processing.data_processes[0].output_parameters.session_date`
- `status` → `processing.data_processes[0].output_parameters.additional_info`
- S3 location → `location`
- Fitting results → `processing.data_processes[0].output_parameters.fitting_results.*`
- Agent alias → `processing.data_processes[0].output_parameters.fitting_results.fit_settings.agent_alias`

#### Field Mapping Summary

| Field | Old Format | New Format |
|-------|-----------|------------|
| subject_id | `subject_id` | `processing.data_processes[0].output_parameters.subject_id` |
| session_date | `session_date` | `processing.data_processes[0].output_parameters.session_date` |
| status | `status` | `processing.data_processes[0].output_parameters.additional_info` |
| S3 location | `s3_location` | `location` |
| agent_alias | `analysis_results.fit_settings.agent_alias` | `processing.data_processes[0].output_parameters.fitting_results.fit_settings.agent_alias` |
| n_trials | `analysis_results.n_trials` | `processing.data_processes[0].output_parameters.fitting_results.n_trials` |
| AIC/BIC | `analysis_results.AIC/BIC` | `processing.data_processes[0].output_parameters.fitting_results.AIC/BIC` |

#### Querying Both Formats

Use MongoDB projection aliasing to normalize fields:

```python
# Query that works for both formats
projection = {
    "_id": 1,
    # Old format fields
    "subject_id": 1,
    "session_date": 1,
    "status": 1,
    "s3_location": 1,
    # New format fields (aliased)
    "subject_id_new": "$processing.data_processes.output_parameters.subject_id",
    "session_date_new": "$processing.data_processes.output_parameters.session_date",
    "location": 1,
}
```

The `aind-analysis-arch-result-access` package handles this automatically by querying both formats and merging results into a unified DataFrame.

## S3 Access

### Public Buckets

Analysis results are in public S3 buckets (no auth needed):

```python
import s3fs

# Anonymous access for public buckets
fs = s3fs.S3FileSystem(anon=True)
```

### Common Bucket Paths

```python
# Old pipeline bucket
S3_PATH_ANALYSIS_OLD = "s3://aind-dynamic-foraging-analysis-prod-o5171v"

# New pipeline bucket (AIND Analysis Framework)
S3_PATH_ANALYSIS_NEW = "s3://aind-analysis-prod-o5171v/dynamic-foraging-model-fitting"

# Bonsai processed data
S3_PATH_BONSAI_ROOT = "s3://aind-behavior-data/foraging_nwb_bonsai_processed"
```

### Asset URL Construction

Convert S3 path to HTTPS for web display:

```python
def s3_to_https(s3_path: str) -> str:
    """Convert s3://bucket/key to https://bucket.s3.amazonaws.com/key"""
    if s3_path.startswith("s3://"):
        s3_path = s3_path[5:]
    bucket = s3_path.split("/")[0]
    key = "/".join(s3_path.split("/")[1:])
    return f"https://{bucket}.s3.amazonaws.com/{key}"
```

### Reading Files from S3

```python
import json
import pickle

# JSON files
with fs.open("s3://bucket/path/file.json") as f:
    data = json.load(f)

# Pickle files
with fs.open("s3://bucket/path/file.pkl", "rb") as f:
    df = pickle.load(f)

# Check existence
if fs.exists("s3://bucket/path/file.png"):
    # File exists
```

### Batch Operations

For multiple S3 reads, use ThreadPoolExecutor:

```python
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm

def fetch_file(s3_path):
    # ... fetch logic
    pass

with ThreadPoolExecutor(max_workers=10) as executor:
    results = list(tqdm(
        executor.map(fetch_file, paths),
        total=len(paths),
        desc="Fetching files"
    ))
```

## Using aind-analysis-arch-result-access

This package provides ready-made functions for specific analyses:

```python
# Install: pip install aind-analysis-arch-result-access
from aind_analysis_arch_result_access import get_mle_model_fitting

# Get foraging model fitting results
# IMPORTANT: At least one filter parameter is required!
df = get_mle_model_fitting(
    subject_id="778869",           # Filter by subject (recommended for fast loading)
    # session_date="2024-10-24",   # Or filter by date
    # agent_alias="QLearning...",  # Or filter by model type
    # from_custom_query={...},     # Or use custom MongoDB query
    if_include_metrics=True,
    if_include_latent_variables=False,  # Set False for faster loading
    if_download_figures=False,
)

# For querying by date range:
from datetime import datetime, timedelta
three_months_ago = (datetime.now() - timedelta(days=90)).strftime("%Y-%m-%d")
df_recent = get_mle_model_fitting(
    from_custom_query={"session_date": {"$gte": three_months_ago}},
    if_include_metrics=True,
    if_include_latent_variables=False,
)
```

**Important notes:**
- Function requires at least one of: `subject_id`, `session_date`, `agent_alias`, or `from_custom_query`
- The package queries both pipeline formats separately and merges results into a unified DataFrame
- `only_recent_version=True` (default) deduplicates by keeping most recent analysis
- Loading all records can be slow; filter by subject_id or date range for prototyping

Key columns in returned DataFrame:
- `_id`: Record identifier
- `subject_id`, `session_date`: Session info
- `agent_alias`: Model type used
- `n_trials`: Number of trials
- `S3_location`: Path to result files (use for constructing asset URLs)
- `status`: "success" or "failed"
- `pipeline_source`: "aind analysis framework" or "han's analysis pipeline"
- Metrics: `log_likelihood`, `AIC`, `BIC`, `prediction_accuracy`, etc.

## Common Asset Types

Assets stored in S3 per record:
- `fitted_session.png` - Main result figure
- `docDB_record.json` - Full analysis results
- `original_results_*.json` - Raw output files
- Latent variables (q-values, RPE, etc.)

## Best Practices

1. **Filter early**: Use MongoDB queries to reduce data before pandas operations
2. **Batch S3 operations**: Use threading for multiple file reads
3. **Cache results**: Consider caching DataFrames for repeated queries
4. **Handle both formats**: Account for old and new pipeline structures
5. **Check S3 existence**: Assets may not exist for all records

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…