-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathcli.py
More file actions
164 lines (138 loc) · 4.75 KB
/
cli.py
File metadata and controls
164 lines (138 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""CLI for wristpy."""
import logging
import pathlib
from enum import Enum
import typer
from wristpy.core import config
logger = config.get_logger()
app = typer.Typer(
help="Run the main Wristpy pipeline.",
epilog="Please report issues at https://github.com/childmindresearch/wristpy.",
)
class OutputFileType(str, Enum):
"""Valid output file types for saving data."""
csv = ".csv"
parquet = ".parquet"
class Calibrator(str, Enum):
"""Setting a calibrator class for typer.
This class is used to define the literal types that are allowed for
calibration, and parsing the strings for the orchestrator.
"""
none = "none"
ggir = "ggir"
gradient = "gradient"
class ActivityMetric(str, Enum):
"""Valid activity metrics for physical activity categorization."""
enmo = "enmo"
mad = "mad"
ag_count = "ag_count"
mims = "mims"
class NonwearAlgorithms(str, Enum):
"""Setting a nonwear algorithm class for typer.
This class is used to define the literal types that are allowed for
nonwear algorithms, and parsing the strings for the orchestrator.
"""
ggir = "ggir"
cta = "cta"
detach = "detach"
@app.command()
def main(
input: pathlib.Path = typer.Argument(
..., help="Path to the input data.", exists=True
),
output: pathlib.Path = typer.Option(
None,
"-o",
"--output",
help="Path where data will be saved. Supports .csv and .parquet formats.",
),
output_filetype: OutputFileType = typer.Option(
None,
"-O",
"--output-filetype",
help="Format for save files when processing directories. "
"Leave as None when processing single files.",
),
calibrator: Calibrator = typer.Option(
Calibrator.none,
"-c",
"--calibrator",
help="Pick which calibrator to use. "
"Must choose one of 'none', 'ggir', or 'gradient'.",
case_sensitive=False,
),
activity_metric: ActivityMetric = typer.Option(
ActivityMetric.enmo,
"-a",
"--activity-metric",
help="Metric used for physical activity categorization. "
"Choose from 'enmo', 'mad', 'ag_count', or 'mims'. ",
case_sensitive=False,
),
thresholds: tuple[float, float, float] = typer.Option(
None,
"-t",
"--thresholds",
help="Provide three thresholds for light, moderate, and vigorous activity. "
"Exactly three values must be >= 0, given in ascending order, "
"and separated by a space. (e.g. '-t 0.1 1.0 1.5').",
min=0,
),
nonwear_algorithm: list[NonwearAlgorithms] = typer.Option(
[NonwearAlgorithms.ggir],
"-n",
"--nonwear-algorithm",
help="Specify the non-wear detection algorithm(s) to use. "
"Specify one or more of 'ggir', 'cta', 'detach'. "
"(e.g. '-n ggir -n cta'). "
"When multiple algorithms are specified, majority voting will be applied.",
),
epoch_length: int = typer.Option(
5,
"-e",
"--epoch-length",
help="Specify the sampling rate in seconds for all metrics. "
"Must be greater than or equal to 1.",
min=1,
),
verbosity: int = typer.Option(
0,
"-v",
"--verbosity",
count=True,
help="Determines the level of verbosity. Use -v for info, -vv for debug. "
"If -vvv or more, it will be set to debug. "
"Default for warning.",
),
version: bool = typer.Option(
False, "-V", "--version", help="Show the version and exit."
),
) -> None:
"""Run wristpy orchestrator with command line arguments."""
from wristpy.core import orchestrator
if version:
typer.echo(f"Wristpy version: {config.get_version()}")
raise typer.Exit()
if verbosity == 0:
log_level = logging.WARNING
elif verbosity == 1:
log_level = logging.INFO
else:
log_level = logging.DEBUG
logger.setLevel(log_level)
nonwear_algorithms = [algo.value for algo in nonwear_algorithm]
calibrator_value = None if calibrator == Calibrator.none else calibrator.value
logger.debug("Running wristpy. arguments given: %s", locals())
orchestrator.run(
input=input,
output=output,
calibrator=calibrator_value,
activity_metric=activity_metric.value,
thresholds=None if thresholds is None else thresholds,
epoch_length=epoch_length,
nonwear_algorithm=nonwear_algorithms, # type: ignore[arg-type] # Covered by NonwearAlgorithm Enum class
verbosity=log_level,
output_filetype=output_filetype.value if output_filetype else None, # type: ignore[arg-type] # Covered by OutputFileType Enum class
)
if __name__ == "__main__":
app()