Battery runner classes and Report classes
These classes / objects are for generic checking / fixing batteries
The BatteryRunner class will run a series of checks on a single object.
A check is a callable, of signature func(obj, fix=False) which returns a tuple (obj, Report) for func(obj, False) or func(obj, True), where the obj may be a modified object, or a different object, if fix==True.
To run checks only, and return problem report objects:
>>> def chk(obj, fix=False): # minimal check
... return obj, Report()
>>> btrun = BatteryRunner((chk,))
>>> reports = btrun.check_only('a string')
To run checks and fixes, returning fixed object and problem report sequence, with possible fix messages:
>>> fixed_obj, report_seq = btrun.check_fix('a string')
Reports are iterable things, where the elements in the iterations are Problems, with attributes error, problem_level, problem_msg, and possibly empty fix_msg. The problem_level is an integer, giving the level of problem, from 0 (no problem) to 50 (very bad problem). The levels follow the log levels from the logging module (e.g 40 equivalent to “error” level, 50 to “critical”). The error can be one of None if no error to suggest, or an Exception class that the user might consider raising for this sitation. The problem_msg and fix_msg are human readable strings that should explain what happened.
Checks are callables returning objects and reports, like chk below, such that:
obj, report = chk(obj, fix=False)
obj, report = chk(obj, fix=True)
For example, for the Analyze header, we need to check the datatype:
def chk_datatype(hdr, fix=True):
rep = Report(hdr, HeaderDataError)
code = int(hdr['datatype'])
try:
dtype = AnalyzeHeader._data_type_codes.dtype[code]
except KeyError:
rep.problem_level = 40
rep.problem_msg = 'data code not recognized'
else:
if dtype.type is np.void:
rep.problem_level = 40
rep.problem_msg = 'data code not supported'
else:
return hdr, rep
if fix:
rep.fix_problem_msg = 'not attempting fix'
return hdr, rep
or the bitpix:
def chk_bitpix(hdr, fix=True):
rep = Report(HeaderDataError)
code = int(hdr['datatype'])
try:
dt = AnalyzeHeader._data_type_codes.dtype[code]
except KeyError:
rep.problem_level = 10
rep.problem_msg = 'no valid datatype to fix bitpix'
return hdr, rep
bitpix = dt.itemsize * 8
if bitpix == hdr['bitpix']:
return hdr, rep
rep.problem_level = 10
rep.problem_msg = 'bitpix does not match datatype')
if fix:
hdr['bitpix'] = bitpix # inplace modification
rep.fix_msg = 'setting bitpix to match datatype'
return hdr, ret
or the pixdims:
def chk_pixdims(hdr, fix=True):
rep = Report(hdr, HeaderDataError)
if not np.any(hdr['pixdim'][1:4] < 0):
return hdr, rep
rep.problem_level = 40
rep.problem_msg = 'pixdim[1,2,3] should be positive'
if fix:
hdr['pixdim'][1:4] = np.abs(hdr['pixdim'][1:4])
rep.fix_msg = 'setting to abs of pixdim values'
return hdr, rep
BatteryRunner(checks) | Class to run set of checks |
Report([error, problem_level, problem_msg, ...]) | Initialize report with values |
Bases: object
Class to run set of checks
Initialize instance from sequence of checks
Parameters: | checks : sequence
|
---|
Examples
>>> def chk(obj, fix=False): # minimal check
... return obj, Report()
>>> btrun = BatteryRunner((chk,))
Initialize instance from sequence of checks
Parameters: | checks : sequence
|
---|
Examples
>>> def chk(obj, fix=False): # minimal check
... return obj, Report()
>>> btrun = BatteryRunner((chk,))
Run checks, with fixes, on obj returning obj, reports
Parameters: | obj : anything
|
---|---|
Returns: | obj : anything
reports : sequence
|
Run checks on obj returning reports
Parameters: | obj : anything
|
---|---|
Returns: | reports : sequence
|
Bases: object
Initialize report with values
Parameters: | error : None or Exception
problem_level : int
problem_msg : string
fix_msg : string
|
---|
Examples
>>> rep = Report()
>>> rep.problem_level
0
>>> rep = Report(TypeError, 10)
>>> rep.problem_level
10
Initialize report with values
Parameters: | error : None or Exception
problem_level : int
problem_msg : string
fix_msg : string
|
---|
Examples
>>> rep = Report()
>>> rep.problem_level
0
>>> rep = Report(TypeError, 10)
>>> rep.problem_level
10
Log problem, raise error if problem >= error_level
Parameters: | logger : log
error_level : int, optional
|
---|
formatted message string, including fix message if present
Write report to stream
Parameters: | stream : file-like
error_level : int, optional
log_level : int, optional
|
---|