Skip to content

Commit f1cd308

Browse files
committed
compton-convgen: Misc: Clean up
compton-convgen: Misc: Clean up. The commit brings no change to the functionality of the script. - Partially fix PEP 8 compliance: - Place imports on separate lines. - Replace leading tabs with 4 spaces. - Add docstrings to classes and functions. - Surround top-level function and class definitions with two blank lines. - Remove spaces around keyword arguments. - Move all statements to separate lines. - Break some long lines into several lines. - Remove trailing semicolons after statements. - CGError: Use functionality from the base class Exception to store the description, instead of the custom logic. - CGInternal: Remove, as it is unused. - Hide the internal function gen_invalid() and args_readfactors() by prefixing their names with an underscore. - Move the module-level command-line handling code to two new functions, _main() and _parse_args(), and only execute if running in the main scope.
1 parent 2343e4b commit f1cd308

File tree

1 file changed

+137
-108
lines changed

1 file changed

+137
-108
lines changed

bin/compton-convgen.py

+137-108
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,161 @@
1-
#! /usr/bin/env python3
1+
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33
# vim:fileencoding=utf-8
44

5-
import math, argparse
5+
import math
6+
import argparse
7+
68

79
class CGError(Exception):
8-
def __init__(self, value):
9-
self.value = value
10-
def __str__(self):
11-
return repr(self.value)
10+
'''An error in the convolution kernel generator.'''
11+
def __init__(self, desc):
12+
super().__init__(desc)
13+
14+
15+
class CGBadArg(CGError):
16+
'''An exception indicating an invalid argument has been passed to the
17+
convolution kernel generator.'''
18+
pass
1219

13-
class CGBadArg(CGError): pass
14-
class CGInternal(CGError): pass
1520

1621
def mbuild(width, height):
17-
"""Build a NxN matrix filled with 0."""
18-
result = list()
19-
for i in range(height):
20-
result.append(list())
21-
for j in range(width):
22-
result[i].append(0.0)
23-
return result
22+
"""Build a NxN matrix filled with 0."""
23+
result = list()
24+
for i in range(height):
25+
result.append(list())
26+
for j in range(width):
27+
result[i].append(0.0)
28+
return result
29+
2430

2531
def mdump(matrix):
26-
"""Dump a matrix in natural format."""
27-
for col in matrix:
28-
print("[ ", end = '');
29-
for ele in col:
30-
print(format(ele, "13.6g") + ", ", end = " ")
31-
print("],")
32+
"""Dump a matrix in natural format."""
33+
for col in matrix:
34+
print("[ ", end='')
35+
for ele in col:
36+
print(format(ele, "13.6g") + ", ", end=" ")
37+
print("],")
38+
3239

3340
def mdumpcompton(matrix):
34-
"""Dump a matrix in compton's format."""
35-
width = len(matrix[0])
36-
height = len(matrix)
37-
print("{},{},".format(width, height), end = '')
38-
for i in range(height):
39-
for j in range(width):
40-
if int(height / 2) == i and int(width / 2) == j:
41-
continue;
42-
print(format(matrix[i][j], ".6f"), end = ",")
43-
print()
41+
"""Dump a matrix in compton's format."""
42+
width = len(matrix[0])
43+
height = len(matrix)
44+
print("{},{},".format(width, height), end='')
45+
for i in range(height):
46+
for j in range(width):
47+
if int(height / 2) == i and int(width / 2) == j:
48+
continue
49+
print(format(matrix[i][j], ".6f"), end=",")
50+
print()
51+
4452

4553
def mnormalize(matrix):
46-
"""Scale a matrix according to the value in the center."""
47-
width = len(matrix[0])
48-
height = len(matrix)
49-
factor = 1.0 / matrix[int(height / 2)][int(width / 2)]
50-
if 1.0 == factor: return matrix
51-
for i in range(height):
52-
for j in range(width):
53-
matrix[i][j] *= factor
54-
return matrix
54+
"""Scale a matrix according to the value in the center."""
55+
width = len(matrix[0])
56+
height = len(matrix)
57+
factor = 1.0 / matrix[int(height / 2)][int(width / 2)]
58+
if 1.0 == factor:
59+
return matrix
60+
for i in range(height):
61+
for j in range(width):
62+
matrix[i][j] *= factor
63+
return matrix
64+
5565

5666
def mmirror4(matrix):
57-
"""Do a 4-way mirroring on a matrix from top-left corner."""
58-
width = len(matrix[0])
59-
height = len(matrix)
60-
for i in range(height):
61-
for j in range(width):
62-
x = min(i, height - 1 - i)
63-
y = min(j, width - 1 - j)
64-
matrix[i][j] = matrix[x][y]
65-
return matrix
67+
"""Do a 4-way mirroring on a matrix from top-left corner."""
68+
width = len(matrix[0])
69+
height = len(matrix)
70+
for i in range(height):
71+
for j in range(width):
72+
x = min(i, height - 1 - i)
73+
y = min(j, width - 1 - j)
74+
matrix[i][j] = matrix[x][y]
75+
return matrix
76+
6677

6778
def gen_gaussian(width, height, factors):
68-
"""Build a Gaussian blur kernel."""
79+
"""Build a Gaussian blur kernel."""
80+
81+
if width != height:
82+
raise CGBadArg("Cannot build an uneven Gaussian blur kernel.")
6983

70-
if width != height:
71-
raise CGBadArg("Cannot build an uneven Gaussian blur kernel.")
84+
size = width
85+
sigma = float(factors.get('sigma', 0.84089642))
7286

