Menu

Module 1 · Section 1.5

Contenu en GC et usage des codons

55 min · niveau intermediaire · dernière révision : 2026-11-01

Objectifs d'apprentissage

  • Calculer un contenu en GC global, par fenêtre et par position de codon
  • Interpréter un biais de composition et distinguer GC global et GC3
  • Calculer et interpréter le RSCU d'une famille de codons synonymes
  • Construire un indice d'adaptation des codons à partir d'un jeu de référence
  • Produire un rapport reproductible d'usage des codons avec Biopython

Prérequis : 1.3 Parsing avec Biopython SeqIO

Biopython 1.88NumPy 2.x

Prérequis

Cette section suppose acquises la notion de codon et le découpage en cadres de lecture présentés en 1.1, ainsi que la lecture de séquences avec Biopython SeqIO vue en 1.3. Il faut savoir compter les bases et manipuler un dictionnaire Python. Les formules utilisent la notation du cours : s=s1s2…sns = s_1 s_2 \dots s_n, les positions sont 1-based dans le texte et 0-based dans le code.

Introduction

Le contenu en GC est l'une des statistiques les plus simples que l'on puisse calculer sur une séquence : la proportion de guanines et de cytosines. Le GC varie entre espèces, entre chromosomes et le long d'un même génome ; il reflète l'histoire mutationnelle, la pression de sélection, la composition des enzymes de réparation et, chez les bactéries, des phénomènes d'asymétrie entre les deux brins. Chez Escherichia coli K-12 MG1655, le GC global est proche de 50 %, mais cette moyenne masque des variations locales de plusieurs points.

La composition ne se limite pas à la proportion globale. Le code génétique est redondant : plusieurs codons désignent le même acide aminé. Cette redondance n'est pas utilisée au hasard. Certains codons sont plus fréquents que d'autres dans une espèce, et ce biais varie entre gènes. Les gènes très exprimés, notamment ceux qui codent les protéines ribosomiques, utilisent préférentiellement les codons que les ARN de transfert abondants reconnaissent efficacement. Mesurer ce biais demande des outils adaptés : le RSCU compare les codons synonymes entre eux, tandis que l'indice d'adaptation des codons, ou CAI, résume l'écart d'un gène à un ensemble de référence.

Le défi computationnel est double. D'abord, il faut définir précisément les fenêtres, les dénominateurs et le traitement des bases ambiguës : un NN dans une fenêtre change le résultat selon qu'on le compte ou non. Ensuite, il faut construire une référence explicite et vérifier la cohérence des codons. Un CAI calculé avec les gènes d'une autre espèce, ou avec un jeu de référence mal filtré, n'a pas le même sens. La reproductibilité exige de publier la valeur finale, le jeu de référence, la version de la bibliothèque et la convention adoptée pour les codons stop.

Cette section part de la composition globale, puis descend vers la fenêtre et la position du codon. Elle définit le RSCU et le CAI, montre un exemple calculé à la main, et applique l'ensemble au gène lacZ d'E. coli.

Théorie

Composition globale et biais de composition

Pour une séquence d'ADN ss de longueur nn, le contenu en GC s'écrit

GC(s)=#G(s)+#C(s)n×100.\mathrm{GC}(s) = \frac{\#G(s) + \#C(s)}{n} \times 100.

Le calcul est linéaire en temps, O(n)O(n), et ne demande qu'un compteur. Il faut décider une fois pour toutes comment traiter les caractères non canoniques. Si l'on compte les NN dans le dénominateur, une fenêtre riche en bases inconnues voit son GC mécaniquement diminuer ; si on les exclut, le GC porte seulement sur les bases connues et peut devenir instable pour de petites fenêtres. Dans ce cours, le dénominateur est la longueur totale de la fenêtre, NN compris, sauf mention contraire.

Le GC global n'est pas une constante de l'organisme. Il dépend de la région, de la pression mutationnelle et de la sélection. Chez les bactéries, on observe souvent un biais de composition entre les brins, et les régions proches de l'origine de réplication ne se comportent pas comme les régions terminales. Un GC de 50 % peut donc cacher une alternance de zones très riches et très pauvres.

