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.
Gather what you need
- The External ID from your GenoPixel email. Tell us you need to
connect your own
.h5addata, 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.
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, andlayersuses 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. varshows gene symbols: either its index is the gene symbols, or, if it is indexed by Ensembl IDs, it has a gene-symbol column: one offeature_name,gene_name,gene_names,gene_symbols,symbol,hgnc_symbol.obsmhas an embedding such asX_umap,X_pca, orX_tsne. For spatial data,obsm["spatial"]is enough.obshas a cell-type column (cell_type,author_cell_type,celltype) and a sample or donor column — one ofsample_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
Xandraw/Xare not. Acountslayer duplicating yourraw/Xis 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.
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
| Parameter | Value |
|---|---|
ExternalId | The value we sent you |
DatasetBucket | Your bucket name |
DatasetPrefix | e.g. genopixel |
KmsKeyArn | Your key ARN, or empty |
GrantKmsDecrypt | true if SSE-KMS |
GenoPixelPrincipalArn | Leave the default |
For Terraform or CDK, ask GenoPixel for the equivalent trust and permission JSON.
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.
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:
Ready. We connect it to your workspace.
Loads, but a required feature is missing. Not connected.
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
| Action | Scope |
|---|---|
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.