jarvisplot 1.3.11__tar.gz → 1.4.1__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.
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/JarvisPLOT.egg-info/PKG-INFO +1 -1
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/JarvisPLOT.egg-info/SOURCES.txt +4 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/PKG-INFO +1 -1
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/adapters_rect.py +9 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/colorbar_runtime.py +2 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/density_cell_runtime.py +101 -15
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/figure.py +6 -0
- jarvisplot-1.4.1/jarvisplot/Figure/figure_types.py +597 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/interp_2d_runtime.py +60 -97
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/interp_natural_neighbor_exact.py +3 -1
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/layer_runtime.py +119 -6
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/method_registry.py +1 -0
- jarvisplot-1.4.1/jarvisplot/Figure/posterior_density_runtime.py +226 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/posterior_hpd.py +89 -0
- jarvisplot-1.4.1/jarvisplot/Figure/posterior_mesh.py +1416 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/preprocessor.py +50 -8
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/preprocessor_runtime.py +25 -1
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/flowchart/default.json +1 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/core.py +2 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/core_runtime.py +62 -10
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/data_loader_runtime.py +14 -1
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/flowchart.py +149 -5
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/pyproject.toml +1 -1
- jarvisplot-1.4.1/tests/test_density_cell_transform.py +523 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_figure_contracts.py +135 -0
- jarvisplot-1.4.1/tests/test_figure_type_expander.py +272 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_flowchart_renderer.py +71 -1
- jarvisplot-1.3.11/tests/test_density_cell_transform.py +0 -147
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/JarvisPLOT.egg-info/entry_points.txt +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/JarvisPLOT.egg-info/requires.txt +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/JarvisPLOT.egg-info/top_level.txt +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/README.md +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/__init__.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/adapters_ternary.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/config_runtime.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/data_pipelines.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/dynesty_runtime.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/helper.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/interp_natural_neighbor.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/layout_runtime.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/profile_runtime.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/Figure/style_runtime.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/__init__.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cache_store.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/args.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/colors/colormaps.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/default/output.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/gambit/2x1/ternary.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/flowchart/JarvisHEP.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/flowchart/calculator.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/flowchart/inputfile.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/flowchart/opera.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/flowchart/outputfile.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/flowchart/sampler.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/gambit.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/icons/gambit_small.png +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cards/style_preference.json +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/cli.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/client.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/config.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/core_assets.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/data_loader.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/data_loader_hdf5.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/data_loader_summary.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/inner_func.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/memtrace.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/utils/__init__.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/utils/cmaps.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/utils/dataframes.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/utils/expression.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/utils/interpolator.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/jarvisplot/utils/pathing.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/setup.cfg +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_data_loader_contracts.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_docs_status_labels.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_interp_2d_transform.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_interp_natural_neighbor.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_interpolator_contracts.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_jpcontour_methods.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_parse_data_metadata.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_pathing_contracts.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_posterior_hpd.py +0 -0
- {jarvisplot-1.3.11 → jarvisplot-1.4.1}/tests/test_template_json.py +0 -0
|
@@ -30,6 +30,7 @@ jarvisplot/Figure/data_pipelines.py
|
|
|
30
30
|
jarvisplot/Figure/density_cell_runtime.py
|
|
31
31
|
jarvisplot/Figure/dynesty_runtime.py
|
|
32
32
|
jarvisplot/Figure/figure.py
|
|
33
|
+
jarvisplot/Figure/figure_types.py
|
|
33
34
|
jarvisplot/Figure/helper.py
|
|
34
35
|
jarvisplot/Figure/interp_2d_runtime.py
|
|
35
36
|
jarvisplot/Figure/interp_natural_neighbor.py
|
|
@@ -37,7 +38,9 @@ jarvisplot/Figure/interp_natural_neighbor_exact.py
|
|
|
37
38
|
jarvisplot/Figure/layer_runtime.py
|
|
38
39
|
jarvisplot/Figure/layout_runtime.py
|
|
39
40
|
jarvisplot/Figure/method_registry.py
|
|
41
|
+
jarvisplot/Figure/posterior_density_runtime.py
|
|
40
42
|
jarvisplot/Figure/posterior_hpd.py
|
|
43
|
+
jarvisplot/Figure/posterior_mesh.py
|
|
41
44
|
jarvisplot/Figure/preprocessor.py
|
|
42
45
|
jarvisplot/Figure/preprocessor_runtime.py
|
|
43
46
|
jarvisplot/Figure/profile_runtime.py
|
|
@@ -82,6 +85,7 @@ tests/test_data_loader_contracts.py
|
|
|
82
85
|
tests/test_density_cell_transform.py
|
|
83
86
|
tests/test_docs_status_labels.py
|
|
84
87
|
tests/test_figure_contracts.py
|
|
88
|
+
tests/test_figure_type_expander.py
|
|
85
89
|
tests/test_flowchart_renderer.py
|
|
86
90
|
tests/test_interp_2d_transform.py
|
|
87
91
|
tests/test_interp_natural_neighbor.py
|
|
@@ -475,6 +475,15 @@ class StdAxesAdapter:
|
|
|
475
475
|
artists = self.ax.plot(x, y, **kw)
|
|
476
476
|
return _auto_clip(artists, self.ax, self._clip_path)
|
|
477
477
|
|
|
478
|
+
def quiver(self, **kwargs):
|
|
479
|
+
x = kwargs.pop("x")
|
|
480
|
+
y = kwargs.pop("y")
|
|
481
|
+
u = kwargs.pop("u")
|
|
482
|
+
v = kwargs.pop("v")
|
|
483
|
+
kw = self._merge("quiver", kwargs)
|
|
484
|
+
artists = self.ax.quiver(x, y, u, v, **kw)
|
|
485
|
+
return _auto_clip(artists, self.ax, self._clip_path)
|
|
486
|
+
|
|
478
487
|
def fill(self, **kwargs):
|
|
479
488
|
x, y = kwargs.pop("x"), kwargs.pop("y")
|
|
480
489
|
kw = self._merge("fill", kwargs)
|
|
@@ -394,6 +394,8 @@ def collect_and_attach_colorbar(
|
|
|
394
394
|
if not axc._cb.get("used"):
|
|
395
395
|
frame = getattr(fig, "frame", {})
|
|
396
396
|
color_cfg = axc_color_config(frame, cb_name)
|
|
397
|
+
if color_cfg.get("cmap") is None and style.get("cmap") is not None:
|
|
398
|
+
color_cfg["cmap"] = style.get("cmap")
|
|
397
399
|
data_range = collect_layer_color_range(
|
|
398
400
|
df,
|
|
399
401
|
coor,
|
|
@@ -7,7 +7,9 @@ import numpy as np
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
|
|
9
9
|
from ..memtrace import memtrace_checkpoint
|
|
10
|
+
from ..utils.pathing import resolve_project_path
|
|
10
11
|
from ..utils.expression import eval_dataframe_expression
|
|
12
|
+
from .posterior_mesh import build_posterior_mesh, conservative_density, mesh_diagnostics_frame
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
_DENSITY_CELL_TYPES = {"make_density_core"}
|
|
@@ -67,7 +69,11 @@ def _coord_cfg(cfg: Mapping[str, Any], key: str) -> Mapping[str, Any]:
|
|
|
67
69
|
|
|
68
70
|
|
|
69
71
|
def _output_name(cfg: Mapping[str, Any], key: str, default: str) -> str:
|
|
70
|
-
|
|
72
|
+
output = cfg.get("output", {})
|
|
73
|
+
if isinstance(output, Mapping) and output.get(key) is not None:
|
|
74
|
+
name = output.get(key, default)
|
|
75
|
+
else:
|
|
76
|
+
name = _coord_cfg(cfg, key).get("name", default)
|
|
71
77
|
text = str(name).strip()
|
|
72
78
|
return text or default
|
|
73
79
|
|
|
@@ -144,7 +150,7 @@ def _unproject_axis(values: np.ndarray, lim: Tuple[float, float], scale: str) ->
|
|
|
144
150
|
return lo + values * (hi - lo)
|
|
145
151
|
|
|
146
152
|
|
|
147
|
-
def _grid_shape(cfg: Mapping[str, Any], default: int =
|
|
153
|
+
def _grid_shape(cfg: Mapping[str, Any], default: int = 64) -> Tuple[int, int]:
|
|
148
154
|
grid = cfg.get("grid", {})
|
|
149
155
|
if not isinstance(grid, Mapping):
|
|
150
156
|
grid = {}
|
|
@@ -309,7 +315,7 @@ def _bridson_density_cell(x, y, w, cfg, logger):
|
|
|
309
315
|
bridson = cfg.get("bridson", {})
|
|
310
316
|
if not isinstance(bridson, Mapping):
|
|
311
317
|
bridson = {}
|
|
312
|
-
bin_value = int(bridson.get("bin", bridson.get("bins", cfg.get("bin",
|
|
318
|
+
bin_value = int(bridson.get("bin", bridson.get("bins", cfg.get("bin", cfg.get("bins", 64)))))
|
|
313
319
|
if bin_value <= 0:
|
|
314
320
|
raise ValueError("make_density_core bridson bin must be positive.")
|
|
315
321
|
radius = 1.0 / float(bin_value)
|
|
@@ -318,20 +324,31 @@ def _bridson_density_cell(x, y, w, cfg, logger):
|
|
|
318
324
|
k = int(bridson.get("k", bridson.get("candidates", 30)))
|
|
319
325
|
support = _bridson_points(radius, seed=seed, k=k)
|
|
320
326
|
samples = np.column_stack([xp[inside], yp[inside]])
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
327
|
+
mesh_cfg = cfg.get("_mesh_debug", {})
|
|
328
|
+
if not isinstance(mesh_cfg, Mapping):
|
|
329
|
+
mesh_cfg = {}
|
|
330
|
+
refinement_cfg = cfg.get("refinement", mesh_cfg.get("refinement", None))
|
|
331
|
+
mesh = build_posterior_mesh(
|
|
332
|
+
support,
|
|
333
|
+
samples,
|
|
334
|
+
w[inside],
|
|
335
|
+
xlim=(0.0, 1.0),
|
|
336
|
+
ylim=(0.0, 1.0),
|
|
337
|
+
include_polygons=bool(mesh_cfg.get("include_polygons", False)),
|
|
338
|
+
strict_geometry=False,
|
|
339
|
+
geometry_space="normalized",
|
|
340
|
+
refinement=refinement_cfg if isinstance(refinement_cfg, Mapping) else None,
|
|
341
|
+
)
|
|
342
|
+
_bridson_density_cell.last_mesh = mesh
|
|
343
|
+
mass = mesh.masses
|
|
344
|
+
xs = _unproject_axis(mesh.generators[:, 0], xlim, xscale)
|
|
345
|
+
ys = _unproject_axis(mesh.generators[:, 1], ylim, yscale)
|
|
332
346
|
return xs, ys, mass
|
|
333
347
|
|
|
334
348
|
|
|
349
|
+
_bridson_density_cell.last_mesh = None # type: ignore[attr-defined]
|
|
350
|
+
|
|
351
|
+
|
|
335
352
|
def _kde_core(x, y, w, cfg, logger):
|
|
336
353
|
xlim = _axis_lim(x, cfg, "x")
|
|
337
354
|
ylim = _axis_lim(y, cfg, "y")
|
|
@@ -376,6 +393,60 @@ def _diagnostics(*, method: str, input_count: int, output_count: int, normalize:
|
|
|
376
393
|
)
|
|
377
394
|
|
|
378
395
|
|
|
396
|
+
def _mesh_diagnostics(mesh) -> str:
|
|
397
|
+
if mesh is None:
|
|
398
|
+
return ""
|
|
399
|
+
diag = getattr(mesh, "diagnostics", {}) or {}
|
|
400
|
+
return (
|
|
401
|
+
"\nposterior mesh diagnostics:\n"
|
|
402
|
+
f"\t generators \t-> {int(diag.get('generator_count', 0))}\n"
|
|
403
|
+
f"\t nonzero_mass \t-> {int(diag.get('nonzero_mass_generators', 0))}\n"
|
|
404
|
+
f"\t empty_generators -> {int(diag.get('empty_generators', 0))}\n"
|
|
405
|
+
f"\t area_method \t-> {diag.get('area_method', 'not_performed')}\n"
|
|
406
|
+
f"\t geometry_space \t-> {diag.get('geometry_space', 'unknown')}\n"
|
|
407
|
+
f"\t max_centroid_drift -> {float(diag.get('max_centroid_drift', float('nan'))):.17g}\n"
|
|
408
|
+
f"\t max_anisotropy \t-> {float(diag.get('max_anisotropy_ratio', float('nan'))):.17g}\n"
|
|
409
|
+
f"\t mass_vs_geometry_corr -> {float(diag.get('mass_geometry_stress_corr', float('nan'))):.17g}\n"
|
|
410
|
+
f"\t refinement_enabled -> {bool(diag.get('refinement_enabled', False))}\n"
|
|
411
|
+
f"\t refinement_iters -> {int(diag.get('refinement_iterations_completed', 0))}\n"
|
|
412
|
+
f"\t refinement_splits -> {int(diag.get('refinement_splits', 0))}\n"
|
|
413
|
+
f"\t refinement_merges -> {int(diag.get('refinement_merges', 0))}"
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _export_mesh_debug(mesh, cfg: Mapping[str, Any], xs: np.ndarray, ys: np.ndarray, logger) -> None:
|
|
418
|
+
if mesh is None:
|
|
419
|
+
return
|
|
420
|
+
mesh_cfg = cfg.get("_mesh_debug", {})
|
|
421
|
+
if not isinstance(mesh_cfg, Mapping):
|
|
422
|
+
return
|
|
423
|
+
target = mesh_cfg.get("to_csv", mesh_cfg.get("path", None))
|
|
424
|
+
if target is None:
|
|
425
|
+
return
|
|
426
|
+
path = str(target).strip()
|
|
427
|
+
if not path:
|
|
428
|
+
return
|
|
429
|
+
base_dir = cfg.get("_base_dir", None)
|
|
430
|
+
out_path = resolve_project_path(path, base_dir=base_dir)
|
|
431
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
432
|
+
frame = mesh_diagnostics_frame(mesh, x=xs, y=ys)
|
|
433
|
+
try:
|
|
434
|
+
xlim = _axis_lim(np.asarray(xs, dtype=float), cfg, "x")
|
|
435
|
+
ylim = _axis_lim(np.asarray(ys, dtype=float), cfg, "y")
|
|
436
|
+
xscale = _axis_scale(cfg, "x")
|
|
437
|
+
yscale = _axis_scale(cfg, "y")
|
|
438
|
+
centroid_x = _unproject_axis(mesh.centroid_proposal[:, 0], xlim, xscale)
|
|
439
|
+
centroid_y = _unproject_axis(mesh.centroid_proposal[:, 1], ylim, yscale)
|
|
440
|
+
frame["centroid_x"] = centroid_x
|
|
441
|
+
frame["centroid_y"] = centroid_y
|
|
442
|
+
frame["drift_x"] = centroid_x - np.asarray(xs, dtype=float)
|
|
443
|
+
frame["drift_y"] = centroid_y - np.asarray(ys, dtype=float)
|
|
444
|
+
except Exception:
|
|
445
|
+
pass
|
|
446
|
+
frame.to_csv(out_path, index=False)
|
|
447
|
+
_logger_emit(logger, "warning", f"posterior mesh diagnostics exported -> {out_path}")
|
|
448
|
+
|
|
449
|
+
|
|
379
450
|
def density_cell(df: pd.DataFrame, cfg: Mapping[str, Any], logger=None) -> pd.DataFrame:
|
|
380
451
|
"""
|
|
381
452
|
Construct a minimal posterior density-support table from raw samples.
|
|
@@ -387,19 +458,29 @@ def density_cell(df: pd.DataFrame, cfg: Mapping[str, Any], logger=None) -> pd.Da
|
|
|
387
458
|
if not isinstance(df, pd.DataFrame):
|
|
388
459
|
raise TypeError("make_density_core expects a pandas DataFrame.")
|
|
389
460
|
cfg = cfg if isinstance(cfg, Mapping) else {}
|
|
390
|
-
method = str(cfg.get("method", "
|
|
461
|
+
method = str(cfg.get("method", "bridson")).strip().lower()
|
|
391
462
|
if method not in {"grid", "bridson", "kde"}:
|
|
392
463
|
raise ValueError("make_density_core method must be one of: grid, bridson, kde.")
|
|
393
464
|
memtrace_checkpoint(logger, "make_density_core.before", df)
|
|
465
|
+
density_cell.last_mesh = None
|
|
394
466
|
x, y, w, input_count = _prepare_samples(df, cfg, logger)
|
|
395
467
|
if method == "grid":
|
|
396
468
|
xs, ys, mass = _grid_density_cell(x, y, w, cfg, logger)
|
|
397
469
|
elif method == "bridson":
|
|
398
470
|
xs, ys, mass = _bridson_density_cell(x, y, w, cfg, logger)
|
|
471
|
+
density_cell.last_mesh = _bridson_density_cell.last_mesh
|
|
399
472
|
else:
|
|
400
473
|
xs, ys, mass = _kde_core(x, y, w, cfg, logger)
|
|
401
474
|
normalize = bool(cfg.get("normalize", True))
|
|
402
475
|
mass = _normalize(mass, enabled=normalize)
|
|
476
|
+
if density_cell.last_mesh is not None:
|
|
477
|
+
density_cell.last_mesh.masses = np.asarray(mass, dtype=float)
|
|
478
|
+
density_cell.last_mesh.densities = conservative_density(
|
|
479
|
+
density_cell.last_mesh.masses,
|
|
480
|
+
density_cell.last_mesh.areas,
|
|
481
|
+
)
|
|
482
|
+
density_cell.last_mesh.diagnostics["mass_sum"] = float(np.sum(density_cell.last_mesh.masses))
|
|
483
|
+
_export_mesh_debug(density_cell.last_mesh, cfg, xs, ys, logger)
|
|
403
484
|
names = (
|
|
404
485
|
_output_name(cfg, "x", "x"),
|
|
405
486
|
_output_name(cfg, "y", "y"),
|
|
@@ -417,6 +498,8 @@ def density_cell(df: pd.DataFrame, cfg: Mapping[str, Any], logger=None) -> pd.Da
|
|
|
417
498
|
total=float(np.sum(out[names[2]].to_numpy(dtype=float))),
|
|
418
499
|
)
|
|
419
500
|
if bool(cfg.get("diagnostics", True)):
|
|
501
|
+
if method == "bridson":
|
|
502
|
+
msg += _mesh_diagnostics(density_cell.last_mesh)
|
|
420
503
|
_logger_emit(logger, "warning", msg)
|
|
421
504
|
memtrace_checkpoint(
|
|
422
505
|
logger,
|
|
@@ -425,3 +508,6 @@ def density_cell(df: pd.DataFrame, cfg: Mapping[str, Any], logger=None) -> pd.Da
|
|
|
425
508
|
extra={"method": method, "rows": int(out.shape[0]), "weight_sum": float(np.sum(out[names[2]]))},
|
|
426
509
|
)
|
|
427
510
|
return out
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
density_cell.last_mesh = None # type: ignore[attr-defined]
|
|
@@ -711,6 +711,7 @@ class Figure:
|
|
|
711
711
|
read-only during the main render loop.
|
|
712
712
|
"""
|
|
713
713
|
cb_ranges: dict[str, list] = {}
|
|
714
|
+
cb_style_cmaps: dict[str, object] = {}
|
|
714
715
|
|
|
715
716
|
for ax, ly in self._render_queue:
|
|
716
717
|
cb_name = ly.get("colorbar", "axc")
|
|
@@ -724,6 +725,9 @@ class Figure:
|
|
|
724
725
|
if not layer_uses_color(style, coor, method_key):
|
|
725
726
|
continue
|
|
726
727
|
|
|
728
|
+
if style.get("cmap") is not None:
|
|
729
|
+
cb_style_cmaps.setdefault(cb_name, style.get("cmap"))
|
|
730
|
+
|
|
727
731
|
# Load data (pipeline cache hit on second call in render loop)
|
|
728
732
|
runtime_load_layer_runtime_data(self, ly)
|
|
729
733
|
df = ly.get("data")
|
|
@@ -742,6 +746,8 @@ class Figure:
|
|
|
742
746
|
if axc_obj is None or not hasattr(axc_obj, "_cb"):
|
|
743
747
|
continue
|
|
744
748
|
color_cfg = axc_color_config(self.frame, cb_name)
|
|
749
|
+
if color_cfg.get("cmap") is None and cb_name in cb_style_cmaps:
|
|
750
|
+
color_cfg["cmap"] = cb_style_cmaps[cb_name]
|
|
745
751
|
axc_obj._cb.update(
|
|
746
752
|
precompute_colorbar_cb(color_cfg, ranges, logger=self.logger)
|
|
747
753
|
)
|