From 8dbdca877ef8266a008ff50cd0b7376a272ffeba Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 20 Dec 2025 16:19:33 -0600 Subject: [PATCH 1/2] Removed remodeler CLI for hedpy, updated docs --- CHANGELOG.md | 6 +- README.md | 4 +- docs/_static/custom.css | 16 +- docs/_templates/sidebar/brand.html | 6 + docs/conf.py | 4 +- docs/introduction.md | 12 +- docs/user_guide.md | 332 +++++++++++++++++- examples/extract_json_template.ipynb | 4 +- examples/find_event_combinations.ipynb | 14 +- examples/merge_spreadsheet_into_sidecar.ipynb | 7 +- examples/sidecar_to_spreadsheet.ipynb | 16 +- examples/summarize_events.ipynb | 12 +- examples/validate_bids_dataset.ipynb | 8 +- .../validate_bids_dataset_nondefault.ipynb | 8 +- ...validate_bids_dataset_with_libraries.ipynb | 17 +- examples/validate_bids_datasets.ipynb | 5 +- hed/cli/cli.py | 172 +-------- hed/schema/hed_schema.py | 8 +- hed/schema/hed_schema_io.py | 4 +- hed/schema/schema_io/json2schema.py | 6 +- hed/schema/schema_io/schema2base.py | 4 +- hed/schema/schema_io/schema2wiki.py | 2 +- hed/schema/schema_io/wiki2schema.py | 6 +- hed/scripts/hed_script_util.py | 4 +- pyproject.toml | 3 - requirements-dev.txt | 2 +- tests/schema/test_schema_format_roundtrip.py | 16 +- tests/test_cli_parameter_parity.py | 105 ------ 28 files changed, 435 insertions(+), 368 deletions(-) create mode 100644 docs/_templates/sidebar/brand.html diff --git a/CHANGELOG.md b/CHANGELOG.md index acfd5ece..d5bbcedf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,7 +64,7 @@ Release 0.8.0 November 18, 2025 - Fixed `remodel` commands: Corrected argument names, added missing parameters, fixed option conflicts. - Fixed `schema` commands: Corrected positional vs option argument structures for add-ids and create-ontology. - Added comprehensive test suite (`tests/test_cli_parameter_parity.py`) to verify CLI parameters match original parsers. -- **JSON Schema Format Support**: Added comprehensive JSON format support for HED schemas alongside existing XML, MediaWiki, and TSV formats. +- **JSON Schema Format Support**: Added comprehensive JSON format support for HED schemas alongside existing XML, MEDIAWIKI, and TSV formats. - Implemented `SchemaLoaderJSON` class for loading JSON schemas (`hed/schema/schema_io/json2schema.py`). - Implemented `Schema2JSON` class for exporting schemas to JSON (`hed/schema/schema_io/schema2json.py`). - Added JSON constants and key mappings (`hed/schema/schema_io/json_constants.py`). @@ -72,13 +72,13 @@ Release 0.8.0 November 18, 2025 - JSON format uses flat tag structure with hierarchy metadata for easier programmatic access. - Separate units section in JSON format for improved AI/tool accessibility. - Placeholder structure for takes-value tags with proper attribute inheritance. - - Full roundtrip validation ensures JSON format produces identical validation results to XML/MediaWiki. + - Full roundtrip validation ensures JSON format produces identical validation results to XML/MEDIAWIKI. - **New BIDS Sidecar Extraction Tool**: Added `hed_extract_bids_sidecar` command-line script for extracting sidecar templates from BIDS datasets. - Configurable value columns and skip columns for flexible template generation. - Comprehensive logging support with file output and verbosity control. - Integrated with BidsDataset and TabularSummary classes for robust extraction. - **Schema Validation Enhancements**: Extended schema validation to include JSON format in roundtrip testing. - - Updated `hed_script_util.py` to validate all 4 schema formats (XML, MediaWiki, TSV, JSON). + - Updated `hed_script_util.py` to validate all 4 schema formats (XML, MEDIAWIKI, TSV, JSON). - Updated schema conversion script to automatically generate JSON format alongside other formats. - **Python Version Requirements**: Minimum Python version raised to 3.10 (dropped 3.9 support). - **Documentation Improvements**: Added comprehensive Google-style docstrings to all functions in `hed_script_util.py`. diff --git a/README.md b/README.md index 09b9eb9d..ba0886bc 100644 --- a/README.md +++ b/README.md @@ -79,11 +79,9 @@ hedpy extract-sidecar /path/to/dataset --suffix events # Validate HED schemas hedpy schema validate /path/to/schema.xml -# Convert schema between formats (XML, MediaWiki, TSV, JSON) +# Convert schema between formats (XML, MEDIAWIKI, TSV, JSON) hedpy schema convert /path/to/schema.xml -# Run remodeling operations on event files -hedpy remodel run /path/to/data /path/to/remodel_config.json ``` **Legacy commands** (deprecated, use `hedpy` instead): diff --git a/docs/_static/custom.css b/docs/_static/custom.css index ba864571..2dcee3db 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -1,4 +1,18 @@ -/* Custom styles for HED Python Tools Documentation - Furo Theme */ +/* Custom styles for HED Python tools Documentation - Furo Theme */ + +/* Project name styling below logo */ +.sidebar-brand-text { + font-size: 1.5rem !important; + font-weight: 600 !important; + color: #0969da !important; + margin-top: 0.5rem !important; + text-align: center !important; +} + +html[data-theme="dark"] .sidebar-brand-text, +body[data-theme="dark"] .sidebar-brand-text { + color: #58a6ff !important; +} /* Quick Links sidebar styling - darker gray box with proper padding */ .sidebar-quicklinks { diff --git a/docs/_templates/sidebar/brand.html b/docs/_templates/sidebar/brand.html new file mode 100644 index 00000000..8d955881 --- /dev/null +++ b/docs/_templates/sidebar/brand.html @@ -0,0 +1,6 @@ +{% extends "furo/sidebar/brand.html" %} + +{% block brand_content %} +{{ super() }} +
+{% endblock brand_content %} diff --git a/docs/conf.py b/docs/conf.py index 83c92e23..35e52175 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,7 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = "HED Python Tools" +project = "HED Python tools" copyright = "2024, HED Standard" author = "HED Standard" @@ -56,7 +56,7 @@ "source_directory": "docs/", } -html_title = "HED Python Tools" +html_title = "HED Python tools" # Configure sidebar to show logo, search, navigation, and quick links html_sidebars = { diff --git a/docs/introduction.md b/docs/introduction.md index 09105ef5..6d5aea7a 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -24,12 +24,12 @@ The **hedtools** Python package (`hed-python` repository) provides: ### Related tools and resources - **[HED homepage](https://www.hedtags.org)**: Overview and links for HED -- **[HED Schemas](https://github.com/hed-standard/hed-schemas)**: Standardized vocabularies in XML/MediaWiki/OWL formats -- **[HED Specification](https://www.hedtags.org/hed-specification/)**: Formal specification defining HED annotation rules -- **[HED Online Tools](https://hedtools.org/hed)**: Web-based interface requiring no programming -- **[HED Examples](https://github.com/hed-standard/hed-examples)**: Example datasets annotated with HED -- **[HED Resources](https://www.hedtags.org/hed-resources)**: Comprehensive tutorials and documentation -- **[HED MATLAB Tools](https://www.hedtags.org/hed-resources/HedMatlabTools.html)**: MATLAB wrapper for Python tools +- **[HED schemas](https://github.com/hed-standard/hed-schemas)**: Standardized vocabularies in XML/MEDIAWIKI/TSV/JSON formats +- **[HED specification](https://www.hedtags.org/hed-specification/)**: Formal specification defining HED annotation rules +- **[HED online tools](https://hedtools.org/hed)**: Web-based interface requiring no programming +- **[HED examples](https://github.com/hed-standard/hed-examples)**: Example datasets annotated with HED +- **[HED resources](https://www.hedtags.org/hed-resources)**: Comprehensive tutorials and documentation +- **[HED MATLAB tools](https://www.hedtags.org/hed-resources/HedMatlabTools.html)**: MATLAB wrapper for Python tools ## Installation diff --git a/docs/user_guide.md b/docs/user_guide.md index c4236b29..44a83fa4 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -269,22 +269,336 @@ See the [examples README](https://github.com/hed-standard/hed-python/tree/main/e ## Command-line tools -HEDTools provides command-line scripts for common operations. These are installed with the package: +HEDTools provides a unified command-line interface (CLI) using a **git-style command structure**. The main command is `hedpy`, which provides subcommands for validation and schema management. -### Validate BIDS dataset +### Available commands + +| Command | Description | +| ------------------------------ | ----------------------------------------------------------- | +| `hedpy validate-bids` | Validate HED annotations in BIDS datasets | +| `hedpy extract-sidecar` | Extract JSON sidecar template from BIDS event files | +| **Schema Management** | | +| `hedpy schema validate` | Validate HED schema files | +| `hedpy schema convert` | Convert schemas between formats (XML, MEDIAWIKI, TSV, JSON) | +| `hedpy schema add-ids` | Add unique HED IDs to schema terms | +| `hedpy schema create-ontology` | Generate OWL ontology files from HED schemas | + +### Installation and basic usage + +The CLI is installed automatically with the hedtools package: + +```bash +pip install hedtools +``` + +Get help on available commands: + +```bash +# General help +hedpy --help + +# Help for a specific command +hedpy validate-bids --help + +# Help for command groups +hedpy schema --help +``` + +Get version information: + +```bash +hedpy --version +``` + +______________________________________________________________________ + +### BIDS validation + +Validate HED annotations in BIDS datasets using `hedpy validate-bids`. + +#### Basic validation + +```bash +# Validate a BIDS dataset +hedpy validate-bids /path/to/bids/dataset + +# Include warnings in addition to errors +hedpy validate-bids /path/to/bids/dataset -w + +# Enable verbose output +hedpy validate-bids /path/to/bids/dataset -v +``` + +#### Output options + +```bash +# Save results to a file +hedpy validate-bids /path/to/bids/dataset -o validation_results.txt + +# Output in JSON format +hedpy validate-bids /path/to/bids/dataset -f json -o results.json + +# Pretty-printed JSON +hedpy validate-bids /path/to/bids/dataset -f json_pp -o results.json + +# Print to stdout AND save to file +hedpy validate-bids /path/to/bids/dataset -o results.txt -p +``` + +#### Filtering validation ```bash -# Basic validation -python -m hed.scripts.validate_bids /path/to/bids/dataset +# Validate specific file types (default: events, participants) +hedpy validate-bids /path/to/bids/dataset -s events -s participants -s sessions -# Include warnings -python -m hed.scripts.validate_bids /path/to/bids/dataset --check-warnings +# Exclude certain directories (default: sourcedata, derivatives, code, stimuli) +hedpy validate-bids /path/to/bids/dataset -x derivatives -x sourcedata -x mydata -# Use specific schema version -python -m hed.scripts.validate_bids /path/to/bids/dataset --schema-version 8.4.0 +# Limit number of errors reported per error type +hedpy validate-bids /path/to/bids/dataset -ec 5 + +# Apply error limit per file instead of overall +hedpy validate-bids /path/to/bids/dataset -ec 5 -ef +``` + +#### Logging options + +```bash +# Set log level +hedpy validate-bids /path/to/bids/dataset -l DEBUG + +# Save logs to file +hedpy validate-bids /path/to/bids/dataset -lf validation.log + +# Save logs to file without stderr output +hedpy validate-bids /path/to/bids/dataset -lf validation.log -lq +``` + +#### Complete example + +```bash +# Comprehensive validation with all options +hedpy validate-bids /path/to/bids/dataset \ + -w \ + -v \ + -f json_pp \ + -o validation_results.json \ + -s events \ + -x derivatives \ + -ec 10 \ + -lf validation.log +``` + +______________________________________________________________________ + +### Sidecar template extraction + +Extract a JSON sidecar template from BIDS event files using `hedpy extract-sidecar`. + +#### Basic extraction + +```bash +# Extract template for events files +hedpy extract-sidecar /path/to/bids/dataset -s events + +# Save to specific file +hedpy extract-sidecar /path/to/bids/dataset -s events -o task_events.json ``` -Use `--help` with any script to see all available options. +#### Column handling + +```bash +# Specify value columns (columns with unique values needing # placeholders) +hedpy extract-sidecar /path/to/bids/dataset -s events \ + -vc response_time -vc accuracy -vc subject_id + +# Skip specific columns (default: onset, duration, sample) +hedpy extract-sidecar /path/to/bids/dataset -s events \ + -sc onset -sc duration -sc trial_type + +# Exclude certain directories +hedpy extract-sidecar /path/to/bids/dataset -s events \ + -x derivatives -x pilot_data +``` + +#### Complete example + +```bash +# Extract events template with custom column handling +hedpy extract-sidecar /path/to/bids/dataset \ + -s events \ + -vc response_time \ + -vc reaction_time \ + -sc onset -sc duration \ + -o events_template.json \ + -v +``` + +______________________________________________________________________ + +### Schema management + +The `hedpy schema` command group provides tools for validating, converting, and managing HED schemas. + +#### Schema validation + +Validate HED schema files: + +```bash +# Validate a single schema +hedpy schema validate /path/to/schema.xml + +# Validate multiple schemas +hedpy schema validate schema1.xml schema2.xml schema3.xml + +# Validate with verbose output +hedpy schema validate /path/to/schema.xml -v + +# Verify all format versions are equivalent +hedpy schema validate /path/to/schema.xml --add-all-extensions +``` + +#### Schema format conversion + +Convert schemas between formats (XML, MEDIAWIKI, TSV, JSON): + +```bash +# Convert schema (format auto-detected from extension) +hedpy schema convert schema.xml # Creates schema.mediawiki, schema.tsv, etc. + +# Convert multiple schemas +hedpy schema convert schema1.xml schema2.xml + +# Convert and set/update HED IDs +hedpy schema convert schema.xml --set-ids +``` + +**Supported formats:** + +- `.xml` - XML format (standard) +- `.mediawiki` - MEDIAWIKI format +- `.tsv` - TSV (tab-separated value) format +- `.json` - JSON format + +#### Add HED IDs to schema + +Add unique HED IDs to schema terms: + +```bash +# Add IDs to a standard schema +hedpy schema add-ids /path/to/hed-schemas standard 8.4.0 + +# Add IDs to a library schema +hedpy schema add-ids /path/to/hed-schemas score 2.1.0 +``` + +**Requirements:** + +- Path must be to a hed-schemas repository clone +- Schema name and version must match directory structure +- Modifies the schema in-place + +#### Create ontology from schema + +Generate OWL ontology files from HED schemas: + +```bash +# Create ontology for a schema +hedpy schema create-ontology /path/to/hed-schemas standard 8.4.0 + +# Specify output directory +hedpy schema create-ontology /path/to/hed-schemas standard 8.4.0 \ + --dest /path/to/output + +# Create ontology for library schema +hedpy schema create-ontology /path/to/hed-schemas score 2.1.0 \ + --dest ./ontologies +``` + +______________________________________________________________________ + +### Legacy script access + +For backward compatibility, you can still access scripts directly using Python module syntax: + +```bash +# Validation +python -m hed.scripts.validate_bids /path/to/dataset --check-warnings + +# Sidecar extraction +python -m hed.scripts.hed_extract_bids_sidecar /path/to/dataset -s events + +# Schema validation +python -m hed.scripts.validate_schemas schema.xml +``` + +**However, the `hedpy` CLI is the recommended interface** as it provides a more consistent and discoverable command structure. + +______________________________________________________________________ + +### Common workflows + +#### Workflow 1: First-time BIDS dataset validation + +```bash +# Step 1: Extract sidecar template +hedpy extract-sidecar /path/to/dataset -s events -o events.json + +# Step 2: Edit events.json to add HED tags +# (manual editing step) + +# Step 3: Validate with warnings +hedpy validate-bids /path/to/dataset -w -v -o validation.txt + +# Step 4: Fix issues and re-validate +hedpy validate-bids /path/to/dataset -w +``` + +#### Workflow 2: Schema development and testing + +```bash +# Step 1: Validate schema +hedpy schema validate my_schema.xml -v + +# Step 2: Convert to all formats +hedpy schema convert my_schema.xml + +# Step 3: Verify all formats are equivalent +hedpy schema validate my_schema.xml --add-all-extensions + +# Step 4: Add HED IDs +hedpy schema add-ids /path/to/hed-schemas my_library 1.0.0 + +# Step 5: Generate ontology +hedpy schema create-ontology /path/to/hed-schemas my_library 1.0.0 +``` + +______________________________________________________________________ + +### Tips and best practices + +1. **Use verbose mode (`-v`)** during development to see detailed progress +2. **Save output to files (`-o`)** for documentation and tracking +3. **Use JSON output format (`-f json_pp`)** for programmatic processing +4. **Leverage tab completion** in your shell for command discovery +5. **Use `--help` liberally** to explore options for each command +6. **Test on small datasets first** before processing large corpora + +### Getting help + +Each command provides detailed help: + +```bash +# Top-level help +hedpy --help + +# Command-specific help +hedpy validate-bids --help +hedpy schema validate --help + +# Command group help +hedpy schema --help +``` ## Best practices diff --git a/examples/extract_json_template.ipynb b/examples/extract_json_template.ipynb index 4276df47..00954e6e 100644 --- a/examples/extract_json_template.ipynb +++ b/examples/extract_json_template.ipynb @@ -46,8 +46,8 @@ "from hed.tools.analysis.tabular_summary import TabularSummary\n", "from hed.tools.util.io_util import get_file_list\n", "\n", - "dataset_root = '../../../datasets/eeg_ds003645s_hed'\n", - "exclude_dirs = ['stimuli', 'code', 'derivatives', 'sourcedata', 'phenotype']\n", + "dataset_root = \"../../../datasets/eeg_ds003645s_hed\"\n", + "exclude_dirs = [\"stimuli\", \"code\", \"derivatives\", \"sourcedata\", \"phenotype\"]\n", "skip_columns = [\"onset\", \"duration\", \"sample\"]\n", "value_columns = [\"stim_file\", \"response_time\"]\n", "output_path = None\n", diff --git a/examples/find_event_combinations.ipynb b/examples/find_event_combinations.ipynb index 8c4213cb..a586b67f 100644 --- a/examples/find_event_combinations.ipynb +++ b/examples/find_event_combinations.ipynb @@ -72,10 +72,10 @@ "from hed.tools.util.io_util import get_file_list\n", "\n", "# Variables to set for the specific dataset\n", - "dataset_root = '../../../datasets/eeg_ds002893s_hed_attention_shift'\n", - "exclude_dirs = ['stimuli', 'code', 'derivatives', 'sourcedata', 'phenotype']\n", - "output_path = ''\n", - "exclude_dirs = ['trial', 'derivatives', 'code', 'sourcedata']\n", + "dataset_root = \"../../../datasets/eeg_ds002893s_hed_attention_shift\"\n", + "exclude_dirs = [\"stimuli\", \"code\", \"derivatives\", \"sourcedata\", \"phenotype\"]\n", + "output_path = \"\"\n", + "exclude_dirs = [\"trial\", \"derivatives\", \"code\", \"sourcedata\"]\n", "\n", "# Construct the key map\n", "key_columns = [\"focus_modality\", \"event_type\", \"attention_status\"]\n", @@ -90,12 +90,12 @@ "\n", "key_map.resort()\n", "template = key_map.make_template()\n", - "key_counts_sum = template['key_counts'].sum()\n", + "key_counts_sum = template[\"key_counts\"].sum()\n", "print(f\"The total count of the keys is:{key_counts_sum}\")\n", "if output_path:\n", - " template.to_csv(output_path, sep='\\t', index=False, header=True)\n", + " template.to_csv(output_path, sep=\"\\t\", index=False, header=True)\n", "else:\n", - " print(template)\n" + " print(template)" ] } ], diff --git a/examples/merge_spreadsheet_into_sidecar.ipynb b/examples/merge_spreadsheet_into_sidecar.ipynb index 21d212ae..c7d9605a 100644 --- a/examples/merge_spreadsheet_into_sidecar.ipynb +++ b/examples/merge_spreadsheet_into_sidecar.ipynb @@ -37,11 +37,12 @@ "from hed.tools import df_to_hed, merge_hed_dict\n", "\n", "# Spreadsheet input\n", - "spreadsheet_path = os.path.realpath('../../../docs/source/_static/data/task-WorkingMemory_example_spreadsheet.tsv')\n", + "spreadsheet_path = os.path.realpath(\"../../../docs/source/_static/data/task-WorkingMemory_example_spreadsheet.tsv\")\n", "filename = os.path.basename(spreadsheet_path)\n", "worksheet_name = None\n", - "spreadsheet = SpreadsheetInput(file=spreadsheet_path, worksheet_name=worksheet_name,\n", - " tag_columns=['HED'], has_column_names=True, name=filename)\n", + "spreadsheet = SpreadsheetInput(\n", + " file=spreadsheet_path, worksheet_name=worksheet_name, tag_columns=[\"HED\"], has_column_names=True, name=filename\n", + ")\n", "\n", "# Must convert the spreadsheet to a sidecar before merging\n", "spreadsheet_sidecar = df_to_hed(spreadsheet.dataframe, description_tag=False)\n", diff --git a/examples/sidecar_to_spreadsheet.ipynb b/examples/sidecar_to_spreadsheet.ipynb index 3a7523eb..189869a5 100644 --- a/examples/sidecar_to_spreadsheet.ipynb +++ b/examples/sidecar_to_spreadsheet.ipynb @@ -29,17 +29,25 @@ "from io import StringIO\n", "from hed.tools import hed_to_df\n", "\n", - "json_path = os.path.realpath('../../../datasets/eeg_ds003645s_hed/task-FacePerception_events.json')\n", - "spreadsheet_filename = ''\n", + "json_path = os.path.realpath(\"../../../datasets/eeg_ds003645s_hed/task-FacePerception_events.json\")\n", + "spreadsheet_filename = \"\"\n", "with open(json_path) as fp:\n", " example_sidecar = json.load(fp)\n", "example_spreadsheet = hed_to_df(example_sidecar)\n", "if spreadsheet_filename:\n", " print(f\"Saving the spreadsheet to {os.path.basename(spreadsheet_filename)}\")\n", - " example_spreadsheet.to_csv(spreadsheet_filename, sep='\\t', index=False,)\n", + " example_spreadsheet.to_csv(\n", + " spreadsheet_filename,\n", + " sep=\"\\t\",\n", + " index=False,\n", + " )\n", "else:\n", " output = StringIO()\n", - " example_spreadsheet.to_csv(output, sep='\\t', index=False,)\n", + " example_spreadsheet.to_csv(\n", + " output,\n", + " sep=\"\\t\",\n", + " index=False,\n", + " )\n", " print(f\"{output.getvalue()}\")" ], "metadata": { diff --git a/examples/summarize_events.ipynb b/examples/summarize_events.ipynb index 17e3a9e4..b6b6725a 100644 --- a/examples/summarize_events.ipynb +++ b/examples/summarize_events.ipynb @@ -108,10 +108,10 @@ "from hed.tools import TabularSummary, get_file_list\n", "\n", "# Variables to set for the specific dataset\n", - "dataset_path = os.path.realpath('../../../datasets/eeg_ds003645s_hed')\n", - "output_path = ''\n", - "name = 'eeg_ds003645s_hed'\n", - "exclude_dirs = ['stimuli', 'code', 'derivatives', 'sourcedata', 'phenotype']\n", + "dataset_path = os.path.realpath(\"../../../datasets/eeg_ds003645s_hed\")\n", + "output_path = \"\"\n", + "name = \"eeg_ds003645s_hed\"\n", + "exclude_dirs = [\"stimuli\", \"code\", \"derivatives\", \"sourcedata\", \"phenotype\"]\n", "skip_columns = [\"onset\", \"duration\", \"sample\", \"trial\", \"response_time\"]\n", "value_columns = [\"stim_file\"]\n", "\n", @@ -128,10 +128,10 @@ "\n", "# Save or print\n", "if output_path:\n", - " with open(output_path, 'w') as fp:\n", + " with open(output_path, \"w\") as fp:\n", " fp.write(f\"{tab_sum}\")\n", "else:\n", - " print(f\"{tab_sum}\")\n" + " print(f\"{tab_sum}\")" ] } ], diff --git a/examples/validate_bids_dataset.ipynb b/examples/validate_bids_dataset.ipynb index a3d20eb2..359619b5 100644 --- a/examples/validate_bids_dataset.ipynb +++ b/examples/validate_bids_dataset.ipynb @@ -38,9 +38,9 @@ "\n", "## Set the dataset location and the check_for_warnings flag\n", "check_for_warnings = True\n", - "dataset_dir = '../../../datasets/eeg_ds004105s_hed'\n", + "dataset_dir = \"../../../datasets/eeg_ds004105s_hed\"\n", "# outfile = 'temp.txt'\n", - "outfile = ''\n", + "outfile = \"\"\n", "\n", "## Validate the dataset\n", "bids = BidsDataset(dataset_dir)\n", @@ -52,10 +52,10 @@ "# print(issue_str)\n", "print(f\"Number of issues: {len(issue_list)}\")\n", "if outfile and issue_list:\n", - " with open(outfile, 'w') as fp:\n", + " with open(outfile, \"w\") as fp:\n", " fp.write(issue_str)\n", "else:\n", - " print(f\"{issue_str}\")\n" + " print(f\"{issue_str}\")" ], "metadata": { "collapsed": false, diff --git a/examples/validate_bids_dataset_nondefault.ipynb b/examples/validate_bids_dataset_nondefault.ipynb index 1001f222..e57697ec 100644 --- a/examples/validate_bids_dataset_nondefault.ipynb +++ b/examples/validate_bids_dataset_nondefault.ipynb @@ -36,9 +36,9 @@ "\n", "## Set the dataset location and the check_for_warnings flag\n", "check_for_warnings = True\n", - "dataset_dir = '../../../datasets/eeg_ds003645s_hed_demo'\n", + "dataset_dir = \"../../../datasets/eeg_ds003645s_hed_demo\"\n", "# outfile = 'temp.txt'\n", - "outfile = ''\n", + "outfile = \"\"\n", "\n", "## Validate the dataset -- using all possible suffixes (e.g., suffixes=None) will validate all files .tsv and .json files in the dataset\n", "bids = BidsDataset(dataset_dir, suffixes=None)\n", @@ -50,10 +50,10 @@ "# print(issue_str)\n", "print(f\"Number of issues: {len(issue_list)}\")\n", "if outfile and issue_list:\n", - " with open(outfile, 'w') as fp:\n", + " with open(outfile, \"w\") as fp:\n", " fp.write(issue_str)\n", "else:\n", - " print(f\"{issue_str}\")\n" + " print(f\"{issue_str}\")" ], "metadata": { "collapsed": false, diff --git a/examples/validate_bids_dataset_with_libraries.ipynb b/examples/validate_bids_dataset_with_libraries.ipynb index 379b1ec7..921cae7f 100644 --- a/examples/validate_bids_dataset_with_libraries.ipynb +++ b/examples/validate_bids_dataset_with_libraries.ipynb @@ -30,7 +30,7 @@ "\n", "## Set the dataset location and the check_for_warnings flag\n", "check_for_warnings = False\n", - "dataset_path = '../../../datasets/eeg_ds003645s_hed_library'\n", + "dataset_path = \"../../../datasets/eeg_ds003645s_hed_library\"\n", "bids = BidsDataset(dataset_path)\n", "\n", "## Validate the dataset using the information from the dataset_description\n", @@ -44,13 +44,14 @@ "\n", "## Now validate URLs\n", "print(\"\\nNow validating with schema URLs.\")\n", - "base_version = '8.3.0'\n", - "library1_url = \"https://raw.githubusercontent.com/hed-standard/hed-schemas/main/\" + \\\n", - " \"library_schemas/score/hedxml/HED_score_2.0.0.xml\"\n", - "library2_url = \"https://raw.githubusercontent.com/hed-standard/hed-schemas/main/\" + \\\n", - " \"library_schemas/testlib/hedxml/HED_testlib_1.0.2.xml\"\n", - "schema_list = [load_schema(library1_url, schema_namespace=\"\"),\n", - " load_schema(library2_url, schema_namespace=\"test\")]\n", + "base_version = \"8.3.0\"\n", + "library1_url = (\n", + " \"https://raw.githubusercontent.com/hed-standard/hed-schemas/main/\" + \"library_schemas/score/hedxml/HED_score_2.0.0.xml\"\n", + ")\n", + "library2_url = (\n", + " \"https://raw.githubusercontent.com/hed-standard/hed-schemas/main/\" + \"library_schemas/testlib/hedxml/HED_testlib_1.0.2.xml\"\n", + ")\n", + "schema_list = [load_schema(library1_url, schema_namespace=\"\"), load_schema(library2_url, schema_namespace=\"test\")]\n", "bids.schema = HedSchemaGroup(schema_list)\n", "\n", "\n", diff --git a/examples/validate_bids_datasets.ipynb b/examples/validate_bids_datasets.ipynb index 0db313b8..b8af286c 100644 --- a/examples/validate_bids_datasets.ipynb +++ b/examples/validate_bids_datasets.ipynb @@ -89,15 +89,14 @@ "from hed import _version as vr\n", "\n", "print(f\"Using HEDTOOLS version: {str(vr.get_versions())}\")\n", - "datasets_dir = '../../../datasets'\n", + "datasets_dir = \"../../../datasets\"\n", "\n", "## Set the dataset locations and the check_for_warnings flag\n", "check_for_warnings = False\n", "\n", "## Get a list of subdirectories\n", "entries = os.listdir(datasets_dir)\n", - "bids_datasets = [entry for entry in entries\n", - " if os.path.isdir(os.path.join(datasets_dir, entry))]\n", + "bids_datasets = [entry for entry in entries if os.path.isdir(os.path.join(datasets_dir, entry))]\n", "\n", "## Validate each dataset using the standard configuration (event files only).\n", "for bids_dataset in bids_datasets:\n", diff --git a/hed/cli/cli.py b/hed/cli/cli.py index 05677b26..876544b1 100644 --- a/hed/cli/cli.py +++ b/hed/cli/cli.py @@ -3,7 +3,7 @@ HED Command Line Interface A unified command-line interface for HED (Hierarchical Event Descriptors) tools. -Provides a git-like interface with subcommands for validation, remodeling, and schema management. +Provides a git-like interface with subcommands for validation and schema management. """ import click @@ -16,23 +16,13 @@ def cli(): """HED (Hierarchical Event Descriptors) command-line tools. This tool provides various commands for working with HED annotations, - including validation, remodeling, and schema management. + including validation and schema management. Use 'hedpy COMMAND --help' for more information on a specific command. """ pass -@cli.group() -def remodel(): - """Remodel and transform HED-annotated datasets. - - Commands for running remodeling operations on BIDS datasets - with HED annotations. - """ - pass - - @cli.group() def schema(): """HED schema management and validation tools. @@ -122,162 +112,6 @@ def validate_bids_cmd( validate_bids_main(args) -@remodel.command(name="run") -@click.argument("data_dir", type=click.Path(exists=True)) -@click.argument("model_path", type=click.Path(exists=True)) -@click.option("-bd", "--backup-dir", default="", help="Directory for the backup being created.") -@click.option("-bn", "--backup-name", default="", help="Name of the default backup for remodeling.") -@click.option("-b", "--bids-format", "use_bids", is_flag=True, help="Dataset is in BIDS format with sidecars.") -@click.option("-fs", "--file-suffix", "suffixes", multiple=True, default=["events"], help="File suffixes to process.") -@click.option( - "-i", - "--individual-summaries", - type=click.Choice(["separate", "consolidated", "none"]), - default="separate", - help="Controls individual file summaries.", -) -@click.option("-j", "--json-sidecar", default=None, help="Path to JSON sidecar with HED information.") -@click.option("-ld", "--log-dir", default="", help="Directory for storing log entries for errors.") -@click.option("-nb", "--no-backup", is_flag=True, help="Operations run directly on files with no backup.") -@click.option("-ns", "--no-summaries", is_flag=True, help="Summaries are not saved.") -@click.option("-nu", "--no-update", is_flag=True, help="Files are not saved.") -@click.option("-hv", "--hed-versions", multiple=True, default=[], help="HED schema versions for annotation.") -@click.option("-s", "--save-formats", multiple=True, default=[".json", ".txt"], help="Format for saving summaries.") -@click.option("-t", "--task-names", multiple=True, default=[], help="Task names to process.") -@click.option("-v", "--verbose", is_flag=True, help="Output informational messages.") -@click.option("-w", "--work-dir", default="", help="Path to directory for saving.") -@click.option("-x", "--exclude-dirs", multiple=True, default=[], help="Directory names to exclude.") -def remodel_run_cmd( - data_dir, - model_path, - backup_dir, - backup_name, - use_bids, - suffixes, - individual_summaries, - json_sidecar, - log_dir, - no_backup, - no_summaries, - no_update, - hed_versions, - save_formats, - task_names, - verbose, - work_dir, - exclude_dirs, -): - """Run remodeling operations on a dataset. - - DATA_DIR: Root directory of the dataset to remodel. - MODEL_PATH: Path to JSON file with remodeling instructions. - """ - from hed.tools.remodeling.cli.run_remodel import main as run_remodel_main - - args = [data_dir, model_path] - if backup_dir: - args.extend(["-bd", backup_dir]) - if backup_name: - args.extend(["-bn", backup_name]) - if use_bids: - args.append("-b") - if suffixes: - args.append("-fs") - args.extend(suffixes) - if individual_summaries: - args.extend(["-i", individual_summaries]) - if json_sidecar: - args.extend(["-j", json_sidecar]) - if log_dir: - args.extend(["-ld", log_dir]) - if no_backup: - args.append("-nb") - if no_summaries: - args.append("-ns") - if no_update: - args.append("-nu") - if hed_versions: - args.append("-hv") - args.extend(hed_versions) - if save_formats: - args.append("-s") - args.extend(save_formats) - if task_names: - args.append("-t") - args.extend(task_names) - if verbose: - args.append("-v") - if work_dir: - args.extend(["-w", work_dir]) - if exclude_dirs: - args.append("-x") - args.extend(exclude_dirs) - - run_remodel_main(args) - - -@remodel.command(name="backup") -@click.argument("data_dir", type=click.Path(exists=True)) -@click.option("-bd", "--backup-dir", default="", help="Directory for the backup being created.") -@click.option("-bn", "--backup-name", default="", help="Name for this backup.") -@click.option("-fs", "--file-suffix", "suffixes", multiple=True, default=["events"], help="File suffixes to backup.") -@click.option("-t", "--task-names", multiple=True, default=[], help="Task names to backup.") -@click.option("-v", "--verbose", is_flag=True, help="Enable verbose output.") -@click.option("-x", "--exclude-dirs", multiple=True, default=["derivatives"], help="Directories to exclude.") -def remodel_backup_cmd(data_dir, backup_dir, backup_name, suffixes, task_names, verbose, exclude_dirs): - """Create a backup of dataset files before remodeling. - - DATA_DIR: Root directory of the dataset to backup. - """ - from hed.tools.remodeling.cli.run_remodel_backup import main as backup_main - - args = [data_dir] - if backup_dir: - args.extend(["-bd", backup_dir]) - if backup_name: - args.extend(["-bn", backup_name]) - if suffixes: - args.append("-fs") - args.extend(suffixes) - if task_names: - args.append("-t") - args.extend(task_names) - if verbose: - args.append("-v") - if exclude_dirs: - args.append("-x") - args.extend(exclude_dirs) - - backup_main(args) - - -@remodel.command(name="restore") -@click.argument("data_dir", type=click.Path(exists=True)) -@click.option("-bd", "--backup-dir", default="", help="Directory containing the backup.") -@click.option("-bn", "--backup-name", default="", help="Name of backup to restore.") -@click.option("-t", "--task-names", multiple=True, default=[], help="Task names to restore.") -@click.option("-v", "--verbose", is_flag=True, help="Enable verbose output.") -def remodel_restore(data_dir, backup_dir, backup_name, task_names, verbose): - """Restore dataset files from a backup. - - DATA_DIR: Root directory of the dataset to restore. - """ - from hed.tools.remodeling.cli.run_remodel_restore import main as restore_main - - args = [data_dir] - if backup_dir: - args.extend(["-bd", backup_dir]) - if backup_name: - args.extend(["-bn", backup_name]) - if task_names: - args.append("-t") - args.extend(task_names) - if verbose: - args.append("-v") - - restore_main(args) - - @schema.command(name="validate") @click.argument("schema_path", type=click.Path(exists=True), nargs=-1, required=True) @click.option("--add-all-extensions", is_flag=True, help="Always verify all versions of the same schema are equal.") @@ -302,7 +136,7 @@ def schema_validate_cmd(schema_path, add_all_extensions, verbose): @click.argument("schema_path", type=click.Path(exists=True), nargs=-1, required=True) @click.option("--set-ids", is_flag=True, help="Set/update HED IDs in the schema.") def schema_convert_cmd(schema_path, set_ids): - """Convert HED schema between formats (TSV, XML, MediaWiki, JSON). + """Convert HED schema between formats (TSV, XML, MEDIAWIKI, JSON). SCHEMA_PATH: Path(s) to schema file(s) to convert. """ diff --git a/hed/schema/hed_schema.py b/hed/schema/hed_schema.py index 171f9804..21944eea 100644 --- a/hed/schema/hed_schema.py +++ b/hed/schema/hed_schema.py @@ -54,7 +54,7 @@ def __init__(self): self._namespace = "" self._sections = self._create_empty_sections() - self.source_format = None # The type of file this was loaded from(mediawiki, xml, or owl - None if mixed) + self.source_format = None # The type of file this was loaded from(MEDIAWIKI, XML, or JSON - None if mixed) # =============================================== # Basic schema properties @@ -286,14 +286,14 @@ def get_extras(self, extras_key) -> Union[DataFrame, None]: # pass def get_as_mediawiki_string(self, save_merged=False) -> str: - """Return the schema to a mediawiki string. + """Return the schema to a MEDIAWIKI string. Parameters: save_merged (bool): If True, this will save the schema as a merged schema if it is a "withStandard" schema. If it is not a "withStandard" schema, this setting has no effect. Returns: - str: The schema as a string in mediawiki format. + str: The schema as a string in MEDIAWIKI format. """ output_strings = Schema2Wiki().process_schema(self, save_merged) @@ -343,7 +343,7 @@ def get_as_dataframes(self, save_merged=False) -> dict[DataFrame]: return output_dfs def save_as_mediawiki(self, filename, save_merged=False): - """Save as mediawiki to a file. + """Save as MEDIAWIKI to a file. Parameters: filename (str): Save location. diff --git a/hed/schema/hed_schema_io.py b/hed/schema/hed_schema_io.py index 7d262c3e..910d650e 100644 --- a/hed/schema/hed_schema_io.py +++ b/hed/schema/hed_schema_io.py @@ -118,9 +118,9 @@ def from_string(schema_string, schema_format=".xml", schema_namespace=None, sche """Create a schema from the given string. Parameters: - schema_string (str): An XML or mediawiki file as a single long string + schema_string (str): An XML or MEDIAWIKI file as a single long string schema_format (str): The schema format of the source schema string. - Allowed normal values: .mediawiki, .xml + Allowed normal values: .mediawiki, .xml, .json schema_namespace (str, None): The name_prefix all tags in this schema will accept. schema (HedSchema or None): A HED schema to merge this new file into It must be a with-standard schema with the same value. diff --git a/hed/schema/schema_io/json2schema.py b/hed/schema/schema_io/json2schema.py index 5f812b2b..6b9c44de 100644 --- a/hed/schema/schema_io/json2schema.py +++ b/hed/schema/schema_io/json2schema.py @@ -116,7 +116,7 @@ def _parse_data(self): self._load_extras() # Parse each section - initialize attributes before loading each section - # This follows the same pattern as MediaWiki/XML loaders + # This follows the same pattern as MEDIAWIKI/XML loaders for section_key, parse_func in parse_order.items(): self._schema._initialize_attributes(section_key) parse_func() @@ -147,7 +147,7 @@ def _create_property_entry(self, prop_name, prop_data): if json_constants.DESCRIPTION_KEY in prop_data: desc = prop_data[json_constants.DESCRIPTION_KEY] - # Convert empty string back to None to match XML/MediaWiki behavior + # Convert empty string back to None to match XML/MEDIAWIKI behavior entry.description = desc if desc else None # Add any other attributes from the data @@ -493,7 +493,7 @@ def _load_extras(self): self._schema.extras = {} - # Load sources - always create DataFrame even if empty to match XML/MediaWiki behavior + # Load sources - always create DataFrame even if empty to match XML/MEDIAWIKI behavior sources_list = [] if json_constants.SOURCES_KEY in self._json_data: sources_data = self._json_data[json_constants.SOURCES_KEY] diff --git a/hed/schema/schema_io/schema2base.py b/hed/schema/schema_io/schema2base.py index d4ca80e1..ca0a57e0 100644 --- a/hed/schema/schema_io/schema2base.py +++ b/hed/schema/schema_io/schema2base.py @@ -1,4 +1,4 @@ -"""Baseclass for mediawiki/xml writers""" +"""Baseclass for MEDIAWIKI/XML/JSON/TSV writers""" from hed.schema.hed_schema_constants import HedSectionKey, HedKey from hed.errors.exceptions import HedFileError, HedExceptions @@ -15,7 +15,7 @@ def __init__(self): self._schema = None def process_schema(self, hed_schema, save_merged=False): - """Takes a HedSchema object and returns it in the inherited form(mediawiki, xml, etc) + """Takes a HedSchema object and returns it in the inherited form(MEDIAWIKI, XML, etc) Parameters: hed_schema (HedSchema): The schema to be processed. diff --git a/hed/schema/schema_io/schema2wiki.py b/hed/schema/schema_io/schema2wiki.py index edc67254..097fc273 100644 --- a/hed/schema/schema_io/schema2wiki.py +++ b/hed/schema/schema_io/schema2wiki.py @@ -1,4 +1,4 @@ -"""Allows output of HedSchema objects as .mediawiki format""" +"""Allows output of HedSchema objects as MEDIAWIKI format""" from hed.schema.hed_schema_constants import HedSectionKey from hed.schema.schema_io import wiki_constants, df_constants diff --git a/hed/schema/schema_io/wiki2schema.py b/hed/schema/schema_io/wiki2schema.py index 06d202a5..75cf8ef0 100644 --- a/hed/schema/schema_io/wiki2schema.py +++ b/hed/schema/schema_io/wiki2schema.py @@ -39,7 +39,7 @@ class SchemaLoaderWiki(SchemaLoader): - """Load MediaWiki schemas from filenames or strings. + """Load MEDIAWIKI schemas from filenames or strings. Expected usage is SchemaLoaderWiki.load(filename) @@ -269,7 +269,7 @@ def _read_attributes(self, lines): self._read_section(lines, HedSectionKey.Attributes) def _get_header_attributes_internal(self, version_line): - """Extracts all valid attributes like version from the HED line in .mediawiki format. + """Extracts all valid attributes like version from the HED line in MEDIAWIKI format. Parameters: version_line (str): The line in the wiki file that contains the version or other attributes. @@ -292,7 +292,7 @@ def _get_header_attributes_internal(self, version_line): return attributes def _get_header_attributes_internal_old(self, version_line): - """Extract all valid attributes like version from the HED line in .mediawiki format. + """Extract all valid attributes like version from the HED line in MEDIAWIKI format. Parameters: version_line (str): The line in the wiki file that contains the version or other attributes. diff --git a/hed/scripts/hed_script_util.py b/hed/scripts/hed_script_util.py index dcd7d46b..4afd7ea3 100644 --- a/hed/scripts/hed_script_util.py +++ b/hed/scripts/hed_script_util.py @@ -11,7 +11,7 @@ def validate_schema_object(base_schema, schema_name): """Validate a schema object by checking compliance and roundtrip conversion. Tests the schema for compliance issues and validates that it can be successfully - converted to and reloaded from all four formats (MediaWiki, XML, JSON, TSV). + converted to and reloaded from all four formats (MEDIAWIKI, XML, JSON, TSV). Parameters: base_schema (HedSchema): The schema object to validate. @@ -168,7 +168,7 @@ def sort_base_schemas(filenames, add_all_extensions=False): def validate_all_schema_formats(basename): """Validate that all 4 format versions of a schema are identical. - Loads the schema from all four formats (MediaWiki, XML, JSON, TSV) and + Loads the schema from all four formats (MEDIAWIKI, XML, JSON, TSV) and verifies they are equivalent. Used when multiple formats are modified simultaneously to ensure consistency. diff --git a/pyproject.toml b/pyproject.toml index b1900145..a72ca008 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -98,9 +98,6 @@ examples = [ hedpy = "hed.cli.cli:main" # Legacy commands (deprecated - use 'hedpy' instead) -run_remodel = "hed.tools.remodeling.cli.run_remodel:main" -run_remodel_backup = "hed.tools.remodeling.cli.run_remodel_backup:main" -run_remodel_restore = "hed.tools.remodeling.cli.run_remodel_restore:main" validate_bids = "hed.scripts.validate_bids:main" hed_extract_bids_sidecar = "hed.scripts.hed_extract_bids_sidecar:main" hed_validate_schemas = "hed.scripts.validate_schemas:main" diff --git a/requirements-dev.txt b/requirements-dev.txt index db9547c0..bee8afab 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,7 @@ coverage>=7.0.0 # Code quality tools ruff>=0.8.0 codespell>=2.2.0 -black>=24.0.0 +black[jupyter]>=24.0.0 # Documentation requirements sphinx>=7.0.0 diff --git a/tests/schema/test_schema_format_roundtrip.py b/tests/schema/test_schema_format_roundtrip.py index 386b44ec..14c77051 100644 --- a/tests/schema/test_schema_format_roundtrip.py +++ b/tests/schema/test_schema_format_roundtrip.py @@ -1,7 +1,7 @@ """ Unit tests for schema format I/O roundtrip validation. -Tests that schemas can be loaded, saved in all 4 formats (XML, MediaWiki, TSV, JSON), +Tests that schemas can be loaded, saved in all 4 formats (XML, MEDIAWIKI, TSV, JSON), and reloaded with perfect fidelity for both standard and library schemas. """ @@ -13,7 +13,7 @@ class TestSchemaFormatRoundtrip(unittest.TestCase): - """Test that all 4 schema formats (XML, MediaWiki, TSV, JSON) roundtrip correctly.""" + """Test that all 4 schema formats (XML, MEDIAWIKI, TSV, JSON) roundtrip correctly.""" @classmethod def setUpClass(cls): @@ -50,7 +50,7 @@ def _test_format_roundtrip(self, schema, schema_name, save_merged=True): # Verify files were created self.assertTrue(os.path.exists(xml_path), f"XML file not created: {xml_path}") - self.assertTrue(os.path.exists(mediawiki_path), f"MediaWiki file not created: {mediawiki_path}") + self.assertTrue(os.path.exists(mediawiki_path), f"MEDIAWIKI file not created: {mediawiki_path}") self.assertTrue(os.path.exists(json_path), f"JSON file not created: {json_path}") tsv_tag_file = os.path.join(tsv_dir, f"{basename}_Tag.tsv") self.assertTrue(os.path.exists(tsv_tag_file), f"TSV Tag file not created: {tsv_tag_file}") @@ -64,14 +64,14 @@ def _test_format_roundtrip(self, schema, schema_name, save_merged=True): # Compare all schemas to original self.assertEqual(schema, schema_from_xml, f"XML roundtrip failed for {schema_name} (save_merged={save_merged})") self.assertEqual( - schema, schema_from_mediawiki, f"MediaWiki roundtrip failed for {schema_name} (save_merged={save_merged})" + schema, schema_from_mediawiki, f"MEDIAWIKI roundtrip failed for {schema_name} (save_merged={save_merged})" ) self.assertEqual(schema, schema_from_tsv, f"TSV roundtrip failed for {schema_name} (save_merged={save_merged})") self.assertEqual(schema, schema_from_json, f"JSON roundtrip failed for {schema_name} (save_merged={save_merged})") # Compare all formats to each other self.assertEqual( - schema_from_xml, schema_from_mediawiki, f"XML vs MediaWiki mismatch for {schema_name} (save_merged={save_merged})" + schema_from_xml, schema_from_mediawiki, f"XML vs MEDIAWI mismatch for {schema_name} (save_merged={save_merged})" ) self.assertEqual( schema_from_xml, schema_from_tsv, f"XML vs TSV mismatch for {schema_name} (save_merged={save_merged})" @@ -127,7 +127,7 @@ def test_format_compatibility_standard(self): # Load all formats schemas = { "XML": load_schema(xml_path), - "MediaWiki": load_schema(mediawiki_path), + "MEDIAWIKI": load_schema(mediawiki_path), "TSV": load_schema(tsv_dir), "JSON": load_schema(json_path), } @@ -160,7 +160,7 @@ def test_format_compatibility_library_merged(self): # Load all formats schemas = { "XML": load_schema(xml_path), - "MediaWiki": load_schema(mediawiki_path), + "MEDIAWIKI": load_schema(mediawiki_path), "TSV": load_schema(tsv_dir), "JSON": load_schema(json_path), } @@ -193,7 +193,7 @@ def test_format_compatibility_library_unmerged(self): # Load all formats schemas = { "XML": load_schema(xml_path), - "MediaWiki": load_schema(mediawiki_path), + "MEDIAWIKI": load_schema(mediawiki_path), "TSV": load_schema(tsv_dir), "JSON": load_schema(json_path), } diff --git a/tests/test_cli_parameter_parity.py b/tests/test_cli_parameter_parity.py index 68bf9284..78d33e4a 100644 --- a/tests/test_cli_parameter_parity.py +++ b/tests/test_cli_parameter_parity.py @@ -8,9 +8,6 @@ from hed.scripts.validate_bids import get_parser as get_validate_bids_parser from hed.scripts.hed_extract_bids_sidecar import get_parser as get_extract_sidecar_parser from hed.scripts.validate_schemas import get_parser as get_validate_schemas_parser -from hed.tools.remodeling.cli.run_remodel import get_parser as get_remodel_parser -from hed.tools.remodeling.cli.run_remodel_backup import get_parser as get_backup_parser -from hed.tools.remodeling.cli.run_remodel_restore import get_parser as get_restore_parser class TestCLIParameterParity(unittest.TestCase): @@ -141,105 +138,6 @@ def test_validate_bids_parameters(self): if flag in original_flags: self.assertIn(flag, cli_flags, f"Flag '{flag}' from original parser not found in CLI") - def test_remodel_backup_parameters(self): - """Test remodel backup CLI parameters match run_remodel_backup.py parser.""" - original_parser = get_backup_parser() - original_opts = self._get_parser_options(original_parser) - - # Get remodel group, then backup command - remodel_group = cli.commands.get("remodel") - self.assertIsNotNone(remodel_group, "remodel group not found") - - backup_command = remodel_group.commands.get("backup") - self.assertIsNotNone(backup_command, "backup command not found in remodel group") - - cli_opts = self._get_click_options(backup_command) - - # Check positional count matches - self.assertEqual( - len(cli_opts["positional"]), - len(original_opts["positional"]), - f"Positional argument count mismatch: CLI has {len(cli_opts['positional'])}, original has {len(original_opts['positional'])}", - ) - - # Check optional parameters from original parser exist in CLI - original_dests = set(original_opts["optional"].keys()) - cli_dests = set(cli_opts["optional"].keys()) - - for orig_dest in original_dests: - self.assertIn(orig_dest, cli_dests, f"Parameter '{orig_dest}' from original parser not found in CLI") - - # Check flags from original parser exist in CLI - original_flags = {flag[0] for flag in original_opts["flags"]} - cli_flags = {flag[0] for flag in cli_opts["flags"]} - - for orig_flag in original_flags: - self.assertIn(orig_flag, cli_flags, f"Flag '{orig_flag}' from original parser not found in CLI") - - def test_remodel_restore_parameters(self): - """Test remodel restore CLI parameters match run_remodel_restore.py parser.""" - original_parser = get_restore_parser() - original_opts = self._get_parser_options(original_parser) - - remodel_group = cli.commands.get("remodel") - restore_command = remodel_group.commands.get("restore") - self.assertIsNotNone(restore_command, "restore command not found") - - cli_opts = self._get_click_options(restore_command) - - # Check positional count matches - self.assertEqual( - len(cli_opts["positional"]), - len(original_opts["positional"]), - f"Positional argument count mismatch: CLI has {len(cli_opts['positional'])}, original has {len(original_opts['positional'])}", - ) - - # Check optional parameters from original parser exist in CLI - original_dests = set(original_opts["optional"].keys()) - cli_dests = set(cli_opts["optional"].keys()) - - for orig_dest in original_dests: - self.assertIn(orig_dest, cli_dests, f"Parameter '{orig_dest}' from original parser not found in CLI") - - # Check flags from original parser exist in CLI - original_flags = {flag[0] for flag in original_opts["flags"]} - cli_flags = {flag[0] for flag in cli_opts["flags"]} - - for orig_flag in original_flags: - self.assertIn(orig_flag, cli_flags, f"Flag '{orig_flag}' from original parser not found in CLI") - - def test_remodel_run_parameters(self): - """Test remodel run CLI parameters match run_remodel.py parser.""" - original_parser = get_remodel_parser() - original_opts = self._get_parser_options(original_parser) - - remodel_group = cli.commands.get("remodel") - run_command = remodel_group.commands.get("run") - self.assertIsNotNone(run_command, "run command not found") - - cli_opts = self._get_click_options(run_command) - - # Check positional count matches - self.assertEqual( - len(cli_opts["positional"]), - len(original_opts["positional"]), - f"Positional argument count mismatch: CLI has {len(cli_opts['positional'])}, original has {len(original_opts['positional'])}", - ) - - # Check optional parameters from original parser exist in CLI - original_dests = set(original_opts["optional"].keys()) - cli_dests = set(cli_opts["optional"].keys()) - - for orig_dest in original_dests: - self.assertIn(orig_dest, cli_dests, f"Parameter '{orig_dest}' from original parser not found in CLI") - - # Check flags from original parser exist in CLI - original_flags = {flag[0] for flag in original_opts["flags"]} - cli_flags = {flag[0] for flag in cli_opts["flags"]} - - for orig_flag in original_flags: - self.assertIn(orig_flag, cli_flags, f"Flag '{orig_flag}' from original parser not found in CLI") - def test_extract_sidecar_parameters(self): """Test extract-sidecar CLI parameters match hed_extract_bids_sidecar.py parser.""" original_parser = get_extract_sidecar_parser() @@ -336,9 +234,6 @@ def test_all_legacy_commands_have_cli_equivalents(self): # Legacy commands from pyproject.toml legacy_to_cli = { "validate_bids": "validate-bids", - "run_remodel": "remodel run", - "run_remodel_backup": "remodel backup", - "run_remodel_restore": "remodel restore", "hed_extract_bids_sidecar": "extract-sidecar", "hed_validate_schemas": "schema validate", "hed_update_schemas": "schema convert", From 98f1dbd548c9b5f4f93d10f879f33d8958954d6b Mon Sep 17 00:00:00 2001 From: Kay Robbins <1189050+VisLab@users.noreply.github.com> Date: Sat, 20 Dec 2025 16:56:59 -0600 Subject: [PATCH 2/2] Corrected typo --- tests/schema/test_schema_format_roundtrip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/schema/test_schema_format_roundtrip.py b/tests/schema/test_schema_format_roundtrip.py index 14c77051..68330fec 100644 --- a/tests/schema/test_schema_format_roundtrip.py +++ b/tests/schema/test_schema_format_roundtrip.py @@ -71,7 +71,7 @@ def _test_format_roundtrip(self, schema, schema_name, save_merged=True): # Compare all formats to each other self.assertEqual( - schema_from_xml, schema_from_mediawiki, f"XML vs MEDIAWI mismatch for {schema_name} (save_merged={save_merged})" + schema_from_xml, schema_from_mediawiki, f"XML vs MEDIAWIKI mismatch for {schema_name} (save_merged={save_merged})" ) self.assertEqual( schema_from_xml, schema_from_tsv, f"XML vs TSV mismatch for {schema_name} (save_merged={save_merged})"