Skip to content

Commit 85b73c6

Browse files
committed
Restructured code to clean up imports.
1 parent c04c687 commit 85b73c6

23 files changed

+746
-744
lines changed

spectral/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
from __future__ import division, print_function, unicode_literals
3333

34-
__version__ = '0.20'
34+
__version__ = '0.21-dev'
3535

3636
import sys
3737
if sys.byteorder == 'little':
@@ -43,12 +43,12 @@
4343
BIL = 1
4444
BIP = 2
4545

46-
class SpyException(Exception):
47-
'''Base class for spectral module-specific exceptions.'''
48-
pass
46+
from .utilities.errors import SpyException
47+
from .config import SpySettings, spy_colors
48+
settings = SpySettings()
4949

5050
from .spectral import (open_image, load_training_sets, save_training_sets,
51-
settings, tile_image, spy_colors, BandInfo)
51+
BandInfo)
5252
from .io import *
5353
from .algorithms import *
5454
from .graphics import *

spectral/algorithms/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
# Thomas Boggs, [email protected]
3030
#
3131

32-
from __future__ import division, print_function, unicode_literals
32+
from __future__ import absolute_import, division, print_function, unicode_literals
3333

3434
from .algorithms import (mean_cov, covariance, principal_components, bdist,
3535
linear_discriminant, create_training_classes, ndvi,

spectral/algorithms/algorithms.py

Lines changed: 33 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,18 @@
3232
'''
3333
Various functions and algorithms for processing spectral data.
3434
'''
35-
from __future__ import division, print_function, unicode_literals
35+
from __future__ import absolute_import, division, print_function, unicode_literals
3636

37-
import numpy
37+
import math
38+
from numbers import Integral
3839
import numpy as np
40+
import pickle
3941

40-
from warnings import warn
41-
42+
import spectral as spy
43+
from ..io.spyfile import SpyFile, TransformedImage
44+
from ..utilities.errors import has_nan, NaNValueError
45+
from .spymath import matrix_sqrt
46+
from .transforms import LinearTransform
4247

4348
class Iterator:
4449
'''
@@ -233,11 +238,7 @@ def mean_cov(image, mask=None, index=None):
233238
Calculate the mean and covariance of of the given vectors. The argument
234239
can be an Iterator, a SpyFile object, or an `MxNxB` array.
235240
'''
236-
import spectral
237-
import numpy as np
238-
from numpy import zeros, transpose, dot, newaxis
239-
240-
status = spectral._status
241+
status = spy._status
241242

242243
if isinstance(image, np.ndarray):
243244
X = image.astype(np.float64)
@@ -262,8 +263,8 @@ def mean_cov(image, mask=None, index=None):
262263
nSamples = it.get_num_elements()
263264
B = it.get_num_bands()
264265

265-
sumX = zeros((B,), 'd')
266-
sumX2 = zeros((B, B), 'd')
266+
sumX = np.zeros((B,), 'd')
267+
sumX2 = np.zeros((B, B), 'd')
267268
count = 0
268269

269270
statusInterval = max(1, nSamples / 100)
@@ -273,10 +274,10 @@ def mean_cov(image, mask=None, index=None):
273274
status.update_percentage(float(count) / nSamples * 100.)
274275
count += 1
275276
sumX += x
276-
x = x.astype(np.float64)[:, newaxis]
277+
x = x.astype(np.float64)[:, np.newaxis]
277278
sumX2 += x.dot(x.T)
278279
mean = (sumX / count)
279-
sumX = sumX[:, newaxis]
280+
sumX = sumX[:, np.newaxis]
280281
cov = (sumX2 - sumX.dot(sumX.T) / count) / (count - 1)
281282
status.end_percentage()
282283
return (mean, cov, count)
@@ -400,7 +401,6 @@ class PrincipalComponents:
400401
A callable function that returns a function for denoising data.
401402
'''
402403
def __init__(self, vals, vecs, stats):
403-
from .transforms import LinearTransform
404404
self.eigenvalues = vals
405405
self.eigenvectors = vecs
406406
self.stats = stats
@@ -434,9 +434,7 @@ def reduce(self, N=0, **kwargs):
434434
will be retained (starting from greatest to smallest) until
435435
`fraction` of total image variance is retained.
436436
'''
437-
import spectral
438-
439-
status = spectral._status
437+
status = spy._status
440438

441439
num = kwargs.get('num', None)
442440
eigs = kwargs.get('eigs', None)
@@ -453,7 +451,7 @@ def reduce(self, N=0, **kwargs):
453451
if not 0 < fraction <= 1:
454452
raise Exception('fraction must be in range (0,1].')
455453
N = len(self.eigenvalues)
456-
cumsum = numpy.cumsum(self.eigenvalues)
454+
cumsum = np.cumsum(self.eigenvalues)
457455
sum = cumsum[-1]
458456
# Count how many values to retain.
459457
for i in range(N):
@@ -532,7 +530,6 @@ def get_denoising_transform(self, **kwargs):
532530
Returns a callable :class:`~spectral.algorithms.transforms.LinearTransform`
533531
object for denoising image data.
534532
'''
535-
from .transforms import LinearTransform
536533
V = self.reduce(self, **kwargs).eigenvectors
537534
f = LinearTransform(V.dot(V.T), pre=-self.mean,
538535
post=self.mean)
@@ -586,14 +583,12 @@ def principal_components(image):
586583
587584
A callable function that returns a function for denoising data.
588585
'''
589-
from numpy import sqrt, sum
590-
591586
if isinstance(image, GaussianStats):
592587
stats = image
593588
else:
594589
stats = calc_stats(image)
595590

596-
(L, V) = numpy.linalg.eig(stats.cov)
591+
(L, V) = np.linalg.eig(stats.cov)
597592

598593
# numpy says eigenvalues may not be sorted so we'll sort them, if needed.
599594
if not np.alltrue(np.diff(L) <= 0):
@@ -635,7 +630,6 @@ class FisherLinearDiscriminant:
635630
linear discriminant.
636631
'''
637632
def __init__(self, vals, vecs, mean, cov_b, cov_w):
638-
from .transforms import LinearTransform
639633
self.eigenvalues = vals
640634
self.eigenvectors = vecs
641635
self.mean = mean
@@ -673,8 +667,6 @@ class covariances, mean vector, and a callable transform to convert data to
673667
Richards, J.A. & Jia, X. Remote Sensing Digital Image Analysis: An
674668
Introduction. (Springer: Berlin, 1999).
675669
'''
676-
import math
677-
678670
C = len(classes) # Number of training sets
679671
rank = len(classes) - 1
680672

@@ -716,7 +708,7 @@ class covariances, mean vector, and a callable transform to convert data to
716708

717709

718710
def log_det(x):
719-
return sum(numpy.log([eigv for eigv in numpy.linalg.eigvals(x)
711+
return sum(np.log([eigv for eigv in np.linalg.eigvals(x)
720712
if eigv > 0]))
721713

722714

@@ -796,7 +788,6 @@ def sqrt_cov(self):
796788
such that S.dot(S) == C.
797789
'''
798790
if self._sqrt_cov is None:
799-
from spectral.algorithms.spymath import matrix_sqrt
800791
pcs = self.principal_components
801792
self._sqrt_cov = matrix_sqrt(eigs=(pcs.eigenvalues,
802793
pcs.eigenvectors),
@@ -810,7 +801,6 @@ def sqrt_inv_cov(self):
810801
such that S.dot(S) == inv(C).
811802
'''
812803
if self._sqrt_inv_cov is None:
813-
from spectral.algorithms.spymath import matrix_sqrt
814804
pcs = self.principal_components
815805
self._sqrt_inv_cov = matrix_sqrt(eigs=(pcs.eigenvalues,
816806
pcs.eigenvectors),
@@ -834,7 +824,6 @@ def log_det_cov(self):
834824

835825
def transform(self, xform):
836826
'''Returns a version of the stats transformed by a linear transform.'''
837-
from spectral.algorithms.transforms import LinearTransform
838827
if not isinstance(xform, LinearTransform):
839828
raise TypeError('Expected a LinearTransform object.')
840829
m = xform(self.mean)
@@ -843,8 +832,6 @@ def transform(self, xform):
843832

844833
def get_whitening_transform(self):
845834
'''Returns transform that centers and whitens data for these stats.'''
846-
from spectral.algorithms.transforms import LinearTransform
847-
from spectral.algorithms.spymath import matrix_sqrt
848835
C_1 = np.linalg.inv(self.cov)
849836
return LinearTransform(matrix_sqrt(C_1, True), pre=-self.mean)
850837

@@ -887,7 +874,6 @@ def calc_stats(image, mask=None, index=None, allow_nan=False):
887874
888875
This object will have members `mean`, `cov`, and `nsamples`.
889876
'''
890-
from spectral.algorithms.spymath import has_nan, NaNValueError
891877
(mean, cov, N) = mean_cov(image, mask, index)
892878
if has_nan(mean) and not allow_nan:
893879
raise NaNValueError('NaN values present in data.')
@@ -1003,12 +989,6 @@ def transform(self, transform):
1003989
1004990
After `transform` is applied, the class statistics will have `C` bands.
1005991
'''
1006-
1007-
from .transforms import LinearTransform
1008-
from numpy.linalg import det, inv
1009-
import math
1010-
from spectral.io.spyfile import TransformedImage
1011-
1012992
if isinstance(transform, np.ndarray):
1013993
transform = LinearTransform(transform)
1014994
self.stats.mean = transform(self.stats.mean)
@@ -1090,7 +1070,6 @@ def calc_stats(self):
10901070
self.nbands = list(self.classes.values())[0].nbands
10911071

10921072
def save(self, filename, calc_stats=False):
1093-
import pickle
10941073
for c in list(self.classes.values()):
10951074
if c.stats is None:
10961075
if calc_stats == False:
@@ -1116,7 +1095,6 @@ def save(self, filename, calc_stats=False):
11161095
f.close()
11171096

11181097
def load(self, filename, image):
1119-
import pickle
11201098
f = open(filename, 'rb')
11211099
mask = pickle.load(f)
11221100
nclasses = pickle.load(f)
@@ -1255,14 +1233,10 @@ def bdist_terms(a, b):
12551233
RETURN VALUE:
12561234
A 2-tuple of the linear and quadratic terms
12571235
'''
1258-
from math import exp
1259-
from numpy import dot, transpose
1260-
from numpy.linalg import inv
1261-
12621236
m = a.stats.mean - b.stats.mean
12631237
avgCov = (a.stats.cov + b.stats.cov) / 2
12641238

1265-
lin_term = (1 / 8.) * dot(transpose(m), dot(inv(avgCov), m))
1239+
lin_term = (1 / 8.) * np.dot(np.transpose(m), np.dot(np.inv(avgCov), m))
12661240

12671241
quad_term = 0.5 * (log_det(avgCov)
12681242
- 0.5 * a.stats.log_det_cov
@@ -1293,18 +1267,15 @@ def transform_image(matrix, image):
12931267
:class:`spectral.TransformedImage` object and no transformation of data
12941268
will occur until elements of the object are accessed.
12951269
'''
1296-
from spectral.io.spyfile import TransformedImage
1297-
from spectral.io.spyfile import SpyFile
1298-
12991270
if isinstance(image, SpyFile):
13001271
return TransformedImage(matrix, image)
13011272
elif isinstance(image, np.ndarray):
13021273
(M, N, B) = image.shape
1303-
ximage = numpy.zeros((M, N, matrix.shape[0]), float)
1274+
ximage = np.zeros((M, N, matrix.shape[0]), float)
13041275

13051276
for i in range(M):
13061277
for j in range(N):
1307-
ximage[i, j] = numpy.dot(matrix, image[i, j].astype(float))
1278+
ximage[i, j] = np.dot(matrix, image[i, j].astype(float))
13081279
return ximage
13091280
else:
13101281
raise 'Unrecognized image type passed to transform_image.'
@@ -1331,25 +1302,22 @@ def orthogonalize(vecs, start=0):
13311302
A new `CxB` containing an orthonormal basis for the given vectors.
13321303
'''
13331304

1334-
from numpy import transpose, dot, identity
1335-
from numpy.linalg import inv
1336-
from math import sqrt
1337-
13381305
(M, N) = vecs.shape
1339-
basis = numpy.array(transpose(vecs))
1306+
basis = np.array(np.transpose(vecs))
13401307
eye = identity(N).astype(float)
13411308
if start == 0:
1342-
basis[:, 0] /= sqrt(dot(basis[:, 0], basis[:, 0]))
1309+
basis[:, 0] /= math.sqrt(np.dot(basis[:, 0], basis[:, 0]))
13431310
start = 1
13441311

13451312
for i in range(start, M):
1346-
v = basis[:, i] / sqrt(dot(basis[:, i], basis[:, i]))
1313+
v = basis[:, i] / math.sqrt(np.dot(basis[:, i], basis[:, i]))
13471314
U = basis[:, :i]
1348-
P = eye - dot(U, dot(inv(dot(transpose(U), U)), transpose(U)))
1349-
basis[:, i] = dot(P, v)
1350-
basis[:, i] /= sqrt(dot(basis[:, i], basis[:, i]))
1315+
P = eye - np.dot(U, np.dot(np.inv(np.dot(np.transpose(U), U)),
1316+
np.transpose(U)))
1317+
basis[:, i] = np.dot(P, v)
1318+
basis[:, i] /= math.sqrt(np.dot(basis[:, i], basis[:, i]))
13511319

1352-
return transpose(basis)
1320+
return np.transpose(basis)
13531321

13541322

13551323
def unmix(data, members):
@@ -1373,23 +1341,19 @@ def unmix(data, members):
13731341
Note that depending on endmembers given, fractional abundances for
13741342
endmembers may be negative.
13751343
'''
1376-
1377-
from numpy import transpose, dot, zeros
1378-
from numpy.linalg import inv
1379-
13801344
assert members.shape[1] == data.shape[2], \
13811345
'Matrix dimensions are not aligned.'
13821346

13831347
members = members.astype(float)
13841348
# Calculate the pseudo inverse
1385-
pi = dot(members, transpose(members))
1386-
pi = dot(inv(pi), members)
1349+
pi = np.dot(members, np.transpose(members))
1350+
pi = np.dot(np.inv(pi), members)
13871351

13881352
(M, N, B) = data.shape
1389-
unmixed = zeros((M, N, members.shape[0]), float)
1353+
unmixed = np.zeros((M, N, members.shape[0]), float)
13901354
for i in range(M):
13911355
for j in range(N):
1392-
unmixed[i, j] = dot(pi, data[i, j].astype(float))
1356+
unmixed[i, j] = np.dot(pi, data[i, j].astype(float))
13931357
return unmixed
13941358

13951359

@@ -1462,8 +1426,6 @@ def msam(data, members):
14621426
# The modifications to the `spectral_angles` function were contributed by
14631427
# Christian Mielke.
14641428

1465-
import math
1466-
14671429
assert members.shape[1] == data.shape[2], \
14681430
'Matrix dimensions are not aligned.'
14691431

@@ -1623,7 +1585,6 @@ def get_denoising_transform(self, **kwargs):
16231585
Returns a callable :class:`~spectral.algorithms.transforms.LinearTransform`
16241586
object for denoising image data.
16251587
'''
1626-
from spectral.algorithms.transforms import LinearTransform
16271588
N = self._num_from_kwargs(**kwargs)
16281589
V = self.napc.eigenvectors
16291590
Vr = np.array(V)
@@ -1681,7 +1642,6 @@ def get_reduction_transform(self, **kwargs):
16811642
Returns a callable :class:`~spectral.algorithms.transforms.LinearTransform`
16821643
object for reducing the dimensionality of image data.
16831644
'''
1684-
from spectral.algorithms.transforms import LinearTransform
16851645
N = self._num_from_kwargs(**kwargs)
16861646
V = self.napc.eigenvectors
16871647
f = LinearTransform(V[:, :N].T.dot(self.noise.sqrt_inv_cov),
@@ -1741,8 +1701,6 @@ def mnf(signal, noise):
17411701
principal components transform." Geoscience and Remote Sensing, IEEE
17421702
Transactions on 28.3 (1990): 295-304.
17431703
'''
1744-
from spectral.algorithms.transforms import LinearTransform
1745-
from spectral.algorithms.algorithms import PrincipalComponents, GaussianStats
17461704
C = noise.sqrt_inv_cov.dot(signal.cov).dot(noise.sqrt_inv_cov)
17471705
(L, V) = np.linalg.eig(C)
17481706
# numpy says eigenvalues may not be sorted so we'll sort them, if needed.
@@ -1825,11 +1783,6 @@ def ppi(X, niters, threshold=0, centered=False, start=None, display=0,
18251783
Partial Unmixing of AVIRIS Data," Pasadena, California, USA, 23 Jan 1995,
18261784
URI: http://hdl.handle.net/2014/33635
18271785
'''
1828-
from numbers import Integral
1829-
import spectral as spy
1830-
from spectral.algorithms.algorithms import calc_stats
1831-
1832-
18331786
if display is not None:
18341787
if not isinstance(display, Integral) or isinstance(display, bool) or \
18351788
display < 0:

0 commit comments

Comments
 (0)