73-
size = width
74-
sigma = float(factors.get('sigma', 0.84089642))
87+
result = mbuild(size, size)
88+
for i in range(int(size / 2) + 1):
89+
for j in range(int(size / 2) + 1):
90+
diffx = i - int(size / 2)
91+
diffy = j - int(size / 2)
92+
result[i][j] = 1.0 / (2 * math.pi * sigma) \
93+
* pow(math.e, - (diffx * diffx + diffy * diffy) \
94+
/ (2 * sigma * sigma))
95+
mnormalize(result)
96+
mmirror4(result)
7597

76-
result = mbuild(size, size)
77-
for i in range(int(size / 2) + 1):
78-
for j in range(int(size / 2) + 1):
79-
diffx = i - int(size / 2);
80-
diffy = j - int(size / 2);
81-
result[i][j] = 1.0 / (2 * math.pi * sigma) * pow(math.e, - (diffx * diffx + diffy * diffy) / (2 * sigma * sigma))
82-
mnormalize(result)
83-
mmirror4(result)
98+
return result
8499

85-
return result
86100

87101
def gen_box(width, height, factors):
88-
"""Build a box blur kernel."""
89-
result = mbuild(width, height)
90-
for i in range(height):
91-
for j in range(width):
92-
result[i][j] = 1.0
93-
return result
94-
95-
def gen_invalid(width, height, factors):
96-
raise CGBadArg("Unknown kernel type.")
97-
98-
def args_readfactors(lst):
99-
"""Parse the factor arguments."""
100-
factors = dict()
101-
if lst:
102-
for s in lst:
103-
res = s.partition('=')
104-
if not res[0]:
105-
raise CGBadArg("Factor has no key.")
106-
if not res[2]:
107-
raise CGBadArg("Factor has no value.")
108-
factors[res[0]] = float(res[2])
109-
return factors
110-
111-
parser = argparse.ArgumentParser(description='Build a convolution kernel.')
112-
parser.add_argument('type', help='Type of convolution kernel. May be "gaussian" (factor sigma = 0.84089642) or "box".')
113-
parser.add_argument('width', type=int, help='Width of convolution kernel. Must be an odd number.')
114-
parser.add_argument('height', nargs='?', type=int, help='Height of convolution kernel. Must be an odd number. Equals to width if omitted.')
115-
parser.add_argument('-f', '--factor', nargs='+', help='Factors of the convolution kernel, in name=value format.')
116-
parser.add_argument('--dump-compton', action='store_true', help='Dump in compton format.')
117-
args = parser.parse_args()
118-
119-
width = args.width
120-
height = args.height
121-
if not height:
122-
height = width
123-
if not (width > 0 and height > 0):
124-
raise CGBadArg("Invalid width/height.")
125-
factors = args_readfactors(args.factor)
126-
127-
funcs = dict(gaussian = gen_gaussian, box = gen_box)
128-
matrix = (funcs.get(args.type, gen_invalid))(width, height, factors)
129-
if args.dump_compton:
130-
mdumpcompton(matrix)
131-
else:
132-
mdump(matrix)
102+
"""Build a box blur kernel."""
103+
result = mbuild(width, height)
104+
for i in range(height):
105+
for j in range(width):
106+
result[i][j] = 1.0
107+
return result
108+
109+
110+
def _gen_invalid(width, height, factors):
111+
'''Handle a convolution kernel generation request of an unrecognized type.'''
112+
raise CGBadArg("Unknown kernel type.")
113+
114+
115+
def _args_readfactors(lst):
116+
"""Parse the factor arguments."""
117+
factors = dict()
118+
if lst:
119+
for s in lst:
120+
res = s.partition('=')
121+
if not res[0]:
122+
raise CGBadArg("Factor has no key.")
123+
if not res[2]:
124+
raise CGBadArg("Factor has no value.")
125+
factors[res[0]] = float(res[2])
126+
return factors
127+
128+
129+
def _parse_args():
130+
'''Parse the command-line arguments.'''
131+
132+
parser = argparse.ArgumentParser(description='Build a convolution kernel.')
133+
parser.add_argument('type', help='Type of convolution kernel. May be "gaussian" (factor sigma = 0.84089642) or "box".')
134+
parser.add_argument('width', type=int, help='Width of convolution kernel. Must be an odd number.')
135+
parser.add_argument('height', nargs='?', type=int, help='Height of convolution kernel. Must be an odd number. Equals to width if omitted.')
136+
parser.add_argument('-f', '--factor', nargs='+', help='Factors of the convolution kernel, in name=value format.')
137+
parser.add_argument('--dump-compton', action='store_true', help='Dump in compton format.')
138+
return parser.parse_args()
139+
140+
141+
def _main():
142+
args = _parse_args()
143+
144+
width = args.width
145+
height = args.height
146+
if not height:
147+
height = width
148+
if not (width > 0 and height > 0):
149+
raise CGBadArg("Invalid width/height.")
150+
factors = _args_readfactors(args.factor)
151+
152+
funcs = dict(gaussian=gen_gaussian, box=gen_box)
153+
matrix = (funcs.get(args.type, _gen_invalid))(width, height, factors)
154+
if args.dump_compton:
155+
mdumpcompton(matrix)
156+
else:
157+
mdump(matrix)
158+
159+
160+
if __name__ == '__main__':
161+
_main()

0 commit comments

Comments
 (0)