← Catalogo
ORF
PyJS

Open Reading Frames

Combinatorics

Pagina originale su rosalind.info

Descrizione

Una stringa di DNA implica sei possibili reading frame (tre lette direttamente, tre sul reverse complement). Un Open Reading Frame (ORF) inizia con il codone di start (AUG) e termina con un codone di stop, senza altri codoni di stop nel mezzo. Ogni ORF corrisponde a una possibile stringa proteica candidata.

Given

Una stringa di DNA s di lunghezza massima 1 kbp, in formato FASTA.

Return

Ogni distinta stringa proteica candidata traducibile dagli ORF di s. Le stringhe possono essere restituite in qualsiasi ordine.

Sample Dataset

>Rosalind_99
AGCCATGTAGCTAACTCAGGTTACATGGGGATGACCCCGCGACTTGGATTAGAGTCTCTTTTGGAATAAGCCTGAATGATCCGAGTAGCATCTCAG

Sample Output

MLLGSFRLIPKETLIQVAGSSPCNLS
M
MGMTPRLGLESLLE
MTPRLGLESLLE

La mia esecuzione

08/24/2026 11:24:47

Input · dataset.txt

>Rosalind_2649
ATTCGTTCCATTAAGAATACGGGATCTTATGCCATCAACCATTGCAACAACCCCCCCAGT
AATTAGCCAGGCTTTTAAGATACCAGATTAGAGCGCAAAGCTGTTCCATGCATGCTACGG
TCGATGTAGTAGTAATAATCTAACGTAATGAGGATGGCACCACCGAGTCCTCGCGGTTAG
ACAGGGTACCTATGCCATCACTCTGAAAAAACGAAATGTGCTCTAAGAGCTCCAGTTTGG
AACTTGGATTGGATAACCAGAATTCATGCGAACCCGGCGGGGCTTATCCCCAGTCGCAAC
AGACAGATTCGTTCGCCGTCAAGCACACTTGATCGTACGAATTTCCATCAAAGGAGGCAA
CAGGCGCATTCTCGACAGGACGTTGGATCAGTTCAGGTTCGCACTGGCGCGGATGGACTG
GAAGCAAGTTCTTTAGCTAAAGAACTTGCTTCCAGTCCATATGTCGCTCTTGTATACACA
TTGTATCGTAGTCTCTGTCAACACCAGGCCGTTCAATAAGACTCTCAACAATCCGGCTCA
CTAGCGATTCAAGGAGTGACTGTGTTCGAGATACCATCCACATTCCCGTCGTTACATCGT
ATGTCAAGCAGAATGAAGGTGGAACCCTGGAGCCTGCTGCTTTTGGGAGGCCTCCGATTC
CTACGCTGCGGCGATAGCCACTTTGTCCTACCCCATTGTCCGTGCTCCCGCCTCGTGGCT
GTAGTACAACTAACCCCGCACCGGGCTGGTCAAAGCAGTATACTGTTATAAATTGGCAGG
ATAAACCTGAGGTATAACCTGACTATGTGTGACTGTATCACAATATAGGCGCAATAAGCG
TTTCCACGACGAGTTGCCACAGTGACTTACCC

Output · run_log.txt

OK
MLRSM
M
MRMAPPSPRG
MAPPSPRG
MSSRMKVEPWSLLLLGGLRFLRCGDSHFVLPHCPCSRLVAVVQLTPHRAGQSSILL
MKVEPWSLLLLGGLRFLRCGDSHFVLPHCPCSRLVAVVQLTPHRAGQSSILL
MCDCITI
MPSTIATTPPVISQAFKIPD
MRTRRGLSPVATDRFVRRQAHLIVRISIKGGNRRILDRTLDQFRFALARMDWKQVL
MDWKQVL
MSLLYTHCIVVSVNTRPFNKTLNNPAH
MHATVDVVVII
MPSL
MCSKSSSLELGLDNQNSCEPGGAYPQSQQTDSFAVKHT
MHGTALRSNLVS
MA
MWMVSRTQSLLESLVSRIVESLIERPGVDRDYDTMCIQERHMDWKQVL
MVSRTQSLLESLVSRIVESLIERPGVDRDYDTMCIQERHMDWKQVL
MCIQERHMDWKQVL
MEQLCALIWYLKSLANYWGGCCNG
MG
MRLLPPLMEIRTIKCA
MEIRTIKCA
MNSGYPIQVPNWSS

Esegui nel browser · Pyodide

