seraplot 2.3.84__tar.gz → 2.3.85__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {seraplot-2.3.84 → seraplot-2.3.85}/Cargo.lock +1 -1
- {seraplot-2.3.84 → seraplot-2.3.85}/Cargo.toml +1 -1
- {seraplot-2.3.84 → seraplot-2.3.85}/PKG-INFO +1 -1
- {seraplot-2.3.84 → seraplot-2.3.85}/pyproject.toml +1 -1
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/commands/charts.rs +150 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/commands/registry.rs +6 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/registry_macro.rs +159 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/SUMMARY.md +11 -0
- seraplot-2.3.85/src/docs/config/a11y.md +41 -0
- seraplot-2.3.85/src/docs/config/automl.md +69 -0
- seraplot-2.3.85/src/docs/config/csp.md +33 -0
- seraplot-2.3.85/src/docs/config/diff.md +53 -0
- seraplot-2.3.85/src/docs/config/downsample.md +63 -0
- seraplot-2.3.85/src/docs/config/drift.md +77 -0
- seraplot-2.3.85/src/docs/config/export.md +231 -0
- seraplot-2.3.85/src/docs/config/facet.md +67 -0
- seraplot-2.3.85/src/docs/config/ml-persistence.md +292 -0
- seraplot-2.3.85/src/docs/config/pickle.md +43 -0
- seraplot-2.3.85/src/docs/config/streaming.md +235 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/lib.rs +114 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/.gitignore +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/05--Diabetes_SeraPlot.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/07--OpenFoodFacts_SeraPlot_Benchmark.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/README.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/TEST_1M_Battle.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_all.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_bigdata.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_full.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_issues.json +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_knn_sgd.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_perf.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_quick.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_quick2.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_scale.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_seraplot.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_sklearn.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_svc.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_svc2.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/bench_test.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_gridsearch.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_gridsearch2.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_kmeans_heavy.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_kmeans_openfoodfacts.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_ml.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_ml_openfoodfacts.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/benchmark_ml_out.ipynb +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/build.log +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/gen_bench_slides.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/1.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/2.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/3.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/4.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/5.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/6.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/7.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/2d/8.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/1.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/2.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/3.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/4.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/5.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/6.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/7.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/3d/8.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/README.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/benchmark/1.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/benchmark/2.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/benchmark/3.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/images/logo.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/kmeans_test.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/publish_2378.log +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/publish_log.txt +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/python/seraplot/__init__.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/python/seraplot/matplotlib.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/python/seraplot/seraplot.cp311-win_amd64.pyd.old +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/results_seraplot.json +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/results_sklearn.json +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/.github/workflows/mdbook.yml +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/README.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/asset/SVG World Map with labels.svg +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/asset/logo.png +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/asset/world.svg +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/builder_template.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/chart_types.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/commands/docs.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/commands/ml.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/commands/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/commands/native.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/export_builder.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/fast_export_c.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/fast_render.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/memory_pool.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/unified_builder.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/unified_config.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/arena_alloc.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/bitset.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/compact_state.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/data_processor.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/image_processor.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/lazy_builders.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/memory_pool.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/simd_ops.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/bindings/utils/state_export.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/book.toml +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/core/builders.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/core/math.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/core/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/data/conversion.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/data/index.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/data/loader.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/data/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/data/processor.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/api/index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/area.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/bar.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/boxplot.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/bubble.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/bullet.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/candlestick.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/donut.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/dumbbell.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/funnel.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/gauge.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/grid.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/grouped-bar.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/hbar.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/heatmap.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/histogram-overlay.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/histogram.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/kde.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/line.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/lollipop.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/multiline.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/parallel.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/pie.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/radar.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/ridgeline.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/scatter.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/slideshow.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/slope.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/stacked-bar.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/sunburst.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/treemap.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/violin.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/waterfall.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/2d/wordcloud.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/bar3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/bubble3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/candlestick3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/dumbbell3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/funnel3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/globe3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/heatmap3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/kde3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/line3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/lollipop3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/pie3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/radar3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/ridgeline3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/scatter3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/stacked-bar3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/sunburst3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/3d/violin3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/map/bubble-map.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/map/choropleth.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/charts/map/index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/config/auto-display.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/config/background.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/config/hover.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/config/palette.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/getting-started/chart-methods.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/getting-started/chart-object.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/getting-started/installation.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/getting-started/quickstart.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/introduction.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/adaboost.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/bayes-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/clustering-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/dbscan-class.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/dbscan.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/dbscan3d.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/decision-tree.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/decomposition-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/decomposition.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/elastic-net.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/evaluation-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/gradient-boosting.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/grid-search.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/kmeans-class.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/kmeans.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/knn.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/lasso.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/linear-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/linear-regression.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/logistic-regression.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/metrics.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/naive-bayes.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/neighbors-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/preprocessing-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/preprocessing.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/random-forest.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/ridge.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/selection-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/sgd.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/svm-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/svm.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/train-test-split.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/ml/tree-index.md +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/area.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bar.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bar3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bench-matplotlib.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bench-plotly.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bench-seraplot.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/boxplot.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bubble-map.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bubble.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bubble3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/bullet.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/candlestick.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/candlestick3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/choropleth.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/dbscan-class.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/dbscan.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/dbscan3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/donut.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/dumbbell.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/dumbbell3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/funnel.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/funnel3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/gauge.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/globe3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/grid.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/grouped-bar.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/hbar.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/heatmap.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/heatmap3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/histogram-overlay.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/histogram.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/kde.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/kde3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/line.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/line3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/lollipop.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/lollipop3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/multiline.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/parallel.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/pie.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/pie3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/radar.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/radar3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/ridgeline.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/ridgeline3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/scatter.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/scatter3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/slideshow.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/slope.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/stacked-bar.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/stacked-bar3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/sunburst.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/sunburst3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/treemap.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/violin.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/violin3d.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/waterfall.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/previews/wordcloud.html +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/theme/custom.css +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/docs/theme/lang-switcher.js +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/assets.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/fast_builders.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/fast_exporter.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/hover.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/html_export.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/html_template.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/js_3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/html/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/cache.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/decomposition/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/decomposition/pca.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linalg.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/elastic_net.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/lasso.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/logistic.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/ols.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/ridge.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/linear/sgd.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/metrics/classification.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/metrics/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/metrics/regression.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/model_selection/cross_val.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/model_selection/grid_search.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/model_selection/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/model_selection/split.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/naive_bayes/bernoulli.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/naive_bayes/gaussian.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/naive_bayes/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/naive_bayes/multinomial.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/neighbors/knn.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/neighbors/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/preprocessing/encoders.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/preprocessing/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/preprocessing/scalers.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/svm/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/svm/svm.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/tree/adaboost.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/tree/decision_tree.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/tree/decision_tree_backup.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/tree/gradient_boosting.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/tree/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/ml/tree/random_forest.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/camera.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/canvas.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/containers_3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/controller/chart_controller.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/controller/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/controller/plot_3d_controller.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/_3d/bar_3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/_3d/line_3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/_3d/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/_3d/plot_3d_types.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/_3d/scatter_3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/bar.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/chart.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/kmeans.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/line.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/scatter.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/default/svg.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/generic.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/_3d/globe.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/_3d/globe_html.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/_3d/globe_types.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/_3d/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/bubble_map.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/chart.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/choropleth.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/svg_parser.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/map/world_data.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/projection.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/renderers.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/scale_renderer.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/seaborn/_3d/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/seaborn/_3d/plot_3d_types.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/seaborn/chart.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/seaborn/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/candlestick3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/dumbbell3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/funnel3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/heatmap3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/kde3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/lollipop3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/pie3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/plot_3d_types.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/radar3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/ridgeline3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/stacked_bar3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/sunburst3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/_3d/violin3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/area.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/boxplot.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/bubble.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/bullet.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/candlestick.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/common.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/dumbbell.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/funnel.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/gauge.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/grouped_bar.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/heatmap.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/histogram.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/kde.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/lollipop.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/multiline.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/parallel.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/pie.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/radar.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/ridgeline.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/slope.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/sunburst.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/treemap.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/violin.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/waterfall.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/plot/statistical/wordcloud.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/cache.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/chart.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/gui.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/hybrid.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/manager/button_manager.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/manager/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/render/advanced_render.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/render/fast_render_gui.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/render/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/render/pipeline.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/render/viewer_3d.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/render/wiki_viewer.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/utils/image_loader.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/viewer/utils/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/wiki/api.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/wiki/extractor.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/wiki/language.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/wiki/macros.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/wiki/metadata.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/src/wiki/mod.rs +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/test_accuracy.py +0 -0
- {seraplot-2.3.84 → seraplot-2.3.85}/test_universal_ml.js +0 -0
|
@@ -1583,6 +1583,156 @@ pub fn chart_info(input: &str) -> String {
|
|
|
1583
1583
|
serde_json::json!({"size":len,"paths":n_paths,"rects":n_rects,"circles":n_circles,"has_svg":has_svg}).to_string()
|
|
1584
1584
|
}
|
|
1585
1585
|
|
|
1586
|
+
pub fn validate_input(input: &str) -> String {
|
|
1587
|
+
#[derive(serde::Deserialize)]
|
|
1588
|
+
struct In { labels: Option<Vec<String>>, values: Option<Vec<f64>>, x: Option<Vec<f64>>, y: Option<Vec<f64>>, series: Option<Vec<Vec<f64>>> }
|
|
1589
|
+
let v: In = match serde_json::from_str::<In>(input) {
|
|
1590
|
+
Ok(v) => v,
|
|
1591
|
+
Err(e) => return serde_json::json!({"ok":false,"error":format!("invalid JSON: {e}")}).to_string(),
|
|
1592
|
+
};
|
|
1593
|
+
if let (Some(l), Some(va)) = (v.labels.as_ref(), v.values.as_ref()) {
|
|
1594
|
+
if l.len() != va.len() {
|
|
1595
|
+
return serde_json::json!({"ok":false,"error":format!("labels ({}) and values ({}) length mismatch", l.len(), va.len())}).to_string();
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
if let (Some(x), Some(y)) = (v.x.as_ref(), v.y.as_ref()) {
|
|
1599
|
+
if x.len() != y.len() {
|
|
1600
|
+
return serde_json::json!({"ok":false,"error":format!("x ({}) and y ({}) length mismatch", x.len(), y.len())}).to_string();
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
if let (Some(l), Some(s)) = (v.labels.as_ref(), v.series.as_ref()) {
|
|
1604
|
+
for (i, row) in s.iter().enumerate() {
|
|
1605
|
+
if row.len() != l.len() {
|
|
1606
|
+
return serde_json::json!({"ok":false,"error":format!("series[{i}] length {} != labels length {}", row.len(), l.len())}).to_string();
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
serde_json::json!({"ok":true}).to_string()
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
pub fn downsample_lttb(input: &str) -> String {
|
|
1614
|
+
#[derive(serde::Deserialize)]
|
|
1615
|
+
struct In { x: Vec<f64>, y: Vec<f64>, threshold: usize }
|
|
1616
|
+
let v: In = match serde_json::from_str(input) {
|
|
1617
|
+
Ok(v) => v,
|
|
1618
|
+
Err(e) => return serde_json::json!({"ok":false,"error":format!("invalid JSON: {e}")}).to_string(),
|
|
1619
|
+
};
|
|
1620
|
+
let n = v.x.len();
|
|
1621
|
+
if n != v.y.len() {
|
|
1622
|
+
return serde_json::json!({"ok":false,"error":"x and y length mismatch"}).to_string();
|
|
1623
|
+
}
|
|
1624
|
+
let th = v.threshold;
|
|
1625
|
+
if th >= n || th < 3 {
|
|
1626
|
+
return serde_json::json!({"ok":true,"x":v.x,"y":v.y}).to_string();
|
|
1627
|
+
}
|
|
1628
|
+
let bucket_size = (n - 2) as f64 / (th - 2) as f64;
|
|
1629
|
+
let mut out_x: Vec<f64> = Vec::with_capacity(th);
|
|
1630
|
+
let mut out_y: Vec<f64> = Vec::with_capacity(th);
|
|
1631
|
+
out_x.push(v.x[0]); out_y.push(v.y[0]);
|
|
1632
|
+
let mut a: usize = 0;
|
|
1633
|
+
for i in 0..(th - 2) {
|
|
1634
|
+
let avg_start = ((i + 1) as f64 * bucket_size).floor() as usize + 1;
|
|
1635
|
+
let avg_end = (((i + 2) as f64 * bucket_size).floor() as usize + 1).min(n);
|
|
1636
|
+
let avg_len = (avg_end - avg_start).max(1) as f64;
|
|
1637
|
+
let mut avg_x = 0.0; let mut avg_y = 0.0;
|
|
1638
|
+
for k in avg_start..avg_end { avg_x += v.x[k]; avg_y += v.y[k]; }
|
|
1639
|
+
avg_x /= avg_len; avg_y /= avg_len;
|
|
1640
|
+
let range_offs = (i as f64 * bucket_size).floor() as usize + 1;
|
|
1641
|
+
let range_to = ((i + 1) as f64 * bucket_size).floor() as usize + 1;
|
|
1642
|
+
let pax = v.x[a]; let pay = v.y[a];
|
|
1643
|
+
let mut max_area = -1.0f64;
|
|
1644
|
+
let mut next_a = range_offs;
|
|
1645
|
+
for k in range_offs..range_to.min(n) {
|
|
1646
|
+
let area = ((pax - avg_x) * (v.y[k] - pay) - (pax - v.x[k]) * (avg_y - pay)).abs() * 0.5;
|
|
1647
|
+
if area > max_area { max_area = area; next_a = k; }
|
|
1648
|
+
}
|
|
1649
|
+
out_x.push(v.x[next_a]); out_y.push(v.y[next_a]);
|
|
1650
|
+
a = next_a;
|
|
1651
|
+
}
|
|
1652
|
+
out_x.push(v.x[n - 1]); out_y.push(v.y[n - 1]);
|
|
1653
|
+
serde_json::json!({"ok":true,"x":out_x,"y":out_y,"reduction":format!("{}->{}", n, out_x.len())}).to_string()
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
pub fn chart_diff(input: &str) -> String {
|
|
1657
|
+
#[derive(serde::Deserialize)]
|
|
1658
|
+
struct In { a: String, b: String }
|
|
1659
|
+
let v: In = match serde_json::from_str(input) {
|
|
1660
|
+
Ok(v) => v,
|
|
1661
|
+
Err(_) => return serde_json::json!({"ok":false,"error":"invalid JSON"}).to_string(),
|
|
1662
|
+
};
|
|
1663
|
+
let svg_a = extract_svg(&v.a);
|
|
1664
|
+
let svg_b = extract_svg(&v.b);
|
|
1665
|
+
let identical = svg_a == svg_b;
|
|
1666
|
+
let len_a = svg_a.len();
|
|
1667
|
+
let len_b = svg_b.len();
|
|
1668
|
+
let common = svg_a.bytes().zip(svg_b.bytes()).take_while(|(x, y)| x == y).count();
|
|
1669
|
+
let similarity = if len_a == 0 && len_b == 0 { 1.0 } else {
|
|
1670
|
+
let max_len = len_a.max(len_b) as f64;
|
|
1671
|
+
common as f64 / max_len
|
|
1672
|
+
};
|
|
1673
|
+
serde_json::json!({
|
|
1674
|
+
"ok":true,
|
|
1675
|
+
"identical":identical,
|
|
1676
|
+
"size_a":len_a,
|
|
1677
|
+
"size_b":len_b,
|
|
1678
|
+
"common_prefix":common,
|
|
1679
|
+
"similarity":similarity
|
|
1680
|
+
}).to_string()
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
fn extract_svg(html: &str) -> String {
|
|
1684
|
+
let start = match html.find("<svg") { Some(i) => i, None => return String::new() };
|
|
1685
|
+
let end = match html[start..].find("</svg>") { Some(i) => start + i + 6, None => return String::new() };
|
|
1686
|
+
html[start..end].to_string()
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
pub fn drift_ks(input: &str) -> String {
|
|
1690
|
+
#[derive(serde::Deserialize)]
|
|
1691
|
+
struct In { reference: Vec<f64>, current: Vec<f64> }
|
|
1692
|
+
let v: In = match serde_json::from_str(input) {
|
|
1693
|
+
Ok(v) => v,
|
|
1694
|
+
Err(e) => return serde_json::json!({"ok":false,"error":format!("invalid JSON: {e}")}).to_string(),
|
|
1695
|
+
};
|
|
1696
|
+
let mut a = v.reference.clone();
|
|
1697
|
+
let mut b = v.current.clone();
|
|
1698
|
+
if a.is_empty() || b.is_empty() {
|
|
1699
|
+
return serde_json::json!({"ok":false,"error":"empty array"}).to_string();
|
|
1700
|
+
}
|
|
1701
|
+
a.sort_by(|x, y| x.partial_cmp(y).unwrap_or(std::cmp::Ordering::Equal));
|
|
1702
|
+
b.sort_by(|x, y| x.partial_cmp(y).unwrap_or(std::cmp::Ordering::Equal));
|
|
1703
|
+
let n = a.len() as f64;
|
|
1704
|
+
let m = b.len() as f64;
|
|
1705
|
+
let mut i = 0usize; let mut j = 0usize;
|
|
1706
|
+
let mut max_d = 0.0f64;
|
|
1707
|
+
while i < a.len() && j < b.len() {
|
|
1708
|
+
let cdf_a = (i + 1) as f64 / n;
|
|
1709
|
+
let cdf_b = (j + 1) as f64 / m;
|
|
1710
|
+
let d = (cdf_a - cdf_b).abs();
|
|
1711
|
+
if d > max_d { max_d = d; }
|
|
1712
|
+
if a[i] <= b[j] { i += 1; } else { j += 1; }
|
|
1713
|
+
}
|
|
1714
|
+
let coeff = ((n * m) / (n + m)).sqrt();
|
|
1715
|
+
let lambda = (coeff + 0.12 + 0.11 / coeff) * max_d;
|
|
1716
|
+
let mut p_value = 0.0f64;
|
|
1717
|
+
let mut sign = 1.0f64;
|
|
1718
|
+
for k in 1..=100 {
|
|
1719
|
+
let term = sign * 2.0 * (-2.0 * lambda * lambda * (k * k) as f64).exp();
|
|
1720
|
+
p_value += term;
|
|
1721
|
+
sign = -sign;
|
|
1722
|
+
if term.abs() < 1e-10 { break; }
|
|
1723
|
+
}
|
|
1724
|
+
p_value = p_value.clamp(0.0, 1.0);
|
|
1725
|
+
let drift_detected = p_value < 0.05;
|
|
1726
|
+
serde_json::json!({
|
|
1727
|
+
"ok":true,
|
|
1728
|
+
"ks_statistic":max_d,
|
|
1729
|
+
"p_value":p_value,
|
|
1730
|
+
"drift_detected":drift_detected,
|
|
1731
|
+
"n_reference":a.len(),
|
|
1732
|
+
"n_current":b.len()
|
|
1733
|
+
}).to_string()
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1586
1736
|
pub fn bench_chart_value(s: &str) -> bool {
|
|
1587
1737
|
serde_json::from_str::<serde_json::Value>(s).is_ok()
|
|
1588
1738
|
}
|
|
@@ -39,6 +39,12 @@ pub fn register_submodules(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|
|
39
39
|
m.add_function(wrap_pyfunction!(export_png, m)?)?;
|
|
40
40
|
m.add_function(wrap_pyfunction!(chart_info, m)?)?;
|
|
41
41
|
m.add_class::<LiveStream>()?;
|
|
42
|
+
m.add_function(wrap_pyfunction!(facet, m)?)?;
|
|
43
|
+
m.add_function(wrap_pyfunction!(drift, m)?)?;
|
|
44
|
+
m.add_function(wrap_pyfunction!(lttb, m)?)?;
|
|
45
|
+
m.add_function(wrap_pyfunction!(show, m)?)?;
|
|
46
|
+
m.add_function(wrap_pyfunction!(auto_classify, m)?)?;
|
|
47
|
+
m.add_class::<Pipeline>()?;
|
|
42
48
|
|
|
43
49
|
for (alias, canonical) in crate::bindings::registry_macro::CHART_ALIASES {
|
|
44
50
|
if let Ok(func) = m.getattr(*canonical) {
|
|
@@ -187,6 +187,10 @@ macro_rules! for_each_fn {
|
|
|
187
187
|
$mac!(ml_save_model, "mlSaveModel");
|
|
188
188
|
$mac!(ml_load_model, "mlLoadModel");
|
|
189
189
|
$mac!(chart_info, "chartInfo");
|
|
190
|
+
$mac!(validate_input, "validateInput");
|
|
191
|
+
$mac!(downsample_lttb, "downsampleLttb");
|
|
192
|
+
$mac!(chart_diff, "chartDiff");
|
|
193
|
+
$mac!(drift_ks, "driftKs");
|
|
190
194
|
};
|
|
191
195
|
}
|
|
192
196
|
|
|
@@ -619,5 +623,160 @@ macro_rules! impl_python_bindings {
|
|
|
619
623
|
pub fn clear(&mut self) { self.xs.clear(); self.ys.clear(); }
|
|
620
624
|
#[getter] pub fn n(&self) -> usize { self.xs.len() }
|
|
621
625
|
}
|
|
626
|
+
|
|
627
|
+
#[pyfunction]
|
|
628
|
+
#[pyo3(signature = (charts, cols=2, gap=16, bg=None, cell_height=520))]
|
|
629
|
+
pub fn facet(
|
|
630
|
+
charts: Vec<pyo3::PyRef<crate::Chart>>,
|
|
631
|
+
cols: usize,
|
|
632
|
+
gap: i32,
|
|
633
|
+
bg: Option<&str>,
|
|
634
|
+
cell_height: i32,
|
|
635
|
+
) -> crate::Chart {
|
|
636
|
+
let html_strs: Vec<String> = charts.iter().map(|c| c.html.clone()).collect();
|
|
637
|
+
crate::Chart::new(
|
|
638
|
+
crate::bindings::commands::charts::build_grid(
|
|
639
|
+
&serde_json::json!({"charts": html_strs, "cols": cols, "gap": gap, "background": bg, "cell_height": cell_height}).to_string()
|
|
640
|
+
)
|
|
641
|
+
)
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
#[pyfunction]
|
|
645
|
+
#[pyo3(signature = (reference, current))]
|
|
646
|
+
pub fn drift(reference: Vec<f64>, current: Vec<f64>) -> String {
|
|
647
|
+
crate::bindings::commands::charts::drift_ks(
|
|
648
|
+
&serde_json::json!({"reference": reference, "current": current}).to_string()
|
|
649
|
+
)
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
#[pyfunction]
|
|
653
|
+
#[pyo3(signature = (input, threshold=2000))]
|
|
654
|
+
pub fn lttb(input: Vec<(f64, f64)>, threshold: usize) -> Vec<(f64, f64)> {
|
|
655
|
+
let xs: Vec<f64> = input.iter().map(|p| p.0).collect();
|
|
656
|
+
let ys: Vec<f64> = input.iter().map(|p| p.1).collect();
|
|
657
|
+
let res = crate::bindings::commands::charts::downsample_lttb(
|
|
658
|
+
&serde_json::json!({"x": xs, "y": ys, "threshold": threshold}).to_string()
|
|
659
|
+
);
|
|
660
|
+
let v: serde_json::Value = match serde_json::from_str(&res) { Ok(v) => v, Err(_) => return input };
|
|
661
|
+
let nx: Vec<f64> = v.get("x").and_then(|a| a.as_array()).map(|a| a.iter().filter_map(|n| n.as_f64()).collect()).unwrap_or_default();
|
|
662
|
+
let ny: Vec<f64> = v.get("y").and_then(|a| a.as_array()).map(|a| a.iter().filter_map(|n| n.as_f64()).collect()).unwrap_or_default();
|
|
663
|
+
nx.into_iter().zip(ny).collect()
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
#[pyfunction]
|
|
667
|
+
pub fn show(py: Python<'_>, chart: &crate::Chart) -> PyResult<()> {
|
|
668
|
+
chart.show(py)
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
#[pyfunction]
|
|
672
|
+
#[pyo3(signature = (x, y, models=None))]
|
|
673
|
+
pub fn auto_classify(py: Python<'_>, x: &PyAny, y: Vec<i64>, models: Option<Vec<String>>) -> PyResult<pyo3::Py<pyo3::types::PyDict>> {
|
|
674
|
+
let (flat, n, dims) = crate::bindings::commands::ml::extract_flat(x)?;
|
|
675
|
+
let chosen = models.unwrap_or_else(|| vec![
|
|
676
|
+
"logistic".to_string(),
|
|
677
|
+
"knn".to_string(),
|
|
678
|
+
"decision_tree".to_string(),
|
|
679
|
+
"random_forest".to_string(),
|
|
680
|
+
"gradient_boosting".to_string(),
|
|
681
|
+
]);
|
|
682
|
+
let mut leaderboard: Vec<(String, f64)> = Vec::new();
|
|
683
|
+
for name in chosen.iter() {
|
|
684
|
+
let payload = serde_json::json!({"x": flat, "n": n, "dims": dims, "y": y}).to_string();
|
|
685
|
+
let raw = match name.as_str() {
|
|
686
|
+
"logistic" => crate::bindings::commands::charts::ml_logistic_regression(&payload),
|
|
687
|
+
"knn" => crate::bindings::commands::charts::ml_knn_classifier(&payload),
|
|
688
|
+
"decision_tree" => crate::bindings::commands::charts::ml_decision_tree_classifier(&payload),
|
|
689
|
+
"random_forest" => crate::bindings::commands::charts::ml_random_forest_classifier(&payload),
|
|
690
|
+
"gradient_boosting" => crate::bindings::commands::charts::ml_gradient_boosting_classifier(&payload),
|
|
691
|
+
_ => continue,
|
|
692
|
+
};
|
|
693
|
+
let score = serde_json::from_str::<serde_json::Value>(&raw).ok()
|
|
694
|
+
.and_then(|v| v.get("score").and_then(|s| s.as_f64()))
|
|
695
|
+
.or_else(|| serde_json::from_str::<serde_json::Value>(&raw).ok().and_then(|v| v.get("accuracy").and_then(|s| s.as_f64())))
|
|
696
|
+
.unwrap_or(f64::NAN);
|
|
697
|
+
leaderboard.push((name.clone(), score));
|
|
698
|
+
}
|
|
699
|
+
leaderboard.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
|
|
700
|
+
let dict = pyo3::types::PyDict::new(py);
|
|
701
|
+
let lb = pyo3::types::PyList::empty(py);
|
|
702
|
+
for (name, score) in leaderboard.iter() {
|
|
703
|
+
let row = pyo3::types::PyDict::new(py);
|
|
704
|
+
row.set_item("model", name)?;
|
|
705
|
+
row.set_item("score", score)?;
|
|
706
|
+
lb.append(row)?;
|
|
707
|
+
}
|
|
708
|
+
dict.set_item("leaderboard", lb)?;
|
|
709
|
+
if let Some((best_name, best_score)) = leaderboard.first() {
|
|
710
|
+
dict.set_item("best_model", best_name)?;
|
|
711
|
+
dict.set_item("best_score", best_score)?;
|
|
712
|
+
}
|
|
713
|
+
Ok(dict.into())
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
#[pyclass(module = "seraplot", name = "Pipeline")]
|
|
717
|
+
pub struct Pipeline {
|
|
718
|
+
steps: Vec<(String, pyo3::PyObject)>,
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
#[pymethods]
|
|
722
|
+
impl Pipeline {
|
|
723
|
+
#[new]
|
|
724
|
+
#[pyo3(signature = (steps))]
|
|
725
|
+
pub fn py_new(steps: Vec<(String, pyo3::PyObject)>) -> Self {
|
|
726
|
+
Self { steps }
|
|
727
|
+
}
|
|
728
|
+
pub fn fit(&mut self, py: Python<'_>, x: &PyAny, y: Option<&PyAny>) -> PyResult<()> {
|
|
729
|
+
let mut current: pyo3::PyObject = x.into();
|
|
730
|
+
for (i, (_, step)) in self.steps.iter().enumerate() {
|
|
731
|
+
let st = step.as_ref(py);
|
|
732
|
+
let is_last = i == self.steps.len() - 1;
|
|
733
|
+
if is_last {
|
|
734
|
+
if let Some(yy) = y {
|
|
735
|
+
let _ = st.call_method1("fit", (current.as_ref(py), yy));
|
|
736
|
+
} else {
|
|
737
|
+
let _ = st.call_method1("fit", (current.as_ref(py),));
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
if let Some(yy) = y {
|
|
741
|
+
let _ = st.call_method1("fit", (current.as_ref(py), yy));
|
|
742
|
+
} else {
|
|
743
|
+
let _ = st.call_method1("fit", (current.as_ref(py),));
|
|
744
|
+
}
|
|
745
|
+
if let Ok(t) = st.call_method1("transform", (current.as_ref(py),)) {
|
|
746
|
+
current = t.into();
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
Ok(())
|
|
751
|
+
}
|
|
752
|
+
pub fn predict(&self, py: Python<'_>, x: &PyAny) -> PyResult<pyo3::PyObject> {
|
|
753
|
+
let mut current: pyo3::PyObject = x.into();
|
|
754
|
+
for (i, (_, step)) in self.steps.iter().enumerate() {
|
|
755
|
+
let st = step.as_ref(py);
|
|
756
|
+
let is_last = i == self.steps.len() - 1;
|
|
757
|
+
if is_last {
|
|
758
|
+
return Ok(st.call_method1("predict", (current.as_ref(py),))?.into());
|
|
759
|
+
}
|
|
760
|
+
if let Ok(t) = st.call_method1("transform", (current.as_ref(py),)) {
|
|
761
|
+
current = t.into();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
Ok(current)
|
|
765
|
+
}
|
|
766
|
+
pub fn transform(&self, py: Python<'_>, x: &PyAny) -> PyResult<pyo3::PyObject> {
|
|
767
|
+
let mut current: pyo3::PyObject = x.into();
|
|
768
|
+
for (_, step) in self.steps.iter() {
|
|
769
|
+
let st = step.as_ref(py);
|
|
770
|
+
if let Ok(t) = st.call_method1("transform", (current.as_ref(py),)) {
|
|
771
|
+
current = t.into();
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
Ok(current)
|
|
775
|
+
}
|
|
776
|
+
#[getter] pub fn step_names(&self) -> Vec<String> { self.steps.iter().map(|(n, _)| n.clone()).collect() }
|
|
777
|
+
fn __repr__(&self) -> String {
|
|
778
|
+
format!("Pipeline(steps={:?})", self.steps.iter().map(|(n, _)| n.clone()).collect::<Vec<_>>())
|
|
779
|
+
}
|
|
780
|
+
}
|
|
622
781
|
};
|
|
623
782
|
}
|
|
@@ -130,6 +130,17 @@
|
|
|
130
130
|
- [Auto Display](config/auto-display.md)
|
|
131
131
|
- [Hover JSON](config/hover.md)
|
|
132
132
|
- [Palette](config/palette.md)
|
|
133
|
+
- [Export (SVG / PNG / Data URL)](config/export.md)
|
|
134
|
+
- [Live Streaming](config/streaming.md)
|
|
135
|
+
- [ML Persistence](config/ml-persistence.md)
|
|
136
|
+
- [Faceting / Small Multiples](config/facet.md)
|
|
137
|
+
- [Downsampling (LTTB)](config/downsample.md)
|
|
138
|
+
- [Chart Diff](config/diff.md)
|
|
139
|
+
- [Accessibility (a11y)](config/a11y.md)
|
|
140
|
+
- [CSP-safe Mode](config/csp.md)
|
|
141
|
+
- [Pickle / Serialization](config/pickle.md)
|
|
142
|
+
- [AutoML & Pipeline](config/automl.md)
|
|
143
|
+
- [Drift Detection](config/drift.md)
|
|
133
144
|
|
|
134
145
|
---
|
|
135
146
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Accessibility (a11y)
|
|
2
|
+
|
|
3
|
+
<div class="lang-en">
|
|
4
|
+
|
|
5
|
+
Inject ARIA roles, `<title>` and `<desc>` into the chart SVG for screen readers and B2B compliance (WCAG 2.1).
|
|
6
|
+
|
|
7
|
+
## Python
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import seraplot as sp
|
|
11
|
+
|
|
12
|
+
chart = (
|
|
13
|
+
sp.bar([10,20,30], ["EU","US","APAC"])
|
|
14
|
+
.a11y(title="Quarterly revenue by region",
|
|
15
|
+
desc="Bar chart, EU 10M, US 20M, APAC 30M")
|
|
16
|
+
)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The resulting SVG includes `role="img"`, `aria-label`, `<title>`, `<desc>` — recognized by NVDA, JAWS, VoiceOver.
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="lang-fr">
|
|
24
|
+
|
|
25
|
+
Injecte les rôles ARIA, `<title>` et `<desc>` dans le SVG pour les lecteurs d'écran et la conformité B2B (WCAG 2.1).
|
|
26
|
+
|
|
27
|
+
## Python
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import seraplot as sp
|
|
31
|
+
|
|
32
|
+
chart = (
|
|
33
|
+
sp.bar([10,20,30], ["EU","US","APAC"])
|
|
34
|
+
.a11y(title="Revenu trimestriel par région",
|
|
35
|
+
desc="Bar chart, EU 10M, US 20M, APAC 30M")
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Le SVG résultant inclut `role="img"`, `aria-label`, `<title>`, `<desc>` — reconnus par NVDA, JAWS, VoiceOver.
|
|
40
|
+
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# AutoML & Pipeline
|
|
2
|
+
|
|
3
|
+
<div class="lang-en">
|
|
4
|
+
|
|
5
|
+
## auto_classify
|
|
6
|
+
|
|
7
|
+
Try several classifiers, return the leaderboard sorted by score.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import seraplot as sp
|
|
11
|
+
|
|
12
|
+
result = sp.auto_classify(X_train, y_train)
|
|
13
|
+
print(result["best_model"], result["best_score"])
|
|
14
|
+
for row in result["leaderboard"]:
|
|
15
|
+
print(row)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Default models: `logistic`, `knn`, `decision_tree`, `random_forest`, `gradient_boosting`. Customize with `models=["random_forest","knn"]`.
|
|
19
|
+
|
|
20
|
+
## Pipeline
|
|
21
|
+
|
|
22
|
+
Chain transformers + estimator (sklearn-compatible API).
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from seraplot import StandardScaler, RandomForestClassifier, Pipeline
|
|
26
|
+
|
|
27
|
+
pipe = Pipeline([
|
|
28
|
+
("scaler", StandardScaler()),
|
|
29
|
+
("model", RandomForestClassifier(n_estimators=200)),
|
|
30
|
+
])
|
|
31
|
+
pipe.fit(X_train, y_train)
|
|
32
|
+
preds = pipe.predict(X_test)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="lang-fr">
|
|
38
|
+
|
|
39
|
+
## auto_classify
|
|
40
|
+
|
|
41
|
+
Essaie plusieurs classifieurs, retourne le leaderboard trié par score.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import seraplot as sp
|
|
45
|
+
|
|
46
|
+
result = sp.auto_classify(X_train, y_train)
|
|
47
|
+
print(result["best_model"], result["best_score"])
|
|
48
|
+
for row in result["leaderboard"]:
|
|
49
|
+
print(row)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Modèles par défaut : `logistic`, `knn`, `decision_tree`, `random_forest`, `gradient_boosting`. Personnalisable avec `models=["random_forest","knn"]`.
|
|
53
|
+
|
|
54
|
+
## Pipeline
|
|
55
|
+
|
|
56
|
+
Enchaîne transformers + estimateur (API compatible sklearn).
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from seraplot import StandardScaler, RandomForestClassifier, Pipeline
|
|
60
|
+
|
|
61
|
+
pipe = Pipeline([
|
|
62
|
+
("scaler", StandardScaler()),
|
|
63
|
+
("model", RandomForestClassifier(n_estimators=200)),
|
|
64
|
+
])
|
|
65
|
+
pipe.fit(X_train, y_train)
|
|
66
|
+
preds = pipe.predict(X_test)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# CSP-safe Mode
|
|
2
|
+
|
|
3
|
+
<div class="lang-en">
|
|
4
|
+
|
|
5
|
+
Strict Content Security Policies block inline `<script>`. The `csp_safe()` method extracts JS into a `<script type="application/json">` payload + a single nonce-able loader.
|
|
6
|
+
|
|
7
|
+
## Python
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import seraplot as sp
|
|
11
|
+
|
|
12
|
+
chart = sp.line([1,2,3,4], [10,20,15,25]).csp_safe()
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Apply your CSP `script-src 'nonce-sp-nonce'` and the chart still renders.
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="lang-fr">
|
|
20
|
+
|
|
21
|
+
Les CSP strictes bloquent les `<script>` inline. La méthode `csp_safe()` extrait le JS dans un payload `<script type="application/json">` + un loader unique compatible nonce.
|
|
22
|
+
|
|
23
|
+
## Python
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import seraplot as sp
|
|
27
|
+
|
|
28
|
+
chart = sp.line([1,2,3,4], [10,20,15,25]).csp_safe()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Applique ta CSP `script-src 'nonce-sp-nonce'` et le chart se rend toujours.
|
|
32
|
+
|
|
33
|
+
</div>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Chart Diff
|
|
2
|
+
|
|
3
|
+
<div class="lang-en">
|
|
4
|
+
|
|
5
|
+
Compare two charts structurally — useful for visual CI / regression testing.
|
|
6
|
+
|
|
7
|
+
## Python
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import seraplot as sp
|
|
11
|
+
|
|
12
|
+
a = sp.bar([1,2,3], ["x","y","z"])
|
|
13
|
+
b = sp.bar([1,2,4], ["x","y","z"])
|
|
14
|
+
result = a.diff(b)
|
|
15
|
+
print(result)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Returns JSON: `{ "ok": true, "identical": false, "size_a": 4521, "size_b": 4523, "common_prefix": 4400, "similarity": 0.97 }`.
|
|
19
|
+
|
|
20
|
+
## JavaScript
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { chartDiff } from "seraplot";
|
|
24
|
+
const diff = JSON.parse(chartDiff(JSON.stringify({ a: htmlA, b: htmlB })));
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="lang-fr">
|
|
30
|
+
|
|
31
|
+
Compare deux charts structurellement — utile pour les CI visuelles / tests de régression.
|
|
32
|
+
|
|
33
|
+
## Python
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import seraplot as sp
|
|
37
|
+
|
|
38
|
+
a = sp.bar([1,2,3], ["x","y","z"])
|
|
39
|
+
b = sp.bar([1,2,4], ["x","y","z"])
|
|
40
|
+
result = a.diff(b)
|
|
41
|
+
print(result)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Retourne du JSON : `{ "ok": true, "identical": false, "size_a": 4521, "size_b": 4523, "common_prefix": 4400, "similarity": 0.97 }`.
|
|
45
|
+
|
|
46
|
+
## JavaScript
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import { chartDiff } from "seraplot";
|
|
50
|
+
const diff = JSON.parse(chartDiff(JSON.stringify({ a: htmlA, b: htmlB })));
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
</div>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Downsampling (LTTB)
|
|
2
|
+
|
|
3
|
+
<div class="lang-en">
|
|
4
|
+
|
|
5
|
+
Reduce massive datasets while preserving visual shape using the **Largest-Triangle-Three-Buckets** algorithm. A 10M-point scatter chart becomes 5K points indistinguishable to the eye.
|
|
6
|
+
|
|
7
|
+
## Python
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import seraplot as sp
|
|
11
|
+
|
|
12
|
+
chart = sp.scatter(big_x, big_y).downsample(n=5000)
|
|
13
|
+
|
|
14
|
+
points = sp.lttb(list(zip(big_x, big_y)), threshold=5000)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## JavaScript
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { downsampleLttb } from "seraplot";
|
|
21
|
+
const reduced = JSON.parse(downsampleLttb(JSON.stringify({ x, y, threshold: 5000 })));
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Why LTTB?
|
|
25
|
+
|
|
26
|
+
| Method | Preserves peaks | Speed | Visual fidelity |
|
|
27
|
+
|--------|----------------|-------|-----------------|
|
|
28
|
+
| Random sample | No | Fast | Poor |
|
|
29
|
+
| Every-Nth | Maybe | Fast | OK |
|
|
30
|
+
| **LTTB** | Yes | Fast | Excellent |
|
|
31
|
+
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="lang-fr">
|
|
35
|
+
|
|
36
|
+
Réduit les datasets massifs en préservant la forme visuelle avec l'algorithme **Largest-Triangle-Three-Buckets**. Un scatter de 10M points devient 5K points indistinguables à l'œil.
|
|
37
|
+
|
|
38
|
+
## Python
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import seraplot as sp
|
|
42
|
+
|
|
43
|
+
chart = sp.scatter(big_x, big_y).downsample(n=5000)
|
|
44
|
+
|
|
45
|
+
points = sp.lttb(list(zip(big_x, big_y)), threshold=5000)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## JavaScript
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
import { downsampleLttb } from "seraplot";
|
|
52
|
+
const reduced = JSON.parse(downsampleLttb(JSON.stringify({ x, y, threshold: 5000 })));
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Pourquoi LTTB ?
|
|
56
|
+
|
|
57
|
+
| Méthode | Préserve les pics | Vitesse | Fidélité visuelle |
|
|
58
|
+
|---------|-------------------|---------|-------------------|
|
|
59
|
+
| Échantillon aléatoire | Non | Rapide | Mauvaise |
|
|
60
|
+
| Tous les N | Peut-être | Rapide | OK |
|
|
61
|
+
| **LTTB** | Oui | Rapide | Excellente |
|
|
62
|
+
|
|
63
|
+
</div>
|