defmodule Mix.Tasks.Bio.Random.Dna do
@moduledoc """
Bio.Random.Dna will generate random sequences of DNA. Sequences are written to
a file with 1 per line, and are separated by a `\n` character.
## Command line options
* `--seed/-s` - RNG seed (defaults to RNG default seeding)
* `--algorithm/-a` - RNG algorithm (defaults to exsss)
* `--seq-count/-c` - integer number of sequences to generate (required)
* `--seq-size/-z` - integer size of sequence to generate (required)
* `--outfile/-f` - output filename or path (default: random_sequences.txt)
## Examples
$ mix bio.random.dna -s 0 -c 100 -z 50
This would write 100 sequences of 50 nucleotides to a file called
`random_sequences.txt`.
$ mix bio.random.dna -s 0 -c 100 -z 50 -f my_random_sequences.txt
This would write the same 100 sequences of 50 nucleotides to a file called
`my_random_sequences.txt`.
"""
@shortdoc "Generate random dna sequences"
use Mix.Task
@options [
seed: :integer,
algorithm: :string,
outfile: :string,
seq_size: :integer,
seq_count: :integer
]
@aliases [
s: :seed,
a: :algorithm,
f: :outfile,
z: :seq_size,
c: :seq_count
]
def run(options) do
{opts, _, _} = OptionParser.parse(options, aliases: @aliases, strict: @options)
algorithm = Keyword.get(opts, :algorithm, "exsss")
size = Keyword.get(opts, :seq_size)
count = Keyword.get(opts, :seq_count)
filename = Keyword.get(opts, :outfile, "random_sequences.txt")
case {size, count} do
{nil, nil} -> Mix.raise("Please provide values for --seq-size/-z and --seq-count/-c")
{_, nil} -> Mix.raise("Please provide value for --seq-count/-c")
{nil, _} -> Mix.raise("Please provide values for --seq-size/-z")
_ -> nil
end
case opts[:seed] do
nil -> :rand.seed(String.to_atom(algorithm))
seed -> :rand.seed(String.to_atom(algorithm), seed)
end
File.write(
filename,
0..count
|> Enum.map(fn _ ->
0..size
|> Enum.map(fn _ ->
Enum.random('atgc')
end)
|> List.to_string()
end)
|> Enum.reduce("", fn line, lines ->
lines <> "#{line}\n"
end)
)
end
end