Mostra il codice sorgente (problem.py)
mappa = {"UUU":"F", "UUC":"F", "UUA":"L", "UUG":"L",
    "UCU":"S", "UCC":"S", "UCA":"S", "UCG":"S",
    "UAU":"Y", "UAC":"Y", "UAA":"STOP", "UAG":"STOP",
    "UGU":"C", "UGC":"C", "UGA":"STOP", "UGG":"W",
    "CUU":"L", "CUC":"L", "CUA":"L", "CUG":"L",
    "CCU":"P", "CCC":"P", "CCA":"P", "CCG":"P",
    "CAU":"H", "CAC":"H", "CAA":"Q", "CAG":"Q",
    "CGU":"R", "CGC":"R", "CGA":"R", "CGG":"R",
    "AUU":"I", "AUC":"I", "AUA":"I", "AUG":"M",
    "ACU":"T", "ACC":"T", "ACA":"T", "ACG":"T",
    "AAU":"N", "AAC":"N", "AAA":"K", "AAG":"K",
    "AGU":"S", "AGC":"S", "AGA":"R", "AGG":"R",
    "GUU":"V", "GUC":"V", "GUA":"V", "GUG":"V",
    "GCU":"A", "GCC":"A", "GCA":"A", "GCG":"A",
    "GAU":"D", "GAC":"D", "GAA":"E", "GAG":"E",
    "GGU":"G", "GGC":"G", "GGA":"G", "GGG":"G"}

START = "AUG"

FIRST = "<"
LAST = ">" 

def RNA2PRT(inputFunc):
    def RNA2PRT(*args):
        record = inputFunc(*args) 
        stringa = ""   
        terna = ""     
        t=0
        for i in range(len(record)):
            terna += record[i]
            t = (t + 1)%3 
            if t == 0:
               if terna not in mappa:
                  stringa += "?"
               elif terna == START:
                  stringa += "<"+mappa[terna]
               elif mappa[terna].upper() == "STOP":
                  stringa += ">"
               else :
                  stringa += mappa[terna]
               terna = ""
        return stringa
    return RNA2PRT

def get_chunks(inputFunc):
    def get_chunks(*args):
        prt = inputFunc(*args)  
        chunks = []
        for i in range(len(prt)):
            if prt[i]==FIRST:
               j = prt.find(LAST, i+1)
               if j !=-1:
                  chunks.append(prt[i:j])
        return chunks
    return get_chunks

@get_chunks
@RNA2PRT
def DNA2PRT(record):
    return record.replace('T', 'U')

def lettura(filename):
    data = []
    with open(filename) as f:
        header = None
        body = ""   
        for riga in f:
               riga = riga.rstrip("\n")
               if riga[0] == ">":
                  if header is None:   
                     header = riga[1:]
                  else:
                     data.append({"header": header, "body": body})
                     header = riga
                     body = ""
               else:             
                  body += riga
        data.append({"header": header, "body": body})
    return data


def reverseDNA(dna):
    s = ""
    for i in range(len(dna)):
        key = dna[len(dna)-1-i]
        if key == 'G':
           key = 'C'
        elif key == 'C':
           key = 'G'
        elif key == 'T':
           key = 'A'
        elif key == 'A':
           key = 'T'
        s+=key
    return s


def step(soluzioni, dna):
    for i in [0, 1, 2]:
        sequence = dna[i:]
        chunks = DNA2PRT(sequence)
        for j in range(len(chunks)):
            current = chunks[j].replace(FIRST, '').replace(LAST, '') 
            if current not in soluzioni:
               soluzioni.append(current)
    return soluzioni               

def main():
    soluzioni = []
    records = lettura("dataset.txt")
    record = records[0]   
    dna = record["body"]
    step(soluzioni, dna)
    dna = reverseDNA(dna)    
    step(soluzioni, dna)
    for sol in soluzioni:
        print(sol)

if __name__ == "__main__":
    # execute only if run as a script
    main()

Soluzione JavaScript

Esegui ora, live

