Skip to content

Commit

Permalink
MinION workflow update with ex3
Browse files Browse the repository at this point in the history
  • Loading branch information
lerch-a committed Nov 21, 2024
1 parent e19f92b commit 2042407
Show file tree
Hide file tree
Showing 59 changed files with 567 additions and 95 deletions.
110 changes: 41 additions & 69 deletions R/callHaplotypeDADA2.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,18 @@ createFinalHaplotypTableDADA2 <- function(outputDir, sampleTable, markerTable, r
minHaplotypCoverage=3, minReplicate=2,
detectability=1/100, minSampleCoverage=300,
minSeqLength=5, maxSeqLength=9999, filterIndel=T,
tempdir=tempdir(),
multithread=FALSE, pool="pseudo", OMEGA_A=1e-120){
require(dada2)

# check if input file exists
sampleTable <- sampleTable[!is.na(sampleTable$ReadFile),]
sampleTable <- sampleTable[file.exists(sampleTable$ReadFile),]
sampleTable <- sampleTable[!is.na(sampleTable$FileR1),]
sampleTable <- sampleTable[file.exists(sampleTable$FileR1),]

# check args
stopifnot(
is.character(outputDir), length(outputDir) == 1, file.exists(outputDir),
is.data.frame(sampleTable), all(c("MarkerID", "ReadFile", "SampleID", "SampleName","numRead") %in% colnames(sampleTable)),
is.character(sampleTable$ReadFile),
is.data.frame(sampleTable), all(c("MarkerID", "FileR1", "SampleID", "SampleName") %in% colnames(sampleTable)),
is.character(sampleTable$FileR1),
is.data.frame(markerTable), all(c("MarkerID") %in% colnames(markerTable)),
is.character(postfix), length(postfix) == 1,
is.numeric(minHaplotypCoverage), length(minHaplotypCoverage) == 1,
Expand All @@ -44,17 +43,17 @@ createFinalHaplotypTableDADA2 <- function(outputDir, sampleTable, markerTable, r
}

# filter read file
filtDir <- file.path(tempdir,"filtered")
filtDir <- file.path(outputDir,"filtered")
dir.create(filtDir)
newFile <- file.path(filtDir, basename(sampleTable$ReadFile))
numReads <- unlist(lapply(seq_along(sampleTable$ReadFile), function(ii){
sr <- readFastq(sampleTable$ReadFile[ii])
newFile <- file.path(filtDir, basename(sampleTable$FileR1))
numReads <- unlist(lapply(seq_along(sampleTable$FileR1), function(ii){
sr <- readFastq(sampleTable$FileR1[ii])
sr <- sr[minSeqLength<width(sr) & width(sr)<maxSeqLength]
sr <- rmNreads(sr)
#length(sr)
writeFastq(sr, newFile[[ii]], compress = T)
}))
sampleTable$ReadFile <- newFile
sampleTable$FileR1 <- newFile
sampleTable$numReads <- numReads
sampleTable <- sampleTable[sampleTable$numReads>=3,]
#write.table(sampleTable, "demultiplexMarkerSummary_MinION_filt.txt", sep="\t", row.names=F)
Expand All @@ -64,24 +63,25 @@ createFinalHaplotypTableDADA2 <- function(outputDir, sampleTable, markerTable, r
# compress=TRUE, multithread=TRUE)

# run dada2
err <- learnErrors(sampleTable$ReadFile, multithread=multithread)
err <- learnErrors(sampleTable$FileR1, multithread=multithread)
# plotErrors(err, nominalQ=TRUE)
dadas <- dada(sampleTable$ReadFile, err=err, multithread=multithread, pool=pool, OMEGA_A=OMEGA_A)
dadas <- dada(sampleTable$FileR1, err=err, multithread=multithread, pool=pool, OMEGA_A=OMEGA_A)
seqtab <- makeSequenceTable(dadas)
# remove chimera
seqtab.nochim <- removeBimeraDenovo(seqtab, method="consensus", multithread=multithread, verbose=TRUE)
#sum(seqtab.nochim)/sum(seqtab)
seqtabLst <- split(as.data.frame(seqtab.nochim), sampleTable$MarkerID)
file.remove(newFile)

# Apply cut-off only in 1 sample
selMarker <- unique(sampleTable$MarkerID)
resultsLst <- lapply(selMarker, function(nm){
# nm <- "ama1_D3"
# message(nm)
# get read counts and rename sample
markTab <- seqtabLst[[nm]]
markTab <- markTab[,colSums(markTab)>0, drop=F]
rownames(markTab) <- sampleTable$SampleID[match(rownames(markTab), basename(sampleTable$ReadFile))]
rownames(markTab) <- sampleTable$SampleID[match(rownames(markTab), basename(sampleTable$FileR1))]
# get haplotype sequence
haplotyp <- DNAStringSet(colnames(markTab))

Expand Down Expand Up @@ -121,66 +121,38 @@ createFinalHaplotypTableDADA2 <- function(outputDir, sampleTable, markerTable, r
})
names(resultsLst) <- selMarker

file.remove(newFile[file.exists(newFile)])
file.remove(newFile) # list.files(filtDir,"fastq.gz"))
file.remove(filtDir)
finalHaplotyopList <- writeHaplotypList(resultsLst)
#write.csv(finalHaplotyopList, file=file.path(outputDir, "finalHaplotypList_MinION_MH.csv"), row.names=F)
haplotyopList <- writeHaplotypList(resultsLst)

## Start TODO
#browser()
## check replicates
if(minReplicate==1){
rownames(haplotyopList) <- NULL
return(haplotyopList)
}else{
stop("Filtering by replicate is currently not supported. Please run it without accounting for with 'minReplicate==1'")
haplotyopList <- haplotyopList
samTab <- sampleTable[,c("SampleID","SampleName")]
samTab <- samTab[!duplicated(samTab),]
rownames(samTab) <- samTab$SampleID
haplotyopList <- split(haplotyopList, paste(samTab[haplotyopList$SampleID,"SampleName"], haplotyopList$MarkerID))
haplotyopList <- do.call(rbind, lapply(haplotyopList, function(lst){
# lst <- haplotyopList[[1]]
isCens <- lst$Haplotype=="Censored"
tab <- table(lst$Haplotype[!isCens])
repMissing <- names(tab)[tab<minReplicate]
if(length(repMissing)>0){
lst$Haplotype[lst$Haplotype %in% repMissing] <- "ReplicatMissing"
}
return(lst)
}))
rownames(haplotyopList) <- NULL
return(haplotyopList)
}

# set final haplotype names
# rownames(haplotypesSample) <- overviewHap[rownames(haplotypesSample), "FinalHaplotype"]
# if(devMode)
# write.table(cbind(HaplotypNames=rownames(haplotypesSample),haplotypesSample),
# file=file.path(outputDir, sprintf("rawHaplotypeTable_%s%s.txt", marker, postfix)), sep="\t", row.names=F, col.names=T)

# haplotypesSample <- reclusterHaplotypesTable(haplotypesSample)
# if(devMode)
# write.table(cbind(HaplotypNames=rownames(haplotypesSample),haplotypesSample),
# file=file.path(outputDir, sprintf("reclusteredHaplotypeTable_%s%s.txt", marker, postfix)), sep="\t", row.names=F, col.names=T)

# # Apply cut-off haplotype only in 1 sample
# haplotypesSample <- callHaplotype(haplotypesSample, minHaplotypCoverage=minHaplotypCoverage, minReplicate=minReplicate,
# detectability=detectability, minSampleCoverage=1)

# if(devMode)
# write.table(cbind(HaplotypNames=rownames(haplotypesSample), haplotypesSample),
# file=file.path(outputDir, sprintf("finalHaplotypeTable_Hcov%.0f_Scov%.0f_occ%i_sens%.4f_%s%s.txt",
# minHaplotypCoverage, minSampleCoverage, minReplicate, detectability, marker, postfix)),
# sep="\t", row.names=F, col.names=T)


# # check replicates
# idx <- split(1:dim(haplotypesSample)[2], samTab$SampleID)
# markerRes <- lapply(idx, function(i){
# tab <- callHaplotype(haplotypesSample[,i, drop=F], minHaplotypCoverage=minHaplotypCoverage,
# minReplicate=minReplicate, detectability=detectability, minSampleCoverage=minSampleCoverage,
# reportBackground=T)
# tab <- cbind(samTab[rep(i,each=dim(tab)[1]), c("SampleID","SampleName","MarkerID")],
# Haplotype=rownames(tab), Reads=as.integer(tab), FlagChimera=F)
# colnames(tab) <- c("SampleID","SampleName","MarkerID","Haplotype","Reads")
# rownames(tab) <- NULL
#
# #check individual samples for chimera
# do.call(rbind, lapply(split(tab, tab$SampleID), function(tt){
# chim <- NULL
# hIdx <- grep(marker, tt$Haplotype)
# if(length(hIdx)>2){
# chim <- flagChimera(tt[hIdx,], overviewHap)
# }
# tt$FlagChimera <- tt$Haplotype %in% chim
# return(tt)
# }))
# return(tab)
# })
# markerRes <- do.call(rbind.data.frame, markerRes)
# rownames(markerRes) <- NULL
# markerResFn <- file.path(outputDir, sprintf("finalHaplotypeList_Hcov%.0f_Scov%.0f_occ%i_sens%.4f_%s%s.txt",
# minHaplotypCoverage, minSampleCoverage, minReplicate, detectability, marker, postfix))
# write.table(markerRes, file=markerResFn, sep="\t", row.names=F, col.names=T)
# return(markerRes)
## End TODO
return(finalHaplotyopList)
# write.table(haplotyopList, file=markerResFn, sep="\t", row.names=F, col.names=T)
# write.csv(haplotyopList, file=markerResFn, row.names=F)
}

7 changes: 4 additions & 3 deletions R/minION_function.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ demultiplexByMarkerMinION <- function (sampleTable, markerTable, outputDir, trim


removePrimerMinION <- function (fastqFileR1, outputFile, primerFwd, primerRev,
max.mismatch = 0, with.indels = F, outputPrimerSequence = F,
max.mismatch = 0, with.indels = F, outputPrimerSequence = F, outputUntrimedSequence = F,
progressReport = message) {
if (!is.function(progressReport))
progressReport <- message
Expand Down Expand Up @@ -85,8 +85,9 @@ removePrimerMinION <- function (fastqFileR1, outputFile, primerFwd, primerRev,
srR <- srR[index==1]
srR <- reverseComplement(srR)
sr <- append(srF,srR)
writeFastq(sr, file = paste(outputFile, "_untrimF.fastq.gz", sep = ""), mode = mode,
compress = T)
if(outputUntrimedSequence){
writeFastq(sr, file = paste(outputFile, "_untrimF.fastq.gz", sep = ""), mode = mode, compress = T)
}
rm(srF, srR)
if (length(sr) > 0) {
fPrimCoord <- vmatchPattern(primerFwd, sread(sr),
Expand Down
41 changes: 18 additions & 23 deletions docs/documentation/minIon_workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The HaplotypR project was developed by Anita Lerch. A paper with more details ab

* Lerch, A. et al. Development Of Amplicon Deep Sequencing Markers And Data Analysis Pipeline For Genotyping Multi-Clonal Malaria Infections. BMC Genomics (2017), 18(1), p.864, http://dx.doi.org/10.1186/s12864-017-4260-y.
* Lerch, A. et al. Longitudinal tracking and quantification of individual Plasmodium falciparum clones in complex infections. Sci. Rep. 9, 3333 (2019), http://dx.doi.org/10.1038/s41598-019-39656-7.
* xx
* Holzschuh A, et al. (2024) Using a mobile nanopore sequencing lab for end-to-end genomic surveillance of Plasmodium falciparum: A feasibility study. PLOS Glob Public Health 4(2): e0002743, https://doi.org/10.1371/journal.pgph.0002743.
* xx

# License
Expand Down Expand Up @@ -51,28 +51,28 @@ outputDir <- "exampleHaplotypR"
if(!dir.exists(outputDir))
dir.create(outputDir, recursive=T)

# Copy example files to output directory
# Copy example files to working directory
file.copy(from=system.file(package="HaplotypR", "extdata/ex3"), to=".", recursive = T)

# List files example files in output direcoty
dir(file.path("ex3"))
```
The following files should be listed with the last R command: "marker_file.txt", "reads2_F.fastq.gz", "sample_file.txt".
The following files should be listed with the last R command: "marker_file_ex3.txt", "sample_file_ex3.txt" and others.

Run demultiplexing by sample and rename output files
```R
# set input file path
primerFile <- "ex3/marker_file.txt"
sampleFile <- "ex3/sample_file.txt"
reads <- list.files("ex3", pattern="reads", full.names = T)
primerFile <- "ex3/marker_file_ex3.txt"
sampleFile <- "ex3/sample_file_ex3.txt"
readsDir <- "ex3/read_dir_ex3"

# create output subdirectory
outDeplexSample <- file.path(outputDir, "dePlexSample")
dir.create(outDeplexSample)
dir.create(outDeplexSample, recursive=T)

# rename output files to sample files
# load rename sample files and merge to a single file per sample if needed
sampleTab <- read.delim(sampleFile, stringsAsFactors=F)
dePlexSample <- renameDemultiplexedFiles(sampleTab, dePlexSample)
dePlexSample <- mergeMinIONfiles(inDir=readsDir, outDir=outDeplexSample, sampleTab=sampleTab)

# save summary table
write.table(dePlexSample, file.path(outputDir, "demultiplexSampleSummary.txt"), sep="\t", row.names=F)
Expand All @@ -86,34 +86,29 @@ dir.create(outDeplexMarker)

# process each marker
markerTab <- read.delim(primerFile, stringsAsFactors=F)
dePlexMarker <- demultiplexByMarker(dePlexSample, markerTab, outDeplexMarker)
# shorten primer sequence to same length for demultiplexing
markerTab$Forward <- substr(markerTab$Forward, start=nchar(markerTab$Forward)-20, stop=nchar(markerTab$Forward))
markerTab$Reverse <- substr(markerTab$Reverse, start=nchar(markerTab$Reverse)-20, stop=nchar(markerTab$Reverse))
dePlexMarker <- demultiplexByMarkerMinION(dePlexSample, markerTab, outDeplexMarker, max.mismatch=2)

# save summary table
write.table(dePlexMarker, file.path(outputDir, "demultiplexMarkerSummary.txt"), sep="\t", row.names=F)
```

subset: remove markers without sufficient reads
```R
procReads <- procReads[procReads$numRead>10,]

```

Call Haplotypes
```R
# call haplotype options
minCov <- 3
detectionLimit <- 1/100
minOccHap <- 2
minCovSample <- 25

# remove samples without reads
procReads <- procReads[procReads$numRead>0,]
minOccHap <- 1
minCovSample <- 100

# call final haplotypes
finalTab <- createFinalHaplotypTableDADA2(
outputDir = outputDir, sampleTable = procReads, markerTable = markerTab,
referenceSequence=refSeq, filterIndel=T,
outputDir = outputDir, sampleTable = dePlexMarker, markerTable = markerTab,
referenceSequence=NULL, filterIndel=T,
minHaplotypCoverage = minCov, minReplicate = minOccHap,
detectability = detectionLimit, minSampleCoverage = minCovSample,
multithread=FALSE, pool="pseudo", OMEGA_A=1e-120)
```

84 changes: 84 additions & 0 deletions inst/extdata/ex3/MH_ama1_D2_18.fasta
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
>Pfalciparum3D7
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGGAAATC
AATATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAGAACCTCTTATGTCACCAATGACATTAGATGAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>Pfalciparum7G8
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAAAACCGGTAGCTACGGGAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCTTATATCACCAATGACATTAGATCATATGAGAGAT
TTTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumCD01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAGAACCTCTTATGTCACCAATGACATTAGATCGTATGAGAGAT
TTTTATAAAAATAATGAAGATGTAAAAAATTTAGATGAATT
>PfalciparumDd2
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGGAAATC
AATATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATGATATGAGACTT
TTGTATAAAGATAATGAAGATGTAAAAAATTTAGATGAATT
>PfalciparumGA01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCTTATATCACCAATGACATTAGATCATATGAGAGAT
TCTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumGB4
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATCAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>PfalciparumGN01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATCAAATGAGAGAT
TTTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumHB3
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAAAACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAGAACCTCTTATATCACCAATGACATTAGATCAAATGAGACAT
CTTTATAAAGATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumIT
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAAAACCGGTAGCTACGGGAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCTTATATCACCAATGACATTAAATGGTATGAGAGAT
TTTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumKE01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGGAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCCTATGTCACCAATGACATTAAATGGTATGAGAGAT
TTATATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumKH01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATCAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>PfalciparumKH02
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAAAACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAGAACCTCTTATGTCACCAATGACATTAGATCAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>PfalciparumML01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGGAAATC
AATATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATGATATGAGACTT
TTGTATAAAGATAATGAAGATGTAAAAAATTTAGATGAATT
>PfalciparumSD01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATCAAATGAGACAT
TTTTATAAAGATAATGAAGATGTAAAAAATTTAGATGAATT
>PfalciparumSN01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGGAAATC
AATATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAGAACCTCTTATGTCACCAATGACATTAGATGAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>PfalciparumTG01
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAAACCTCTTATGTCACCAATGACATTAGATCAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>PfalciparumNF135C10
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAAAACCGGTAGCTACGGGAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCTTATATCACCAATGACATTAAATGGTATGAGAGAT
TTTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumNF166
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAAAACTACTTTTTTAACACCGGTAGCTACGGAAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCCTATGTCACCAATGACATTAAATGGTATGAGAGAT
TTATATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumNF54
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAACACCGGTAGCTACGGGAAATC
AATATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAGAACCTCTTATGTCACCAATGACATTAGATGAAATGAGACAT
TTTTATAAAGATAATAAATATGTAAAAAATTTAGATGAATT
>PfalciparumK1
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAAAACCGGTAGCTACGGGAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCTTATATCACCAATGACATTAAATGGTATGAGAGAT
TTTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
>PfalciparumFCB1
GAAATGTCCAGTATTTGGTAAAGGTATAATTATTGAGAATTCAAATACTACTTTTTTAAAACCGGTAGCTACGGGAAATC
AAGATTTAAAAGATGGAGGTTTTGCTTTTCCTCCAACAAATCCTCTTATATCACCAATGACATTAAATGGTATGAGAGAT
TTTTATAAAAATAATGAATATGTAAAAAATTTAGATGAATT
Loading

0 comments on commit 2042407

Please sign in to comment.