Skip to content

oxytcmri.infrastructure.cli

Command line interface.

Classes:

Name Description
CLIOptionFactory

Factory class for creating Typer CLI options with consistent parameters.

DatabaseSetup

Utility class for database configuration.

CLIArgumentParser

Parser for CLI arguments with support for various data types.

ControllerFactory

Factory for creating controllers with appropriate configurations.

BaseDTICommand

Abstract base class defining the common workflow for DTI commands.

ComputeDTINormativeValuesCommand

Command to compute DTI normative values.

SegmentDTILesionsCommand

Command to segment DTI lesions.

ComputeBrainLesionsVolumesCommand

Command to compute brain lesions volumes.

LoadData

Command to load data into the database.

Functions:

Name Description
load_data

Load data into the database from configured importers.

compute_dti_normative_values

Compute DTI normative values for all centers and store the results in the database.

segment_dti_lesions

Segment DTI lesions based on normative values.

compute_brain_lesions_volumes

Compute brain lesions volumes for specified DTI metrics and MRI exam.

Attributes:

Name Type Description
command_line_interface

command_line_interface = typer.Typer(add_completion=False) module-attribute

CLIOptionFactory

Factory class for creating Typer CLI options with consistent parameters.

Methods:

Name Description
settings_option

Create a standard settings file option.

dti_metrics_option

Create a standard DTI metrics option.

statistics_strategies_option

Create a statistics strategies option.

mri_exam_id_option

Create a standard MRI exam ID option.

regions_of_interest_option

Create a regions of interest option.

settings_option() staticmethod

Create a standard settings file option.

Returns:

Type Description
Option

Option for settings file path

Source code in oxytcmri/infrastructure/cli.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@staticmethod
def settings_option():
    """Create a standard settings file option.

    Returns
    -------
    typer.Option
        Option for settings file path
    """
    return typer.Option(
        ...,
        "--settings",
        "-s",
        help="Path to the settings file"
    )

dti_metrics_option() staticmethod

Create a standard DTI metrics option.

Returns:

Type Description
Option

Option for DTI metrics

Source code in oxytcmri/infrastructure/cli.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@staticmethod
def dti_metrics_option():
    """Create a standard DTI metrics option.

    Returns
    -------
    typer.Option
        Option for DTI metrics
    """
    return typer.Option(
        None,
        "--dti-metrics",
        "-dti",
        help="Comma-separated list of DTI metrics to include in computations (e.g. 'FA,MD')"
    )

statistics_strategies_option() staticmethod

Create a statistics strategies option.

Returns:

Type Description
Option

Option for statistics strategies

Source code in oxytcmri/infrastructure/cli.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@staticmethod
def statistics_strategies_option():
    """Create a statistics strategies option.

    Returns
    -------
    typer.Option
        Option for statistics strategies
    """
    return typer.Option(
        None,
        "--statistics-strategies",
        "-stats",
        help="Comma-separated list of statistical strategies to include in computations (e.g. 'mean,std_dev')"
    )

mri_exam_id_option() classmethod

Create a standard MRI exam ID option.

Returns:

Type Description
Option

Option for MRI exam ID

Source code in oxytcmri/infrastructure/cli.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
@classmethod
def mri_exam_id_option(cls):
    """
    Create a standard MRI exam ID option.

    Returns
    -------
    typer.Option
        Option for MRI exam ID
    """
    return typer.Option(
        None,
        "--mri-exam-id",
        "-mri",
        help="MRI exam ID to segment lesions"
    )

regions_of_interest_option() classmethod

Create a regions of interest option.

Returns:

Type Description
Option

Option for regions of interest

Source code in oxytcmri/infrastructure/cli.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
@classmethod
def regions_of_interest_option(cls):
    """Create a regions of interest option.

    Returns
    -------
    typer.Option
        Option for regions of interest
    """
    return typer.Option(
        None,
        "--regions-of-interest",
        "-roi",
        help="Comma-separated list of regions of interest for volume computation (e.g. 'thalamus,corpus_callosum')"
    )

DatabaseSetup

Utility class for database configuration.

Methods:

Name Description
create_database_gateway

Configure and return a database gateway.

create_database_gateway(settings) staticmethod

Configure and return a database gateway.

Parameters:

Name Type Description Default
settings Settings

The application settings

required

Returns:

Type Description
SQLModelSQLiteDataGateway

Configured database gateway

Raises:

Type Description
FileExistsError

If database file exists and overwrite_database_file is False