Mostra il codice sorgente
// Open Reading Frames (Rosalind ID: ORF) - soluzione JavaScript
// indipendente, non una trascrizione di problem.py: stessa logica
// (traduce ciascuno dei 3 frame di lettura in avanti e dei 3 sul
// complemento inverso, marcando ogni "AUG" come possibile inizio e ogni
// stop come fine, poi estrae tutte le sottosequenze proteiche valide -
// una per ogni AUG interno fino al primo stop successivo - deduplicando
// i risultati), riscritta in modo idiomatico per JS.
//
// I due decoratori Python (RNA2PRT, get_chunks) sono qui semplici
// funzioni in pipeline, non un'astrazione a decoratori - stesso
// comportamento, resa più diretta in JS.
//
// Contratto: riceve il contenuto testuale di dataset.txt, restituisce
// l'output testuale (stessa forma dell'output Python).
const MAPPA = {
  UUU: "F", UUC: "F", UUA: "L", UUG: "L",
  UCU: "S", UCC: "S", UCA: "S", UCG: "S",
  UAU: "Y", UAC: "Y", UAA: "STOP", UAG: "STOP",
  UGU: "C", UGC: "C", UGA: "STOP", UGG: "W",
  CUU: "L", CUC: "L", CUA: "L", CUG: "L",
  CCU: "P", CCC: "P", CCA: "P", CCG: "P",
  CAU: "H", CAC: "H", CAA: "Q", CAG: "Q",
  CGU: "R", CGC: "R", CGA: "R", CGG: "R",
  AUU: "I", AUC: "I", AUA: "I", AUG: "M",
  ACU: "T", ACC: "T", ACA: "T", ACG: "T",
  AAU: "N", AAC: "N", AAA: "K", AAG: "K",
  AGU: "S", AGC: "S", AGA: "R", AGG: "R",
  GUU: "V", GUC: "V", GUA: "V", GUG: "V",
  GCU: "A", GCC: "A", GCA: "A", GCG: "A",
  GAU: "D", GAC: "D", GAA: "E", GAG: "E",
  GGU: "G", GGC: "G", GGA: "G", GGG: "G",
};
const START = "AUG";

// Traduce l'RNA in una stringa "marcata": '<' + M prima di ogni AUG
// (possibile inizio ORF), '>' al posto di ogni stop, '?' per codoni
// sconosciuti (es. lunghezza non multipla di 3 all'ultima terna).
function rna2prt(rna) {
  let stringa = "";
  let terna = "";
  let t = 0;
  for (const ch of rna) {
    terna += ch;
    t = (t + 1) % 3;
    if (t === 0) {
      if (!(terna in MAPPA)) stringa += "?";
      else if (terna === START) stringa += `<${MAPPA[terna]}`;
      else if (MAPPA[terna] === "STOP") stringa += ">";
      else stringa += MAPPA[terna];
      terna = "";
    }
  }
  return stringa;
}

// Per ogni '<' nella stringa marcata, estrae il chunk fino al primo '>'
// successivo (se esiste) - un chunk per OGNI AUG interno, non solo il
// primo, così un frame con AUG multipli produce un ORF candidato per
// ciascuno.
function getChunks(prt) {
  const chunks = [];
  for (let i = 0; i < prt.length; i++) {
    if (prt[i] === "<") {
      const j = prt.indexOf(">", i + 1);
      if (j !== -1) chunks.push(prt.slice(i, j));
    }
  }
  return chunks;
}

function dna2prt(sequenceDna) {
  const rna = sequenceDna.replaceAll("T", "U");
  return getChunks(rna2prt(rna));
}

const COMPLEMENT = { A: "T", T: "A", C: "G", G: "C" };
function reverseDNA(dna) {
  let s = "";
  for (let i = dna.length - 1; i >= 0; i--) {
    s += COMPLEMENT[dna[i]] ?? dna[i];
  }
  return s;
}

function parseFasta(testo) {
  const righe = testo.split("\n").map((r) => r.replace(/\r$/, ""));
  const bodies = [];
  let corpo = "";
  let first = true;
  for (const riga of righe) {
    if (riga.startsWith(">")) {
      if (!first) bodies.push(corpo);
      corpo = "";
      first = false;
    } else {
      corpo += riga;
    }
  }
  bodies.push(corpo);
  return bodies;
}

function step(soluzioni, dna) {
  for (const i of [0, 1, 2]) {
    const sequence = dna.slice(i);
    const chunks = dna2prt(sequence);
    for (const chunk of chunks) {
      const current = chunk.replaceAll("<", "").replaceAll(">", "");
      if (!soluzioni.includes(current)) soluzioni.push(current);
    }
  }
  return soluzioni;
}

export default function solve(datasetText) {
  const records = parseFasta(datasetText);
  const dna = records[0];

  if (!dna) {
    throw new Error("Input non valido: nessuna sequenza FASTA trovata");
  }

  const soluzioni = [];
  step(soluzioni, dna);
  step(soluzioni, reverseDNA(dna));

  return `${soluzioni.join("\n")}\n`;
}