6
$\begingroup$

Given a read ID, I want to edit a single basecall (e.g. the 12th base) for just that read from within a large FASTQ file containing millions of reads.

example, i want to change the 12th base ('C') in read 31027 to a 'T':

@70630 1:N:0:ATCACG
GAAGGTCCATGGATAATACTCAATTTTCCACAACAGCTTTTGTACTCTAGATCATTGATATTTACCAAAAGTCACTCAAACTCATCCTATGCATAATTCTAGTCCACCAATCATGATATGATGGAGAACATGGTTGTAATCAGGAAGACAG
+
DDDDDHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIGHHIIIIIIIIIIIIIIIIIIIIIIHIIHIHIIIHHIGIIIIHHHHIIH@
@31027 1:N:0:ATCACG
CAAAAGTCACTCAAACTCATCCTATGCATAATTCTAGTCCACCAATCATGATATGATGGAGAACATGGTTGTAATCAGGAAGACAGATAAAGCAGCAGACCAAAAGTAATCTGAGAAATTATATTTGAATCACTCAGATATACATCAAATA
+
DDBDDHC@GHFHHIIE@CEHHIHEFFCGFCH?HHEGFCCEHHCGH@HFHHHCHHIIIHEHIIHII@CECHIHIIIEECCDGEHFFHHHHEHHFHHGGIHHHDGHFHIIIGHHHHHHEHHIIHIIIGGHHHCHHHCHIIIHHIEH@GHIHIC
@87319 1:N:0:ATCACG
CAATTAAGCTTTGGCAACGGTGGTCAAGATGAGATGCATATGGAGATAATAACTAAAAGTCAATCGAGACTCATCGTATGCATATTTCTAGTCCATCGATCATGAAATGATAGGATAGCTAGAATGAAAAGTAAATTTCCAGAAGGTCCAT
+
DDDDDIIIIIIIIIIIIIHIHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHHIIIIIIIIIIIIIIIIIHIIHIIIIIIIIIIIIHIIIIIIIIIHIHIH

Of course I could stream through the entire FASTQ file rewriting everything to a new file until i get to the read of interest, do the edits to that read, write it out to the new file, and then keep going until the end. BioPython would work fine for this as would other approaches.

However, is there an efficient way to do this without the full read/write stream? Could this be done with sed/awk ? What about an indexed fastq file?

cheers David

$\endgroup$
  • $\begingroup$ Just out of curiosity, why do you need to edit your reads? $\endgroup$ – Joe Healey Aug 7 '17 at 11:07
  • $\begingroup$ Yes, sed/awk can do this but unless you have built some sort of index every approach will have to read through the file. On the bright side, that won't be too slow with fast tools like sed or awk. $\endgroup$ – terdon Aug 7 '17 at 11:33
  • 1
    $\begingroup$ @JoeHealey I am introducing SNVs into specific samples in order to estimate false negative rates for a variant calling pipeline. I know reads can be simulated but I would actually prefer to use the real data so as to keep everything else equal. $\endgroup$ – dkainer Aug 7 '17 at 23:56
5
$\begingroup$

You'll first need to determine the appropriate line number, which you can do with grep -m1 -nw "@31027" foo.fastq. After that, note that you can provide a line number to sed:

sed -i '123456s/CAAAAGTCACTCA/CAAAAGTCACTTA/' foo.fastq

That will do the replacement only on line 123456 and edit the file in place (the -i option).

$\endgroup$
  • $\begingroup$ I was not aware of the -n option for grep. This should do the job $\endgroup$ – dkainer Aug 7 '17 at 23:53
  • 1
    $\begingroup$ @dkainer just for completion's sake, you can get the line number of the line(s) matching the string foo with sed -n /foo/= or perl -ne 'print $. if /foo/ or awk '/foo/{print NR} as well. $\endgroup$ – terdon Aug 8 '17 at 8:48
2
$\begingroup$

If your fastq file is simple, if each of your reads only has a single line of DNA, you could do:

awk '{
        if($1 == "@31027"){
            a=NR+1
        } 
        if(NR==a){
            split($0,s,""); 
            s[12]="T"; 
            for(i in s){
                seq = sprintf("%s%s",seq,s[i]);
            } 
            $0=seq
        }
    }1;' file.fastq 
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.