diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9638907..7b65fee 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,7 +22,43 @@ jobs: - name: Instantiate test environment run: julia --project=test -e 'using Pkg; Pkg.instantiate()' - name: Check formatting - run: julia --project=test -e 'using Runic; Runic.main(["--check", "src/", "test/", "docs/"])' + run: julia --project=test -e 'using Runic; Runic.main(["--check", "src/", "test/", "docs/", "benchmarking/"])' + + benchmark: + name: Benchmark + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v1 + with: + version: '1' + - uses: julia-actions/cache@v1 + - name: Configure benchmark environment + run: | + julia --project=benchmarking -e ' + using Pkg + Pkg.develop(PackageSpec(path=pwd())) + Pkg.instantiate()' + - name: Run request benchmarks + run: | + julia --project=benchmarking benchmarking/run_benchmarks.jl \ + --only julia --output benchmarking/benchmark_ci.csv + julia --project=benchmarking benchmarking/write_ci_results.jl \ + benchmarking/benchmark_ci.csv benchmarking/benchmark_ci.json + - name: Record benchmark results + continue-on-error: true + uses: benchmark-action/github-action-benchmark@v1 + with: + name: KEGGAPI request time + tool: customSmallerIsBetter + output-file-path: benchmarking/benchmark_ci.json + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + alert-threshold: '200%' + fail-on-alert: true + summary-always: true test: name: Test (${{ matrix.version }}; ${{ matrix.os }} ${{ matrix.arch }}) diff --git a/.gitignore b/.gitignore index ad48938..6e4b024 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /docs/Manifest.toml /docs/build/ /benchmarking/Manifest.toml +/benchmarking/benchmark_ci.* *.png -!benchmark_compare.png +!benchmarking/benchmark.png benchmarking/.Rhistory diff --git a/benchmarking/Project.toml b/benchmarking/Project.toml index 4546546..f2bbc0b 100644 --- a/benchmarking/Project.toml +++ b/benchmarking/Project.toml @@ -1,9 +1,4 @@ [deps] -AlgebraOfGraphics = "cbdf2221-f076-402e-a563-3d30da359d67" -CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" -Chain = "8be319e6-bccf-4806-a6f7-6fae938471bc" -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" KEGGAPI = "e8256861-d17c-4800-bf17-838497555b93" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" diff --git a/benchmarking/README.md b/benchmarking/README.md index 8aadc87..8cdd0af 100644 --- a/benchmarking/README.md +++ b/benchmarking/README.md @@ -1,32 +1,21 @@ # Benchmarking This benchmark compares `KEGGAPI.jl`, `KEGGREST` for R, `Bio.KEGG.REST` for -Python, and raw `curl` across these KEGG operations: - -| Operation | Query | Covered by | -|:----------|:-------------------------------|:----------------------| -| `Info` | `info/kegg` | all | -| `List` | `list/pathway` | all | -| `Find` | `find/compound/glucose` | all | -| `Get` | `get/hsa:10458` | all | -| `GetSeq` | `get/hsa:10458/aaseq` | all | -| `Conv` | `conv/ncbi-geneid/eco:b0002` | all | -| `Link` | `link/pathway/hsa:10458` | all | -| `Ddi` | `ddi/D00564` | KEGGAPI.jl, curl only | - -KEGGREST and Bio.KEGG.REST do not wrap `ddi`, so the figure omits their bars for -that operation. The `conv` case uses `ncbi-geneid` rather than -`ncbi-proteinid` because Bio.KEGG.REST only recognises the legacy outside-database -names (`ncbi-gi | ncbi-geneid | uniprot`) and rejects the newer ones. - -`KEGGAPI.jl`'s chunked `kegg_get` waits between requests to respect KEGG's rate -limit. The Julia runner passes `request_delay = 0.0` because it already spaces -calls and must not time the same delay twice. - -Each interface runs every operation in one process, which excludes interpreter -startup from the measurements. The runner discards a warm-up call before the -measured replicates and spaces calls by `--pause` -seconds (default 0.4 s) to stay under KEGG's limit of 3 requests per second. +Python, and raw `curl`. [`cases.tsv`](cases.tsv) defines 25 distinct requests for +each operation: `info`, `list`, `find`, `get`, amino-acid `get`, `conv`, `link`, +and `ddi`. Single-entry gene and drug requests keep response sizes bounded, +while the `info` and `find` cases span valid databases and search terms. +KEGGREST and Bio.KEGG.REST do not wrap `ddi`, so their distributions omit that +operation. + +Each interface runs in one process, which excludes interpreter startup. One +warm-up call per operation precedes the measurements. Calls are spaced by +`--pause` seconds, 0.4 by default, to stay below KEGG's limit of three requests +per second. The CSV retains each request timing, and the plot shows its +distribution instead of reducing all requests to one value. + +`KEGGAPI.jl`'s chunked `kegg_get` can wait between requests. The Julia runner +passes `request_delay = 0.0` because the runner already spaces calls. ## Running @@ -36,13 +25,13 @@ One-time setup of the isolated benchmarking environment: julia --project=benchmarking -e 'using Pkg; Pkg.develop(PackageSpec(path=".")); Pkg.instantiate()' ``` -Run the benchmarks (writes `benchmark_compare.csv`): +Run the benchmarks, which writes `benchmark_compare.csv`: ```bash -julia --project=benchmarking benchmarking/run_benchmarks.jl --nreps 15 +julia --project=benchmarking benchmarking/run_benchmarks.jl ``` -Regenerate the figure used in the main README (writes `benchmark_compare.png`): +Regenerate the SVG used in the main README and its PNG counterpart: ```bash julia --project=benchmarking benchmarking/plot_benchmarks.jl @@ -100,26 +89,33 @@ Set `JULIA`, `RSCRIPT`, or `PYTHON` to select an interpreter. For example, use ```bash PYTHON=/tmp/kegg_bench_venv/bin/python \ - julia --project=benchmarking benchmarking/run_benchmarks.jl --nreps 15 + julia --project=benchmarking benchmarking/run_benchmarks.jl ``` +Use `--only julia,curl` to select interfaces. `--nreps N` repeats all 25 cases +for each selected operation. + ## Layout | Path | Purpose | |:-------------------------|:---------------------------------------------------| -| `run_benchmarks.jl` | Orchestrator: runs each interface, writes the CSV | -| `plot_benchmarks.jl` | Renders the CSV to `benchmark_compare.png` | +| `cases.tsv` | The 25 requests for each operation | +| `run_benchmarks.jl` | Runs each interface and writes raw timings | +| `plot_benchmarks.jl` | Plots the request-time distributions | +| `write_ci_results.jl` | Converts Julia timings to CI benchmark JSON | | `runners/bench_julia.jl` | KEGGAPI.jl timings | | `runners/bench_r.R` | KEGGREST timings | | `runners/bench_python.py`| Bio.KEGG.REST timings | | `runners/bench_curl.sh` | Raw REST timings via `curl -w %{time_total}` | -Each runner prints one `Function,Language,seconds` row per replicate. Run an +Each runner prints one `Function,Request,Language,Seconds` row per call. Run an individual runner with: ```bash -julia --project=benchmarking benchmarking/runners/bench_julia.jl 5 0.4 +julia --project=benchmarking benchmarking/runners/bench_julia.jl 1 0.4 ``` Network round-trip time to `rest.kegg.jp` dominates these results. Compare interfaces within one run because location and server load vary between runs. +CI records the median Julia time for each operation and warns, without failing +the job, when it exceeds the previous value by the configured threshold. diff --git a/benchmarking/benchmark.png b/benchmarking/benchmark.png new file mode 100644 index 0000000..a5e04b0 Binary files /dev/null and b/benchmarking/benchmark.png differ diff --git a/benchmarking/benchmark.svg b/benchmarking/benchmark.svg index 865ce74..5201721 100644 --- a/benchmarking/benchmark.svg +++ b/benchmarking/benchmark.svg @@ -1,598 +1,504 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/benchmarking/benchmark_compare.csv b/benchmarking/benchmark_compare.csv index 888c8a9..fe1f03f 100644 --- a/benchmarking/benchmark_compare.csv +++ b/benchmarking/benchmark_compare.csv @@ -1,33 +1,751 @@ -Function,Language,Median -info,KEGGAPI.jl,0.307882604 -info,KEGGREST (R),0.34338712692260753 -info,Bio.KEGG.REST (Python),1.167023624991998 -info,curl,1.172729 -list,KEGGAPI.jl,0.3293254165 -list,KEGGREST (R),0.347944498062134 -list,Bio.KEGG.REST (Python),1.7430932079441845 -list,curl,1.6577104999999999 -find,KEGGAPI.jl,0.7023177085 -find,KEGGREST (R),0.7486366033554075 -find,Bio.KEGG.REST (Python),1.8074901875806972 -find,curl,1.5090075 -get,KEGGAPI.jl,0.273175521 -get,KEGGREST (R),0.341122031211853 -get,Bio.KEGG.REST (Python),1.111077479668893 -get,curl,1.125364 -getseq,KEGGAPI.jl,0.2717634375 -getseq,KEGGREST (R),0.29120397567749046 -getseq,Bio.KEGG.REST (Python),1.137285729055293 -getseq,curl,1.1196380000000001 -conv,KEGGAPI.jl,0.309721292 -conv,KEGGREST (R),0.3259974718093875 -conv,Bio.KEGG.REST (Python),1.1793734789825976 -conv,curl,1.1173565 -link,KEGGAPI.jl,0.31500602099999997 -link,KEGGREST (R),0.331033945083618 -link,Bio.KEGG.REST (Python),1.1386673335218802 -link,curl,1.1256504999999999 -ddi,KEGGAPI.jl,1.0907793125 -ddi,KEGGREST (R), -ddi,Bio.KEGG.REST (Python), -ddi,curl,3.0146245 +Function,Request,Language,Seconds +info,info/kegg,KEGGAPI.jl,0.3077775 +info,info/pathway,KEGGAPI.jl,0.96303975 +info,info/brite,KEGGAPI.jl,0.935796208 +info,info/module,KEGGAPI.jl,0.922787416 +info,info/ko,KEGGAPI.jl,0.963228875 +info,info/genome,KEGGAPI.jl,0.99582475 +info,info/genes,KEGGAPI.jl,0.315099542 +info,info/ligand,KEGGAPI.jl,0.62070375 +info,info/compound,KEGGAPI.jl,0.621208875 +info,info/glycan,KEGGAPI.jl,0.543819458 +info,info/reaction,KEGGAPI.jl,0.53362475 +info,info/rclass,KEGGAPI.jl,0.583050083 +info,info/enzyme,KEGGAPI.jl,0.826399 +info,info/network,KEGGAPI.jl,0.509424167 +info,info/variant,KEGGAPI.jl,0.525780708 +info,info/disease,KEGGAPI.jl,0.547429292 +info,info/drug,KEGGAPI.jl,0.597524375 +info,info/dgroup,KEGGAPI.jl,0.498197167 +info,info/cel,KEGGAPI.jl,0.642881459 +info,info/hsa,KEGGAPI.jl,0.621316833 +info,info/eco,KEGGAPI.jl,1.953235917 +info,info/sce,KEGGAPI.jl,0.621393541 +info,info/ath,KEGGAPI.jl,0.622009375 +info,info/dme,KEGGAPI.jl,0.564229834 +info,info/mmu,KEGGAPI.jl,0.577999833 +list,list/hsa:10458,KEGGAPI.jl,0.722918417 +list,list/hsa:7157,KEGGAPI.jl,0.72444375 +list,list/hsa:672,KEGGAPI.jl,0.724431084 +list,list/hsa:675,KEGGAPI.jl,0.679090042 +list,list/hsa:1956,KEGGAPI.jl,0.700290667 +list,list/hsa:2064,KEGGAPI.jl,0.7044555 +list,list/hsa:5290,KEGGAPI.jl,0.709485333 +list,list/hsa:7422,KEGGAPI.jl,0.67905875 +list,list/hsa:3845,KEGGAPI.jl,0.768545708 +list,list/hsa:5970,KEGGAPI.jl,0.702529334 +list,list/hsa:4609,KEGGAPI.jl,0.74600525 +list,list/hsa:2475,KEGGAPI.jl,0.723711666 +list,list/hsa:5728,KEGGAPI.jl,0.724450375 +list,list/hsa:1029,KEGGAPI.jl,0.724611958 +list,list/hsa:3553,KEGGAPI.jl,0.725165833 +list,list/hsa:7124,KEGGAPI.jl,0.688680167 +list,list/hsa:7040,KEGGAPI.jl,0.758334667 +list,list/hsa:3091,KEGGAPI.jl,0.690401709 +list,list/hsa:3105,KEGGAPI.jl,0.757856 +list,list/hsa:4318,KEGGAPI.jl,0.72437525 +list,list/hsa:5243,KEGGAPI.jl,0.726477792 +list,list/hsa:5468,KEGGAPI.jl,0.686373792 +list,list/hsa:2099,KEGGAPI.jl,0.68047525 +list,list/hsa:2100,KEGGAPI.jl,0.700951291 +list,list/hsa:348,KEGGAPI.jl,0.724667334 +find,find/compound/glucose,KEGGAPI.jl,0.6898745 +find,find/compound/fructose,KEGGAPI.jl,0.680679584 +find,find/compound/galactose,KEGGAPI.jl,0.665822 +find,find/compound/mannose,KEGGAPI.jl,0.6789645 +find,find/compound/sucrose,KEGGAPI.jl,0.702786625 +find,find/compound/lactose,KEGGAPI.jl,0.708557084 +find,find/compound/maltose,KEGGAPI.jl,0.739025084 +find,find/compound/ribose,KEGGAPI.jl,0.72092275 +find,find/compound/xylose,KEGGAPI.jl,0.725615125 +find,find/compound/pyruvate,KEGGAPI.jl,0.727562834 +find,find/compound/citrate,KEGGAPI.jl,0.719372833 +find,find/compound/acetate,KEGGAPI.jl,1.032336875 +find,find/compound/ethanol,KEGGAPI.jl,0.724714542 +find,find/compound/cholesterol,KEGGAPI.jl,0.673380958 +find,find/compound/adenine,KEGGAPI.jl,0.678385417 +find,find/compound/guanine,KEGGAPI.jl,0.717631542 +find,find/compound/cytosine,KEGGAPI.jl,0.714372208 +find,find/compound/thymine,KEGGAPI.jl,0.733448209 +find,find/compound/uracil,KEGGAPI.jl,0.726009083 +find,find/compound/glycine,KEGGAPI.jl,0.683401834 +find,find/compound/alanine,KEGGAPI.jl,0.682084583 +find,find/compound/valine,KEGGAPI.jl,0.700989792 +find,find/compound/leucine,KEGGAPI.jl,0.7233725 +find,find/compound/serine,KEGGAPI.jl,0.726117292 +find,find/compound/cysteine,KEGGAPI.jl,0.682259375 +get,get/hsa:10458,KEGGAPI.jl,0.356735375 +get,get/hsa:7157,KEGGAPI.jl,0.272564833 +get,get/hsa:672,KEGGAPI.jl,0.357257875 +get,get/hsa:675,KEGGAPI.jl,0.275365 +get,get/hsa:1956,KEGGAPI.jl,0.356997667 +get,get/hsa:2064,KEGGAPI.jl,0.273656709 +get,get/hsa:5290,KEGGAPI.jl,0.600749209 +get,get/hsa:7422,KEGGAPI.jl,0.270681458 +get,get/hsa:3845,KEGGAPI.jl,0.313876375 +get,get/hsa:5970,KEGGAPI.jl,0.316080959 +get,get/hsa:4609,KEGGAPI.jl,0.271843042 +get,get/hsa:2475,KEGGAPI.jl,0.354312083 +get,get/hsa:5728,KEGGAPI.jl,0.275390459 +get,get/hsa:1029,KEGGAPI.jl,0.297292333 +get,get/hsa:3553,KEGGAPI.jl,0.271996125 +get,get/hsa:7124,KEGGAPI.jl,0.309515083 +get,get/hsa:7040,KEGGAPI.jl,0.314916333 +get,get/hsa:3091,KEGGAPI.jl,0.273901292 +get,get/hsa:3105,KEGGAPI.jl,0.27249875 +get,get/hsa:4318,KEGGAPI.jl,0.272858583 +get,get/hsa:5243,KEGGAPI.jl,0.280674708 +get,get/hsa:5468,KEGGAPI.jl,0.276074083 +get,get/hsa:2099,KEGGAPI.jl,0.289789208 +get,get/hsa:2100,KEGGAPI.jl,0.330727833 +get,get/hsa:348,KEGGAPI.jl,0.284997042 +getseq,get/hsa:10458/aaseq,KEGGAPI.jl,0.346396375 +getseq,get/hsa:7157/aaseq,KEGGAPI.jl,0.3104015 +getseq,get/hsa:672/aaseq,KEGGAPI.jl,0.27192175 +getseq,get/hsa:675/aaseq,KEGGAPI.jl,0.275351208 +getseq,get/hsa:1956/aaseq,KEGGAPI.jl,0.270801584 +getseq,get/hsa:2064/aaseq,KEGGAPI.jl,0.338588959 +getseq,get/hsa:5290/aaseq,KEGGAPI.jl,0.315220958 +getseq,get/hsa:7422/aaseq,KEGGAPI.jl,0.312460166 +getseq,get/hsa:3845/aaseq,KEGGAPI.jl,0.314449084 +getseq,get/hsa:5970/aaseq,KEGGAPI.jl,0.268376417 +getseq,get/hsa:4609/aaseq,KEGGAPI.jl,0.269938625 +getseq,get/hsa:2475/aaseq,KEGGAPI.jl,0.299718583 +getseq,get/hsa:5728/aaseq,KEGGAPI.jl,0.31735925 +getseq,get/hsa:1029/aaseq,KEGGAPI.jl,0.315183208 +getseq,get/hsa:3553/aaseq,KEGGAPI.jl,0.312809 +getseq,get/hsa:7124/aaseq,KEGGAPI.jl,0.313729625 +getseq,get/hsa:7040/aaseq,KEGGAPI.jl,0.271941417 +getseq,get/hsa:3091/aaseq,KEGGAPI.jl,0.269240542 +getseq,get/hsa:3105/aaseq,KEGGAPI.jl,0.311101083 +getseq,get/hsa:4318/aaseq,KEGGAPI.jl,0.305006875 +getseq,get/hsa:5243/aaseq,KEGGAPI.jl,0.3142715 +getseq,get/hsa:5468/aaseq,KEGGAPI.jl,0.313958 +getseq,get/hsa:2099/aaseq,KEGGAPI.jl,0.314631583 +getseq,get/hsa:2100/aaseq,KEGGAPI.jl,0.314252333 +getseq,get/hsa:348/aaseq,KEGGAPI.jl,0.314387959 +conv,conv/ncbi-geneid/hsa:10458,KEGGAPI.jl,0.314524708 +conv,conv/ncbi-geneid/hsa:7157,KEGGAPI.jl,0.313243791 +conv,conv/ncbi-geneid/hsa:672,KEGGAPI.jl,0.317403667 +conv,conv/ncbi-geneid/hsa:675,KEGGAPI.jl,0.312777209 +conv,conv/ncbi-geneid/hsa:1956,KEGGAPI.jl,0.319520041 +conv,conv/ncbi-geneid/hsa:2064,KEGGAPI.jl,0.3136645 +conv,conv/ncbi-geneid/hsa:5290,KEGGAPI.jl,0.316226917 +conv,conv/ncbi-geneid/hsa:7422,KEGGAPI.jl,0.309582208 +conv,conv/ncbi-geneid/hsa:3845,KEGGAPI.jl,0.310918959 +conv,conv/ncbi-geneid/hsa:5970,KEGGAPI.jl,0.314732792 +conv,conv/ncbi-geneid/hsa:4609,KEGGAPI.jl,0.416112292 +conv,conv/ncbi-geneid/hsa:2475,KEGGAPI.jl,0.315479208 +conv,conv/ncbi-geneid/hsa:5728,KEGGAPI.jl,0.31318275 +conv,conv/ncbi-geneid/hsa:1029,KEGGAPI.jl,0.314787167 +conv,conv/ncbi-geneid/hsa:3553,KEGGAPI.jl,0.315413208 +conv,conv/ncbi-geneid/hsa:7124,KEGGAPI.jl,0.313842291 +conv,conv/ncbi-geneid/hsa:7040,KEGGAPI.jl,0.318847291 +conv,conv/ncbi-geneid/hsa:3091,KEGGAPI.jl,0.312884208 +conv,conv/ncbi-geneid/hsa:3105,KEGGAPI.jl,0.311124625 +conv,conv/ncbi-geneid/hsa:4318,KEGGAPI.jl,0.34654 +conv,conv/ncbi-geneid/hsa:5243,KEGGAPI.jl,0.310097791 +conv,conv/ncbi-geneid/hsa:5468,KEGGAPI.jl,0.311857125 +conv,conv/ncbi-geneid/hsa:2099,KEGGAPI.jl,0.310580625 +conv,conv/ncbi-geneid/hsa:2100,KEGGAPI.jl,0.393567667 +conv,conv/ncbi-geneid/hsa:348,KEGGAPI.jl,0.314307583 +link,link/pathway/hsa:10458,KEGGAPI.jl,0.3188535 +link,link/pathway/hsa:7157,KEGGAPI.jl,0.314266583 +link,link/pathway/hsa:672,KEGGAPI.jl,0.314931292 +link,link/pathway/hsa:675,KEGGAPI.jl,0.3186485 +link,link/pathway/hsa:1956,KEGGAPI.jl,0.311933458 +link,link/pathway/hsa:2064,KEGGAPI.jl,0.316663833 +link,link/pathway/hsa:5290,KEGGAPI.jl,0.318829542 +link,link/pathway/hsa:7422,KEGGAPI.jl,0.313101458 +link,link/pathway/hsa:3845,KEGGAPI.jl,0.312684458 +link,link/pathway/hsa:5970,KEGGAPI.jl,0.316117875 +link,link/pathway/hsa:4609,KEGGAPI.jl,0.312753792 +link,link/pathway/hsa:2475,KEGGAPI.jl,0.3192855 +link,link/pathway/hsa:5728,KEGGAPI.jl,0.312728208 +link,link/pathway/hsa:1029,KEGGAPI.jl,0.313635541 +link,link/pathway/hsa:3553,KEGGAPI.jl,0.315000667 +link,link/pathway/hsa:7124,KEGGAPI.jl,0.315748 +link,link/pathway/hsa:7040,KEGGAPI.jl,0.315760959 +link,link/pathway/hsa:3091,KEGGAPI.jl,0.321853291 +link,link/pathway/hsa:3105,KEGGAPI.jl,0.314124 +link,link/pathway/hsa:4318,KEGGAPI.jl,0.31995 +link,link/pathway/hsa:5243,KEGGAPI.jl,0.31542175 +link,link/pathway/hsa:5468,KEGGAPI.jl,0.314314083 +link,link/pathway/hsa:2099,KEGGAPI.jl,0.31315025 +link,link/pathway/hsa:2100,KEGGAPI.jl,0.313166583 +link,link/pathway/hsa:348,KEGGAPI.jl,0.313986042 +ddi,ddi/D00006,KEGGAPI.jl,0.761043791 +ddi,ddi/D00008,KEGGAPI.jl,0.821654166 +ddi,ddi/D00015,KEGGAPI.jl,0.871222875 +ddi,ddi/D00018,KEGGAPI.jl,0.826554334 +ddi,ddi/D00020,KEGGAPI.jl,0.827731459 +ddi,ddi/D00028,KEGGAPI.jl,0.764735291 +ddi,ddi/D00032,KEGGAPI.jl,0.785970375 +ddi,ddi/D00033,KEGGAPI.jl,0.825911 +ddi,ddi/D00043,KEGGAPI.jl,0.826639375 +ddi,ddi/D00045,KEGGAPI.jl,0.827301541 +ddi,ddi/D00049,KEGGAPI.jl,0.824407584 +ddi,ddi/D00052,KEGGAPI.jl,0.827566875 +ddi,ddi/D00058,KEGGAPI.jl,0.758327 +ddi,ddi/D00059,KEGGAPI.jl,0.79421825 +ddi,ddi/D00060,KEGGAPI.jl,0.8251195 +ddi,ddi/D00062,KEGGAPI.jl,0.76262425 +ddi,ddi/D00063,KEGGAPI.jl,0.791356167 +ddi,ddi/D00066,KEGGAPI.jl,0.824179708 +ddi,ddi/D00067,KEGGAPI.jl,0.768654417 +ddi,ddi/D00068,KEGGAPI.jl,0.78047 +ddi,ddi/D00069,KEGGAPI.jl,0.763107375 +ddi,ddi/D00070,KEGGAPI.jl,0.788219459 +ddi,ddi/D00073,KEGGAPI.jl,0.764393208 +ddi,ddi/D00074,KEGGAPI.jl,0.788815917 +ddi,ddi/D00075,KEGGAPI.jl,0.825214625 +info,info/kegg,KEGGREST (R),0.312999999999999 +info,info/pathway,KEGGREST (R),1.176 +info,info/brite,KEGGREST (R),2.334 +info,info/module,KEGGREST (R),0.795999999999999 +info,info/ko,KEGGREST (R),1.37 +info,info/genome,KEGGREST (R),1.377 +info,info/genes,KEGGREST (R),0.315999999999999 +info,info/ligand,KEGGREST (R),0.598999999999997 +info,info/compound,KEGGREST (R),0.553000000000001 +info,info/glycan,KEGGREST (R),0.579000000000001 +info,info/reaction,KEGGREST (R),0.524000000000001 +info,info/rclass,KEGGREST (R),0.533000000000001 +info,info/enzyme,KEGGREST (R),0.811 +info,info/network,KEGGREST (R),0.527000000000001 +info,info/variant,KEGGREST (R),0.593999999999998 +info,info/disease,KEGGREST (R),0.594999999999999 +info,info/drug,KEGGREST (R),0.583000000000002 +info,info/dgroup,KEGGREST (R),0.509 +info,info/cel,KEGGREST (R),0.570999999999998 +info,info/hsa,KEGGREST (R),0.583000000000002 +info,info/eco,KEGGREST (R),0.564999999999998 +info,info/sce,KEGGREST (R),0.567 +info,info/ath,KEGGREST (R),0.568000000000005 +info,info/dme,KEGGREST (R),0.633000000000003 +info,info/mmu,KEGGREST (R),0.561 +list,list/hsa:10458,KEGGREST (R),0.700000000000003 +list,list/hsa:7157,KEGGREST (R),0.693000000000005 +list,list/hsa:672,KEGGREST (R),0.692 +list,list/hsa:675,KEGGREST (R),0.706999999999994 +list,list/hsa:1956,KEGGREST (R),0.713999999999999 +list,list/hsa:2064,KEGGREST (R),0.724999999999994 +list,list/hsa:5290,KEGGREST (R),0.787999999999997 +list,list/hsa:7422,KEGGREST (R),0.716000000000001 +list,list/hsa:3845,KEGGREST (R),0.731999999999999 +list,list/hsa:5970,KEGGREST (R),0.720999999999997 +list,list/hsa:4609,KEGGREST (R),0.677 +list,list/hsa:2475,KEGGREST (R),0.667000000000002 +list,list/hsa:5728,KEGGREST (R),0.722000000000001 +list,list/hsa:1029,KEGGREST (R),0.725000000000001 +list,list/hsa:3553,KEGGREST (R),0.719999999999999 +list,list/hsa:7124,KEGGREST (R),0.722000000000001 +list,list/hsa:7040,KEGGREST (R),0.713000000000001 +list,list/hsa:3091,KEGGREST (R),0.737000000000002 +list,list/hsa:3105,KEGGREST (R),0.710999999999999 +list,list/hsa:4318,KEGGREST (R),0.736000000000004 +list,list/hsa:5243,KEGGREST (R),0.722000000000001 +list,list/hsa:5468,KEGGREST (R),0.722999999999999 +list,list/hsa:2099,KEGGREST (R),0.676000000000002 +list,list/hsa:2100,KEGGREST (R),0.655000000000001 +list,list/hsa:348,KEGGREST (R),0.701999999999998 +find,find/compound/glucose,KEGGREST (R),0.709000000000003 +find,find/compound/fructose,KEGGREST (R),0.769000000000005 +find,find/compound/galactose,KEGGREST (R),0.722000000000008 +find,find/compound/mannose,KEGGREST (R),0.722000000000008 +find,find/compound/sucrose,KEGGREST (R),0.721999999999994 +find,find/compound/lactose,KEGGREST (R),0.688999999999993 +find,find/compound/maltose,KEGGREST (R),0.762 +find,find/compound/ribose,KEGGREST (R),0.652000000000001 +find,find/compound/xylose,KEGGREST (R),0.701999999999998 +find,find/compound/pyruvate,KEGGREST (R),0.709000000000003 +find,find/compound/citrate,KEGGREST (R),0.721999999999994 +find,find/compound/acetate,KEGGREST (R),0.703999999999994 +find,find/compound/ethanol,KEGGREST (R),0.694000000000003 +find,find/compound/cholesterol,KEGGREST (R),0.677999999999997 +find,find/compound/adenine,KEGGREST (R),0.712000000000003 +find,find/compound/guanine,KEGGREST (R),0.670000000000002 +find,find/compound/cytosine,KEGGREST (R),0.661999999999992 +find,find/compound/thymine,KEGGREST (R),0.728999999999999 +find,find/compound/uracil,KEGGREST (R),0.671999999999997 +find,find/compound/glycine,KEGGREST (R),0.777000000000001 +find,find/compound/alanine,KEGGREST (R),0.697000000000003 +find,find/compound/valine,KEGGREST (R),0.691000000000003 +find,find/compound/leucine,KEGGREST (R),0.674999999999997 +find,find/compound/serine,KEGGREST (R),0.718000000000004 +find,find/compound/cysteine,KEGGREST (R),0.73299999999999 +get,get/hsa:10458,KEGGREST (R),0.344999999999999 +get,get/hsa:7157,KEGGREST (R),0.328000000000003 +get,get/hsa:672,KEGGREST (R),0.367999999999995 +get,get/hsa:675,KEGGREST (R),0.356999999999999 +get,get/hsa:1956,KEGGREST (R),0.361000000000004 +get,get/hsa:2064,KEGGREST (R),0.343000000000004 +get,get/hsa:5290,KEGGREST (R),0.408999999999992 +get,get/hsa:7422,KEGGREST (R),0.338000000000008 +get,get/hsa:3845,KEGGREST (R),0.379999999999995 +get,get/hsa:5970,KEGGREST (R),0.356999999999999 +get,get/hsa:4609,KEGGREST (R),0.341000000000008 +get,get/hsa:2475,KEGGREST (R),0.351000000000013 +get,get/hsa:5728,KEGGREST (R),0.317000000000007 +get,get/hsa:1029,KEGGREST (R),0.332000000000008 +get,get/hsa:3553,KEGGREST (R),0.349000000000004 +get,get/hsa:7124,KEGGREST (R),0.411999999999992 +get,get/hsa:7040,KEGGREST (R),0.34899999999999 +get,get/hsa:3091,KEGGREST (R),0.325000000000003 +get,get/hsa:3105,KEGGREST (R),0.334000000000003 +get,get/hsa:4318,KEGGREST (R),0.318000000000012 +get,get/hsa:5243,KEGGREST (R),0.298000000000002 +get,get/hsa:5468,KEGGREST (R),0.317000000000007 +get,get/hsa:2099,KEGGREST (R),0.347999999999999 +get,get/hsa:2100,KEGGREST (R),0.334000000000003 +get,get/hsa:348,KEGGREST (R),0.304000000000002 +getseq,get/hsa:10458/aaseq,KEGGREST (R),0.277000000000001 +getseq,get/hsa:7157/aaseq,KEGGREST (R),0.287000000000006 +getseq,get/hsa:672/aaseq,KEGGREST (R),0.283999999999992 +getseq,get/hsa:675/aaseq,KEGGREST (R),0.277000000000001 +getseq,get/hsa:1956/aaseq,KEGGREST (R),0.278000000000006 +getseq,get/hsa:2064/aaseq,KEGGREST (R),0.280000000000001 +getseq,get/hsa:5290/aaseq,KEGGREST (R),0.284000000000006 +getseq,get/hsa:7422/aaseq,KEGGREST (R),0.283999999999992 +getseq,get/hsa:3845/aaseq,KEGGREST (R),0.284000000000006 +getseq,get/hsa:5970/aaseq,KEGGREST (R),0.283000000000001 +getseq,get/hsa:4609/aaseq,KEGGREST (R),0.319000000000003 +getseq,get/hsa:2475/aaseq,KEGGREST (R),0.281000000000006 +getseq,get/hsa:5728/aaseq,KEGGREST (R),0.283000000000001 +getseq,get/hsa:1029/aaseq,KEGGREST (R),0.285000000000011 +getseq,get/hsa:3553/aaseq,KEGGREST (R),0.280000000000001 +getseq,get/hsa:7124/aaseq,KEGGREST (R),0.274000000000001 +getseq,get/hsa:7040/aaseq,KEGGREST (R),0.286000000000001 +getseq,get/hsa:3091/aaseq,KEGGREST (R),0.277000000000001 +getseq,get/hsa:3105/aaseq,KEGGREST (R),0.272999999999996 +getseq,get/hsa:4318/aaseq,KEGGREST (R),0.282000000000011 +getseq,get/hsa:5243/aaseq,KEGGREST (R),0.284999999999997 +getseq,get/hsa:5468/aaseq,KEGGREST (R),0.275999999999996 +getseq,get/hsa:2099/aaseq,KEGGREST (R),0.284999999999997 +getseq,get/hsa:2100/aaseq,KEGGREST (R),0.296000000000006 +getseq,get/hsa:348/aaseq,KEGGREST (R),0.283999999999992 +conv,conv/ncbi-geneid/hsa:10458,KEGGREST (R),0.334000000000003 +conv,conv/ncbi-geneid/hsa:7157,KEGGREST (R),0.318999999999988 +conv,conv/ncbi-geneid/hsa:672,KEGGREST (R),0.317000000000007 +conv,conv/ncbi-geneid/hsa:675,KEGGREST (R),0.319999999999993 +conv,conv/ncbi-geneid/hsa:1956,KEGGREST (R),0.326999999999998 +conv,conv/ncbi-geneid/hsa:2064,KEGGREST (R),0.316000000000003 +conv,conv/ncbi-geneid/hsa:5290,KEGGREST (R),0.361000000000018 +conv,conv/ncbi-geneid/hsa:7422,KEGGREST (R),0.325999999999993 +conv,conv/ncbi-geneid/hsa:3845,KEGGREST (R),0.320999999999998 +conv,conv/ncbi-geneid/hsa:5970,KEGGREST (R),0.323999999999984 +conv,conv/ncbi-geneid/hsa:4609,KEGGREST (R),0.319999999999993 +conv,conv/ncbi-geneid/hsa:2475,KEGGREST (R),0.320000000000022 +conv,conv/ncbi-geneid/hsa:5728,KEGGREST (R),0.316000000000003 +conv,conv/ncbi-geneid/hsa:1029,KEGGREST (R),0.317000000000007 +conv,conv/ncbi-geneid/hsa:3553,KEGGREST (R),0.323000000000008 +conv,conv/ncbi-geneid/hsa:7124,KEGGREST (R),0.37299999999999 +conv,conv/ncbi-geneid/hsa:7040,KEGGREST (R),0.318000000000012 +conv,conv/ncbi-geneid/hsa:3091,KEGGREST (R),0.322000000000003 +conv,conv/ncbi-geneid/hsa:3105,KEGGREST (R),0.310000000000002 +conv,conv/ncbi-geneid/hsa:4318,KEGGREST (R),0.317000000000007 +conv,conv/ncbi-geneid/hsa:5243,KEGGREST (R),0.370999999999981 +conv,conv/ncbi-geneid/hsa:5468,KEGGREST (R),0.332999999999998 +conv,conv/ncbi-geneid/hsa:2099,KEGGREST (R),0.317999999999984 +conv,conv/ncbi-geneid/hsa:2100,KEGGREST (R),0.313999999999993 +conv,conv/ncbi-geneid/hsa:348,KEGGREST (R),0.317999999999984 +link,link/pathway/hsa:10458,KEGGREST (R),0.326999999999998 +link,link/pathway/hsa:7157,KEGGREST (R),0.323999999999984 +link,link/pathway/hsa:672,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:675,KEGGREST (R),0.321000000000026 +link,link/pathway/hsa:1956,KEGGREST (R),0.325999999999993 +link,link/pathway/hsa:2064,KEGGREST (R),0.323999999999984 +link,link/pathway/hsa:5290,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:7422,KEGGREST (R),0.321999999999974 +link,link/pathway/hsa:3845,KEGGREST (R),0.362000000000023 +link,link/pathway/hsa:5970,KEGGREST (R),0.319000000000017 +link,link/pathway/hsa:4609,KEGGREST (R),0.358000000000004 +link,link/pathway/hsa:2475,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:5728,KEGGREST (R),0.323000000000008 +link,link/pathway/hsa:1029,KEGGREST (R),0.319999999999993 +link,link/pathway/hsa:3553,KEGGREST (R),0.319999999999993 +link,link/pathway/hsa:7124,KEGGREST (R),0.317000000000007 +link,link/pathway/hsa:7040,KEGGREST (R),0.328000000000003 +link,link/pathway/hsa:3091,KEGGREST (R),0.317999999999984 +link,link/pathway/hsa:3105,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:4318,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:5243,KEGGREST (R),0.320999999999998 +link,link/pathway/hsa:5468,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:2099,KEGGREST (R),0.322000000000003 +link,link/pathway/hsa:2100,KEGGREST (R),0.319999999999993 +link,link/pathway/hsa:348,KEGGREST (R),0.321999999999974 +info,info/kegg,Bio.KEGG.REST (Python),1.1378032910000009 +info,info/pathway,Bio.KEGG.REST (Python),2.259181583 +info,info/brite,Bio.KEGG.REST (Python),2.052842709 +info,info/module,Bio.KEGG.REST (Python),2.6720954999999975 +info,info/ko,Bio.KEGG.REST (Python),2.0495354999999975 +info,info/genome,Bio.KEGG.REST (Python),2.668302875000002 +info,info/genes,Bio.KEGG.REST (Python),1.5442346250000014 +info,info/ligand,Bio.KEGG.REST (Python),1.8475924170000013 +info,info/compound,Bio.KEGG.REST (Python),1.7816276659999986 +info,info/glycan,Bio.KEGG.REST (Python),1.7350019169999982 +info,info/reaction,Bio.KEGG.REST (Python),1.8257569590000031 +info,info/rclass,Bio.KEGG.REST (Python),2.772457250000002 +info,info/enzyme,Bio.KEGG.REST (Python),2.105032792000003 +info,info/network,Bio.KEGG.REST (Python),1.5964059169999985 +info,info/variant,Bio.KEGG.REST (Python),1.537703124999993 +info,info/disease,Bio.KEGG.REST (Python),1.5240346659999986 +info,info/drug,Bio.KEGG.REST (Python),1.6628786249999976 +info,info/dgroup,Bio.KEGG.REST (Python),1.5764427080000019 +info,info/cel,Bio.KEGG.REST (Python),1.6372939580000008 +info,info/hsa,Bio.KEGG.REST (Python),1.7642906669999974 +info,info/eco,Bio.KEGG.REST (Python),1.634666666000001 +info,info/sce,Bio.KEGG.REST (Python),1.7353652919999973 +info,info/ath,Bio.KEGG.REST (Python),1.6279540830000059 +info,info/dme,Bio.KEGG.REST (Python),1.641668249999995 +info,info/mmu,Bio.KEGG.REST (Python),1.6841685840000054 +list,list/hsa:10458,Bio.KEGG.REST (Python),1.9267421659999968 +list,list/hsa:7157,Bio.KEGG.REST (Python),1.936393707999997 +list,list/hsa:672,Bio.KEGG.REST (Python),1.8476595420000024 +list,list/hsa:675,Bio.KEGG.REST (Python),1.7531275829999942 +list,list/hsa:1956,Bio.KEGG.REST (Python),1.8420920829999972 +list,list/hsa:2064,Bio.KEGG.REST (Python),1.9484575419999999 +list,list/hsa:5290,Bio.KEGG.REST (Python),1.9512792919999953 +list,list/hsa:7422,Bio.KEGG.REST (Python),1.8207060830000046 +list,list/hsa:3845,Bio.KEGG.REST (Python),1.8234489580000002 +list,list/hsa:5970,Bio.KEGG.REST (Python),1.700368791999992 +list,list/hsa:4609,Bio.KEGG.REST (Python),1.7480958329999936 +list,list/hsa:2475,Bio.KEGG.REST (Python),1.850909915999992 +list,list/hsa:5728,Bio.KEGG.REST (Python),1.951909624999999 +list,list/hsa:1029,Bio.KEGG.REST (Python),1.8555264999999963 +list,list/hsa:3553,Bio.KEGG.REST (Python),1.9439987909999985 +list,list/hsa:7124,Bio.KEGG.REST (Python),1.7259076659999977 +list,list/hsa:7040,Bio.KEGG.REST (Python),1.8532386669999994 +list,list/hsa:3091,Bio.KEGG.REST (Python),1.8632421249999993 +list,list/hsa:3105,Bio.KEGG.REST (Python),1.965623249999993 +list,list/hsa:4318,Bio.KEGG.REST (Python),1.9397121660000067 +list,list/hsa:5243,Bio.KEGG.REST (Python),1.8659156249999995 +list,list/hsa:5468,Bio.KEGG.REST (Python),1.92992979200001 +list,list/hsa:2099,Bio.KEGG.REST (Python),1.851579166999997 +list,list/hsa:2100,Bio.KEGG.REST (Python),2.0641882909999936 +list,list/hsa:348,Bio.KEGG.REST (Python),2.0410075000000063 +find,find/compound/glucose,Bio.KEGG.REST (Python),2.1579835419999824 +find,find/compound/fructose,Bio.KEGG.REST (Python),2.0562182500000006 +find,find/compound/galactose,Bio.KEGG.REST (Python),1.5416677080000056 +find,find/compound/mannose,Bio.KEGG.REST (Python),1.5113994169999785 +find,find/compound/sucrose,Bio.KEGG.REST (Python),1.7765986660000124 +find,find/compound/lactose,Bio.KEGG.REST (Python),1.6023077920000048 +find,find/compound/maltose,Bio.KEGG.REST (Python),1.6573601249999967 +find,find/compound/ribose,Bio.KEGG.REST (Python),1.5697123749999946 +find,find/compound/xylose,Bio.KEGG.REST (Python),1.5397108749999973 +find,find/compound/pyruvate,Bio.KEGG.REST (Python),1.621569041999976 +find,find/compound/citrate,Bio.KEGG.REST (Python),1.565646541999996 +find,find/compound/acetate,Bio.KEGG.REST (Python),2.136780625 +find,find/compound/ethanol,Bio.KEGG.REST (Python),1.971567666999988 +find,find/compound/cholesterol,Bio.KEGG.REST (Python),1.607041584000001 +find,find/compound/adenine,Bio.KEGG.REST (Python),1.6821092919999785 +find,find/compound/guanine,Bio.KEGG.REST (Python),1.7476097910000021 +find,find/compound/cytosine,Bio.KEGG.REST (Python),1.5476472919999935 +find,find/compound/thymine,Bio.KEGG.REST (Python),1.6381023749999883 +find,find/compound/uracil,Bio.KEGG.REST (Python),1.6441996249999988 +find,find/compound/glycine,Bio.KEGG.REST (Python),1.4687432089999959 +find,find/compound/alanine,Bio.KEGG.REST (Python),1.8178203749999966 +find,find/compound/valine,Bio.KEGG.REST (Python),1.5512657080000167 +find,find/compound/leucine,Bio.KEGG.REST (Python),1.5342897919999814 +find,find/compound/serine,Bio.KEGG.REST (Python),1.5143259580000006 +find,find/compound/cysteine,Bio.KEGG.REST (Python),1.536184416000026 +get,get/hsa:10458,Bio.KEGG.REST (Python),1.1664195419999999 +get,get/hsa:7157,Bio.KEGG.REST (Python),1.28126658299999 +get,get/hsa:672,Bio.KEGG.REST (Python),1.3383629169999836 +get,get/hsa:675,Bio.KEGG.REST (Python),1.4438358749999907 +get,get/hsa:1956,Bio.KEGG.REST (Python),1.4361752080000088 +get,get/hsa:2064,Bio.KEGG.REST (Python),1.296142792000012 +get,get/hsa:5290,Bio.KEGG.REST (Python),1.7445253340000022 +get,get/hsa:7422,Bio.KEGG.REST (Python),1.2338122499999997 +get,get/hsa:3845,Bio.KEGG.REST (Python),1.3781010419999973 +get,get/hsa:5970,Bio.KEGG.REST (Python),1.3974503330000232 +get,get/hsa:4609,Bio.KEGG.REST (Python),1.1026948749999974 +get,get/hsa:2475,Bio.KEGG.REST (Python),3.9425574170000175 +get,get/hsa:5728,Bio.KEGG.REST (Python),1.0311535000000163 +get,get/hsa:1029,Bio.KEGG.REST (Python),1.1159964160000015 +get,get/hsa:3553,Bio.KEGG.REST (Python),1.0675411670000017 +get,get/hsa:7124,Bio.KEGG.REST (Python),1.4035540419999961 +get,get/hsa:7040,Bio.KEGG.REST (Python),1.0284751670000105 +get,get/hsa:3091,Bio.KEGG.REST (Python),1.0417248329999893 +get,get/hsa:3105,Bio.KEGG.REST (Python),1.2218096670000023 +get,get/hsa:4318,Bio.KEGG.REST (Python),1.131122041999987 +get,get/hsa:5243,Bio.KEGG.REST (Python),1.145474207999996 +get,get/hsa:5468,Bio.KEGG.REST (Python),1.188769083000011 +get,get/hsa:2099,Bio.KEGG.REST (Python),1.0474247089999835 +get,get/hsa:2100,Bio.KEGG.REST (Python),1.0234109999999816 +get,get/hsa:348,Bio.KEGG.REST (Python),1.2552709159999722 +getseq,get/hsa:10458/aaseq,Bio.KEGG.REST (Python),1.4446801659999835 +getseq,get/hsa:7157/aaseq,Bio.KEGG.REST (Python),1.4872600829999953 +getseq,get/hsa:672/aaseq,Bio.KEGG.REST (Python),1.2895276249999768 +getseq,get/hsa:675/aaseq,Bio.KEGG.REST (Python),1.0388489580000169 +getseq,get/hsa:1956/aaseq,Bio.KEGG.REST (Python),1.0286315839999816 +getseq,get/hsa:2064/aaseq,Bio.KEGG.REST (Python),1.0227877500000204 +getseq,get/hsa:5290/aaseq,Bio.KEGG.REST (Python),1.0754189170000075 +getseq,get/hsa:7422/aaseq,Bio.KEGG.REST (Python),1.0341356670000152 +getseq,get/hsa:3845/aaseq,Bio.KEGG.REST (Python),1.0383827080000003 +getseq,get/hsa:5970/aaseq,Bio.KEGG.REST (Python),1.0346831249999866 +getseq,get/hsa:4609/aaseq,Bio.KEGG.REST (Python),1.10999187500002 +getseq,get/hsa:2475/aaseq,Bio.KEGG.REST (Python),1.0368355839999879 +getseq,get/hsa:5728/aaseq,Bio.KEGG.REST (Python),1.071545083000018 +getseq,get/hsa:1029/aaseq,Bio.KEGG.REST (Python),1.027099082999996 +getseq,get/hsa:3553/aaseq,Bio.KEGG.REST (Python),1.0338142919999882 +getseq,get/hsa:7124/aaseq,Bio.KEGG.REST (Python),1.1326496660000203 +getseq,get/hsa:7040/aaseq,Bio.KEGG.REST (Python),1.643319417000015 +getseq,get/hsa:3091/aaseq,Bio.KEGG.REST (Python),1.2871899580000274 +getseq,get/hsa:3105/aaseq,Bio.KEGG.REST (Python),1.3294830830000137 +getseq,get/hsa:4318/aaseq,Bio.KEGG.REST (Python),1.2646227079999903 +getseq,get/hsa:5243/aaseq,Bio.KEGG.REST (Python),1.2711517089999802 +getseq,get/hsa:5468/aaseq,Bio.KEGG.REST (Python),1.2695187499999747 +getseq,get/hsa:2099/aaseq,Bio.KEGG.REST (Python),1.2725486670000237 +getseq,get/hsa:2100/aaseq,Bio.KEGG.REST (Python),1.3201035839999804 +getseq,get/hsa:348/aaseq,Bio.KEGG.REST (Python),1.3887070000000108 +conv,conv/ncbi-geneid/hsa:10458,Bio.KEGG.REST (Python),1.3768580839999913 +conv,conv/ncbi-geneid/hsa:7157,Bio.KEGG.REST (Python),1.3060283749999826 +conv,conv/ncbi-geneid/hsa:672,Bio.KEGG.REST (Python),1.419429124999965 +conv,conv/ncbi-geneid/hsa:675,Bio.KEGG.REST (Python),1.383622833000004 +conv,conv/ncbi-geneid/hsa:1956,Bio.KEGG.REST (Python),1.3958427910000069 +conv,conv/ncbi-geneid/hsa:2064,Bio.KEGG.REST (Python),1.5400292080000213 +conv,conv/ncbi-geneid/hsa:5290,Bio.KEGG.REST (Python),4.613783832999957 +conv,conv/ncbi-geneid/hsa:7422,Bio.KEGG.REST (Python),1.3350833339999895 +conv,conv/ncbi-geneid/hsa:3845,Bio.KEGG.REST (Python),1.3941767910000067 +conv,conv/ncbi-geneid/hsa:5970,Bio.KEGG.REST (Python),1.3142880839999975 +conv,conv/ncbi-geneid/hsa:4609,Bio.KEGG.REST (Python),1.3238829589999455 +conv,conv/ncbi-geneid/hsa:2475,Bio.KEGG.REST (Python),1.3569682090000015 +conv,conv/ncbi-geneid/hsa:5728,Bio.KEGG.REST (Python),1.3128397079999559 +conv,conv/ncbi-geneid/hsa:1029,Bio.KEGG.REST (Python),1.3374027080000133 +conv,conv/ncbi-geneid/hsa:3553,Bio.KEGG.REST (Python),1.3272456669999997 +conv,conv/ncbi-geneid/hsa:7124,Bio.KEGG.REST (Python),1.3378876660000287 +conv,conv/ncbi-geneid/hsa:7040,Bio.KEGG.REST (Python),1.4399041670000088 +conv,conv/ncbi-geneid/hsa:3091,Bio.KEGG.REST (Python),1.3349166659999696 +conv,conv/ncbi-geneid/hsa:3105,Bio.KEGG.REST (Python),1.3862223749999885 +conv,conv/ncbi-geneid/hsa:4318,Bio.KEGG.REST (Python),1.2973417499999869 +conv,conv/ncbi-geneid/hsa:5243,Bio.KEGG.REST (Python),1.3109360419999803 +conv,conv/ncbi-geneid/hsa:5468,Bio.KEGG.REST (Python),1.3305285829999889 +conv,conv/ncbi-geneid/hsa:2099,Bio.KEGG.REST (Python),1.3210788339999908 +conv,conv/ncbi-geneid/hsa:2100,Bio.KEGG.REST (Python),1.3180549999999585 +conv,conv/ncbi-geneid/hsa:348,Bio.KEGG.REST (Python),1.4988959589999808 +link,link/pathway/hsa:10458,Bio.KEGG.REST (Python),1.3288588749999803 +link,link/pathway/hsa:7157,Bio.KEGG.REST (Python),1.3457278750000228 +link,link/pathway/hsa:672,Bio.KEGG.REST (Python),1.3125581249999527 +link,link/pathway/hsa:675,Bio.KEGG.REST (Python),1.3022608750000018 +link,link/pathway/hsa:1956,Bio.KEGG.REST (Python),1.3175900830000273 +link,link/pathway/hsa:2064,Bio.KEGG.REST (Python),1.3273051250000094 +link,link/pathway/hsa:5290,Bio.KEGG.REST (Python),1.3433206249999898 +link,link/pathway/hsa:7422,Bio.KEGG.REST (Python),1.322914959000002 +link,link/pathway/hsa:3845,Bio.KEGG.REST (Python),1.1359465829999635 +link,link/pathway/hsa:5970,Bio.KEGG.REST (Python),1.1417904580000027 +link,link/pathway/hsa:4609,Bio.KEGG.REST (Python),1.3258713749999629 +link,link/pathway/hsa:2475,Bio.KEGG.REST (Python),1.1387891669999703 +link,link/pathway/hsa:5728,Bio.KEGG.REST (Python),1.0752243750000048 +link,link/pathway/hsa:1029,Bio.KEGG.REST (Python),1.4973894589999759 +link,link/pathway/hsa:3553,Bio.KEGG.REST (Python),1.4009690409999962 +link,link/pathway/hsa:7124,Bio.KEGG.REST (Python),1.475534916000015 +link,link/pathway/hsa:7040,Bio.KEGG.REST (Python),1.3431667920000336 +link,link/pathway/hsa:3091,Bio.KEGG.REST (Python),1.3109967920000258 +link,link/pathway/hsa:3105,Bio.KEGG.REST (Python),1.4512476670000183 +link,link/pathway/hsa:4318,Bio.KEGG.REST (Python),1.4566849999999931 +link,link/pathway/hsa:5243,Bio.KEGG.REST (Python),1.424360374999992 +link,link/pathway/hsa:5468,Bio.KEGG.REST (Python),1.3410890829999857 +link,link/pathway/hsa:2099,Bio.KEGG.REST (Python),1.3325150830000325 +link,link/pathway/hsa:2100,Bio.KEGG.REST (Python),1.3314765419999617 +link,link/pathway/hsa:348,Bio.KEGG.REST (Python),1.3103822079999645 +info,info/kegg,curl,1.322392 +info,info/pathway,curl,1.897206 +info,info/brite,curl,1.796503 +info,info/module,curl,1.928149 +info,info/ko,curl,2.010719 +info,info/genome,curl,2.068994 +info,info/genes,curl,1.330207 +info,info/ligand,curl,1.637724 +info,info/compound,curl,1.57954 +info,info/glycan,curl,1.517033 +info,info/reaction,curl,1.496665 +info,info/rclass,curl,1.555349 +info,info/enzyme,curl,1.838024 +info,info/network,curl,1.565784 +info,info/variant,curl,1.610395 +info,info/disease,curl,1.524115 +info,info/drug,curl,1.558095 +info,info/dgroup,curl,1.495107 +info,info/cel,curl,1.559044 +info,info/hsa,curl,1.56265 +info,info/eco,curl,1.578661 +info,info/sce,curl,1.535565 +info,info/ath,curl,1.54854 +info,info/dme,curl,1.549765 +info,info/mmu,curl,1.546549 +list,list/hsa:10458,curl,1.754025 +list,list/hsa:7157,curl,1.659672 +list,list/hsa:672,curl,1.692028 +list,list/hsa:675,curl,1.667961 +list,list/hsa:1956,curl,1.669167 +list,list/hsa:2064,curl,1.710764 +list,list/hsa:5290,curl,1.723103 +list,list/hsa:7422,curl,1.718145 +list,list/hsa:3845,curl,1.762285 +list,list/hsa:5970,curl,1.659278 +list,list/hsa:4609,curl,1.734134 +list,list/hsa:2475,curl,1.792645 +list,list/hsa:5728,curl,1.728749 +list,list/hsa:1029,curl,1.712311 +list,list/hsa:3553,curl,1.719025 +list,list/hsa:7124,curl,1.705707 +list,list/hsa:7040,curl,1.702842 +list,list/hsa:3091,curl,1.757566 +list,list/hsa:3105,curl,1.762245 +list,list/hsa:4318,curl,1.700349 +list,list/hsa:5243,curl,1.75333 +list,list/hsa:5468,curl,1.711922 +list,list/hsa:2099,curl,1.724266 +list,list/hsa:2100,curl,1.771723 +list,list/hsa:348,curl,1.726561 +find,find/compound/glucose,curl,2.060762 +find,find/compound/fructose,curl,1.730552 +find,find/compound/galactose,curl,1.48732 +find,find/compound/mannose,curl,1.506387 +find,find/compound/sucrose,curl,1.447524 +find,find/compound/lactose,curl,1.523535 +find,find/compound/maltose,curl,1.479297 +find,find/compound/ribose,curl,1.519659 +find,find/compound/xylose,curl,1.47697 +find,find/compound/pyruvate,curl,1.523155 +find,find/compound/citrate,curl,1.504457 +find,find/compound/acetate,curl,2.030077 +find,find/compound/ethanol,curl,1.708204 +find,find/compound/cholesterol,curl,1.52411 +find,find/compound/adenine,curl,1.534985 +find,find/compound/guanine,curl,1.522478 +find,find/compound/cytosine,curl,1.535496 +find,find/compound/thymine,curl,1.51614 +find,find/compound/uracil,curl,1.440645 +find,find/compound/glycine,curl,1.459744 +find,find/compound/alanine,curl,1.688229 +find,find/compound/valine,curl,1.652786 +find,find/compound/leucine,curl,1.473687 +find,find/compound/serine,curl,1.570675 +find,find/compound/cysteine,curl,1.499064 +get,get/hsa:10458,curl,1.102962 +get,get/hsa:7157,curl,1.28206 +get,get/hsa:672,curl,1.258738 +get,get/hsa:675,curl,1.325361 +get,get/hsa:1956,curl,1.685351 +get,get/hsa:2064,curl,1.291893 +get,get/hsa:5290,curl,1.585455 +get,get/hsa:7422,curl,1.021244 +get,get/hsa:3845,curl,1.374268 +get,get/hsa:5970,curl,1.344754 +get,get/hsa:4609,curl,1.299873 +get,get/hsa:2475,curl,1.290724 +get,get/hsa:5728,curl,1.088543 +get,get/hsa:1029,curl,1.038785 +get,get/hsa:3553,curl,1.039356 +get,get/hsa:7124,curl,1.289689 +get,get/hsa:7040,curl,1.051094 +get,get/hsa:3091,curl,1.024622 +get,get/hsa:3105,curl,1.030356 +get,get/hsa:4318,curl,1.036827 +get,get/hsa:5243,curl,1.0279 +get,get/hsa:5468,curl,1.022028 +get,get/hsa:2099,curl,1.073177 +get,get/hsa:2100,curl,1.068155 +get,get/hsa:348,curl,1.077396 +getseq,get/hsa:10458/aaseq,curl,1.03664 +getseq,get/hsa:7157/aaseq,curl,1.021925 +getseq,get/hsa:672/aaseq,curl,1.075162 +getseq,get/hsa:675/aaseq,curl,1.076278 +getseq,get/hsa:1956/aaseq,curl,1.134205 +getseq,get/hsa:2064/aaseq,curl,1.097801 +getseq,get/hsa:5290/aaseq,curl,1.023933 +getseq,get/hsa:7422/aaseq,curl,1.184752 +getseq,get/hsa:3845/aaseq,curl,1.091252 +getseq,get/hsa:5970/aaseq,curl,1.028201 +getseq,get/hsa:4609/aaseq,curl,1.176584 +getseq,get/hsa:2475/aaseq,curl,1.035608 +getseq,get/hsa:5728/aaseq,curl,1.123888 +getseq,get/hsa:1029/aaseq,curl,1.41752 +getseq,get/hsa:3553/aaseq,curl,1.059988 +getseq,get/hsa:7124/aaseq,curl,1.131823 +getseq,get/hsa:7040/aaseq,curl,1.320676 +getseq,get/hsa:3091/aaseq,curl,1.34669 +getseq,get/hsa:3105/aaseq,curl,1.338214 +getseq,get/hsa:4318/aaseq,curl,1.278413 +getseq,get/hsa:5243/aaseq,curl,1.352818 +getseq,get/hsa:5468/aaseq,curl,1.342408 +getseq,get/hsa:2099/aaseq,curl,1.3558 +getseq,get/hsa:2100/aaseq,curl,1.369172 +getseq,get/hsa:348/aaseq,curl,1.266235 +conv,conv/ncbi-geneid/hsa:10458,curl,1.308543 +conv,conv/ncbi-geneid/hsa:7157,curl,1.303341 +conv,conv/ncbi-geneid/hsa:672,curl,1.300993 +conv,conv/ncbi-geneid/hsa:675,curl,1.406502 +conv,conv/ncbi-geneid/hsa:1956,curl,1.330483 +conv,conv/ncbi-geneid/hsa:2064,curl,1.321999 +conv,conv/ncbi-geneid/hsa:5290,curl,1.298372 +conv,conv/ncbi-geneid/hsa:7422,curl,1.386182 +conv,conv/ncbi-geneid/hsa:3845,curl,1.321902 +conv,conv/ncbi-geneid/hsa:5970,curl,1.30425 +conv,conv/ncbi-geneid/hsa:4609,curl,1.311538 +conv,conv/ncbi-geneid/hsa:2475,curl,1.365007 +conv,conv/ncbi-geneid/hsa:5728,curl,1.331298 +conv,conv/ncbi-geneid/hsa:1029,curl,1.378926 +conv,conv/ncbi-geneid/hsa:3553,curl,1.360778 +conv,conv/ncbi-geneid/hsa:7124,curl,1.332136 +conv,conv/ncbi-geneid/hsa:7040,curl,1.30291 +conv,conv/ncbi-geneid/hsa:3091,curl,1.305841 +conv,conv/ncbi-geneid/hsa:3105,curl,1.323523 +conv,conv/ncbi-geneid/hsa:4318,curl,1.344628 +conv,conv/ncbi-geneid/hsa:5243,curl,1.293187 +conv,conv/ncbi-geneid/hsa:5468,curl,1.339419 +conv,conv/ncbi-geneid/hsa:2099,curl,1.311107 +conv,conv/ncbi-geneid/hsa:2100,curl,1.332708 +conv,conv/ncbi-geneid/hsa:348,curl,1.324312 +link,link/pathway/hsa:10458,curl,1.391532 +link,link/pathway/hsa:7157,curl,1.31629 +link,link/pathway/hsa:672,curl,1.349629 +link,link/pathway/hsa:675,curl,1.305197 +link,link/pathway/hsa:1956,curl,1.310748 +link,link/pathway/hsa:2064,curl,1.30643 +link,link/pathway/hsa:5290,curl,1.333224 +link,link/pathway/hsa:7422,curl,1.323807 +link,link/pathway/hsa:3845,curl,1.348449 +link,link/pathway/hsa:5970,curl,1.076229 +link,link/pathway/hsa:4609,curl,1.313767 +link,link/pathway/hsa:2475,curl,1.067359 +link,link/pathway/hsa:5728,curl,1.093161 +link,link/pathway/hsa:1029,curl,1.319468 +link,link/pathway/hsa:3553,curl,1.311523 +link,link/pathway/hsa:7124,curl,1.318955 +link,link/pathway/hsa:7040,curl,1.332867 +link,link/pathway/hsa:3091,curl,1.346838 +link,link/pathway/hsa:3105,curl,1.322622 +link,link/pathway/hsa:4318,curl,1.316255 +link,link/pathway/hsa:5243,curl,1.336 +link,link/pathway/hsa:5468,curl,1.382411 +link,link/pathway/hsa:2099,curl,1.620365 +link,link/pathway/hsa:2100,curl,1.324806 +link,link/pathway/hsa:348,curl,1.379263 +ddi,ddi/D00006,curl,1.808338 +ddi,ddi/D00008,curl,1.886911 +ddi,ddi/D00015,curl,1.755841 +ddi,ddi/D00018,curl,1.823794 +ddi,ddi/D00020,curl,1.782555 +ddi,ddi/D00028,curl,1.900043 +ddi,ddi/D00032,curl,1.908649 +ddi,ddi/D00033,curl,1.95868 +ddi,ddi/D00043,curl,2.023666 +ddi,ddi/D00045,curl,1.604179 +ddi,ddi/D00049,curl,1.914641 +ddi,ddi/D00052,curl,2.05876 +ddi,ddi/D00058,curl,1.910477 +ddi,ddi/D00059,curl,2.11394 +ddi,ddi/D00060,curl,1.95688 +ddi,ddi/D00062,curl,1.600534 +ddi,ddi/D00063,curl,1.865384 +ddi,ddi/D00066,curl,1.60293 +ddi,ddi/D00067,curl,1.639928 +ddi,ddi/D00068,curl,1.638694 +ddi,ddi/D00069,curl,1.718556 +ddi,ddi/D00070,curl,1.607039 +ddi,ddi/D00073,curl,1.720881 +ddi,ddi/D00074,curl,1.811919 +ddi,ddi/D00075,curl,3.444944 diff --git a/benchmarking/benchmark_compare.png b/benchmarking/benchmark_compare.png deleted file mode 100644 index f26c16e..0000000 Binary files a/benchmarking/benchmark_compare.png and /dev/null differ diff --git a/benchmarking/cases.tsv b/benchmarking/cases.tsv new file mode 100644 index 0000000..3cacf66 --- /dev/null +++ b/benchmarking/cases.tsv @@ -0,0 +1,201 @@ +operation argument1 argument2 +info kegg - +info pathway - +info brite - +info module - +info ko - +info genome - +info genes - +info ligand - +info compound - +info glycan - +info reaction - +info rclass - +info enzyme - +info network - +info variant - +info disease - +info drug - +info dgroup - +info cel - +info hsa - +info eco - +info sce - +info ath - +info dme - +info mmu - +list hsa:10458 - +list hsa:7157 - +list hsa:672 - +list hsa:675 - +list hsa:1956 - +list hsa:2064 - +list hsa:5290 - +list hsa:7422 - +list hsa:3845 - +list hsa:5970 - +list hsa:4609 - +list hsa:2475 - +list hsa:5728 - +list hsa:1029 - +list hsa:3553 - +list hsa:7124 - +list hsa:7040 - +list hsa:3091 - +list hsa:3105 - +list hsa:4318 - +list hsa:5243 - +list hsa:5468 - +list hsa:2099 - +list hsa:2100 - +list hsa:348 - +find compound glucose +find compound fructose +find compound galactose +find compound mannose +find compound sucrose +find compound lactose +find compound maltose +find compound ribose +find compound xylose +find compound pyruvate +find compound citrate +find compound acetate +find compound ethanol +find compound cholesterol +find compound adenine +find compound guanine +find compound cytosine +find compound thymine +find compound uracil +find compound glycine +find compound alanine +find compound valine +find compound leucine +find compound serine +find compound cysteine +get hsa:10458 - +get hsa:7157 - +get hsa:672 - +get hsa:675 - +get hsa:1956 - +get hsa:2064 - +get hsa:5290 - +get hsa:7422 - +get hsa:3845 - +get hsa:5970 - +get hsa:4609 - +get hsa:2475 - +get hsa:5728 - +get hsa:1029 - +get hsa:3553 - +get hsa:7124 - +get hsa:7040 - +get hsa:3091 - +get hsa:3105 - +get hsa:4318 - +get hsa:5243 - +get hsa:5468 - +get hsa:2099 - +get hsa:2100 - +get hsa:348 - +getseq hsa:10458 - +getseq hsa:7157 - +getseq hsa:672 - +getseq hsa:675 - +getseq hsa:1956 - +getseq hsa:2064 - +getseq hsa:5290 - +getseq hsa:7422 - +getseq hsa:3845 - +getseq hsa:5970 - +getseq hsa:4609 - +getseq hsa:2475 - +getseq hsa:5728 - +getseq hsa:1029 - +getseq hsa:3553 - +getseq hsa:7124 - +getseq hsa:7040 - +getseq hsa:3091 - +getseq hsa:3105 - +getseq hsa:4318 - +getseq hsa:5243 - +getseq hsa:5468 - +getseq hsa:2099 - +getseq hsa:2100 - +getseq hsa:348 - +conv ncbi-geneid hsa:10458 +conv ncbi-geneid hsa:7157 +conv ncbi-geneid hsa:672 +conv ncbi-geneid hsa:675 +conv ncbi-geneid hsa:1956 +conv ncbi-geneid hsa:2064 +conv ncbi-geneid hsa:5290 +conv ncbi-geneid hsa:7422 +conv ncbi-geneid hsa:3845 +conv ncbi-geneid hsa:5970 +conv ncbi-geneid hsa:4609 +conv ncbi-geneid hsa:2475 +conv ncbi-geneid hsa:5728 +conv ncbi-geneid hsa:1029 +conv ncbi-geneid hsa:3553 +conv ncbi-geneid hsa:7124 +conv ncbi-geneid hsa:7040 +conv ncbi-geneid hsa:3091 +conv ncbi-geneid hsa:3105 +conv ncbi-geneid hsa:4318 +conv ncbi-geneid hsa:5243 +conv ncbi-geneid hsa:5468 +conv ncbi-geneid hsa:2099 +conv ncbi-geneid hsa:2100 +conv ncbi-geneid hsa:348 +link pathway hsa:10458 +link pathway hsa:7157 +link pathway hsa:672 +link pathway hsa:675 +link pathway hsa:1956 +link pathway hsa:2064 +link pathway hsa:5290 +link pathway hsa:7422 +link pathway hsa:3845 +link pathway hsa:5970 +link pathway hsa:4609 +link pathway hsa:2475 +link pathway hsa:5728 +link pathway hsa:1029 +link pathway hsa:3553 +link pathway hsa:7124 +link pathway hsa:7040 +link pathway hsa:3091 +link pathway hsa:3105 +link pathway hsa:4318 +link pathway hsa:5243 +link pathway hsa:5468 +link pathway hsa:2099 +link pathway hsa:2100 +link pathway hsa:348 +ddi D00006 - +ddi D00008 - +ddi D00015 - +ddi D00018 - +ddi D00020 - +ddi D00028 - +ddi D00032 - +ddi D00033 - +ddi D00043 - +ddi D00045 - +ddi D00049 - +ddi D00052 - +ddi D00058 - +ddi D00059 - +ddi D00060 - +ddi D00062 - +ddi D00063 - +ddi D00066 - +ddi D00067 - +ddi D00068 - +ddi D00069 - +ddi D00070 - +ddi D00073 - +ddi D00074 - +ddi D00075 - diff --git a/benchmarking/figure.jl b/benchmarking/figure.jl new file mode 100644 index 0000000..cf5cb2e --- /dev/null +++ b/benchmarking/figure.jl @@ -0,0 +1,2160 @@ +### A Pluto.jl notebook ### +# v0.20.24 + +using Markdown +using InteractiveUtils + +# ╔═╡ 4c14aad4-bb94-11f1-90df-4d61c6cdbcfe +begin + using AlgebraOfGraphics + using CairoMakie + using CSV + using DataFrames + using Statistics +end + +# ╔═╡ 5e83c41a-85f0-4095-92d2-5ceeb6d10408 +md""" +# KEGG API benchmark + +Median request time for each client and KEGG operation. KEGGREST and +Bio.KEGG.REST do not provide a DDI method. +""" + +# ╔═╡ 6c1424e5-60a9-406d-b3b5-66eabec2ad44 +begin + csv_path = joinpath(@__DIR__, "benchmark_compare.csv") + isfile(csv_path) || error("$csv_path not found. Run run_benchmarks.jl first.") + benchmarks = CSV.read(csv_path, DataFrame) + + expected_columns = ["Function", "Request", "Language", "Seconds"] + names(benchmarks) == expected_columns || error("Unexpected columns in $csv_path") + all(isfinite, benchmarks.Seconds) && all(>=(0), benchmarks.Seconds) || + error("Benchmark timings must be finite and nonnegative") + + function median_value(values) + sorted = sort(collect(values)) + middle = length(sorted) ÷ 2 + return isodd(length(sorted)) ? sorted[middle + 1] : (sorted[middle] + sorted[middle + 1]) / 2 + end + + plot_data = combine( + groupby(filter(:Function => !=("getseq"), benchmarks), [:Function, :Language]), + :Seconds => median_value => :Median, + :Seconds => minimum => :Minimum, + :Seconds => maximum => :Maximum, + :Seconds => std => :sd, + :Seconds => mean => :mean, + ) + new_rows = DataFrame( + Function = ["ddi", "ddi"], + Language = ["Bio.KEGG.REST (Python)", "KEGGREST (R)"], + Median = [0,0], + Minimum = [0,0], + Maximum = [0,0], + sd = [0,0], + mean = [0,0] + ) + + # Append the new rows to the DataFrame + #append!(new_rows, plot_data) + #plot_data + +end + +# ╔═╡ 91976867-0ecd-4d32-abc7-f64c817e6894 + + +# ╔═╡ 4e2857e6-0765-422c-a22a-7ea60c91ce57 +begin + nerd_font = String(readchomp(`fc-match -f "%{file}" "JetBrainsMono Nerd Font"`)) + language_names = Dict( + "KEGGAPI.jl" => "KEGGAPI.jl \ue624", + "KEGGREST (R)" => "KEGGREST \ue68a", + "Bio.KEGG.REST (Python)" => "Bio.KEGG.REST \ue73c", + "curl" => "curl \uf31a", + ) + client_order = [language_names[k] for k in [ + "curl", + "Bio.KEGG.REST (Python)", + "KEGGREST (R)", + "KEGGAPI.jl", + ]] + language_order = reverse(client_order) +end + +# ╔═╡ 7c3a0227-12da-4440-bb2d-f5fb37dba4ee +begin + set_theme!(theme_minimal(); Axis = (; yticklabelfont = nerd_font)) + figure = draw( + data(plot_data) + * mapping( + :Language => (name -> language_names[String(name)]) => "", + :Median => "Seconds per call (median)", + col = :Function => presorted, + color = :Language, + ) + * visual( + BarPlot; + direction = :x, + bar_labels = :y, + flip_labels_at = (0, 1.0), + label_formatter = value -> trunc(value; digits = 2), + ), + scales( + Y = (; categories = language_order), + Color = (; palette = ["gainsboro", "#0031a9", "gainsboro", "gainsboro"]), + ); + figure = (; size = (1000, 250)), + axis = (; + limits = (0, nothing, nothing, nothing), + xticks = [-1], + bottomspinevisible = false, + ), + legend = (; show = false), + facet = (; linkxaxes = :none), + ) +end + +# ╔═╡ dece6392-d991-440d-97e1-9f51c30570d0 +let + set_theme!(theme_minimal(); Axis = (; yticklabelfont = nerd_font)) + figure = draw( + data(plot_data) + * mapping( + :Language => (name -> language_names[String(name)]) => "", + :Minimum => "Seconds per call (minimum)", + col = :Function => presorted, + color = :Language, + ) + * visual( + BarPlot; + direction = :x, + bar_labels = :y, + flip_labels_at = (0, 1.0), + label_formatter = value -> trunc(value; digits = 2), + ), + scales( + Y = (; categories = language_order), + Color = (; palette = ["gainsboro", "#0031a9", "gainsboro", "gainsboro"]), + ); + figure = (; size = (1000, 250)), + axis = (; + limits = (0, nothing, nothing, nothing), + xticks = [-1], + bottomspinevisible = false, + ), + legend = (; show = false), + facet = (; linkxaxes = :none), + ) +end + +# ╔═╡ 1164a037-20ce-4731-bbb2-80e6bdddd495 +let + set_theme!(theme_minimal(); Axis = (; yticklabelfont = nerd_font)) + figure = draw( + data(plot_data) + * mapping( + :Language => (name -> language_names[String(name)]) => "", + :Maximum => "Seconds per call (maximum)", + col = :Function => presorted, + color = :Language, + ) + * visual( + BarPlot; + direction = :x, + bar_labels = :y, + flip_labels_at = (0, 1.0), + label_formatter = value -> trunc(value; digits = 2), + ), + scales( + Y = (; categories = language_order), + Color = (; palette = ["gainsboro", "#0031a9", "gainsboro", "gainsboro"]), + ); + figure = (; size = (1000, 250)), + axis = (; + limits = (0, nothing, nothing, nothing), + xticks = [-1], + bottomspinevisible = false, + ), + legend = (; show = false), + facet = (; linkxaxes = :none), + ) +end + +# ╔═╡ 7023db0d-ad08-4e7a-9c0d-e04f0b49dd57 +let + set_theme!() + client = :Language => (name -> language_names[String(name)]) => "Client" + + bars = mapping( + :Function => presorted, + :mean => "Request time (seconds)"; + dodge = client, + color = client, + ) * visual(BarPlot) + + error_bars = mapping( + :Function => presorted, + :mean => "Request time (seconds)", + :sd; + dodge_x = client, + + ) * visual(Errorbars; color = :black, whiskerwidth = 4, linewidth = 1) + + draw( + data(plot_data) * (bars + error_bars) + mapping([0.5+i for i in 1:6]) * visual(VLines, color=:black, linestyle=:dot), + scales( + DodgeX = (; categories = client_order), + Color = (; categories = client_order, + #palette = [:lightgreen, :magenta, :orange, :gainsboro] + palette = :julialegacy + ), + ); + figure = (; size = (700, 250)), + axis = (; + #title = "Mean request time ± 1 SD", + xlabel = "KEGG operation", + limits = (0.5, 7.5, 0, nothing), + xgridvisible=false + ), + legend = (; framevisible = false, labelfont = nerd_font) + ) +end + +# ╔═╡ 11d16508-1718-4ade-b713-2809b8d7be3d +benchmarks + +# ╔═╡ 0eea9b04-1741-47f2-9c45-1bedc8a08769 +draw( + data(sort(transform(benchmarks, :Function => (x -> replace(x, "getseq" => "get")) => :Function), :Seconds)) + * mapping(:Seconds, layout=:Function => presorted, color=:Language) + * visual(Lines), + scales( + #Layout = (; categories = [""]) + ), + axis = (; limits = (nothing, nothing, 0.2, 1) ), + figure = (; sharex=false) +) + + +# ╔═╡ f221ca13-ad01-480b-a923-c7e9eaaff71b +transform(benchmarks, :Function => (x -> replace(x, "getseq" => "get")) => :Function) + +# ╔═╡ 7b38d542-57d9-4f1a-af35-1bf1a39a9b3f + + +# ╔═╡ d9a02b4d-ee72-40a3-9be2-fad6256ce600 +let + f=Figure(size=(250,50)) + ax = Axis(f[1,1]) + heatmap!(ax,rand(128,1), colormap=:Oranges) + hidedecorations!(ax) + f +end + +# ╔═╡ 6e70799b-3271-4dbf-85e9-ded8ac07bbc9 +let + f=Figure(size=(250,50)) + ax = Axis(f[1,1]) + heatmap!(ax,rand(128,1), colormap=:Greens) + hidedecorations!(ax) + f +end + +# ╔═╡ 2babdf19-d03a-4223-8cb0-c9b8a4510fd1 +let + f=Figure(size=(250,50)) + ax = Axis(f[1,1]) + heatmap!(ax,rand(128,1), colormap=:Purples) + hidedecorations!(ax) + f +end + +# ╔═╡ 4ad6cf74-42d3-44f5-b694-3b2f005bfda3 +let + f=Figure(size=(250,50)) + ax = Axis(f[1,1]) + heatmap!(ax,rand(128,1), colormap=:Greys) + hidedecorations!(ax) + f +end + +# ╔═╡ 7249e211-b3d0-41f8-a5b2-40c5076c81f5 +let + s = "Hello, World!" + f=Figure(size=(200,250)) + ax = Axis(f[1,1], xticks=(1:length(s), string.(collect(s)))) + heatmap!(ax,rand(length(s), 128), colormap=:Purples) + #hidedecorations!(ax) + f +end + +# ╔═╡ fcfb2fd2-e8a5-414e-b3d2-b208123ad874 + + +# ╔═╡ 00000000-0000-0000-0000-000000000001 +PLUTO_PROJECT_TOML_CONTENTS = """ +[deps] +AlgebraOfGraphics = "cbdf2221-f076-402e-a563-3d30da359d67" +CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[compat] +AlgebraOfGraphics = "~0.13.2" +CSV = "~1.1.0" +CairoMakie = "~0.15.15" +DataFrames = "~1.8.2" +""" + +# ╔═╡ 00000000-0000-0000-0000-000000000002 +PLUTO_MANIFEST_TOML_CONTENTS = """ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.12.6" +manifest_format = "2.0" +project_hash = "ce5cf1cf37c02c4f860ceb198180abae7539b906" + +[[deps.AbstractFFTs]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.5.0" + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" + + [deps.AbstractFFTs.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.AbstractTrees]] +git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177" +uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" +version = "0.4.5" + +[[deps.Accessors]] +deps = ["CompositionsBase", "ConstructionBase", "Dates", "InverseFunctions", "MacroTools"] +git-tree-sha1 = "7063ad1083578215c7c4bf410368150abe8d5524" +uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" +version = "0.1.45" + + [deps.Accessors.extensions] + AxisKeysExt = "AxisKeys" + IntervalSetsExt = "IntervalSets" + LinearAlgebraExt = "LinearAlgebra" + StaticArraysExt = "StaticArrays" + StructArraysExt = "StructArrays" + TestExt = "Test" + UnitfulExt = "Unitful" + + [deps.Accessors.weakdeps] + AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5" + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.Adapt]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "7c2c19b5a26e601634bf718490b89d59685f122e" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "4.7.1" +weakdeps = ["SparseArrays", "StaticArrays"] + + [deps.Adapt.extensions] + AdaptSparseArraysExt = "SparseArrays" + AdaptStaticArraysExt = "StaticArrays" + +[[deps.AdaptivePredicates]] +git-tree-sha1 = "7e651ea8d262d2d74ce75fdf47c4d63c07dba7a6" +uuid = "35492f91-a3bd-45ad-95db-fcad7dcfedb7" +version = "1.2.0" + +[[deps.AlgebraOfGraphics]] +deps = ["Accessors", "Colors", "DataAPI", "Dates", "Dictionaries", "FileIO", "GLM", "GeoInterface", "GeometryBasics", "GridLayoutBase", "Isoband", "KernelDensity", "Loess", "Makie", "NaturalSort", "PlotUtils", "PolygonOps", "PooledArrays", "PrecompileTools", "RelocatableFolders", "StatsBase", "StructArrays", "Tables"] +git-tree-sha1 = "88b1f363a4c69268ab705bcb5a049768a367bed9" +uuid = "cbdf2221-f076-402e-a563-3d30da359d67" +version = "0.13.2" + + [deps.AlgebraOfGraphics.extensions] + AlgebraOfGraphicsDynamicQuantitiesExt = "DynamicQuantities" + AlgebraOfGraphicsUnitfulExt = "Unitful" + + [deps.AlgebraOfGraphics.weakdeps] + DynamicQuantities = "06fc5a27-2a28-4c7c-a15d-362465fb6821" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.AliasTables]] +deps = ["PtrArrays", "Random"] +git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff" +uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8" +version = "1.1.3" + +[[deps.Animations]] +deps = ["Colors"] +git-tree-sha1 = "e092fa223bf66a3c41f9c022bd074d916dc303e7" +uuid = "27a7e980-b3e6-11e9-2bcd-0b925532e340" +version = "0.4.2" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.2" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +version = "1.11.0" + +[[deps.Automa]] +deps = ["PrecompileTools", "TranscodingStreams"] +git-tree-sha1 = "94eab0b3ccdcac361188cc661daf69d4433c1818" +uuid = "67c07d97-cdcb-5c2c-af73-a7f9c32a568b" +version = "1.2.0" + +[[deps.AxisAlgorithms]] +deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"] +git-tree-sha1 = "01b8ccb13d68535d73d2b0c23e39bd23155fb712" +uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950" +version = "1.1.0" + +[[deps.AxisArrays]] +deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"] +git-tree-sha1 = "4126b08903b777c88edf1754288144a0492c05ad" +uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9" +version = "0.4.8" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" + +[[deps.BaseDirs]] +git-tree-sha1 = "8c290a1b223deaeea9aea44b235d24546da8eb98" +uuid = "18cc8868-cbac-4acf-b575-c8ff214dc66f" +version = "1.4.0" + +[[deps.Bzip2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1b96ea4a01afe0ea4090c5c8039690672dd13f2e" +uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" +version = "1.0.9+0" + +[[deps.CEnum]] +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.5.0" + +[[deps.CRC32c]] +uuid = "8bf52ea8-c179-5cab-976a-9e18b702a9bc" +version = "1.11.0" + +[[deps.CRlibm]] +deps = ["CRlibm_jll"] +git-tree-sha1 = "66188d9d103b92b6cd705214242e27f5737a1e5e" +uuid = "96374032-68de-5a5b-8d9e-752f78720389" +version = "1.0.2" + +[[deps.CRlibm_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "e329286945d0cfc04456972ea732551869af1cfc" +uuid = "4e9b3aee-d8a1-5a3d-ad8b-7d824db253f0" +version = "1.0.1+0" + +[[deps.CSV]] +deps = ["CodecZlib", "DataStrings", "Dates", "Downloads", "Durations", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "Printf", "Tables", "Unicode"] +git-tree-sha1 = "ed05d41d96b1a815d52e9de1ef472971bc509832" +uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +version = "1.1.0" + + [deps.CSV.extensions] + CSVDataDecimalsExt = "DataDecimals" + CSVFilePathsBaseExt = "FilePathsBase" + CSVInlineStringsExt = "InlineStrings" + + [deps.CSV.weakdeps] + DataDecimals = "3e2245cb-6932-498d-a7cf-39d39de8bde3" + FilePathsBase = "48062228-2e41-5def-b9a4-89aafe57970f" + InlineStrings = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" + +[[deps.Cairo]] +deps = ["Cairo_jll", "Colors", "Glib_jll", "Graphics", "Libdl", "Pango_jll"] +git-tree-sha1 = "71aa551c5c33f1a4415867fe06b7844faadb0ae9" +uuid = "159f3aea-2a34-519c-b102-8c37f9878175" +version = "1.1.1" + +[[deps.CairoMakie]] +deps = ["CRC32c", "Cairo", "Cairo_jll", "Colors", "FileIO", "FreeType", "GeometryBasics", "LinearAlgebra", "Makie", "PrecompileTools"] +git-tree-sha1 = "1cda0b7d5abfc95357dae18aca934d401f7869ad" +uuid = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +version = "0.15.15" + +[[deps.Cairo_jll]] +deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "1fa950ebc3e37eccd51c6a8fe1f92f7d86263522" +uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a" +version = "1.18.7+0" + +[[deps.ChainRulesCore]] +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "12177ad6b3cad7fd50c8b3825ce24a99ad61c18f" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "1.26.1" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" + +[[deps.CodecZlib]] +deps = ["TranscodingStreams", "Zlib_jll"] +git-tree-sha1 = "970758a3d591a2a5c2a907c53f2e2f8c1b1d3537" +uuid = "944b1d66-785c-5afd-91f1-9de20f533193" +version = "0.7.9" + +[[deps.CodecZstd]] +deps = ["TranscodingStreams", "Zstd_jll"] +git-tree-sha1 = "da54a6cd93c54950c15adf1d336cfd7d71f51a56" +uuid = "6b39b394-51ab-5f42-8807-6242bab2b4c2" +version = "0.8.7" + +[[deps.ColorBrewer]] +deps = ["Colors", "JSON"] +git-tree-sha1 = "07da79661b919001e6863b81fc572497daa58349" +uuid = "a2cac450-b92f-5266-8821-25eda20663c8" +version = "0.4.2" + +[[deps.ColorSchemes]] +deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] +git-tree-sha1 = "b0fd3f56fa442f81e0a47815c92245acfaaa4e34" +uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +version = "3.31.0" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "67e11ee83a43eb71ddc950302c53bf33f0690dfe" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.12.1" +weakdeps = ["StyledStrings"] + + [deps.ColorTypes.extensions] + StyledStringsExt = "StyledStrings" + +[[deps.ColorVectorSpace]] +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "8b3b6f87ce8f65a2b4f857528fd8d70086cd72b1" +uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" +version = "0.11.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "37ea44092930b1811e666c3bc38065d7d87fcc74" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.13.1" + +[[deps.CommonSolve]] +deps = ["PrecompileTools"] +git-tree-sha1 = "6c389fa857f6ca5a95474b52a52023fd77f24cb7" +uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" +version = "0.2.14" + +[[deps.Compat]] +deps = ["TOML", "UUIDs"] +git-tree-sha1 = "9d8a54ce4b17aa5bdce0ea5c34bc5e7c340d16ad" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.18.1" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.3.0+1" + +[[deps.CompositionsBase]] +git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad" +uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b" +version = "0.1.2" +weakdeps = ["InverseFunctions"] + + [deps.CompositionsBase.extensions] + CompositionsBaseInverseFunctionsExt = "InverseFunctions" + +[[deps.ComputePipeline]] +deps = ["Observables", "Preferences"] +git-tree-sha1 = "7bc84b769c1d384315e7b5c4ac03a6c303e6cf35" +uuid = "95dc2771-c249-4cd0-9c9f-1f3b4330693c" +version = "0.1.8" + +[[deps.ConstructionBase]] +git-tree-sha1 = "b4b092499347b18a015186eae3042f72267106cb" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.6.0" +weakdeps = ["IntervalSets", "LinearAlgebra", "StaticArrays"] + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseLinearAlgebraExt = "LinearAlgebra" + ConstructionBaseStaticArraysExt = "StaticArrays" + +[[deps.Contour]] +git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8" +uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" +version = "0.6.3" + +[[deps.CoreMath]] +deps = ["CoreMath_jll"] +git-tree-sha1 = "8c0480f92b1b1796239156a1b9b1bfb1b39499b4" +uuid = "b7a15901-be09-4a0e-87d2-2e66b0e09b5a" +version = "0.1.0" + +[[deps.CoreMath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "a692a4c1dc59a4b8bc0b6403876eb3250fde2bc3" +uuid = "a38c48d9-6df1-5ac9-9223-b6ada3b5572b" +version = "0.1.0+0" + +[[deps.Crayons]] +git-tree-sha1 = "54b76cbb40d9a0f5368c880725b2f141da77c94f" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.2.0" + +[[deps.DataAPI]] +git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.16.0" + +[[deps.DataFrames]] +deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "5fab31e2e01e70ad66e3e24c968c264d1cf166d6" +uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +version = "1.8.2" + +[[deps.DataStrings]] +git-tree-sha1 = "b8032263d364177a0b192ea15f277df4e6ab07e2" +uuid = "48204bd6-5611-42ea-b167-fc1d713f9be2" +version = "1.1.0" + +[[deps.DataStructures]] +deps = ["OrderedCollections"] +git-tree-sha1 = "b0bc6d2cad1fed8b7fd59a1551a991cb3d2809e6" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.19.6" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" + +[[deps.DelaunayTriangulation]] +deps = ["AdaptivePredicates", "EnumX", "ExactPredicates", "Random"] +git-tree-sha1 = "4ac548adcad90c1d5d677af13568a748af4c952b" +uuid = "927a84f5-c5f4-47a5-9785-b46e178433df" +version = "1.6.7" + +[[deps.Dictionaries]] +deps = ["Indexing", "Random", "Serialization"] +git-tree-sha1 = "a55766a9c8f66cf19ffcdbdb1444e249bb4ace33" +uuid = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" +version = "0.4.6" + +[[deps.Distances]] +deps = ["LinearAlgebra", "Statistics", "StatsAPI"] +git-tree-sha1 = "c7e3a542b999843086e2f29dac96a618c105be1d" +uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" +version = "0.10.12" +weakdeps = ["ChainRulesCore", "SparseArrays"] + + [deps.Distances.extensions] + DistancesChainRulesCoreExt = "ChainRulesCore" + DistancesSparseArraysExt = "SparseArrays" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" +version = "1.11.0" + +[[deps.Distributions]] +deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "Roots", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "a958ab3a40c755563f5e1405c0846cb0446bf19d" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.25.131" + + [deps.Distributions.extensions] + DistributionsChainRulesCoreExt = "ChainRulesCore" + DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsSparseConnectivityTracerExt = "SparseConnectivityTracer" + DistributionsTestExt = "Test" + + [deps.Distributions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + SparseConnectivityTracer = "9f842d2f-2579-4b1d-911e-f412cf18a3f5" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.DocStringExtensions]] +git-tree-sha1 = "7442a5dfe1ebb773c29cc2962a8980f47221d76c" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.5" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.7.0" + +[[deps.Durations]] +deps = ["Dates"] +git-tree-sha1 = "a2f9c974a78a23661f0e41d0b80b687f844c018e" +uuid = "41ac09f5-0a95-4810-aa18-c88bf48ee130" +version = "1.2.0" + + [deps.Durations.extensions] + DurationsArrowExt = "Arrow" + + [deps.Durations.weakdeps] + Arrow = "69666777-d1a9-59fb-9406-91d4454c9d45" + +[[deps.EarCut_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "e3290f2d49e661fbd94046d7e3726ffcb2d41053" +uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5" +version = "2.2.4+0" + +[[deps.EnumX]] +git-tree-sha1 = "c49898e8438c828577f04b92fc9368c388ac783c" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.7" + +[[deps.ExactPredicates]] +deps = ["IntervalArithmetic", "Random", "StaticArrays"] +git-tree-sha1 = "83231673ea4d3d6008ac74dc5079e77ab2209d8f" +uuid = "429591f6-91af-11e9-00e2-59fbe8cec110" +version = "2.2.9" + +[[deps.Expat_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "2bfb1e047e2ad0a5ca94365340bde8005d637568" +uuid = "2e619515-83b5-522b-bb60-26c02a35a201" +version = "2.8.4+0" + +[[deps.Extents]] +git-tree-sha1 = "b309b36a9e02fe7be71270dd8c0fd873625332b4" +uuid = "411431e0-e8b7-467b-b5e0-f676ba4f2910" +version = "0.1.6" + +[[deps.FFMPEG_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libva_jll", "libvorbis_jll", "x264_jll", "x265_jll"] +git-tree-sha1 = "e3c081ec777297fb8fc433012d15a6eaf806b4d2" +uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" +version = "9.0.1+0" + +[[deps.FFTA]] +deps = ["AbstractFFTs", "DocStringExtensions", "LinearAlgebra", "MuladdMacro", "Primes", "Random", "Reexport"] +git-tree-sha1 = "65e55303b72f4a567a51b174dd2c47496efeb95a" +uuid = "b86e33f2-c0db-4aa1-a6e0-ab43e668529e" +version = "0.3.1" + +[[deps.FileIO]] +deps = ["Pkg", "Requires", "UUIDs"] +git-tree-sha1 = "6621fef488e496356c9c9625d0562c12a6070819" +uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +version = "1.20.0" + + [deps.FileIO.extensions] + HTTPExt = "HTTP" + + [deps.FileIO.weakdeps] + HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" + +[[deps.FilePaths]] +deps = ["FilePathsBase", "MacroTools", "Reexport"] +git-tree-sha1 = "a1b2fbfe98503f15b665ed45b3d149e5d8895e4c" +uuid = "8fc22ac5-c921-52a6-82fd-178b2807b824" +version = "0.9.0" + + [deps.FilePaths.extensions] + FilePathsGlobExt = "Glob" + FilePathsURIParserExt = "URIParser" + FilePathsURIsExt = "URIs" + + [deps.FilePaths.weakdeps] + Glob = "c27321d9-0574-5035-807b-f59d2c89b15c" + URIParser = "30578b45-9adc-5946-b283-645ec420af67" + URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" + +[[deps.FilePathsBase]] +deps = ["Compat", "Dates"] +git-tree-sha1 = "3bab2c5aa25e7840a4b065805c0cdfc01f3068d2" +uuid = "48062228-2e41-5def-b9a4-89aafe57970f" +version = "0.9.24" + + [deps.FilePathsBase.extensions] + FilePathsBaseMmapExt = "Mmap" + FilePathsBaseTestExt = "Test" + + [deps.FilePathsBase.weakdeps] + Mmap = "a63ad114-7e13-5084-954f-fe012c677804" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +version = "1.11.0" + +[[deps.FillArrays]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "5bad39456d9f0166184fce2248783dd9862645c1" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.17.0" +weakdeps = ["PDMats", "SparseArrays", "StaticArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStaticArraysExt = "StaticArrays" + FillArraysStatisticsExt = "Statistics" + +[[deps.FixedPointNumbers]] +deps = ["Random", "Statistics"] +git-tree-sha1 = "59af96b98217c6ef4ae0dfe065ac7c20831d1a84" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.6" + +[[deps.Fontconfig_jll]] +deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Zlib_jll"] +git-tree-sha1 = "f85dac9a96a01087df6e3a749840015a0ca3817d" +uuid = "a3f928ae-7b40-5064-980b-68af3947d34b" +version = "2.17.1+0" + +[[deps.Format]] +git-tree-sha1 = "9c68794ef81b08086aeb32eeaf33531668d5f5fc" +uuid = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8" +version = "1.3.7" + +[[deps.FreeType]] +deps = ["CEnum", "FreeType2_jll"] +git-tree-sha1 = "907369da0f8e80728ab49c1c7e09327bf0d6d999" +uuid = "b38be410-82b0-50bf-ab77-7b57e271db43" +version = "4.1.1" + +[[deps.FreeType2_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "70329abc09b886fd2c5d94ad2d9527639c421e3e" +uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" +version = "2.14.3+1" + +[[deps.FreeTypeAbstraction]] +deps = ["BaseDirs", "ColorVectorSpace", "Colors", "FreeType", "GeometryBasics", "Mmap"] +git-tree-sha1 = "4ebb930ef4a43817991ba35db6317a05e59abd11" +uuid = "663a7486-cb36-511b-a19d-713bb74d65c9" +version = "0.10.8" + +[[deps.FriBidi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "7a214fdac5ed5f59a22c2d9a885a16da1c74bbc7" +uuid = "559328eb-81f9-559d-9380-de523a88c83c" +version = "1.0.17+0" + +[[deps.Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" +version = "1.11.0" + +[[deps.GLM]] +deps = ["Distributions", "LinearAlgebra", "LogExpFunctions", "Printf", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsModels"] +git-tree-sha1 = "c963639ae5b9aab54f543bdc7504f42f59880bec" +uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a" +version = "1.9.5" + +[[deps.Gamma]] +deps = ["LogExpFunctions"] +git-tree-sha1 = "becc397f7cfb06e343496ae6ffb04818a851da51" +uuid = "a0844989-3bd2-4988-8bea-c9407ab0941b" +version = "1.2.0" + +[[deps.GeoFormatTypes]] +git-tree-sha1 = "7528a7956248c723d01a0a9b0447bf254bf4da52" +uuid = "68eda718-8dee-11e9-39e7-89f7f65f511f" +version = "0.4.5" + +[[deps.GeoInterface]] +deps = ["DataAPI", "Extents", "GeoFormatTypes"] +git-tree-sha1 = "20f6b13b28c6304104968374f38c24ef71a8ea16" +uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +version = "1.6.2" + + [deps.GeoInterface.extensions] + GeoInterfaceMakieExt = ["Makie", "GeometryBasics"] + GeoInterfaceRecipesBaseExt = "RecipesBase" + + [deps.GeoInterface.weakdeps] + GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" + +[[deps.GeometryBasics]] +deps = ["EarCut_jll", "LinearAlgebra", "PrecompileTools", "Random", "StaticArrays"] +git-tree-sha1 = "ec46c5825710fa1a15d468acb2d93cc939a7a5fe" +uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326" +version = "0.5.13" +weakdeps = ["Extents", "GeoInterface", "IntervalSets"] + + [deps.GeometryBasics.extensions] + ExtentsExt = "Extents" + GeometryBasicsGeoInterfaceExt = "GeoInterface" + IntervalSetsExt = "IntervalSets" + +[[deps.GettextRuntime_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll"] +git-tree-sha1 = "45288942190db7c5f760f59c04495064eedf9340" +uuid = "b0724c58-0f36-5564-988d-3bb0596ebc4a" +version = "0.22.4+0" + +[[deps.Giflib_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6570366d757b50fabae9f4315ad74d2e40c0560a" +uuid = "59f7168a-df46-5410-90c8-f2779963d0ec" +version = "5.2.3+0" + +[[deps.Glib_jll]] +deps = ["Artifacts", "GettextRuntime_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Zlib_jll"] +git-tree-sha1 = "090526e65de8f69648ac156daae153de8b56df62" +uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" +version = "2.88.3+0" + +[[deps.Graphics]] +deps = ["Colors", "LinearAlgebra", "NaNMath"] +git-tree-sha1 = "a641238db938fff9b2f60d08ed9030387daf428c" +uuid = "a2bd30eb-e257-5431-a919-1863eab51364" +version = "1.1.3" + +[[deps.Graphite2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "69ffb934a5c5b7e086a0b4fee3427db2556fba6e" +uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472" +version = "1.3.16+0" + +[[deps.GridLayoutBase]] +deps = ["GeometryBasics", "InteractiveUtils", "Observables"] +git-tree-sha1 = "ef70da5e123a06a29e2d6ddff0f09985bc226491" +uuid = "3955a311-db13-416c-9275-1d80ed98e5e9" +version = "0.11.3" + +[[deps.HarfBuzz_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll"] +git-tree-sha1 = "9d9531a9cb63a9edc33836414e82a07e81710de2" +uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566" +version = "100.14004.0+0" + +[[deps.HypergeometricFunctions]] +deps = ["Gamma", "LinearAlgebra"] +git-tree-sha1 = "31bb6c92405c084617facc1d7ed9eb6c402d061e" +uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" +version = "0.3.30" + +[[deps.ImageAxes]] +deps = ["AxisArrays", "ImageBase", "ImageCore", "Reexport", "SimpleTraits"] +git-tree-sha1 = "e12629406c6c4442539436581041d372d69c55ba" +uuid = "2803e5a7-5153-5ecf-9a86-9b4c37f5f5ac" +version = "0.6.12" + +[[deps.ImageBase]] +deps = ["ImageCore", "Reexport"] +git-tree-sha1 = "eb49b82c172811fd2c86759fa0553a2221feb909" +uuid = "c817782e-172a-44cc-b673-b171935fbb9e" +version = "0.1.7" + +[[deps.ImageCore]] +deps = ["ColorVectorSpace", "Colors", "FixedPointNumbers", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "PrecompileTools", "Reexport"] +git-tree-sha1 = "8c193230235bbcee22c8066b0374f63b5683c2d3" +uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" +version = "0.10.5" + +[[deps.ImageIO]] +deps = ["FileIO", "IndirectArrays", "JpegTurbo", "LazyModules", "Netpbm", "OpenEXR", "PNGFiles", "QOI", "Sixel", "TiffImages", "UUIDs", "WebP"] +git-tree-sha1 = "f0f005f997dfb8c5fe23920d99458a9619873893" +uuid = "82e4d734-157c-48bb-816b-45c225c6df19" +version = "0.6.10" + +[[deps.ImageMetadata]] +deps = ["AxisArrays", "ImageAxes", "ImageBase", "ImageCore"] +git-tree-sha1 = "2a81c3897be6fbcde0802a0ebe6796d0562f63ec" +uuid = "bc367c6b-8a6b-528e-b4bd-a4b897500b49" +version = "0.9.10" + +[[deps.Imath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "dcc8d0cd653e55213df9b75ebc6fe4a8d3254c65" +uuid = "905a6f67-0a94-5f89-b386-d35d92009cd1" +version = "3.2.2+0" + +[[deps.Indexing]] +git-tree-sha1 = "ce1566720fd6b19ff3411404d4b977acd4814f9f" +uuid = "313cdc1a-70c2-5d6a-ae34-0150d3930a38" +version = "1.1.1" + +[[deps.IndirectArrays]] +git-tree-sha1 = "012e604e1c7458645cb8b436f8fba789a51b257f" +uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959" +version = "1.0.0" + +[[deps.Inflate]] +git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d" +uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" +version = "0.1.5" + +[[deps.InlineStrings]] +git-tree-sha1 = "06b65886c7577a3784d616e29f1302c2e36e389d" +uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" +version = "1.4.6" + + [deps.InlineStrings.extensions] + ArrowTypesExt = "ArrowTypes" + ParsersExt = "Parsers" + + [deps.InlineStrings.weakdeps] + ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" + Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" + +[[deps.IntegerMathUtils]] +git-tree-sha1 = "c72458f1962faeb003bf23cbdb75164fe6280906" +uuid = "18e54dd8-cb9d-406c-a71d-865a43cbb235" +version = "0.1.4" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +version = "1.11.0" + +[[deps.Interpolations]] +deps = ["Adapt", "AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"] +git-tree-sha1 = "48922d06068130f87e43edef52382e6a94305ae6" +uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" +version = "0.16.3" + + [deps.Interpolations.extensions] + InterpolationsForwardDiffExt = "ForwardDiff" + InterpolationsUnitfulExt = "Unitful" + + [deps.Interpolations.weakdeps] + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.IntervalArithmetic]] +deps = ["CRlibm", "CoreMath", "MacroTools", "OpenBLASConsistentFPCSR_jll", "Printf", "Random", "RoundingEmulator"] +git-tree-sha1 = "1c531bf0f8a5c60a340926e058fd3f209b5eef5d" +uuid = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" +version = "1.0.12" + + [deps.IntervalArithmetic.extensions] + IntervalArithmeticArblibExt = "Arblib" + IntervalArithmeticDiffRulesExt = "DiffRules" + IntervalArithmeticForwardDiffExt = "ForwardDiff" + IntervalArithmeticIntervalSetsExt = "IntervalSets" + IntervalArithmeticIrrationalConstantsExt = "IrrationalConstants" + IntervalArithmeticLinearAlgebraExt = "LinearAlgebra" + IntervalArithmeticMakieExt = "Makie" + IntervalArithmeticRecipesBaseExt = "RecipesBase" + IntervalArithmeticSparseArraysExt = "SparseArrays" + + [deps.IntervalArithmetic.weakdeps] + Arblib = "fb37089c-8514-4489-9461-98f9c8763369" + DiffRules = "b552c78f-8df3-52c6-915a-8e097449b14b" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + IrrationalConstants = "92d709cd-6900-40b7-9082-c6be49f344b6" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.IntervalSets]] +git-tree-sha1 = "79d6bd28c8d9bccc2229784f1bd637689b256377" +uuid = "8197267c-284f-5f27-9208-e0e47529a953" +version = "0.7.14" + + [deps.IntervalSets.extensions] + IntervalSetsRandomExt = "Random" + IntervalSetsRecipesBaseExt = "RecipesBase" + IntervalSetsStatisticsExt = "Statistics" + + [deps.IntervalSets.weakdeps] + Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" + Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[deps.InverseFunctions]] +git-tree-sha1 = "a779299d77cd080bf77b97535acecd73e1c5e5cb" +uuid = "3587e190-3f89-42d0-90ee-14403ec27112" +version = "0.1.17" + + [deps.InverseFunctions.extensions] + InverseFunctionsDatesExt = "Dates" + InverseFunctionsTestExt = "Test" + + [deps.InverseFunctions.weakdeps] + Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.InvertedIndices]] +git-tree-sha1 = "6da3c4316095de0f5ee2ebd875df8721e7e0bdbe" +uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" +version = "1.3.1" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "b2d91fe939cae05960e760110b328288867b5758" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.6" + +[[deps.Isoband]] +deps = ["isoband_jll"] +git-tree-sha1 = "f9b6d97355599074dc867318950adaa6f9946137" +uuid = "f1662d9f-8043-43de-a69a-05efc1cc6ff4" +version = "0.1.1" + +[[deps.IterTools]] +git-tree-sha1 = "42d5f897009e7ff2cf88db414a389e5ed1bdd023" +uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" +version = "1.10.0" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7204148362dafe5fe6a273f855b8ccbe4df8173e" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.8.0" + +[[deps.JSON]] +deps = ["Dates", "Logging", "Parsers", "PrecompileTools", "StructUtils", "UUIDs", "Unicode"] +git-tree-sha1 = "633b5a34494e711f694ccbc88a6e00102f10238c" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "1.9.0" + + [deps.JSON.extensions] + JSONArrowExt = ["ArrowTypes"] + + [deps.JSON.weakdeps] + ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" + +[[deps.JpegTurbo]] +deps = ["CEnum", "FileIO", "ImageCore", "JpegTurbo_jll", "TOML"] +git-tree-sha1 = "9496de8fb52c224a2e3f9ff403947674517317d9" +uuid = "b835a17e-a41a-41e7-81f0-2f016b05efe0" +version = "0.1.6" + +[[deps.JpegTurbo_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "037babc10853eeb8e585418922246cb97b8e5b74" +uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" +version = "3.2.0+1" + +[[deps.JuliaSyntaxHighlighting]] +deps = ["StyledStrings"] +uuid = "ac6e5ff7-fb65-4e79-a425-ec3bc9c03011" +version = "1.12.0" + +[[deps.KernelDensity]] +deps = ["Distributions", "DocStringExtensions", "FFTA", "Interpolations", "StatsBase"] +git-tree-sha1 = "9eda8292dd3268b3b7ec9df21bbfac24e177ec52" +uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b" +version = "0.6.12" + +[[deps.LAME_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "059aabebaa7c82ccb853dd4a0ee9d17796f7e1bc" +uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d" +version = "3.100.3+0" + +[[deps.LERC_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "39bca05343661c347aae0bca57a5994a0bf4f08d" +uuid = "88015f11-f218-50d7-93a8-a6af411a945d" +version = "4.2.0+0" + +[[deps.LLVMOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e5b100780d4d30d63b4618d7930d48af409c1772" +uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" +version = "23.1.1+0" + +[[deps.LaTeXStrings]] +git-tree-sha1 = "f88f3ccef05a6a72a0cf0ed417c8fd68530f4ab2" +uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +version = "1.4.1" + +[[deps.LazyModules]] +git-tree-sha1 = "a560dd966b386ac9ae60bdd3a3d3a326062d3c3e" +uuid = "8cdb02fc-e678-4876-92c5-9defec4f444e" +version = "0.3.1" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "OpenSSL_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.15.0+0" + +[[deps.LibGit2]] +deps = ["LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +version = "1.11.0" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "OpenSSL_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.9.0+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "OpenSSL_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.3+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +version = "1.11.0" + +[[deps.Libffi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "c8da7e6a91781c41a863611c7e966098d783c57a" +uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490" +version = "3.4.7+0" + +[[deps.Libglvnd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll", "Xorg_libXext_jll"] +git-tree-sha1 = "d36c21b9e7c172a44a10484125024495e2625ac0" +uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29" +version = "1.7.1+1" + +[[deps.Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "be484f5c92fad0bd8acfef35fe017900b0b73809" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.18.0+0" + +[[deps.Libmount_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "cc3ad4faf30015a3e8094c9b5b7f19e85bdf2386" +uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" +version = "2.42.0+0" + +[[deps.Libtiff_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "aebd334d06cee9f24cea70bd19a39749daf73881" +uuid = "89763e89-9b03-5906-acba-b20f662cd828" +version = "4.7.3+0" + +[[deps.Libuuid_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d620582b1f0cbe2c72dd1d5bd195a9ce73370ab1" +uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700" +version = "2.42.0+0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +version = "1.12.0" + +[[deps.Loess]] +deps = ["Distances", "LinearAlgebra", "Statistics", "StatsAPI", "StatsFuns"] +git-tree-sha1 = "aac61f60ed2b1561ae1bbef4e6d7b75c27f1f9e3" +uuid = "4345ca2d-374a-55d4-8d30-97f9976e7612" +version = "0.6.6" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "bba2d9aa057d8f126415de240573e86a8f39d2a1" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "1.0.1" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" + +[[deps.MacroTools]] +git-tree-sha1 = "1e0228a030642014fe5cfe68c2c0a818f9e3f522" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.16" + +[[deps.Makie]] +deps = ["Animations", "Base64", "CRC32c", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "ComputePipeline", "Contour", "Dates", "DelaunayTriangulation", "Distributions", "DocStringExtensions", "Downloads", "FFMPEG_jll", "FileIO", "FilePaths", "FixedPointNumbers", "Format", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageBase", "ImageIO", "InteractiveUtils", "Interpolations", "IntervalSets", "InverseFunctions", "Isoband", "KernelDensity", "LaTeXStrings", "LinearAlgebra", "MacroTools", "Markdown", "MathTeXEngine", "Observables", "OffsetArrays", "PNGFiles", "Packing", "Pkg", "PlotUtils", "PolygonOps", "PrecompileTools", "Printf", "REPL", "Random", "RelocatableFolders", "Scratch", "ShaderAbstractions", "SignedDistanceFields", "SparseArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "TriplotBase", "UnicodeFun", "Unitful"] +git-tree-sha1 = "5f6f5d1b1fb7ff98c9a083bbfd4c661a9808e758" +uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" +version = "0.24.15" + + [deps.Makie.extensions] + MakieDynamicQuantitiesExt = "DynamicQuantities" + + [deps.Makie.weakdeps] + DynamicQuantities = "06fc5a27-2a28-4c7c-a15d-362465fb6821" + +[[deps.MappedArrays]] +git-tree-sha1 = "0ee4497a4e80dbd29c058fcee6493f5219556f40" +uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900" +version = "0.4.3" + +[[deps.Markdown]] +deps = ["Base64", "JuliaSyntaxHighlighting", "StyledStrings"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" + +[[deps.MathTeXEngine]] +deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "UnicodeFun"] +git-tree-sha1 = "aa1078778be5a8e5259ff04fbc3d258b3e78d464" +uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53" +version = "0.6.9" + +[[deps.Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.2.0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" +version = "1.11.0" + +[[deps.MosaicViews]] +deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"] +git-tree-sha1 = "7b86a5d4d70a9f5cdf2dacb3cbe6d251d1a61dbe" +uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389" +version = "0.3.4" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2025.11.4" + +[[deps.MuladdMacro]] +deps = ["PrecompileTools"] +git-tree-sha1 = "283bf85d4a767481dd924dff0eee1735e95f449e" +uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" +version = "0.2.7" + +[[deps.NaNMath]] +deps = ["OpenLibm_jll"] +git-tree-sha1 = "dbd2e8cd2c1c27f0b584f6661b4309609c5a685e" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "1.1.4" + +[[deps.NaturalSort]] +git-tree-sha1 = "eda490d06b9f7c00752ee81cfa451efe55521e21" +uuid = "c020b1a1-e9b0-503a-9c33-f039bfc54a85" +version = "1.0.0" + +[[deps.Netpbm]] +deps = ["FileIO", "ImageCore", "ImageMetadata"] +git-tree-sha1 = "d92b107dbb887293622df7697a2223f9f8176fcd" +uuid = "f09324ee-3d7c-5217-9330-fc30815ba969" +version = "1.1.1" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.3.0" + +[[deps.Observables]] +git-tree-sha1 = "7438a59546cf62428fc9d1bc94729146d37a7225" +uuid = "510215fc-4207-5dde-b226-833fc4488ee2" +version = "0.5.5" + +[[deps.OffsetArrays]] +git-tree-sha1 = "117432e406b5c023f665fa73dc26e79ec3630151" +uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +version = "1.17.0" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" + +[[deps.Ogg_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "b6aa4566bb7ae78498a5e68943863fa8b5231b59" +uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" +version = "1.3.6+0" + +[[deps.OpenBLASConsistentFPCSR_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "38a93f17e431141c6470bb67a88952a7c4f0e928" +uuid = "6cdc7f73-28fd-5e50-80fb-958a8875b1af" +version = "0.3.34+0" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.29+0" + +[[deps.OpenEXR]] +deps = ["Colors", "FileIO", "OpenEXR_jll"] +git-tree-sha1 = "97db9e07fe2091882c765380ef58ec553074e9c7" +uuid = "52e1d378-f018-4a11-a4be-720524705ac7" +version = "0.3.3" + +[[deps.OpenEXR_jll]] +deps = ["Artifacts", "Imath_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "1bcebd887dd33f1108210b3954049b1bb8af0e7a" +uuid = "18a262bb-aa17-5467-a713-aee519bc75cb" +version = "3.4.15+0" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.7+0" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.5.4+0" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1346c9208249809840c91b26703912dff463d335" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.6+0" + +[[deps.Opus_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e2bb57a313a74b8104064b7efd01406c0a50d2ff" +uuid = "91d4177d-7536-5919-b921-800302f37372" +version = "1.6.1+0" + +[[deps.OrderedCollections]] +git-tree-sha1 = "05f45c2e0de6259db764adbfd2f1dc6d3f8de13c" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "2.0.1" + +[[deps.PCRE2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" +version = "10.44.0+1" + +[[deps.PDMats]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "123266c25174ef6c8d4718920abc206452cf8de6" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.11.41" +weakdeps = ["StatsBase"] + + [deps.PDMats.extensions] + StatsBaseExt = "StatsBase" + +[[deps.PNGFiles]] +deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"] +git-tree-sha1 = "32b657a0d57c310a1a172bfc8c8cf68c5e674323" +uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883" +version = "0.4.5" + +[[deps.Packing]] +deps = ["GeometryBasics"] +git-tree-sha1 = "bc5bf2ea3d5351edf285a06b0016788a121ce92c" +uuid = "19eb6ba3-879d-56ad-ad62-d5c202156566" +version = "0.5.1" + +[[deps.PaddedViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "0fac6313486baae819364c52b4f483450a9d793f" +uuid = "5432bcbf-9aad-5242-b902-cca2824c8663" +version = "0.5.12" + +[[deps.Pango_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1912a9f1b9ca55005b03ba075f8e19993583e237" +uuid = "36c8627f-9965-5494-a995-c6b170f724f3" +version = "1.58.2+0" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools"] +git-tree-sha1 = "663e8b48b789916221e0765393b289ca6c88f24e" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "3.0.0" + +[[deps.Pixman_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "Libdl"] +git-tree-sha1 = "e4a6721aa89e62e5d4217c0b21bd714263779dda" +uuid = "30392449-352a-5448-841d-b1acce4e97dc" +version = "0.46.4+0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.12.1" +weakdeps = ["REPL"] + + [deps.Pkg.extensions] + REPLExt = "REPL" + +[[deps.PkgVersion]] +deps = ["Pkg"] +git-tree-sha1 = "f9501cc0430a26bc3d156ae1b5b0c1b47af4d6da" +uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688" +version = "0.3.3" + +[[deps.PlotUtils]] +deps = ["ColorSchemes", "Colors", "Dates", "PrecompileTools", "Printf", "Reexport", "Statistics"] +git-tree-sha1 = "f20e945b895d2009c6c28d8bbf40a5cd846f7c2f" +uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" +version = "1.5.0" + +[[deps.PolygonOps]] +git-tree-sha1 = "77b3d3605fc1cd0b42d95eba87dfcd2bf67d5ff6" +uuid = "647866c9-e3ac-4575-94e7-e3d426903924" +version = "0.1.2" + +[[deps.PooledArrays]] +deps = ["DataAPI", "Future"] +git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" +uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +version = "1.4.3" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "edbeefc7a4889f528644251bdb5fc9ab5348bc2c" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.3.4" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "5005266de4bfe50e53ff44a5cb5c540b6e47a254" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.6.0" + +[[deps.PrettyTables]] +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "1b8aa19f229b1cea7fc93874a52e49db6a854450" +uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +version = "3.4.8" + + [deps.PrettyTables.extensions] + PrettyTablesExcelExt = "XLSX" + PrettyTablesTypstryExt = "Typstry" + + [deps.PrettyTables.weakdeps] + Typstry = "f0ed7684-a786-439e-b1e3-3b82803b501e" + XLSX = "fdbf4ff8-1666-58a4-91e7-1b58723a45e0" + +[[deps.Primes]] +deps = ["IntegerMathUtils"] +git-tree-sha1 = "25cdd1d20cd005b52fc12cb6be3f75faaf59bb9b" +uuid = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" +version = "0.5.7" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" + +[[deps.ProgressMeter]] +deps = ["Distributed", "Printf"] +git-tree-sha1 = "fbb92c6c56b34e1a2c4c36058f68f332bec840e7" +uuid = "92933f4c-e287-5a05-a399-4b506db050ca" +version = "1.11.0" + +[[deps.PtrArrays]] +git-tree-sha1 = "4fbbafbc6251b883f4d2705356f3641f3652a7fe" +uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" +version = "1.4.0" + +[[deps.QOI]] +deps = ["ColorTypes", "FileIO", "FixedPointNumbers"] +git-tree-sha1 = "472daaa816895cb7aee81658d4e7aec901fa1106" +uuid = "4b34888f-f399-49d4-9bb3-47ed5cae4e65" +version = "1.0.2" + +[[deps.QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "5e8e8b0ab68215d7a2b14b9921a946fee794749e" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.11.3" + + [deps.QuadGK.extensions] + QuadGKEnzymeExt = "Enzyme" + + [deps.QuadGK.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + +[[deps.REPL]] +deps = ["InteractiveUtils", "JuliaSyntaxHighlighting", "Markdown", "Sockets", "StyledStrings", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +version = "1.11.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" + +[[deps.RangeArrays]] +git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5" +uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d" +version = "0.3.2" + +[[deps.Ratios]] +deps = ["Requires"] +git-tree-sha1 = "1342a47bf3260ee108163042310d26f2be5ec90b" +uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" +version = "0.4.5" +weakdeps = ["FixedPointNumbers"] + + [deps.Ratios.extensions] + RatiosFixedPointNumbersExt = "FixedPointNumbers" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.RelocatableFolders]] +deps = ["SHA", "Scratch"] +git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" +uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" +version = "1.0.1" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.1" + +[[deps.Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "5b3d50eb374cea306873b371d3f8d3915a018f0b" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.9.0" + +[[deps.Rmath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6d40b2fe70437b01397d2a4d5b020008da4e7019" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.5.2+0" + +[[deps.Roots]] +deps = ["Accessors", "CommonSolve", "Printf"] +git-tree-sha1 = "4db094d5e079abbda658acfe1c4d098430417717" +uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" +version = "3.0.8" + + [deps.Roots.extensions] + RootsChainRulesCoreExt = "ChainRulesCore" + RootsForwardDiffExt = "ForwardDiff" + RootsIntervalRootFindingExt = "IntervalRootFinding" + RootsSymPyExt = "SymPy" + RootsSymPyPythonCallExt = "SymPyPythonCall" + RootsUnitfulExt = "Unitful" + + [deps.Roots.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" + SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" + SymPyPythonCall = "bc8888f7-b21e-4b7c-a06a-5d9c9496438c" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.RoundingEmulator]] +git-tree-sha1 = "40b9edad2e5287e05bd413a38f61a8ff55b9557b" +uuid = "5eaf0fd0-dfba-4ccb-bf02-d820a40db705" +version = "0.2.1" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.SIMD]] +deps = ["PrecompileTools"] +git-tree-sha1 = "e24dc23107d426a096d3eae6c165b921e74c18e4" +uuid = "fdea26ae-647d-5447-a871-4b548cad5224" +version = "3.7.2" + +[[deps.Scratch]] +deps = ["Dates"] +git-tree-sha1 = "9b81b8393e50b7d4e6d0a9f14e192294d3b7c109" +uuid = "6c6a2e73-6563-6170-7368-637461726353" +version = "1.3.0" + +[[deps.SentinelArrays]] +deps = ["Dates", "Random"] +git-tree-sha1 = "084c47c7c5ce5cfecefa0a98dff69eb3646b5a80" +uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" +version = "1.4.10" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +version = "1.11.0" + +[[deps.ShaderAbstractions]] +deps = ["ColorTypes", "FixedPointNumbers", "GeometryBasics", "LinearAlgebra", "Observables", "StaticArrays"] +git-tree-sha1 = "57aa595158717ef165e6f5ab639fe2e3178c0a2b" +uuid = "65257c39-d410-5151-9873-9b3e5be5013e" +version = "0.5.1" + +[[deps.SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" +version = "1.11.0" + +[[deps.ShiftedArrays]] +git-tree-sha1 = "503688b59397b3307443af35cd953a13e8005c16" +uuid = "1277b4bf-5013-50f5-be3d-901d8477a67a" +version = "2.0.0" + +[[deps.SignedDistanceFields]] +deps = ["Statistics"] +git-tree-sha1 = "3949ad92e1c9d2ff0cd4a1317d5ecbba682f4b92" +uuid = "73760f76-fbc4-59ce-8f25-708e95d2df96" +version = "0.4.1" + +[[deps.SimpleTraits]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "7ddb0b49c109481b046972c0e4ab02b2127d6a75" +uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +version = "0.9.6" + +[[deps.Sixel]] +deps = ["Dates", "FileIO", "ImageCore", "IndirectArrays", "OffsetArrays", "REPL", "libsixel_jll"] +git-tree-sha1 = "0494aed9501e7fb65daba895fb7fd57cc38bc743" +uuid = "45858cf5-a6b0-47a3-bbea-62219f50df47" +version = "0.1.5" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" +version = "1.11.0" + +[[deps.SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "13cd91cc9be159e3f4d95b857fa2aa383b53772a" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.2.3" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.12.0" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "429071b23f4c9a13fb6582f807cc2ef454082408" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.9.0" +weakdeps = ["ChainRulesCore"] + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + +[[deps.StackViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "be1cf4eb0ac528d96f5115b4ed80c26a8d8ae621" +uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15" +version = "0.1.2" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "39e70e0ab5d7f89833a62ab7c79df15d4fc417c1" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.9.22" +weakdeps = ["ChainRulesCore", "Statistics"] + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "6ab403037779dae8c514bad259f32a447262455a" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.4" + +[[deps.Statistics]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "e2b53ce13a53367e96601081e33d34746b571bad" +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.11.5" +weakdeps = ["SparseArrays"] + + [deps.Statistics.extensions] + SparseArraysExt = ["SparseArrays"] + +[[deps.StatsAPI]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "178ed29fd5b2a2cfc3bd31c13375ae925623ff36" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.8.0" + +[[deps.StatsBase]] +deps = ["AliasTables", "DataAPI", "DataStructures", "IrrationalConstants", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "adb9da019510162e67a4493fc235c23203d8b09e" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.34.13" + +[[deps.StatsFuns]] +deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] +git-tree-sha1 = "91a5737baed20ee31f3faea0e51f57461f6a689e" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "2.2.1" +weakdeps = ["ChainRulesCore", "InverseFunctions"] + + [deps.StatsFuns.extensions] + StatsFunsChainRulesCoreExt = "ChainRulesCore" + StatsFunsInverseFunctionsExt = "InverseFunctions" + +[[deps.StatsModels]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "REPL", "ShiftedArrays", "SparseArrays", "StatsAPI", "StatsBase", "StatsFuns", "Tables"] +git-tree-sha1 = "0db41c4e0d9f3fa195395a6401a8290752c9cd3d" +uuid = "3eaba693-59b7-5ba5-a881-562e759f1c8d" +version = "0.7.10" + +[[deps.StringManipulation]] +deps = ["PrecompileTools"] +git-tree-sha1 = "773065c6e0e903924a9d838259be74338422aef2" +uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" +version = "0.5.0" + +[[deps.StructArrays]] +deps = ["ConstructionBase", "DataAPI", "Tables"] +git-tree-sha1 = "ad8002667372439f2e3611cfd14097e03fa4bccd" +uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +version = "0.7.3" + + [deps.StructArrays.extensions] + StructArraysAdaptExt = "Adapt" + StructArraysGPUArraysCoreExt = ["GPUArraysCore", "KernelAbstractions"] + StructArraysLinearAlgebraExt = "LinearAlgebra" + StructArraysSparseArraysExt = "SparseArrays" + StructArraysStaticArraysExt = "StaticArrays" + + [deps.StructArrays.weakdeps] + Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" + GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" + KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.StructUtils]] +deps = ["Dates", "UUIDs"] +git-tree-sha1 = "b814d5005d6a529d740ffe06f8a86396f6501138" +uuid = "ec057cc2-7a8d-4b58-b3b3-92acb9f63b42" +version = "2.9.2" + + [deps.StructUtils.extensions] + StructUtilsLazilyInitializedFieldsExt = ["LazilyInitializedFields"] + StructUtilsMeasurementsExt = ["Measurements"] + StructUtilsStaticArraysCoreExt = ["StaticArraysCore"] + StructUtilsTablesExt = ["Tables"] + + [deps.StructUtils.weakdeps] + LazilyInitializedFields = "0e77f7df-68c5-4e49-93ce-4cd80f5598bf" + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" + Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" + +[[deps.StyledStrings]] +uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" +version = "1.11.0" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "7.8.3+2" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "a94d9bdda1b7bed0046cea645639ab3f62196fac" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.14.0" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.TensorCore]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" +uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" +version = "0.1.1" + +[[deps.TiffImages]] +deps = ["CodecZstd", "ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "PrecompileTools", "ProgressMeter", "SIMD", "UUIDs"] +git-tree-sha1 = "9ca5f1f2d42f80df4b8c9f6ab5a64f438bbd9976" +uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69" +version = "0.11.9" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.11.3" + +[[deps.TriplotBase]] +git-tree-sha1 = "4d4ed7f294cda19382ff7de4c137d24d16adc89b" +uuid = "981d1d27-644d-49a2-9326-4793e63143c3" +version = "0.1.0" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +version = "1.11.0" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" + +[[deps.UnicodeFun]] +deps = ["REPL"] +git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf" +uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1" +version = "0.4.1" + +[[deps.Unitful]] +deps = ["Dates", "LinearAlgebra", "Random"] +git-tree-sha1 = "1f0f9f401753701a7e4113b5056ca38d33875b55" +uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" +version = "1.29.0" + + [deps.Unitful.extensions] + ConstructionBaseUnitfulExt = "ConstructionBase" + ForwardDiffExt = "ForwardDiff" + InverseFunctionsUnitfulExt = "InverseFunctions" + LatexifyExt = ["Latexify", "LaTeXStrings"] + NaNMathExt = "NaNMath" + PrintfExt = "Printf" + + [deps.Unitful.weakdeps] + ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" + Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" + NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" + Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.WebP]] +deps = ["CEnum", "ColorTypes", "FileIO", "FixedPointNumbers", "ImageCore", "libwebp_jll"] +git-tree-sha1 = "aa1ca3c47f119fbdae8770c29820e5e6119b83f2" +uuid = "e3aaa7dc-3e4b-44e0-be63-ffb868ccd7c1" +version = "0.1.3" + +[[deps.WoodburyMatrices]] +deps = ["LinearAlgebra", "SparseArrays"] +git-tree-sha1 = "248a7031b3da79a127f14e5dc5f417e26f9f6db7" +uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6" +version = "1.1.0" + +[[deps.XZ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e52eca002a11c30a858185efdfb15311e1c7a6bf" +uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800" +version = "5.8.4+0" + +[[deps.Xorg_libX11_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] +git-tree-sha1 = "808090ede1d41644447dd5cbafced4731c56bd2f" +uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" +version = "1.8.13+0" + +[[deps.Xorg_libXau_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "aa1261ebbac3ccc8d16558ae6799524c450ed16b" +uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" +version = "1.0.13+0" + +[[deps.Xorg_libXdmcp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "52858d64353db33a56e13c341d7bf44cd0d7b309" +uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" +version = "1.1.6+0" + +[[deps.Xorg_libXext_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "1a4a26870bf1e5d26cd585e38038d399d7e65706" +uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3" +version = "1.3.8+0" + +[[deps.Xorg_libXfixes_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "75e00946e43621e09d431d9b95818ee751e6b2ef" +uuid = "d091e8ba-531a-589c-9de9-94069b037ed8" +version = "6.0.2+0" + +[[deps.Xorg_libXrender_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "7ed9347888fac59a618302ee38216dd0379c480d" +uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" +version = "0.9.12+0" + +[[deps.Xorg_libpciaccess_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "58972370b81423fc546c56a60ed1a009450177c3" +uuid = "a65dc6b1-eb27-53a1-bb3e-dea574b5389e" +version = "0.19.0+0" + +[[deps.Xorg_libxcb_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libXau_jll", "Xorg_libXdmcp_jll"] +git-tree-sha1 = "bfcaf7ec088eaba362093393fe11aa141fa15422" +uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" +version = "1.17.1+0" + +[[deps.Xorg_xtrans_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "a63799ff68005991f9d9491b6e95bd3478d783cb" +uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" +version = "1.6.0+0" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.3.1+2" + +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "446b23e73536f84e8037f5dce465e92275f6a308" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.7+1" + +[[deps.isoband_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "51b5eeb3f98367157a7a12a1fb0aa5328946c03c" +uuid = "9a68df92-36a6-505f-a73e-abb412b6bfb4" +version = "0.2.3+0" + +[[deps.libaom_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "ef17c47d22224aaecc76e597ab21a072e025cf7b" +uuid = "a4ae2306-e953-59d6-aa16-d00cac43593b" +version = "3.14.1+0" + +[[deps.libass_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "cb007192783c56d8249db4cf0e3495001edfe414" +uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0" +version = "0.17.5+0" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.15.0+0" + +[[deps.libdrm_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libpciaccess_jll"] +git-tree-sha1 = "28e57478e8a160d346a19c28b3fffb9273bcc9c2" +uuid = "8e53e030-5e6c-5a89-a30b-be5b7263a166" +version = "2.4.134+0" + +[[deps.libfdk_aac_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "646634dd19587a56ee2f1199563ec056c5f228df" +uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" +version = "2.0.4+0" + +[[deps.libpng_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "e51150d5ab85cee6fc36726850f0e627ad2e4aba" +uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" +version = "1.6.58+0" + +[[deps.libsixel_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "libpng_jll"] +git-tree-sha1 = "c1733e347283df07689d71d61e14be986e49e47a" +uuid = "075b6546-f08a-558a-be8f-8157d0f608a5" +version = "1.10.5+0" + +[[deps.libva_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll", "Xorg_libXext_jll", "Xorg_libXfixes_jll", "libdrm_jll"] +git-tree-sha1 = "7dbf96baae3310fe2fa0df0ccbb3c6288d5816c9" +uuid = "9a156e7d-b971-5f62-b2c9-67348b8fb97c" +version = "2.23.0+0" + +[[deps.libvorbis_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll"] +git-tree-sha1 = "11e1772e7f3cc987e9d3de991dd4f6b2602663a5" +uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" +version = "1.3.8+0" + +[[deps.libwebp_jll]] +deps = ["Artifacts", "Giflib_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libglvnd_jll", "Libtiff_jll", "libpng_jll"] +git-tree-sha1 = "4e4282c4d846e11dce56d74fa8040130b7a95cb3" +uuid = "c5f90fcd-3b7e-5836-afba-fc50a0988cb2" +version = "1.6.0+0" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.64.0+1" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.7.0+0" + +[[deps.x264_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "14cc7083fc6dff3cc44f2bc435ee96d06ed79aa7" +uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a" +version = "10164.0.1+0" + +[[deps.x265_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e7b67590c14d487e734dcb925924c5dc43ec85f3" +uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76" +version = "4.1.0+0" +""" + +# ╔═╡ Cell order: +# ╠═4c14aad4-bb94-11f1-90df-4d61c6cdbcfe +# ╟─5e83c41a-85f0-4095-92d2-5ceeb6d10408 +# ╠═6c1424e5-60a9-406d-b3b5-66eabec2ad44 +# ╠═91976867-0ecd-4d32-abc7-f64c817e6894 +# ╠═4e2857e6-0765-422c-a22a-7ea60c91ce57 +# ╠═7c3a0227-12da-4440-bb2d-f5fb37dba4ee +# ╠═dece6392-d991-440d-97e1-9f51c30570d0 +# ╠═1164a037-20ce-4731-bbb2-80e6bdddd495 +# ╠═7023db0d-ad08-4e7a-9c0d-e04f0b49dd57 +# ╠═11d16508-1718-4ade-b713-2809b8d7be3d +# ╠═0eea9b04-1741-47f2-9c45-1bedc8a08769 +# ╠═f221ca13-ad01-480b-a923-c7e9eaaff71b +# ╠═7b38d542-57d9-4f1a-af35-1bf1a39a9b3f +# ╠═d9a02b4d-ee72-40a3-9be2-fad6256ce600 +# ╠═6e70799b-3271-4dbf-85e9-ded8ac07bbc9 +# ╠═2babdf19-d03a-4223-8cb0-c9b8a4510fd1 +# ╠═4ad6cf74-42d3-44f5-b694-3b2f005bfda3 +# ╠═7249e211-b3d0-41f8-a5b2-40c5076c81f5 +# ╠═fcfb2fd2-e8a5-414e-b3d2-b208123ad874 +# ╟─00000000-0000-0000-0000-000000000001 +# ╟─00000000-0000-0000-0000-000000000002 diff --git a/benchmarking/notebook.jl b/benchmarking/notebook.jl deleted file mode 100644 index 77233cb..0000000 --- a/benchmarking/notebook.jl +++ /dev/null @@ -1,68 +0,0 @@ -### A Pluto.jl notebook ### -# v0.20.24 - -using Markdown -using InteractiveUtils - -# ╔═╡ 434324c8-8a87-11f1-adb0-599460332cfd -begin - using Pkg - Pkg.activate(".") - Pkg.add(["CSV", "DataFrames", "Chain", "CairoMakie", "AlgebraOfGraphics"]) - - using CSV - using DataFrames - using Chain - using CairoMakie - using AlgebraOfGraphics -end - -# ╔═╡ 39f4659c-fd34-444d-8cbd-1fa73468ffd4 -df = CSV.read("/Users/carlos/git/KEGGAPI.jl/benchmarking/benchmark_compare.csv", DataFrame) - -# ╔═╡ 1b2ff946-cfca-4e81-9391-cdfe7054fdf5 -name_map = Dict( - "KEGGAPI.jl" => "KEGGAPI.jl", - "KEGGREST (R)" => "KEGGREST", - "Bio.KEGG.REST (Python)" => "Bio.KEGG", - "curl" => "curl" -) - -# ╔═╡ 5807e3a7-e12f-4ce4-b19b-37f281397904 -let - px = 250 - set_theme!(theme_minimal()) - f = draw( - data(filter(r -> r.Function != "getseq", eachrow(df))) - * mapping( - :Language => (x -> name_map[String(x)]) => "", - :Median => "Seconds per call (median)", - col = :Function => presorted, - color = :Language - ) - * visual( - BarPlot, - direction = :x, - bar_labels = :y, - flip_labels_at = (0, 1.1), - label_formatter = x -> trunc(x, digits = 2) - ), - - scales(; - Y = (; categories = ["KEGGAPI.jl", "KEGGREST", "Bio.KEGG", "curl"] |> reverse), - Color = (; palette = ["gainsboro", "#0031a9", "gainsboro", "gainsboro"]) - ), - figure = (; size = (4 * px, px)), - axis = (; limits = (0, nothing, nothing, nothing), xticks = [-1], bottomspinevisible = false), - legend = (; show = false), - facet = (; linkxaxes = :none) - ) - save("benchmark.svg", f) - f -end - -# ╔═╡ Cell order: -# ╠═434324c8-8a87-11f1-adb0-599460332cfd -# ╠═39f4659c-fd34-444d-8cbd-1fa73468ffd4 -# ╠═1b2ff946-cfca-4e81-9391-cdfe7054fdf5 -# ╠═5807e3a7-e12f-4ce4-b19b-37f281397904 diff --git a/benchmarking/plot_benchmarks.jl b/benchmarking/plot_benchmarks.jl old mode 100644 new mode 100755 index b004aa5..4b7a5ca --- a/benchmarking/plot_benchmarks.jl +++ b/benchmarking/plot_benchmarks.jl @@ -1,62 +1,51 @@ #!/usr/bin/env julia -# -# Render benchmark_compare.csv to benchmark_compare.png (the figure used in the -# README). -# -# julia --project=benchmarking benchmarking/plot_benchmarks.jl -# +# Render the request-time distributions in benchmark_compare.csv. using DelimitedFiles using Plots -using Plots.PlotMeasures # provides `mm` for margins -using StatsPlots # provides `groupedbar` +using Plots.PlotMeasures +using StatsPlots const BENCHDIR = @__DIR__ const CSV = joinpath(BENCHDIR, "benchmark_compare.csv") +const CANONICAL = ["info", "list", "find", "get", "getseq", "conv", "link", "ddi"] isfile(CSV) || error("$CSV not found. Run run_benchmarks.jl first.") +raw, header = readdlm(CSV, ',', String, header = true) +vec(header) == ["Function", "Request", "Language", "Seconds"] || error("Unexpected columns in $CSV") -# Read as text so blank medians (unsupported/skipped pairs) survive parsing. -raw, _ = readdlm(CSV, ',', String, header = true) functions = strip.(raw[:, 1]) -languages = strip.(raw[:, 2]) -medians = [isempty(strip(s)) ? NaN : parse(Float64, strip(s)) for s in raw[:, 3]] +languages = strip.(raw[:, 3]) +seconds = parse.(Float64, strip.(raw[:, 4])) +all(isfinite, seconds) && all(>=(0), seconds) || + error("Benchmark timings must be finite and nonnegative") -# One grouped bar per operation, one series per interface. Operations follow the -# canonical KEGG order rather than the CSV's order; anything not listed is -# appended so new cases still plot. -const CANONICAL = ["info", "list", "find", "get", "getseq", "conv", "link", "ddi"] present = unique(functions) -fn_order = [f for f in CANONICAL if f in present] -append!(fn_order, sort([f for f in present if f ∉ CANONICAL])) -lang_order = unique(languages) +fn_order = [function_name for function_name in CANONICAL if function_name in present] +append!(fn_order, sort([function_name for function_name in present if function_name ∉ CANONICAL])) +fn_index = Dict(function_name => index for (index, function_name) in enumerate(fn_order)) +ordered_functions = [fn_index[function_name] for function_name in functions] -# Blank cells -- e.g. ddi, which KEGGREST and Bio.KEGG.REST do not wrap -- stay -# NaN so no bar is drawn for them. -matrix = fill(NaN, length(fn_order), length(lang_order)) -for i in eachindex(functions) - r = findfirst(==(functions[i]), fn_order) - c = findfirst(==(languages[i]), lang_order) - matrix[r, c] = medians[i] -end - -plt = groupedbar( - fn_order, - matrix; - label = permutedims(lang_order), +plt = groupedboxplot( + ordered_functions, + seconds; + group = languages, + label = permutedims(unique(languages)), + xticks = (eachindex(fn_order), fn_order), xlabel = "KEGG operation", - ylabel = "Median time per call (s)", - title = "KEGGAPI.jl benchmarks", + ylabel = "Request time (s)", + title = "KEGG API request-time distributions", legend = :topleft, - # Headroom so the tallest bar is not clipped by the axis. - ylims = (0, 1.08 * maximum(filter(!isnan, matrix))), - bar_width = 0.7, + outliers = true, + bar_width = 0.75, framestyle = :box, - size = (1000, 500), + size = (1100, 600), dpi = 200, left_margin = 8mm, bottom_margin = 8mm, ) -out = joinpath(BENCHDIR, "benchmark_compare.png") -savefig(plt, out) -@info "Wrote $out" +for extension in ("svg", "png") + output = joinpath(BENCHDIR, "benchmark.$extension") + savefig(plt, output) + @info "Wrote $output" +end diff --git a/benchmarking/run_benchmarks.jl b/benchmarking/run_benchmarks.jl old mode 100644 new mode 100755 index a64a933..5cdc3d5 --- a/benchmarking/run_benchmarks.jl +++ b/benchmarking/run_benchmarks.jl @@ -1,118 +1,134 @@ #!/usr/bin/env julia # -# Benchmark KEGGAPI.jl against KEGGREST (R), Bio.KEGG.REST (Python) and raw curl. +# Benchmark KEGGAPI.jl against KEGGREST, Bio.KEGG.REST, and raw curl. # -# julia --project=benchmarking benchmarking/run_benchmarks.jl [--nreps N] [--pause S] +# julia --project=benchmarking benchmarking/run_benchmarks.jl # -# Each interface runs the same three operations (info/kegg, list/pathway, -# get/hsa:10458) inside a single process, so what is measured is per-call time -# rather than interpreter startup. Interfaces whose dependencies are missing are -# reported and skipped, so this runs even with only Julia available. -# -# Writes benchmark_compare.csv (Function,Language,Mean,SD) next to this script. - -using Statistics -using Printf +# Each runner emits one timing for every request in cases.tsv. Optional +# interfaces are skipped when their dependencies are unavailable. const BENCHDIR = @__DIR__ const RUNNERS = joinpath(BENCHDIR, "runners") +const CASE_FILE = joinpath(BENCHDIR, "cases.tsv") +const OPERATIONS = Set(["info", "list", "find", "get", "getseq", "conv", "link", "ddi"]) + +function validate_cases(path) + lines = readlines(path) + first(lines) == "operation\targument1\targument2" || error("Unexpected header in $path") + rows = [Tuple(split(line, '\t'; keepempty = true)) for line in Iterators.drop(lines, 1)] + all(length(row) == 3 for row in rows) || error("Every benchmark case must have three fields") + length(unique(rows)) == length(rows) || error("Benchmark cases must be unique") + counts = Dict(operation => count(row -> first(row) == operation, rows) for operation in OPERATIONS) + Set(first.(rows)) == OPERATIONS || error("Unexpected benchmark operations in $path") + all(==(25), values(counts)) || error("Each operation must have exactly 25 benchmark cases") + return nothing +end -# ------------------------------------------------------------------ CLI parsing function parse_args(args) - nreps, pause = 5, 0.4 + nreps, pause = 1, 0.4 + only = Set(["julia", "r", "python", "curl"]) + output = joinpath(BENCHDIR, "benchmark_compare.csv") i = 1 while i <= length(args) + i == length(args) && error("Missing value for $(args[i])") if args[i] == "--nreps" - nreps = parse(Int, args[i + 1]); i += 2 + nreps = parse(Int, args[i + 1]) elseif args[i] == "--pause" - pause = parse(Float64, args[i + 1]); i += 2 + pause = parse(Float64, args[i + 1]) + elseif args[i] == "--only" + only = Set(split(args[i + 1], ',')) + elseif args[i] == "--output" + output = abspath(args[i + 1]) else error("Unknown argument: $(args[i])") end + i += 2 end - return nreps, pause + nreps > 0 || error("--nreps must be positive") + pause >= 0 || error("--pause must be nonnegative") + valid = Set(["julia", "r", "python", "curl"]) + only ⊆ valid || error("--only accepts a comma-separated subset of $(join(sort!(collect(valid)), ", "))") + return (; nreps, pause, only, output) end -const NREPS, PAUSE = parse_args(ARGS) - -# ------------------------------------------------------------------ Interfaces -# `probe` must succeed for the interface to be benchmarked. struct Interface + key::String name::String probe::Cmd run::Cmd end -# Interpreters are overridable so a virtualenv / custom R can be used, e.g. -# PYTHON=/path/to/venv/bin/python julia --project=benchmarking ... +const OPTIONS = parse_args(ARGS) +validate_cases(CASE_FILE) const JULIA = get(ENV, "JULIA", "julia") const RSCRIPT = get(ENV, "RSCRIPT", "Rscript") const PYTHON = get(ENV, "PYTHON", "python3") interfaces = [ Interface( + "julia", "KEGGAPI.jl", `$JULIA --version`, - `$JULIA --project=$BENCHDIR $(joinpath(RUNNERS, "bench_julia.jl")) $NREPS $PAUSE`, + `$JULIA --project=$BENCHDIR $(joinpath(RUNNERS, "bench_julia.jl")) $(OPTIONS.nreps) $(OPTIONS.pause)`, ), Interface( + "r", "KEGGREST (R)", `$RSCRIPT -e "suppressMessages(library(KEGGREST))"`, - `$RSCRIPT $(joinpath(RUNNERS, "bench_r.R")) $NREPS $PAUSE`, + `$RSCRIPT $(joinpath(RUNNERS, "bench_r.R")) $(OPTIONS.nreps) $(OPTIONS.pause)`, ), Interface( + "python", "Bio.KEGG.REST (Python)", `$PYTHON -c "import Bio.KEGG.REST"`, - `$PYTHON $(joinpath(RUNNERS, "bench_python.py")) $NREPS $PAUSE`, + `$PYTHON $(joinpath(RUNNERS, "bench_python.py")) $(OPTIONS.nreps) $(OPTIONS.pause)`, ), Interface( + "curl", "curl", `curl --version`, - `bash $(joinpath(RUNNERS, "bench_curl.sh")) $NREPS $PAUSE`, + `bash $(joinpath(RUNNERS, "bench_curl.sh")) $(OPTIONS.nreps) $(OPTIONS.pause)`, ), ] -available(iface) = success(pipeline(iface.probe, stdout = devnull, stderr = devnull)) +available(interface) = success(pipeline(interface.probe, stdout = devnull, stderr = devnull)) -# ------------------------------------------------------------------ Run -samples = Dict{Tuple{String, String}, Vector{Float64}}() -for iface in interfaces - if !available(iface) - @warn "Skipping $(iface.name): dependencies not installed" probe = iface.probe - continue - end - - @info "Benchmarking $(iface.name) ($NREPS replicates)..." - output = try - read(iface.run, String) - catch e - @warn "Skipping $(iface.name): runner failed" exception = e +samples = NamedTuple{(:operation, :request, :language, :seconds), Tuple{String, String, String, Float64}}[] +for interface in interfaces + interface.key in OPTIONS.only || continue + if !available(interface) + @warn "Skipping $(interface.name): dependencies not installed" probe = interface.probe continue end + operation_count = interface.key in ("r", "python") ? 7 : 8 + expected_samples = 25 * operation_count * OPTIONS.nreps + @info "Benchmarking $(interface.name)" requests = expected_samples + output = read(interface.run, String) + initial_length = length(samples) for line in eachline(IOBuffer(output)) + isempty(strip(line)) && continue fields = split(strip(line), ',') - length(fields) == 3 || continue # NOTE: ignore any incidental stdout noise - fn, lang, secs = fields - push!(get!(samples, (String(fn), String(lang)), Float64[]), parse(Float64, secs)) + length(fields) == 4 || error("Malformed output from $(interface.name): $line") + operation, request, language, seconds = fields + language == interface.name || error("Unexpected interface label '$language'") + elapsed = parse(Float64, seconds) + isfinite(elapsed) && elapsed >= 0 || error("Invalid timing from $(interface.name): $seconds") + push!(samples, (; operation = String(operation), request = String(request), language = String(language), seconds = elapsed)) end + length(samples) - initial_length == expected_samples || + error("Expected $expected_samples results from $(interface.name)") end -isempty(samples) && error("No interface could be benchmarked.") - -# Every operation x interface pair gets a row. Pairs with no samples -- an -# interface that was skipped, or an operation it does not wrap (e.g. ddi in -# KEGGREST) -- are written with an empty median rather than omitted. -const OPERATIONS = ["info", "list", "find", "get", "getseq", "conv", "link", "ddi"] - -observed = unique(first.(keys(samples))) -operations = vcat(OPERATIONS, sort([op for op in observed if op ∉ OPERATIONS])) +isempty(samples) && error("No interface could be benchmarked") -outfile = joinpath(BENCHDIR, "benchmark_compare.csv") -open(outfile, "w") do io - println(io, "Function,Language,Median") - for op in operations, iface in interfaces - times = get(samples, (op, iface.name), Float64[]) - println(io, "$op,$(iface.name),", isempty(times) ? "" : median(times)) +# issue #45: retain every request timing so plots and CI use the distribution, +# rather than reducing repeated calls to one median before writing the file. +mkpath(dirname(OPTIONS.output)) +open(OPTIONS.output, "w") do io + println(io, "Function,Request,Language,Seconds") + for sample in samples + println(io, "$(sample.operation),$(sample.request),$(sample.language),$(sample.seconds)") end end +@info "Wrote $(OPTIONS.output)" samples = length(samples) diff --git a/benchmarking/runners/bench_curl.sh b/benchmarking/runners/bench_curl.sh old mode 100644 new mode 100755 index 7374dba..6c3c22b --- a/benchmarking/runners/bench_curl.sh +++ b/benchmarking/runners/bench_curl.sh @@ -1,42 +1,49 @@ #!/usr/bin/env bash -# curl runner: times raw REST calls and prints one CSV row per replicate. -# Usage: bash runners/bench_curl.sh +# Time raw REST calls and print one CSV row per request. +# Usage: bash bench_curl.sh set -euo pipefail -NREPS="${1:-5}" +NREPS="${1:-1}" PAUSE="${2:-0.4}" - BASE="https://rest.kegg.jp" - -# label|path pairs -- keep in sync with the other runners. -CASES=( - "info|$BASE/info/kegg" - "list|$BASE/list/pathway" - "find|$BASE/find/compound/glucose" - "get|$BASE/get/hsa:10458" - "getseq|$BASE/get/hsa:10458/aaseq" - "conv|$BASE/conv/ncbi-geneid/eco:b0002" - "link|$BASE/link/pathway/hsa:10458" - "ddi|$BASE/ddi/D00564" -) - -# Must match the interface name in run_benchmarks.jl. +CASE_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/cases.tsv" LABEL="curl" -# `curl -w %{time_total}` reports the transfer time without shell startup cost. +case_path() { + local operation="$1" argument1="$2" argument2="$3" + case "$operation" in + info) printf 'info/%s' "$argument1" ;; + list) printf 'list/%s' "$argument1" ;; + find) printf 'find/%s/%s' "$argument1" "$argument2" ;; + get) printf 'get/%s' "$argument1" ;; + getseq) printf 'get/%s/aaseq' "$argument1" ;; + conv) printf 'conv/%s/%s' "$argument1" "$argument2" ;; + link) printf 'link/%s/%s' "$argument1" "$argument2" ;; + ddi) printf 'ddi/%s' "$argument1" ;; + *) echo "Unknown benchmark operation: $operation" >&2; return 1 ;; + esac +} + timeit() { - curl -s -o /dev/null -w '%{time_total}' "$1" + curl -fsS -o /dev/null -w '%{time_total}' "$1" } -# Warm up before the measured replicates. -for case in "${CASES[@]}"; do - curl -s -o /dev/null "${case#*|}" +# Warm up each operation once so connection setup is absent from measurements. +previous_operation="" +while IFS=$'\t' read -r operation argument1 argument2; do + [[ "$operation" == "operation" ]] && continue + [[ "$operation" == "$previous_operation" ]] && continue + path="$(case_path "$operation" "$argument1" "$argument2")" + curl -fsS -o /dev/null "$BASE/$path" + previous_operation="$operation" sleep "$PAUSE" -done +done < "$CASE_FILE" for _ in $(seq 1 "$NREPS"); do - for case in "${CASES[@]}"; do - echo "${case%%|*},$LABEL,$(timeit "${case#*|}")" + while IFS=$'\t' read -r operation argument1 argument2; do + [[ "$operation" == "operation" ]] && continue + path="$(case_path "$operation" "$argument1" "$argument2")" + echo "$operation,$path,$LABEL,$(timeit "$BASE/$path")" sleep "$PAUSE" - done + done < "$CASE_FILE" done diff --git a/benchmarking/runners/bench_julia.jl b/benchmarking/runners/bench_julia.jl index b591c74..959750f 100644 --- a/benchmarking/runners/bench_julia.jl +++ b/benchmarking/runners/bench_julia.jl @@ -1,33 +1,56 @@ -# Julia runner: times KEGGAPI.jl calls and prints one CSV row per replicate. -# Usage: julia --project=. runners/bench_julia.jl +# Julia runner: time KEGGAPI.jl calls and print one CSV row per request. +# Usage: julia --project=benchmarking bench_julia.jl using KEGGAPI -const NREPS = length(ARGS) >= 1 ? parse(Int, ARGS[1]) : 5 +const NREPS = length(ARGS) >= 1 ? parse(Int, ARGS[1]) : 1 const PAUSE = length(ARGS) >= 2 ? parse(Float64, ARGS[2]) : 0.4 - -# This runner already spaces its calls, so disable the internal batching delay -# to measure request and parsing work only. -get_entry(args...) = KEGGAPI.kegg_get(args...; request_delay = 0.0) - -# (label, thunk) pairs -- keep in sync with the other runners. -const CASES = [ - ("info", () -> KEGGAPI.kegg_info("kegg")), - ("list", () -> KEGGAPI.kegg_list("pathway")), - ("find", () -> KEGGAPI.kegg_find("compound", "glucose")), - ("get", () -> get_entry("hsa:10458")), - ("getseq", () -> get_entry("hsa:10458", :aaseq)), - ("conv", () -> KEGGAPI.kegg_conv("ncbi-geneid", "eco:b0002")), - ("link", () -> KEGGAPI.kegg_link("pathway", "hsa:10458")), - ("ddi", () -> KEGGAPI.kegg_ddi("D00564")), -] - -# Must match the interface name in run_benchmarks.jl. +const CASE_FILE = joinpath(@__DIR__, "..", "cases.tsv") const LABEL = "KEGGAPI.jl" -# Warm up so compilation latency is not attributed to the first replicate. -for (_, thunk) in CASES - thunk() - sleep(PAUSE) +struct BenchmarkCase + operation::String + argument1::String + argument2::String +end + +function load_cases(path) + lines = readlines(path) + first(lines) == "operation\targument1\targument2" || error("Unexpected case-file header") + cases = BenchmarkCase[] + for (index, line) in enumerate(Iterators.drop(lines, 1)) + fields = split(line, '\t'; keepempty = true) + length(fields) == 3 || error("Invalid benchmark case on line $(index + 1)") + push!(cases, BenchmarkCase(fields...)) + end + return cases +end + +function request_path(case) + op, arg1, arg2 = case.operation, case.argument1, case.argument2 + op == "info" && return "info/$arg1" + op == "list" && return "list/$arg1" + op == "find" && return "find/$arg1/$arg2" + op == "get" && return "get/$arg1" + op == "getseq" && return "get/$arg1/aaseq" + op == "conv" && return "conv/$arg1/$arg2" + op == "link" && return "link/$arg1/$arg2" + op == "ddi" && return "ddi/$arg1" + error("Unknown benchmark operation: $op") +end + +# The runner spaces calls itself. Disable KEGGAPI's internal batching delay so +# the measurement contains only request and parsing time. +function run_case(case) + op, arg1, arg2 = case.operation, case.argument1, case.argument2 + op == "info" && return KEGGAPI.kegg_info(arg1) + op == "list" && return KEGGAPI.kegg_list(arg1) + op == "find" && return KEGGAPI.kegg_find(arg1, arg2) + op == "get" && return KEGGAPI.kegg_get(arg1; request_delay = 0.0) + op == "getseq" && return KEGGAPI.kegg_get(arg1, :aaseq; request_delay = 0.0) + op == "conv" && return KEGGAPI.kegg_conv(arg1, arg2) + op == "link" && return KEGGAPI.kegg_link(arg1, arg2) + op == "ddi" && return KEGGAPI.kegg_ddi(arg1) + error("Unknown benchmark operation: $op") end function timeit(f) @@ -36,7 +59,18 @@ function timeit(f) return (time_ns() - t0) / 1.0e9 end -for _ in 1:NREPS, (label, thunk) in CASES - println("$label,$LABEL,", timeit(thunk)) +const CASES = load_cases(CASE_FILE) + +# Warm up each operation once so compilation is absent from measured calls. +warmed = Set{String}() +for case in CASES + case.operation in warmed && continue + run_case(case) + push!(warmed, case.operation) + sleep(PAUSE) +end + +for _ in 1:NREPS, case in CASES + println("$(case.operation),$(request_path(case)),$LABEL,", timeit(() -> run_case(case))) sleep(PAUSE) end diff --git a/benchmarking/runners/bench_python.py b/benchmarking/runners/bench_python.py index 987839a..f85b022 100644 --- a/benchmarking/runners/bench_python.py +++ b/benchmarking/runners/bench_python.py @@ -1,43 +1,89 @@ -"""Python runner: times Bio.KEGG.REST calls, one CSV row per replicate. +"""Time Bio.KEGG.REST calls and print one CSV row per request. -Usage: python3 runners/bench_python.py +Usage: python3 bench_python.py """ +import csv +import os import sys import time import Bio.KEGG.REST as BK -NREPS = int(sys.argv[1]) if len(sys.argv) > 1 else 5 +NREPS = int(sys.argv[1]) if len(sys.argv) > 1 else 1 PAUSE = float(sys.argv[2]) if len(sys.argv) > 2 else 0.4 - -# (label, thunk) pairs -- keep in sync with the other runners. Bio.KEGG.REST has -# no ddi wrapper, so that case is absent here and reported as unsupported. -CASES = [ - ("info", lambda: BK.kegg_info("kegg")), - ("list", lambda: BK.kegg_list("pathway")), - ("find", lambda: BK.kegg_find("compound", "glucose")), - ("get", lambda: BK.kegg_get("hsa:10458")), - ("getseq", lambda: BK.kegg_get("hsa:10458", "aaseq")), - ("conv", lambda: BK.kegg_conv("ncbi-geneid", "eco:b0002")), - ("link", lambda: BK.kegg_link("pathway", "hsa:10458")), -] - -# Must match the interface name in run_benchmarks.jl. +CASE_FILE = os.path.join(os.path.dirname(__file__), "..", "cases.tsv") LABEL = "Bio.KEGG.REST (Python)" +def load_cases(path): + with open(path, newline="", encoding="utf-8") as handle: + return list(csv.DictReader(handle, delimiter="\t")) + + +def request_path(case): + op = case["operation"] + arg1 = case["argument1"] + arg2 = case["argument2"] + if op == "info": + return "info/{}".format(arg1) + if op == "list": + return "list/{}".format(arg1) + if op == "find": + return "find/{}/{}".format(arg1, arg2) + if op == "get": + return "get/{}".format(arg1) + if op == "getseq": + return "get/{}/aaseq".format(arg1) + if op == "conv": + return "conv/{}/{}".format(arg1, arg2) + if op == "link": + return "link/{}/{}".format(arg1, arg2) + raise ValueError("Unknown benchmark operation: {}".format(op)) + + +def run_case(case): + op = case["operation"] + arg1 = case["argument1"] + arg2 = case["argument2"] + if op == "info": + response = BK.kegg_info(arg1) + elif op == "list": + response = BK.kegg_list(arg1) + elif op == "find": + response = BK.kegg_find(arg1, arg2) + elif op == "get": + response = BK.kegg_get(arg1) + elif op == "getseq": + response = BK.kegg_get(arg1, "aaseq") + elif op == "conv": + response = BK.kegg_conv(arg1, arg2) + elif op == "link": + response = BK.kegg_link(arg1, arg2) + else: + raise ValueError("Unknown benchmark operation: {}".format(op)) + response.read() + + def timeit(fn): - t0 = time.perf_counter() - fn().read() - return time.perf_counter() - t0 + start = time.perf_counter() + fn() + return time.perf_counter() - start + +# Bio.KEGG.REST has no DDI wrapper. +CASES = [case for case in load_cases(CASE_FILE) if case["operation"] != "ddi"] -# Warm up (connection setup, imports) before the measured replicates. -for _, thunk in CASES: - thunk().read() +# Warm up each operation once so connection setup is absent from measurements. +warmed = set() +for case in CASES: + if case["operation"] in warmed: + continue + run_case(case) + warmed.add(case["operation"]) time.sleep(PAUSE) for _ in range(NREPS): - for label, thunk in CASES: - print("{},{},{}".format(label, LABEL, timeit(thunk))) + for case in CASES: + elapsed = timeit(lambda: run_case(case)) + print("{},{},{},{}".format(case["operation"], request_path(case), LABEL, elapsed)) time.sleep(PAUSE) diff --git a/benchmarking/runners/bench_r.R b/benchmarking/runners/bench_r.R index dc8e53b..f2bb1a7 100644 --- a/benchmarking/runners/bench_r.R +++ b/benchmarking/runners/bench_r.R @@ -1,42 +1,76 @@ -# R runner: times KEGGREST calls and prints one CSV row per replicate. -# Usage: Rscript runners/bench_r.R +# Time KEGGREST calls and print one CSV row per request. +# Usage: Rscript bench_r.R suppressMessages(library(KEGGREST)) args <- commandArgs(trailingOnly = TRUE) -nreps <- if (length(args) >= 1) as.integer(args[1]) else 5 +nreps <- if (length(args) >= 1) as.integer(args[1]) else 1 pause <- if (length(args) >= 2) as.numeric(args[2]) else 0.4 +script_arg <- grep("^--file=", commandArgs(trailingOnly = FALSE), value = TRUE) +if (length(script_arg) != 1) stop("bench_r.R must be run with Rscript") +script_path <- sub("^--file=", "", script_arg[[1]]) +case_file <- file.path(dirname(normalizePath(script_path)), "..", "cases.tsv") +label <- "KEGGREST (R)" -# (label, thunk) pairs -- keep in sync with the other runners. KEGGREST has no -# ddi wrapper, so that case is absent here and reported as unsupported. -# NOTE: keggList (not keggInfo) is the counterpart of the list operation. -cases <- list( - list("info", function() keggInfo("kegg")), - list("list", function() keggList("pathway")), - list("find", function() keggFind("compound", "glucose")), - list("get", function() keggGet("hsa:10458")), - list("getseq", function() keggGet("hsa:10458", "aaseq")), - list("conv", function() keggConv("ncbi-geneid", "eco:b0002")), - list("link", function() keggLink("pathway", "hsa:10458")) -) +cases <- read.delim(case_file, stringsAsFactors = FALSE, check.names = FALSE) +# KEGGREST has no DDI wrapper. +cases <- cases[cases$operation != "ddi", ] -# Must match the interface name in run_benchmarks.jl. -label <- "KEGGREST (R)" +request_path <- function(case) { + op <- case$operation + arg1 <- case$argument1 + arg2 <- case$argument2 + if (op == "info") return(sprintf("info/%s", arg1)) + if (op == "list") return(sprintf("list/%s", arg1)) + if (op == "find") return(sprintf("find/%s/%s", arg1, arg2)) + if (op == "get") return(sprintf("get/%s", arg1)) + if (op == "getseq") return(sprintf("get/%s/aaseq", arg1)) + if (op == "conv") return(sprintf("conv/%s/%s", arg1, arg2)) + if (op == "link") return(sprintf("link/%s/%s", arg1, arg2)) + stop(sprintf("Unknown benchmark operation: %s", op)) +} + +run_case <- function(case) { + op <- case$operation + arg1 <- case$argument1 + arg2 <- case$argument2 + result <- switch( + op, + info = keggInfo(arg1), + list = keggList(arg1), + find = keggFind(arg1, arg2), + get = keggGet(arg1), + getseq = keggGet(arg1, "aaseq"), + conv = keggConv(arg1, arg2), + link = keggLink(arg1, arg2), + stop(sprintf("Unknown benchmark operation: %s", op)) + ) + invisible(result) +} timeit <- function(fn) { - t0 <- Sys.time() - invisible(fn()) - as.numeric(difftime(Sys.time(), t0, units = "secs")) + start <- proc.time()[["elapsed"]] + fn() + proc.time()[["elapsed"]] - start } -# Warm up before the measured replicates. -for (case in cases) { - invisible(case[[2]]()) +# Warm up each operation once so connection setup is absent from measurements. +warmed <- character() +for (i in seq_len(nrow(cases))) { + case <- cases[i, ] + if (case$operation %in% warmed) next + run_case(case) + warmed <- c(warmed, case$operation) Sys.sleep(pause) } -for (i in seq_len(nreps)) { - for (case in cases) { - cat(sprintf("%s,%s,%s\n", case[[1]], label, timeit(case[[2]]))) +for (rep in seq_len(nreps)) { + for (i in seq_len(nrow(cases))) { + case <- cases[i, ] + elapsed <- timeit(function() run_case(case)) + cat(sprintf( + "%s,%s,%s,%s\n", + case$operation, request_path(case), label, elapsed + )) Sys.sleep(pause) } } diff --git a/benchmarking/write_ci_results.jl b/benchmarking/write_ci_results.jl new file mode 100755 index 0000000..53822ca --- /dev/null +++ b/benchmarking/write_ci_results.jl @@ -0,0 +1,39 @@ +#!/usr/bin/env julia +# Convert KEGGAPI.jl request timings to github-action-benchmark's custom JSON. +using DelimitedFiles +using Printf +using Statistics + +length(ARGS) == 2 || error("Usage: write_ci_results.jl INPUT.csv OUTPUT.json") +input, output = ARGS +raw, header = readdlm(input, ',', String, header = true) +vec(header) == ["Function", "Request", "Language", "Seconds"] || error("Unexpected columns in $input") + +samples = Dict{String, Vector{Float64}}() +for row in eachrow(raw) + strip(row[3]) == "KEGGAPI.jl" || continue + elapsed = parse(Float64, strip(row[4])) + isfinite(elapsed) && elapsed >= 0 || error("Benchmark timings must be finite and nonnegative") + push!(get!(samples, strip(row[1]), Float64[]), elapsed) +end +isempty(samples) && error("No KEGGAPI.jl timings found in $input") + +const ORDER = ["info", "list", "find", "get", "getseq", "conv", "link", "ddi"] +operations = [operation for operation in ORDER if haskey(samples, operation)] +for operation in operations + length(samples[operation]) >= 25 || error("Expected at least 25 '$operation' timings") +end + +open(output, "w") do io + println(io, "[") + for (index, operation) in enumerate(operations) + index > 1 && println(io, ",") + @printf( + io, + " {\"name\": \"%s request\", \"unit\": \"seconds\", \"value\": %.9g}", + operation, + median(samples[operation]), + ) + end + println(io, "\n]") +end