Connect your h5ad data.

Follow these five steps to connect .h5ad files from one S3 folder (in S3 terms, a prefix). AWS setup takes about 15 minutes once the files are ready. Access is read-only, and your S3 folder remains the only durable copy.

AWS setupAbout 15 minutes
AccessRead-only, one folder
ConnectingWe do it with you
RevokeDelete one stack
01

Gather what you need

  • The External ID from your GenoPixel email. Tell us you need to connect your own .h5ad data, and we will generate an External ID and email it to you.
  • Your S3 bucket name and folder (its prefix, such as genopixel).
  • AWS CLI credentials for the account that owns the bucket, with permission to read the bucket and create the GenoPixel IAM role.
  • Python 3. The connection script has no extra dependencies.

Confirm that the AWS CLI points to the right account and can see the bucket:

aws sts get-caller-identity
aws s3api list-objects-v2 --bucket your-bucket --prefix your-prefix/ --max-items 1

If the first command fails, sign in to AWS or contact your AWS administrator. If access is restricted, give your administrator the prerequisite policy and ask them to replace <BUCKET> with your bucket name (the name only, not the folder) before attaching it.

02

Prepare your files

We validate every .h5ad file in your folder and connect only the files that get a Pass. Before connecting the bucket, use this checklist to avoid the findings that most often prevent a Pass:

  • Every sparse matrix in X, raw/X, and layers uses CSC, not CSR format. Note: CSC format adds 17–45% to stored size. It buys a 77× faster gene query, which is why it is required rather than suggested.
  • var shows gene symbols: either its index is the gene symbols, or, if it is indexed by Ensembl IDs, it has a gene-symbol column: one of feature_name, gene_name, gene_names, gene_symbols, symbol, hgnc_symbol.
  • obsm has an embedding such as X_umap, X_pca, or X_tsne. For spatial data, obsm["spatial"] is enough.
  • obs has a cell-type column (cell_type, author_cell_type, celltype) and a sample or donor column — one of sample_id, sample, donor_id, donor, biosample_id, specimen.
  • Delete any layer you will not query. Every layer is loaded into memory in full when the dataset opens, while X and raw/X are not. A counts layer duplicating your raw/X is the usual candidate.

Put the files in one S3 folder, with one subfolder per study: GenoPixel lists each subfolder as one study in the catalog. All .h5ad files placed directly in each subfolder become the dataset or variants of that study. Keep variants of the same study together.

# s3://your-bucket/genopixel/
genopixel/
├── colon-atlas/
│   ├── genopixel.yaml         # optional
│   ├── colon-atlas-full.h5ad
│   └── colon-atlas-epi.h5ad   # a variant of the same study
└── lung-sclc/
    └── lung-sclc.h5ad

Give variants distinct titles inside the .h5ad files (uns["title"]). The dataset picker shows each file’s title and cell count, not its filename.

Optional study metadata

Metadata helps you differentiate different studies — add genopixel.yaml beside the study files:

title:    Colonic mucosa in ulcerative colitis
author:   Nguyen et al.
year:     2025
journal:  Nature Immunology
doi:      10.1038/s41590-025-0000-0
tissue:   [colon, ileum]
disease:  ulcerative colitis
organism: Homo sapiens
assay:    10x 3' v3

The title in this .yaml file will become the study title — one per subfolder, shared by every file in it.

03

Connect your bucket

Download the connection script and preview the change. Replace the three highlighted values with your own.

curl -O https://genopixel.com/templates/v1/genopixel-connect.py

# Preview only: this changes nothing.
python3 genopixel-connect.py \
  --bucket      your-bucket \
  --prefix      your-prefix \
  --external-id <the value we sent you> \
  --dry-run

Review the account, bucket, encryption, and CloudFormation command in the preview. If they are correct, run the same command without --dry-run:

python3 genopixel-connect.py \
  --bucket      your-bucket \
  --prefix      your-prefix \
  --external-id <the value we sent you>

