nvflare.tool.agent.dataset_inspect module
Static dataset classification for nvflare agent inspect.
Classifies a data-only directory as a tabular or image dataset and emits a
metadata-only evidence block. It never emits values from rows classified
as data and never emits pixel data, and follows no symlinks. The one
inference in the block is the header row: names are emitted only under
the strong rule (every numeric-bodied column non-numeric, names unique
and non-empty), and a masked data row that satisfies all of that is
emitted as names — by construction no inference can tell it from a
header, so datasets with masked/sentinel first rows must declare names. Read bounds: text and image reads are capped at
max_file_bytes each (worst case max_files x max_file_bytes);
parquet metadata reads parse only the file footer via pyarrow — they are
not capped by max_file_bytes and are accounted in scan at file
size as the upper bound.
Dataset block contract (all keys always present per modality):
modality:tabular|image|mixed, decided per site, not by file-count share. Targeted shapes: a tabular dataset tolerates stray images (<= 2 per site, e.g. exported plots); an image dataset tolerates companion tabular metadata (<= 4 files per site, e.g. train/val/test label files, flaggedtabular_companions, never a statistics target); tiny sites inside both tolerance windows resolve to the side with more files overall; anything else — an image-only site among tabular sites, materially both modalities, or a dead file-count tie — ismixed, reported but not routed (target_typestaysunknown_target).layout:per_site_directories|flat|root_and_site_directories(root-level data files coexist with site directories — ambiguous site mapping, an ask/fail-closed input for the consumer; the root group appears as site.).file_census: extension -> count (bounded; seecounts_approximate).counts_approximate: true when a walk limit was hit.scan:files_read/bytes_readperformed by this classification.sites: per top-level directory (or.when flat): - always:name,data_files,tabular_files,image_files; - tabular/parquet:format,header,column_count,features,dtypes,row_count,row_count_approximate, and for parquetschema_available.header: presentmeans “names available” (parquet always has names when readable);header: ambiguousmeans names must be user-supplied.row_countaggregates every tabular file in the site; sharded CSV sites are always approximate (per-shard headers are unknowable; a shard whose header-like first row disagrees with the site schema flagsshard_schema_consistent: false), parquet shards are exact metadata sums when the shards agree on schema. Feature names are sanitized: control characters stripped and length capped (feature_names_truncatedmarks a cap hit); schemas wider than the column cap setcolumns_truncated— drift past the cap is invisible.header: presentrequires every numeric-bodied column to carry a non-numeric first value AND the names to be unique and non-empty; parquet names failing that are flaggedfeature_names_invalid. Dtype classes are inferred from a bounded row sample; a full-file reader (pandas at job runtime) can disagree when anomalies appear past the sample.image:
image_formats(the site’s image extensions, so the consumer picks the matching loader) andpixel_depthfrom one sample when an optional loader exists (PIL formats only; DICOM/NIfTI depth stays null and the loader must be chosen fromimage_formats).
schema_agreement(tabular): compares feature names, column counts, AND dtype classes across sites; any drift is amismatchwith per-site issues (feature_names_differ|column_count_differs|header_presence_differs(one site has a header, another is ambiguous — alignment unverifiable even at equal widths) |dtypes_differ|shards_differ, the last when shards inside one site disagree — flagged per site asshard_schema_consistent: false).
Walk bounds: max_files counts data files so non-data clutter cannot
hide a dataset, and MAX_WALK_ENTRIES bounds total traversal (files and
directories). This deliberately differs from the code walk in
inspector.py, which bounds per-file scan work; the two walks bound
different costs and are kept separate on purpose.