Coverage for labnirs2snirf / labnirs2snirf.py: 100%

45 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-28 06:02 +0000

1""" 

2Main entrypoint for LABNIRS to SNIRF conversion when run as a script. 

3""" 

4 

5import logging 

6import sys 

7from pprint import pformat 

8 

9from .args import ArgumentError, Arguments 

10from .error import Labnirs2SnirfError 

11from .labnirs import read_labnirs 

12from .layout import read_layout, update_layout 

13from .log import config_logger 

14from .snirf import write_snirf 

15 

16 

17def main() -> int: 

18 """ 

19 LABNIRS to SNIRF conversion script. 

20 

21 This function coordinates the full conversion workflow when 

22 run as `python -m labnirs2snirf` on the command line: 

23 

24 1. Parse command-line arguments 

25 2. Configure logging based on user preferences 

26 3. Read and parse LABNIRS data file 

27 4. Optionally add probe position information 

28 5. Write output in SNIRF format 

29 

30 Returns 

31 ------- 

32 int 

33 Exit code: 0 for success, 1 for failure. 

34 

35 Notes 

36 ----- 

37 Exception handling is designed with the intention to reduce end-user exposure 

38 to stack traces and technical details. Most exceptions are hidden from end users, 

39 providing only a concise error message. Detailed error information can be 

40 obtained by increasing verbosity with -v flags and/or using --log to write 

41 to a log file. 

42 """ 

43 log = None 

44 args = None 

45 try: 

46 # 1. Read and check arguments 

47 args = Arguments().parse(sys.argv[1:]) 

48 

49 # Since we're not a library, we will configure logging here. 

50 config_logger(file_logging=args.log, verbosity_level=args.verbosity) 

51 log = logging.getLogger(__name__) 

52 log.info("Logger configured") 

53 

54 log.debug("Parsed arguments: %s", pformat(args, indent=2)) 

55 

56 # 2. Read in labNIRS file 

57 log.info("Reading labNIRS data") 

58 data = read_labnirs( 

59 data_file=args.source_file, 

60 keep_category=args.type, 

61 drop_subtype=args.drop, 

62 ) 

63 # raise RuntimeError("Test exception") 

64 

65 # 3. Add probe positions if provided 

66 if args.locations is not None: 

67 log.info("Reading probe layout from file") 

68 layout = read_layout(args.locations) 

69 update_layout(data, layout) 

70 

71 # 4. Export SNIRF data 

72 log.info("Writing SNIRF file") 

73 write_snirf(data, args.target_file) 

74 

75 log.info("Successfully completed conversion") 

76 return 0 

77 

78 # Hide all exceptions from end users as they aren't necessarily developers. 

79 # Provide error message, explain how to enable logging and get more information about the issue. 

80 except ArgumentError as e: 

81 print(f"Argument error: {e}") 

82 return 1 

83 except Labnirs2SnirfError as e: 

84 if log is not None: 

85 log.exception("%s", e) 

86 print( 

87 f"Conversion failed: {e}\n" 

88 "Increase verbosity (-v, -vv, -vvv) for more details. Use --log to log messages to a file.", 

89 ) 

90 return 1 

91 except Exception as e: # pylint: disable=W0718 

92 print( 

93 "Something went wrong. Increase verbosity (-v, -vv, -vvv) for more details. Use --log to log messages to a file.", 

94 ) 

95 if log is not None: 

96 log.exception("Exception received. Error message: %s", e) 

97 else: 

98 print("Logging not configured, dumping exception:") 

99 raise 

100 return 1 

101 

102 

103if __name__ == "__main__": 

104 sys.exit(main())