Il faut aussi distinguer le GC de l'ADN génomique complet, qui contient des régions intergéniques, des ARN non codants et des séquences répétées, du GC d'une séquence codante, ou CDS (coding sequence). Une CDS peut avoir un GC de 56 % alors que le génome qui la porte est à 50 %. Comparer les deux sans préciser le périmètre est fréquent.

GC par fenêtre

Pour décrire une hétérogénéité locale, on découpe la séquence en fenêtres. Une fenêtre glissante de taille ww produit n−w+1n - w + 1 valeurs :

GCi=#G(si…si+w−1)+#C(si…si+w−1)w×100,i=1,…,n−w+1.\mathrm{GC}_i = \frac{\#G(s_i \dots s_{i+w-1}) + \#C(s_i \dots s_{i+w-1})}{w} \times 100, \quad i = 1, \dots, n-w+1.

Le calcul naïf recompte chaque fenêtre et coûte O(nw)O(nw). Une somme glissante le ramène à O(n)O(n) : on retire la base qui sort, on ajoute celle qui entre, et l'on divise par ww.

Le choix de ww est un compromis. Une fenêtre courte révèle des variations locales mais produit un profil bruité ; une fenêtre longue lisse les transitions et peut masquer des îlots. Il n'existe pas de taille universelle : w=1 000w = 1\,000 ou w=10 000w = 10\,000 sont fréquents pour les génomes, w=30w = 30 à 100100 pour examiner une CDS.

Les fenêtres glissantes ne sont pas indépendantes : deux valeurs voisines partagent w−1w-1 bases. Un test statistique naïf qui les traite comme indépendantes surestime donc la signification. Pour comparer deux régions, on préfère des fenêtres disjointes ou un modèle qui tient compte de l'autocorrélation.

GC1, GC2 et GC3

Dans une séquence codante, les trois positions du codon n'ont pas le même rôle. La troisième position est souvent dite dégénérée : une mutation y est souvent synonyme, elle ne change pas l'acide aminé. On définit le contenu en GC de la position kk par

GCk=#{i:s3(i−1)+k∈{G,C}}N×100,k∈{1,2,3},\mathrm{GC}_k = \frac{\#\{i : s_{3(i-1)+k} \in \{G, C\}\}}{N} \times 100, \quad k \in \{1, 2, 3\},

où NN est le nombre de codons pris en compte. Le plus souvent, on exclut le codon stop terminal, qui n'est pas un codon synonyme comme les autres. Le GC1 et le GC2 sont contraints par la protéine : un changement y modifie l'acide aminé, sauf pour quelques familles. Le GC3 est beaucoup plus libre et constitue donc un indicateur privilégié du biais mutationnel et de l'usage des codons.

Chez E. coli, le GC3 des gènes très exprimés est souvent plus élevé que le GC global, et les codons se terminant par G ou C sont surreprésentés dans certaines familles. Cette tendance n'est pas une loi universelle : elle dépend de l'espèce, du taux de GC génomique et de la sélection. Un GC3 élevé ne signifie pas nécessairement que le gène est très exprimé ; il peut simplement refléter une région génomique riche en GC.

Il faut également éviter de confondre le GC3 avec le GC du troisième codon ou avec le GC de la troisième base de la séquence. Le GC3 est une moyenne sur toutes les troisièmes positions des codons sens. Un cadre de lecture mal choisi décale toutes les positions et produit un GC3 différent : l'annotation du cadre et du codon d'initiation doit précéder tout calcul.

Figure 1.5.1. Les trois positions d'un codon ne subissent pas la même contrainte. La troisième position est la plus libre et porte l'essentiel du biais d'usage des codons.

Usage des codons et RSCU

Le code génétique standard associe 61 codons à 20 acides aminés et réserve trois codons stop. Pour un acide aminé aa possédant nan_a codons synonymes, notons xijx_{ij} le nombre d'occurrences du codon jj dans le gène ii. Le RSCU (relative synonymous codon usage) du codon jj vaut

RSCUij=xij1na∑k=1naxik=na xij∑k=1naxik.\mathrm{RSCU}_{ij} = \frac{x_{ij}}{\frac{1}{n_a}\sum_{k=1}^{n_a} x_{ik}} = \frac{n_a \, x_{ij}}{\sum_{k=1}^{n_a} x_{ik}}.

