Skip to content

Commit

Permalink
feat(cli): add ability to output Auspice JSON v2 in CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-aksamentov committed Sep 12, 2020
1 parent 6ab4de4 commit 77563a3
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 8 deletions.
2 changes: 2 additions & 0 deletions packages/cli/README.md
Expand Up @@ -54,6 +54,8 @@ Generated file `results.json` will contain the results in JSON format.
Similarly, results can be generated in .csv or .tsv format, or in multiple formats (by passing multiple `--output-<format>=` flags)
All files have the same format as exports from the [Nextclade web application](https://clades.nextstrain.org).

Additionally, Nextclade can output a new Nextstrain tree (in the same Auspice JSON v2 format), with the user-provided sequences placed on it, with `--output-tree`. Note that this simplified tree placement is to give a rough idea of where the sequences may end up, and this does not substitute the full Nextstrain build.

### With docker

Docker images with Nextclade CLI are hosted in docker hub repository [`neherlab/nextclade`](https://hub.docker.com/r/neherlab/nextclade)
Expand Down
48 changes: 40 additions & 8 deletions packages/web/src/cli/cli.ts
@@ -1,3 +1,4 @@
import { AuspiceJsonV2 } from 'auspice'
import path from 'path'
import { AnalysisResult } from 'src/algorithms/types'
import fs from 'fs-extra'
Expand All @@ -21,7 +22,8 @@ import pkg from 'src/../package.json'
const OUTPUT_JSON = 'output-json' as const
const OUTPUT_CSV = 'output-csv' as const
const OUTPUT_TSV = 'output-tsv' as const
const OUTPUT_OPTS = [OUTPUT_JSON, OUTPUT_CSV, OUTPUT_TSV] as const
const OUTPUT_TREE = 'output-tree' as const
const OUTPUT_OPTS = [OUTPUT_JSON, OUTPUT_CSV, OUTPUT_TSV, OUTPUT_TREE] as const

export function parseCommandLine() {
const params = yargs(process.argv)
Expand Down Expand Up @@ -49,7 +51,8 @@ export function parseCommandLine() {
.option('input-tree', {
alias: 'a',
type: 'string',
description: 'Path to Auspice JSON v2 file containing custom reference tree',
description:
'Path to Auspice JSON v2 file containing custom reference tree. See https://nextstrain.org/docs/bioinformatics/data-formats',
})
.option(OUTPUT_JSON, {
alias: 'o',
Expand All @@ -64,7 +67,13 @@ export function parseCommandLine() {
.option(OUTPUT_TSV, {
alias: 't',
type: 'string',
description: 'Path to output CSV results file',
description: 'Path to output TSV results file',
})
.option(OUTPUT_TREE, {
alias: 'T',
type: 'string',
description:
'Path to output Auspice JSON V2 results file. See https://nextstrain.org/docs/bioinformatics/data-formats',
})
.check((argv) => {
if (!OUTPUT_OPTS.some((opt) => argv[opt])) {
Expand Down Expand Up @@ -106,12 +115,14 @@ export async function validateParams(params: CliParams) {
const outputJson = params[OUTPUT_JSON]
const outputCsv = params[OUTPUT_CSV]
const outputTsv = params[OUTPUT_TSV]
const outputTree = params[OUTPUT_TREE]

await assertCanCreate(outputJson)
await assertCanCreate(outputCsv)
await assertCanCreate(outputTsv)
await assertCanCreate(outputTree)

return { inputFasta, inputQcConfig, inputRootSeq, inputTree, outputJson, outputCsv, outputTsv }
return { inputFasta, inputQcConfig, inputRootSeq, inputTree, outputJson, outputCsv, outputTsv, outputTree }
}

export interface ReadInputsParams {
Expand Down Expand Up @@ -146,12 +157,21 @@ export async function readInputs({ inputFasta, inputQcConfig, inputRootSeq, inpu

export interface WriteResultsParams {
results: AnalysisResult[]
auspiceData: AuspiceJsonV2
outputJson?: string
outputCsv?: string
outputTsv?: string
outputTree?: string
}

export async function writeResults({ results, outputJson, outputCsv, outputTsv }: WriteResultsParams) {
export async function writeResults({
results,
auspiceData,
outputJson,
outputCsv,
outputTsv,
outputTree,
}: WriteResultsParams) {
const json = results.map(prepareResultJson)
if (outputJson) {
await fs.writeJson(outputJson, json, { spaces: 2 })
Expand All @@ -168,22 +188,34 @@ export async function writeResults({ results, outputJson, outputCsv, outputTsv }
const tsv = await toCsvString(data, '\t')
await fs.writeFile(outputTsv, tsv)
}

if (outputTree) {
await fs.writeJson(outputTree, auspiceData, { spaces: 2 })
}
}

export async function main() {
const params = parseCommandLine()

const { inputFasta, outputJson, outputCsv, outputTsv, inputQcConfig, inputRootSeq } = await validateParams(params)
const {
inputFasta,
outputJson,
outputCsv,
outputTsv,
outputTree,
inputQcConfig,
inputRootSeq,
} = await validateParams(params)

const { input, rootSeq, qcRulesConfig, auspiceDataReference } = await readInputs({
inputFasta,
inputQcConfig,
inputRootSeq,
})

const { results } = run(input, rootSeq, qcRulesConfig, auspiceDataReference)
const { results, auspiceData } = run(input, rootSeq, qcRulesConfig, auspiceDataReference)

await writeResults({ results, outputJson, outputCsv, outputTsv })
await writeResults({ results, auspiceData, outputJson, outputCsv, outputTsv, outputTree })
}

main().catch((error_) => {
Expand Down

0 comments on commit 77563a3

Please sign in to comment.