Source code in oxytcmri/infrastructure/cli.py
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
@staticmethod
def create_database_gateway(settings: Settings) -> SQLModelSQLiteDataGateway:
    """Configure and return a database gateway.

    Parameters
    ----------
    settings: Settings
        The application settings

    Returns
    -------
    SQLModelSQLiteDataGateway
        Configured database gateway

    Raises
    ------
    FileExistsError
        If database file exists and overwrite_database_file is False
    """
    sqlite_database_path = settings.database.path
    overwrite_database_file = settings.database.overwrite_data
    # Delete the existing database file if it exists and overwrite option is set to True
    if Path(sqlite_database_path).exists():
        if overwrite_database_file:
            Path(sqlite_database_path).unlink()
    else:
        # Create the database file if it does not exist
        Path(sqlite_database_path).touch()
    return SQLModelSQLiteDataGateway(sqlite_database_path)

CLIArgumentParser

Parser for CLI arguments with support for various data types.

This class centralizes the parsing logic for different types of CLI arguments, providing consistent error handling and format conversion.

Methods:

Name Description
parse_dti_metrics

Parse DTI metrics input and return a typed list.

parse_statistics_strategies

Parse statistics strategies input and return a typed list.

parse_mri_exam_id

Parse MRI exam ID input.

parse_dti_metrics(metrics_input) staticmethod

Parse DTI metrics input and return a typed list.

Parameters:

Name Type Description Default
metrics_input Optional[List[str]]

Raw input from CLI for DTI metrics

required

Returns:

Type Description
List[DTIMetric]

Parsed DTI metrics

Raises:

Type Description
ValueError

If invalid metrics are provided

Source code in oxytcmri/infrastructure/cli.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
@staticmethod
def parse_dti_metrics(metrics_input: Optional[List[str]]) -> List[DTIMetric]:
    """Parse DTI metrics input and return a typed list.

    Parameters
    ----------
    metrics_input: Optional[List[str]]
        Raw input from CLI for DTI metrics

    Returns
    -------
    List[DTIMetric]
        Parsed DTI metrics

    Raises
    ------
    ValueError
        If invalid metrics are provided
    """
    if not metrics_input:
        return []

    try:
        acronyms_list = metrics_input[0].split(',')
        return [DTIMetric.from_acronym(acronym) for acronym in acronyms_list]
    except KeyError:
        valid_options = ', '.join([m.name for m in DTIMetric])
        raise ValueError(f"Invalid DTI metrics. Valid options are: {valid_options}")

parse_statistics_strategies(strategies_input) staticmethod

Parse statistics strategies input and return a typed list.

Parameters:

Name Type Description Default
strategies_input Optional[List[str]]

Raw input from CLI for statistics strategies

required

Returns:

Type Description
List[StatisticStrategy]

List of statistics strategies

Raises:

Type Description
ValueError

If invalid strategies are provided

Source code in oxytcmri/infrastructure/cli.py
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
@staticmethod
def parse_statistics_strategies(strategies_input: Optional[List[str]]) -> List[StatisticStrategy]:
    """Parse statistics strategies input and return a typed list.

    Parameters
    ----------
    strategies_input: Optional[List[str]]
        Raw input from CLI for statistics strategies

    Returns
    -------
    List[StatisticStrategy]
        List of statistics strategies

    Raises
    ------
    ValueError
        If invalid strategies are provided
    """
    if not strategies_input:
        return list(StatisticsStrategies.all())

    try:
        stats_names_list = strategies_input[0].split(',')
        # Replace underscores with spaces in statistical strategy names
        stats_names_list_without_underscores = [name.replace('_', ' ') for name in stats_names_list]
        return [StatisticsStrategies.get_by_name(stat_name)
                for stat_name in stats_names_list_without_underscores]
    except ValueError:
        valid_strategies = [s.name.replace(' ', '_') for s in StatisticsStrategies.all()]
        raise ValueError(f"Invalid statistical strategies. Valid options are: {', '.join(valid_strategies)}")

parse_mri_exam_id(mri_exam_id) classmethod

Parse MRI exam ID input.

Parameters:

Name Type Description Default
mri_exam_id Optional[str]

Raw input from CLI for MRI exam ID

required

Returns:

Type Description
Optional[str]

Parsed MRI exam ID