If the bucket uses a named AWS CLI profile, add --profile your-profile to both commands.

If your bucket is encrypted with a KMS key

Reading an object then needs permission on the key as well as on the bucket. Without it every read fails with a plain AccessDenied that never mentions KMS, so it looks like a bucket problem and sends you looking in the wrong place.

The script handles the normal case: it reads your bucket’s default encryption and grants the role kms:Decrypt on that key. Before you apply, check the preview shows your key ARN and kms:Decrypt GRANTED.

Two cases it cannot see: objects encrypted with a different key from the bucket’s default, which must be added by hand, and a key whose policy you have customised, which may refuse the role even though IAM allows it. A key still on its default policy is fine — the role is created in your own account, so IAM alone is enough.

Verify the two files against our published digests

The script, which you downloaded. Check it yourself:

shasum -a 256 genopixel-connect.py

genopixel-connect.py   2e250f90ce88c435b127e91f90726c28ef5cce78b32fbb0ff37dff79c1643ce8

The CloudFormation template, which the script downloads for you. Nothing is generated on your machine: the dry run fetches genopixel.com/templates/v1/byo-access-role.yaml — the same file under “Other setup methods” below — saves it, and prints its SHA-256 for you to compare against:

byo-access-role.yaml   08797c384e99fa6beb75fdc427ab95363c0c561ea66c083de65b8ee8df09d87a

Other setup methods

To use the CloudFormation console, download the template and upload it as a new stack:

curl -O https://genopixel.com/templates/v1/byo-access-role.yaml
ParameterValue
ExternalIdThe value we sent you
DatasetBucketYour bucket name
DatasetPrefixe.g. genopixel
KmsKeyArnYour key ARN, or empty
GrantKmsDecrypttrue if SSE-KMS
GenoPixelPrincipalArnLeave the default

For Terraform or CDK, ask GenoPixel for the equivalent trust and permission JSON.

04

Send GenoPixel two lines

Copy the two lines from the script’s final output and reply to your welcome email with them:

Role ARN:      arn:aws:iam::<YOUR_ACCOUNT>:role/GenoPixelByoAccess-<stack>
Data location: s3://your-bucket/your-prefix/

Do not resend the External ID. We already have it.

05

Review your validation report

GenoPixel validates HDF5 metadata through byte-range requests. We do not download or decompress the full dataset during validation. We email you one result per file, as a reply to the same thread:

Pass

Ready. We connect it to your workspace.

Degraded

Loads, but a required feature is missing. Not connected.

Fail

Cannot load, plot, or run safely as provided. Not connected.

We connect only Pass files. The report explains what to fix in Degraded and Fail files; revalidation is free. We confirm when each passing file is available in your workspace.

Access and revocation

  • GenoPixel can list and read only the folder you specify. It cannot write, delete, or read anything outside that folder.
  • Only the GenoPixel connector principal can assume the role, using your External ID.
  • When you open a dataset, a tenant-scoped working copy is stored temporarily on the local disk of the AWS EC2 instance that runs the analysis. It is never written to a GenoPixel S3 bucket.
  • Deleting the stack starts revocation. After deletion completes, new loads are denied. An open session rechecks before a query once its previous check is more than five minutes old, when AWS is reachable. Its local working copy is removed after 24 hours without use.

Use the stack name you deployed. The script’s default is genopixel-byo.

aws cloudformation delete-stack --stack-name genopixel-byo
The exact permissions, and why there is an External ID
ActionScope
s3:ListBucket Only keys under your chosen prefix
s3:GetObject arn:aws:s3:::<BUCKET>/<PREFIX>/*
kms:Decrypt, kms:DescribeKey Your bucket’s key — only if it uses SSE-KMS

The customer-specific External ID prevents another customer from using your role. Use the value GenoPixel sent you; do not replace it or share it.