quantized-lab 0.8.1__tar.gz → 0.9.0__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.
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/PKG-INFO +1 -1
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/pyproject.toml +1 -1
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/__init__.py +1 -1
- quantized_lab-0.9.0/src/quantized/calc/figure_labels.py +127 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_overrides.py +24 -0
- quantized_lab-0.9.0/src/quantized/calc/figure_shapes.py +153 -0
- quantized_lab-0.9.0/src/quantized/web/assets/index-D8RNGjHO.js +27 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/web/index.html +1 -1
- quantized_lab-0.8.1/src/quantized/calc/figure_labels.py +0 -62
- quantized_lab-0.8.1/src/quantized/web/assets/index-BHmmCL-x.js +0 -27
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/.gitignore +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/LICENSE +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/NOTICE +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/README.md +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/__main__.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/api.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/app.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/__init__.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/_clipfit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/_natural_neighbor.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/aggregate.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/backgrounds.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/baseline.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/batch_fit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/constants.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/corrections.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/crystallography.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/diffusion.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/electrical.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/electrochemistry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/element_data.json +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/element_data.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/errors.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_break.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_categorical.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_corner.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_facets.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_field.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_hitmap.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_map.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_page.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_scale.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_statplots.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_styles.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_ternary.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/figure_ticks.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_autoguess.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_bootstrap.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_bumps.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_constraints.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_equation.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_findxy.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_models.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_models_special.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_odr.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_scan.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fit_stats.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/fitting.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/formula.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/global_curve_fit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/global_fit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/interp2d.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/linecut.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/magnetic.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/magnetometry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/map.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/mcmc.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/optics.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/pawley.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peak_batch.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peak_fit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peak_integrate.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peak_multifit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peak_track.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peaks.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/peakshapes.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/plotting.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/processing.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/qspace.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/reductions.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/reductions_fft.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/refl_sld_presets.json +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/reflectivity.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/registry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/relaxation.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/report.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/report_emit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/resample.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/rsm.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/rsm_analyze.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/semiconductor.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/sld.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/sld_formula.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/spectral.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/statplots.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_anova2.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_anova_ext.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_dist.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_glm.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_multivar.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_roc.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_survival.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/stats_tests.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/substrates.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/superconductor.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/surface_fit.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/surface_models.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/thermal.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/thin_film.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/unit_convert.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/units.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/vacuum.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/calc/xray.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/cli.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/datastruct.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/__init__.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/_hdf5_layout.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/_jcamp_asdf.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/_xrdml_scan.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/base.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/bruker_brml.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/bruker_raw.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/cif.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/consolidated.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/delimited.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/excel.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/hdf5.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/import_filters.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/import_preview.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/jcamp.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/lakeshore.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/ncnr.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/netcdf.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/opus.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_com.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/__init__.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/annotation_marks.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/container.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/curve_style_color.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/figure_geometry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/figure_layers.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/figure_text.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/figures.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/figures_opju.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/notes.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opj.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opj_curves.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opj_shapes.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_axis_real_form.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_axis_specimen_form.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_codec.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_curves.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_curves_allcols.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_figure_curves.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_figure_text.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/opju_reports.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/origin_richtext.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/preview.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/templates.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/tree.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/tree_opju.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/windows.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/windows_opju.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/writer.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/origin_project/writer_blocks.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/qd.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/refl1d.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/registry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/report_export.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/rigaku.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/sims.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/spc.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/xrd_csv.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/io/xrdml.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/jobs.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/plugins/__init__.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/plugins/contract.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/plugins/loader.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/plugins/steps.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/__init__.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/_bookcache.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/_export_common.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/_payload.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/_uploadcache.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/aggregate.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/baseline.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/books.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/calc.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/corrections.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/crystallography.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/diffusion.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/electrical.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/electrochemistry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/export.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/export_facets.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/export_figures.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/export_page.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/fitting.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/fitting_bumps.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/import_template.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/import_wizard.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/jobs_api.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/magnetic.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/magnetometry.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/optics.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/parsers.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/peaks.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/plot.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/reductions.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/reference.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/reflectivity.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/report_export.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/rsm.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/samples.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/semiconductor.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/sld.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/spectral.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/statplots.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/stats.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/stats_design.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/substrates.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/superconductor.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/thermal.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/thin_film.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/vacuum.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/routes/xray.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/samples/demo_vsm.csv +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/server_launch.py +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/web/assets/JetBrainsMono-Bold-CUogYd9I.woff2 +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/web/assets/JetBrainsMono-Regular-CA-Os4ii.woff2 +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/web/assets/index-BiZzN7J6.css +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/src/quantized/web/loading.html +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/tools/origin_compare/README.md +0 -0
- {quantized_lab-0.8.1 → quantized_lab-0.9.0}/tools/visual/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quantized-lab
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Plot, analyze, and publish lab data - magnetometry, XRD, reflectometry - with OriginPro file interop, golden-verified analysis, and reproducible pipelines.
|
|
5
5
|
Project-URL: Homepage, https://github.com/pquarterman17/quantized
|
|
6
6
|
Project-URL: Documentation, https://github.com/pquarterman17/quantized/wiki
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "quantized-lab"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.9.0"
|
|
4
4
|
description = "Plot, analyze, and publish lab data - magnetometry, XRD, reflectometry - with OriginPro file interop, golden-verified analysis, and reproducible pipelines."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Mathtext label guard for figure export (GOTO #5 rich-text labels).
|
|
2
|
+
|
|
3
|
+
Labels flow from the UI as plain text with optional ``$...$`` mathtext
|
|
4
|
+
regions (the frontend's ``lib/richtext`` micro-syntax is a strict subset of
|
|
5
|
+
matplotlib mathtext, so passthrough is the rendering mechanism). matplotlib
|
|
6
|
+
parses math regions at DRAW time, which means an invalid label would raise
|
|
7
|
+
inside ``fig.savefig`` and turn an export into a 500. This module is the
|
|
8
|
+
shared chokepoint every ``calc.figure*`` renderer routes its user-supplied
|
|
9
|
+
strings through: it pre-validates with matplotlib's own mathtext parser and,
|
|
10
|
+
on failure, escapes the dollar signs so the label renders as literal text
|
|
11
|
+
(matplotlib renders ``\\$`` as a plain ``$``) -- an invalid label must NEVER
|
|
12
|
+
error an export.
|
|
13
|
+
|
|
14
|
+
Screen/export WYSIWYG (bug-hunt fix): the frontend's parser
|
|
15
|
+
(``frontend/src/lib/richtext.ts``) only accepts a STRICT SUBSET of
|
|
16
|
+
mathtext -- Greek letters, ``\\AA \\circ \\times \\cdot \\pm \\prime \\,
|
|
17
|
+
\\mathrm \\mathit``, and literal Unicode -- and rejects everything else
|
|
18
|
+
(e.g. ``\\frac``, ``\\sqrt``, ``\\sum``) as invalid markup, rendering it
|
|
19
|
+
literally on screen. Raw matplotlib accepts a much larger command set, so
|
|
20
|
+
without this gate a label like ``$\\frac{1}{2}$`` would render literal text
|
|
21
|
+
("Invalid markup") on screen but an actual fraction in the PDF/SVG export --
|
|
22
|
+
a WYSIWYG violation. `_uses_only_supported_commands` enumerates the SAME
|
|
23
|
+
command set the frontend parser accepts and rejects (falls back to literal)
|
|
24
|
+
any ``$...$`` region using a command outside it, BEFORE the matplotlib trial
|
|
25
|
+
parse below ever runs. Keep `SUPPORTED_MATHTEXT_COMMANDS` in sync with
|
|
26
|
+
richtext.ts's ``GREEK``/``SYMBOLS`` tables + ``mathrm``/``mathit`` handling.
|
|
27
|
+
|
|
28
|
+
Pure layer: string in -> string out. matplotlib is imported lazily (same
|
|
29
|
+
convention as the figure modules -- the heavy import is paid only on export).
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import re
|
|
35
|
+
from functools import lru_cache
|
|
36
|
+
from typing import Any
|
|
37
|
+
|
|
38
|
+
__all__ = ["safe_mathtext_label", "SUPPORTED_MATHTEXT_COMMANDS"]
|
|
39
|
+
|
|
40
|
+
# A "$" not preceded by a backslash -- matplotlib's own math-region rule
|
|
41
|
+
# (matplotlib.cbook.is_math_text counts these; an odd count means the string
|
|
42
|
+
# is rendered as literal text, dollars visible, no mathtext at all).
|
|
43
|
+
_UNESCAPED_DOLLAR = re.compile(r"(?<!\\)\$")
|
|
44
|
+
|
|
45
|
+
# A backslash command name (`\foo`) inside a math region. `\,` (thin space)
|
|
46
|
+
# is handled separately by richtext.ts before its name-based dispatch and
|
|
47
|
+
# has no letters, so it never matches this and is implicitly always allowed.
|
|
48
|
+
_COMMAND = re.compile(r"\\([a-zA-Z]+)")
|
|
49
|
+
|
|
50
|
+
# Mirrors frontend/src/lib/richtext.ts's `GREEK` table: lowercase (+ \var*
|
|
51
|
+
# variants) render italic, uppercase upright -- irrelevant here, we only
|
|
52
|
+
# need the NAME set, not the styling.
|
|
53
|
+
_GREEK_COMMANDS = frozenset(
|
|
54
|
+
{
|
|
55
|
+
"alpha", "beta", "gamma", "delta", "epsilon", "varepsilon", "zeta",
|
|
56
|
+
"eta", "theta", "vartheta", "iota", "kappa", "lambda", "mu", "nu",
|
|
57
|
+
"xi", "pi", "rho", "sigma", "varsigma", "tau", "upsilon", "phi",
|
|
58
|
+
"varphi", "chi", "psi", "omega",
|
|
59
|
+
"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon",
|
|
60
|
+
"Phi", "Psi", "Omega",
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
# Mirrors richtext.ts's `SYMBOLS` table (non-Greek symbol commands).
|
|
64
|
+
_SYMBOL_COMMANDS = frozenset({"AA", "circ", "times", "cdot", "pm", "prime"})
|
|
65
|
+
# Mirrors richtext.ts's `\mathrm{...}` / `\mathit{...}` style-group handling.
|
|
66
|
+
_STYLE_COMMANDS = frozenset({"mathrm", "mathit"})
|
|
67
|
+
|
|
68
|
+
SUPPORTED_MATHTEXT_COMMANDS = _GREEK_COMMANDS | _SYMBOL_COMMANDS | _STYLE_COMMANDS
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _uses_only_supported_commands(label: str) -> bool:
|
|
72
|
+
"""True when every backslash command inside every ``$...$`` region of
|
|
73
|
+
`label` is in `SUPPORTED_MATHTEXT_COMMANDS`. Text OUTSIDE `$...$` is
|
|
74
|
+
never scanned -- a stray backslash there is the caller's problem, not
|
|
75
|
+
this gate's (and richtext.ts itself only ever considers commands inside
|
|
76
|
+
math regions). Assumes a balanced (even) unescaped-`$` count, as
|
|
77
|
+
guaranteed by `safe_mathtext_label` calling this only after that check.
|
|
78
|
+
"""
|
|
79
|
+
segments = _UNESCAPED_DOLLAR.split(label)
|
|
80
|
+
for i, segment in enumerate(segments):
|
|
81
|
+
if i % 2 == 0:
|
|
82
|
+
continue # literal text outside $...$
|
|
83
|
+
for m in _COMMAND.finditer(segment):
|
|
84
|
+
if m.group(1) not in SUPPORTED_MATHTEXT_COMMANDS:
|
|
85
|
+
return False
|
|
86
|
+
return True
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@lru_cache(maxsize=1)
|
|
90
|
+
def _parser() -> Any:
|
|
91
|
+
"""The mathtext trial parser (cached -- construction is not free)."""
|
|
92
|
+
from matplotlib.mathtext import MathTextParser
|
|
93
|
+
|
|
94
|
+
return MathTextParser("agg")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def safe_mathtext_label(label: str) -> str:
|
|
98
|
+
"""Return ``label`` unchanged when it renders safely; else de-math it.
|
|
99
|
+
|
|
100
|
+
- No ``$`` at all: fast path, returned as-is (byte-identical to today).
|
|
101
|
+
- Odd count of unescaped ``$``: matplotlib already treats the whole
|
|
102
|
+
string as literal text -- returned as-is.
|
|
103
|
+
- Balanced ``$...$`` regions using only commands the frontend's
|
|
104
|
+
richtext.ts subset also accepts (`SUPPORTED_MATHTEXT_COMMANDS`), AND
|
|
105
|
+
that trial-parse successfully with matplotlib's mathtext parser ->
|
|
106
|
+
unchanged (mathtext renders it at export, matching the screen).
|
|
107
|
+
Otherwise (an out-of-subset command, e.g. ``\\frac``/``\\sqrt``/
|
|
108
|
+
``\\sum``, OR a parse failure even within the subset, e.g. unbalanced
|
|
109
|
+
braces) -> every unescaped ``$`` is escaped to ``\\$`` so matplotlib
|
|
110
|
+
renders the literal string (dollars visible) instead of raising at
|
|
111
|
+
savefig time OR silently rendering richer math than the screen ever
|
|
112
|
+
showed.
|
|
113
|
+
"""
|
|
114
|
+
if not label or "$" not in label:
|
|
115
|
+
return label
|
|
116
|
+
n_math = len(_UNESCAPED_DOLLAR.findall(label))
|
|
117
|
+
if n_math == 0 or n_math % 2 == 1:
|
|
118
|
+
# Zero unescaped $ (all \$-escaped) or an odd count: matplotlib
|
|
119
|
+
# already renders the whole string as literal text -- leave it be.
|
|
120
|
+
return label
|
|
121
|
+
if not _uses_only_supported_commands(label):
|
|
122
|
+
return _UNESCAPED_DOLLAR.sub(r"\\$", label)
|
|
123
|
+
try:
|
|
124
|
+
_parser().parse(label)
|
|
125
|
+
except Exception: # ANY parse failure means "render literal", never raise
|
|
126
|
+
return _UNESCAPED_DOLLAR.sub(r"\\$", label)
|
|
127
|
+
return label
|
|
@@ -17,6 +17,7 @@ from collections.abc import Mapping
|
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
19
|
from quantized.calc.figure_labels import safe_mathtext_label
|
|
20
|
+
from quantized.calc.figure_shapes import _apply_shapes, _validate_shapes
|
|
20
21
|
|
|
21
22
|
__all__ = ["_apply_overrides", "_validate_overrides"]
|
|
22
23
|
|
|
@@ -63,6 +64,7 @@ def _validate_overrides(ov: Mapping[str, Any]) -> None:
|
|
|
63
64
|
if prev_hi is not None and lo < prev_hi:
|
|
64
65
|
raise ValueError("x_breaks entries must be sorted and non-overlapping")
|
|
65
66
|
prev_hi = hi
|
|
67
|
+
_validate_shapes(ov.get("shapes"))
|
|
66
68
|
|
|
67
69
|
|
|
68
70
|
def _apply_overrides(
|
|
@@ -142,6 +144,23 @@ def _apply_overrides(
|
|
|
142
144
|
# pixel-identical placement between screen and export.
|
|
143
145
|
ann_kw["xycoords"] = "figure fraction"
|
|
144
146
|
y = 1.0 - y
|
|
147
|
+
frame = ann.get("frame")
|
|
148
|
+
if frame:
|
|
149
|
+
# MAIN #27 "text box": a bbox behind the annotation text. `pad`
|
|
150
|
+
# (screen CSS px around the measured text) has no exact
|
|
151
|
+
# matplotlib equivalent (`boxstyle="square,pad=N"`'s pad is in
|
|
152
|
+
# font-size units, not px) -- divided by a fixed factor so the
|
|
153
|
+
# box reads as padded rather than pixel-identical, the same
|
|
154
|
+
# "Origin-parity-in-spirit, not pixel-identical" caveat the
|
|
155
|
+
# page-anchor y-flip above documents. fc/ec default to a plain
|
|
156
|
+
# white-card-on-black-border look (independent of the screen's
|
|
157
|
+
# own dark-canvas ink default -- publication export is white-bg).
|
|
158
|
+
ann_kw["bbox"] = dict(
|
|
159
|
+
boxstyle=f"square,pad={float(frame.get('pad', 4)) / 4.0}",
|
|
160
|
+
fc=frame.get("fill") or "white",
|
|
161
|
+
ec=frame.get("stroke") or "black",
|
|
162
|
+
alpha=frame.get("opacity", 1.0),
|
|
163
|
+
)
|
|
145
164
|
ax.annotate(
|
|
146
165
|
safe_mathtext_label(str(ann.get("text", ""))),
|
|
147
166
|
xy=(x, y),
|
|
@@ -157,3 +176,8 @@ def _apply_overrides(
|
|
|
157
176
|
top=None if margins.get("top") is None else 1.0 - float(margins["top"]),
|
|
158
177
|
bottom=margins.get("bottom"),
|
|
159
178
|
)
|
|
179
|
+
|
|
180
|
+
# MAIN #27: shapes paint LAST -- on top of everything else this sweep
|
|
181
|
+
# drew (annotations included), matching export intent: shapes mark up
|
|
182
|
+
# the finished figure.
|
|
183
|
+
_apply_shapes(fig, ax, ov.get("shapes"))
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Drawn-shape overrides (MAIN #27) -- export parity for the screen's
|
|
2
|
+
``lib/uplotShapes.ts``. Split out of ``figure_overrides.py`` purely to stay
|
|
3
|
+
under each module's line-count discipline (same reasoning as
|
|
4
|
+
``figure_labels.py`` / ``figure_break.py``) -- the behavioural contract is
|
|
5
|
+
still ``figure_overrides``'s; ``_apply_overrides`` calls ``_apply_shapes``
|
|
6
|
+
as its last step, AFTER the annotation sweep, so shapes paint on TOP of
|
|
7
|
+
everything else the override sweep drew (annotations included) -- matching
|
|
8
|
+
export intent: shapes mark up the finished figure. Pure layer: mapping in ->
|
|
9
|
+
mutates the passed matplotlib Figure/Axes, no return value.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from collections.abc import Mapping, Sequence
|
|
15
|
+
from typing import Any, Literal
|
|
16
|
+
|
|
17
|
+
from matplotlib.lines import Line2D
|
|
18
|
+
from matplotlib.patches import Ellipse, FancyArrowPatch, Rectangle
|
|
19
|
+
|
|
20
|
+
__all__ = ["_apply_shapes", "_validate_shapes"]
|
|
21
|
+
|
|
22
|
+
_SHAPE_KINDS = frozenset({"arrow", "line", "rect", "ellipse"})
|
|
23
|
+
|
|
24
|
+
# Default whole-shape opacity (fill AND stroke, ONE knob) mirroring the
|
|
25
|
+
# screen's `defaultShapeOpacity` (lib/uplotShapes.ts): 1 for line/arrow, 0.35
|
|
26
|
+
# for rect/ellipse (a freshly drawn box reads as visibly translucent OVER
|
|
27
|
+
# the data it marks).
|
|
28
|
+
_DEFAULT_OPACITY = {"arrow": 1.0, "line": 1.0, "rect": 0.35, "ellipse": 0.35}
|
|
29
|
+
_DEFAULT_WIDTH = 1.5
|
|
30
|
+
_DEFAULT_STROKE = "black"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _validate_shapes(shapes: Sequence[Mapping[str, Any]] | None) -> None:
|
|
34
|
+
"""Raise ``ValueError`` on a malformed shape (bad kind, non-finite
|
|
35
|
+
coords); a shape with an unknown/missing key inside is otherwise
|
|
36
|
+
tolerant (unknown keys ignored), mirroring ``_validate_overrides``."""
|
|
37
|
+
if not shapes:
|
|
38
|
+
return
|
|
39
|
+
for sh in shapes:
|
|
40
|
+
kind = sh.get("kind")
|
|
41
|
+
if kind not in _SHAPE_KINDS:
|
|
42
|
+
raise ValueError(f"shape kind must be one of {sorted(_SHAPE_KINDS)}")
|
|
43
|
+
for key in ("x1", "y1", "x2", "y2"):
|
|
44
|
+
v = sh.get(key)
|
|
45
|
+
if not isinstance(v, (int, float)) or isinstance(v, bool):
|
|
46
|
+
raise ValueError(f"shape {key} must be a number")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _shape_endpoints(
|
|
50
|
+
sh: Mapping[str, Any], ax: Any, fig: Any
|
|
51
|
+
) -> tuple[tuple[float, float], tuple[float, float], Any]:
|
|
52
|
+
"""(p1, p2, transform) for one shape, resolving its anchor -- DATA (the
|
|
53
|
+
default: ``ax.transData``, applied implicitly by omitting ``transform``
|
|
54
|
+
and adding via ``ax.add_patch``/``ax.add_line``) or PAGE (explicit
|
|
55
|
+
``fig.transFigure``, Y FLIPPED -- canvas y grows downward, matplotlib
|
|
56
|
+
figure fraction grows upward -- the SAME convention
|
|
57
|
+
``_apply_overrides``'s page-anchored annotation uses)."""
|
|
58
|
+
x1, y1 = float(sh["x1"]), float(sh["y1"])
|
|
59
|
+
x2, y2 = float(sh["x2"]), float(sh["y2"])
|
|
60
|
+
if sh.get("anchor") == "page":
|
|
61
|
+
return (x1, 1.0 - y1), (x2, 1.0 - y2), fig.transFigure
|
|
62
|
+
return (x1, y1), (x2, y2), ax.transData
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _apply_shapes(fig: Any, ax: Any, shapes: Sequence[Mapping[str, Any]] | None) -> None:
|
|
66
|
+
"""Draw MAIN #27 shapes (arrow/line/rect/ellipse). Arrows use
|
|
67
|
+
``FancyArrowPatch``; plain lines ``Line2D``; rect/ellipse the matching
|
|
68
|
+
matplotlib patch with ``alpha`` -- all added via ``ax.add_patch``/
|
|
69
|
+
``ax.add_line`` (data-anchored, the default -- no explicit ``transform``
|
|
70
|
+
needed there; matplotlib resolves an artist added this way against
|
|
71
|
+
``ax.transData``) or with an EXPLICIT ``transform=fig.transFigure`` for
|
|
72
|
+
a page-anchored shape (``ax.add_patch``/``add_line`` never override an
|
|
73
|
+
already-set transform -- verified empirically, see the porting notes).
|
|
74
|
+
"""
|
|
75
|
+
if not shapes:
|
|
76
|
+
return
|
|
77
|
+
for sh in shapes:
|
|
78
|
+
kind = sh.get("kind")
|
|
79
|
+
if kind not in _SHAPE_KINDS:
|
|
80
|
+
continue
|
|
81
|
+
p1, p2, transform = _shape_endpoints(sh, ax, fig)
|
|
82
|
+
stroke = sh.get("stroke") or _DEFAULT_STROKE
|
|
83
|
+
# `is not None` (not `or`): an explicit `width: 0` is falsy in Python
|
|
84
|
+
# and `... or _DEFAULT_WIDTH` was silently replacing it with the
|
|
85
|
+
# default (1.5) -- unlike the correct `opacity` idiom two lines below.
|
|
86
|
+
width = float(sh["width"]) if sh.get("width") is not None else _DEFAULT_WIDTH
|
|
87
|
+
dash: Literal["-", "--"] = "--" if sh.get("dash") else "-"
|
|
88
|
+
opacity = sh.get("opacity")
|
|
89
|
+
opacity = float(opacity) if opacity is not None else _DEFAULT_OPACITY[kind]
|
|
90
|
+
fill = sh.get("fill") or stroke
|
|
91
|
+
patch: Any
|
|
92
|
+
|
|
93
|
+
if kind == "arrow":
|
|
94
|
+
patch = FancyArrowPatch(
|
|
95
|
+
p1,
|
|
96
|
+
p2,
|
|
97
|
+
transform=transform,
|
|
98
|
+
arrowstyle="-|>",
|
|
99
|
+
mutation_scale=12 + width * 4,
|
|
100
|
+
# matplotlib's FancyArrowPatch default shrinkA/shrinkB=2pt
|
|
101
|
+
# insets BOTH ends from the given points (meant for
|
|
102
|
+
# "annotate near, not touching, an object") -- WYSIWYG with
|
|
103
|
+
# the screen's canvas draw (no shrink at all) needs the
|
|
104
|
+
# endpoints to land EXACTLY where dragged.
|
|
105
|
+
shrinkA=0,
|
|
106
|
+
shrinkB=0,
|
|
107
|
+
color=stroke,
|
|
108
|
+
linewidth=width,
|
|
109
|
+
linestyle=dash,
|
|
110
|
+
alpha=opacity,
|
|
111
|
+
)
|
|
112
|
+
ax.add_patch(patch)
|
|
113
|
+
elif kind == "line":
|
|
114
|
+
line = Line2D(
|
|
115
|
+
[p1[0], p2[0]],
|
|
116
|
+
[p1[1], p2[1]],
|
|
117
|
+
transform=transform,
|
|
118
|
+
color=stroke,
|
|
119
|
+
linewidth=width,
|
|
120
|
+
linestyle=dash,
|
|
121
|
+
alpha=opacity,
|
|
122
|
+
)
|
|
123
|
+
ax.add_line(line)
|
|
124
|
+
elif kind == "rect":
|
|
125
|
+
x0, x1v = min(p1[0], p2[0]), max(p1[0], p2[0])
|
|
126
|
+
y0, y1v = min(p1[1], p2[1]), max(p1[1], p2[1])
|
|
127
|
+
patch = Rectangle(
|
|
128
|
+
(x0, y0),
|
|
129
|
+
x1v - x0,
|
|
130
|
+
y1v - y0,
|
|
131
|
+
transform=transform,
|
|
132
|
+
edgecolor=stroke,
|
|
133
|
+
facecolor=fill,
|
|
134
|
+
linewidth=width,
|
|
135
|
+
linestyle=dash,
|
|
136
|
+
alpha=opacity,
|
|
137
|
+
)
|
|
138
|
+
ax.add_patch(patch)
|
|
139
|
+
else: # ellipse
|
|
140
|
+
cx, cy = (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2
|
|
141
|
+
w, h = abs(p2[0] - p1[0]), abs(p2[1] - p1[1])
|
|
142
|
+
patch = Ellipse(
|
|
143
|
+
(cx, cy),
|
|
144
|
+
w,
|
|
145
|
+
h,
|
|
146
|
+
transform=transform,
|
|
147
|
+
edgecolor=stroke,
|
|
148
|
+
facecolor=fill,
|
|
149
|
+
linewidth=width,
|
|
150
|
+
linestyle=dash,
|
|
151
|
+
alpha=opacity,
|
|
152
|
+
)
|
|
153
|
+
ax.add_patch(patch)
|