acmc.main

main.py module

This module provides the functionality for the acmc command line interface

  1"""
  2main.py module
  3
  4This module provides the functionality for the acmc command line interface
  5"""
  6
  7import argparse
  8import logging
  9from pathlib import Path
 10
 11import acmc
 12from acmc import trud, omop, phen, parse, logging_config as lc
 13
 14
 15DEFAULT_WORKSPACE_PATH = Path("./workspace")
 16"""Default phenotype workspace path"""
 17
 18
 19def _trud_install(args: argparse.Namespace):
 20    """Handle the `trud install` command."""
 21    trud.install()
 22
 23
 24def _omop_install(args: argparse.Namespace):
 25    """Handle the `omop install` command."""
 26    omop.install(args.omop_zip_file, args.version)
 27
 28
 29def _omop_clear(args: argparse.Namespace):
 30    """Handle the `omop clear` command."""
 31    omop.clear(omop.DB_PATH)
 32
 33
 34def _omop_delete(args: argparse.Namespace):
 35    """Handle the `omop delete` command."""
 36    omop.delete(omop.DB_PATH)
 37
 38
 39def _phen_init(args: argparse.Namespace):
 40    """Handle the `phen init` command."""
 41    phen.init(args.phen_dir, args.remote_url)
 42
 43
 44def _phen_fork(args: argparse.Namespace):
 45    """Handle the `phen fork` command."""
 46    phen.fork(
 47        args.phen_dir,
 48        args.upstream_url,
 49        args.upstream_version,
 50        new_origin_url=args.remote_url,
 51    )
 52
 53
 54def _phen_validate(args: argparse.Namespace):
 55    """Handle the `phen validate` command."""
 56    phen.validate(args.phen_dir)
 57
 58
 59def _phen_map(args: argparse.Namespace):
 60    """Handle the `phen map` command."""
 61    phen.map(
 62        args.phen_dir,
 63        args.target_coding,
 64        args.not_translate,
 65        args.no_metadata,
 66        args.do_reverse_translate,
 67    )
 68
 69
 70def _phen_export(args: argparse.Namespace):
 71    """Handle the `phen copy` command."""
 72    phen.export(args.phen_dir, args.version)
 73
 74
 75def _phen_publish(args: argparse.Namespace):
 76    """Handle the `phen publish` command."""
 77    phen.publish(args.phen_dir, args.msg, args.remote_url, args.increment)
 78
 79
 80def _phen_copy(args: argparse.Namespace):
 81    """Handle the `phen copy` command."""
 82    phen.copy(args.phen_dir, args.target_dir, args.version)
 83
 84
 85def _phen_diff(args: argparse.Namespace):
 86    """Handle the `phen diff` command."""
 87    phen.diff(
 88        args.phen_dir,
 89        args.version,
 90        args.old_phen_dir,
 91        args.old_version,
 92        args.not_check_config,
 93        args.output_changed_concepts,
 94    )
 95
 96
 97def main():
 98    parser = argparse.ArgumentParser(description="ACMC command-line tool")
 99    parser.add_argument("--debug", action="store_true", help="Enable debug mode")
