polars-bio
Aperçu
polars-bio est une bibliothèque Python haute performance pour les opérations sur intervalles génomiques et les entrées/sorties de fichiers bioinformatiques, construite sur Polars, Apache Arrow et Apache DataFusion. Elle fournit une API centrée sur les DataFrames pour l'arithmétique des intervalles (chevauchement, plus proche, fusion, couverture, complément, soustraction) et la lecture/écriture de formats bioinformatiques courants (BED, VCF, BAM, CRAM, GFF/GTF, FASTA, FASTQ).
Propositions de valeur clés :
- 6 à 38 fois plus rapide que bioframe sur les benchmarks génomiques réels
- Support streaming/hors mémoire pour les grands génomes via DataFusion
- Entrées/sorties natives cloud (S3, GCS, Azure) avec predicate pushdown
- Deux styles d'API : fonctionnel (
pb.overlap(df1, df2)) et chaînage de méthodes (df1.lazy().pb.overlap(df2)) - Interface SQL pour les données génomiques via le moteur DataFusion SQL
Quand utiliser cette compétence
Utilisez cette compétence quand :
- Vous effectuez des opérations sur intervalles génomiques (chevauchement, plus proche, fusion, couverture, complément, soustraction)
- Vous lisez/écrivez des formats de fichiers bioinformatiques (BED, VCF, BAM, CRAM, GFF/GTF, FASTA, FASTQ)
- Vous traitez de grands ensembles de données génomiques qui ne rentrent pas en mémoire (mode streaming)
- Vous exécutez des requêtes SQL sur des fichiers de données génomiques
- Vous migrez de bioframe vers une alternative plus rapide
- Vous calculez la profondeur de lecture/pileup à partir de fichiers BAM/CRAM
- Vous travaillez avec des DataFrames Polars contenant des intervalles génomiques
Démarrage rapide
Installation
pip install polars-bio
# ou
uv pip install polars-bio
Pour la compatibilité pandas :
pip install polars-bio[pandas]
Exemple basique de chevauchement
import polars as pl
import polars_bio as pb
# Créer deux DataFrames d'intervalles
df1 = pl.DataFrame({
"chrom": ["chr1", "chr1", "chr1"],
"start": [1, 5, 22],
"end": [6, 9, 30],
})
df2 = pl.DataFrame({
"chrom": ["chr1", "chr1"],
"start": [3, 25],
"end": [8, 28],
})
# API fonctionnelle (retourne LazyFrame par défaut)
result = pb.overlap(df1, df2)
result_df = result.collect()
# Obtenir un DataFrame directement
result_df = pb.overlap(df1, df2, output_type="polars.DataFrame")
# API avec chaînage de méthodes (via l'accesseur .pb sur LazyFrame)
result = df1.lazy().pb.overlap(df2)
result_df = result.collect()
Lecture d'un fichier BED
import polars_bio as pb
# Lecture entière (charge le fichier entièrement)
df = pb.read_bed("regions.bed")
# Balayage paresseux (streaming, pour les gros fichiers)
lf = pb.scan_bed("regions.bed")
result = lf.collect()
Capacités principales
1. Opérations sur intervalles génomiques
polars-bio fournit 8 opérations d'intervalles essentielles pour l'arithmétique des plages génomiques. Toutes les opérations acceptent des DataFrames Polars avec des colonnes chrom, start, end (configurables). Toutes les opérations retournent une LazyFrame par défaut (utilisez output_type="polars.DataFrame" pour des résultats entiers).
Opérations :
overlap/count_overlaps- Trouver ou compter les intervalles qui se chevauchent entre deux ensemblesnearest- Trouver les intervalles les plus proches (avec paramètresk,overlap,distanceconfigurables)merge- Fusionner les intervalles qui se chevauchent ou sont bout à bout dans un ensemblecluster- Assigner des ID de cluster aux intervalles qui se chevauchentcoverage- Calculer les comptages de couverture par intervalle (opération à deux entrées)complement- Trouver les écarts entre intervalles dans un génomesubtract- Supprimer les portions d'intervalles qui chevauchent un autre ensemble
Exemple :
import polars_bio as pb
# Trouver les intervalles qui se chevauchent (retourne LazyFrame)
result = pb.overlap(df1, df2, suffixes=("_1", "_2"))
# Compter les chevauchements par intervalle
counts = pb.count_overlaps(df1, df2)
# Fusionner les intervalles qui se chevauchent
merged = pb.merge(df1)
# Trouver les intervalles les plus proches
nearest = pb.nearest(df1, df2)
# Collecter tout résultat LazyFrame en DataFrame
result_df = result.collect()
Référence : Voir references/interval_operations.md pour la documentation détaillée de toutes les opérations, paramètres, schémas de sortie et considérations de performance.
2. Entrées/sorties de fichiers bioinformatiques
Lire et écrire des formats bioinformatiques courants avec les fonctions read_*, scan_*, write_* et sink_*. Supporte le stockage cloud (S3, GCS, Azure) et la compression (GZIP, BGZF).
Formats supportés :
- BED - Intervalles génomiques (
read_bed,scan_bed,write_*via générique) - VCF - Variantes génétiques (
read_vcf,scan_vcf,write_vcf,sink_vcf) - BAM - Lectures alignées (
read_bam,scan_bam,write_bam,sink_bam) - CRAM - Alignements comprimés (
read_cram,scan_cram,write_cram,sink_cram) - GFF - Annotations de gènes (
read_gff,scan_gff) - GTF - Annotations de gènes (
read_gtf,scan_gtf) - FASTA - Séquences de référence (
read_fasta,scan_fasta) - FASTQ - Lectures de séquençage (
read_fastq,scan_fastq,write_fastq,sink_fastq) - SAM - Alignements texte (
read_sam,scan_sam,write_sam,sink_sam) - Paires Hi-C - Contacts de chromatine (
read_pairs,scan_pairs)
Exemple :
import polars_bio as pb
# Lire un fichier VCF
variants = pb.read_vcf("samples.vcf.gz")
# Balayage paresseux du fichier BAM (streaming)
alignments = pb.scan_bam("aligned.bam")
# Lire les annotations GFF
genes = pb.read_gff("annotations.gff3")
# Stockage cloud (paramètres individuels, pas un dictionnaire)
df = pb.read_bed("s3://bucket/regions.bed",
allow_anonymous=True)
Référence : Voir references/file_io.md pour les schémas de colonnes par format, paramètres, options de stockage cloud et support de la compression.
3. Traitement des données SQL
Enregistrer les fichiers bioinformatiques comme tableaux et les interroger à l'aide de DataFusion SQL. Combine la puissance de SQL avec les lecteurs génomiques de polars-bio.
import polars as pl
import polars_bio as pb
# Enregistrer les fichiers comme tableaux SQL (chemin en premier, mot-clé name=)
pb.register_vcf("samples.vcf.gz", name="variants")
pb.register_bed("target_regions.bed", name="regions")
# Interroger avec SQL (retourne LazyFrame)
result = pb.sql("SELECT chrom, start, end, ref, alt FROM variants WHERE qual > 30")
result_df = result.collect()
# Enregistrer un DataFrame Polars comme tableau SQL
pb.from_polars("my_intervals", df)
result = pb.sql("SELECT * FROM my_intervals WHERE chrom = 'chr1'").collect()
Référence : Voir references/sql_processing.md pour les fonctions d'enregistrement, la syntaxe SQL et les exemples.
4. Opérations Pileup
Calculer la profondeur de lecture par base à partir de fichiers BAM/CRAM avec calcul de profondeur conscient du CIGAR.
import polars_bio as pb
# Calculer la profondeur sur tout un fichier BAM
depth_lf = pb.depth("aligned.bam")
depth_df = depth_lf.collect()
# Avec filtre de qualité
depth_lf = pb.depth("aligned.bam", min_mapping_quality=20)
Référence : Voir references/pileup_operations.md pour les paramètres et les modèles d'intégration.
Concepts clés
Systèmes de coordonnées
polars-bio utilise par défaut des coordonnées basées sur 1 (convention génomique). Cela peut être modifié globalement :
import polars_bio as pb
# Basculer vers des coordonnées basées sur 0
pb.set_option("coordinate_system", "0-based")
# Revenir aux coordonnées basées sur 1 (par défaut)
pb.set_option("coordinate_system", "1-based")
Les fonctions d'entrée/sortie acceptent aussi use_zero_based pour définir les métadonnées de coordonnées sur le DataFrame résultant :
# Lire BED avec métadonnées explicites basées sur 0
df = pb.read_bed("regions.bed", use_zero_based=True)
Important : Les fichiers BED sont toujours basés sur 0 demi-ouvert dans le format de fichier. polars-bio gère la conversion automatiquement lors de la lecture de fichiers BED. Les métadonnées de coordonnées sont attachées aux DataFrames par les fonctions d'entrée/sortie et propagées à travers les opérations.
Deux styles d'API
API fonctionnelle - fonctions autonomes, entrées explicites :
result = pb.overlap(df1, df2, suffixes=("_1", "_2"))
merged = pb.merge(df)
API avec chaînage de méthodes - via l'accesseur .pb sur les LazyFrames (pas les DataFrames) :
result = df1.lazy().pb.overlap(df2)
merged = df.lazy().pb.merge()
Important : L'accesseur .pb pour les opérations sur intervalles n'est disponible que sur LazyFrame. Sur DataFrame, .pb fournit uniquement les opérations d'écriture (write_bam, write_vcf, etc.).
Le chaînage de méthodes permet des pipelines fluides :
# Chaîner les opérations sur intervalles (note : overlap génère des colonnes suffixées,
# donc renommez avant merge qui attend chrom/start/end)
result = (
df1.lazy()
.pb.overlap(df2)
.filter(pl.col("start_2") > 1000)
.select(
pl.col("chrom_1").alias("chrom"),
pl.col("start_1").alias("start"),
pl.col("end_1").alias("end"),
)
.pb.merge()
.collect()
)
Architecture Probe-Build
Pour les opérations à deux entrées (overlap, nearest, count_overlaps, coverage), polars-bio utilise une stratégie de jointure probe-build :
- Le premier DataFrame est la probe (itérée)
- Le deuxième DataFrame est la build (indexée pour la recherche)
Pour de meilleures performances, passez le plus grand DataFrame comme premier argument (probe) et le plus petit comme deuxième (build).
Conventions de colonnes
Par défaut, polars-bio s'attend à des colonnes nommées chrom, start, end. Des noms de colonnes personnalisés peuvent être spécifiés via des listes :
result = pb.overlap(
df1, df2,
cols1=["chromosome", "begin", "finish"],
cols2=["chr", "pos_start", "pos_end"],
)
Types de retour et collecte des résultats
Toutes les opérations sur intervalles et pb.sql() retournent une LazyFrame par défaut. Utilisez .collect() pour matérialiser les résultats, ou passez output_type="polars.DataFrame" pour une évaluation entière :
# Paresseux (par défaut) - collecter quand nécessaire
result_lf = pb.overlap(df1, df2)
result_df = result_lf.collect()
# Entier - obtenir DataFrame directement
result_df = pb.overlap(df1, df2, output_type="polars.DataFrame")
Traitement streaming et hors mémoire
Pour les ensembles de données plus grands que la RAM disponible, utilisez les fonctions scan_* et l'exécution en streaming :
# Balayer les fichiers paresseusement
lf = pb.scan_bed("large_intervals.bed")
# Traiter avec streaming
result = lf.collect(streaming=True)
Le streaming DataFusion est activé par défaut pour les opérations sur intervalles, en traitant les données par lots sans charger l'ensemble complet en mémoire.
Pièges courants
-
Accesseur
.pbsur DataFrame vs LazyFrame : Les opérations sur intervalles (overlap, merge, etc.) ne sont disponibles que surLazyFrame.pb.DataFrame.pbn'a que les méthodes d'écriture. Utilisez.lazy()pour convertir avant de chaîner les opérations sur intervalles. -
Retours LazyFrame : Toutes les opérations sur intervalles et
pb.sql()retournentLazyFramepar défaut. N'oubliez pas.collect()ou utilisezoutput_type="polars.DataFrame". -
Incompatibilités de noms de colonnes : polars-bio s'attend à
chrom,start,endpar défaut. Utilisez les paramètrescols1/cols2(comme listes) si vos colonnes ont des noms différents. -
Métadonnées du système de coordonnées : Lors de la construction manuelle de DataFrames (pas via
read_*/scan_*), polars-bio avertit des métadonnées de coordonnées manquantes. Utilisezpb.set_option("coordinate_system", "0-based")globalement, ou utilisez les fonctions d'entrée/sortie qui définissent les métadonnées automatiquement. -
L'ordre probe-build compte : Pour overlap, nearest et coverage, le premier DataFrame est testé par rapport au deuxième. Inverser les arguments change les intervalles qui apparaissent dans les colonnes de sortie gauche vs droite, et peut affecter les performances.
-
Limite de position INT32 : Les positions génomiques sont stockées en entiers 32 bits, limitant les coordonnées à environ 2,1 milliards. C'est suffisant pour tous les génomes connus mais peut être un problème avec les espaces de coordonnées personnalisés.
-
Exigences d'index BAM :
read_bametscan_bamnécessitent un fichier d'index.baià côté du BAM. Créez-en un avecsamtools indexs'il est manquant. -
Exécution parallèle désactivée par défaut : Le parallélisme DataFusion se limite par défaut à 1 partition. Activez-le pour les gros ensembles de données :
pb.set_option("datafusion.execution.target_partitions", 8) -
CRAM a des fonctions séparées : Utilisez
read_cram/scan_cram/register_crampour les fichiers CRAM (pasread_bam). Les fonctions CRAM nécessitent un paramètrereference_path.
Bonnes pratiques
-
*Utilisez `scan_
pour les gros fichiers :** Préférezscan_bed,scanvcf, etc. àread*` pour les fichiers plus grands que la RAM disponible. Les fonctions scan activent le streaming et le predicate pushdown. -
Configurez le parallélisme pour les gros ensembles de données :
import os pb.set_option("datafusion.execution.target_partitions", os.cpu_count()) -
Utilisez la compression BGZF : Les fichiers comprimés BGZF (
.bed.gz,.vcf.gz) supportent la décompression de blocs parallèles, significativement plus rapide que le GZIP simple. -
Sélectionnez les colonnes en début : Quand seules certaines colonnes sont nécessaires, sélectionnez-les en début pour réduire l'utilisation mémoire :
df = pb.read_vcf("large.vcf.gz").select("chrom", "start", "end", "ref", "alt") -
Utilisez les chemins cloud directement : Passez les URI S3/GCS/Azure directement aux fonctions read/scan au lieu de télécharger les fichiers en premier :
df = pb.read_bed("s3://my-bucket/regions.bed", allow_anonymous=True) -
Préférez l'API fonctionnelle pour les opérations simples, le chaînage de méthodes pour les pipelines : Utilisez
pb.overlap()pour les opérations ponctuelles et.lazy().pb.overlap()lors de la construction de pipelines multi-étapes.
Ressources
references/
Documentation détaillée pour chaque capacité majeure :
-
interval_operations.md - Les 8 opérations d'intervalles avec paramètres, exemples, schémas de sortie et conseils de performance. Référence essentielle pour l'arithmétique des plages génomiques.
-
file_io.md - Tableau des formats supportés, schémas de colonnes par format, configuration du stockage cloud, support de la compression et paramètres courants.
-
sql_processing.md - Fonctions d'enregistrement, syntaxe DataFusion SQL, combinaison de SQL avec opérations sur intervalles et exemples de requêtes.
-
pileup_operations.md - Calcul de la profondeur de lecture par base à partir de fichiers BAM/CRAM, paramètres et intégration avec opérations sur intervalles.
-
configuration.md - Paramètres globaux (parallélisme, systèmes de coordonnées, modes streaming), journalisation et gestion des métadonnées.
-
bioframe_migration.md - Tableau de mappage des opérations, différences d'API, comparaison des performances, exemples de code de migration et mode de compatibilité pandas.