Completed
Pull Request — master (#127)
by Jasper
01:07
created

niprov.log()   F

Complexity

Conditions 12

Size

Total Lines 97

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 12
dl 0
loc 97
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like niprov.log() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/python
2
# -*- coding: UTF-8 -*-
3
from niprov.dependencies import Dependencies
4
from niprov.adding import add
5
import copy
6
7
8
def log(new, transformation, parents, code=None, logtext=None, transient=False,
9
        script=None, provenance=None, opts=None, dependencies=Dependencies()):
10
    """
11
    Register a transformation that creates a new image (or several).
12
13
    This will retrieve the primary parent's provenance. if no provenance is 
14
    availale for the primary parent, calls listener.unknownFile. Otherwise,
15
    some fields are copied from the primary parent, subject to availability. 
16
    For instance, if the parent has no 'subject' field, the new file's 
17
    provenance won't either.
18
19
    Args:
20
        new (str or list): Path(s) to the newly created file(s).
21
        transformation (str): Name of the operation that has been used.
22
        parents (str or list): Path(s) to the file(s) that were used as the 
23
            basis of the transformation. Assumes that the first file in the 
24
            list is the primary parent for which basic provenance is known.
25
        code (str, optional): Code that was used to generate the new file
26
        logtext (str, optional): Any information about the transformation that 
27
            was logged.
28
        script (str, optional): Path to the code file that contains the 
29
            transformation code.
30
        transient (bool, optional): Set this to True to indicate that the file 
31
            is only temporary and future checks should not expect it to be 
32
            physically present. Defaults to False, assuming that the file 
33
            remains.
34
        provenance (dict, optional): Add the key-value pairs in this dictionary 
35
            to the provenance record for the new files.
36
        opts (Configuration): General settings for niprov. 
37
            See :py:mod:`niprov.config`
38
39
    Raises:
40
      IOError: '[Errno 2] File not found' is raised if the new file does not
41
        exist on the filesystem and is not marked as transient.
42
43
    Returns:
44
        BaseFile: New provenance, if multiple files were created, this is 
45
            a list of images, otherwise, it is a single object.
46
    """
47
    repository = dependencies.getRepository()
48
    listener = dependencies.getListener()
49
    factory = dependencies.getFileFactory()
50
    filesys = dependencies.getFilesystem()
51
    opts = dependencies.reconfigureOrGetConfiguration(opts)
52
    location = dependencies.getLocationFactory()
53
54
    if isinstance(new, basestring):
55
        new = [new]
56
    if isinstance(parents, basestring):
57
        parents = [parents]
58
    if provenance is None:
59
        provenance = {}
60
61
    #gather provenance common to all new files
62
    inheritableFields = [
63
    'acquired',
64
    'subject',
65
    'protocol',
66
    'technique',
67
    'repetition-time',
68
    'epi-factor',
69
    'magnetization-transfer-contrast',
70
    'diffusion',
71
    'echo-time',
72
    'flip-angle',
73
    'inversion-time',
74
    'duration',
75
    'subject-position',
76
    'water-fat-shift',
77
    ]
78
    commonProvenance = provenance
79
    commonProvenance['parents'] = [location.completeString(p) for p in parents]
80
    commonProvenance['transformation'] = transformation
81
    commonProvenance['script'] = script
82
    if code:
83
        commonProvenance['code'] = code
84
    if logtext:
85
        commonProvenance['logtext'] = logtext
86
    if not repository.knowsByLocation(commonProvenance['parents'][0]):
87
        add(parents[0])
88
        listener.addUnknownParent(parents[0])
89
    parentProvenance = repository.byLocation(
90
        commonProvenance['parents'][0]).provenance
91
    for field in inheritableFields:
92
        if field in parentProvenance:
93
            commonProvenance[field] = parentProvenance[field]
94
95
    # do things specific to each new file
96
    newImages = []
97
    for newfile in new:
98
        singleProvenance = copy.deepcopy(commonProvenance)
99
        image = add(newfile, transient=transient, provenance=singleProvenance, 
100
            dependencies=dependencies)
101
        newImages.append(image)
102
103
    # only return one image if only one file was created
104
    if len(new) == 1:
105
        return image
106
107
    return newImages
108
109