Le dénominateur est l'effectif attendu de chaque codon si les nan_a codons synonymes étaient utilisés également. Un RSCU de 1 signifie donc un usage conforme à l'équiprobabilité ; une valeur supérieure à 1 indique une surreprésentation, une valeur inférieure à 1 une sous-représentation. La somme des RSCU d'une famille vaut exactement nan_a lorsque la famille est présente. Pour la méthionine et le tryptophane, qui n'ont qu'un codon, le RSCU vaut 1 lorsqu'ils sont présents : il n'apporte aucune information.

Le RSCU a l'avantage d'être comparable entre gènes de longueurs différentes, puisqu'il normalise par la famille. Il ne dit rien sur l'expression absolue : un gène peut avoir un RSCU élevé pour un codon rare simplement parce que ce codon est le seul de sa famille dans la séquence. Les petites familles et les gènes courts produisent des valeurs instables.

Prenons les comptages réels du gène lacZ pour l'alanine, famille de quatre codons. Les effectifs sont GCT = 9, GCC = 28, GCA = 12 et GCG = 28, soit un total de 77. Le calcul à la main donne :

CodonEffectifCalculRSCU
GCT99×4/77=36/779 \times 4 / 77 = 36/770,468
GCC2828×4/77=112/7728 \times 4 / 77 = 112/771,455
GCA1212×4/77=48/7712 \times 4 / 77 = 48/770,623
GCG2828×4/77=112/7728 \times 4 / 77 = 112/771,455

La somme vaut 0,468+1,455+0,623+1,455=4,0010{,}468 + 1{,}455 + 0{,}623 + 1{,}455 = 4{,}001, aux arrondis près. Les codons GCC et GCG sont surreprésentés, GCT est rare. Ce résultat décrit lacZ, pas l'ensemble du génome : il faudrait répéter l'analyse sur de nombreux gènes pour conclure à un biais d'espèce.

Indice d'adaptation des codons (CAI)

Le RSCU décrit un gène, le CAI le compare à une référence. On construit d'abord, pour chaque codon jj d'une famille de nan_a codons, une adaptativité relative

wij=xijmax⁡k=1naxik,w_{ij} = \frac{x_{ij}}{\max_{k=1}^{n_a} x_{ik}},

où les xijx_{ij} sont cette fois les effectifs observés dans un jeu de gènes de référence. Le codon le plus fréquent de chaque famille reçoit w=1w = 1 ; les autres reçoivent une valeur comprise entre 0 et 1. Pour un codon absent de la référence, la convention de Sharp et Li attribue une pseudo-valeur de 0,5 avant normalisation, ce qui évite une division par zéro et un poids nul.

Le CAI d'une CDS est la moyenne géométrique des ww de ses codons :

CAI=(∏k=1Lwk)1/L=exp⁡(1L∑k=1Lln⁡wk),\mathrm{CAI} = \left(\prod_{k=1}^{L} w_k\right)^{1/L} = \exp\left(\frac{1}{L}\sum_{k=1}^{L} \ln w_k\right),

où LL est le nombre de codons pris en compte. On exclut généralement les codons ATG et TGG, dont l'adaptativité vaut toujours 1, ainsi que le codon stop. Le CAI vaut 1 lorsqu'un gène utilise exclusivement les codons les plus fréquents de la référence ; il tend vers 0 lorsqu'il utilise des codons très rares. La moyenne géométrique pénalise les codons de poids faible plus fortement qu'une moyenne arithmétique, ce qui correspond à l'idée qu'un seul codon très rare peut limiter la traduction.

Le choix de la référence est la décision la plus importante. Un CAI calculé sur les gènes ribosomiques mesure l'adaptation à la traduction rapide ; un CAI calculé sur l'ensemble des gènes mesure plutôt l'écart à la composition moyenne du génome. Les deux valeurs ne sont pas interchangeables. Il faut donc construire la référence à partir de gènes très exprimés, vérifier qu'ils appartiennent à la même espèce et à la même condition de croissance, et publier la liste utilisée.

Complexité et précautions

Le comptage des codons, le RSCU et le CAI s'effectuent en O(n)O(n) sur une CDS de longueur nn, avec une mémoire O(1)O(1) si l'on ne conserve que les compteurs. Le CAI ajoute un logarithme par codon, ce qui reste négligeable. Le coût réel vient de la construction de la référence et des accès réseau lorsqu'on télécharge les séquences.

