-
Notifications
You must be signed in to change notification settings - Fork 6
correction of lookup label #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e182f97
41c709e
3f18f64
b845c32
367e48d
fc67169
48e76ea
186c42d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,12 +3,13 @@ | |
| from openminds import Collection | ||
| import os | ||
| import click | ||
| import re | ||
| from . import main | ||
| from . import utility | ||
| from . import report | ||
|
|
||
|
|
||
| def convert(input_path, save_output=False, output_path=None, multiple_files=False, include_empty_properties=False, quiet=False): | ||
| def convert(input_path, save_output=False, output_path=None, multiple_files=False, include_empty_properties=False, quiet=False, short_name=None): | ||
| if not (os.path.isdir(input_path)): | ||
| raise NotADirectoryError( | ||
| f"The input directory is not valid, you have specified {input_path} which is not a directory." | ||
|
|
@@ -32,8 +33,42 @@ def convert(input_path, save_output=False, output_path=None, multiple_files=Fal | |
|
|
||
| dataset_description = utility.read_json(dataset_description_path.iat[0, 0]) | ||
|
|
||
| if short_name is None: | ||
| while True: | ||
| input_name = input( | ||
| "To convert this dataset, a short name is required.\n" | ||
| "Please enter an informative short name (less than 10 characters).\n" | ||
| "If you don't want to assign one now, press Enter, " | ||
| "lookup labels and internal identifiers will be the same.\n> " | ||
| ).strip() | ||
|
|
||
| # User pressed Enter → skip assigning | ||
| if not input_name: | ||
| short_name = None | ||
| break | ||
|
|
||
| # Check length | ||
| if len(input_name) < 10: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not an requirement from our side |
||
| short_name = input_name | ||
| break | ||
| else: | ||
| print( | ||
| "The short name must be fewer than 10 characters. Please try again.\n") | ||
|
|
||
| elif short_name is False: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't be none later needs to be defined (is a required property and needs to be set as a default) |
||
| # Explicit opt-out — skip prompt | ||
| short_name = None | ||
|
|
||
| else: | ||
| # Ensure the short name has no spaces and is under 10 characters | ||
| short_name = short_name.replace(" ", "") | ||
| if len(short_name) > 10: | ||
| while len(short_name) > 10: | ||
| short_name = input( | ||
| "The short name must be fewer than 10 characters. Please try again.").strip() | ||
|
|
||
| [subjects_dict, subject_state_dict, subjects_list] = main.create_subjects( | ||
| subjects_id, layout_df, bids_layout, collection) | ||
| subjects_id, layout_df, bids_layout, collection, short_name) | ||
|
|
||
| behavioral_protocols, behavioral_protocols_dict = main.create_behavioral_protocol( | ||
| bids_layout, collection) | ||
|
|
@@ -42,10 +77,10 @@ def convert(input_path, save_output=False, output_path=None, multiple_files=Fal | |
| layout_df, input_path, collection) | ||
|
|
||
| dataset_version = main.create_dataset_version( | ||
| bids_layout, dataset_description, layout_df, subjects_list, file_repository, behavioral_protocols, collection) | ||
| bids_layout, dataset_description, layout_df, subjects_list, file_repository, behavioral_protocols, short_name, collection) | ||
|
|
||
| dataset = main.create_dataset( | ||
| dataset_description, dataset_version, collection) | ||
| dataset_description, dataset_version, short_name, collection) | ||
|
|
||
| failures = collection.validate(ignore=["required", "value"]) | ||
| assert len(failures) == 0 | ||
|
|
@@ -60,9 +95,13 @@ def convert(input_path, save_output=False, output_path=None, multiple_files=Fal | |
| collection.save(output_path, individual_files=multiple_files, | ||
| include_empty_properties=include_empty_properties) | ||
|
|
||
| save_text = f"the openMINDS file is in {output_path}" | ||
| else: | ||
| save_text = save_text = "No files were saved; the function returned the output collection instead." | ||
|
|
||
| if not quiet: | ||
| print(report.create_report(dataset, dataset_version, collection, | ||
| dataset_description, input_path, output_path)) | ||
| dataset_description, input_path, save_text)) | ||
|
|
||
| else: | ||
| print("Conversion was successful") | ||
|
|
@@ -77,9 +116,10 @@ def convert(input_path, save_output=False, output_path=None, multiple_files=Fal | |
| @click.option("--multiple-files", "multiple_files", flag_value=True, help="Each node is saved into a separate file within the specified directory. 'output-path' if specified, must be a directory.") | ||
| @click.option("-e", "--include-empty-properties", is_flag=True, default=False, help="Whether to include empty properties in the final file.") | ||
| @click.option("-q", "--quiet", is_flag=True, default=False, help="Not generate the final report and no warning.") | ||
| def convert_click(input_path, output_path, multiple_files, include_empty_properties, quiet): | ||
| @click.option("-n", "--short-name", default=None, help="Short name for the dataset (less than 10 characters). If None, you'll be prompted (default); if False, no short name will be assigned.") | ||
| def convert_click(input_path, output_path, multiple_files, include_empty_properties, quiet, short_name): | ||
| convert(input_path, save_output=True, output_path=output_path, | ||
| multiple_files=multiple_files, include_empty_properties=include_empty_properties, quiet=quiet) | ||
| multiple_files=multiple_files, include_empty_properties=include_empty_properties, quiet=quiet, short_name=short_name) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -184,7 +184,7 @@ def create_openminds_age(data_subject): | |
| return None | ||
|
|
||
|
|
||
| def create_dataset_version(bids_layout, dataset_description, layout_df, studied_specimens, file_repository, behavioral_protocols, collection): | ||
| def create_dataset_version(bids_layout, dataset_description, layout_df, studied_specimens, file_repository, behavioral_protocols, short_name, collection): | ||
|
|
||
| # Fetch the dataset type from dataset description file | ||
|
|
||
|
|
@@ -236,7 +236,7 @@ def create_dataset_version(bids_layout, dataset_description, layout_df, studied_ | |
| dataset_version = omcore.DatasetVersion( | ||
| digital_identifier=digital_identifier, | ||
| experimental_approaches=experimental_approaches, | ||
| short_name=dataset_description["Name"], | ||
| short_name=short_name, | ||
| full_name=dataset_description["Name"], | ||
| studied_specimens=studied_specimens, | ||
| authors=authors, | ||
|
|
@@ -254,13 +254,13 @@ def create_dataset_version(bids_layout, dataset_description, layout_df, studied_ | |
| return dataset_version | ||
|
|
||
|
|
||
| def create_dataset(dataset_description, dataset_version, collection): | ||
| def create_dataset(dataset_description, dataset_version, short_name, collection): | ||
|
|
||
| dataset = omcore.Dataset( | ||
| digital_identifier=dataset_version.digital_identifier, | ||
| authors=dataset_version.authors, | ||
| full_name=dataset_version.full_name, | ||
| short_name=dataset_version.short_name, | ||
| short_name=short_name, | ||
| has_versions=dataset_version | ||
| ) | ||
|
|
||
|
|
@@ -315,7 +315,13 @@ def sex_openminds(data_subject: pd.DataFrame): | |
| return None | ||
|
|
||
|
|
||
| def create_subjects(subject_id, layout_df, layout, collection): | ||
| def create_subjects(subject_id, layout_df, layout, collection, dataset_short_name): | ||
Peyman-N marked this conversation as resolved.
Show resolved
Hide resolved
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. short_name or dataset_short_name? what is the difference? |
||
|
|
||
| if dataset_short_name: | ||
| dataset_short_name_ = dataset_short_name + "_" | ||
| else: | ||
| # If there is no short name, assign an empty string so lookup labels don’t include it | ||
| dataset_short_name_ = "" | ||
|
|
||
| sessions = layout.get_sessions() | ||
| subjects_dict = {} | ||
|
|
@@ -333,9 +339,8 @@ def create_subjects(subject_id, layout_df, layout, collection): | |
| # dealing with condition that have no seasion | ||
| if not sessions: | ||
| state = omcore.SubjectState( | ||
| internal_identifier=f"Studied state {subject_name}".strip( | ||
| ), | ||
| lookup_label=f"Studied state {subject_name}".strip() | ||
| lookup_label=f"{dataset_short_name_}{subject_name}_ses-01".strip(), | ||
| internal_identifier=None | ||
| ) | ||
| collection.add(state) | ||
| state_cache_dict[""] = state | ||
|
|
@@ -345,17 +350,16 @@ def create_subjects(subject_id, layout_df, layout, collection): | |
| for session in sessions: | ||
| if not (table_filter(table_filter(layout_df, session, "session"), subject, "subject").empty): | ||
| state = omcore.SubjectState( | ||
| internal_identifier=f"Studied state {subject_name} {session}".strip( | ||
| ), | ||
| lookup_label=f"Studied state {subject_name} {session}".strip( | ||
| lookup_label=f"{dataset_short_name_}{subject_name}_ses-{session}".strip(), | ||
| internal_identifier=f"{subject_name}_ses-{session}".strip( | ||
| ) | ||
| ) | ||
| collection.add(state) | ||
| state_cache_dict[f"{session}"] = state | ||
| state_cache.append(state) | ||
| subject_state_dict[f"{subject}"] = state_cache_dict | ||
| subject_cache = omcore.Subject( | ||
| lookup_label=f"{subject_name}", | ||
| lookup_label=f"{dataset_short_name_}{subject_name}", | ||
| internal_identifier=f"{subject_name}", | ||
| studied_states=state_cache | ||
| ) | ||
|
|
@@ -380,8 +384,8 @@ def create_subjects(subject_id, layout_df, layout, collection): | |
| state = omcore.SubjectState( | ||
| age=create_openminds_age(data_subject), | ||
| handedness=handedness_openminds(data_subject), | ||
| internal_identifier=f"Studied state {subject_name}".strip(), | ||
| lookup_label=f"Studied state {subject_name}".strip() | ||
| internal_identifier=None, | ||
| lookup_label=f"{dataset_short_name_}{subject_name}_ses-01".strip() | ||
| ) | ||
| collection.add(state) | ||
| state_cache_dict[""] = state | ||
|
|
@@ -392,18 +396,16 @@ def create_subjects(subject_id, layout_df, layout, collection): | |
| state = omcore.SubjectState( | ||
| age=create_openminds_age(data_subject), | ||
| handedness=handedness_openminds(data_subject), | ||
| internal_identifier=f"Studied state {subject_name} {session}".strip( | ||
| ), | ||
| lookup_label=f"Studied state {subject_name} {session}".strip( | ||
| ) | ||
| internal_identifier=f"{subject_name}_ses-{session}".strip(), | ||
| lookup_label=f"{dataset_short_name_}{subject_name}_ses-{session}".strip() | ||
| ) | ||
| collection.add(state) | ||
| state_cache_dict[f"{session}"] = state | ||
| state_cache.append(state) | ||
| subject_state_dict[f"{subject}"] = state_cache_dict | ||
| subject_cache = omcore.Subject( | ||
| biological_sex=sex_openminds(data_subject), | ||
| lookup_label=f"{subject_name}", | ||
| lookup_label=f"{dataset_short_name_}{subject_name}", | ||
| internal_identifier=f"{subject_name}", | ||
| # TODO species should default to homo sapiens | ||
| species=spices_openminds(data_subject), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ The ``convert`` function processes a Brain Imaging Data Structure (BIDS) directo | |
|
|
||
| Function Signature | ||
| ################## | ||
| >>> def convert(input_path, save_output=False, output_path=None, multiple_files=False, include_empty_properties=False, quiet=False): | ||
| >>> def convert(input_path, save_output=False, output_path=None, short_name=None, multiple_files=False, include_empty_properties=False, quiet=False): | ||
|
|
||
| Parameters | ||
| ########## | ||
|
|
@@ -23,6 +23,7 @@ Parameters | |
| - ``multiple_files`` (bool, default=False): If True, the OpenMINDS data will be saved into multiple files within the specified output_path. | ||
| - ``include_empty_properties`` (bool, default=False): If True, includes all the openMINDS properties with empty values in the final output. Otherwise includes only properties that have a non `None` value. | ||
| - ``quiet`` (bool, default=False): If True, suppresses warnings and the final report output. Only prints success messages. | ||
| - ``short_name`` (str or bool, default=None): A short name for the dataset (less than 10 characters). If None, you'll be prompted (default); if False, no short name will be assigned. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the character limitation is not correct. we don't have this. also if False it cannot just be not defined. It has to be defined. If False a default needs to be set. |
||
|
|
||
| Returns | ||
| ####### | ||
|
|
@@ -32,7 +33,7 @@ Example Usage | |
| ############# | ||
| >>> import bids2openminds.converter as converter | ||
| >>> input_path = "/path/to/BIDS/dataset" | ||
| >>> collection = converter.convert(input_path, save_output=True, output_path="/path/to/output", multiple_files=False, include_empty_properties=False, quiet=False) | ||
| >>> collection = converter.convert(input_path, save_output=True, short_name=ShortName, output_path="/path/to/output", multiple_files=False, include_empty_properties=False, quiet=False) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this the convention (CamelCase) how to write string variables? |
||
|
|
||
| Or one can chose the default parmetrs as following: | ||
|
|
||
|
|
@@ -48,14 +49,23 @@ This function is also accessible via a command-line interface using the `click` | |
|
|
||
| Usage: bids2openminds [OPTIONS] INPUT_PATH | ||
|
|
||
| Arguments: | ||
| input-path Path to the BIDS directory. | ||
|
|
||
| Options: | ||
| -o, --output-path PATH The output path or filename for OpenMINDS file/files. | ||
| --single-file Save the entire collection into a single file (default). | ||
| --multiple-files Save each node into a separate file within the specified directory. | ||
| -e, --include-empty-properties | ||
| Include empty properties in the final file. | ||
| -q, --quiet Suppress warnings and reports. | ||
| -o, --output-path PATH The output path or filename for OpenMINDS | ||
| file/files. | ||
| --single-file Save the entire collection into a single | ||
| file (default). | ||
| --multiple-files Each node is saved into a separate file | ||
| within the specified directory. 'output- | ||
| path' if specified, must be a directory. | ||
| -e, --include-empty-properties Whether to include empty properties in the | ||
| final file. | ||
| -q, --quiet Not generate the final report and no | ||
| warning. | ||
| -n, --short-name TEXT Short name for the dataset (less than 10 | ||
| characters). If None, you'll be prompted | ||
| (default); if False, no short name will be | ||
| assigned. | ||
| --help Show this message and exit. | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand that part. This should not be a prompt but a function in my opinion and the short name should be set automatically from available information when not specified/overwritten and should not be required for proceeding.
Automatic setting could use the short citation handle (e.g. Zehl et al. 2024) as done in EBRAINS.