Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 79 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,98 @@ Currently, `graphomotor` is available as an importable Python library. CLI funct

### Extracting Features from Spiral Drawing Data

#### Single File Processing

```python
from graphomotor.core import orchestrator

# Path to your spiral drawing data file
input_file = "path/to/your/spiral_data.csv"

# Directory where extracted features will be saved
output_dir = "path/to/output/directory"
# Option 1: Process file without saving any CSV file
# Only return the DataFrame with extracted features
features_df = orchestrator.run_pipeline(
input_path=input_file
)

# Option 2: Save to a directory with auto-generated filename
# Creates a CSV file with auto-generated name in the specified directory
# Format: {participant_id}_{task}_{hand}_features_{YYYYMMDD_HHMM}.csv
features_df = orchestrator.run_pipeline(
input_path=input_file,
output_path="path/to/output/directory"
)

# Run the analysis pipeline
features = orchestrator.run_pipeline(
# Option 3: Save to a specific CSV file
# Features will be saved to the specified file path
features_df = orchestrator.run_pipeline(
input_path=input_file,
output_path=output_dir
output_path="path/to/features.csv"
)

# Features are returned as a dictionary and saved as CSV
print(f"Successfully extracted {len(features)} feature categories")
# Features are returned as a pandas DataFrame with source file as index
print(f"Successfully processed {len(features_df)} file")
print(f"Extracted features: {list(features_df.columns)}")

# Access the single file's data (features_df has one row)
file_path = features_df.index[0]
print(f"File: {file_path}")
print(f"Participant: {features_df.loc[file_path, 'participant_id']}")
print(f"Task: {features_df.loc[file_path, 'task']}")
print(f"Hand: {features_df.loc[file_path, 'hand']}")
print(f"Duration: {features_df.loc[file_path, 'duration']}")
```

For detailed configuration options and additional parameters, refer to the [`run_pipeline` documentation](https://childmindresearch.github.io/graphomotor/graphomotor/core/orchestrator.html#run_pipeline).
#### Batch Processing

```python
from graphomotor.core import orchestrator

# Path to directory containing multiple spiral drawing data files
input_dir = "path/to/your/spiral_data_directory"

# Option 1: Process files without saving any CSV files
# Only return the DataFrame with extracted features
features_df = orchestrator.run_pipeline(
input_path=input_dir,
)

# Option 2: Save to a directory with auto-generated filename
# Creates a single consolidated CSV file with auto-generated name
# Format: batch_features_{YYYYMMDD_HHMM}.csv
features_df = orchestrator.run_pipeline(
input_path=input_dir,
output_path="path/to/output/directory"
)

# Option 3: Save to a specific CSV file (single consolidated file)
# All features will be written to one specified file
features_df = orchestrator.run_pipeline(
input_path=input_dir,
output_path="path/to/consolidated_features.csv"
)

# Features are returned as a pandas DataFrame with source files as index
# Columns include: participant_id, task, hand, start_time, and calculated features
print(f"Successfully processed {len(features_df)} files")

> **Note:** Currently, only single file processing is supported, with batch processing planned for future releases.
# Access metadata and features for a specific file
for file_path in features_df.index:
print(f"File: {file_path}")
print(f"Participant: {features_df.loc[file_path, 'participant_id']}")
print(f"Task: {features_df.loc[file_path, 'task']}")
print(f"Hand: {features_df.loc[file_path, 'hand']}")
print(f"Duration: {features_df.loc[file_path, 'duration']}")

# Or work with the DataFrame directly
print(f"Mean duration across all files: {features_df['duration'].astype(float).mean()}")
print(f"Spiral with highest linear velocity: {features_df['linear_velocity_median'].astype(float).idxmax()}")

# Easy filtering and grouping by metadata
print(f"Files with dominant hand: {len(features_df[features_df['hand'] == 'Dom'])}")
```

For detailed configuration options and additional parameters, refer to the [`run_pipeline` documentation](https://childmindresearch.github.io/graphomotor/graphomotor/core/orchestrator.html#run_pipeline).

## Future Directions

Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ dependencies = [
"pandas>=2.2.3",
"pydantic>=2.11.1",
"scipy>=1.15.2",
"shapely>=2.1.0"
"shapely>=2.1.0",
"tqdm>=4.66.0"
]

[dependency-groups]
Expand Down
3 changes: 2 additions & 1 deletion src/graphomotor/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class Spiral(pydantic.BaseModel):
- id: Unique identifier for the participant,
- hand: Hand used ('Dom' for dominant, 'NonDom' for non-dominant),
- task: Task name,
- start_time: Start time of drawing.
- start_time: Start time of drawing,
- source_path: Path to the source CSV file.
"""

model_config = pydantic.ConfigDict(arbitrary_types_allowed=True)
Expand Down
Loading
Loading