100    parser.add_argument(
101        "--version", action="version", version=f"acmc {acmc.__version__}"
102    )
103
104    # Top-level commands
105    subparsers = parser.add_subparsers(
106        dest="command", required=True, help="Available commands"
107    )
108
109    ### TRUD Command ###
110    trud_parser = subparsers.add_parser("trud", help="TRUD commands")
111    trud_subparsers = trud_parser.add_subparsers(
112        dest="subcommand", required=True, help="TRUD subcommands"
113    )
114
115    # trud install
116    trud_install_parser = trud_subparsers.add_parser(
117        "install", help="Install TRUD components"
118    )
119    trud_install_parser.set_defaults(func=_trud_install)
120
121    ### OMOP Command ###
122    omop_parser = subparsers.add_parser("omop", help="OMOP commands")
123    omop_subparsers = omop_parser.add_subparsers(
124        dest="subcommand", required=True, help="OMOP subcommands"
125    )
126
127    # omop install
128    omop_install_parser = omop_subparsers.add_parser(
129        "install", help="Install OMOP codes within database"
130    )
131    omop_install_parser.add_argument(
132        "-f", "--omop-zip-file", required=True, help="Path to downloaded OMOP zip file"
133    )
134    omop_install_parser.add_argument(
135        "-v", "--version", required=True, help="OMOP vocabularies release version"
136    )
137    omop_install_parser.set_defaults(func=_omop_install)
138
139    # omop clear
140    omop_clear_parser = omop_subparsers.add_parser(
141        "clear", help="Clear OMOP data from database"
142    )
143    omop_clear_parser.set_defaults(func=_omop_clear)
144
145    # omop delete
146    omop_delete_parser = omop_subparsers.add_parser(
147        "delete", help="Delete OMOP database"
148    )
149    omop_delete_parser.set_defaults(func=_omop_delete)
150
151    ### PHEN Command ###
152    phen_parser = subparsers.add_parser("phen", help="Phen commands")
153    phen_subparsers = phen_parser.add_subparsers(
154        dest="subcommand", required=True, help="Phen subcommands"
155    )
156
157    # phen init
158    phen_init_parser = phen_subparsers.add_parser(
159        "init", help="Initiatise phenotype directory"
160    )
161    phen_init_parser.add_argument(
162        "-d",
163        "--phen-dir",
164        type=str,
165        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
166        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
167    )
168    phen_init_parser.add_argument(
169        "-r",
170        "--remote_url",
171        help="(Optional) URL to repository where the phenotype will be published.",
172    )
173    phen_init_parser.set_defaults(func=_phen_init)
174
175    # phen fork
176    phen_fork_parser = phen_subparsers.add_parser(
177        "fork", help="Fork an existing phenotype"
178    )
179    phen_fork_parser.add_argument(
180        "-d",
181        "--phen-dir",
182        type=str,
183        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
184        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
185    )
186    phen_fork_parser.add_argument(
187        "-r",
188        "--remote_url",
189        help="(Optional) URL to repository where the forked phenotype will be published.",
190    )
191    phen_fork_parser.add_argument(
192        "-u",
193        "--upstream-url",
194        required=True,
195        help="(Required) URL to the phenotype repository to fork.",
196    )
197    phen_fork_parser.add_argument(
198        "-v",
199        "--upstream-version",
200        required=True,
201        help="(Required) Phenotype version to fork.",
202    )
203    phen_fork_parser.set_defaults(func=_phen_fork)
204
205    # phen validate
206    phen_validate_parser = phen_subparsers.add_parser(
207        "validate", help="Validate phenotype configuration"
208    )
209    phen_validate_parser.add_argument(
210        "-d",
211        "--phen-dir",
212        type=str,
213        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
214        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
215    )
216    phen_validate_parser.set_defaults(func=_phen_validate)
217
218    # phen map
219    phen_map_parser = phen_subparsers.add_parser("map", help="Process phen mapping")
220    phen_map_parser.add_argument(
221        "-d",
222        "--phen-dir",
223        type=str,
224        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
225        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
226    )
227    phen_map_parser.add_argument(
228        "-t",
229        "--target-coding",
230        choices=parse.SUPPORTED_CODE_TYPES,
231        help=f"Specify the target coding {parse.SUPPORTED_CODE_TYPES}",
232    )
233    phen_map_parser.add_argument(
234        "--not-translate",
235        action="store_true",
236        default=False,
237        help="(Optional) Prevent any phenotype translation using NHS TRUD vocabularies.",
238    )
239    phen_map_parser.add_argument(
240        "--no-metadata",
241        action="store_true",
242        default=False,
243        help="(Optional) Prevent copying of metadata columns to output.",
244    )
245    phen_map_parser.add_argument(
246        "--do-reverse-translate",
247        action="store_true",
248        default=False,
249        help="(Optional) Enable reversing one directional mappings. WARNING goes against NHS TRUD guidelines.",
250    )
251    phen_map_parser.set_defaults(func=_phen_map)
252
253    # phen export
254    phen_export_parser = phen_subparsers.add_parser(
255        "export", help="Export phen to OMOP database"
256    )
257    phen_export_parser.add_argument(
258        "-d",
259        "--phen-dir",
260        type=str,
261        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
262        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
263    )
264    phen_export_parser.add_argument(
265        "-v",
266        "--version",
267        type=str,
268        default="latest",
269        help="Phenotype version to export, defaults to the latest version",
270    )
271    phen_export_parser.set_defaults(func=_phen_export)
272
273    # phen publish
274    phen_publish_parser = phen_subparsers.add_parser(
275        "publish", help="Publish phenotype configuration"
276    )
277    phen_publish_parser.add_argument(
278        "-d",
279        "--phen-dir",
280        type=str,
281        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
282        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
283    )
284    phen_publish_parser.add_argument(
285        "-i",
286        "--increment",
287        type=str,
288        default=phen.DEFAULT_VERSION_INC,
289        choices=phen.SEMANTIC_VERSION_TYPES,
290        help=f"Version increment: {phen.SEMANTIC_VERSION_TYPES}, default is {phen.DEFAULT_VERSION_INC} increment",
291    )
292    phen_publish_parser.add_argument(
293        "-m", "--msg", help="Message to include with the published version"
294    )
295    phen_publish_parser.add_argument(
296        "-r", "--remote_url", help="URL to remote git repository"
297    )
298    phen_publish_parser.set_defaults(func=_phen_publish)
299
300    # phen copy
301    phen_copy_parser = phen_subparsers.add_parser(
302        "copy", help="Publish phenotype configuration"
303    )
304    phen_copy_parser.add_argument(
305        "-d",
306        "--phen-dir",
307        type=str,
308        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
309        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
310    )
311    phen_copy_parser.add_argument(
312        "-td",
313        "--target-dir",
314        type=str,
315        default=str(DEFAULT_WORKSPACE_PATH.resolve()),
316        help="Target directory for the copy",
317    )
318    phen_copy_parser.add_argument(
319        "-v",
320        "--version",
321        type=str,
322        default="latest",
323        help="Phenotype version to copy, defaults to the latest version",
324    )
325    phen_copy_parser.set_defaults(func=_phen_copy)
326
327    # phen diff
328    phen_diff_parser = phen_subparsers.add_parser(
329        "diff", help="Publish phenotype configuration"
330    )
331    phen_diff_parser.add_argument(
332        "-d",
333        "--phen-dir",
334        type=str,
335        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
336        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
337    )
338    phen_diff_parser.add_argument(
339        "-v",
340        "--version",
341        default="latest",
342        help="Phenotype version to compare with an old version, defaults to the HEAD of the workspace directory",
343    )
344    phen_diff_parser.add_argument(
345        "-od",
346        "--old-phen-dir",
347        type=str,
348        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
349        help="Directory for the old phenotype version, defaults to workspace directory",
350    )
351    phen_diff_parser.add_argument(
352        "-ov",
353        "--old-version",
354        required=True,
355        help="Old phenotype version to compare with the changed version",
356    )
357    phen_diff_parser.add_argument(
358        "--not-check-config",
359        action="store_true",
360        default=False,
361        help="(Optional) Prevent loading and comparing config file, in the case where one does not exist",
362    )
363    phen_diff_parser.add_argument(
364        "--output-changed-concepts",
365        action="store_true",
366        default=False,
367        help="(Optional) Output a table of concepts that have been added or removed to csv",
368    )
369    phen_diff_parser.set_defaults(func=_phen_diff)
370
371    # Parse arguments
372    args = parser.parse_args()
373
374    # setup logging
375    if args.debug:
376        lc.set_log_level(logging.DEBUG)
377
378    # Call the function associated with the command
379    args.func(args)
380
381
382if __name__ == "__main__":
383    main()
DEFAULT_WORKSPACE_PATH = PosixPath('workspace')