Les valeurs numériques doivent être interprétées avec leur incertitude. Un CAI calculé sur 50 codons est beaucoup plus variable qu'un CAI calculé sur 1 000 codons. Enfin, le CAI suppose que l'adaptativité des codons est multiplicative et indépendante du contexte ; cette hypothèse ignore les effets de voisinage, la structure de l'ARN messager et la disponibilité réelle des ARN de transfert.

Implémentation

Les quatre fonctions ci-dessous forment le noyau de l'analyse. Elles sont volontairement autonomes et n'utilisent que la bibliothèque standard. gc_windows emploie une somme glissante, codon_frequencies initialise les 64 codons pour garantir un schéma stable, rscu normalise chaque famille et cai calcule une moyenne géométrique en excluant ATG, TGG et les codons stop.

GC par fenêtre, comptage, RSCU et CAI
SortieCtrl+Entrée pour exécuter · 10 s max
Aucune sortie. Exécutez le code pour voir le résultat.

Le code s'exécute dans votre navigateur (Web Worker isolé). Il n'a pas accès au serveur ; l'accès réseau est désactivé pendant l'exécution. Le premier clic sur « Exécuter » télécharge Pyodide depuis jsDelivr (plusieurs mégaoctets, version 0.26.4 épinglée) ; rien n'est chargé avant ce clic.

La sortie vérifiée le 2026-11-01 est :

fenêtres: [100.0, 75.0, 50.0, 25.0, 0.0]
RSCU Ala: {'GCT': 0.468, 'GCC': 1.455, 'GCA': 0.623, 'GCG': 1.455}
CAI: 0.7937

Le CAI de 0,7937 correspond à la moyenne géométrique de 1, 0,5 et 1 : (1×0,5×1)1/3≈0,7937(1 \times 0{,}5 \times 1)^{1/3} \approx 0{,}7937. La fonction exclut bien le codon stop TAA et les codons ATG et TGG. Elle ne vérifie pas la présence de tous les poids nécessaires : dans un usage réel, il faut valider la référence avant l'appel, comme le fait le mini-projet.

Biopython fournit une implémentation de référence. Le bloc suivant construit un index à partir de trois CDS synthétiques, affiche les poids de quelques codons et calcule un CAI. Il faut l'exécuter avec Biopython 1.88 installé.

from Bio.SeqUtils import CodonAdaptationIndex
 
references = ["ATGGCTGCTTAA", "ATGGCCGCATAA", "ATGGGTGGTTAA"]
index = CodonAdaptationIndex(references)
print("poids GCT, GCC, GGT:", [round(index[c], 3) for c in ("GCT", "GCC", "GGT")])
print("CAI avec stop:", round(index.calculate("ATGGCTGCCGGTTAA"), 4))
for stop in ("TAA", "TAG", "TGA"):
    index.pop(stop, None)
print("CAI sans stop:", round(index.calculate("ATGGCTGCCGGTTAA"), 4))

Sortie vérifiée le 2026-11-01 avec Biopython 1.88 :

poids GCT, GCC, GGT: [1.0, 0.5, 1.0]
CAI avec stop: 0.8409
CAI sans stop: 0.7937

L'écart entre 0,8409 et 0,7937 n'est pas une erreur d'arrondi : dans la version 1.88, calculate compte le codon stop terminal lorsque son poids est présent dans l'index, car le codon existe dans le dictionnaire. La branche prévue pour les stops absents n'est donc pas utilisée dans ce cas. Pour appliquer la convention de Sharp et Li, retirez les trois codons stop de l'index avant l'appel, ou utilisez une fonction qui les exclut explicitement. Ce détail illustre une règle générale : une valeur de CAI n'est comparable qu'à convention de calcul égale.

Étude de cas

Nous analysons le gène lacZ d'E. coli K-12 MG1655, qui code la β-galactosidase. Dans la version NC_000913.3, la CDS est portée par le brin moins aux positions 363 231–366 305. Elle mesure 3 075 pb, soit 1 025 codons dont le codon stop TAA, et 1 024 acides aminés. Coordonnées vérifiées dans GenBank le 2026-11-01 (produit NP_414878.1 [À VÉRIFIER]).

