From b89fc26d0f9c5555730b576aa5bac0a8ed9f2cf0 Mon Sep 17 00:00:00 2001 From: Manuel Holtgrewe Date: Thu, 11 Jul 2024 08:40:11 +0200 Subject: [PATCH] feat: implement OpenAPI documentation (#162) (#165) --- .github/workflows/release-please.yml | 6 - .github/workflows/rust.yml | 31 +- Cargo.lock | 615 +++++++++- Cargo.toml | 12 +- openapi.yaml | 374 ++++++ src/common.rs | 5 +- src/main.rs | 30 +- src/query/mod.rs | 30 +- ...est__hpo_sim_term_gene_terms_gene_ids.snap | 1073 ----------------- src/server/actix_server/mod.rs | 115 -- src/server/mod.rs | 168 +-- src/server/{actix_server => run}/hpo_genes.rs | 209 +++- src/server/{actix_server => run}/hpo_omims.rs | 177 ++- .../{actix_server => run}/hpo_sim/mod.rs | 0 ...po_sim_term_gene_terms_hgnc_gene_ids.snap} | 2 +- ...po_sim_term_gene_terms_ncbi_gene_ids.snap} | 2 +- ...est__hpo_sim_term_gene_terms_symbols.snap} | 2 +- ...erm__test__hpo_sim_term_term_one_one.snap} | 3 +- ...erm__test__hpo_sim_term_term_two_two.snap} | 3 +- .../hpo_sim/term_gene.rs | 72 +- .../hpo_sim/term_term.rs | 95 +- src/server/{actix_server => run}/hpo_terms.rs | 114 +- src/server/run/mod.rs | 341 ++++++ ...es_gene_symbol_contains_no_hpo_terms.snap} | 3 +- ..._gene_symbol_contains_with_hpo_terms.snap} | 3 +- ...genes_gene_symbol_exact_no_hpo_terms.snap} | 3 +- ...nes_gene_symbol_exact_with_hpo_terms.snap} | 3 +- ...enes_gene_symbol_prefix_no_hpo_terms.snap} | 3 +- ...es_gene_symbol_prefix_with_hpo_terms.snap} | 3 +- ...enes_gene_symbol_suffix_no_hpo_terms.snap} | 3 +- ...es_gene_symbol_suffix_with_hpo_terms.snap} | 3 +- ...enes_hgnc_gene_id_exact_no_hpo_terms.snap} | 3 +- ...es_hgnc_gene_id_exact_with_hpo_terms.snap} | 3 +- ...enes_ncbi_gene_id_exact_no_hpo_terms.snap} | 3 +- ...es_ncbi_gene_id_exact_with_hpo_terms.snap} | 3 +- ...hpo_omims_name_contains_no_hpo_terms.snap} | 3 +- ...o_omims_name_contains_with_hpo_terms.snap} | 3 +- ...t__hpo_omims_name_exact_no_hpo_terms.snap} | 3 +- ..._hpo_omims_name_exact_with_hpo_terms.snap} | 3 +- ...__hpo_omims_name_prefix_no_hpo_terms.snap} | 3 +- ...hpo_omims_name_prefix_with_hpo_terms.snap} | 3 +- ...__hpo_omims_name_suffix_no_hpo_terms.snap} | 3 +- ...hpo_omims_name_suffix_with_hpo_terms.snap} | 3 +- ...hpo_omims_omim_id_exact_no_hpo_terms.snap} | 3 +- ...o_omims_omim_id_exact_with_hpo_terms.snap} | 3 +- ..._test__hpo_terms_name_exact_no_genes.snap} | 3 +- ...est__hpo_terms_name_exact_with_genes.snap} | 3 +- ..._test__hpo_terms_name_fuzzy_no_genes.snap} | 3 +- ...est__hpo_terms_name_fuzzy_with_genes.snap} | 3 +- ...st__hpo_terms_term_id_exact_no_genes.snap} | 3 +- ...__hpo_terms_term_id_exact_with_genes.snap} | 3 +- src/server/schema.rs | 51 + 52 files changed, 1949 insertions(+), 1665 deletions(-) create mode 100644 openapi.yaml delete mode 100644 src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_gene_ids.snap delete mode 100644 src/server/actix_server/mod.rs rename src/server/{actix_server => run}/hpo_genes.rs (54%) rename src/server/{actix_server => run}/hpo_omims.rs (58%) rename src/server/{actix_server => run}/hpo_sim/mod.rs (100%) rename src/server/{actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap => run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap} (99%) rename src/server/{actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap => run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap} (99%) rename src/server/{actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap => run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap} (99%) rename src/server/{actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap => run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap} (85%) rename src/server/{actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap => run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap} (91%) rename src/server/{actix_server => run}/hpo_sim/term_gene.rs (69%) rename src/server/{actix_server => run}/hpo_sim/term_term.rs (70%) rename src/server/{actix_server => run}/hpo_terms.rs (77%) create mode 100644 src/server/run/mod.rs rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap} (97%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap} (99%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap} (93%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap} (93%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap} (86%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap} (85%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap => run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap} (98%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_no_genes.snap => run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_no_genes.snap} (94%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_with_genes.snap => run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_with_genes.snap} (99%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap => run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap} (94%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap => run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap} (99%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap => run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap} (91%) rename src/server/{actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap => run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap} (99%) diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index a18e5c8..13e8091 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -49,12 +49,6 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2 - if: ${{ needs.release-please.outputs.release_created }} - with: - cache-directories: | - ~/.cargo/registry/src/**/librocksdb-sys-* - - name: Publish crate if: ${{ needs.release-please.outputs.release_created }} uses: actions-rs/cargo@v1 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e2cedd6..2fbd07e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -79,11 +79,6 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2 - with: - cache-directories: | - ~/.cargo/registry/src/**/librocksdb-sys-* - - name: Run cargo-tarpaulin uses: actions-rs/tarpaulin@v0.1 with: @@ -95,3 +90,29 @@ jobs: with: verbose: true token: ${{ secrets.CODECOV_TOKEN }} + + Schema-Unchanged: # ensure schema is not changed + needs: Formatting + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + lfs: true + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Setup protoc + uses: arduino/setup-protoc@v1.1.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Check schema + run: | + cargo run -- server schema --output-file /tmp/openapi.yaml + set -e + diff openapi.yaml /tmp/openapi.yaml diff --git a/Cargo.lock b/Cargo.lock index e25970a..5e2291c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,7 +30,7 @@ dependencies = [ "actix-service", "actix-utils", "ahash", - "base64", + "base64 0.21.5", "bitflags 2.4.1", "brotli", "bytes", @@ -40,7 +40,7 @@ dependencies = [ "flate2", "futures-core", "h2", - "http", + "http 0.2.11", "httparse", "httpdate", "itoa", @@ -75,7 +75,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" dependencies = [ "bytestring", - "http", + "http 0.2.11", "regex", "serde", "tracing", @@ -315,6 +315,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arc-swap" version = "1.6.0" @@ -359,6 +368,12 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -583,9 +598,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -625,12 +640,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.17" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -714,6 +726,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -758,6 +781,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "downcast-rs" version = "1.2.0" @@ -1071,7 +1105,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.11", "indexmap", "slab", "tokio", @@ -1152,6 +1186,40 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" @@ -1170,6 +1238,63 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1237,6 +1362,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.9" @@ -1473,6 +1604,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1611,6 +1752,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -1761,6 +1923,26 @@ dependencies = [ "indexmap", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1903,6 +2085,53 @@ dependencies = [ "prost", ] +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.35" @@ -2094,6 +2323,64 @@ dependencies = [ "winapi", ] +[[package]] +name = "reqwest" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rstest" version = "0.21.0" @@ -2124,6 +2411,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "rust-embed" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.48", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rust-stemmers" version = "1.2.0" @@ -2168,6 +2489,47 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -2189,6 +2551,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -2265,7 +2636,7 @@ version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981" dependencies = [ - "base64", + "base64 0.21.5", "chrono", "hex", "indexmap", @@ -2287,6 +2658,19 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "serde_yaml" +version = "0.9.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2375,9 +2759,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smartstring" @@ -2400,6 +2784,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -2459,6 +2849,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -2481,6 +2877,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "tantivy" version = "0.21.1" @@ -2490,7 +2892,7 @@ dependencies = [ "aho-corasick", "arc-swap", "async-trait", - "base64", + "base64 0.21.5", "bitpacking", "byteorder", "census", @@ -2750,6 +3152,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -2781,6 +3194,33 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" @@ -2843,6 +3283,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.17.0" @@ -2855,6 +3301,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.14" @@ -2882,6 +3337,18 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -2905,6 +3372,50 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utoipa" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "serde_yaml", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 2.0.48", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943e0ff606c6d57d410fd5663a4d7c074ab2c5f14ab903b9514565e59fa1189e" +dependencies = [ + "actix-web", + "mime_guess", + "regex", + "reqwest", + "rust-embed", + "serde", + "serde_json", + "url", + "utoipa", + "zip", +] + [[package]] name = "uuid" version = "1.6.1" @@ -2969,6 +3480,27 @@ dependencies = [ "thiserror", "tracing", "tracing-subscriber", + "utoipa", + "utoipa-swagger-ui", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", ] [[package]] @@ -3002,6 +3534,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.89" @@ -3041,6 +3585,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" @@ -3244,6 +3797,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -3273,6 +3836,28 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zip" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "num_enum", + "thiserror", +] + [[package]] name = "zstd" version = "0.12.4" diff --git a/Cargo.toml b/Cargo.toml index db01f2e..4b54948 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,16 +3,16 @@ name = "viguno" version = "0.2.1" edition = "2021" authors = ["Manuel Holtgrewe "] -description = "Rust template repository" +description = "Phenotype/disease for VarFish" license = "Apache-2.0" -homepage = "https://github.com/varfish-org/viguno" +repository = "https://github.com/varfish-org/viguno" readme = "README.md" [dependencies] actix-web = "4.5" anyhow = "1.0" -clap = { version = "4.5", features = ["derive", "help", "env"] } clap-verbosity-flag = "2.1" +clap = { version = "4.5", features = ["derive", "help", "env"] } console = "0.15" csv = "1.3" derive_more = "0.99" @@ -30,17 +30,19 @@ once_cell = "1.18" prost = "0.12" rayon = "1.8" regex = "1.10" -serde = { version = "1.0", features = ["serde_derive"] } serde_json = "1.0" +serde = { version = "1.0", features = ["serde_derive"] } serde_with = { version = "3.6", features=["alloc", "macros", "indexmap_2"], default-features = false } shellexpand = "3.0" -strum = { version = "0.26", features = ["strum_macros", "derive"] } strum_macros = "0.26" +strum = { version = "0.26", features = ["strum_macros", "derive"] } tantivy = "0.21.1" tempdir = "0.3.7" thiserror = "1.0" tracing = "0.1" tracing-subscriber = "0.3" +utoipa-swagger-ui = { version = "7.1.0", features = ["actix-web"] } +utoipa = { version = "4.2", features = ["actix_extras", "chrono", "indexmap", "preserve_order", "yaml"] } [build-dependencies] prost-build = "0.12" diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..7b2d53d --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,374 @@ +openapi: 3.0.3 +info: + title: viguno + description: Phenotype/disease for VarFish + contact: + name: Manuel Holtgrewe + email: manuel.holtgrewe@bih-charite.de + license: + name: Apache-2.0 + version: 0.2.1 +paths: + /hpo/genes: + get: + tags: + - hpo_genes + summary: Query for genes in the HPO database. + operationId: handle + parameters: + - name: gene_id + in: query + description: The gene ID to search for. + required: false + schema: + type: string + nullable: true + - name: gene_symbol + in: query + description: The gene symbol to search for. + required: false + schema: + type: string + nullable: true + - name: match_ + in: query + description: The match mode. + required: false + schema: + allOf: + - $ref: '#/components/schemas/Match' + nullable: true + - name: max_results + in: query + description: Maximal number of results to return. + required: false + schema: + type: integer + minimum: 0 + - name: hpo_terms + in: query + description: Whether to include HPO terms. + required: false + schema: + type: boolean + responses: + '200': + description: The query was successful. + content: + application/json: + schema: + $ref: '#/components/schemas/Result' + /hpo/omims: + get: + tags: + - hpo_omims + summary: Query for OMIM diseases in the HPO database. + operationId: handle + parameters: + - name: omim_id + in: query + description: The OMIM ID to search for. + required: false + schema: + type: string + nullable: true + - name: name + in: query + description: The disease name to search for. + required: false + schema: + type: string + nullable: true + - name: match_ + in: query + description: The match mode. + required: false + schema: + allOf: + - $ref: '#/components/schemas/Match' + nullable: true + - name: max_results + in: query + description: Maximal number of results to return. + required: false + schema: + type: integer + minimum: 0 + - name: hpo_terms + in: query + description: Whether to include HPO terms. + required: false + schema: + type: boolean + responses: + '200': + description: The query was successful. + content: + application/json: + schema: + $ref: '#/components/schemas/Result' + /hpo/terms: + get: + tags: + - hpo_terms + summary: Query for terms in the HPO database. + description: |- + # Errors + + In the case that there is an error running the server. + operationId: handle + parameters: + - name: term_id + in: query + description: The term ID to search for. + required: false + schema: + type: string + nullable: true + - name: name + in: query + description: The term name to search for. + required: false + schema: + type: string + nullable: true + - name: max_results + in: query + description: Maximal number of results to return. + required: false + schema: + type: integer + minimum: 0 + - name: genes + in: query + description: Whether to include genes. + required: false + schema: + type: boolean + responses: + '200': + description: The query was successful. + content: + application/json: + schema: + $ref: '#/components/schemas/Result' +components: + schemas: + HpoTerm: + type: object + description: Struct for loading an HPO term from JSON. + required: + - term_id + properties: + term_id: + type: string + description: The term ID. + term_name: + type: string + description: The term name (optional). + nullable: true + IcBasedOn: + type: string + description: |- + Enum for representing the information content kind. + + We replicate what is in the `hpo` create so we can put them on the command line and use + them in HTTP queries more easily. + enum: + - gene + - omim + Match: + type: string + description: Specify how to perform query matches in the API calls. + enum: + - exact + - prefix + - suffix + - contains + Query: + type: object + title: HpoSimTermGeneQuery + description: |- + Parameters for `handle`. + + This allows to compute differences between + + - `terms` -- set of terms to use as query + - `gene_ids` -- set of ids for genes to use as "database", can be NCBI\ + gene ID or HGNC gene ID. + - `gene_symbols` -- set of symbols for genes to use as + "database" + required: + - terms + properties: + terms: + type: array + items: + type: string + description: Set of terms to use as query. + gene_ids: + type: array + items: + type: string + description: The set of ids for genes to use as "database". + nullable: true + gene_symbols: + type: array + items: + type: string + description: The set of symbols for genes to use as "database". + nullable: true + ResponseQuery: + type: object + title: HpoSimTermTermQuery + description: |- + Request as sent together with the response. + + The difference is that the `lhs` and `rhs` fields are replaced by vecs. + required: + - lhs + - rhs + properties: + lhs: + type: array + items: + type: string + description: The one set of HPO terms to compute similarity for. + rhs: + type: array + items: + type: string + description: The second set of HPO terms to compute similarity for. + ic_base: + $ref: '#/components/schemas/IcBasedOn' + similarity: + $ref: '#/components/schemas/SimilarityMethod' + combiner: + $ref: '#/components/schemas/ScoreCombiner' + Result: + type: object + title: HpoSimTermTermResult + description: Result container. + required: + - version + - query + - result + properties: + version: + $ref: '#/components/schemas/Version' + query: + $ref: '#/components/schemas/ResponseQuery' + result: + type: array + items: + $ref: '#/components/schemas/ResultEntry' + description: The resulting records for the scored genes. + ResultEntry: + type: object + title: HpoSimTermTermResultEntry + description: Result entry for `handle`. + required: + - lhs + - rhs + - score + properties: + lhs: + type: string + description: The lhs entry. + rhs: + type: string + description: The rhs entry. + score: + type: number + format: float + description: The similarity score. + ResultGene: + type: object + description: Representation of a gene. + required: + - ncbi_gene_id + - gene_symbol + properties: + ncbi_gene_id: + type: integer + format: int32 + description: The HPO ID. + minimum: 0 + gene_symbol: + type: string + description: The description. + hgnc_id: + type: string + description: The HGNC ID. + nullable: true + ResultHpoTerm: + type: object + description: Representation of an HPO term. + required: + - term_id + - name + properties: + term_id: + type: string + description: The HPO ID. + name: + type: string + description: The term name. + ScoreCombiner: + type: string + description: |- + Representation of the standard combiners from HPO. + + We replicate what is in the `hpo` create so we can put them on the command line and use + them in HTTP queries more easily. + enum: + - fun-sim-avg + - fun-sim-max + - bma + SimilarityMethod: + type: string + description: |- + Enum for representing similarity method to use. + + We replicate what is in the `hpo` create so we can put them on the command line and use + them in HTTP queries more easily. + enum: + - distance-gene + - graph-ic + - information-coefficient + - jc + - lin + - mutation + - relevance + - resnik + TermDetails: + type: object + title: HpoSimTermGeneTermDetails + description: Detailed term scores. + required: + - term_gene + - score + properties: + term_query: + allOf: + - $ref: '#/components/schemas/HpoTerm' + nullable: true + term_gene: + $ref: '#/components/schemas/HpoTerm' + score: + type: number + format: float + description: The similarity score. + Version: + type: object + description: Version information that is returned by the HTTP server. + required: + - hpo + - viguno + properties: + hpo: + type: string + description: Version of the HPO. + viguno: + type: string + description: Version of the `viguno` package. diff --git a/src/common.rs b/src/common.rs index 7332479..05539b4 100644 --- a/src/common.rs +++ b/src/common.rs @@ -60,6 +60,7 @@ pub fn load_hpo>(path: P) -> Result &'static str { } /// Version information that is returned by the HTTP server. -#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone)] +#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Default, Debug, Clone)] pub struct Version { /// Version of the HPO. pub hpo: String, diff --git a/src/main.rs b/src/main.rs index da01c15..81d95fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,24 @@ struct Cli { enum Commands { Convert(crate::convert::Args), Query(crate::query::Args), - RunServer(crate::server::Args), + Server(Server), +} + +/// Clap sub command below "server". +#[derive(Debug, Parser)] +struct Server { + /// The sub command to run + #[clap(subcommand)] + pub command: ServerSubCommands, +} + +/// Sub commands for "server". +#[derive(Debug, Subcommand)] +enum ServerSubCommands { + /// Run the server. + Run(crate::server::run::Args), + /// Dump the schema. + Schema(crate::server::schema::Args), } fn main() -> Result<(), anyhow::Error> { @@ -71,9 +88,14 @@ fn main() -> Result<(), anyhow::Error> { Commands::Query(args) => { query::run(&cli.common, args)?; } - Commands::RunServer(args) => { - server::run(&cli.common, args)?; - } + Commands::Server(cmd_server) => match &cmd_server.command { + ServerSubCommands::Run(args) => { + server::run::run(&cli.common, args)?; + } + ServerSubCommands::Schema(args) => { + server::schema::run(&cli.common, args)?; + } + }, } Ok::<(), anyhow::Error>(()) diff --git a/src/query/mod.rs b/src/query/mod.rs index 8c66915..ad043b3 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -38,7 +38,7 @@ pub struct Gene { } /// Struct for loading an HPO term from JSON. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, utoipa::ToSchema, Debug, Clone)] pub struct HpoTerm { /// The term ID. pub term_id: String, @@ -49,6 +49,8 @@ pub struct HpoTerm { /// Query result records. pub mod query_result { + use crate::common::Version; + use super::HpoTerm; /// Struct for storing gene information in the result. @@ -66,7 +68,8 @@ pub mod query_result { } /// The performed query. - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] + #[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] + #[schema(title = "HpoSimTermGeneQuery")] pub struct Query { /// The query HPO terms. pub terms: Vec, @@ -75,19 +78,21 @@ pub mod query_result { } /// Result container data structure. - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] - pub struct Container { + #[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] + #[schema(title = "HpoSimTermGeneResult")] + pub struct Result { /// Version information. - pub version: crate::common::Version, + pub version: Version, /// The original query records. pub query: Query, /// The resulting records for the scored genes. - pub result: Vec, + pub result: Vec, } /// Store score for a record with information on individual terms. - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] - pub struct Record { + #[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] + #[schema(title = "HpoSimTermGeneResultEntry")] + pub struct ResultEntry { /// The gene symbol. pub gene_symbol: String, /// The raw Phenomizer score. @@ -98,7 +103,8 @@ pub mod query_result { } /// Detailed term scores. - #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] + #[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] + #[schema(title = "HpoSimTermGeneTermDetails")] pub struct TermDetails { /// The query HPO term. pub term_query: Option, @@ -138,7 +144,7 @@ pub fn run_query( genes: &Vec<&hpo::annotations::Gene>, hpo: &Ontology, ncbi_to_hgnc: &HashMap, -) -> Result +) -> Result where S: std::hash::BuildHasher, { @@ -155,7 +161,7 @@ where .collect(), genes: Vec::new(), }; - let mut result = query_result::Container { + let mut result = query_result::Result { version: crate::common::Version::new(&hpo.hpo_version()), query, result: Vec::new(), @@ -224,7 +230,7 @@ where hgnc_id: ncbi_to_hgnc.get(&ncbi_gene_id).cloned(), }); - result.result.push(query_result::Record { + result.result.push(query_result::ResultEntry { gene_symbol: gene.name().to_string(), raw_score, terms: Some(terms), diff --git a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_gene_ids.snap b/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_gene_ids.snap deleted file mode 100644 index 61c75d8..0000000 --- a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_gene_ids.snap +++ /dev/null @@ -1,1073 +0,0 @@ ---- -source: src/server/actix_server/hpo_sim/term_gene.rs -expression: "&run_query(\"/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=23483,7273\").await?" ---- -version: - hpo: 2023-04-05 - viguno: 0.1.0 -query: - terms: - - term_id: "HP:0000347" - term_name: Micrognathia - - term_id: "HP:0010442" - term_name: Polydactyly - genes: - - entrez_id: 7273 - gene_symbol: TTN - hgnc_id: "HGNC:12403" - - entrez_id: 23483 - gene_symbol: TGDS - hgnc_id: "HGNC:20324" -result: - - gene_symbol: TGDS - p_value: 0.1 - score: 10 - terms: - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000347" - term_name: Micrognathia - score: 1.8309557 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0001831" - term_name: Short toe - score: 1.4382622 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0003097" - term_name: Short femur - score: 1.4382622 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0005792" - term_name: Short humerus - score: 1.4382622 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0010049" - term_name: Short metacarpal - score: 1.4382622 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000272" - term_name: Malar flattening - score: 1.341162 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001181" - term_name: Adducted thumb - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0004209" - term_name: Clinodactyly of the 5th finger - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009464" - term_name: Ulnar deviation of the 2nd finger - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009467" - term_name: Radial deviation of the 2nd finger - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0030368" - term_name: Hyperphalangy of the 2nd finger - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0100490" - term_name: Camptodactyly of finger - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0002857" - term_name: Genu valgum - score: 1.0733097 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0010508" - term_name: Metatarsus valgus - score: 1.0733097 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0005930" - term_name: Abnormal epiphysis morphology - score: 1.002138 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0000954" - term_name: Single transverse palmar crease - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001762" - term_name: Talipes equinovarus - score: 0.73446083 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000470" - term_name: Short neck - score: 0.6371871 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000767" - term_name: Pectus excavatum - score: 0.6371871 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000768" - term_name: Pectus carinatum - score: 0.6371871 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0002650" - term_name: Scoliosis - score: 0.6371871 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001373" - term_name: Joint dislocation - score: 0.48051217 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001387" - term_name: Joint stiffness - score: 0.44339323 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001388" - term_name: Joint laxity - score: 0.44339323 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0005692" - term_name: Joint hyperflexibility - score: 0.44339323 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000160" - term_name: Narrow mouth - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000162" - term_name: Glossoptosis - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000175" - term_name: Cleft palate - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000193" - term_name: Bifid uvula - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000201" - term_name: Pierre-Robin sequence - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000204" - term_name: Cleft upper lip - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000218" - term_name: High palate - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000293" - term_name: Full cheeks - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000460" - term_name: Narrow nose - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000579" - term_name: Nasolacrimal duct obstruction - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000582" - term_name: Upslanted palpebral fissure - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0002553" - term_name: Highly arched eyebrow - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0009933" - term_name: Narrow naris - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0010285" - term_name: Oral synechia - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0010763" - term_name: Low insertion of columella - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0045074" - term_name: Thin eyebrow - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000476" - term_name: Cystic hygroma - score: 0.4094388 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0000023" - term_name: Inguinal hernia - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001537" - term_name: Umbilical hernia - score: 0.28058913 - - term_query: ~ - term_gene: - term_id: "HP:0000028" - term_name: Cryptorchidism - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000316" - term_name: Hypertelorism - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000368" - term_name: "Low-set, posteriorly rotated ears" - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000389" - term_name: Chronic otitis media - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000520" - term_name: Proptosis - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001250" - term_name: Seizure - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001263" - term_name: Global developmental delay - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001508" - term_name: Failure to thrive - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001511" - term_name: Intrauterine growth retardation - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001629" - term_name: Ventricular septal defect - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001631" - term_name: Atrial septal defect - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001651" - term_name: Dextrocardia - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001680" - term_name: Coarctation of aorta - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002119" - term_name: Ventriculomegaly - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002623" - term_name: Overriding aorta - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0004322" - term_name: Short stature - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0008897" - term_name: Postnatal growth retardation - score: 0 - - gene_symbol: TTN - p_value: 0.3 - score: 5.2287874 - terms: - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000308" - term_name: Microretrognathia - score: 1.8309557 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000303" - term_name: Mandibular prognathia - score: 1.5641111 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0100807" - term_name: Long fingers - score: 1.2074362 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001385" - term_name: Hip dysplasia - score: 1.002138 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003273" - term_name: Hip contracture - score: 1.002138 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0000982" - term_name: Palmoplantar keratoderma - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001761" - term_name: Pes cavus - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001762" - term_name: Talipes equinovarus - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001763" - term_name: Pes planus - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001771" - term_name: Achilles tendon contracture - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003547" - term_name: Shoulder girdle muscle weakness - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003691" - term_name: Scapular winging - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003731" - term_name: Quadriceps muscle weakness - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003749" - term_name: Pelvic girdle muscle weakness - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0008959" - term_name: Distal upper limb muscle weakness - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0008963" - term_name: Tibialis muscle weakness - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0008981" - term_name: Calf muscle hypertrophy - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009027" - term_name: Foot dorsiflexor weakness - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009049" - term_name: Peroneal muscle atrophy - score: 0.73446083 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009077" - term_name: Weakness of long finger extensor muscles - score: 0.73446083 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0002650" - term_name: Scoliosis - score: 0.6371871 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0003306" - term_name: Spinal rigidity - score: 0.6371871 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0003307" - term_name: Hyperlordosis - score: 0.6371871 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0002828" - term_name: Multiple joint contractures - score: 0.48051217 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0008800" - term_name: Limited hip movement - score: 0.44339323 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000160" - term_name: Narrow mouth - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000193" - term_name: Bifid uvula - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000218" - term_name: High palate - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0000276" - term_name: Long face - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0001349" - term_name: Facial diplegia - score: 0.4183606 - - term_query: - term_id: "HP:0000347" - term_name: Micrognathia - term_gene: - term_id: "HP:0005991" - term_name: Limited neck flexion - score: 0.4094388 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0001290" - term_name: Generalized hypotonia - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0002355" - term_name: Difficulty walking - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0002359" - term_name: Frequent falls - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0002421" - term_name: Poor head control - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003323" - term_name: Progressive muscle weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003324" - term_name: Generalized muscle weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003327" - term_name: Axial muscle weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003391" - term_name: Gowers sign - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003403" - term_name: "EMG: decremental response of compound muscle action potential to repetitive nerve stimulation" - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003458" - term_name: "EMG: myopathic abnormalities" - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003551" - term_name: Difficulty climbing stairs - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003555" - term_name: Muscle fiber splitting - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003557" - term_name: Increased variability in muscle fiber diameter - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003687" - term_name: Centrally nucleated skeletal muscle fibers - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003700" - term_name: Generalized amyotrophy - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003715" - term_name: Myofibrillar myopathy - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003722" - term_name: Neck flexor weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003741" - term_name: Congenital muscular dystrophy - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003789" - term_name: Minicore myopathy - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003803" - term_name: Type 1 muscle fiber predominance - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0003805" - term_name: Rimmed vacuoles - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0004889" - term_name: Intermittent episodes of respiratory insufficiency due to muscle weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0008978" - term_name: Necrotizing myopathy - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009046" - term_name: Difficulty running - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009058" - term_name: Increased muscle lipid content - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0009113" - term_name: Diaphragmatic weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0012548" - term_name: Fatty replacement of skeletal muscle - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0030091" - term_name: Absent muscle fiber merosin - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0031237" - term_name: Internally nucleated skeletal muscle fibers - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0031374" - term_name: Ankle weakness - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0100293" - term_name: Hypertrophied muscle fibers - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0100295" - term_name: Muscle fiber atrophy - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0100297" - term_name: Increased endomysial connective tissue - score: 0.28058913 - - term_query: - term_id: "HP:0010442" - term_name: Polydactyly - term_gene: - term_id: "HP:0100578" - term_name: Lipoatrophy - score: 0.28058913 - - term_query: ~ - term_gene: - term_id: "HP:0000407" - term_name: Sensorineural hearing impairment - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000411" - term_name: Protruding ear - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000508" - term_name: Ptosis - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000602" - term_name: Ophthalmoplegia - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0000750" - term_name: Delayed speech and language development - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001256" - term_name: "Intellectual disability, mild" - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001260" - term_name: Dysarthria - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001284" - term_name: Areflexia - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001508" - term_name: Failure to thrive - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001618" - term_name: Dysphonia - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001620" - term_name: High pitched voice - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001634" - term_name: Mitral valve prolapse - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001635" - term_name: Congestive heart failure - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001639" - term_name: Hypertrophic cardiomyopathy - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001644" - term_name: Dilated cardiomyopathy - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001645" - term_name: Sudden cardiac death - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001667" - term_name: Right ventricular hypertrophy - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001678" - term_name: Atrioventricular block - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001708" - term_name: Right ventricular failure - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001712" - term_name: Left ventricular hypertrophy - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0001874" - term_name: Abnormality of neutrophils - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002091" - term_name: Restrictive ventilatory defect - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002194" - term_name: Delayed gross motor development - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002312" - term_name: Clumsiness - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002515" - term_name: Waddling gait - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002527" - term_name: Falls - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002792" - term_name: Reduced vital capacity - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002877" - term_name: Nocturnal hypoventilation - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0002878" - term_name: Respiratory failure - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0003376" - term_name: Steppage gait - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0004322" - term_name: Short stature - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0004756" - term_name: Ventricular tachycardia - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0005110" - term_name: Atrial fibrillation - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0006699" - term_name: Premature atrial contractions - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0008180" - term_name: Mildly elevated creatine kinase - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0011717" - term_name: Atrioventricular reentrant tachycardia - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0012666" - term_name: Severely reduced left ventricular ejection fraction - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0012764" - term_name: Orthopnea - score: 0 - - term_query: ~ - term_gene: - term_id: "HP:0030059" - term_name: Mitochondrial depletion - score: 0 - diff --git a/src/server/actix_server/mod.rs b/src/server/actix_server/mod.rs deleted file mode 100644 index 6a1dd36..0000000 --- a/src/server/actix_server/mod.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Implementation of the Actix server. - -pub mod hpo_genes; -pub mod hpo_omims; -pub mod hpo_sim; -pub mod hpo_terms; - -use actix_web::{middleware::Logger, web::Data, App, HttpServer, ResponseError}; -use serde::{Deserialize, Deserializer, Serialize}; - -use super::{Args, WebServerData}; - -#[derive(Debug)] -struct CustomError { - err: anyhow::Error, -} - -impl std::fmt::Display for CustomError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.err) - } -} - -impl CustomError { - fn new(err: anyhow::Error) -> Self { - CustomError { err } - } -} - -impl ResponseError for CustomError {} - -/// Specify how to perform query matches in the API calls. -#[derive(Serialize, Deserialize, Debug, Clone, Copy, Default, PartialEq, Eq)] -#[serde(rename_all = "lowercase")] -enum Match { - #[default] - Exact, - Prefix, - Suffix, - Contains, -} - -/// Representation of a gene. -#[derive( - serde::Deserialize, serde::Serialize, Default, Debug, Clone, PartialOrd, Ord, PartialEq, Eq, -)] -#[serde_with::skip_serializing_none] -struct ResultGene { - /// The HPO ID. - pub ncbi_gene_id: u32, - /// The description. - pub gene_symbol: String, - /// The HGNC ID. - pub hgnc_id: Option, -} - -/// Representation of an HPO term. -#[derive( - serde::Deserialize, serde::Serialize, Default, Debug, Clone, PartialOrd, Ord, PartialEq, Eq, -)] -struct ResultHpoTerm { - /// The HPO ID. - pub term_id: String, - /// The term name. - pub name: String, -} - -/// Helper to deserialize a comma-separated list of strings. -fn vec_str_deserialize<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let str_sequence = String::deserialize(deserializer)?; - Ok(str_sequence - .split(',') - .map(std::borrow::ToOwned::to_owned) - .collect()) -} - -/// Helper to deserialize a comma-separated list of strings. -fn option_vec_str_deserialize<'de, D>(deserializer: D) -> Result>, D::Error> -where - D: Deserializer<'de>, -{ - let str_sequence = String::deserialize(deserializer)?; - if str_sequence.is_empty() { - Ok(None) - } else { - Ok(Some( - str_sequence - .split(',') - .map(std::borrow::ToOwned::to_owned) - .collect(), - )) - } -} - -/// Main entry point for running the REST server. -#[allow(clippy::unused_async)] -#[actix_web::main] -pub async fn main(args: &Args, dbs: Data) -> std::io::Result<()> { - HttpServer::new(move || { - App::new() - .app_data(dbs.clone()) - .service(hpo_genes::handle) - .service(hpo_terms::handle) - .service(hpo_omims::handle) - .service(hpo_sim::term_term::handle) - .service(hpo_sim::term_gene::handle) - .wrap(Logger::default()) - }) - .bind((args.listen_host.as_str(), args.listen_port))? - .run() - .await -} diff --git a/src/server/mod.rs b/src/server/mod.rs index 828d17f..e2c4d7a 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,166 +1,4 @@ -//! Code for running the REST API server. +//! Code for the REST API server. -pub mod actix_server; - -use std::collections::HashMap; - -use clap::Parser; -use hpo::Ontology; - -use crate::common::load_hpo; - -/// Data structure for the web server data. -pub struct WebServerData { - /// The HPO ontology (`hpo` crate). - pub ontology: Ontology, - /// Xlink map from NCBI gene ID to HGNC gene ID. - pub ncbi_to_hgnc: HashMap, - /// Xlink map from HGNC gene ID to NCBI gene ID. - pub hgnc_to_ncbi: HashMap, - /// The full text index over the HPO OBO document. - pub full_text_index: crate::index::Index, -} - -/// Command line arguments for `server pheno` sub command. -#[derive(Parser, Debug)] -#[command(author, version, about = "Run viguno REST API server", long_about = None)] -pub struct Args { - /// Path to the directory with the HPO files. - #[arg(long, required = true)] - pub path_hpo_dir: String, - /// Path to the TSV file with the HGNC xlink data. - #[arg(long, required = true)] - pub path_hgnc_xlink: String, - - /// Whether to suppress printing hints. - #[arg(long, default_value_t = false)] - pub suppress_hints: bool, - - /// IP to listen on. - #[arg(long, default_value = "127.0.0.1")] - pub listen_host: String, - /// Port to listen on. - #[arg(long, default_value_t = 8080)] - pub listen_port: u16, -} - -/// Print some hints via `tracing::info!`. -pub fn print_hints(args: &Args) { - tracing::info!( - "Launching server main on http://{}:{} ...", - args.listen_host.as_str(), - args.listen_port - ); - - // Short-circuit if no hints are to be - if args.suppress_hints { - return; - } - - // The endpoint `/hpo/genes` provides information related to genes by symbol. - tracing::info!( - " try: http://{}:{}/hpo/genes?gene_symbol=TGDS", - args.listen_host.as_str(), - args.listen_port - ); - // Also, you can query `/hpo/genes` by NCBI gene ID and return the HPO terms of the gene. - tracing::info!( - " try: http://{}:{}/hpo/genes?gene_id=23483&hpo_terms=true", - args.listen_host.as_str(), - args.listen_port - ); - // The `/hpo/omims` term provides information on OMIM terms and can include HPO terms for - // the disease. - tracing::info!( - " try: http://{}:{}/hpo/omims?omim_id=616145&hpo_terms=true", - args.listen_host.as_str(), - args.listen_port - ); - // The `/hpo/terms` endpoint allows to query by HPO term ID and optionally return a list of - // genes that are linked to the term. - tracing::info!( - " try: http://{}:{}/hpo/terms?term_id=HP:0000023&genes=true", - args.listen_host.as_str(), - args.listen_port - ); - // We can use `/hpo/sim/term-term` to compute similarity between two HPO term sets `lhs` - // and `rhs` using a similarity metric. - tracing::info!( - " try: http://{}:{}/hpo/sim/term-term?lhs=HP:0001166,HP:0040069&rhs=HP:0005918,\ - HP:0004188", - args.listen_host.as_str(), - args.listen_port - ); - // The endpoint `/hpo/sim/term-gene` allows to compute the same for a list of `terms` and - // `gene_symbols`. - tracing::info!( - " try: http://{}:{}/hpo/sim/term-gene?terms=HP:0001166,HP:0000098&gene_symbols=FBN1,TGDS,TTN", - args.listen_host.as_str(), - args.listen_port - ); -} - -/// Main entry point for `run-server` sub command. -/// -/// # Errors -/// -/// In the case that there is an error running the server. -pub fn run(args_common: &crate::common::Args, args: &Args) -> Result<(), anyhow::Error> { - tracing::info!("args_common = {:?}", &args_common); - tracing::info!("args = {:?}", &args); - - if let Some(level) = args_common.verbose.log_level() { - match level { - log::Level::Trace | log::Level::Debug => { - std::env::set_var("RUST_LOG", "debug"); - env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - } - _ => (), - } - } - - // Load data that we need for running the server. - tracing::info!("Loading HPO..."); - let before_loading = std::time::Instant::now(); - let ontology = load_hpo(&args.path_hpo_dir)?; - tracing::info!("...done loading HPO in {:?}", before_loading.elapsed()); - - tracing::info!("Loading HGNC xlink..."); - let before_load_xlink = std::time::Instant::now(); - let ncbi_to_hgnc = crate::common::hgnc_xlink::load_ncbi_to_hgnc(&args.path_hgnc_xlink)?; - let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); - tracing::info!( - "... done loading HGNC xlink in {:?}", - before_load_xlink.elapsed() - ); - - tracing::info!("Loading HPO OBO..."); - let before_load_obo = std::time::Instant::now(); - let hpo_doc = fastobo::from_file(format!("{}/{}", &args.path_hpo_dir, "hp.obo")) - .map_err(|e| anyhow::anyhow!("Error loading HPO OBO: {}", e))?; - tracing::info!( - "... done loading HPO OBO in {:?}", - before_load_obo.elapsed() - ); - - tracing::info!("Indexing OBO..."); - let before_index_obo = std::time::Instant::now(); - let full_text_index = crate::index::Index::new(hpo_doc) - .map_err(|e| anyhow::anyhow!("Error indexing HPO OBO: {}", e))?; - tracing::info!("... done indexing OBO in {:?}", before_index_obo.elapsed()); - - let data = actix_web::web::Data::new(WebServerData { - ontology, - ncbi_to_hgnc, - hgnc_to_ncbi, - full_text_index, - }); - - // Print the server URL and some hints (the latter: unless suppressed). - print_hints(args); - // Launch the Actix web server. - actix_server::main(args, data)?; - - tracing::info!("All done. Have a nice day!"); - Ok(()) -} +pub mod run; +pub mod schema; diff --git a/src/server/actix_server/hpo_genes.rs b/src/server/run/hpo_genes.rs similarity index 54% rename from src/server/actix_server/hpo_genes.rs rename to src/server/run/hpo_genes.rs index 0e3afdc..63b2c91 100644 --- a/src/server/actix_server/hpo_genes.rs +++ b/src/server/run/hpo_genes.rs @@ -1,6 +1,6 @@ //! Implementation of `/hpo/genes`. -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; use actix_web::{ get, @@ -12,7 +12,7 @@ use hpo::{ Ontology, }; -use crate::server::WebServerData; +use crate::{common::Version, server::run::WebServerData}; use super::{CustomError, Match, ResultHpoTerm}; @@ -29,8 +29,11 @@ use super::{CustomError, Match, ResultHpoTerm}; /// The following propery defines how matches are performed: /// /// - `match` -- how to match -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -struct Query { +#[derive( + serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, Debug, Clone, +)] +#[schema(title = "HpoGenesQuery")] +pub struct Query { /// The gene ID to search for. pub gene_id: Option, /// The gene symbol to search for. @@ -57,9 +60,20 @@ fn _default_hpo_terms() -> bool { } /// Result entry for `handle`. -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive( + serde::Serialize, + serde::Deserialize, + utoipa::ToSchema, + Debug, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, +)] #[serde_with::skip_serializing_none] -struct ResultEntry { +#[schema(title = "HpoGenesResultEntry")] +pub struct ResultEntry { /// The gene's NCBI ID. pub gene_ncbi_id: u32, /// The gene's HGNC symbol. @@ -72,6 +86,7 @@ struct ResultEntry { } impl ResultEntry { + /// Create a `ResultEntry` from a `Gene` with an `Ontology`. pub fn from_gene_with_ontology( gene: &Gene, ontology: &Ontology, @@ -103,10 +118,11 @@ impl ResultEntry { } /// Container for the result. -#[derive(Debug, serde::Serialize, serde::Deserialize)] -struct Container { +#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +#[schema(title = "HpoGenesResult")] +pub struct Result { /// Version information. - pub version: crate::common::Version, + pub version: Version, /// The original query records. pub query: Query, /// The resulting records for the scored genes. @@ -115,9 +131,15 @@ struct Container { /// Query for genes in the HPO database. #[allow(clippy::unused_async)] +#[utoipa::path( + params(Query), + responses( + (status = 200, description = "The query was successful.", body = Result), + ) +)] #[get("/hpo/genes")] async fn handle( - data: Data, + data: Data>, _path: Path<()>, query: web::Query, ) -> actix_web::Result { @@ -174,8 +196,8 @@ async fn handle( result.sort(); - let result = Container { - version: crate::common::Version::new(&data.ontology.hpo_version()), + let result = Result { + version: Version::new(&data.ontology.hpo_version()), query: query.into_inner(), result, }; @@ -184,113 +206,200 @@ async fn handle( } #[cfg(test)] -mod test { - /// Helper function for running a query. - #[allow(dead_code)] - async fn run_query(uri: &str) -> Result { - let ontology = crate::common::load_hpo("tests/data/hpo")?; +pub(crate) mod test { + use std::sync::Arc; + + /// Return the default ``crate::server::run::WebServerData`` for testing. + #[rstest::fixture] + #[once] + pub fn web_server_data() -> Arc { + let ontology = crate::common::load_hpo("tests/data/hpo").expect("could not load HPO"); let ncbi_to_hgnc = - crate::common::hgnc_xlink::load_ncbi_to_hgnc("tests/data/hgnc_xlink.tsv")?; + crate::common::hgnc_xlink::load_ncbi_to_hgnc("tests/data/hgnc_xlink.tsv") + .expect("could not HGNC xlink"); let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); - let hpo_doc = fastobo::from_file("tests/data/hpo/hp.obo")?; + let hpo_doc = fastobo::from_file("tests/data/hpo/hp.obo").expect("could not load HPO OBO"); + + Arc::new(crate::server::run::WebServerData { + ontology, + ncbi_to_hgnc, + hgnc_to_ncbi, + full_text_index: crate::index::Index::new(hpo_doc) + .expect("could not create full text index"), + }) + } + + /// Helper function for running a query. + #[allow(dead_code)] + pub async fn run_query( + web_server_data: Arc, + uri: &str, + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() - .app_data(actix_web::web::Data::new(crate::server::WebServerData { - ontology, - ncbi_to_hgnc, - hgnc_to_ncbi, - full_text_index: crate::index::Index::new(hpo_doc)?, - })) + .app_data(actix_web::web::Data::new(web_server_data)) .service(super::handle), ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Container = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_ncbi_gene_id_exact_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_ncbi_gene_id_exact_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_id=2348").await? + &run_query(web_server_data.clone(), "/hpo/genes?gene_id=2348").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_ncbi_gene_id_exact_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_ncbi_gene_id_exact_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_id=2348&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_id=2348&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_hgnc_gene_id_exact_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_hgnc_gene_id_exact_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_id=HGNC:3791").await? + &run_query(web_server_data.clone(), "/hpo/genes?gene_id=HGNC:3791").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_hgnc_gene_id_exact_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_hgnc_gene_id_exact_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_id=HGNC:3791&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_id=HGNC:3791&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_exact_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_exact_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=TGDS").await? + &run_query(web_server_data.clone(), "/hpo/genes?gene_symbol=TGDS").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_exact_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_exact_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=TGDS&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=TGDS&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_prefix_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_prefix_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=TGD&match=prefix").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=TGD&match=prefix" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_prefix_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_prefix_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=TGD&match=prefix&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=TGD&match=prefix&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_suffix_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_suffix_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=GDS&match=suffix").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=GDS&match=suffix" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_suffix_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_suffix_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=GDS&match=suffix&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=GDS&match=suffix&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_contains_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_contains_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=GD&match=contains").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=GD&match=contains" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_genes_gene_symbol_contains_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_genes_gene_symbol_contains_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/genes?gene_symbol=GD&match=contains&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/genes?gene_symbol=GD&match=contains&hpo_terms=true" + ) + .await? )) } } diff --git a/src/server/actix_server/hpo_omims.rs b/src/server/run/hpo_omims.rs similarity index 58% rename from src/server/actix_server/hpo_omims.rs rename to src/server/run/hpo_omims.rs index 266e3e7..c294d03 100644 --- a/src/server/actix_server/hpo_omims.rs +++ b/src/server/run/hpo_omims.rs @@ -1,5 +1,7 @@ //! Implementation of `/hpo/omims`. +use std::sync::Arc; + use actix_web::{ get, web::{self, Data, Json, Path}, @@ -11,7 +13,7 @@ use hpo::{ Ontology, }; -use crate::server::WebServerData; +use crate::{common::Version, server::run::WebServerData}; use super::{CustomError, Match, ResultHpoTerm}; @@ -28,8 +30,11 @@ use super::{CustomError, Match, ResultHpoTerm}; /// The following propery defines how matches are performed: /// /// - `match` -- how to match -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -struct Query { +#[derive( + serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, Debug, Clone, +)] +#[schema(title = "HpoOmimsQuery")] +pub struct Query { /// The OMIM ID to search for. pub omim_id: Option, /// The disease name to search for. @@ -56,8 +61,9 @@ fn _default_hpo_terms() -> bool { } /// Result entry for `handle`. -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -struct ResultEntry { +#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] +#[schema(title = "HpoOmimsResultEntry")] +pub struct ResultEntry { /// The OMIM ID. pub omim_id: String, /// The OMIM disease name. @@ -92,6 +98,7 @@ impl Ord for ResultEntry { } impl ResultEntry { + /// Create a `ResultEntry` from an `OmimDisease`. pub fn from_omim_disease_with_ontology( omim_disease: &OmimDisease, ontology: &Ontology, @@ -104,14 +111,10 @@ impl ResultEntry { .into_iter() .collect::() .into_iter() - .map(|term_id| ontology.hpo(term_id)) - .filter(std::option::Option::is_some) - .map(|term| { - let term = term.expect("filtered above"); - ResultHpoTerm { - term_id: term.id().to_string(), - name: term.name().to_string(), - } + .filter_map(|term_id| ontology.hpo(term_id)) + .map(|term| ResultHpoTerm { + term_id: term.id().to_string(), + name: term.name().to_string(), }) .collect::>(); result.sort(); @@ -128,10 +131,11 @@ impl ResultEntry { } /// Container for the result. -#[derive(Debug, serde::Serialize, serde::Deserialize)] -struct Container { +#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug)] +#[schema(title = "HpoOmimsResult")] +pub struct Result { /// Version information. - pub version: crate::common::Version, + pub version: Version, /// The original query records. pub query: Query, /// The resulting records for the scored genes. @@ -140,9 +144,15 @@ struct Container { /// Query for OMIM diseases in the HPO database. #[allow(clippy::unused_async)] +#[utoipa::path( + params(Query), + responses( + (status = 200, description = "The query was successful.", body = Result), + ) +)] #[get("/hpo/omims")] async fn handle( - data: Data, + data: Data>, _path: Path<()>, query: web::Query, ) -> actix_web::Result { @@ -201,8 +211,8 @@ async fn handle( result.sort(); - let result = Container { - version: crate::common::Version::new(&data.ontology.hpo_version()), + let result = Result { + version: Version::new(&data.ontology.hpo_version()), query: query.into_inner(), result, }; @@ -212,98 +222,161 @@ async fn handle( #[cfg(test)] mod test { + use std::sync::Arc; + + use crate::server::run::hpo_genes::test::web_server_data; + /// Helper function for running a query. #[allow(dead_code)] - async fn run_query(uri: &str) -> Result { - let ontology = crate::common::load_hpo("tests/data/hpo")?; - let ncbi_to_hgnc = - crate::common::hgnc_xlink::load_ncbi_to_hgnc("tests/data/hgnc_xlink.tsv")?; - let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); - let hpo_doc = fastobo::from_file("tests/data/hpo/hp.obo")?; + pub async fn run_query( + web_server_data: Arc, + uri: &str, + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() - .app_data(actix_web::web::Data::new(crate::server::WebServerData { - ontology, - ncbi_to_hgnc, - hgnc_to_ncbi, - full_text_index: crate::index::Index::new(hpo_doc)?, - })) + .app_data(actix_web::web::Data::new(web_server_data)) .service(super::handle), ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Container = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_omim_id_exact_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_omim_id_exact_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?omim_id=616145").await? + &run_query(web_server_data.clone(), "/hpo/omims?omim_id=616145").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_omim_id_exact_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_omim_id_exact_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?omim_id=616145&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?omim_id=616145&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_exact_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_exact_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=Catel-Manzke+syndrome").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=Catel-Manzke+syndrome" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_exact_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_exact_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_prefix_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_prefix_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=Catel-Manzke+syndro&match=prefix").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=Catel-Manzke+syndro&match=prefix" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_prefix_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_prefix_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_suffix_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_suffix_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=tel-Manzke+syndrome&match=suffix").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=tel-Manzke+syndrome&match=suffix" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_suffix_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_suffix_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_contains_no_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_contains_no_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=tel-Manzke+syndro&match=contains").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=tel-Manzke+syndro&match=contains" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_omims_name_contains_with_hpo_terms() -> Result<(), anyhow::Error> { + async fn hpo_omims_name_contains_with_hpo_terms( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true").await? + &run_query( + web_server_data.clone(), + "/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true" + ) + .await? )) } } diff --git a/src/server/actix_server/hpo_sim/mod.rs b/src/server/run/hpo_sim/mod.rs similarity index 100% rename from src/server/actix_server/hpo_sim/mod.rs rename to src/server/run/hpo_sim/mod.rs diff --git a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap similarity index 99% rename from src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap rename to src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap index 3f0915d..c9b90ee 100644 --- a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap +++ b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_hgnc_gene_ids.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_sim/term_gene.rs +source: src/server/run/hpo_sim/term_gene.rs expression: "&run_query(\"/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=HGNC:20324,HGNC:12403\").await?" --- version: diff --git a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap similarity index 99% rename from src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap rename to src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap index 70c16b8..037fb40 100644 --- a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap +++ b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_ncbi_gene_ids.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_sim/term_gene.rs +source: src/server/run/hpo_sim/term_gene.rs expression: "&run_query(\"/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=23483,7273\").await?" --- version: diff --git a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap similarity index 99% rename from src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap rename to src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap index 817282d..4a7fbb4 100644 --- a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap +++ b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_gene__test__hpo_sim_term_gene_terms_symbols.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_sim/term_gene.rs +source: src/server/run/hpo_sim/term_gene.rs expression: "&run_query(\"/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_symbols=TGDS,TTN\").await?" --- version: diff --git a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap similarity index 85% rename from src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap rename to src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap index 75cf7ca..c3a92b8 100644 --- a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap +++ b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_one_one.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_sim/term_term.rs +source: src/server/run/hpo_sim/term_term.rs expression: "&run_query(\"/hpo/sim/term-term?lhs=HP:0010442&rhs=HP:0001780\").await?" --- version: @@ -17,4 +17,3 @@ result: - lhs: "HP:0010442" rhs: "HP:0001780" score: 1.2074362 - diff --git a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap similarity index 91% rename from src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap rename to src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap index 2ebe20d..ac39b28 100644 --- a/src/server/actix_server/hpo_sim/snapshots/viguno__server__actix_server__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap +++ b/src/server/run/hpo_sim/snapshots/viguno__server__run__hpo_sim__term_term__test__hpo_sim_term_term_two_two.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_sim/term_term.rs +source: src/server/run/hpo_sim/term_term.rs expression: "&run_query(\"/hpo/sim/term-term?lhs=HP:0010442,HP:0000347&rhs=HP:0001780,HP:0000252\").await?" --- version: @@ -28,4 +28,3 @@ result: - lhs: "HP:0000347" rhs: "HP:0001780" score: 0.48051217 - diff --git a/src/server/actix_server/hpo_sim/term_gene.rs b/src/server/run/hpo_sim/term_gene.rs similarity index 69% rename from src/server/actix_server/hpo_sim/term_gene.rs rename to src/server/run/hpo_sim/term_gene.rs index 57fd8a9..4e3b34f 100644 --- a/src/server/actix_server/hpo_sim/term_gene.rs +++ b/src/server/run/hpo_sim/term_gene.rs @@ -1,6 +1,8 @@ //! Entry point `/hpo/sim/term-gene` that allows the similarity computation between a set of //! terms and a gene. +use std::sync::Arc; + use actix_web::{ get, web::{self, Data, Json, Path}, @@ -10,7 +12,7 @@ use actix_web::{ use hpo::{annotations::GeneId, term::HpoGroup, HpoTermId, Ontology}; use super::super::CustomError; -use crate::{query, server::WebServerData}; +use crate::{query, server::run::WebServerData}; /// Parameters for `handle`. /// @@ -21,8 +23,9 @@ use crate::{query, server::WebServerData}; /// gene ID or HGNC gene ID. /// - `gene_symbols` -- set of symbols for genes to use as /// "database" -#[derive(serde::Deserialize, Debug, Clone)] -struct Query { +#[derive(serde::Deserialize, Debug, Clone, utoipa::ToSchema, utoipa::IntoParams)] +#[schema(title = "HpoSimTermGeneQuery")] +pub struct Query { /// Set of terms to use as query. #[serde(deserialize_with = "super::super::vec_str_deserialize")] pub terms: Vec, @@ -45,9 +48,15 @@ struct Query { /// Query for similarity between a set of terms to each entry in a /// list of genes. #[allow(clippy::unused_async)] +#[utoipa::path( + params(Query), + responses( + (status = 200, description = "The query was successful.", body = Result), + ) +)] #[get("/hpo/sim/term-gene")] async fn handle( - data: Data, + data: Data>, _path: Path<()>, query: web::Query, ) -> actix_web::Result { @@ -98,57 +107,68 @@ async fn handle( #[cfg(test)] mod test { + use std::sync::Arc; + + use crate::server::run::hpo_genes::test::web_server_data; + /// Helper function for running a query. #[allow(dead_code)] - async fn run_query(uri: &str) -> Result { - let hpo_path = "tests/data/hpo"; - let ontology = crate::common::load_hpo(hpo_path)?; - let ncbi_to_hgnc = - crate::common::hgnc_xlink::load_ncbi_to_hgnc("tests/data/hgnc_xlink.tsv")?; - let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); - let hpo_doc = fastobo::from_file("tests/data/hpo/hp.obo")?; - + pub async fn run_query( + web_server_data: Arc, + uri: &str, + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() - .app_data(actix_web::web::Data::new(crate::server::WebServerData { - ontology, - ncbi_to_hgnc, - hgnc_to_ncbi, - full_text_index: crate::index::Index::new(hpo_doc)?, - })) + .app_data(actix_web::web::Data::new(web_server_data)) .service(super::handle), ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: crate::query::query_result::Container = + let resp: crate::query::query_result::Result = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_sim_term_gene_terms_ncbi_gene_ids() -> Result<(), anyhow::Error> { + async fn hpo_sim_term_gene_terms_ncbi_gene_ids( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=23483,7273") - .await? + &run_query( + web_server_data.clone(), + "/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=23483,7273" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_sim_term_gene_terms_hgnc_gene_ids() -> Result<(), anyhow::Error> { + async fn hpo_sim_term_gene_terms_hgnc_gene_ids( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( &run_query( + web_server_data.clone(), "/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_ids=HGNC:20324,HGNC:12403" ) .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_sim_term_gene_terms_symbols() -> Result<(), anyhow::Error> { + async fn hpo_sim_term_gene_terms_symbols( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_symbols=TGDS,TTN") - .await? + &run_query( + web_server_data.clone(), + "/hpo/sim/term-gene?terms=HP:0010442,HP:0000347&gene_symbols=TGDS,TTN" + ) + .await? )) } } diff --git a/src/server/actix_server/hpo_sim/term_term.rs b/src/server/run/hpo_sim/term_term.rs similarity index 70% rename from src/server/actix_server/hpo_sim/term_term.rs rename to src/server/run/hpo_sim/term_term.rs index 076062e..1535394 100644 --- a/src/server/actix_server/hpo_sim/term_term.rs +++ b/src/server/run/hpo_sim/term_term.rs @@ -1,6 +1,8 @@ //! Entry point `/hpo/sim/term-term` allows the pairwise similary computation between two sets //! of HPO terms. +use std::sync::Arc; + use actix_web::{ get, web::{self, Data, Json, Path}, @@ -12,8 +14,8 @@ use hpo::{ }; use itertools::Itertools; -use crate::common::{to_pairwise_sim, IcBasedOn, ScoreCombiner, SimilarityMethod}; -use crate::server::{actix_server::CustomError, WebServerData}; +use crate::common::{to_pairwise_sim, IcBasedOn, ScoreCombiner, SimilarityMethod, Version}; +use crate::server::{run::CustomError, run::WebServerData}; /// Parameters for `handle`. /// @@ -21,7 +23,7 @@ use crate::server::{actix_server::CustomError, WebServerData}; /// /// - `lhs` -- first set of terms to compute similarity for /// - `rhs` -- econd set of terms to compute similarity for -#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone)] +#[derive(serde::Serialize, serde::Deserialize, utoipa::IntoParams, Default, Debug, Clone)] pub struct RequestQuery { /// The one set of HPO terms to compute similarity for. #[serde(deserialize_with = "super::super::vec_str_deserialize")] @@ -43,7 +45,8 @@ pub struct RequestQuery { /// Request as sent together with the response. /// /// The difference is that the `lhs` and `rhs` fields are replaced by vecs. -#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone)] +#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Default, Debug, Clone)] +#[schema(title = "HpoSimTermTermQuery")] pub struct ResponseQuery { /// The one set of HPO terms to compute similarity for. pub lhs: Vec, @@ -61,10 +64,11 @@ pub struct ResponseQuery { } /// Result container. -#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone)] -pub struct Container { +#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Default, Debug, Clone)] +#[schema(title = "HpoSimTermTermResult")] +pub struct Result { /// Version information. - pub version: crate::common::Version, + pub version: Version, /// The original query records. pub query: ResponseQuery, /// The resulting records for the scored genes. @@ -72,7 +76,17 @@ pub struct Container { } /// Result entry for `handle`. -#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone, PartialEq, PartialOrd)] +#[derive( + serde::Serialize, + serde::Deserialize, + utoipa::ToSchema, + Default, + Debug, + Clone, + PartialEq, + PartialOrd, +)] +#[schema(title = "HpoSimTermTermResultEntry")] pub struct ResultEntry { /// The lhs entry. pub lhs: String, @@ -90,9 +104,15 @@ pub struct ResultEntry { /// /// In the case that there is an error running the server. #[allow(clippy::unused_async)] +#[utoipa::path( + params(RequestQuery), + responses( + (status = 200, description = "The query was successful.", body = Result), + ) +)] #[get("/hpo/sim/term-term")] async fn handle( - data: Data, + data: Data>, _path: Path<()>, query: web::Query, ) -> actix_web::Result { @@ -140,8 +160,8 @@ async fn handle( combiner, } = query.into_inner(); - let result = Container { - version: crate::common::Version::new(&data.ontology.hpo_version()), + let result = Result { + version: Version::new(&data.ontology.hpo_version()), query: ResponseQuery { lhs, rhs, @@ -159,50 +179,53 @@ async fn handle( #[cfg(test)] mod test { + use std::sync::Arc; + + use crate::server::run::hpo_genes::test::web_server_data; + /// Helper function for running a query. #[allow(dead_code)] - async fn run_query(uri: &str) -> Result { - let ontology = crate::common::load_hpo("tests/data/hpo")?; - let ncbi_to_hgnc = - crate::common::hgnc_xlink::load_ncbi_to_hgnc("tests/data/hgnc_xlink.tsv")?; - let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); - let hpo_doc = fastobo::from_file("tests/data/hpo/hp.obo")?; - + pub async fn run_query( + web_server_data: Arc, + uri: &str, + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() - .app_data(actix_web::web::Data::new(crate::server::WebServerData { - ontology, - ncbi_to_hgnc, - hgnc_to_ncbi, - full_text_index: crate::index::Index::new(hpo_doc)?, - })) + .app_data(actix_web::web::Data::new(web_server_data)) .service(super::handle), ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - dbg!(&req); - let resp: serde_json::Value = actix_web::test::call_and_read_body_json(&app, req).await; - dbg!(&resp); - let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - dbg!(&req); - let resp = actix_web::test::call_and_read_body_json(&app, req).await; - dbg!(&resp); + let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_sim_term_term_one_one() -> Result<(), anyhow::Error> { + async fn hpo_sim_term_term_one_one( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/sim/term-term?lhs=HP:0010442&rhs=HP:0001780").await? + &run_query( + web_server_data.clone(), + "/hpo/sim/term-term?lhs=HP:0010442&rhs=HP:0001780" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_sim_term_term_two_two() -> Result<(), anyhow::Error> { + async fn hpo_sim_term_term_two_two( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/sim/term-term?lhs=HP:0010442,HP:0000347&rhs=HP:0001780,HP:0000252") - .await? + &run_query( + web_server_data.clone(), + "/hpo/sim/term-term?lhs=HP:0010442,HP:0000347&rhs=HP:0001780,HP:0000252" + ) + .await? )) } } diff --git a/src/server/actix_server/hpo_terms.rs b/src/server/run/hpo_terms.rs similarity index 77% rename from src/server/actix_server/hpo_terms.rs rename to src/server/run/hpo_terms.rs index ada04e7..06ada38 100644 --- a/src/server/actix_server/hpo_terms.rs +++ b/src/server/run/hpo_terms.rs @@ -1,6 +1,6 @@ //! Implementation of `/hpo/terms`. -use std::collections::HashMap; +use std::{collections::HashMap, sync::Arc}; use actix_web::{ get, @@ -9,7 +9,7 @@ use actix_web::{ }; use hpo::{annotations::AnnotationId, HpoTerm, HpoTermId, Ontology}; -use crate::server::WebServerData; +use crate::{common::Version, server::run::WebServerData}; use super::{CustomError, ResultGene}; @@ -22,8 +22,11 @@ use super::{CustomError, ResultGene}; /// - `gene_symbol` -- specify the gene symbol /// - `max_results` -- the maximum number of records to return /// - `genes` -- whether to include `"genes"` in result -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -struct Query { +#[derive( + serde::Serialize, serde::Deserialize, utoipa::ToSchema, utoipa::IntoParams, Debug, Clone, +)] +#[schema(title = "HpoTermsQuery")] +pub struct Query { /// The term ID to search for. pub term_id: Option, /// The term name to search for. @@ -47,8 +50,9 @@ fn _default_genes() -> bool { } /// Result entry for `fetch_hpo_genes`. -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -struct ResultEntry { +#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema, Debug, Clone)] +#[schema(title = "HpoTermsResultEntry")] +pub struct ResultEntry { /// The HPO term's ID. pub term_id: String, /// The HPO term's name. @@ -89,6 +93,8 @@ impl Ord for ResultEntry { } impl ResultEntry { + /// Create a `ResultEntry` from an `HpoTerm`. + #[allow(clippy::missing_panics_doc)] pub fn from_term_with_ontology( term: &HpoTerm, ontology: &Ontology, @@ -183,10 +189,11 @@ impl ResultEntry { } /// Container for the result. -#[derive(Debug, serde::Serialize, serde::Deserialize)] -struct Container { +#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)] +#[schema(title = "HpoTermsResult")] +pub struct Result { /// Version information. - pub version: crate::common::Version, + pub version: Version, /// The original query records. pub query: Query, /// The resulting records for the scored genes. @@ -200,9 +207,15 @@ struct Container { /// In the case that there is an error running the server. #[allow(clippy::unused_async)] #[allow(clippy::too_many_lines)] +#[utoipa::path( + params(Query), + responses( + (status = 200, description = "The query was successful.", body = Result), + ) +)] #[get("/hpo/terms")] async fn handle( - data: Data, + data: Data>, _path: Path<()>, query: web::Query, ) -> actix_web::Result { @@ -319,8 +332,8 @@ async fn handle( } }; - let result = Container { - version: crate::common::Version::new(&data.ontology.hpo_version()), + let result = Result { + version: Version::new(&data.ontology.hpo_version()), query: query.into_inner(), result, }; @@ -330,70 +343,97 @@ async fn handle( #[cfg(test)] mod test { + use std::sync::Arc; + + use crate::server::run::hpo_genes::test::web_server_data; + /// Helper function for running a query. #[allow(dead_code)] - async fn run_query(uri: &str) -> Result { - let ontology = crate::common::load_hpo("tests/data/hpo")?; - let ncbi_to_hgnc = - crate::common::hgnc_xlink::load_ncbi_to_hgnc("tests/data/hgnc_xlink.tsv")?; - let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); - let hpo_doc = fastobo::from_file("tests/data/hpo/hp.obo")?; + pub async fn run_query( + web_server_data: Arc, + uri: &str, + ) -> Result { let app = actix_web::test::init_service( actix_web::App::new() - .app_data(actix_web::web::Data::new(crate::server::WebServerData { - ontology, - ncbi_to_hgnc, - hgnc_to_ncbi, - full_text_index: crate::index::Index::new(hpo_doc)?, - })) + .app_data(actix_web::web::Data::new(web_server_data)) .service(super::handle), ) .await; let req = actix_web::test::TestRequest::get().uri(uri).to_request(); - let resp: super::Container = actix_web::test::call_and_read_body_json(&app, req).await; + let resp: super::Result = actix_web::test::call_and_read_body_json(&app, req).await; Ok(resp) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_terms_term_id_exact_no_genes() -> Result<(), anyhow::Error> { + async fn hpo_terms_term_id_exact_no_genes( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/terms?term_id=HP:0000023").await? + &run_query(web_server_data.clone(), "/hpo/terms?term_id=HP:0000023").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_terms_term_id_exact_with_genes() -> Result<(), anyhow::Error> { + async fn hpo_terms_term_id_exact_with_genes( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/terms?term_id=HP:0000023&genes=true").await? + &run_query( + web_server_data.clone(), + "/hpo/terms?term_id=HP:0000023&genes=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_terms_name_exact_no_genes() -> Result<(), anyhow::Error> { + async fn hpo_terms_name_exact_no_genes( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/terms?name=Inguinal+hernia").await? + &run_query(web_server_data.clone(), "/hpo/terms?name=Inguinal+hernia").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_terms_name_exact_with_genes() -> Result<(), anyhow::Error> { + async fn hpo_terms_name_exact_with_genes( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/terms?name=Inguinal+hernia&genes=true").await? + &run_query( + web_server_data.clone(), + "/hpo/terms?name=Inguinal+hernia&genes=true" + ) + .await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_terms_name_fuzzy_no_genes() -> Result<(), anyhow::Error> { + async fn hpo_terms_name_fuzzy_no_genes( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/terms?name=Inguinal+hern").await? + &run_query(web_server_data.clone(), "/hpo/terms?name=Inguinal+hern").await? )) } + #[rstest::rstest] #[actix_web::test] - async fn hpo_terms_name_fuzzy_with_genes() -> Result<(), anyhow::Error> { + async fn hpo_terms_name_fuzzy_with_genes( + web_server_data: &Arc, + ) -> Result<(), anyhow::Error> { Ok(insta::assert_yaml_snapshot!( - &run_query("/hpo/terms?name=Inguinal+hern&genes=true").await? + &run_query( + web_server_data.clone(), + "/hpo/terms?name=Inguinal+hern&genes=true" + ) + .await? )) } } diff --git a/src/server/run/mod.rs b/src/server/run/mod.rs new file mode 100644 index 0000000..f46994e --- /dev/null +++ b/src/server/run/mod.rs @@ -0,0 +1,341 @@ +//! Implementation of the Actix server. + +pub mod hpo_genes; +pub mod hpo_omims; +pub mod hpo_sim; +pub mod hpo_terms; + +use std::{collections::HashMap, sync::Arc}; + +use actix_web::{middleware::Logger, web::Data, App, HttpServer, ResponseError}; +use serde::{Deserialize, Deserializer, Serialize}; +use utoipa::OpenApi; + +use crate::common::load_hpo; + +/// Data structure for the web server data. +pub struct WebServerData { + /// The HPO ontology (`hpo` crate). + pub ontology: hpo::Ontology, + /// Xlink map from NCBI gene ID to HGNC gene ID. + pub ncbi_to_hgnc: HashMap, + /// Xlink map from HGNC gene ID to NCBI gene ID. + pub hgnc_to_ncbi: HashMap, + /// The full text index over the HPO OBO document. + pub full_text_index: crate::index::Index, +} + +/// Command line arguments for `server run` sub command. +#[derive(clap::Parser, Debug)] +#[command(author, version, about = "Run viguno REST API server", long_about = None)] +pub struct Args { + /// Path to the directory with the HPO files. + #[arg(long, required = true)] + pub path_hpo_dir: String, + /// Path to the TSV file with the HGNC xlink data. + #[arg(long, required = true)] + pub path_hgnc_xlink: String, + + /// Whether to suppress printing hints. + #[arg(long, default_value_t = false)] + pub suppress_hints: bool, + + /// IP to listen on. + #[arg(long, default_value = "127.0.0.1")] + pub listen_host: String, + /// Port to listen on. + #[arg(long, default_value_t = 8080)] + pub listen_port: u16, +} + +#[derive(Debug)] +struct CustomError { + err: anyhow::Error, +} + +impl std::fmt::Display for CustomError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.err) + } +} + +impl CustomError { + fn new(err: anyhow::Error) -> Self { + CustomError { err } + } +} + +impl ResponseError for CustomError {} + +/// Specify how to perform query matches in the API calls. +#[derive(Serialize, Deserialize, utoipa::ToSchema, Debug, Clone, Copy, Default, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum Match { + #[default] + /// Exact string match. + Exact, + /// Prefix string match. + Prefix, + /// Suffix string match. + Suffix, + /// String containment. + Contains, +} + +/// Representation of a gene. +#[derive( + serde::Deserialize, + serde::Serialize, + utoipa::ToSchema, + Default, + Debug, + Clone, + PartialOrd, + Ord, + PartialEq, + Eq, +)] +#[serde_with::skip_serializing_none] +pub struct ResultGene { + /// The HPO ID. + pub ncbi_gene_id: u32, + /// The description. + pub gene_symbol: String, + /// The HGNC ID. + pub hgnc_id: Option, +} + +/// Representation of an HPO term. +#[derive( + serde::Deserialize, + serde::Serialize, + utoipa::ToSchema, + Default, + Debug, + Clone, + PartialOrd, + Ord, + PartialEq, + Eq, +)] +pub struct ResultHpoTerm { + /// The HPO ID. + pub term_id: String, + /// The term name. + pub name: String, +} + +/// Helper to deserialize a comma-separated list of strings. +fn vec_str_deserialize<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let str_sequence = String::deserialize(deserializer)?; + Ok(str_sequence + .split(',') + .map(std::borrow::ToOwned::to_owned) + .collect()) +} + +/// Helper to deserialize a comma-separated list of strings. +fn option_vec_str_deserialize<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let str_sequence = String::deserialize(deserializer)?; + if str_sequence.is_empty() { + Ok(None) + } else { + Ok(Some( + str_sequence + .split(',') + .map(std::borrow::ToOwned::to_owned) + .collect(), + )) + } +} + +/// Utoipa-based `OpenAPI` generation helper. +#[derive(utoipa::OpenApi)] +#[openapi( + paths(hpo_genes::handle, hpo_terms::handle, hpo_omims::handle,), + components(schemas( + hpo_genes::Query, + hpo_genes::Result, + hpo_genes::ResultEntry, + hpo_omims::Query, + hpo_omims::Result, + hpo_omims::ResultEntry, + hpo_terms::Query, + hpo_terms::Result, + hpo_terms::ResultEntry, + hpo_sim::term_gene::Query, + crate::query::query_result::Result, + crate::query::query_result::ResultEntry, + crate::query::query_result::TermDetails, + crate::query::HpoTerm, + hpo_sim::term_term::ResponseQuery, + hpo_sim::term_term::Result, + hpo_sim::term_term::ResultEntry, + ResultGene, + ResultHpoTerm, + Match, + crate::common::Version, + crate::common::IcBasedOn, + crate::common::SimilarityMethod, + crate::common::ScoreCombiner, + )) +)] +pub struct ApiDoc; + +/// Main entry point for running the REST server. +#[allow(clippy::unused_async)] +#[actix_web::main] +pub async fn main(args: &Args, dbs: Data>) -> std::io::Result<()> { + let openapi = ApiDoc::openapi(); + + HttpServer::new(move || { + App::new() + .app_data(dbs.clone()) + .service(hpo_genes::handle) + .service(hpo_terms::handle) + .service(hpo_omims::handle) + .service(hpo_sim::term_term::handle) + .service(hpo_sim::term_gene::handle) + .service( + utoipa_swagger_ui::SwaggerUi::new("/swagger-ui/{_:.*}") + .url("/api-docs/openapi.json", openapi.clone()), + ) + .wrap(Logger::default()) + }) + .bind((args.listen_host.as_str(), args.listen_port))? + .run() + .await +} + +/// Print some hints via `tracing::info!`. +pub fn print_hints(args: &Args) { + tracing::info!( + "Launching server main on http://{}:{} ...", + args.listen_host.as_str(), + args.listen_port + ); + + // Short-circuit if no hints are to be + if args.suppress_hints { + return; + } + + tracing::info!( + " ==> for Swagger UI, see: http://{}:{}/swagger-ui/", + args.listen_host.as_str(), + args.listen_port + ); + + // The endpoint `/hpo/genes` provides information related to genes by symbol. + tracing::info!( + " try: http://{}:{}/hpo/genes?gene_symbol=TGDS", + args.listen_host.as_str(), + args.listen_port + ); + // Also, you can query `/hpo/genes` by NCBI gene ID and return the HPO terms of the gene. + tracing::info!( + " try: http://{}:{}/hpo/genes?gene_id=23483&hpo_terms=true", + args.listen_host.as_str(), + args.listen_port + ); + // The `/hpo/omims` term provides information on OMIM terms and can include HPO terms for + // the disease. + tracing::info!( + " try: http://{}:{}/hpo/omims?omim_id=616145&hpo_terms=true", + args.listen_host.as_str(), + args.listen_port + ); + // The `/hpo/terms` endpoint allows to query by HPO term ID and optionally return a list of + // genes that are linked to the term. + tracing::info!( + " try: http://{}:{}/hpo/terms?term_id=HP:0000023&genes=true", + args.listen_host.as_str(), + args.listen_port + ); + // We can use `/hpo/sim/term-term` to compute similarity between two HPO term sets `lhs` + // and `rhs` using a similarity metric. + tracing::info!( + " try: http://{}:{}/hpo/sim/term-term?lhs=HP:0001166,HP:0040069&rhs=HP:0005918,\ + HP:0004188", + args.listen_host.as_str(), + args.listen_port + ); + // The endpoint `/hpo/sim/term-gene` allows to compute the same for a list of `terms` and + // `gene_symbols`. + tracing::info!( + " try: http://{}:{}/hpo/sim/term-gene?terms=HP:0001166,HP:0000098&gene_symbols=FBN1,TGDS,TTN", + args.listen_host.as_str(), + args.listen_port + ); +} + +/// Main entry point for `run-server` sub command. +/// +/// # Errors +/// +/// In the case that there is an error running the server. +pub fn run(args_common: &crate::common::Args, args: &Args) -> Result<(), anyhow::Error> { + tracing::info!("args_common = {:?}", &args_common); + tracing::info!("args = {:?}", &args); + + if let Some(level) = args_common.verbose.log_level() { + match level { + log::Level::Trace | log::Level::Debug => { + std::env::set_var("RUST_LOG", "debug"); + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + } + _ => (), + } + } + + // Load data that we need for running the server. + tracing::info!("Loading HPO..."); + let before_loading = std::time::Instant::now(); + let ontology = load_hpo(&args.path_hpo_dir)?; + tracing::info!("...done loading HPO in {:?}", before_loading.elapsed()); + + tracing::info!("Loading HGNC xlink..."); + let before_load_xlink = std::time::Instant::now(); + let ncbi_to_hgnc = crate::common::hgnc_xlink::load_ncbi_to_hgnc(&args.path_hgnc_xlink)?; + let hgnc_to_ncbi = crate::common::hgnc_xlink::inverse_hashmap(&ncbi_to_hgnc); + tracing::info!( + "... done loading HGNC xlink in {:?}", + before_load_xlink.elapsed() + ); + + tracing::info!("Loading HPO OBO..."); + let before_load_obo = std::time::Instant::now(); + let hpo_doc = fastobo::from_file(format!("{}/{}", &args.path_hpo_dir, "hp.obo")) + .map_err(|e| anyhow::anyhow!("Error loading HPO OBO: {}", e))?; + tracing::info!( + "... done loading HPO OBO in {:?}", + before_load_obo.elapsed() + ); + + tracing::info!("Indexing OBO..."); + let before_index_obo = std::time::Instant::now(); + let full_text_index = crate::index::Index::new(hpo_doc) + .map_err(|e| anyhow::anyhow!("Error indexing HPO OBO: {}", e))?; + tracing::info!("... done indexing OBO in {:?}", before_index_obo.elapsed()); + + let data = actix_web::web::Data::new(Arc::new(WebServerData { + ontology, + ncbi_to_hgnc, + hgnc_to_ncbi, + full_text_index, + })); + + // Print the server URL and some hints (the latter: unless suppressed). + print_hints(args); + // Launch the Actix web server. + main(args, data)?; + + tracing::info!("All done. Have a nice day!"); + Ok(()) +} diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap similarity index 97% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap index e580dc7..b5e2a33 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=GD&match=contains\").await?" --- version: @@ -90,4 +90,3 @@ result: - gene_ncbi_id: 728294 gene_symbol: D2HGDH hgnc_id: "HGNC:28358" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap similarity index 99% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap index 9026baf..412fd0d 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_contains_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=GD&match=contains&hpo_terms=true\").await?" --- version: @@ -2108,4 +2108,3 @@ result: name: Myoclonic seizure - term_id: "HP:0100704" name: Cerebral visual impairment - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap index a07fdd6..feaeb0e 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=TGDS\").await?" --- version: @@ -15,4 +15,3 @@ result: - gene_ncbi_id: 23483 gene_symbol: TGDS hgnc_id: "HGNC:20324" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap index 540e7ff..43d40f0 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_exact_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=TGDS&hpo_terms=true\").await?" --- version: @@ -142,4 +142,3 @@ result: name: Thin eyebrow - term_id: "HP:0100490" name: Camptodactyly of finger - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap index 8245e7f..d8a9f2b 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=TGD&match=prefix\").await?" --- version: @@ -15,4 +15,3 @@ result: - gene_ncbi_id: 23483 gene_symbol: TGDS hgnc_id: "HGNC:20324" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap index 67cf9ac..d26f565 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_prefix_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=TGD&match=prefix&hpo_terms=true\").await?" --- version: @@ -142,4 +142,3 @@ result: name: Thin eyebrow - term_id: "HP:0100490" name: Camptodactyly of finger - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap index 0dc5946..f05816e 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=GDS&match=suffix\").await?" --- version: @@ -15,4 +15,3 @@ result: - gene_ncbi_id: 23483 gene_symbol: TGDS hgnc_id: "HGNC:20324" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap index 148f0fe..5c30b6e 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_gene_symbol_suffix_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_symbol=GDS&match=suffix&hpo_terms=true\").await?" --- version: @@ -142,4 +142,3 @@ result: name: Thin eyebrow - term_id: "HP:0100490" name: Camptodactyly of finger - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap index d2d3173..e074ea0 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_id=HGNC:3791\").await?" --- version: @@ -15,4 +15,3 @@ result: - gene_ncbi_id: 2348 gene_symbol: FOLR1 hgnc_id: "HGNC:3791" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap similarity index 93% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap index 9f613e9..a02ed94 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_hgnc_gene_id_exact_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_id=HGNC:3791&hpo_terms=true\").await?" --- version: @@ -26,4 +26,3 @@ result: name: Neurodegeneration - term_id: "HP:0002376" name: Developmental regression - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap index a2a8434..8c8a419 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_id=2348\").await?" --- version: @@ -15,4 +15,3 @@ result: - gene_ncbi_id: 2348 gene_symbol: FOLR1 hgnc_id: "HGNC:3791" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap similarity index 93% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap index fda3fe1..6744808 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_genes__test__hpo_genes_ncbi_gene_id_exact_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_genes.rs +source: src/server/run/hpo_genes.rs expression: "&run_query(\"/hpo/genes?gene_id=2348&hpo_terms=true\").await?" --- version: @@ -26,4 +26,3 @@ result: name: Neurodegeneration - term_id: "HP:0002376" name: Developmental regression - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap index 393544b..5273993 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=tel-Manzke+syndro&match=contains\").await?" --- version: @@ -14,4 +14,3 @@ query: result: - omim_id: "OMIM:616145" name: Catel-Manzke syndrome - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap index 2d7651e..fe84f8c 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_contains_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=tel-Manzke+syndro&match=contains&hpo_terms=true\").await?" --- version: @@ -115,4 +115,3 @@ result: name: Hyperphalangy of the 2nd finger - term_id: "HP:0045074" name: Thin eyebrow - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap index e461112..9d4f627 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=Catel-Manzke+syndrome\").await?" --- version: @@ -14,4 +14,3 @@ query: result: - omim_id: "OMIM:616145" name: Catel-Manzke syndrome - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap index 006520f..bffb04c 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_exact_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=Catel-Manzke+syndrome&hpo_terms=true\").await?" --- version: @@ -115,4 +115,3 @@ result: name: Hyperphalangy of the 2nd finger - term_id: "HP:0045074" name: Thin eyebrow - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap index 244739e..281fdd5 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=Catel-Manzke+syndro&match=prefix\").await?" --- version: @@ -14,4 +14,3 @@ query: result: - omim_id: "OMIM:616145" name: Catel-Manzke syndrome - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap index 9684c28..3341d7c 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_prefix_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=Catel-Manzke+syndro&match=prefix&hpo_terms=true\").await?" --- version: @@ -115,4 +115,3 @@ result: name: Hyperphalangy of the 2nd finger - term_id: "HP:0045074" name: Thin eyebrow - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap similarity index 86% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap index 44abfda..0410ae3 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=tel-Manzke+syndrome&match=suffix\").await?" --- version: @@ -14,4 +14,3 @@ query: result: - omim_id: "OMIM:616145" name: Catel-Manzke syndrome - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap index 37727be..e9b2bcb 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_name_suffix_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?name=tel-Manzke+syndrome&match=suffix&hpo_terms=true\").await?" --- version: @@ -115,4 +115,3 @@ result: name: Hyperphalangy of the 2nd finger - term_id: "HP:0045074" name: Thin eyebrow - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap similarity index 85% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap index bb27f40..07efe5d 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_no_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?omim_id=616145\").await?" --- version: @@ -14,4 +14,3 @@ query: result: - omim_id: "OMIM:616145" name: Catel-Manzke syndrome - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap similarity index 98% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap rename to src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap index 2f7cc4a..361cfd1 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_omims__test__hpo_omims_omim_id_exact_with_hpo_terms.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_omims.rs +source: src/server/run/hpo_omims.rs expression: "&run_query(\"/hpo/omims?omim_id=616145&hpo_terms=true\").await?" --- version: @@ -115,4 +115,3 @@ result: name: Hyperphalangy of the 2nd finger - term_id: "HP:0045074" name: Thin eyebrow - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_no_genes.snap b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_no_genes.snap similarity index 94% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_no_genes.snap rename to src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_no_genes.snap index 051839c..e27673f 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_no_genes.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_no_genes.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_terms.rs +source: src/server/run/hpo_terms.rs expression: "&run_query(\"/hpo/terms?name=Inguinal+hernia\").await?" --- version: @@ -30,4 +30,3 @@ result: - "MSH:D006550" - "SNOMEDCT_US:50063009" - "UMLS:C0019288" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_with_genes.snap b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_with_genes.snap similarity index 99% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_with_genes.snap rename to src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_with_genes.snap index 9b2eea0..85aba17 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_exact_with_genes.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_exact_with_genes.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_terms.rs +source: src/server/run/hpo_terms.rs expression: "&run_query(\"/hpo/terms?name=Inguinal+hernia&genes=true\").await?" --- version: @@ -962,4 +962,3 @@ result: - ncbi_gene_id: 129563 gene_symbol: DIS3L2 hgnc_id: "HGNC:28648" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap similarity index 94% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap rename to src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap index 0c8095b..737d89e 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_no_genes.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_terms.rs +source: src/server/run/hpo_terms.rs expression: "&run_query(\"/hpo/terms?name=Inguinal+hern\").await?" --- version: @@ -30,4 +30,3 @@ result: - "MSH:D006550" - "SNOMEDCT_US:50063009" - "UMLS:C0019288" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap similarity index 99% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap rename to src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap index e2067cf..12d5f8a 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_name_fuzzy_with_genes.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_terms.rs +source: src/server/run/hpo_terms.rs expression: "&run_query(\"/hpo/terms?name=Inguinal+hern&genes=true\").await?" --- version: @@ -962,4 +962,3 @@ result: - ncbi_gene_id: 129563 gene_symbol: DIS3L2 hgnc_id: "HGNC:28648" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap similarity index 91% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap rename to src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap index eb65f00..4d3d479 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_no_genes.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_terms.rs +source: src/server/run/hpo_terms.rs expression: "&run_query(\"/hpo/terms?term_id=HP:0000023\").await?" --- version: @@ -20,4 +20,3 @@ result: - "MSH:D006552" - "SNOMEDCT_US:396232000" - "UMLS:C0019294" - diff --git a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap similarity index 99% rename from src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap rename to src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap index 5340e3e..5548ee4 100644 --- a/src/server/actix_server/snapshots/viguno__server__actix_server__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap +++ b/src/server/run/snapshots/viguno__server__run__hpo_terms__test__hpo_terms_term_id_exact_with_genes.snap @@ -1,5 +1,5 @@ --- -source: src/server/actix_server/hpo_terms.rs +source: src/server/run/hpo_terms.rs expression: "&run_query(\"/hpo/terms?term_id=HP:0000023&genes=true\").await?" --- version: @@ -897,4 +897,3 @@ result: - ncbi_gene_id: 653361 gene_symbol: NCF1 hgnc_id: "HGNC:7660" - diff --git a/src/server/schema.rs b/src/server/schema.rs index e69de29..7707cc5 100644 --- a/src/server/schema.rs +++ b/src/server/schema.rs @@ -0,0 +1,51 @@ +//! Dump schema of the REST API server. + +use std::{ + fs::File, + io::{self, Write}, +}; + +use utoipa::OpenApi as _; + +use crate::server::run::ApiDoc; + +/// Command line arguments for `server schema` sub command. +#[derive(clap::Parser, Debug)] +#[command(author, version, about = "Dump REST API schema", long_about = None)] +pub struct Args { + /// Path to the output file. Use stdout if missing. + #[arg(long)] + pub output_file: Option, +} + +impl Args { + /// Get writeable output file or stdout. + fn get_output(&self) -> Result, io::Error> { + match self.output_file { + Some(ref path) => File::create(path).map(|f| Box::new(f) as Box), + None => Ok(Box::new(io::stdout())), + } + } +} + +/// Main entry point for `run-server` sub command. +/// +/// # Errors +/// +/// In the case that there is an error running the server. +pub fn run(args_common: &crate::common::Args, args: &Args) -> Result<(), anyhow::Error> { + tracing::info!("args_common = {:?}", &args_common); + tracing::info!("args = {:?}", &args); + + let schema_yaml = ApiDoc::openapi() + .to_yaml() + .map_err(|e| anyhow::anyhow!("Failed to convert OpenAPI to YAML: {}", e))?; + let mut output = args + .get_output() + .map_err(|e| anyhow::anyhow!("Failed to open output file: {}", e))?; + write!(output, "{}", &schema_yaml) + .map_err(|e| anyhow::anyhow!("Failed to write output: {}", e))?; + + tracing::info!("All done. Have a nice day!"); + Ok(()) +}