Default phenotype workspace path

def main():
 98def main():
 99    parser = argparse.ArgumentParser(description="ACMC command-line tool")
100    parser.add_argument("--debug", action="store_true", help="Enable debug mode")
101    parser.add_argument(
102        "--version", action="version", version=f"acmc {acmc.__version__}"
103    )
104
105    # Top-level commands
106    subparsers = parser.add_subparsers(
107        dest="command", required=True, help="Available commands"
108    )
109
110    ### TRUD Command ###
111    trud_parser = subparsers.add_parser("trud", help="TRUD commands")
112    trud_subparsers = trud_parser.add_subparsers(
113        dest="subcommand", required=True, help="TRUD subcommands"
114    )
115
116    # trud install
117    trud_install_parser = trud_subparsers.add_parser(
118        "install", help="Install TRUD components"
119    )
120    trud_install_parser.set_defaults(func=_trud_install)
121
122    ### OMOP Command ###
123    omop_parser = subparsers.add_parser("omop", help="OMOP commands")
124    omop_subparsers = omop_parser.add_subparsers(
125        dest="subcommand", required=True, help="OMOP subcommands"
126    )
127
128    # omop install
129    omop_install_parser = omop_subparsers.add_parser(
130        "install", help="Install OMOP codes within database"
131    )
132    omop_install_parser.add_argument(
133        "-f", "--omop-zip-file", required=True, help="Path to downloaded OMOP zip file"
134    )
135    omop_install_parser.add_argument(
136        "-v", "--version", required=True, help="OMOP vocabularies release version"
137    )
138    omop_install_parser.set_defaults(func=_omop_install)
139
140    # omop clear
141    omop_clear_parser = omop_subparsers.add_parser(
142        "clear", help="Clear OMOP data from database"
143    )
144    omop_clear_parser.set_defaults(func=_omop_clear)
145
146    # omop delete
147    omop_delete_parser = omop_subparsers.add_parser(
148        "delete", help="Delete OMOP database"
149    )
150    omop_delete_parser.set_defaults(func=_omop_delete)
151
152    ### PHEN Command ###
153    phen_parser = subparsers.add_parser("phen", help="Phen commands")
154    phen_subparsers = phen_parser.add_subparsers(
155        dest="subcommand", required=True, help="Phen subcommands"
156    )
157
158    # phen init
159    phen_init_parser = phen_subparsers.add_parser(
160        "init", help="Initiatise phenotype directory"
161    )
162    phen_init_parser.add_argument(
163        "-d",
164        "--phen-dir",
165        type=str,
166        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
167        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
168    )
169    phen_init_parser.add_argument(
170        "-r",
171        "--remote_url",
172        help="(Optional) URL to repository where the phenotype will be published.",
173    )
174    phen_init_parser.set_defaults(func=_phen_init)
175
176    # phen fork
177    phen_fork_parser = phen_subparsers.add_parser(
178        "fork", help="Fork an existing phenotype"
179    )
180    phen_fork_parser.add_argument(
181        "-d",
182        "--phen-dir",
183        type=str,
184        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
185        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
186    )
187    phen_fork_parser.add_argument(
188        "-r",
189        "--remote_url",
190        help="(Optional) URL to repository where the forked phenotype will be published.",
191    )
192    phen_fork_parser.add_argument(
193        "-u",
194        "--upstream-url",
195        required=True,
196        help="(Required) URL to the phenotype repository to fork.",
197    )
198    phen_fork_parser.add_argument(
199        "-v",
200        "--upstream-version",
201        required=True,
202        help="(Required) Phenotype version to fork.",
203    )
204    phen_fork_parser.set_defaults(func=_phen_fork)
205
206    # phen validate
207    phen_validate_parser = phen_subparsers.add_parser(
208        "validate", help="Validate phenotype configuration"
209    )
210    phen_validate_parser.add_argument(
211        "-d",
212        "--phen-dir",
213        type=str,
214        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
215        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
216    )
217    phen_validate_parser.set_defaults(func=_phen_validate)
218
219    # phen map
220    phen_map_parser = phen_subparsers.add_parser("map", help="Process phen mapping")
221    phen_map_parser.add_argument(
222        "-d",
223        "--phen-dir",
224        type=str,
225        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
226        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
227    )
228    phen_map_parser.add_argument(
229        "-t",
230        "--target-coding",
231        choices=parse.SUPPORTED_CODE_TYPES,
232        help=f"Specify the target coding {parse.SUPPORTED_CODE_TYPES}",
233    )
234    phen_map_parser.add_argument(
235        "--not-translate",
236        action="store_true",
237        default=False,
238        help="(Optional) Prevent any phenotype translation using NHS TRUD vocabularies.",
239    )
240    phen_map_parser.add_argument(
241        "--no-metadata",
242        action="store_true",
243        default=False,
244        help="(Optional) Prevent copying of metadata columns to output.",
245    )
246    phen_map_parser.add_argument(
247        "--do-reverse-translate",
248        action="store_true",
249        default=False,
250        help="(Optional) Enable reversing one directional mappings. WARNING goes against NHS TRUD guidelines.",
251    )
252    phen_map_parser.set_defaults(func=_phen_map)
253
254    # phen export
255    phen_export_parser = phen_subparsers.add_parser(
256        "export", help="Export phen to OMOP database"
257    )
258    phen_export_parser.add_argument(
259        "-d",
260        "--phen-dir",
261        type=str,
262        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
263        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
264    )
265    phen_export_parser.add_argument(
266        "-v",
267        "--version",
268        type=str,
269        default="latest",
270        help="Phenotype version to export, defaults to the latest version",
271    )
272    phen_export_parser.set_defaults(func=_phen_export)
273
274    # phen publish
275    phen_publish_parser = phen_subparsers.add_parser(
276        "publish", help="Publish phenotype configuration"
277    )
278    phen_publish_parser.add_argument(
279        "-d",
280        "--phen-dir",
281        type=str,
282        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
283        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
284    )
285    phen_publish_parser.add_argument(
286        "-i",
287        "--increment",
288        type=str,
289        default=phen.DEFAULT_VERSION_INC,
290        choices=phen.SEMANTIC_VERSION_TYPES,
291        help=f"Version increment: {phen.SEMANTIC_VERSION_TYPES}, default is {phen.DEFAULT_VERSION_INC} increment",
292    )
293    phen_publish_parser.add_argument(
294        "-m", "--msg", help="Message to include with the published version"
295    )
296    phen_publish_parser.add_argument(
297        "-r", "--remote_url", help="URL to remote git repository"
298    )
299    phen_publish_parser.set_defaults(func=_phen_publish)
300
301    # phen copy
302    phen_copy_parser = phen_subparsers.add_parser(
303        "copy", help="Publish phenotype configuration"
304    )
305    phen_copy_parser.add_argument(
306        "-d",
307        "--phen-dir",
308        type=str,
309        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
310        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
311    )
312    phen_copy_parser.add_argument(
313        "-td",
314        "--target-dir",
315        type=str,
316        default=str(DEFAULT_WORKSPACE_PATH.resolve()),
317        help="Target directory for the copy",
318    )
319    phen_copy_parser.add_argument(
320        "-v",
321        "--version",
322        type=str,
323        default="latest",
324        help="Phenotype version to copy, defaults to the latest version",
325    )
326    phen_copy_parser.set_defaults(func=_phen_copy)
327
328    # phen diff
329    phen_diff_parser = phen_subparsers.add_parser(
330        "diff", help="Publish phenotype configuration"
331    )
332    phen_diff_parser.add_argument(
333        "-d",
334        "--phen-dir",
335        type=str,
336        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
337        help="(Optional) Local phenotype workspace directory (default is ./workspace/phen).",
338    )
339    phen_diff_parser.add_argument(
340        "-v",
341        "--version",
342        default="latest",
343        help="Phenotype version to compare with an old version, defaults to the HEAD of the workspace directory",
344    )
345    phen_diff_parser.add_argument(
346        "-od",
347        "--old-phen-dir",
348        type=str,
349        default=str(phen.DEFAULT_PHEN_PATH.resolve()),
350        help="Directory for the old phenotype version, defaults to workspace directory",
351    )
352    phen_diff_parser.add_argument(
353        "-ov",
354        "--old-version",
355        required=True,
356        help="Old phenotype version to compare with the changed version",
357    )
358    phen_diff_parser.add_argument(
359        "--not-check-config",
360        action="store_true",
361        default=False,
362        help="(Optional) Prevent loading and comparing config file, in the case where one does not exist",
363    )
364    phen_diff_parser.add_argument(
365        "--output-changed-concepts",
366        action="store_true",
367        default=False,
368        help="(Optional) Output a table of concepts that have been added or removed to csv",
369    )
370    phen_diff_parser.set_defaults(func=_phen_diff)
371
372    # Parse arguments
373    args = parser.parse_args()
374
375    # setup logging
376    if args.debug:
377        lc.set_log_level(logging.DEBUG)
378
379    # Call the function associated with the command
380    args.func(args)