La composition de lacZ est-elle homogène, et son usage des codons ressemble-t-il à celui des gènes très exprimés ? Nous extrayons la CDS, calculons les compositions, puis construisons un CAI avec 20 gènes de référence très exprimés.

L'extraction utilise EFetch avec strand=2 pour lire le brin moins dans le sens 5'→3'. Le code ci-dessous vérifie la longueur, le codon start et le codon stop avant tout calcul.

from collections import Counter
from time import sleep
from urllib.error import URLError
 
from Bio import Entrez, SeqIO
 
# Remplacez par votre adresse de contact pour NCBI.
Entrez.email = "cours-bioinfo@example.org"
 
 
def fetch_cds(symbol, start, stop):
    for attempt in range(3):
        try:
            handle = Entrez.efetch(
                db="nuccore", id="NC_000913.3", seq_start=max(1, start - 100),
                seq_stop=stop + 100, rettype="gb", retmode="text",
            )
            record = SeqIO.read(handle, "genbank")
        except (URLError, TimeoutError):
            if attempt == 2:
                raise
            sleep(2)
            continue
        for feature in record.features:
            if feature.type == "CDS" and symbol in feature.qualifiers.get("gene", []):
                return str(feature.extract(record.seq)).upper()
        raise ValueError(f"CDS not found: {symbol}")
 
 
def gc_percent(seq):
    return 100.0 * (seq.count("G") + seq.count("C")) / len(seq)
 
 