Source code in oxytcmri/infrastructure/cli.py
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
@classmethod
def parse_mri_exam_id(cls, mri_exam_id: Optional[str]) -> Optional[MRIExamId]:
    """Parse MRI exam ID input.

    Parameters
    ----------
    mri_exam_id: Optional[str]
        Raw input from CLI for MRI exam ID

    Returns
    -------
    Optional[str]
        Parsed MRI exam ID
    """
    if not mri_exam_id:
        return None
    return MRIExamId(mri_exam_id)

ControllerFactory

Factory for creating controllers with appropriate configurations.

Methods:

Name Description
create_dti_controller

Create and configure a controller for DTI operations.

create_dti_controller(settings, database_gateway) staticmethod

Create and configure a controller for DTI operations.

Source code in oxytcmri/infrastructure/cli.py
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
@staticmethod
def create_dti_controller(settings: Settings,
                          database_gateway: DataBaseGateway) -> Controller:
    """Create and configure a controller for DTI operations."""
    importers = []
    if settings.database.overwrite_data:
        importers = ControllerFactory._get_configured_importers(settings)

    return Controller(
        persistence_gateway=database_gateway,
        importers=importers,
        listeners=[
            TqdmProgressListener(),
        ],
        overwrite_database=settings.database.overwrite_data
    )

BaseDTICommand(settings_filepath)

Bases: ABC

Abstract base class defining the common workflow for DTI commands.

Initialize the command with common parameters.

Parameters:

Name Type Description Default
settings_filepath str

Path to settings file

required

Methods:

Name Description
execute

Template method defining the workflow.

Attributes:

Name Type Description
controller
Source code in oxytcmri/infrastructure/cli.py
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
def __init__(self,
             settings_filepath: str):
    """
    Initialize the command with common parameters.

    Parameters
    ----------
    settings_filepath: str
        Path to settings file
    """
    settings = Settings(settings_filepath)
    Logger(settings).setup()

    # Database setup
    database_gateway = DatabaseSetup.create_database_gateway(settings)

    # Controller setup
    self.controller = ControllerFactory.create_dti_controller(settings, database_gateway)

controller = ControllerFactory.create_dti_controller(settings, database_gateway) instance-attribute

execute() abstractmethod

Template method defining the workflow.

Source code in oxytcmri/infrastructure/cli.py
296
297
298
299
300
@abstractmethod
def execute(self) -> None:
    """
    Template method defining the workflow.
    """

ComputeDTINormativeValuesCommand(settings_filepath, dti_metrics=None, statistics_strategies=None)

Bases: BaseDTICommand

Command to compute DTI normative values.

Initialize the command with specific parameters.

Parameters:

Name Type Description Default
settings_filepath str

Path to settings file

required
dti_metrics Optional[List[str]]

List of DTI metrics to compute

None
statistics_strategies Optional[List[str]]

List of statistics strategies to use

None

Methods:

Name Description
execute

Process the compute DTI normative values command.

Attributes:

Name Type Description
dti_metric_list
statistics_strategies
Source code in oxytcmri/infrastructure/cli.py
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
def __init__(self,
             settings_filepath: str,
             dti_metrics: Optional[List[str]] = None,
             statistics_strategies: Optional[List[str]] = None):
    """
    Initialize the command with specific parameters.

    Parameters
    ----------
    settings_filepath: str
        Path to settings file
    dti_metrics: Optional[List[str]]
        List of DTI metrics to compute
    statistics_strategies: Optional[List[str]]
        List of statistics strategies to use
    """
    super().__init__(settings_filepath)
    self.dti_metric_list = CLIArgumentParser.parse_dti_metrics(dti_metrics)
    self.statistics_strategies = CLIArgumentParser.parse_statistics_strategies(statistics_strategies)

dti_metric_list = CLIArgumentParser.parse_dti_metrics(dti_metrics) instance-attribute

statistics_strategies = CLIArgumentParser.parse_statistics_strategies(statistics_strategies) instance-attribute

execute()

Process the compute DTI normative values command.

Source code in oxytcmri/infrastructure/cli.py
326
327
328
329
330
331
332
def execute(self) -> None:
    """Process the compute DTI normative values command.
    """
    self.controller.compute_normative_dti_values(
        dti_metrics=self.dti_metric_list,
        statistics_strategies=self.statistics_strategies
    )

SegmentDTILesionsCommand(settings_filepath, dti_metrics=None, mri_exam_id=None)

Bases: BaseDTICommand

Command to segment DTI lesions.

Initialize the command with specific parameters.

Parameters:

Name Type Description Default
settings_filepath str

Path to settings file

required
dti_metrics Optional[List[str]]

