Support reading skims from Parquet files, in addition to OMX#6
Conversation
| ): | ||
| return ROW_MAJOR | ||
|
|
||
| col_major_orig = np.tile(np.arange(n), n) |
There was a problem hiding this comment.
col_major_orig is the same as row_major_dest, there is no need to create this array twice.
There was a problem hiding this comment.
Fixed in 288c238 — col-major orig/dest now reuse row_major_dest/row_major_orig instead of recreating equivalent arrays.
| return ROW_MAJOR | ||
|
|
||
| col_major_orig = np.tile(np.arange(n), n) | ||
| col_major_dest = np.repeat(np.arange(n), n) |
There was a problem hiding this comment.
col_major_dest is the same as row_major_orig, there is no need to create this array twice.
There was a problem hiding this comment.
Fixed in 288c238 — same fix, reusing row_major_orig/row_major_dest for the col-major check.
There was a problem hiding this comment.
Pull request overview
Adds Parquet as an additional skim storage/input format for the legacy SkimDict pipeline, auto-detected per file by extension, and extends tests/config fixtures to validate Parquet-based LOS loading.
Changes:
- Introduce
activitysim/core/skim_parquet.pywithParquetSkimFilefor inspecting and reading Parquet skim tables (dense row/col-major and sparse). - Extend
SkimInfo.load_skim_info/_read_skims_from_omxto mix OMX and Parquet skim files under a single skim tag. - Add unit/integration tests and canonical test configs validating Parquet skim loading (single file and multi-file scenarios).
Reviewed changes
Copilot reviewed 9 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| activitysim/core/skim_parquet.py | New Parquet skim reader/inspector used by legacy skim loading. |
| activitysim/core/skim_dict_factory.py | Adds Parquet branching + caching during skim discovery and loading. |
| activitysim/core/configuration/network.py | Documents Parquet skim input expectations under TAZ_Settings. |
| activitysim/core/test/test_skim_parquet.py | New unit tests for dense/sparse Parquet layout detection and reading. |
| activitysim/core/test/test_los.py | New LOS integration tests exercising Parquet skim inputs. |
| activitysim/core/test/los/configs_1z_parquet/settings.yaml | New canonical config for 1-zone Parquet skim test. |
| activitysim/core/test/los/configs_1z_parquet/network_los.yaml | New network LOS config pointing to .parquet skims. |
| activitysim/core/test/los/configs_1z_parquet_multi/settings.yaml | New canonical config for multi-file Parquet skim test. |
| activitysim/core/test/los/configs_1z_parquet_multi/network_los.yaml | New LOS config pointing to two Parquet skim parts. |
Comments suppressed due to low confidence (1)
activitysim/core/skim_parquet.py:138
- Same as above:
pyarrow.Table.column(...)is not reliably name-addressable across the supported pyarrow range. Indexing the table by column name is the stable API.
values = table.column(column_name).to_numpy(zero_copy_only=False)
if dtype is not None:
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| zone_ids = np.unique(np.concatenate([origins, destinations])) | ||
| self.zone_ids = zone_ids | ||
| self.n_zones = len(zone_ids) | ||
|
|
||
| self.shape = (self.n_zones, self.n_zones) | ||
|
|
||
| n_rows = len(origins) | ||
| self.is_dense = n_rows == self.n_zones * self.n_zones | ||
|
|
||
| zone_index = {z: i for i, z in enumerate(zone_ids)} | ||
| orig_idx = np.fromiter( | ||
| (zone_index[o] for o in origins), dtype=np.int64, count=n_rows | ||
| ) | ||
| dest_idx = np.fromiter( | ||
| (zone_index[d] for d in destinations), dtype=np.int64, count=n_rows | ||
| ) | ||
| self._orig_idx = orig_idx | ||
| self._dest_idx = dest_idx |
| if is_parquet_file(omx_file_path): | ||
| parquet_skim_file = skim_info.parquet_files.get(omx_file_path) | ||
| if parquet_skim_file is None: | ||
| parquet_skim_file = ParquetSkimFile(omx_file_path) | ||
| for skim_key, omx_key in omx_keys.items(): |
Skims can currently only be read from OMX files. Parquet storage is significantly more compact (~30% smaller) and can be read faster, so this adds Parquet as an alternative input format, auto-detected per-file, with full backward compatibility for OMX.
New Parquet skim reader (
activitysim/core/skim_parquet.py)ParquetSkimFileinspects a parquet skim file's first two columns (origin, destination) to derive the zone id set and matrix shape; remaining columns are treated as named skim matrices, using the same naming/time-period conventions as OMX (e.g.DIST,DRV_COM_WLK_BOARDS__AM).ValueErrorif data is dense (complete OD coverage) but not sorted row-major/column-major, since it can't be read efficiently or unambiguously in that state.Integration (
activitysim/core/skim_dict_factory.py)SkimInfo.load_skim_infoand_read_skims_from_omxnow branch per-file on extension (.parquet/.pqvs OMX), so OMX and Parquet files can be freely mixed under the same skim tag.los.py: users just reference.parquetfilenames directly innetwork_los.yaml, e.g.:Scope
NumpyArraySkimFactory/MemMapSkimFactorypath (SkimDict).SkimDatasetpath still relies on the externalsharrowpackage'ssh.dataset.from_omx_3dand does not yet support Parquet input; extending that would require changes upstream insharrow.Docs
TAZ_Settings.omxandSkimInfodocstrings updated to describe Parquet input expectations (dense/sparse layout, column conventions).