lacz = fetch_cds("lacZ", 363231, 366305)
sense = lacz[:-3]
counts = Counter(lacz[i:i + 3] for i in range(0, len(lacz) - 2, 3))
print("lacZ:", len(lacz), "pb,", len(lacz) // 3, "codons, stop", lacz[-3:])
print("start:", lacz[:3], "premiers acides aminés:", lacz[:30])
print("GC global:", round(gc_percent(lacz), 2))
print("GC1:", round(gc_percent(sense[0::3]), 2))
print("GC2:", round(gc_percent(sense[1::3]), 2))
print("GC3:", round(gc_percent(sense[2::3]), 2))
print("codons les plus fréquents:", counts.most_common(5))

Sortie vérifiée le 2026-11-01 :

lacZ: 3075 pb, 1025 codons, stop TAA
start: ATG premiers acides aminés: ATGACCATGATTACGGATTCACTGGCCGTC
GC global: 56.26
GC1: 62.11
GC2: 43.65
GC3: 63.18
codons les plus fréquents: [('CTG', 54), ('GAA', 47), ('CAG', 43), ('GAT', 42), ('TGG', 39)]

Le GC global de 56,26 % est supérieur au GC moyen du chromosome, proche de 50 %. Le GC3 de 63,18 % est encore plus élevé, tandis que le GC2 de 43,65 % est plus faible. Cette asymétrie est cohérente avec la structure du code génétique : la deuxième position est fortement contrainte par l'acide aminé, la troisième beaucoup moins. Elle ne prouve pas à elle seule une sélection pour la traduction ; elle peut aussi refléter la composition mutationnelle de la région.

Pour le CAI, nous construisons une référence de 20 gènes très exprimés : 16 protéines ribosomiques, le facteur d'élongation EF-Tu (tufA), EF-G (fusA), la chaperonine GroEL (groL) et la porine OmpA (ompA). Les coordonnées sont celles de NC_000913.3, vérifiées le 2026-11-01. Le script ci-dessous extrait chaque CDS par son annotation, construit l'index et calcule le CAI de lacZ.

from math import exp, log
from time import sleep
from urllib.error import URLError
 
from Bio import Entrez, SeqIO
from Bio.SeqUtils import CodonAdaptationIndex
 
# Remplacez par votre adresse de contact pour NCBI.
Entrez.email = "cours-bioinfo@example.org"
 
REFERENCE_GENES = {
    "rpsA": (961994, 963667), "rpsB": (189873, 190598),
    "rpsC": (3449181, 3449882), "rpsD": (3441054, 3441674),
    "rpsE": (3444725, 3445228), "rpsG": (3473541, 3474080),
    "rpsJ": (3452958, 3453269), "rplA": (4178878, 4179582),
    "rplB": (3450542, 3451363), "rplC": (3452296, 3452925),
    "rplD": (3451680, 3452285), "rplE": (3446898, 3447437),
    "rplJ": (4179995, 4180492), "rplK": (4178446, 4178874),
    "rplL": (4180559, 4180924), "rplM": (3378222, 3378650),
    "tufA": (3470144, 3471328), "fusA": (3471399, 3473513),
    "groL": (4371024, 4372670), "ompA": (1019012, 1020052),
}
 
 
def fetch_cds(symbol, start, stop):
    for attempt in range(3):
        try:
            handle = Entrez.efetch(
                db="nuccore", id="NC_000913.3", seq_start=max(1, start - 100),
                seq_stop=stop + 100, rettype="gb", retmode="text",
            )
            record = SeqIO.read(handle, "genbank")
        except (URLError, TimeoutError):
            if attempt == 2:
                raise
            sleep(2)
            continue
        for feature in record.features:
            if feature.type == "CDS" and symbol in feature.qualifiers.get("gene", []):
                return str(feature.extract(record.seq)).upper()
        raise ValueError(f"CDS not found: {symbol}")
 
 
def cai(cds, weights):
    logs = []
    for i in range(0, len(cds), 3):
        codon = cds[i:i + 3]
        if codon in {"ATG", "TGG", "TAA", "TAG", "TGA"}:
            continue
        logs.append(log(weights[codon]))
    return exp(sum(logs) / len(logs))
 
 
lacz = fetch_cds("lacZ", 363231, 366305)
reference = []
for symbol, (start, stop) in REFERENCE_GENES.items():
    reference.append(fetch_cds(symbol, start, stop))
    sleep(0.34)
 
index = CodonAdaptationIndex(reference)
weights = dict(index)
for stop in ("TAA", "TAG", "TGA"):
    weights.pop(stop, None)
print("CAI lacZ:", round(cai(lacz, weights), 4))
print("CAI moyen des références:", round(sum(cai(s, weights) for s in reference) / len(reference), 4))
print("poids CTG, GAA, CAG, GAT:", [round(weights[c], 4) for c in ("CTG", "GAA", "CAG", "GAT")])

Sortie vérifiée le 2026-11-01 :

CAI lacZ: 0.3436
CAI moyen des références: 0.6979
poids CTG, GAA, CAG, GAT: [1.0, 1.0, 1.0, 0.3879]

Le CAI de lacZ, 0,3436, est nettement inférieur à la moyenne des 20 gènes de référence, 0,6979. Cela ne signifie pas que lacZ n'est pas exprimé : le gène est inductible et sa traduction n'est pas comparable à celle des protéines ribosomiques en croissance rapide. Il illustre aussi la dépendance à la référence : 0,375 avec les 16 gènes ribosomiques seuls, 0,306 avec trois gènes (rpsA, rplB, tufA). Un CAI n'est donc jamais une propriété intrinsèque du gène ; c'est une comparaison.

Les codons CTG, GAA et CAG ont un poids de 1,0, et CTG est le codon le plus fréquent de lacZ (54 occurrences). GAT, fréquent dans lacZ (42 occurrences), a pourtant un poids plus faible (0,388) : la fréquence dans un gène ne définit pas une préférence de référence. Des codons rares comme AGA ou AGG ont un poids très faible et pénalisent le CAI. Cette lecture ne démontre pas un effet sur le taux de traduction, qui dépendrait aussi de la structure de l'ARNm, de la position des codons et de la disponibilité des ARN de transfert.

Erreurs fréquentes

Quiz

  1. Question 1.Que mesure le GC3 d'une séquence codante ?
  2. Question 2.Dans une famille de quatre codons, un codon a un RSCU de 2. Que signifie cette valeur ?
  3. Question 3.Pourquoi un CAI calculé avec les gènes ribosomiques diffère-t-il d'un CAI calculé avec tous les gènes ?
  4. Question 4.Quel module de Biopython 1.88 faut-il utiliser pour calculer un CAI ?
  5. Question 5.Une séquence de longueur 10 est analysée avec des fenêtres glissantes de taille 4. Combien de valeurs obtient-on ?
Répondez à toutes les questions pour valider.

Exercices

Exercice guidé1.5-e1

Énoncé

Implémenter gc_windows(seq, window), codon_frequencies(seq) et rscu(counts). gc_windows renvoie la liste des GC des fenêtres glissantes de taille window, pas de 1, en comptant les N au dénominateur ; une fenêtre nulle ou négative lève ValueError, une fenêtre plus grande que la séquence renvoie une liste vide. codon_frequencies vérifie que la longueur est un multiple de 3 et que l'alphabet est ACGT, puis renvoie les 64 codons avec leurs effectifs. rscu renvoie les 61 codons sens, exclut les codons stop et attribue 0,0 aux familles absentes. Les fonctions de séquence normalisent la casse et les trois fonctions rejettent les types incorrects.

Comment vérifier votre travail

Les tests se trouvent dans exercises/module-1/1.5-contenu-gc-usage-codons/test_1_5.py. Depuis la racine du dépôt :

python -m pytest exercises/module-1/1.5-contenu-gc-usage-codons -q

Corrigé verrouillé

Le corrigé est chargé uniquement après confirmation. Il n'est pas présent dans la page avant cette action.

Exercice approfondi1.5-e2

Énoncé

Implémenter cai(cds, reference_weights) avec validation complète : la CDS doit être non vide, de longueur multiple de 3 et composée de ACGT ; reference_weights doit être un dictionnaire non vide de poids strictement positifs pour les codons utilisés. La fonction exclut ATG, TGG et les trois codons stop, puis renvoie la moyenne géométrique des poids. Elle lève ValueError si un poids manque, si un poids est nul ou négatif, ou si aucun codon n'est utilisable. Vérifier ensuite que le résultat coïncide avec Bio.SeqUtils.CodonAdaptationIndex.calculate après retrait des codons stop de l'index.

Comment vérifier votre travail

Les tests se trouvent dans exercises/module-1/1.5-contenu-gc-usage-codons/test_1_5.py. Depuis la racine du dépôt :

python -m pytest exercises/module-1/1.5-contenu-gc-usage-codons -q

Corrigé verrouillé

Le corrigé est chargé uniquement après confirmation. Il n'est pas présent dans la page avant cette action.

Mini-projet1.5-projet

Énoncé

Mini-projet : rapport d'usage des codons. Implémenter codon_report(cds, reference_cds_list) qui valide la CDS (longueur multiple de 3, alphabet ACGT, codon stop terminal) et la liste de référence (au moins une CDS valide), construit un CodonAdaptationIndex avec Biopython 1.88, puis renvoie un dictionnaire contenant length_bp, length_codons, protein_length, stop_codon, gc, gc1, gc2, gc3, cai, codon_counts, rscu et preferred_codons. Les GC de position portent sur les codons sens, le codon stop est exclu. preferred_codons contient au plus cinq entrées triées par RSCU décroissant, puis par effectif décroissant, puis par codon. Toute erreur de longueur, d'alphabet, de codon stop ou de référence vide lève ValueError ; un type incorrect lève TypeError.

Comment vérifier votre travail

Les tests se trouvent dans exercises/module-1/1.5-contenu-gc-usage-codons/projet/test_projet_1_5.py. Depuis la racine du dépôt :

python -m pytest exercises/module-1/1.5-contenu-gc-usage-codons/projet -q

Corrigé verrouillé

Le corrigé est chargé uniquement après confirmation. Il n'est pas présent dans la page avant cette action.

Résumé

  • Le contenu en GC se calcule en O(n)O(n) et dépend du périmètre : génome, CDS ou fenêtre.
  • Les fenêtres glissantes révèlent l'hétérogénéité locale ; leur taille et leur dénominateur doivent être explicites.
  • Le GC3 mesure la troisième position des codons sens et porte l'essentiel du biais d'usage.
  • Le RSCU normalise les effectifs par famille ; sa somme vaut le nombre de codons synonymes.
  • Le CAI est une moyenne géométrique de poids relatifs estimés sur des gènes très exprimés.
  • Un CAI n'a de sens que relativement à sa référence et à sa convention sur les codons stop.
  • Biopython 1.88 expose CodonAdaptationIndex ; CodonUsage est déprécié.
  • Toute analyse d'usage des codons doit publier la référence, la version et les filtres appliqués.

Références