List of DTI metrics to segment

None
mri_exam_id Optional[str]

MRI exam ID to segment lesions

None

Methods:

Name Description
execute

Process the segment DTI lesions command.

Attributes:

Name Type Description
dti_metric_list
mri_exam_id
Source code in oxytcmri/infrastructure/cli.py
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
def __init__(self, settings_filepath: str,
             dti_metrics: Optional[List[str]] = None,
             mri_exam_id: Optional[str] = None):
    """
    Initialize the command with specific parameters.

    Parameters
    ----------
    settings_filepath: str
        Path to settings file
    dti_metrics: Optional[List[str]]
        List of DTI metrics to segment
    mri_exam_id: Optional[str]
        MRI exam ID to segment lesions
    """
    super().__init__(settings_filepath)
    self.dti_metric_list = CLIArgumentParser.parse_dti_metrics(dti_metrics)
    self.mri_exam_id = CLIArgumentParser.parse_mri_exam_id(mri_exam_id)

dti_metric_list = CLIArgumentParser.parse_dti_metrics(dti_metrics) instance-attribute

mri_exam_id = CLIArgumentParser.parse_mri_exam_id(mri_exam_id) instance-attribute

execute()

Process the segment DTI lesions command.

Source code in oxytcmri/infrastructure/cli.py
357
358
359
360
361
362
363
364
def execute(self) -> None:
    """
    Process the segment DTI lesions command.
    """
    self.controller.segment_dti_abnormal_values(
        dti_metrics=self.dti_metric_list,
        mri_exam_id=self.mri_exam_id
    )

ComputeBrainLesionsVolumesCommand(settings_filepath, dti_metrics=None, mri_exam_id=None, regions_of_interest=None)

Bases: BaseDTICommand

Command to compute brain lesions volumes.

Initialize the command with specific parameters.

Parameters:

Name Type Description Default
settings_filepath str

Path to settings file

required
dti_metrics Optional[List[str]]

List of DTI metrics to compute volumes for

None
mri_exam_id Optional[str]

MRI exam ID to compute volumes for

None
regions_of_interest Optional[List[str]]

Regions of interest for volume computation

None

Methods:

Name Description
execute

Process the compute brain lesions volumes command.

Attributes:

Name Type Description
dti_metric_list
mri_exam_id
regions_of_interest
Source code in oxytcmri/infrastructure/cli.py
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
def __init__(self, settings_filepath: str,
             dti_metrics: Optional[List[str]] = None,
             mri_exam_id: Optional[str] = None,
             regions_of_interest: Optional[List[str]] = None):
    """
    Initialize the command with specific parameters.

    Parameters
    ----------
    settings_filepath: str
        Path to settings file
    dti_metrics: Optional[List[str]]
        List of DTI metrics to compute volumes for
    mri_exam_id: Optional[str]
        MRI exam ID to compute volumes for
    regions_of_interest: Optional[List[str]]
        Regions of interest for volume computation
    """
    super().__init__(settings_filepath)
    self.dti_metric_list = CLIArgumentParser.parse_dti_metrics(dti_metrics)
    self.mri_exam_id = CLIArgumentParser.parse_mri_exam_id(mri_exam_id)
    self.regions_of_interest = regions_of_interest or []

dti_metric_list = CLIArgumentParser.parse_dti_metrics(dti_metrics) instance-attribute

mri_exam_id = CLIArgumentParser.parse_mri_exam_id(mri_exam_id) instance-attribute

regions_of_interest = regions_of_interest or [] instance-attribute

execute()

Process the compute brain lesions volumes command.

Source code in oxytcmri/infrastructure/cli.py
393
394
395
396
397
398
399
def execute(self) -> None:
    """Process the compute brain lesions volumes command."""
    self.controller.compute_brain_lesions_volumes(
        dti_metrics=self.dti_metric_list,
        mri_exam_id=self.mri_exam_id,
        regions_of_interest=[]  # TODO: Implement regions of interest parsing and handling
    )

LoadData(settings_filepath)

Bases: BaseDTICommand

Command to load data into the database.

Initialize the command with specific parameters.

Parameters:

Name Type Description Default
settings_filepath str

Path to settings file

required

Methods:

Name Description
execute

Process the load data command.

Source code in oxytcmri/infrastructure/cli.py
405
406
407
408
409
410
411
412
413
414
def __init__(self, settings_filepath: str):
    """
    Initialize the command with specific parameters.

    Parameters
    ----------
    settings_filepath: str
        Path to settings file
    """
    super().__init__(settings_filepath)

