jarvisplot 1.2.3__tar.gz → 1.2.5__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.2.3 → jarvisplot-1.2.5}/PKG-INFO +1 -1
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/data_loader.py +197 -75
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/inner_func.py +14 -19
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot.egg-info/PKG-INFO +1 -1
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/pyproject.toml +1 -1
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/README.md +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/__init__.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/adapters.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/data_pipelines.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/figure.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/helper.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/load_data.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/method_registry.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/Figure/preprocessor.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/__init__.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cache_store.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/args.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/colors/colormaps.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/default/output.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/gambit/2x1/ternary.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/icons/gambit.png +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/icons/gambit_small.png +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cards/style_preference.json +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/cli.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/client.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/config.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/core.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/utils/__init__.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/utils/cmaps.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot/utils/interpolator.py +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot.egg-info/SOURCES.txt +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot.egg-info/dependency_links.txt +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot.egg-info/entry_points.txt +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot.egg-info/requires.txt +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/jarvisplot.egg-info/top_level.txt +0 -0
- {jarvisplot-1.2.3 → jarvisplot-1.2.5}/setup.cfg +0 -0
|
@@ -120,6 +120,15 @@ class DataSet():
|
|
|
120
120
|
return f" HDF5 loaded!\n\t name -> {self.name}\n\t group -> {self.group}\n\t path -> {self.path}"
|
|
121
121
|
return f" CSV loaded!\n\t name -> {self.name}\n\t path -> {self.path}"
|
|
122
122
|
|
|
123
|
+
def _debug_enabled(self) -> bool:
|
|
124
|
+
"""Best-effort check for loguru debug level without assuming logger internals."""
|
|
125
|
+
try:
|
|
126
|
+
core = getattr(self.logger, "_core", None)
|
|
127
|
+
min_level = getattr(core, "min_level", 100)
|
|
128
|
+
return int(min_level) <= 10
|
|
129
|
+
except Exception:
|
|
130
|
+
return False
|
|
131
|
+
|
|
123
132
|
def _emit_summary_text(self, summary_msg: str) -> None:
|
|
124
133
|
if self.logger:
|
|
125
134
|
self.logger.warning("\n" + str(summary_msg))
|
|
@@ -429,37 +438,74 @@ class DataSet():
|
|
|
429
438
|
_, path, ds = best
|
|
430
439
|
return path, ds[()]
|
|
431
440
|
|
|
432
|
-
def
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
# prefix columns to keep dataset origin
|
|
436
|
-
if name:
|
|
437
|
-
df.columns = [f"{name}:{c}" for c in df.columns]
|
|
438
|
-
return df
|
|
439
|
-
elif hasattr(arr, "ndim") and arr.ndim == 2:
|
|
440
|
-
cols = [f"col{i}" for i in range(arr.shape[1])]
|
|
441
|
-
if name:
|
|
442
|
-
cols = [f"{name}:{c}" for c in cols]
|
|
443
|
-
return pd.DataFrame(arr, columns=cols)
|
|
444
|
-
else:
|
|
445
|
-
col = name if name else "value"
|
|
446
|
-
return pd.DataFrame({col: np.ravel(arr)})
|
|
447
|
-
|
|
448
|
-
def _collect_group_datasets(g: h5py.Group, prefix: str="", whitelist=None):
|
|
449
|
-
"""Recursively collect (path, ndarray) for all datasets under a group."""
|
|
450
|
-
items = []
|
|
441
|
+
def _collect_group_dataset_paths(g: h5py.Group, prefix: str="", whitelist=None):
|
|
442
|
+
"""Recursively collect dataset paths under a group."""
|
|
443
|
+
paths = []
|
|
451
444
|
for k, v in g.items():
|
|
452
445
|
path = f"{prefix}/{k}" if prefix else k
|
|
453
446
|
if isinstance(v, h5py.Dataset):
|
|
454
447
|
if whitelist is None or path in whitelist:
|
|
455
|
-
|
|
448
|
+
paths.append(path)
|
|
456
449
|
elif isinstance(v, h5py.Group):
|
|
457
|
-
|
|
458
|
-
return
|
|
450
|
+
paths.extend(_collect_group_dataset_paths(v, path, whitelist=whitelist))
|
|
451
|
+
return paths
|
|
452
|
+
|
|
453
|
+
def _dataset_to_columns(path: str, ds: h5py.Dataset, row_mask=None, rename_map=None):
|
|
454
|
+
"""
|
|
455
|
+
Convert one HDF5 dataset to DataFrame-ready columns.
|
|
456
|
+
Returns: (columns_dict, nrows, shape_tuple)
|
|
457
|
+
"""
|
|
458
|
+
arr = ds[()]
|
|
459
|
+
|
|
460
|
+
def _apply_mask(vec):
|
|
461
|
+
if row_mask is None:
|
|
462
|
+
return vec
|
|
463
|
+
if len(vec) != len(row_mask):
|
|
464
|
+
raise ValueError(
|
|
465
|
+
"HDF5 row mismatch while applying is_valid mask: "
|
|
466
|
+
f"dataset='{path}', rows={len(vec)}, mask_rows={len(row_mask)}"
|
|
467
|
+
)
|
|
468
|
+
return vec[row_mask]
|
|
469
|
+
|
|
470
|
+
def _map_name(name: str) -> str:
|
|
471
|
+
if isinstance(rename_map, dict):
|
|
472
|
+
return rename_map.get(name, name)
|
|
473
|
+
return name
|
|
474
|
+
|
|
475
|
+
if isinstance(arr, np.ndarray) and getattr(arr.dtype, "names", None):
|
|
476
|
+
# Structured array: one output column per field
|
|
477
|
+
out = {}
|
|
478
|
+
for fname in arr.dtype.names:
|
|
479
|
+
src = f"{path}:{fname}"
|
|
480
|
+
dst = _map_name(src)
|
|
481
|
+
vec = np.asarray(arr[fname]).reshape(-1)
|
|
482
|
+
out[dst] = _apply_mask(vec)
|
|
483
|
+
nrows = len(next(iter(out.values()))) if out else 0
|
|
484
|
+
return out, nrows, (nrows, len(out))
|
|
485
|
+
|
|
486
|
+
if hasattr(arr, "ndim") and getattr(arr, "ndim", 0) == 2:
|
|
487
|
+
# 2D array: one output column per axis-1 entry
|
|
488
|
+
out = {}
|
|
489
|
+
nrows = int(arr.shape[0])
|
|
490
|
+
ncols = int(arr.shape[1])
|
|
491
|
+
for i in range(ncols):
|
|
492
|
+
src = f"{path}:col{i}"
|
|
493
|
+
dst = _map_name(src)
|
|
494
|
+
out[dst] = _apply_mask(arr[:, i])
|
|
495
|
+
out_rows = len(next(iter(out.values()))) if out else 0
|
|
496
|
+
return out, out_rows, (nrows, ncols)
|
|
497
|
+
|
|
498
|
+
# Scalar / 1D / anything else: flatten to one column
|
|
499
|
+
flat = np.ravel(arr)
|
|
500
|
+
src = path if path else "value"
|
|
501
|
+
dst = _map_name(src)
|
|
502
|
+
out = _apply_mask(flat)
|
|
503
|
+
return {dst: out}, len(out), (len(flat), 1)
|
|
459
504
|
|
|
460
505
|
with h5py.File(self.path, "r") as f1:
|
|
461
|
-
#
|
|
462
|
-
|
|
506
|
+
# Tree traversal is expensive on large files; keep it behind debug mode.
|
|
507
|
+
if self._debug_enabled() and self.group in f1:
|
|
508
|
+
print_hdf5_tree_ascii(f1[self.group], root_name=self.group, logger=self.logger)
|
|
463
509
|
|
|
464
510
|
if self.group in f1 and isinstance(f1[self.group], h5py.Group):
|
|
465
511
|
group = f1[self.group]
|
|
@@ -473,9 +519,9 @@ class DataSet():
|
|
|
473
519
|
"HDF5 load_whitelist enabled -> {} paths".format(len(whitelist))
|
|
474
520
|
)
|
|
475
521
|
|
|
476
|
-
# Collect
|
|
477
|
-
|
|
478
|
-
if not
|
|
522
|
+
# Collect dataset paths only (defer heavy reads to reduce peak memory)
|
|
523
|
+
dataset_paths = _collect_group_dataset_paths(group, prefix=self.group, whitelist=whitelist)
|
|
524
|
+
if not dataset_paths:
|
|
479
525
|
if whitelist is not None:
|
|
480
526
|
raise RuntimeError(
|
|
481
527
|
"HDF5 group '{}' has no datasets after applying columns.load_whitelist.".format(
|
|
@@ -484,43 +530,110 @@ class DataSet():
|
|
|
484
530
|
)
|
|
485
531
|
raise RuntimeError(f"HDF5 group '{self.group}' contains no datasets.")
|
|
486
532
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
533
|
+
dataset_set = set(dataset_paths)
|
|
534
|
+
base_paths = [p for p in dataset_paths if not p.endswith("_isvalid")]
|
|
535
|
+
isvalid_paths = [p for p in dataset_paths if p.endswith("_isvalid")]
|
|
536
|
+
|
|
537
|
+
# Step 1: parse columns config and finalize rename mapping first.
|
|
538
|
+
rename_entries = self._columns_dict().get("rename", [])
|
|
539
|
+
rename_map = {}
|
|
540
|
+
if isinstance(rename_entries, list) and rename_entries:
|
|
541
|
+
self.logger.warning("{}: Loading Columns Rename Map".format(self.name))
|
|
542
|
+
for item in rename_entries:
|
|
543
|
+
if not isinstance(item, dict):
|
|
544
|
+
continue
|
|
545
|
+
source = str(item.get("source", "")).strip()
|
|
546
|
+
target = str(item.get("target", "")).strip()
|
|
547
|
+
if not source or not target:
|
|
548
|
+
continue
|
|
549
|
+
source_canon = self._canonical_dataset_path(source)
|
|
550
|
+
rename_map[source_canon] = target
|
|
551
|
+
rename_map[f"{source_canon}_isvalid"] = f"{target}_isvalid"
|
|
552
|
+
|
|
553
|
+
# Step 2: build row mask by isvalid policy, before main table assembly.
|
|
554
|
+
row_mask = None
|
|
555
|
+
filter_rows_before = None
|
|
556
|
+
filter_rows_after = None
|
|
557
|
+
required_base = self._whitelist_base_paths if isinstance(self._whitelist_base_paths, set) else None
|
|
558
|
+
|
|
559
|
+
if self.isvalid_policy == "clean":
|
|
560
|
+
filter_isvalid_paths = []
|
|
561
|
+
if required_base is not None:
|
|
562
|
+
missing_base = sorted([c for c in required_base if c not in dataset_set])
|
|
563
|
+
missing_isvalid = sorted([f"{c}_isvalid" for c in required_base if f"{c}_isvalid" not in dataset_set])
|
|
564
|
+
if missing_base or missing_isvalid:
|
|
565
|
+
self.logger.warning(
|
|
566
|
+
"Skip is_valid policy: not all whitelist columns have companion _isvalid columns. "
|
|
567
|
+
"missing_base={}, missing_isvalid={}".format(missing_base, missing_isvalid)
|
|
568
|
+
)
|
|
569
|
+
else:
|
|
570
|
+
filter_isvalid_paths = [f"{c}_isvalid" for c in sorted(required_base)]
|
|
571
|
+
else:
|
|
572
|
+
# No whitelist: use all available *_isvalid columns with base companions.
|
|
573
|
+
filter_isvalid_paths = [p for p in isvalid_paths if p[:-8] in dataset_set]
|
|
574
|
+
|
|
575
|
+
if filter_isvalid_paths:
|
|
576
|
+
mask = None
|
|
577
|
+
nrows_ref = None
|
|
578
|
+
for vp in filter_isvalid_paths:
|
|
579
|
+
vec = np.ravel(f1[vp][()]).astype(bool, copy=False)
|
|
580
|
+
if nrows_ref is None:
|
|
581
|
+
nrows_ref = len(vec)
|
|
582
|
+
mask = vec.copy()
|
|
583
|
+
else:
|
|
584
|
+
if len(vec) != nrows_ref:
|
|
585
|
+
raise ValueError(
|
|
586
|
+
"HDF5 is_valid datasets have inconsistent row counts: '{}' has {}, expected {}.".format(
|
|
587
|
+
vp, len(vec), nrows_ref
|
|
588
|
+
)
|
|
589
|
+
)
|
|
590
|
+
mask &= vec
|
|
591
|
+
row_mask = mask
|
|
592
|
+
filter_rows_before = int(nrows_ref or 0)
|
|
593
|
+
filter_rows_after = int(mask.sum()) if mask is not None else filter_rows_before
|
|
594
|
+
|
|
595
|
+
# Step 3: decide final output columns, then assemble DataFrame once.
|
|
596
|
+
# clean mode drops *_isvalid by default; if whitelist is incomplete, keep them (existing behavior).
|
|
597
|
+
read_paths = list(base_paths)
|
|
598
|
+
if self.isvalid_policy == "raw":
|
|
599
|
+
read_paths.extend(isvalid_paths)
|
|
600
|
+
elif required_base is not None and row_mask is None:
|
|
601
|
+
read_paths.extend(isvalid_paths)
|
|
602
|
+
|
|
603
|
+
merged_cols = {}
|
|
604
|
+
shapes = {}
|
|
605
|
+
expected_rows = None
|
|
606
|
+
row_mismatch = False
|
|
607
|
+
for path in read_paths:
|
|
608
|
+
ds = f1[path]
|
|
609
|
+
cols_dict, nrows, shape_token = _dataset_to_columns(path, ds, row_mask=row_mask, rename_map=rename_map)
|
|
610
|
+
shapes[path] = shape_token
|
|
611
|
+
|
|
612
|
+
if expected_rows is None:
|
|
613
|
+
expected_rows = nrows
|
|
614
|
+
elif nrows != expected_rows:
|
|
615
|
+
row_mismatch = True
|
|
616
|
+
|
|
617
|
+
for cname, cval in cols_dict.items():
|
|
618
|
+
merged_cols[cname] = cval
|
|
619
|
+
|
|
620
|
+
if not row_mismatch:
|
|
501
621
|
# safe to concat by columns → single merged DataFrame only
|
|
502
|
-
self.data = pd.
|
|
622
|
+
self.data = pd.DataFrame(merged_cols, copy=False)
|
|
503
623
|
|
|
504
624
|
self.keys = list(self.data.columns)
|
|
505
|
-
|
|
506
|
-
self.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if not source or not target:
|
|
518
|
-
continue
|
|
519
|
-
source_canon = self._canonical_dataset_path(source)
|
|
520
|
-
cmap[source_canon] = target
|
|
521
|
-
cmap[f"{source_canon}_isvalid"] = f"{target}_isvalid"
|
|
522
|
-
if cmap:
|
|
523
|
-
self.rename_columns(cmap)
|
|
625
|
+
|
|
626
|
+
if row_mask is not None and self.isvalid_policy == "clean":
|
|
627
|
+
self.logger.warning("Filtering Invalid Data from HDF5 Output")
|
|
628
|
+
self.logger.warning(
|
|
629
|
+
"DataSet Shape: \n\t Before filtering -> ({}, {})\n\t After filtering -> ({}, {})".format(
|
|
630
|
+
filter_rows_before if filter_rows_before is not None else self.data.shape[0],
|
|
631
|
+
self.data.shape[1],
|
|
632
|
+
filter_rows_after if filter_rows_after is not None else self.data.shape[0],
|
|
633
|
+
self.data.shape[1],
|
|
634
|
+
)
|
|
635
|
+
)
|
|
636
|
+
|
|
524
637
|
self._apply_dataset_transform(stage="hdf5")
|
|
525
638
|
|
|
526
639
|
# Emit a pretty summary BEFORE returning
|
|
@@ -542,7 +655,6 @@ class DataSet():
|
|
|
542
655
|
print_hdf5_tree_ascii(group, root_name=self.group, logger=self.logger)
|
|
543
656
|
except Exception:
|
|
544
657
|
pass
|
|
545
|
-
shapes = {p: df.shape for p, df in dfs}
|
|
546
658
|
raise ValueError(
|
|
547
659
|
"HDF5 group '{grp}' is invalid for merging: datasets have different row counts. "
|
|
548
660
|
"Please fix the input or choose a different dataset/group. Details: {details}".format(
|
|
@@ -557,16 +669,14 @@ class DataSet():
|
|
|
557
669
|
if self.data is None:
|
|
558
670
|
self.load(force=False)
|
|
559
671
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
if
|
|
563
|
-
for col in self.keys:
|
|
564
|
-
if isinstance(col, str) and col.endswith("_isvalid"):
|
|
565
|
-
all_isvalid_cols.append(col)
|
|
672
|
+
source_cols = list(self.keys or [])
|
|
673
|
+
source_col_set = set(source_cols)
|
|
674
|
+
all_isvalid_cols = [col for col in source_cols if isinstance(col, str) and col.endswith("_isvalid")]
|
|
566
675
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
676
|
+
isvalids = [
|
|
677
|
+
kk for kk in kkeys
|
|
678
|
+
if isinstance(kk, str) and kk.endswith("_isvalid") and kk[:-8] in source_col_set
|
|
679
|
+
]
|
|
570
680
|
|
|
571
681
|
# Fallback: if mapping by kkeys fails, still use loaded *_isvalid columns.
|
|
572
682
|
if not isvalids:
|
|
@@ -574,9 +684,8 @@ class DataSet():
|
|
|
574
684
|
|
|
575
685
|
required_base = self._whitelist_base_paths if isinstance(self._whitelist_base_paths, set) else None
|
|
576
686
|
if required_base is not None:
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
missing_isvalid = sorted([f"{c}_isvalid" for c in required_base if f"{c}_isvalid" not in loaded_cols])
|
|
687
|
+
missing_base = sorted([c for c in required_base if c not in source_col_set])
|
|
688
|
+
missing_isvalid = sorted([f"{c}_isvalid" for c in required_base if f"{c}_isvalid" not in source_col_set])
|
|
580
689
|
if missing_base or missing_isvalid:
|
|
581
690
|
self.logger.warning(
|
|
582
691
|
"Skip is_valid policy: not all whitelist columns have companion _isvalid columns. "
|
|
@@ -642,9 +751,21 @@ def dataframe_summary(df: pd.DataFrame, name: str = "") -> str:
|
|
|
642
751
|
tail = max(0, width - head - 3)
|
|
643
752
|
return s[:head] + "..." + s[-tail:]
|
|
644
753
|
|
|
754
|
+
def human_bytes(num_bytes: int) -> str:
|
|
755
|
+
size = float(max(0, num_bytes))
|
|
756
|
+
for unit in ("B", "KB", "MB", "GB", "TB"):
|
|
757
|
+
if size < 1024.0 or unit == "TB":
|
|
758
|
+
return f"{size:.2f} {unit}"
|
|
759
|
+
size /= 1024.0
|
|
760
|
+
|
|
645
761
|
nrows, ncols = df.shape
|
|
646
762
|
cols = list(df.columns)
|
|
647
763
|
show_cols = cols[:]
|
|
764
|
+
try:
|
|
765
|
+
# Fast estimate (deep=False) to avoid expensive scans on large object columns.
|
|
766
|
+
mem_bytes = int(df.memory_usage(index=True, deep=False).sum())
|
|
767
|
+
except Exception:
|
|
768
|
+
mem_bytes = 0
|
|
648
769
|
|
|
649
770
|
# Compute per-column stats for the shown columns
|
|
650
771
|
dtypes = df[show_cols].dtypes.astype(str)
|
|
@@ -699,7 +820,8 @@ def dataframe_summary(df: pd.DataFrame, name: str = "") -> str:
|
|
|
699
820
|
head_lines = []
|
|
700
821
|
if name:
|
|
701
822
|
head_lines.append(f"Selected dataset:{name}")
|
|
702
|
-
head_lines.append(f"DataFrame shape
|
|
823
|
+
head_lines.append(f"\t DataFrame shape\t-> {nrows}\t rows × {ncols} \tcols")
|
|
824
|
+
head_lines.append(f"\t Approx memory usage\t-> {human_bytes(mem_bytes)}")
|
|
703
825
|
head_lines.append("=== DataFrame Summary Table ===")
|
|
704
826
|
|
|
705
827
|
# Column table header
|
|
@@ -136,23 +136,14 @@ def LogGauss(xx, mean, err):
|
|
|
136
136
|
return prob
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
def _extract_operas_full_name_map(
|
|
140
|
-
"""Build `namespace.function -> callable` map from Jarvis-Operas
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
continue
|
|
148
|
-
for short_name, symbol_fn in attrs.items():
|
|
149
|
-
if not isinstance(short_name, str):
|
|
150
|
-
continue
|
|
151
|
-
symbolic_name = str(symbol_fn)
|
|
152
|
-
fn = numeric_funcs.get(symbolic_name)
|
|
153
|
-
if callable(fn):
|
|
154
|
-
full_name_map[f"{namespace}.{short_name}"] = fn
|
|
155
|
-
return full_name_map
|
|
139
|
+
def _extract_operas_full_name_map():
|
|
140
|
+
"""Build `namespace.function -> callable` map from Jarvis-Operas registry."""
|
|
141
|
+
try:
|
|
142
|
+
from jarvis_operas import build_register_dicts
|
|
143
|
+
|
|
144
|
+
return build_register_dicts()
|
|
145
|
+
except Exception:
|
|
146
|
+
return {}
|
|
156
147
|
|
|
157
148
|
|
|
158
149
|
def _build_operas_eval_namespaces(full_name_map):
|
|
@@ -184,11 +175,15 @@ def update_funcs(funcs):
|
|
|
184
175
|
# Keep both symbolic/numeric views for compatibility, and provide
|
|
185
176
|
# namespace-style objects so plain `eval` can call `namespace.func(x)`.
|
|
186
177
|
try:
|
|
187
|
-
from jarvis_operas import
|
|
178
|
+
from jarvis_operas import build_sympy_dicts
|
|
188
179
|
|
|
180
|
+
operas_full_name_map = _extract_operas_full_name_map()
|
|
181
|
+
func_locals, numeric_funcs = build_sympy_dicts(
|
|
182
|
+
operas_full_name_map,
|
|
183
|
+
include_all=True,
|
|
184
|
+
)
|
|
189
185
|
funcs.update(numeric_funcs)
|
|
190
186
|
funcs.update(func_locals)
|
|
191
|
-
operas_full_name_map = _extract_operas_full_name_map(func_locals, numeric_funcs)
|
|
192
187
|
funcs.update(operas_full_name_map)
|
|
193
188
|
funcs.update(_build_operas_eval_namespaces(operas_full_name_map))
|
|
194
189
|
except Exception:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|