execute()

Process the load data command.

Source code in oxytcmri/infrastructure/cli.py
416
417
418
def execute(self) -> None:
    """Process the load data command."""
    getLogger().info("Data loaded successfully.")

load_data(settings_filepath=CLIOptionFactory.settings_option())

Load data into the database from configured importers.

This command initializes the database and imports data from CSV files and NIfTI folders as specified in the settings.

Source code in oxytcmri/infrastructure/cli.py
421
422
423
424
425
426
427
428
429
430
431
@command_line_interface.command()
def load_data(
        settings_filepath: str = CLIOptionFactory.settings_option(),
):
    """Load data into the database from configured importers.

    This command initializes the database and imports data from CSV files
    and NIfTI folders as specified in the settings.
    """
    command = LoadData(settings_filepath=settings_filepath)
    command.execute()

compute_dti_normative_values(settings_filepath=CLIOptionFactory.settings_option(), dti_metrics=CLIOptionFactory.dti_metrics_option(), statistics_strategies=CLIOptionFactory.statistics_strategies_option())

Compute DTI normative values for all centers and store the results in the database.

This command processes DTI data to calculate normative values across centers for specified metrics and statistical strategies.

Source code in oxytcmri/infrastructure/cli.py
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
@command_line_interface.command()
def compute_dti_normative_values(
        settings_filepath: str = CLIOptionFactory.settings_option(),
        dti_metrics: Optional[List[str]] = CLIOptionFactory.dti_metrics_option(),
        statistics_strategies: Optional[List[str]] = CLIOptionFactory.statistics_strategies_option(),
):
    """Compute DTI normative values for all centers and store the results in the database.

    This command processes DTI data to calculate normative values across centers
    for specified metrics and statistical strategies.
    """
    command = ComputeDTINormativeValuesCommand(
        settings_filepath=settings_filepath,
        dti_metrics=dti_metrics,
        statistics_strategies=statistics_strategies
    )
    command.execute()

segment_dti_lesions(settings_filepath=CLIOptionFactory.settings_option(), dti_metrics=CLIOptionFactory.dti_metrics_option(), mri_exam_id=CLIOptionFactory.mri_exam_id_option())

Segment DTI lesions based on normative values.

This command uses previously computed normative values to identify and segment abnormal regions in DTI data.

Source code in oxytcmri/infrastructure/cli.py
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
@command_line_interface.command()
def segment_dti_lesions(
        settings_filepath: str = CLIOptionFactory.settings_option(),
        dti_metrics: Optional[List[str]] = CLIOptionFactory.dti_metrics_option(),
        mri_exam_id: Optional[str] = CLIOptionFactory.mri_exam_id_option(),
):
    """Segment DTI lesions based on normative values.

    This command uses previously computed normative values to identify
    and segment abnormal regions in DTI data.
    """
    command = SegmentDTILesionsCommand(
        settings_filepath=settings_filepath,
        dti_metrics=dti_metrics,
        mri_exam_id=mri_exam_id
    )
    command.execute()

compute_brain_lesions_volumes(settings_filepath=CLIOptionFactory.settings_option(), dti_metrics=CLIOptionFactory.dti_metrics_option(), mri_exam_id=CLIOptionFactory.mri_exam_id_option(), regions_of_interest=CLIOptionFactory.regions_of_interest_option())

Compute brain lesions volumes for specified DTI metrics and MRI exam.

This command calculates the volumes of brain lesions based on DTI metrics and specified regions of interest.

Source code in oxytcmri/infrastructure/cli.py
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
@command_line_interface.command()
def compute_brain_lesions_volumes(
        settings_filepath: str = CLIOptionFactory.settings_option(),
        dti_metrics: Optional[List[str]] = CLIOptionFactory.dti_metrics_option(),
        mri_exam_id: Optional[str] = CLIOptionFactory.mri_exam_id_option(),
        regions_of_interest: Optional[List[str]] = CLIOptionFactory.regions_of_interest_option(),
):
    """Compute brain lesions volumes for specified DTI metrics and MRI exam.

    This command calculates the volumes of brain lesions based on DTI metrics
    and specified regions of interest.
    """
    command = ComputeBrainLesionsVolumesCommand(
        settings_filepath=settings_filepath,
        dti_metrics=dti_metrics,
        mri_exam_id=mri_exam_id,
        regions_of_interest=regions_of_interest
    )
    command.execute()