├── inputs ├── A.mat └── BANDS.mat ├── .gitignore ├── README.md ├── pyversion ├── conjugate.py ├── getSynData.py ├── steepdescent.py ├── vca.py ├── mvcnmf.py └── nmf_test.py ├── conjugate.m ├── getSynData.m ├── steepdescent.m ├── mvcnmf.m ├── vca.m ├── nmf_test.m ├── LICENSE └── fix_data.ipynb /inputs/A.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drkostas/MVCNMF/HEAD/inputs/A.mat -------------------------------------------------------------------------------- /inputs/BANDS.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drkostas/MVCNMF/HEAD/inputs/BANDS.mat -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*Landsat* 2 | **/.DS_Store 3 | outputs/* 4 | **/.vscode 5 | inputs/*.csv 6 | *.pyc 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MVCNMF 2 | 3 | The Minimum Volume Constrained Non-negative Matrix Factorization (MVC-NMF) is an unsupervised endmember extraction algorithm. It is designed for highly mixed image data. 4 | 5 | ## Usage 6 | 7 | run "nmf_test.m" 8 | 9 | ## Contributors 10 | 11 | Lidan Miao, Hairong Qi (hqi@utk.edu), EECS, University of Tennessee, Knoxville 12 | 13 | ## Reference 14 | 15 | L. Miao, H. Qi, "Endmember extraction from highly mixed data using minimum volume constrained non-negative matrix factorization," IEEE Transactions on Geoscience and Remote Sensing, 45(3):765-777, March 2007. 16 | 17 | The paper received the Highest Impact Paper Award in 2012 from the IEEE Geoscience and Remote Sensing Society. 18 | -------------------------------------------------------------------------------- /pyversion/conjugate.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def conjugate(X, A, S, maxiter, U, mean_data, tao): 5 | """ 6 | Projected conjugate gradient learning 7 | """ 8 | A = A.astype(np.float64) 9 | 10 | maxiter = 1 11 | AtA = A.T @ A 12 | AtX = A.T @ X 13 | L, _ = X.shape 14 | c, N = S.shape 15 | 16 | cons = 0 17 | if L > N: 18 | cons = 1 19 | mean_data = mean_data.T @ np.ones((1, c)) 20 | C = np.vstack((np.ones((1, c)), np.zeros((c - 1, c)))) 21 | B = np.vstack((np.zeros((1, c - 1)), np.eye(c - 1))) 22 | Z = C + B @ U.T @ (S.T - mean_data) 23 | ZD = np.linalg.pinv(Z) @ B @ U.T 24 | detz2 = (np.linalg.det(Z) ** 2).reshape(-1, 1) 25 | 26 | # initial gradient 27 | if cons == 1: 28 | gradp = AtA @ S - AtX + tao * detz2 * ZD # type: ignore 29 | else: 30 | gradp = AtA @ S - AtX 31 | 32 | # initial conjugate direction 33 | conjp = gradp 34 | S = S - 0.001 * gradp 35 | 36 | for iter in range(maxiter): 37 | if cons == 1: 38 | Z = C + B @ U.T @ (S.T - mean_data) # type: ignore 39 | ZD = np.linalg.pinv(Z) @ B @ U.T # type: ignore 40 | detz2 = np.linalg.det(Z) ** 2 41 | grad = AtA @ S - AtX + tao * detz2 * ZD 42 | else: 43 | grad = AtA @ S - AtX 44 | 45 | # parameter beta 46 | beta = np.sum(grad * (grad - gradp), axis=1) / np.maximum( 47 | np.sum(gradp**2, axis=1), np.finfo(float).eps 48 | ).reshape(1, -1) 49 | 50 | # new conjugate direction 51 | conj = -grad + np.multiply(beta.reshape(-1, 1), conjp) 52 | 53 | AAd = AtA @ conj 54 | alpha = np.sum(conj * (-grad), axis=0, keepdims=True) / np.maximum( 55 | np.sum(conj * AAd, axis=0, keepdims=True), np.finfo(float).eps) 56 | 57 | 58 | 59 | 60 | S = S + (conj * alpha) 61 | 62 | gradp = grad 63 | conjp = conj 64 | 65 | 66 | return S 67 | -------------------------------------------------------------------------------- /pyversion/getSynData.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.signal import convolve2d 3 | from scipy.ndimage import convolve 4 | # from mvcnmf import print_summary 5 | 6 | 7 | def get_syn_data(A, win, pure): 8 | """ 9 | Generate synthetic data. 10 | The spectra of simulated data is obtained from 11 | the USGS library "signatures" 12 | 13 | Input 14 | - A: matrix of reflectances 15 | - win: size of smoothing filter 16 | - pure: 0 - no pure pixels, 1 - exist pure pixel 17 | 18 | Output 19 | - mixed: generated synthetic mixed data 20 | - abf: actual abundance fractions 21 | """ 22 | 23 | band, c = A.shape 24 | dim = 64 25 | 26 | label = np.ones(((dim // 8) ** 2, 1)) 27 | num = int(label.size / c) 28 | 29 | for i in range(c - 1): 30 | label[i * num:(i + 1) * num] = i + 2 31 | 32 | ridx = np.random.permutation(label.size) 33 | label = label[ridx].reshape(dim // 8, dim // 8) 34 | abf = np.zeros((dim, dim, c)) 35 | img = np.zeros((dim, dim)) 36 | 37 | for i in range(dim): 38 | for j in range(dim): 39 | for cls in range(c): 40 | if label[(i - 1) // 8, (j - 1) // 8] == cls + 1: 41 | tmp = np.zeros(c) 42 | tmp[cls] = 1 43 | abf[i, j, :] = tmp 44 | img[i, j] = c 45 | 46 | # low pass filter 47 | H = np.ones((win, win)) / (win * win) 48 | for i in range(c): 49 | abf[:, :, i] = convolve(abf[:, :, i], H) 50 | abf = abf[win // 2: -win // 2 + 1, win // 2: -win // 2 + 1, :] 51 | 52 | # generate mixtures 53 | M, N, c = abf.shape 54 | abf = abf.reshape((M * N, c)).T 55 | 56 | # remove pure pixels 57 | if pure == 0: 58 | rows, cols = np.where(abf > 0.8) 59 | index = np.unique(np.ceil(cols / c).astype(int)) 60 | 61 | for idx in index: 62 | col_indices = np.where(np.ceil(cols / c).astype(int) == idx)[0] 63 | if idx < abf.shape[1]: 64 | abf[rows[col_indices], cols[col_indices]] = (1 / c) * np.ones(len(col_indices)) 65 | 66 | 67 | # print_summary(A, "A-before") 68 | # print_summary(abf, "abf-before") 69 | mixed = (A @ abf).T.reshape(M, N, band) 70 | # print_summary(abf, "mixed-before") 71 | 72 | return mixed, abf 73 | 74 | -------------------------------------------------------------------------------- /conjugate.m: -------------------------------------------------------------------------------- 1 | function S = conjugate(X, A, S, maxiter, U, meanData, tao) 2 | % 3 | % Projected conjugate gradient learning 4 | % 5 | 6 | % initialize 7 | maxiter = 1; 8 | AtA = A' * A; 9 | 10 | AtX = A' * X; 11 | [L, N] = size(X); [c, N] = size(S); 12 | 13 | % the constraint is only included when estimating A 14 | cons = 0; 15 | 16 | if L > N 17 | cons = 1; 18 | meanData = meanData' * ones(1, c); 19 | C = [ones(1, c); zeros(c - 1, c)]; 20 | B = [zeros(1, c - 1); eye(c - 1)]; 21 | Z = C + B * U' * (S' - meanData); 22 | ZD = pinv(Z) * B * U'; 23 | detz2 = (det(Z) ^ 2); 24 | end 25 | 26 | % initial gradient 27 | if cons == 1 28 | gradp = AtA * S - AtX + tao * detz2 * ZD; 29 | else 30 | gradp = AtA * S - AtX; 31 | end 32 | 33 | % initial conjugate direction 34 | conjp = gradp; 35 | S = S - 0.001 * gradp; 36 | 37 | for iter = 1:maxiter 38 | 39 | % new gradient 40 | if cons == 1 41 | Z = C + B * U' * (S' - meanData); 42 | ZD = pinv(Z) * B * U'; 43 | detz2 = det(Z) ^ 2; 44 | grad = AtA * S - AtX + tao * detz2 * ZD; 45 | else 46 | grad = AtA * S - AtX; 47 | end 48 | 49 | % parameter beta 50 | beta = sum(grad .* (grad - gradp), 1) ./ (sum(gradp .^ 2, 1)); 51 | 52 | % new conjugate direction 53 | conj = -grad + ones(c, 1) * beta .* conjp; 54 | 55 | % steplength: line search to find exact minimizer of alpha 56 | AAd = AtA * conj; 57 | alpha = sum(conj .* (-grad), 1) ./ max(sum(conj .* AAd, 1), eps); 58 | 59 | % update 60 | S = S + conj .* repmat(alpha, size(AtA, 2), 1); 61 | 62 | % save the current directions 63 | gradp = grad; 64 | conjp = conj; 65 | % disp("****************") 66 | % print_summary(AtA, "AtA") 67 | % print_summary(A, "A") 68 | % print_summary(S, "S") 69 | % print_summary(grad, "grad") 70 | % disp("****************") 71 | 72 | end 73 | end 74 | 75 | % function print_summary(array, name) 76 | % disp("---------------------------") 77 | % fprintf('Size of %s: ', name); 78 | % disp(size(array)); 79 | % fprintf('Minimum value: %.2f\n', min(array, [], 'all')); 80 | % fprintf('Maximum value: %.2f\n', max(array, [], 'all')); 81 | % fprintf('Mean value: %.2f\n', mean(array, 'all')); 82 | % fprintf('Standard deviation: %.2f\n\n', std(array, 0, 'all')); 83 | % disp("---------------------------") 84 | % end -------------------------------------------------------------------------------- /getSynData.m: -------------------------------------------------------------------------------- 1 | function [mixed, abf] = getSynData(A, win, pure) 2 | % 3 | % Generate synthetic data. 4 | % The spectra of simulated data is obtained from the USGS library "signatures" 5 | % 6 | % Input 7 | % - A: matrix of reflectances 8 | % - win: size of smoothing filter 9 | % - pure: 0 - no pure pixels, 1 - exist pure pixel 10 | % 11 | % Output 12 | % - mixed: generated synthetic mixed data 13 | % - abf: actual abundance fractions 14 | % 15 | % The pure pixels can be removed by adding the following two lines 16 | % ----Index = ceil(find(abf>0.8)/c); 17 | % ----abf(:,Index) = 1/c*ones(c,1)*ones(1,length(Index)); 18 | % 19 | 20 | 21 | [band, c] = size(A); 22 | dim = 64; 23 | 24 | label = ones((dim/8)^2,1); 25 | num = floor(length(label)/c); 26 | 27 | for i=1:c-1 28 | label((i-1)*num+1:i*num) = (i+1); 29 | end 30 | 31 | ridx = randperm(length(label)); 32 | label = label(ridx)'; 33 | label = reshape(label,dim/8,dim/8); 34 | abf = zeros(dim,dim,c); 35 | img = zeros(dim,dim); 36 | for i=1:dim 37 | for j=1:dim 38 | for cls = 1:c 39 | if label(floor((i-1)/8)+1,floor((j-1)/8)+1) == cls 40 | tmp = zeros(c,1); 41 | tmp(cls) = 1; 42 | abf(i,j,:) = tmp; 43 | img(i,j) = c; 44 | end 45 | end 46 | end 47 | end 48 | % print_summary(abf, "abf-1") 49 | 50 | %low pass filter 51 | H = ones(win,win)/(win*win); 52 | % img_fil = filter2(H,img); 53 | for i=1:c 54 | abf(:,:,i) = filter2(H,abf(:,:,i)); 55 | end 56 | 57 | abf = abf(ceil(win/2):end-floor(win/2),ceil(win/2):end-floor(win/2),:); 58 | 59 | % generate mixtures 60 | [M,N,c] = size(abf); 61 | 62 | abf = reshape(abf,M*N,c)'; 63 | 64 | % remove pure pixels 65 | if pure == 0 66 | Index = ceil(find(abf>0.8)/c); 67 | abf(:,Index) = 1/c*ones(c,1)*ones(1,length(Index)); 68 | end 69 | % print_summary(A, "A-before") 70 | % print_summary(abf, "abf-before") 71 | 72 | mixed = reshape((A*abf)',M,N,band); 73 | % print_summary(mixed, "mixed-before") 74 | end 75 | 76 | % function print_summary(array, name) 77 | % disp("---------------------------") 78 | % fprintf('Size of %s: ', name); 79 | % disp(size(array)); 80 | % fprintf('Minimum value: %.2f\n', min(array, [], 'all')); 81 | % fprintf('Maximum value: %.2f\n', max(array, [], 'all')); 82 | % fprintf('Mean value: %.2f\n', mean(array, 'all')); 83 | % fprintf('Standard deviation: %.2f\n\n', std(array, 0, 'all')); 84 | % disp("---------------------------") 85 | % end -------------------------------------------------------------------------------- /steepdescent.m: -------------------------------------------------------------------------------- 1 | function [S, grad, iter] = steepdescent(X, A, S, tol, maxiter, U, meanData, tao) 2 | 3 | % S, grad: output solution and gradient 4 | % iter: #iterations used 5 | % X, A: constant matrices 6 | % tol: stopping tolerance 7 | % maxiter: limit of iterations 8 | % U, meanData: principal components and data mean to calculate the volume 9 | % tao: regularization parameter 10 | 11 | [L, N] = size(X); 12 | [c, N] = size(S); 13 | 14 | % The constraint is only included when estimating A 15 | cons = 0; 16 | 17 | if L > N 18 | cons = 1; 19 | 20 | % precalculation for volume constraint 21 | meanData = meanData' * ones(1, c); 22 | C = [ones(1, c); zeros(c - 1, c)]; 23 | B = [zeros(1, c - 1); eye(c - 1)]; 24 | 25 | end 26 | 27 | % precalculation to reduce computational complexity 28 | AtX = A' * X; 29 | AtA = A' * A; 30 | 31 | alpha = 1; beta = 0.1; sigma = 0.01; 32 | 33 | for iter = 1:maxiter 34 | 35 | % constraint on S^T 36 | if cons == 1 37 | Z = C + B * U' * (S' - meanData); 38 | ZD = pinv(Z) * B * U'; 39 | detz2 = det(Z) ^ 2; 40 | f = sum(sum((X - A * S) .^ 2)) + tao * det(Z) ^ 2; 41 | end 42 | 43 | % gradient with respective to S 44 | if cons == 1 45 | grad = AtA * S - AtX + tao * detz2 * ZD; 46 | else 47 | grad = AtA * S - AtX; 48 | end 49 | 50 | projgrad = norm(grad(grad < 0 | S > 0)); 51 | 52 | if projgrad < tol 53 | break 54 | end 55 | 56 | % search step size 57 | for inner_iter = 1:50 58 | Sn = max(S - alpha * grad, 0); d = Sn - S; 59 | 60 | if cons == 1 61 | fn = sum(sum((X - A * Sn) .^ 2)) + tao * det(C + B * U' * (Sn' - meanData)) ^ 2; 62 | suff_decr = fn - f <= sigma * sum(sum(grad .* d)); 63 | else 64 | gradd = sum(sum(grad .* d)); 65 | 66 | dQd = sum(sum((AtA * d) .* d)); 67 | suff_decr = 0.99 * gradd + 0.5 * dQd < 0; 68 | end 69 | 70 | if inner_iter == 1 % the first iteration determines whether we should increase or decrease alpha 71 | decr_alpha = ~suff_decr; Sp = S; 72 | end 73 | 74 | if decr_alpha 75 | 76 | if suff_decr 77 | S = Sn; break; 78 | else 79 | alpha = alpha * beta; 80 | end 81 | 82 | else 83 | 84 | if ~suff_decr | Sp == Sn 85 | S = Sp; break; 86 | else 87 | alpha = alpha / beta; Sp = Sn; 88 | end 89 | 90 | end 91 | 92 | end 93 | 94 | end 95 | -------------------------------------------------------------------------------- /pyversion/steepdescent.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | 5 | def steep_descent(X, A, S, tol, maxiter, U, mean_data, tao): 6 | """ 7 | S, grad: output solution and gradient 8 | iter: #iterations used 9 | X, A: constant matrices 10 | tol: stopping tolerance 11 | maxiter: limit of iterations 12 | U, mean_data: principal components and data mean to calculate the volume 13 | tao: regularization parameter 14 | """ 15 | grad = None 16 | L, N = X.shape 17 | c, N = S.shape 18 | 19 | # The constraint is only included when estimating A 20 | cons = 0 21 | if L > N: 22 | cons = 1 23 | 24 | # precalculation for volume constraint 25 | mean_data = mean_data.T @ np.ones((1, c)) 26 | C = np.vstack((np.ones((1, c)), np.zeros((c - 1, c)))) 27 | B = np.vstack((np.zeros((1, c - 1)), np.eye(c - 1))) 28 | 29 | # precalculation to reduce computational complexity 30 | AtX = A.T @ X 31 | AtA = A.T @ A 32 | alpha = 1 33 | beta = 0.1 34 | sigma = 0.01 35 | 36 | iter_i = None 37 | for iter_i in range(maxiter): 38 | # constraint on S^T 39 | if cons == 1: 40 | Z = C + B @ U.T @ (S.T - mean_data) # type: ignore 41 | ZD = np.linalg.pinv(Z) @ B @ U.T # type: ignore 42 | detz2 = np.linalg.det(Z) ** 2 43 | f = (np.sum(np.sum((X - A @ S) ** 2)) 44 | + tao * np.linalg.det(Z) ** 2) # type: ignore 45 | 46 | # gradient with respective to S 47 | if cons == 1: 48 | grad = AtA @ S - AtX + tao * detz2 * ZD # type: ignore 49 | else: 50 | grad = AtA @ S - AtX 51 | 52 | projgrad = np.linalg.norm(grad[(grad < 0) | (S > 0)]) 53 | if projgrad < tol: 54 | break 55 | 56 | # search step size 57 | for inner_iter in range(50): 58 | Sn = np.maximum(S - alpha * grad, 0) 59 | d = Sn - S 60 | 61 | if cons == 1: 62 | fn = ( 63 | np.sum(np.sum((X - A @ Sn) ** 2)) 64 | + tao 65 | * np.linalg.det(C + B @ U.T # type: ignore 66 | @ (Sn.T - mean_data)) ** 2 67 | ) 68 | suff_decr = (fn - f <= # type: ignore 69 | sigma * np.sum(np.sum(grad * d))) 70 | else: 71 | gradd = np.sum(np.sum(grad * d)) 72 | dQd = np.sum(np.sum((AtA @ d) * d)) 73 | suff_decr = 0.99 * gradd + 0.5 * dQd < 0 74 | 75 | if inner_iter == 0: 76 | # the first iteration determines whether we should increase 77 | # or decrease alpha 78 | decr_alpha = not suff_decr 79 | Sp = S 80 | else: 81 | decr_alpha = None 82 | 83 | if decr_alpha: 84 | if suff_decr: 85 | S = Sn 86 | break 87 | else: 88 | alpha = alpha * beta 89 | else: 90 | if not suff_decr or np.allclose(Sp, Sn): # type: ignore 91 | S = Sp # type: ignore 92 | break 93 | else: 94 | alpha = alpha / beta 95 | Sp = Sn 96 | if grad is None: 97 | raise ValueError("Gradient is None") 98 | return S, grad, iter_i 99 | -------------------------------------------------------------------------------- /pyversion/vca.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.sparse.linalg import svds 3 | 4 | 5 | def vca(R, p, SNR=None, verbose=True): 6 | """ 7 | Vertex Component Analysis 8 | 9 | Ae, indice, Rp = vca(R, p, SNR=None, verbose=True) 10 | 11 | Parameters 12 | ---------- 13 | R : numpy array, shape (L, N) 14 | Matrix with dimensions L(channels) x N(pixels) 15 | Each pixel is a linear mixture of p endmembers 16 | signatures R = M x s, where s = gamma x alfa 17 | gamma is a illumination perturbation factor and 18 | alfa are the abundance fractions of each endmember. 19 | 20 | p : int 21 | Positive integer number of endmembers in the scene 22 | 23 | SNR : float, optional 24 | Signal to noise ratio (dB) 25 | 26 | verbose : bool, optional 27 | Print progress and additional information 28 | 29 | Returns 30 | ------- 31 | Ae : numpy array 32 | Estimated mixing matrix (endmembers signatures) 33 | 34 | indice : numpy array 35 | Pixels that were chosen to be the most pure 36 | 37 | Rp : numpy array 38 | Data matrix R projected. 39 | """ 40 | 41 | if R.size == 0: 42 | raise ValueError("There is no data") 43 | else: 44 | L, N = R.shape 45 | 46 | if p < 0 or p > L or p != int(p): 47 | raise ValueError( 48 | f"ENDMEMBERS parameter ({p}) must be integer between 1 and {L}" 49 | ) 50 | 51 | if SNR is None: 52 | snr_input = 0 53 | r_m = np.mean(R, axis=1)[:, np.newaxis] 54 | R_m = np.tile(r_m, [1, N]) 55 | R_o = R - R_m 56 | Ud, Sd, Vd = svds(R_o @ R_o.T / N, p) 57 | x_p = Ud.T @ R_o 58 | SNR = estimate_snr(R, r_m, x_p) 59 | if verbose: 60 | print(f"SNR estimated = {SNR:.2f}[dB]") 61 | else: 62 | snr_input = 1 63 | if verbose: 64 | print(f"input SNR = {SNR:.2f}[dB]") 65 | 66 | SNR_th = 15 + 10 * np.log10(p) 67 | 68 | if SNR < SNR_th: 69 | if verbose: 70 | print("... Select the projective projection") 71 | d = p - 1 72 | if snr_input == 0: 73 | Ud = Ud[:, :d] # type: ignore 74 | else: 75 | r_m = np.mean(R, axis=1)[:, np.newaxis] 76 | R_m = np.tile(r_m, [1, N]) 77 | R_o = R - R_m 78 | Ud, Sd, Vd = svds(R_o @ R_o.T / N, d) 79 | x_p = Ud.T @ R_o 80 | Rp = Ud @ x_p[:d, :] + np.tile(r_m, [1, N]) # type: ignore 81 | x = x_p[:d, :] # type: ignore 82 | c = np.max(np.sum(x**2, axis=0)) ** 0.5 83 | y = np.vstack([x, c * np.ones((1, N))]) 84 | else: 85 | if verbose: 86 | print("... Select projection to p-1") 87 | d = p 88 | Ud, Sd, Vd = svds(R @ R.T / N, d) 89 | x_p = Ud.T @ R 90 | Rp = Ud @ x_p[:d, :] 91 | x = Ud.T @ R 92 | u = np.mean(x, axis=1)[:, np.newaxis] 93 | y = x / np.tile(np.sum(x * np.tile(u, [1, N]), axis=0), [d, 1]) 94 | 95 | indice = np.zeros(p, dtype=int) - 1 96 | A = np.zeros((p, p)) 97 | A[-1, 0] = 1 98 | 99 | for i in range(p): 100 | w = np.random.rand(p, 1) 101 | f = w - A @ np.linalg.pinv(A) @ w 102 | f = f / np.sqrt(np.sum(f**2)) 103 | 104 | v = f.T @ y 105 | _, indice[i] = np.max(np.abs(v)), np.argmax(np.abs(v)) - 1 106 | A[:, i] = y[:, indice[i]] 107 | 108 | Ae = Rp[:, indice] 109 | 110 | return Ae, indice 111 | 112 | 113 | def estimate_snr(R, r_m, x): 114 | L, N = R.shape 115 | p, _ = x.shape 116 | 117 | P_y = np.sum(R**2) / N 118 | P_x = np.sum(x**2) / N + r_m.T @ r_m 119 | snr_est = 10 * np.log10((P_x - p / L * P_y) / (P_y - P_x)) 120 | 121 | return snr_est.item() 122 | -------------------------------------------------------------------------------- /mvcnmf.m: -------------------------------------------------------------------------------- 1 | function [A, S, time] = mvcnmf(X, Ainit, Sinit, Atrue, UU, PrinComp, meanData, T, tol, maxiter, showflag, type_alg_S, type_alg_A, use_synthetic_data) 2 | 3 | % A,S: output solution 4 | % Ainit,Sinit: initial solutions 5 | % Atrue: true endmembers 6 | % UU: principle components for visualization (SVD) (optional) 7 | % PrinComp: principal components for calculating volme (PCA) 8 | % meanData: for calculating volume 9 | % T: annealing temprature 10 | % tol: tolerance for a relative stopping condition 11 | % maxiter: limit of iterations 12 | % showflag: display scatter plot (1) 13 | % type_alg_S: algorithms for estimating S 14 | % type_alg_A: algorithms for estimating A 15 | % use_synthetic_data: Whether using synthetic data 16 | 17 | A = Ainit; 18 | S = Sinit; 19 | 20 | % dimensions 21 | c = size(S, 1); % number of endmembers 22 | N = size(S, 2); % number of pixels 23 | 24 | % precalculation for visualization 25 | if use_synthetic_data == 1 26 | EM = UU' * Atrue; % low dimensional endmembers 27 | LowX = UU' * X; % low dimensional data 28 | 29 | E = [ones(1, c); PrinComp(:, 1:c - 1)' * (Atrue - meanData' * ones(1, c))]; 30 | vol_t = 1 / factorial(c - 1) * abs(det(E)); % the volume of true endmembers 31 | end 32 | 33 | % PCA to calculate the volume of true EM 34 | vol = []; 35 | 36 | % calculate volume of estimated A 37 | C = [ones(1, c); zeros(c - 1, c)]; 38 | B = [zeros(1, c - 1); eye(c - 1)]; 39 | Z = C + B * (PrinComp(:, 1:c - 1)' * (A - meanData' * ones(1, c))); 40 | detz2 = det(Z) * det(Z); 41 | 42 | % one time draw 43 | if showflag 44 | startA = UU' * Ainit; 45 | figure(1), 46 | 47 | for i = 1:3 48 | 49 | for j = i + 1:3 50 | subplot(2, 2, (i - 1) * 2 + j - i), 51 | plot(LowX(i, 1:6:end), LowX(j, 1:6:end), 'rx'); 52 | hold on, 53 | plot(startA(i, :), startA(j, :), 'bo'); %original estimateion 54 | plot(EM(i, :), EM(j, :), 'go', 'markerfacecolor', 'g'); %true endmember 55 | end 56 | 57 | end 58 | 59 | end 60 | 61 | % print_summary(detz2, "detz2") 62 | % print_summary(S, "S") 63 | % print_summary(B', "B.T") 64 | % print_summary(pinv(Z)', "np.linalg.pinv(Z).T") 65 | % calculate initial gradient 66 | gradA = A * (S * S') - X * S' + T * detz2 * PrinComp(:, 1:c - 1) * B' * pinv(Z)'; 67 | % print_summary(gradA, "gradA") 68 | gradS = (A' * A) * S - A' * X; 69 | % print_summary(gradS, "gradS") 70 | initgrad = norm([gradA; gradS'], 'fro'); 71 | fprintf('Init gradient norm %f\n', initgrad); 72 | % tolA = max(0.001, tol) * initgrad; 73 | % tolS = tolA; 74 | 75 | % Calculate initial objective 76 | % print_summary(A, "A"); 77 | % print_summary(S, "S"); 78 | % print_summary(X, "X"); 79 | objhistory = 0.5 * sum(sum((X - A * S) .^ 2)); 80 | fprintf("Initial objective: %f\n", objhistory); 81 | objhistory = [objhistory 0]; 82 | Ahistory = []; 83 | 84 | % count the number of sucessive increase of obj 85 | inc = 0; 86 | inc0 = 0; 87 | % flag = 0; 88 | iter = 0; 89 | 90 | while inc < 5 && inc0 < 20 91 | fprintf('--- objhistory: %f\n', objhistory(end)); 92 | 93 | % uphill or downhill 94 | if objhistory( end - 1) - objhistory(end) > 0.0001 95 | inc = 0; 96 | elseif objhistory(end) - objhistory(end - 1) > 50 97 | fprintf('Diverge after %d iterations!', iter); 98 | break; 99 | else 100 | disp('uphill'); 101 | inc = inc + 1; 102 | inc0 = inc0 + 1; 103 | end 104 | 105 | if iter < 5 106 | inc = 0; 107 | end 108 | 109 | if iter == 0 110 | objhistory(end) = objhistory(end - 1); 111 | end 112 | 113 | % stopping condition 114 | % projnorm = norm([gradA(gradA < 0 | A > 0); gradS(gradS < 0 | S > 0)]); 115 | 116 | if iter > maxiter 117 | disp('Max iter reached, stopping!'); 118 | break; 119 | end 120 | 121 | % Show progress 122 | E = [ones(1, c); PrinComp(:, 1:c - 1)' * (A - meanData' * ones(1, c))]; 123 | vol_e = 1 / factorial(c - 1) * abs(det(E)); 124 | fprintf('[%d]: %.5f\t', iter, objhistory(end)); 125 | fprintf('Temperature: %f \t', T); 126 | 127 | if use_synthetic_data == 1 128 | fprintf('Actual Vol.: %f \t Estimated Vol.: %f\n', vol_t, vol_e); 129 | else 130 | fprintf('Estimated Vol.: %f\n', vol_e); 131 | end 132 | 133 | vol(iter + 1) = vol_e; 134 | 135 | % real time draw 136 | if showflag 137 | est = UU' * A; 138 | Ahistory = [Ahistory est]; 139 | figure(1), 140 | 141 | for i = 1:3 142 | 143 | for j = i + 1:3 144 | subplot(2, 2, (i - 1) * 2 + j - i), 145 | plot(est(i, :), est(j, :), 'yo'); %estimation from nmf 146 | end 147 | 148 | end 149 | 150 | drawnow; 151 | end 152 | 153 | % to consider the sum-to-one constraint 154 | tX = [X; 20 * ones(1, N)]; 155 | tA = [A; 20 * ones(1, c)]; 156 | % print_summary(tX, "tX-mvc") 157 | % print_summary(tA, "tA-mvc") 158 | 159 | % find S 160 | switch type_alg_S 161 | 162 | case 1 % conjugate gradient learning 163 | 164 | no_iter = 50; 165 | S = conjugate(X, A, S, no_iter, PrinComp(:, 1:c - 1), meanData, T); 166 | 167 | case 2 % steepest descent 168 | 169 | tolS = 0.0001; 170 | [S, ~, ~] = steepdescent(tX, tA, S, tolS, 200, PrinComp(:, 1:c - 1), meanData, T); 171 | 172 | % if iterS == 1 173 | % tolS = 0.1 * tolS; 174 | % end 175 | 176 | end 177 | 178 | % find A 179 | switch type_alg_A 180 | 181 | case 1 % conjugate gradient learning 182 | 183 | no_iter = 50; 184 | A = conjugate(X', S', A', no_iter, PrinComp(:, 1:c - 1), meanData, T); 185 | A = A'; 186 | 187 | case 2 % steepest descent 188 | 189 | tolA = 0.0001; 190 | [A, ~, ~] = steepdescent(X', S', A', tolA, 100, PrinComp(:, 1:c - 1), meanData, T); 191 | A = A'; 192 | % gradA = gradA'; 193 | 194 | % if iterA == 1 195 | % tolA = 0.1 * tolA; 196 | % end 197 | 198 | end 199 | 200 | % print_summary(A, "A-mvc") 201 | % print_summary(S, "S-mvc") 202 | % Calculate objective 203 | newobj = 0.5 * sum(sum((X - A * S) .^ 2)); 204 | objhistory = [objhistory newobj]; 205 | 206 | iter = iter + 1; 207 | 208 | end 209 | end 210 | 211 | % function print_summary(array, name) 212 | % disp("---------------------------") 213 | % fprintf('Size of %s: ', name); 214 | % disp(size(array)); 215 | % fprintf('Minimum value: %.2f\n', min(array, [], 'all')); 216 | % fprintf('Maximum value: %.2f\n', max(array, [], 'all')); 217 | % fprintf('Mean value: %.2f\n', mean(array, 'all')); 218 | % fprintf('Standard deviation: %.2f\n\n', std(array, 0, 'all')); 219 | % disp("---------------------------") 220 | % end 221 | -------------------------------------------------------------------------------- /vca.m: -------------------------------------------------------------------------------- 1 | function [Ae, indice, Rp] = vca(R,varargin) 2 | 3 | % Vertex Component Analysis 4 | % 5 | % [Ae, indice, Rp ]= vca(R,'Endmembers',p,'SNR',r,'verbose',v) 6 | % 7 | % ------- Input variables ------------- 8 | % R - matrix with dimensions L(channels) x N(pixels) 9 | % each pixel is a linear mixture of p endmembers 10 | % signatures R = M x s, where s = gamma x alfa 11 | % gamma is a illumination perturbation factor and 12 | % alfa are the abundance fractions of each endmember. 13 | % 'Endmembers' 14 | % p - positive integer number of endmembers in the scene 15 | % 16 | % ------- Output variables ----------- 17 | % A - estimated mixing matrix (endmembers signatures) 18 | % indice - pixels that were chosen to be the most pure 19 | % Rp - Data matrix R projected. 20 | % 21 | % ------- Optional parameters--------- 22 | % 'SNR' 23 | % r - (double) signal to noise ratio (dB) 24 | % 'verbose' 25 | % v - [{'on'} | 'off'] 26 | % ------------------------------------ 27 | % 28 | % Authors: Jos� Nascimento (zen@isel.pt) 29 | % Jos� Bioucas Dias (bioucas@lx.it.pt) 30 | % Copyright (c) 31 | % version: 2.1 (7-May-2004) 32 | % 33 | % For any comment contact the authors 34 | % 35 | % more details on: 36 | % Jos� M. P. Nascimento and Jos� M. B. Dias 37 | % "Vertex Component Analysis: A Fast Algorithm to Unmix Hyperspectral Data" 38 | % submited to IEEE Trans. Geosci. Remote Sensing, vol. .., no. .., pp. .-., 2004 39 | % 40 | % 41 | 42 | 43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 44 | % Default parameters 45 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 46 | 47 | verbose = 'on'; % default 48 | snr_input = 0; % default this flag is zero, 49 | % which means we estimate the SNR 50 | 51 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 52 | % Looking for input parameters 53 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 | 55 | dim_in_par = length(varargin); 56 | if (nargin - dim_in_par)~=1 57 | error('Wrong parameters'); 58 | elseif rem(dim_in_par,2) == 1 59 | error('Optional parameters should always go by pairs'); 60 | else 61 | for i = 1 : 2 : (dim_in_par-1) 62 | switch lower(varargin{i}) 63 | case 'verbose' 64 | verbose = varargin{i+1}; 65 | case 'endmembers' 66 | p = varargin{i+1}; 67 | case 'snr' 68 | SNR = varargin{i+1}; 69 | snr_input = 1; % flag meaning that user gives SNR 70 | otherwise 71 | fprintf(1,'Unrecognized parameter:%s\n', varargin{i}); 72 | end %switch 73 | end %for 74 | end %if 75 | 76 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77 | % Initializations 78 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 | 80 | if isempty(R) 81 | error('there is no data'); 82 | else 83 | [L N]=size(R); % L number of bands (channels) 84 | % N number of pixels (LxC) 85 | end 86 | 87 | if (p<0 | p>L | rem(p,1)~=0), 88 | % raise error and show actual values of p and L 89 | error_txt = sprintf('ENDMEMBERS parameter (%d) must be integer between 1 and %d',p,L); 90 | error(error_txt); 91 | end 92 | 93 | 94 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 95 | % SNR Estimates 96 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 97 | 98 | if snr_input==0, 99 | r_m = mean(R,2); 100 | R_m = repmat(r_m,[1 N]); % mean of each band 101 | R_o = R - R_m; % data with zero-mean 102 | [Ud,Sd,Vd] = svds(R_o*R_o'/N,p); % computes the p-projection matrix 103 | x_p = Ud' * R_o; % project the zero-mean data onto p-subspace 104 | 105 | SNR = estimate_snr(R,r_m,x_p); 106 | 107 | if strcmp (verbose, 'on'), fprintf(1,'SNR estimated = %g[dB]\n',SNR); end 108 | else 109 | if strcmp (verbose, 'on'), fprintf(1,'input SNR = %g[dB]\t',SNR); end 110 | end 111 | 112 | SNR_th = 15 + 10*log10(p); 113 | 114 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 115 | % Choosing Projective Projection or 116 | % projection to p-1 subspace 117 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 118 | 119 | if SNR < SNR_th, 120 | if strcmp (verbose, 'on'), fprintf(1,'... Select the projective proj.\n',SNR); end 121 | 122 | d = p-1; 123 | if snr_input==0, % it means that the projection is already computed 124 | Ud= Ud(:,1:d); 125 | else 126 | r_m = mean(R,2); 127 | R_m = repmat(r_m,[1 N]); % mean of each band 128 | R_o = R - R_m; % data with zero-mean 129 | 130 | [Ud,Sd,Vd] = svds(R_o*R_o'/N,d); % computes the p-projection matrix 131 | 132 | x_p = Ud' * R_o; % project thezeros mean data onto p-subspace 133 | 134 | end 135 | 136 | Rp = Ud * x_p(1:d,:) + repmat(r_m,[1 N]); % again in dimension L 137 | 138 | x = x_p(1:d,:); % x_p = Ud' * R_o; is on a p-dim subspace 139 | c = max(sum(x.^2,1))^0.5; 140 | y = [x ; c*ones(1,N)] ; 141 | else 142 | if strcmp (verbose, 'on'), fprintf(1,'... Select proj. to p-1\n',SNR); end 143 | 144 | d = p; 145 | [Ud,Sd,Vd] = svds(R*R'/N,d); % computes the p-projection matrix 146 | 147 | x_p = Ud'*R; 148 | Rp = Ud * x_p(1:d,:); % again in dimension L (note that x_p has no null mean) 149 | 150 | x = Ud' * R; 151 | u = mean(x,2); %equivalent to u = Ud' * r_m 152 | y = x./ repmat( sum( x .* repmat(u,[1 N]) ) ,[d 1]); 153 | 154 | end 155 | 156 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 157 | % VCA algorithm 158 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 159 | 160 | indice = zeros(1,p); 161 | A = zeros(p,p); 162 | A(p,1) = 1; 163 | 164 | for i=1:p 165 | w = rand(p,1); 166 | f = w - A*pinv(A)*w; 167 | f = f / sqrt(sum(f.^2)); 168 | 169 | v = f'*y; 170 | [v_max indice(i)] = max(abs(v)); 171 | A(:,i) = y(:,indice(i)); % same as x(:,indice(i)) 172 | end 173 | Ae = Rp(:,indice); 174 | 175 | return; 176 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 177 | % End of the vca function 178 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 179 | 180 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 181 | % Internal functions 182 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 183 | 184 | function snr_est = estimate_snr(R,r_m,x) 185 | 186 | [L N]=size(R); % L number of bands (channels) 187 | % N number of pixels (Lines x Columns) 188 | [p N]=size(x); % p number of endmembers (reduced dimension) 189 | 190 | P_y = sum(R(:).^2)/N; 191 | P_x = sum(x(:).^2)/N + r_m'*r_m; 192 | snr_est = 10*log10( (P_x - p/L*P_y)/(P_y- P_x) ); 193 | return; 194 | 195 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 196 | -------------------------------------------------------------------------------- /pyversion/mvcnmf.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from math import factorial 4 | from steepdescent import steep_descent as steepdescent 5 | from conjugate import conjugate as conjugate 6 | 7 | 8 | def print_summary(array, name): 9 | print("---------------------------") 10 | print(f"Size of {name}: {array.shape}") 11 | print(f"Minimum value: {np.min(array):.2f}") 12 | print(f"Maximum value: {np.max(array):.2f}") 13 | print(f"Mean value: {np.mean(array):.2f}") 14 | print(f"Standard deviation: {np.std(array):.2f}") 15 | print("---------------------------") 16 | 17 | 18 | def mvcnmf_secord( 19 | X, 20 | Ainit, 21 | Sinit, 22 | Atrue, 23 | UU, 24 | PrinComp, 25 | mean_data, 26 | T, 27 | tol, 28 | maxiter, 29 | showflag, 30 | type_alg_S, 31 | type_alg_A, 32 | use_synthetic_data, 33 | ): 34 | A = Ainit.copy().astype('float64') 35 | S = Sinit.copy().astype('float64') 36 | 37 | # dimensions 38 | c = S.shape[0] # number of endmembers 39 | N = S.shape[1] # number of pixels 40 | 41 | PrinComp = PrinComp.T 42 | # precalculation for visualization 43 | if use_synthetic_data == 1: 44 | EM = UU.T @ Atrue # low dimensional endmembers 45 | LowX = UU.T @ X # low dimensional data 46 | 47 | E = np.vstack((np.ones((1, c)), 48 | PrinComp[:, : c - 1].T @ (Atrue - mean_data.T * np.ones((1, c))))) 49 | vol_t = ( 50 | 1 / factorial(c - 1) * abs(np.linalg.det(E)) 51 | ) # the volume of true endmembers 52 | 53 | # PCA to calculate the volume of true EM 54 | vol = [] 55 | 56 | # calculate volume of estimated A 57 | C = np.vstack((np.ones((1, c)), np.zeros((c - 1, c)))) 58 | B = np.vstack((np.zeros((1, c - 1)), np.eye(c - 1))) 59 | Z = C + B @ ( 60 | PrinComp[:, : c - 1].T 61 | @ (A - mean_data.T * np.ones((1, c))) 62 | ) 63 | detz2 = np.linalg.det(Z) * np.linalg.det(Z) 64 | 65 | # one time draw 66 | if showflag: 67 | startA = UU.T @ Ainit 68 | 69 | fig, axes = plt.subplots(2, 2) 70 | # Flatten the axes array to make it 71 | # easier to index 72 | axes = axes.flatten() # type: ignore 73 | index = 0 74 | for i in range(3): 75 | for j in range(i + 1, 3): 76 | ax = axes[index] 77 | ax.plot(LowX[i, ::6], LowX[j, ::6], "rx") 78 | ax.plot(startA[i, :], startA[j, :], "bo") 79 | ax.plot(EM[i, :], EM[j, :], "go", markerfacecolor="g") 80 | index += 1 81 | 82 | # Remove the unused subplot 83 | axes[-1].set_visible(False) 84 | 85 | # print_summary(detz2, "detz2") 86 | # print_summary(S, "S") 87 | # print_summary(B.T, "B.T") 88 | # print_summary(np.linalg.pinv(Z).T, "np.linalg.pinv(Z).T") 89 | # calculate initial gradient 90 | gradA = ( 91 | A @ (S @ S.T) 92 | - X @ S.T 93 | + T * detz2 * PrinComp[:, : c - 1] @ B.T @ np.linalg.pinv(Z).T 94 | ) 95 | # print_summary(gradA, "gradA") 96 | gradS = (A.T @ A) @ S - A.T @ X 97 | # print_summary(gradS, "gradS") 98 | initgrad = np.linalg.norm(np.vstack((gradA, gradS.T)), ord="fro") 99 | print(f"Init gradient norm {initgrad}") 100 | # tolA = max(0.001, tol) * initgrad 101 | # tolS = tolA 102 | 103 | # Calculate initial objective 104 | X[X<0.0] = 0.0 105 | # print_summary(A, "A") 106 | # print_summary(S, "S") 107 | # print_summary(X, "X") 108 | objhistory = 0.5 * np.sum(np.sum((X - A @ S) ** 2)) 109 | print(f"Initial objective {objhistory}") 110 | objhistory = [objhistory, 0] 111 | Ahistory = [] 112 | 113 | # count the number of sucessive increase of obj 114 | inc = 0 115 | inc0 = 0 116 | # flag = 0 117 | iter = 0 118 | 119 | while inc < 5 and inc0 < 20: 120 | # uphill or downhill 121 | if objhistory[-2] - objhistory[-1] > 0.0001: 122 | inc = 0 123 | elif objhistory[-1] - objhistory[-2] > 50: 124 | print(f"Diverge after {iter} iterations!") 125 | print(objhistory) 126 | print("objhistory[-1] - objhistory[-2] > 50") 127 | print(f"{objhistory[-1]} - {objhistory[-2]} > 50") 128 | print(f"{objhistory[-1] - objhistory[-2]} > 50") 129 | print("--------------------") 130 | print(f"[{iter}(final)]: {objhistory[-1]:.5f}\t", end="") 131 | break 132 | else: 133 | print("uphill") 134 | inc = inc + 1 135 | inc0 = inc0 + 1 136 | 137 | if iter < 5: 138 | inc = 0 139 | 140 | if iter == 0: 141 | objhistory[-1] = objhistory[-2] 142 | 143 | # stopping condition 144 | # projnorm = np.linalg.norm( 145 | # np.hstack((gradA[gradA < 0 | A > 0], gradS[gradS < 0 | S > 0])) 146 | # ) 147 | 148 | if iter > maxiter: 149 | print("Max iter reached, stopping!") 150 | break 151 | 152 | # Show progress 153 | E = np.vstack( 154 | ( 155 | np.ones((1, c)), 156 | PrinComp[:, : c - 1].T 157 | @ (A - mean_data.T @ np.ones((1, c))), 158 | ) 159 | ) 160 | vol_e = 1 / factorial(c - 1) * abs(np.linalg.det(E)) 161 | print(f"[{iter}]: {objhistory[-1]:.5f}\t", end="") 162 | print(f"Temperature: {T} \t", end="") 163 | 164 | if use_synthetic_data == 1: 165 | print(f"Actual Vol.: {vol_t} \t Estimated Vol.: {vol_e}") 166 | else: 167 | print(f"Estimated Vol.: {vol_e}") 168 | 169 | vol.append(vol_e) 170 | 171 | if showflag: 172 | est = UU.T @ A 173 | 174 | if len(Ahistory) == 0: 175 | Ahistory = est 176 | else: 177 | Ahistory = np.column_stack([Ahistory, est]) 178 | 179 | index = 0 180 | for i in range(3): 181 | for j in range(i + 1, 3): 182 | ax = axes[index] 183 | ax.plot(est[i, :], est[j, :], 'yo') # estimation from nmf 184 | index += 1 185 | 186 | plt.draw() 187 | plt.pause(0.001) # pause to allow the figure to update 188 | 189 | # to consider the sum-to-one constraint 190 | tX = np.vstack((X, 20 * np.ones((1, N)))) 191 | tA = np.vstack((A, 20 * np.ones((1, c)))) 192 | # print_summary(tX, "tX-mvc") 193 | # print_summary(tA, "tA-mvc") 194 | # find S 195 | if type_alg_S == 1: # conjugate gradient learning 196 | no_iter = 50 197 | S = conjugate( 198 | X, A, S, no_iter, PrinComp[:, : c - 1], mean_data, T 199 | ) 200 | elif type_alg_S == 2: # steepest descent 201 | tolS = 0.0001 202 | S, _, _ = steepdescent( 203 | tX, tA, S, tolS, 200, PrinComp[:, : c - 1], mean_data, T 204 | ) 205 | 206 | # if iterS == 1: 207 | # tolS = 0.1 * tolS 208 | 209 | # find A 210 | if type_alg_A == 1: # conjugate gradient learning 211 | no_iter = 50 212 | A = conjugate( 213 | X.T, S.T, A.T, no_iter, PrinComp[:, : c - 1], mean_data, T 214 | ) 215 | A = A.T 216 | elif type_alg_A == 2: # steepest descent 217 | tolA = 0.0001 218 | A, _, _ = steepdescent( 219 | X.T, S.T, A.T, tolA, 100, PrinComp[:, : c - 1], mean_data, T 220 | ) 221 | A = A.T 222 | # gradA = gradA.T 223 | 224 | # if iterA == 1: 225 | # tolA = 0.1 * tolA 226 | # print_summary(A, "A-mvc") 227 | # print_summary(S, "S-mvc") 228 | # Calculate objective 229 | newobj = 0.5 * np.sum(np.sum((X - A @ S) ** 2)) 230 | objhistory.append(newobj) 231 | 232 | iter = iter + 1 233 | 234 | return A, S 235 | -------------------------------------------------------------------------------- /nmf_test.m: -------------------------------------------------------------------------------- 1 | clear; 2 | rng(0); % Set the seed for reproducibility 3 | 4 | % --- Parameters --- % 5 | % input parameters 6 | % Syntheitc Data 7 | use_synthetic_data = 1; % 1 for synthetic data, 0 for real data 8 | input_mat_name = 'A.mat'; 9 | % bands = (1:4); 10 | bands_mat_name = 'BANDS.mat'; 11 | % Landsat Data 12 | % use_synthetic_data = 0; % 1 for synthetic data, 0 for real data 13 | % input_mat_name = 'Landsat_separate_images_BR_R002.mat'; 14 | % input_mat_name = 'Landsat.mat'; 15 | 16 | % mvcnmf parameters 17 | c = 5; % number of endmembers 18 | SNR = 20; %dB 19 | tol = 1e-6; 20 | maxiter = 5; 21 | T = 0.015; 22 | showflag = 0; 23 | verbose = 'on'; % 'on' or 'off' 24 | 25 | % --- read data --- % 26 | input_path = sprintf('inputs/%s', input_mat_name); 27 | % Load the list of variables in the .mat file 28 | variables = who('-file', input_path); 29 | 30 | % start the timer 31 | tic 32 | 33 | % loop through the variables 34 | for i = 1:length(variables) 35 | clc; 36 | disp("#########################################") 37 | fprintf("Processing %s/%s images\n", num2str(i), num2str(length(variables))); 38 | disp("#########################################") 39 | variable_name = variables{i}; 40 | % variable_name = "BR_R002_23KPR00_2014_01_09"; 41 | % Load the first variable in the list 42 | loaded_variable = load(input_path, variable_name); 43 | % Set variable A equal to the loaded variable 44 | A = loaded_variable.(variable_name); 45 | 46 | if use_synthetic_data == 1 47 | % Load bands 48 | if ~exist('bands_mat_name', 'var') && ~exist('bands', 'var') 49 | A = A(:, (1:c)); 50 | else 51 | 52 | disp("using bands file"); 53 | bands_path = sprintf('inputs/%s', bands_mat_name); 54 | load(bands_path); 55 | A = A(BANDS, (1:c)); 56 | 57 | end 58 | 59 | end 60 | 61 | % --- process --- % 62 | 63 | % print_summary(A, "A"); 64 | if use_synthetic_data == 1 65 | [synthetic, abf] = getSynData(A, 7, 0); 66 | [M, N, D] = size(synthetic); 67 | mixed = reshape(synthetic, M * N, D); 68 | % add noise 69 | variance = sum(mixed(:) .^ 2) / 10 ^ (SNR / 10) / M / N / D; 70 | n = sqrt(variance) * randn([D M * N]); 71 | mixed = mixed' + n; 72 | clear n; 73 | 74 | % remove noise 75 | [UU, SS, VV] = svds(mixed, c); 76 | Lowmixed = UU' * mixed; 77 | 78 | % print_summary(UU, "UU") 79 | % print_summary(Lowmixed, "Lowmixed") 80 | 81 | mixed = UU * Lowmixed; 82 | EM = UU' * A; 83 | % vca algorithm 84 | [A_vca, EndIdx] = vca(mixed, 'Endmembers', c, 'SNR', SNR, 'verbose', verbose); 85 | else 86 | % load data 87 | [M, N, D] = size(A); 88 | mixed = reshape(A, M * N, D); 89 | mixed = mixed'; 90 | % create and empty var for UU 91 | UU = []; 92 | % vca algorithm 93 | [A_vca, EndIdx] = vca(mixed, 'Endmembers', c, 'verbose', verbose); 94 | end 95 | 96 | % FCLS 97 | warning off; 98 | AA = [1e-5 * A_vca; ones(1, length(A_vca(1, :)))]; 99 | s_fcls = zeros(length(A_vca(1, :)), M * N); 100 | 101 | for j = 1:M * N 102 | r = [1e-5 * mixed(:, j); 1]; 103 | % s_fcls(:,j) = nnls(AA,r); 104 | s_fcls(:, j) = lsqnonneg(AA, r); 105 | end 106 | 107 | % use vca to initiate 108 | Ainit = A_vca; 109 | sinit = s_fcls; 110 | 111 | % % random initialization 112 | % idx = ceil(rand(1,c)*(M*N-1)); 113 | % Ainit = mixed(:,idx); 114 | % sinit = zeros(c,M*N); 115 | 116 | % PCA 117 | [PrinComp, pca_score] = pca(mixed'); 118 | % print_summary(PrinComp, "PrinComp") 119 | meanData = mean(pca_score); 120 | %[PrinComp, pca_score] = princomp(mixed', 0); 121 | %meanData = mean(mixed'); 122 | 123 | % use conjugate gradient to find A can speed up the learning 124 | maxiter_str = sprintf('%d', maxiter); 125 | [Aest, sest] = mvcnmf(mixed, 126 | Ainit, 127 | sinit, 128 | A, 129 | UU, 130 | PrinComp, 131 | meanData, 132 | T, 133 | tol, 134 | maxiter, 135 | showflag, 136 | 2, 137 | 1, 138 | use_synthetic_data); 139 | 140 | % visualize endmembers in scatterplots 141 | 142 | if showflag 143 | d = 4; 144 | Anmf = UU' * Aest; 145 | figure, 146 | 147 | for i = 1:d - 1 148 | 149 | for j = i + 1:d - 1 150 | subplot(d - 2, d - 2, (i - 1) * (d - 2) + j - i), 151 | plot(Lowmixed(i, 1:6:end), Lowmixed(j, 1:6:end), 'rx'); 152 | hold on, plot(EM(i, :), EM(j, :), 'go', 'markerfacecolor', 'g'); 153 | plot(Anmf(i, :), Anmf(j, :), 'bo', 'markerfacecolor', 'b'); 154 | end 155 | 156 | end 157 | 158 | end 159 | 160 | if use_synthetic_data == 1 161 | % permute results 162 | CRD = corrcoef([A Aest]); 163 | DD = abs(CRD(c + 1:2 * c, 1:c)); 164 | perm_mtx = zeros(c, c); 165 | aux = zeros(c, 1); 166 | 167 | for i = 1:c 168 | [ld, cd] = find(max(DD(:)) == DD); 169 | ld = ld(1); cd = cd(1); % in the case of more than one maximum 170 | perm_mtx(ld, cd) = 1; 171 | DD(:, cd) = aux; DD(ld, :) = aux'; 172 | end 173 | 174 | end 175 | 176 | % show the estimations 177 | if showflag 178 | figure, 179 | 180 | for i = 1:c 181 | subplot(c, 4, 4 * i - 3), 182 | plot(A(:, i), 'r'); axis([0 300 0 1]) 183 | 184 | if i == 1 185 | title('True end-members'); 186 | end 187 | 188 | subplot(c, 4, 4 * i - 2), 189 | plot(Aest(:, i), 'g'); axis([0 300 0 1]) 190 | 191 | if i == 1 192 | title('Estimated end-members'); 193 | end 194 | 195 | subplot(c, 4, 4 * i - 1), 196 | imagesc(reshape(abf(i, :), M, N)); 197 | 198 | if i == 1 199 | title('True abundance'); 200 | end 201 | 202 | subplot(c, 4, 4 * i), 203 | imagesc(Sest(:, :, i)); 204 | 205 | if i == 1 206 | title('Estimated abundance'); 207 | end 208 | 209 | end 210 | 211 | end 212 | 213 | % quantitative evaluation of spectral signature and abundance 214 | if use_synthetic_data == 1 215 | % rmse error of abundances 216 | E_rmse = sqrt(sum(sum(((abf - sest) .* (abf - sest)) .^ 2)) / (M * N * c)); 217 | display(E_rmse); 218 | 219 | % the angle between abundances 220 | nabf = diag(abf * abf'); 221 | nsest = diag(sest * sest'); 222 | ang_beta = 180 / pi * acos(diag(abf * sest') ./ sqrt(nabf .* nsest)); 223 | E_aad = mean(ang_beta .^ 2) ^ .5; 224 | display(E_aad); 225 | 226 | % cross entropy between abundance 227 | E_entropy = sum(abf .* log((abf +1e-9) ./ (sest +1e-9))) + sum(sest .* log((sest +1e-9) ./ (abf +1e-9))); 228 | E_aid = mean(E_entropy .^ 2) ^ .5; 229 | display(E_aid); 230 | 231 | % the angle between material signatures 232 | nA = diag(A' * A); 233 | nAest = diag(Aest' * Aest); 234 | ang_theta = 180 / pi * acos(diag(A' * Aest) ./ sqrt(nA .* nAest)); 235 | E_sad = mean(ang_theta .^ 2) ^ .5; 236 | display(E_sad); 237 | 238 | % the spectral information divergence 239 | pA = A ./ (repmat(sum(A), [length(A(:, 1)) 1])); 240 | qA = Aest ./ (repmat(sum(Aest), [length(A(:, 1)) 1])); 241 | qA = abs(qA); 242 | SID = sum(pA .* log((pA +1e-9) ./ (qA +1e-9))) + sum(qA .* log((qA +1e-9) ./ (pA +1e-9))); 243 | E_sid = mean(SID .^ 2) ^ .5; 244 | display(E_sid); 245 | end 246 | 247 | % Save output 248 | % keep only 2 digits after the decimal point 249 | T_str = sprintf('%.4f', T); 250 | outputFileName = sprintf('outputs/output_%s_max_iter%s_T%s.mat', variable_name, maxiter_str, T_str); 251 | 252 | if use_synthetic_data == 1 253 | save(outputFileName, 'Aest', 'sest', 'E_rmse', 'E_aad', 'E_aid', 'E_sad', 'E_sid'); 254 | else 255 | save(outputFileName, 'Aest', 'sest'); 256 | end 257 | 258 | break 259 | end 260 | 261 | % Stop the timer 262 | elapsed_time = toc; 263 | 264 | % Display the elapsed time in seconds 265 | fprintf('Elapsed time: %.2f seconds\n', elapsed_time); 266 | % Program finished 267 | disp('Finished'); 268 | 269 | 270 | function print_summary(array, name) 271 | disp("---------------------------") 272 | fprintf('Size of %s: ', name); 273 | disp(size(array)); 274 | fprintf('Minimum value: %.2f\n', min(array, [], 'all')); 275 | fprintf('Maximum value: %.2f\n', max(array, [], 'all')); 276 | fprintf('Mean value: %.2f\n', mean(array, 'all')); 277 | fprintf('Standard deviation: %.2f\n\n', std(array, 0, 'all')); 278 | disp("---------------------------") 279 | end -------------------------------------------------------------------------------- /pyversion/nmf_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.io as sio 3 | from scipy.optimize import nnls 4 | import os 5 | from sklearn.decomposition import PCA 6 | import matplotlib.pyplot as plt 7 | import time 8 | from scipy.sparse.linalg import svds 9 | 10 | 11 | # from sklearn.linear_model import LassoLars 12 | # from scipy.linalg import svdvals 13 | 14 | # Custom libraries 15 | from getSynData import get_syn_data as getSynData 16 | from mvcnmf import mvcnmf_secord as mvcnmf 17 | from vca import vca 18 | 19 | 20 | def print_summary(array, name): 21 | print("---------------------------") 22 | print(f"Size of {name}: {array.shape}") 23 | print(f"Minimum value: {np.min(array):.2f}") 24 | print(f"Maximum value: {np.max(array):.2f}") 25 | print(f"Mean value: {np.mean(array):.2f}") 26 | print(f"Standard deviation: {np.std(array):.2f}") 27 | print("---------------------------") 28 | 29 | 30 | np.random.seed(0) # Set the seed for reproducibility 31 | 32 | # --- Parameters --- % 33 | # input parameters 34 | 35 | # Synthetic Data 36 | # use_synthetic_data = True 37 | # input_mat_name = "A.mat" 38 | # bands_mat_name = "BANDS.mat" 39 | 40 | # Landsat Data 41 | use_synthetic_data = False 42 | input_mat_name = 'Landsat_separate_images_BR_R002.mat' 43 | # input_mat_name = 'Landsat.mat' 44 | 45 | # mvcnmf parameters 46 | c = 5 # number of endmembers 47 | SNR = 20 # dB 48 | tol = 1e-6 49 | maxiter = 150 50 | T = 0.015 51 | showflag = False 52 | verbose = True 53 | 54 | # --- read data --- % 55 | input_path = os.path.join("../inputs", input_mat_name) 56 | # Load the list of variables in the .mat file 57 | variables = [var for var in sio.whosmat(input_path) 58 | if var not in ['__header__', '__version__', '__globals__']] 59 | 60 | if c == 1: 61 | raise ValueError("c must be greater than 1") 62 | 63 | # start the timer 64 | tic = time.time() 65 | 66 | # loop through the variables 67 | for i in range(len(variables)): 68 | print("#########################################") 69 | print(f"Processing {i+1}/{len(variables)} images") 70 | print("#########################################") 71 | # variable_name = variables[i][0] 72 | variable_name = "BR_R002_23KPR00_2014_01_09" 73 | # Load the first variable in the list 74 | loaded_variable = sio.loadmat(input_path) 75 | # Set variable A equal to the loaded variable 76 | A = loaded_variable[variable_name].astype('float64') 77 | if use_synthetic_data: 78 | # Load bands 79 | try: 80 | bands_path = os.path.join("../inputs", bands_mat_name) 81 | bands_mat = sio.loadmat(bands_path) 82 | BANDS = bands_mat["BANDS"].reshape(-1) 83 | A = A[BANDS, :c] 84 | except NameError: 85 | A = A[:, :c] 86 | # --- process --- % 87 | # print_summary(A, "A") 88 | if use_synthetic_data: 89 | [synthetic, abf] = getSynData(A, 7, 0) 90 | M, N, D = synthetic.shape 91 | mixed = synthetic.reshape(M * N, D) 92 | # add noise 93 | variance = np.sum(mixed**2) / 10 ** (SNR / 10) / M / N / D 94 | n = np.sqrt(variance) * np.random.randn(D, M * N) 95 | mixed = mixed.T + n 96 | del n 97 | 98 | # remove noise 99 | UU, SS, VV = svds(mixed, k=c) 100 | UU = UU[:, ::-1] # Reverse the column order to match MATLAB output 101 | Lowmixed = UU.T @ mixed 102 | 103 | # print_summary(UU, "UU") 104 | # print_summary(Lowmixed, "A") 105 | mixed = UU @ Lowmixed 106 | EM = UU.T @ A 107 | # vca algorithm 108 | A_vca, EndIdx = vca(mixed, p=c, SNR=SNR, verbose=verbose) 109 | else: 110 | # load data 111 | M, N, D = A.shape 112 | mixed = A.reshape(M * N, D) 113 | mixed = mixed.T 114 | # create an empty var for UU 115 | UU = np.empty((0, 0)) 116 | # vca algorithm 117 | A_vca, EndIdx = vca(mixed, p=c, verbose=verbose) 118 | 119 | # FCLS 120 | AA = np.vstack([1e-5 * A_vca, np.ones((1, A_vca.shape[1]))]) 121 | s_fcls = np.zeros((A_vca.shape[1], M * N)) 122 | 123 | for j in range(M * N): 124 | r = np.hstack([1e-5 * mixed[:, j], [1]]) 125 | # s_fcls[:, j] = np.linalg.lstsq(AA, r, rcond=None)[0] 126 | s_fcls[:, j] = nnls(AA, r)[0] 127 | 128 | # use vca to initiate 129 | Ainit = A_vca 130 | sinit = s_fcls 131 | 132 | # PCA 133 | pca = PCA() 134 | pca_score = pca.fit_transform(mixed.T) 135 | PrinComp = pca.components_ 136 | meanData = np.mean(pca_score, axis=0)[:, np.newaxis].T 137 | 138 | # use conjugate gradient to find A can speed up the learning 139 | maxiter_str = f"{maxiter}" 140 | Aest, sest = mvcnmf( 141 | mixed, 142 | Ainit, 143 | sinit, 144 | A, 145 | UU, 146 | PrinComp, 147 | meanData, 148 | T, 149 | tol, 150 | maxiter, 151 | showflag, 152 | 2, 153 | 1, 154 | use_synthetic_data, 155 | ) 156 | 157 | # visualize endmembers in scatterplots 158 | 159 | if showflag: 160 | d = 4 161 | Anmf = UU.T @ Aest 162 | 163 | fig, axes = plt.subplots(d - 2, d - 2) 164 | axes = np.ravel(axes) 165 | index = 0 166 | for i in range(d - 1): 167 | for j in range(i + 1, d - 1): 168 | ax = axes[index] 169 | ax.plot(Lowmixed[i, ::6], Lowmixed[j, ::6], 'rx') 170 | ax.plot(EM[i, :], EM[j, :], 'go', markerfacecolor='g') 171 | ax.plot(Anmf[i, :], Anmf[j, :], 'bo', markerfacecolor='b') 172 | index += 1 173 | 174 | plt.show() 175 | 176 | if use_synthetic_data == 1: 177 | # permute results 178 | CRD = np.corrcoef(np.hstack([A, Aest])) 179 | DD = np.abs(CRD[c : 2 * c, :c]) 180 | perm_mtx = np.zeros((c, c)) 181 | aux = np.zeros((c, 1)) 182 | 183 | for i in range(c): 184 | ld, cd = np.unravel_index(np.argmax(DD), DD.shape) 185 | perm_mtx[ld, cd] = 1 186 | DD[:, cd] = aux.squeeze() 187 | DD[ld, :] = aux.squeeze().T 188 | 189 | Aest = Aest @ perm_mtx 190 | sest = (sest.T @ perm_mtx) 191 | Sest = np.reshape(sest, (M, N, c)) 192 | sest = sest.T 193 | 194 | # show the estimations 195 | if showflag: 196 | fig, axs = plt.subplots(c, 4) 197 | 198 | for i in range(c): 199 | axs[i, 0].plot(A[:, i], "r", label="True endmembers") 200 | axs[i, 0].set_ylim(0, 1) 201 | 202 | if i == 0: 203 | axs[i, 0].set_title("True end-members") 204 | 205 | axs[i, 1].plot(Aest[:, i], "g", label="Estimated endmembers") 206 | axs[i, 1].legend() 207 | 208 | axs[i, 1].set_ylim(0, 1) 209 | 210 | if i == 0: 211 | axs[i, 1].set_title("Estimated end-members") 212 | 213 | axs[i, 2].imshow(abf[i, :].reshape(M, N)) 214 | 215 | if i == 0: 216 | axs[i, 2].set_title("True abundance") 217 | 218 | axs[i, 3].imshow(sest[i, :].reshape(M, N)) 219 | 220 | if i == 0: 221 | axs[i, 3].set_title("Estimated abundance") 222 | 223 | plt.show() 224 | 225 | # quantitative evaluation of spectral signature and abundance 226 | if use_synthetic_data: 227 | # rmse error of abundances 228 | E_rmse = np.sqrt(np.sum((abf - sest) ** 2) / (M * N * c)) 229 | print("E_rmse", E_rmse) 230 | 231 | # the angle between abundances 232 | nabf = np.diag(abf @ abf.T) 233 | nsest = np.diag(sest @ sest.T) 234 | ang_beta = ( 235 | 180 236 | / np.pi 237 | * np.arccos(np.diag(abf @ sest.T) / np.sqrt(nabf * nsest)) 238 | ) 239 | E_aad = np.sqrt(np.mean(ang_beta**2)) 240 | print("E_aad", E_aad) 241 | 242 | # cross entropy between abundance 243 | E_entropy = np.sum( 244 | abf * np.log((abf + 1e-9) / (sest + 1e-9)) 245 | ) + np.sum(sest * np.log((sest + 1e-9) / (abf + 1e-9))) 246 | E_aid = np.sqrt(np.mean(E_entropy**2)) 247 | print("E_aid", E_aid) 248 | 249 | # the angle between material signatures 250 | nA = np.diag(A.T @ A) 251 | nAest = np.diag(Aest.T @ Aest) 252 | ang_theta = ( 253 | 180 / np.pi * np.arccos(np.diag(A.T @ Aest) / np.sqrt(nA * nAest)) 254 | ) 255 | E_sad = np.sqrt(np.mean(ang_theta**2)) 256 | print("E_sad", E_sad) 257 | 258 | # the spectral information divergence 259 | pA = A / (np.sum(A, axis=0)) 260 | qA = Aest / (np.sum(Aest, axis=0)) 261 | qA = np.abs(qA) 262 | SID = np.sum(pA * np.log((pA + 1e-9) / (qA + 1e-9))) + np.sum( 263 | qA * np.log((qA + 1e-9) / (pA + 1e-9)) 264 | ) 265 | E_sid = np.sqrt(np.mean(SID**2)) 266 | print("E_sid", E_sid) 267 | 268 | # Save output 269 | # keep only 2 digits after the decimal point 270 | T_str = f"{T:.4f}" 271 | outputFileName = ( 272 | f"../outputs/output_{variable_name}_max_iter{maxiter}_T{T_str}.mat" 273 | ) 274 | 275 | if use_synthetic_data: 276 | data = {"Aest": Aest, "sest": sest, "E_rmse": E_rmse, 277 | "E_aad": E_aad, "E_aid": E_aid, "E_sad": E_sad, 278 | "E_sid": E_sid} 279 | else: 280 | data = {"Aest": Aest, "sest": sest} 281 | 282 | sio.savemat(outputFileName, data, do_compression=True) 283 | break -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /fix_data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "\n", 10 | "import scipy.io as sio\n", 11 | "import os" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 12, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "name = 'Landsat_separate_images_BR_R002'\n", 21 | "mat = sio.loadmat(f'inputs/{name}.mat')" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 13, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "# replace - with _ in the keys\n", 31 | "mat_fixed = {}\n", 32 | "for key in mat.keys():\n", 33 | " mat_fixed[key.replace('-', '_')] = mat[key]\n", 34 | "# save the new mat file\n", 35 | "sio.savemat(f'inputs/{name}_fixed.mat', mat_fixed)" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 14, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "name": "stdout", 45 | "output_type": "stream", 46 | "text": [ 47 | "dict_keys(['__header__', '__version__', '__globals__', 'BR_R002_23KNR90_2014_02_26', 'BR_R002_23KNR90_2021_07_23', 'BR_R002_23KNR90_2015_10_18', 'BR_R002_23KNR90_2021_02_13', 'BR_R002_23KNR90_2019_01_30', 'BR_R002_23KNR90_2015_10_11', 'BR_R002_23KNR90_2019_11_30', 'BR_R002_23KNR90_2016_04_27', 'BR_R002_23KNR90_2020_01_26', 'BR_R002_23KNR90_2014_05_24', 'BR_R002_23KNR90_2015_08_24', 'BR_R002_23KNR90_2021_08_24', 'BR_R002_23KNR90_2014_10_31', 'BR_R002_23KNR90_2018_03_16', 'BR_R002_23KNR90_2017_06_01', 'BR_R002_23KNR90_2021_01_19', 'BR_R002_23KNR90_2020_02_11', 'BR_R002_23KNR90_2018_03_09', 'BR_R002_23KNR90_2018_07_22', 'BR_R002_23KNR90_2017_01_24', 'BR_R002_23KNR90_2018_02_28', 'BR_R002_23KNR90_2020_04_22', 'BR_R002_23KNR90_2020_12_27', 'BR_R002_23KNR90_2017_09_30', 'BR_R002_23KNR90_2014_08_28', 'BR_R002_23KNR90_2018_12_06', 'BR_R002_23KNR90_2021_04_02', 'BR_R002_23KNR90_2018_05_28', 'BR_R002_23KNR90_2021_07_30', 'BR_R002_23KNR90_2019_08_03', 'BR_R002_23KNR90_2017_04_23', 'BR_R002_23KNR90_2018_08_16', 'BR_R002_23KNR90_2018_12_13', 'BR_R002_23KNR90_2020_11_16', 'BR_R002_23KNR90_2017_11_24', 'BR_R002_23KNR90_2018_01_27', 'BR_R002_23KNR90_2016_09_18', 'BR_R002_23KNR90_2017_03_22', 'BR_R002_23KNR90_2020_06_02', 'BR_R002_23KNR90_2018_04_10', 'BR_R002_23KNR90_2016_10_04', 'BR_R002_23KNR90_2016_01_15', 'BR_R002_23KNR90_2014_01_25', 'BR_R002_23KNR90_2017_04_07', 'BR_R002_23KNR90_2015_02_04', 'BR_R002_23KNR90_2014_10_08', 'BR_R002_23KNR90_2020_07_27', 'BR_R002_23KNR90_2020_12_02', 'BR_R002_23KNR90_2020_07_11', 'BR_R002_23KNR90_2018_08_23', 'BR_R002_23KNR90_2014_05_17', 'BR_R002_23KNR90_2014_09_22', 'BR_R002_23KNR90_2016_06_14', 'BR_R002_23KNR90_2019_07_25', 'BR_R002_23KNR90_2014_11_09', 'BR_R002_23KNR90_2017_02_18', 'BR_R002_23KNR90_2020_08_05', 'BR_R002_23KNR90_2015_04_18', 'BR_R002_23KNR90_2015_09_25', 'BR_R002_23KNR90_2015_09_16', 'BR_R002_23KNR90_2019_02_08', 'BR_R002_23KNR90_2016_08_17', 'BR_R002_23KNR90_2016_05_22', 'BR_R002_23KNR90_2015_10_27', 'BR_R002_23KNR90_2016_03_26', 'BR_R002_23KNR90_2015_05_27', 'BR_R002_23KNR90_2019_07_02', 'BR_R002_23KNR90_2016_09_27', 'BR_R002_23KNR90_2014_01_16', 'BR_R002_23KNR90_2014_03_14', 'BR_R002_23KNR90_2015_07_30', 'BR_R002_23KNR90_2015_11_03', 'BR_R002_23KNR90_2020_09_29', 'BR_R002_23KNR90_2020_10_15', 'BR_R002_23KNR90_2018_09_17', 'BR_R002_23KNR90_2014_06_18', 'BR_R002_23KNR90_2017_12_03', 'BR_R002_23KNR90_2017_04_30', 'BR_R002_23KNR90_2019_03_03', 'BR_R002_23KNR90_2021_04_18', 'BR_R002_23KNR90_2015_03_24', 'BR_R002_23KNR90_2015_02_20', 'BR_R002_23KNR90_2020_03_21', 'BR_R002_23KNR90_2015_08_15', 'BR_R002_23KNR90_2021_04_25', 'BR_R002_23KNR90_2018_03_25', 'BR_R002_23KNR90_2015_12_14', 'BR_R002_23KNR90_2021_06_05', 'BR_R002_23KNR90_2016_06_23', 'BR_R002_23KNR90_2017_07_28', 'BR_R002_23KNR90_2015_06_12', 'BR_R002_23KNR90_2017_03_13', 'BR_R002_23KNR90_2016_10_29', 'BR_R002_23KNR90_2020_09_13', 'BR_R002_23KNR90_2016_06_30', 'BR_R002_23KNR90_2017_05_25', 'BR_R002_23KNR90_2017_10_07', 'BR_R002_23KNR90_2015_07_07', 'BR_R002_23KNR90_2017_06_26', 'BR_R002_23KNR90_2019_06_16', 'BR_R002_23KNR90_2015_05_20', 'BR_R002_23KNR90_2015_04_25', 'BR_R002_23KNR90_2014_04_22', 'BR_R002_23KNR90_2016_08_01', 'BR_R002_23KNR90_2019_10_13', 'BR_R002_23KNR90_2017_10_16', 'BR_R002_23KNR90_2017_07_19', 'BR_R002_23KNR90_2018_12_22', 'BR_R002_23KNR90_2021_07_07', 'BR_R002_23KNR90_2016_10_20', 'BR_R002_23KNR90_2021_04_09', 'BR_R002_23KNR90_2020_01_17', 'BR_R002_23KNR90_2020_12_18', 'BR_R002_23KNR90_2015_12_21', 'BR_R002_23KNR90_2018_01_11', 'BR_R002_23KNR90_2019_01_07', 'BR_R002_23KNR90_2015_10_02', 'BR_R002_23KNR90_2021_06_21', 'BR_R002_23KNR90_2017_11_08', 'BR_R002_23KNR90_2018_11_20', 'BR_R002_23KNR90_2015_05_11', 'BR_R002_23KNR90_2019_04_13', 'BR_R002_23KNR90_2016_04_20', 'BR_R002_23KNR90_2019_12_25', 'BR_R002_23KNR90_2015_04_09', 'BR_R002_23KNR90_2016_07_25', 'BR_R002_23KNR90_2014_03_21', 'BR_R002_23KNR90_2021_03_24', 'BR_R002_23KNR90_2016_02_16', 'BR_R002_23KNR90_2014_08_05', 'BR_R002_23KNR90_2021_05_27', 'BR_R002_23KNR90_2016_04_04', 'BR_R002_23KNR90_2019_08_26', 'BR_R002_23KNR90_2014_02_10', 'BR_R002_23KNR90_2020_08_21', 'BR_R002_23KNR90_2014_07_27', 'BR_R002_23KNR90_2018_02_12', 'BR_R002_23KNR90_2016_05_06', 'BR_R002_23KNR90_2020_11_09', 'BR_R002_23KNR90_2015_07_23', 'BR_R002_23KNR90_2020_12_11', 'BR_R002_23KNR90_2016_07_16', 'BR_R002_23KNR90_2016_05_29', 'BR_R002_23KNR90_2019_11_14', 'BR_R002_23KNR90_2017_06_17', 'BR_R002_23KNR90_2015_12_30', 'BR_R002_23KNR90_2014_12_27', 'BR_R002_23KNR90_2015_01_19', 'BR_R002_23KNR90_2021_06_28', 'BR_R002_23KNR90_2014_09_06', 'BR_R002_23KNR90_2014_11_16', 'BR_R002_23KNR90_2017_07_12', 'BR_R002_23KNR90_2017_06_10', 'BR_R002_23KNR90_2018_09_24', 'BR_R002_23KNR90_2016_11_14', 'BR_R002_23KNR90_2019_08_10', 'BR_R002_23KNR90_2016_01_06', 'BR_R002_23KNR90_2016_07_09', 'BR_R002_23KNR90_2017_01_08', 'BR_R002_23KNR90_2020_10_31', 'BR_R002_23KNR90_2014_07_11', 'BR_R002_23KNR90_2019_03_19', 'BR_R002_23KNR90_2019_11_23', 'BR_R002_23KNR90_2017_08_29', 'BR_R002_23KNR90_2014_08_21', 'BR_R002_23KNR90_2014_06_25', 'BR_R002_23KNR90_2015_01_28', 'BR_R002_23KNR90_2014_12_11', 'BR_R002_23KNR90_2016_04_11', 'BR_R002_23KNR90_2017_09_21', 'BR_R002_23KNR90_2020_10_24', 'BR_R002_23KNR90_2019_07_18', 'BR_R002_23KNR90_2014_06_02', 'BR_R002_23KNR90_2017_12_19', 'BR_R002_23KNR90_2021_02_20', 'BR_R002_23KNR90_2015_07_14', 'BR_R002_23KNR90_2021_01_03', 'BR_R002_23KNR90_2020_06_18', 'BR_R002_23KNR90_2017_08_04', 'BR_R002_23KNR90_2018_04_01', 'BR_R002_23KNR90_2020_01_10', 'BR_R002_23KNR90_2021_01_12', 'BR_R002_23KNR90_2021_02_04', 'BR_R002_23KNR90_2015_03_17', 'BR_R002_23KNR90_2017_08_13', 'BR_R002_23KNR90_2019_10_29', 'BR_R002_23KNR90_2014_12_18', 'BR_R002_23KNR90_2018_08_07', 'BR_R002_23KNR90_2019_06_23', 'BR_R002_23KNR90_2018_12_29', 'BR_R002_23KNR90_2016_11_21', 'BR_R002_23KNR90_2019_01_23', 'BR_R002_23KNR90_2014_12_02', 'BR_R002_23KNR90_2018_07_31', 'BR_R002_23KNR90_2021_03_08', 'BR_R002_23KNR90_2020_06_25', 'BR_R002_23KNR90_2015_02_13', 'BR_R002_23KNR90_2015_06_28', 'BR_R002_23KNR90_2014_07_20', 'BR_R002_23KNR90_2017_05_09', 'BR_R002_23KNR90_2018_06_29', 'BR_R002_23KNR90_2018_02_21', 'BR_R002_23KNR90_2021_03_17', 'BR_R002_23KNR90_2019_02_24', 'BR_R002_23KNR90_2018_06_20', 'BR_R002_23KNR90_2017_04_14', 'BR_R002_23KNR90_2019_09_27', 'BR_R002_23KNR90_2014_04_06', 'BR_R002_23KNR90_2014_11_25', 'BR_R002_23KNR90_2018_05_03', 'BR_R002_23KNR90_2020_03_05', 'BR_R002_23KNR90_2019_09_04', 'BR_R002_23KNR90_2017_01_01', 'BR_R002_23KNR90_2015_08_08', 'BR_R002_23KNR90_2018_06_04', 'BR_R002_23KNR90_2016_11_30', 'BR_R002_23KNR90_2014_05_01', 'BR_R002_23KNR90_2016_08_10', 'BR_R002_23KNR90_2020_09_22', 'BR_R002_23KNR90_2015_01_12', 'BR_R002_23KNR90_2016_02_23', 'BR_R002_23KNR90_2016_09_11', 'BR_R002_23KNR90_2018_09_01', 'BR_R002_23KNR90_2014_10_24', 'BR_R002_23KNR90_2019_03_12', 'BR_R002_23KNR90_2016_12_07', 'BR_R002_23KNR90_2020_02_27', 'BR_R002_23KNR90_2019_04_20', 'BR_R002_23KNR90_2018_01_04', 'BR_R002_23KNR90_2021_01_28', 'BR_R002_23KNR90_2017_09_14', 'BR_R002_23KNR90_2016_10_13', 'BR_R002_23KNR90_2019_07_09', 'BR_R002_23KNR90_2019_05_15', 'BR_R002_23KNR90_2018_01_20', 'BR_R002_23KNR90_2021_05_04', 'BR_R002_23KNR90_2018_11_11', 'BR_R002_23KNR90_2019_10_22', 'BR_R002_23KNR90_2017_03_06', 'BR_R002_23KNR90_2019_09_20', 'BR_R002_23KNR90_2017_01_17', 'BR_R002_23KNR90_2020_07_20', 'BR_R002_23KNR90_2017_11_17', 'BR_R002_23KNR90_2020_01_01', 'BR_R002_23KNR90_2021_07_14', 'BR_R002_23KNR90_2014_02_01', 'BR_R002_23KNR90_2021_08_15', 'BR_R002_23KNR90_2016_02_07', 'BR_R002_23KNR90_2019_05_06', 'BR_R002_23KNR90_2018_11_27', 'BR_R002_23KNR90_2019_04_04', 'BR_R002_23KNR90_2017_02_25', 'BR_R002_23KNR90_2018_09_08', 'BR_R002_23KNR90_2015_12_05', 'BR_R002_23KNR90_2016_12_16', 'BR_R002_23KNR90_2017_12_26', 'BR_R002_23KNR90_2018_04_17', 'BR_R002_23KNR90_2014_06_09', 'BR_R002_23KNR90_2019_12_16', 'BR_R002_23KNR90_2018_02_05', 'BR_R002_23KNR90_2018_11_04', 'BR_R002_23KNR90_2020_09_06', 'BR_R002_23KNR90_2016_01_31', 'BR_R002_23KNR90_2014_07_04', 'BR_R002_23KNR90_2016_03_03', 'BR_R002_23KNR90_2021_06_12', 'BR_R002_23KNR90_2019_06_07', 'BR_R002_23KNR90_2017_10_23', 'BR_R002_23KNR90_2017_09_05', 'BR_R002_23KNR90_2014_03_05', 'BR_R002_23KNR90_2014_01_09', 'BR_R002_23KNR90_2015_06_05', 'BR_R002_23KNR90_2020_08_28', 'BR_R002_23KNR90_2019_01_14', 'BR_R002_23KNR90_2018_07_15', 'BR_R002_23KNR90_2020_04_15', 'BR_R002_23KNR90_2020_08_12', 'BR_R002_23KNR90_2017_05_16', 'BR_R002_23KNR90_2018_05_19', 'BR_R002_23KNR90_2020_02_18', 'BR_R002_23KNR90_2020_05_24', 'BR_R002_23KNR90_2019_09_11', 'BR_R002_23KNR90_2019_12_09', 'BR_R002_23KNR90_2018_07_06', 'BR_R002_23KNR90_2018_10_03', 'BR_R002_23KNR90_2017_02_02', 'BR_R002_23KNR90_2018_04_26', 'BR_R002_23KNR90_2015_09_09', 'BR_R002_23KNR90_2016_05_13', 'BR_R002_23KNR90_2020_02_02', 'BR_R002_23KNR90_2016_01_22', 'BR_R002_23KNR90_2014_10_15', 'BR_R002_23KNR90_2018_10_19', 'BR_R002_23KNR90_2016_12_23', 'BR_R002_23KNR90_2020_06_09', 'BR_R002_23KNR90_2021_03_01', 'BR_R002_23KNR90_2019_02_15', 'BR_R002_23KNR90_2016_03_10', 'BR_R002_23KNR90_2020_03_30', 'BR_R002_23KNR90_2019_10_06', 'BR_R002_23KNR90_2015_01_03', 'BR_R002_23KNR90_2015_06_21', 'BR_R002_23KNR90_2016_03_19', 'BR_R002_23KNR90_2014_02_17', 'BR_R002_23KNR90_2015_05_04', 'BR_R002_23KNR90_2015_11_19', 'BR_R002_23KNR90_2019_08_19', 'BR_R002_23KNR90_2014_08_12', 'BR_R002_23KNR90_2015_11_12', 'BR_R002_23KNR90_2017_11_01', 'BR_R002_23KNR90_2018_10_10', 'BR_R002_23KNR90_2014_05_08', 'BR_R002_23KNR90_2020_10_08', 'BR_R002_23KNR90_2016_06_07', 'BR_R002_23KNR90_2021_05_20', 'BR_R002_23KNR90_2020_11_25', 'BR_R002_23KNR90_2020_07_04', 'BR_R002_23KNR90_2019_04_29', 'BR_R002_23KNR90_2021_05_11', 'BR_R002_23KNR90_2015_03_08', 'BR_R002_23KNR90_2016_11_05', 'BR_R002_23KNR90_2017_12_10', 'BR_R002_23KNR90_2020_05_01', 'BR_R002_23KNR90_2017_03_29', 'BR_R002_23KNR90_2014_09_13', 'BR_R002_23KNR90_2019_03_28', 'BR_R002_23KNR90_2020_05_17', 'BR_R002_23KNR90_2017_07_03', 'BR_R002_23KNR90_2016_08_26', 'BR_R002_23KNR90_2015_11_28', 'BR_R002_23KNR90_2021_08_08', 'BR_R002_23KNR90_2020_03_14', 'BR_R002_23KNR90_2016_09_02', 'BR_R002_23KNR90_2014_09_29', 'BR_R002_23KNR90_2015_03_01', 'BR_R002_23KNR90_2017_08_20', 'BR_R002_23KNR90_2015_08_31', 'BR_R002_23KNR90_2018_06_13', 'BR_R002_23KNR90_2018_05_12', 'BR_R002_23KNR90_2017_02_09', 'BR_R002_23KNR90_2019_05_31', 'BR_R002_23KNR90_2019_11_07', 'BR_R002_23KNR90_2019_05_22', 'BR_R002_23KNR90_2015_04_02', 'BR_R002_23KNR90_2018_10_26', 'BR_R002_23KNR90_2020_04_06', 'BR_R002_23KNQ99_2014_02_26', 'BR_R002_23KNQ99_2021_07_23', 'BR_R002_23KNQ99_2015_10_18', 'BR_R002_23KNQ99_2021_02_13', 'BR_R002_23KNQ99_2019_01_30', 'BR_R002_23KNQ99_2015_10_11', 'BR_R002_23KNQ99_2019_11_30', 'BR_R002_23KNQ99_2016_04_27', 'BR_R002_23KNQ99_2020_01_26', 'BR_R002_23KNQ99_2014_05_24', 'BR_R002_23KNQ99_2015_08_24', 'BR_R002_23KNQ99_2021_08_24', 'BR_R002_23KNQ99_2014_10_31', 'BR_R002_23KNQ99_2018_03_16', 'BR_R002_23KNQ99_2017_06_01', 'BR_R002_23KNQ99_2021_01_19', 'BR_R002_23KNQ99_2020_02_11', 'BR_R002_23KNQ99_2018_03_09', 'BR_R002_23KNQ99_2018_07_22', 'BR_R002_23KNQ99_2017_01_24', 'BR_R002_23KNQ99_2018_02_28', 'BR_R002_23KNQ99_2020_04_22', 'BR_R002_23KNQ99_2020_12_27', 'BR_R002_23KNQ99_2017_09_30', 'BR_R002_23KNQ99_2014_08_28', 'BR_R002_23KNQ99_2018_12_06', 'BR_R002_23KNQ99_2021_04_02', 'BR_R002_23KNQ99_2018_05_28', 'BR_R002_23KNQ99_2021_07_30', 'BR_R002_23KNQ99_2019_08_03', 'BR_R002_23KNQ99_2017_04_23', 'BR_R002_23KNQ99_2018_08_16', 'BR_R002_23KNQ99_2018_12_13', 'BR_R002_23KNQ99_2020_11_16', 'BR_R002_23KNQ99_2017_11_24', 'BR_R002_23KNQ99_2018_01_27', 'BR_R002_23KNQ99_2016_09_18', 'BR_R002_23KNQ99_2017_03_22', 'BR_R002_23KNQ99_2020_06_02', 'BR_R002_23KNQ99_2018_04_10', 'BR_R002_23KNQ99_2016_10_04', 'BR_R002_23KNQ99_2016_01_15', 'BR_R002_23KNQ99_2014_01_25', 'BR_R002_23KNQ99_2017_04_07', 'BR_R002_23KNQ99_2015_02_04', 'BR_R002_23KNQ99_2014_10_08', 'BR_R002_23KNQ99_2020_07_27', 'BR_R002_23KNQ99_2020_12_02', 'BR_R002_23KNQ99_2020_07_11', 'BR_R002_23KNQ99_2018_08_23', 'BR_R002_23KNQ99_2014_05_17', 'BR_R002_23KNQ99_2014_09_22', 'BR_R002_23KNQ99_2016_06_14', 'BR_R002_23KNQ99_2019_07_25', 'BR_R002_23KNQ99_2014_11_09', 'BR_R002_23KNQ99_2017_02_18', 'BR_R002_23KNQ99_2020_08_05', 'BR_R002_23KNQ99_2015_04_18', 'BR_R002_23KNQ99_2015_09_25', 'BR_R002_23KNQ99_2015_09_16', 'BR_R002_23KNQ99_2019_02_08', 'BR_R002_23KNQ99_2016_08_17', 'BR_R002_23KNQ99_2016_05_22', 'BR_R002_23KNQ99_2015_10_27', 'BR_R002_23KNQ99_2016_03_26', 'BR_R002_23KNQ99_2015_05_27', 'BR_R002_23KNQ99_2019_07_02', 'BR_R002_23KNQ99_2016_09_27', 'BR_R002_23KNQ99_2014_01_16', 'BR_R002_23KNQ99_2014_03_14', 'BR_R002_23KNQ99_2015_07_30', 'BR_R002_23KNQ99_2015_11_03', 'BR_R002_23KNQ99_2020_09_29', 'BR_R002_23KNQ99_2020_10_15', 'BR_R002_23KNQ99_2018_09_17', 'BR_R002_23KNQ99_2014_06_18', 'BR_R002_23KNQ99_2017_12_03', 'BR_R002_23KNQ99_2017_04_30', 'BR_R002_23KNQ99_2019_03_03', 'BR_R002_23KNQ99_2021_04_18', 'BR_R002_23KNQ99_2015_03_24', 'BR_R002_23KNQ99_2015_02_20', 'BR_R002_23KNQ99_2020_03_21', 'BR_R002_23KNQ99_2015_08_15', 'BR_R002_23KNQ99_2021_04_25', 'BR_R002_23KNQ99_2018_03_25', 'BR_R002_23KNQ99_2015_12_14', 'BR_R002_23KNQ99_2021_06_05', 'BR_R002_23KNQ99_2016_06_23', 'BR_R002_23KNQ99_2017_07_28', 'BR_R002_23KNQ99_2015_06_12', 'BR_R002_23KNQ99_2017_03_13', 'BR_R002_23KNQ99_2016_10_29', 'BR_R002_23KNQ99_2020_09_13', 'BR_R002_23KNQ99_2016_06_30', 'BR_R002_23KNQ99_2017_05_25', 'BR_R002_23KNQ99_2017_10_07', 'BR_R002_23KNQ99_2015_07_07', 'BR_R002_23KNQ99_2017_06_26', 'BR_R002_23KNQ99_2019_06_16', 'BR_R002_23KNQ99_2015_05_20', 'BR_R002_23KNQ99_2015_04_25', 'BR_R002_23KNQ99_2014_04_22', 'BR_R002_23KNQ99_2016_08_01', 'BR_R002_23KNQ99_2019_10_13', 'BR_R002_23KNQ99_2017_10_16', 'BR_R002_23KNQ99_2017_07_19', 'BR_R002_23KNQ99_2018_12_22', 'BR_R002_23KNQ99_2021_07_07', 'BR_R002_23KNQ99_2016_10_20', 'BR_R002_23KNQ99_2021_04_09', 'BR_R002_23KNQ99_2020_01_17', 'BR_R002_23KNQ99_2020_12_18', 'BR_R002_23KNQ99_2015_12_21', 'BR_R002_23KNQ99_2018_01_11', 'BR_R002_23KNQ99_2019_01_07', 'BR_R002_23KNQ99_2015_10_02', 'BR_R002_23KNQ99_2021_06_21', 'BR_R002_23KNQ99_2017_11_08', 'BR_R002_23KNQ99_2018_11_20', 'BR_R002_23KNQ99_2015_05_11', 'BR_R002_23KNQ99_2019_04_13', 'BR_R002_23KNQ99_2016_04_20', 'BR_R002_23KNQ99_2019_12_25', 'BR_R002_23KNQ99_2015_04_09', 'BR_R002_23KNQ99_2016_07_25', 'BR_R002_23KNQ99_2014_03_21', 'BR_R002_23KNQ99_2021_03_24', 'BR_R002_23KNQ99_2016_02_16', 'BR_R002_23KNQ99_2014_08_05', 'BR_R002_23KNQ99_2021_05_27', 'BR_R002_23KNQ99_2016_04_04', 'BR_R002_23KNQ99_2019_08_26', 'BR_R002_23KNQ99_2014_02_10', 'BR_R002_23KNQ99_2020_08_21', 'BR_R002_23KNQ99_2014_07_27', 'BR_R002_23KNQ99_2018_02_12', 'BR_R002_23KNQ99_2016_05_06', 'BR_R002_23KNQ99_2020_11_09', 'BR_R002_23KNQ99_2015_07_23', 'BR_R002_23KNQ99_2020_12_11', 'BR_R002_23KNQ99_2016_07_16', 'BR_R002_23KNQ99_2016_05_29', 'BR_R002_23KNQ99_2019_11_14', 'BR_R002_23KNQ99_2017_06_17', 'BR_R002_23KNQ99_2015_12_30', 'BR_R002_23KNQ99_2014_12_27', 'BR_R002_23KNQ99_2015_01_19', 'BR_R002_23KNQ99_2021_06_28', 'BR_R002_23KNQ99_2014_09_06', 'BR_R002_23KNQ99_2014_11_16', 'BR_R002_23KNQ99_2017_07_12', 'BR_R002_23KNQ99_2017_06_10', 'BR_R002_23KNQ99_2018_09_24', 'BR_R002_23KNQ99_2016_11_14', 'BR_R002_23KNQ99_2019_08_10', 'BR_R002_23KNQ99_2016_01_06', 'BR_R002_23KNQ99_2016_07_09', 'BR_R002_23KNQ99_2017_01_08', 'BR_R002_23KNQ99_2020_10_31', 'BR_R002_23KNQ99_2014_07_11', 'BR_R002_23KNQ99_2019_03_19', 'BR_R002_23KNQ99_2019_11_23', 'BR_R002_23KNQ99_2017_08_29', 'BR_R002_23KNQ99_2014_08_21', 'BR_R002_23KNQ99_2014_06_25', 'BR_R002_23KNQ99_2015_01_28', 'BR_R002_23KNQ99_2014_12_11', 'BR_R002_23KNQ99_2016_04_11', 'BR_R002_23KNQ99_2017_09_21', 'BR_R002_23KNQ99_2020_10_24', 'BR_R002_23KNQ99_2019_07_18', 'BR_R002_23KNQ99_2014_06_02', 'BR_R002_23KNQ99_2017_12_19', 'BR_R002_23KNQ99_2021_02_20', 'BR_R002_23KNQ99_2015_07_14', 'BR_R002_23KNQ99_2021_01_03', 'BR_R002_23KNQ99_2020_06_18', 'BR_R002_23KNQ99_2017_08_04', 'BR_R002_23KNQ99_2018_04_01', 'BR_R002_23KNQ99_2020_01_10', 'BR_R002_23KNQ99_2021_01_12', 'BR_R002_23KNQ99_2021_02_04', 'BR_R002_23KNQ99_2015_03_17', 'BR_R002_23KNQ99_2017_08_13', 'BR_R002_23KNQ99_2019_10_29', 'BR_R002_23KNQ99_2014_12_18', 'BR_R002_23KNQ99_2018_08_07', 'BR_R002_23KNQ99_2019_06_23', 'BR_R002_23KNQ99_2018_12_29', 'BR_R002_23KNQ99_2016_11_21', 'BR_R002_23KNQ99_2019_01_23', 'BR_R002_23KNQ99_2014_12_02', 'BR_R002_23KNQ99_2018_07_31', 'BR_R002_23KNQ99_2021_03_08', 'BR_R002_23KNQ99_2020_06_25', 'BR_R002_23KNQ99_2015_02_13', 'BR_R002_23KNQ99_2015_06_28', 'BR_R002_23KNQ99_2014_07_20', 'BR_R002_23KNQ99_2017_05_09', 'BR_R002_23KNQ99_2018_06_29', 'BR_R002_23KNQ99_2018_02_21', 'BR_R002_23KNQ99_2021_03_17', 'BR_R002_23KNQ99_2019_02_24', 'BR_R002_23KNQ99_2018_06_20', 'BR_R002_23KNQ99_2017_04_14', 'BR_R002_23KNQ99_2019_09_27', 'BR_R002_23KNQ99_2014_04_06', 'BR_R002_23KNQ99_2014_11_25', 'BR_R002_23KNQ99_2018_05_03', 'BR_R002_23KNQ99_2020_03_05', 'BR_R002_23KNQ99_2019_09_04', 'BR_R002_23KNQ99_2017_01_01', 'BR_R002_23KNQ99_2015_08_08', 'BR_R002_23KNQ99_2018_06_04', 'BR_R002_23KNQ99_2016_11_30', 'BR_R002_23KNQ99_2014_05_01', 'BR_R002_23KNQ99_2016_08_10', 'BR_R002_23KNQ99_2020_09_22', 'BR_R002_23KNQ99_2015_01_12', 'BR_R002_23KNQ99_2016_02_23', 'BR_R002_23KNQ99_2016_09_11', 'BR_R002_23KNQ99_2018_09_01', 'BR_R002_23KNQ99_2014_10_24', 'BR_R002_23KNQ99_2019_03_12', 'BR_R002_23KNQ99_2016_12_07', 'BR_R002_23KNQ99_2020_02_27', 'BR_R002_23KNQ99_2019_04_20', 'BR_R002_23KNQ99_2018_01_04', 'BR_R002_23KNQ99_2021_01_28', 'BR_R002_23KNQ99_2017_09_14', 'BR_R002_23KNQ99_2016_10_13', 'BR_R002_23KNQ99_2019_07_09', 'BR_R002_23KNQ99_2019_05_15', 'BR_R002_23KNQ99_2018_01_20', 'BR_R002_23KNQ99_2021_05_04', 'BR_R002_23KNQ99_2018_11_11', 'BR_R002_23KNQ99_2019_10_22', 'BR_R002_23KNQ99_2017_03_06', 'BR_R002_23KNQ99_2019_09_20', 'BR_R002_23KNQ99_2017_01_17', 'BR_R002_23KNQ99_2020_07_20', 'BR_R002_23KNQ99_2017_11_17', 'BR_R002_23KNQ99_2020_01_01', 'BR_R002_23KNQ99_2021_07_14', 'BR_R002_23KNQ99_2014_02_01', 'BR_R002_23KNQ99_2021_08_15', 'BR_R002_23KNQ99_2016_02_07', 'BR_R002_23KNQ99_2019_05_06', 'BR_R002_23KNQ99_2018_11_27', 'BR_R002_23KNQ99_2019_04_04', 'BR_R002_23KNQ99_2017_02_25', 'BR_R002_23KNQ99_2018_09_08', 'BR_R002_23KNQ99_2015_12_05', 'BR_R002_23KNQ99_2016_12_16', 'BR_R002_23KNQ99_2017_12_26', 'BR_R002_23KNQ99_2018_04_17', 'BR_R002_23KNQ99_2014_06_09', 'BR_R002_23KNQ99_2019_12_16', 'BR_R002_23KNQ99_2018_02_05', 'BR_R002_23KNQ99_2018_11_04', 'BR_R002_23KNQ99_2020_09_06', 'BR_R002_23KNQ99_2016_01_31', 'BR_R002_23KNQ99_2014_07_04', 'BR_R002_23KNQ99_2016_03_03', 'BR_R002_23KNQ99_2021_06_12', 'BR_R002_23KNQ99_2019_06_07', 'BR_R002_23KNQ99_2017_10_23', 'BR_R002_23KNQ99_2017_09_05', 'BR_R002_23KNQ99_2014_03_05', 'BR_R002_23KNQ99_2014_01_09', 'BR_R002_23KNQ99_2015_06_05', 'BR_R002_23KNQ99_2020_08_28', 'BR_R002_23KNQ99_2019_01_14', 'BR_R002_23KNQ99_2018_07_15', 'BR_R002_23KNQ99_2020_04_15', 'BR_R002_23KNQ99_2020_08_12', 'BR_R002_23KNQ99_2017_05_16', 'BR_R002_23KNQ99_2018_05_19', 'BR_R002_23KNQ99_2020_02_18', 'BR_R002_23KNQ99_2020_05_24', 'BR_R002_23KNQ99_2019_09_11', 'BR_R002_23KNQ99_2019_12_09', 'BR_R002_23KNQ99_2018_07_06', 'BR_R002_23KNQ99_2018_10_03', 'BR_R002_23KNQ99_2017_02_02', 'BR_R002_23KNQ99_2018_04_26', 'BR_R002_23KNQ99_2015_09_09', 'BR_R002_23KNQ99_2016_05_13', 'BR_R002_23KNQ99_2020_02_02', 'BR_R002_23KNQ99_2016_01_22', 'BR_R002_23KNQ99_2014_10_15', 'BR_R002_23KNQ99_2018_10_19', 'BR_R002_23KNQ99_2016_12_23', 'BR_R002_23KNQ99_2020_06_09', 'BR_R002_23KNQ99_2021_03_01', 'BR_R002_23KNQ99_2019_02_15', 'BR_R002_23KNQ99_2016_03_10', 'BR_R002_23KNQ99_2020_03_30', 'BR_R002_23KNQ99_2019_10_06', 'BR_R002_23KNQ99_2015_01_03', 'BR_R002_23KNQ99_2015_06_21', 'BR_R002_23KNQ99_2016_03_19', 'BR_R002_23KNQ99_2014_02_17', 'BR_R002_23KNQ99_2015_05_04', 'BR_R002_23KNQ99_2015_11_19', 'BR_R002_23KNQ99_2019_08_19', 'BR_R002_23KNQ99_2014_08_12', 'BR_R002_23KNQ99_2015_11_12', 'BR_R002_23KNQ99_2017_11_01', 'BR_R002_23KNQ99_2018_10_10', 'BR_R002_23KNQ99_2014_05_08', 'BR_R002_23KNQ99_2020_10_08', 'BR_R002_23KNQ99_2016_06_07', 'BR_R002_23KNQ99_2021_05_20', 'BR_R002_23KNQ99_2020_11_25', 'BR_R002_23KNQ99_2020_07_04', 'BR_R002_23KNQ99_2019_04_29', 'BR_R002_23KNQ99_2021_05_11', 'BR_R002_23KNQ99_2015_03_08', 'BR_R002_23KNQ99_2016_11_05', 'BR_R002_23KNQ99_2017_12_10', 'BR_R002_23KNQ99_2020_05_01', 'BR_R002_23KNQ99_2017_03_29', 'BR_R002_23KNQ99_2014_09_13', 'BR_R002_23KNQ99_2019_03_28', 'BR_R002_23KNQ99_2020_05_17', 'BR_R002_23KNQ99_2017_07_03', 'BR_R002_23KNQ99_2016_08_26', 'BR_R002_23KNQ99_2015_11_28', 'BR_R002_23KNQ99_2021_08_08', 'BR_R002_23KNQ99_2020_03_14', 'BR_R002_23KNQ99_2016_09_02', 'BR_R002_23KNQ99_2014_09_29', 'BR_R002_23KNQ99_2015_03_01', 'BR_R002_23KNQ99_2017_08_20', 'BR_R002_23KNQ99_2015_08_31', 'BR_R002_23KNQ99_2018_06_13', 'BR_R002_23KNQ99_2018_05_12', 'BR_R002_23KNQ99_2017_02_09', 'BR_R002_23KNQ99_2019_05_31', 'BR_R002_23KNQ99_2019_11_07', 'BR_R002_23KNQ99_2019_05_22', 'BR_R002_23KNQ99_2015_04_02', 'BR_R002_23KNQ99_2018_10_26', 'BR_R002_23KNQ99_2020_04_06', 'BR_R002_23KPR00_2014_02_26', 'BR_R002_23KPR00_2021_07_23', 'BR_R002_23KPR00_2015_10_18', 'BR_R002_23KPR00_2021_02_13', 'BR_R002_23KPR00_2019_01_30', 'BR_R002_23KPR00_2015_10_11', 'BR_R002_23KPR00_2019_11_30', 'BR_R002_23KPR00_2016_04_27', 'BR_R002_23KPR00_2020_01_26', 'BR_R002_23KPR00_2014_05_24', 'BR_R002_23KPR00_2015_08_24', 'BR_R002_23KPR00_2021_08_24', 'BR_R002_23KPR00_2014_10_31', 'BR_R002_23KPR00_2018_03_16', 'BR_R002_23KPR00_2017_06_01', 'BR_R002_23KPR00_2021_01_19', 'BR_R002_23KPR00_2020_02_11', 'BR_R002_23KPR00_2018_03_09', 'BR_R002_23KPR00_2018_07_22', 'BR_R002_23KPR00_2017_01_24', 'BR_R002_23KPR00_2018_02_28', 'BR_R002_23KPR00_2020_04_22', 'BR_R002_23KPR00_2020_12_27', 'BR_R002_23KPR00_2017_09_30', 'BR_R002_23KPR00_2014_08_28', 'BR_R002_23KPR00_2018_12_06', 'BR_R002_23KPR00_2021_04_02', 'BR_R002_23KPR00_2018_05_28', 'BR_R002_23KPR00_2021_07_30', 'BR_R002_23KPR00_2019_08_03', 'BR_R002_23KPR00_2017_04_23', 'BR_R002_23KPR00_2018_08_16', 'BR_R002_23KPR00_2018_12_13', 'BR_R002_23KPR00_2020_11_16', 'BR_R002_23KPR00_2017_11_24', 'BR_R002_23KPR00_2018_01_27', 'BR_R002_23KPR00_2016_09_18', 'BR_R002_23KPR00_2017_03_22', 'BR_R002_23KPR00_2020_06_02', 'BR_R002_23KPR00_2018_04_10', 'BR_R002_23KPR00_2016_10_04', 'BR_R002_23KPR00_2016_01_15', 'BR_R002_23KPR00_2014_01_25', 'BR_R002_23KPR00_2017_04_07', 'BR_R002_23KPR00_2015_02_04', 'BR_R002_23KPR00_2014_10_08', 'BR_R002_23KPR00_2020_07_27', 'BR_R002_23KPR00_2020_12_02', 'BR_R002_23KPR00_2020_07_11', 'BR_R002_23KPR00_2018_08_23', 'BR_R002_23KPR00_2014_05_17', 'BR_R002_23KPR00_2014_09_22', 'BR_R002_23KPR00_2016_06_14', 'BR_R002_23KPR00_2019_07_25', 'BR_R002_23KPR00_2014_11_09', 'BR_R002_23KPR00_2017_02_18', 'BR_R002_23KPR00_2020_08_05', 'BR_R002_23KPR00_2015_04_18', 'BR_R002_23KPR00_2015_09_25', 'BR_R002_23KPR00_2015_09_16', 'BR_R002_23KPR00_2019_02_08', 'BR_R002_23KPR00_2016_08_17', 'BR_R002_23KPR00_2016_05_22', 'BR_R002_23KPR00_2015_10_27', 'BR_R002_23KPR00_2016_03_26', 'BR_R002_23KPR00_2015_05_27', 'BR_R002_23KPR00_2019_07_02', 'BR_R002_23KPR00_2016_09_27', 'BR_R002_23KPR00_2014_01_16', 'BR_R002_23KPR00_2014_03_14', 'BR_R002_23KPR00_2015_07_30', 'BR_R002_23KPR00_2015_11_03', 'BR_R002_23KPR00_2020_09_29', 'BR_R002_23KPR00_2020_10_15', 'BR_R002_23KPR00_2018_09_17', 'BR_R002_23KPR00_2014_06_18', 'BR_R002_23KPR00_2017_12_03', 'BR_R002_23KPR00_2017_04_30', 'BR_R002_23KPR00_2019_03_03', 'BR_R002_23KPR00_2021_04_18', 'BR_R002_23KPR00_2015_03_24', 'BR_R002_23KPR00_2015_02_20', 'BR_R002_23KPR00_2020_03_21', 'BR_R002_23KPR00_2015_08_15', 'BR_R002_23KPR00_2021_04_25', 'BR_R002_23KPR00_2018_03_25', 'BR_R002_23KPR00_2015_12_14', 'BR_R002_23KPR00_2021_06_05', 'BR_R002_23KPR00_2016_06_23', 'BR_R002_23KPR00_2017_07_28', 'BR_R002_23KPR00_2015_06_12', 'BR_R002_23KPR00_2017_03_13', 'BR_R002_23KPR00_2016_10_29', 'BR_R002_23KPR00_2020_09_13', 'BR_R002_23KPR00_2016_06_30', 'BR_R002_23KPR00_2017_05_25', 'BR_R002_23KPR00_2017_10_07', 'BR_R002_23KPR00_2015_07_07', 'BR_R002_23KPR00_2017_06_26', 'BR_R002_23KPR00_2019_06_16', 'BR_R002_23KPR00_2015_05_20', 'BR_R002_23KPR00_2015_04_25', 'BR_R002_23KPR00_2014_04_22', 'BR_R002_23KPR00_2016_08_01', 'BR_R002_23KPR00_2019_10_13', 'BR_R002_23KPR00_2017_10_16', 'BR_R002_23KPR00_2017_07_19', 'BR_R002_23KPR00_2018_12_22', 'BR_R002_23KPR00_2021_07_07', 'BR_R002_23KPR00_2016_10_20', 'BR_R002_23KPR00_2021_04_09', 'BR_R002_23KPR00_2020_01_17', 'BR_R002_23KPR00_2020_12_18', 'BR_R002_23KPR00_2015_12_21', 'BR_R002_23KPR00_2018_01_11', 'BR_R002_23KPR00_2019_01_07', 'BR_R002_23KPR00_2015_10_02', 'BR_R002_23KPR00_2021_06_21', 'BR_R002_23KPR00_2017_11_08', 'BR_R002_23KPR00_2018_11_20', 'BR_R002_23KPR00_2015_05_11', 'BR_R002_23KPR00_2019_04_13', 'BR_R002_23KPR00_2016_04_20', 'BR_R002_23KPR00_2019_12_25', 'BR_R002_23KPR00_2015_04_09', 'BR_R002_23KPR00_2016_07_25', 'BR_R002_23KPR00_2014_03_21', 'BR_R002_23KPR00_2021_03_24', 'BR_R002_23KPR00_2016_02_16', 'BR_R002_23KPR00_2014_08_05', 'BR_R002_23KPR00_2021_05_27', 'BR_R002_23KPR00_2016_04_04', 'BR_R002_23KPR00_2019_08_26', 'BR_R002_23KPR00_2014_02_10', 'BR_R002_23KPR00_2020_08_21', 'BR_R002_23KPR00_2014_07_27', 'BR_R002_23KPR00_2018_02_12', 'BR_R002_23KPR00_2016_05_06', 'BR_R002_23KPR00_2020_11_09', 'BR_R002_23KPR00_2015_07_23', 'BR_R002_23KPR00_2020_12_11', 'BR_R002_23KPR00_2016_07_16', 'BR_R002_23KPR00_2016_05_29', 'BR_R002_23KPR00_2019_11_14', 'BR_R002_23KPR00_2017_06_17', 'BR_R002_23KPR00_2015_12_30', 'BR_R002_23KPR00_2014_12_27', 'BR_R002_23KPR00_2015_01_19', 'BR_R002_23KPR00_2021_06_28', 'BR_R002_23KPR00_2014_09_06', 'BR_R002_23KPR00_2014_11_16', 'BR_R002_23KPR00_2017_07_12', 'BR_R002_23KPR00_2017_06_10', 'BR_R002_23KPR00_2018_09_24', 'BR_R002_23KPR00_2016_11_14', 'BR_R002_23KPR00_2019_08_10', 'BR_R002_23KPR00_2016_01_06', 'BR_R002_23KPR00_2016_07_09', 'BR_R002_23KPR00_2017_01_08', 'BR_R002_23KPR00_2020_10_31', 'BR_R002_23KPR00_2014_07_11', 'BR_R002_23KPR00_2019_03_19', 'BR_R002_23KPR00_2019_11_23', 'BR_R002_23KPR00_2017_08_29', 'BR_R002_23KPR00_2014_08_21', 'BR_R002_23KPR00_2014_06_25', 'BR_R002_23KPR00_2015_01_28', 'BR_R002_23KPR00_2014_12_11', 'BR_R002_23KPR00_2016_04_11', 'BR_R002_23KPR00_2017_09_21', 'BR_R002_23KPR00_2020_10_24', 'BR_R002_23KPR00_2019_07_18', 'BR_R002_23KPR00_2014_06_02', 'BR_R002_23KPR00_2017_12_19', 'BR_R002_23KPR00_2021_02_20', 'BR_R002_23KPR00_2015_07_14', 'BR_R002_23KPR00_2021_01_03', 'BR_R002_23KPR00_2020_06_18', 'BR_R002_23KPR00_2017_08_04', 'BR_R002_23KPR00_2018_04_01', 'BR_R002_23KPR00_2020_01_10', 'BR_R002_23KPR00_2021_01_12', 'BR_R002_23KPR00_2021_02_04', 'BR_R002_23KPR00_2015_03_17', 'BR_R002_23KPR00_2017_08_13', 'BR_R002_23KPR00_2019_10_29', 'BR_R002_23KPR00_2014_12_18', 'BR_R002_23KPR00_2018_08_07', 'BR_R002_23KPR00_2019_06_23', 'BR_R002_23KPR00_2018_12_29', 'BR_R002_23KPR00_2016_11_21', 'BR_R002_23KPR00_2019_01_23', 'BR_R002_23KPR00_2014_12_02', 'BR_R002_23KPR00_2018_07_31', 'BR_R002_23KPR00_2021_03_08', 'BR_R002_23KPR00_2020_06_25', 'BR_R002_23KPR00_2015_02_13', 'BR_R002_23KPR00_2015_06_28', 'BR_R002_23KPR00_2014_07_20', 'BR_R002_23KPR00_2017_05_09', 'BR_R002_23KPR00_2018_06_29', 'BR_R002_23KPR00_2018_02_21', 'BR_R002_23KPR00_2021_03_17', 'BR_R002_23KPR00_2019_02_24', 'BR_R002_23KPR00_2018_06_20', 'BR_R002_23KPR00_2017_04_14', 'BR_R002_23KPR00_2019_09_27', 'BR_R002_23KPR00_2014_04_06', 'BR_R002_23KPR00_2014_11_25', 'BR_R002_23KPR00_2018_05_03', 'BR_R002_23KPR00_2020_03_05', 'BR_R002_23KPR00_2019_09_04', 'BR_R002_23KPR00_2017_01_01', 'BR_R002_23KPR00_2015_08_08', 'BR_R002_23KPR00_2018_06_04', 'BR_R002_23KPR00_2016_11_30', 'BR_R002_23KPR00_2014_05_01', 'BR_R002_23KPR00_2016_08_10', 'BR_R002_23KPR00_2020_09_22', 'BR_R002_23KPR00_2015_01_12', 'BR_R002_23KPR00_2016_02_23', 'BR_R002_23KPR00_2016_09_11', 'BR_R002_23KPR00_2018_09_01', 'BR_R002_23KPR00_2014_10_24', 'BR_R002_23KPR00_2019_03_12', 'BR_R002_23KPR00_2016_12_07', 'BR_R002_23KPR00_2020_02_27', 'BR_R002_23KPR00_2019_04_20', 'BR_R002_23KPR00_2018_01_04', 'BR_R002_23KPR00_2021_01_28', 'BR_R002_23KPR00_2017_09_14', 'BR_R002_23KPR00_2016_10_13', 'BR_R002_23KPR00_2019_07_09', 'BR_R002_23KPR00_2019_05_15', 'BR_R002_23KPR00_2018_01_20', 'BR_R002_23KPR00_2021_05_04', 'BR_R002_23KPR00_2018_11_11', 'BR_R002_23KPR00_2019_10_22', 'BR_R002_23KPR00_2017_03_06', 'BR_R002_23KPR00_2019_09_20', 'BR_R002_23KPR00_2017_01_17', 'BR_R002_23KPR00_2020_07_20', 'BR_R002_23KPR00_2017_11_17', 'BR_R002_23KPR00_2020_01_01', 'BR_R002_23KPR00_2021_07_14', 'BR_R002_23KPR00_2014_02_01', 'BR_R002_23KPR00_2021_08_15', 'BR_R002_23KPR00_2016_02_07', 'BR_R002_23KPR00_2019_05_06', 'BR_R002_23KPR00_2018_11_27', 'BR_R002_23KPR00_2019_04_04', 'BR_R002_23KPR00_2017_02_25', 'BR_R002_23KPR00_2018_09_08', 'BR_R002_23KPR00_2015_12_05', 'BR_R002_23KPR00_2016_12_16', 'BR_R002_23KPR00_2017_12_26', 'BR_R002_23KPR00_2018_04_17', 'BR_R002_23KPR00_2014_06_09', 'BR_R002_23KPR00_2019_12_16', 'BR_R002_23KPR00_2018_02_05', 'BR_R002_23KPR00_2018_11_04', 'BR_R002_23KPR00_2020_09_06', 'BR_R002_23KPR00_2016_01_31', 'BR_R002_23KPR00_2014_07_04', 'BR_R002_23KPR00_2016_03_03', 'BR_R002_23KPR00_2021_06_12', 'BR_R002_23KPR00_2019_06_07', 'BR_R002_23KPR00_2017_10_23', 'BR_R002_23KPR00_2017_09_05', 'BR_R002_23KPR00_2014_03_05', 'BR_R002_23KPR00_2014_01_09', 'BR_R002_23KPR00_2015_06_05', 'BR_R002_23KPR00_2020_08_28', 'BR_R002_23KPR00_2019_01_14', 'BR_R002_23KPR00_2018_07_15', 'BR_R002_23KPR00_2020_04_15', 'BR_R002_23KPR00_2020_08_12', 'BR_R002_23KPR00_2017_05_16', 'BR_R002_23KPR00_2018_05_19', 'BR_R002_23KPR00_2020_02_18', 'BR_R002_23KPR00_2020_05_24', 'BR_R002_23KPR00_2019_09_11', 'BR_R002_23KPR00_2019_12_09', 'BR_R002_23KPR00_2018_07_06', 'BR_R002_23KPR00_2018_10_03', 'BR_R002_23KPR00_2017_02_02', 'BR_R002_23KPR00_2018_04_26', 'BR_R002_23KPR00_2015_09_09', 'BR_R002_23KPR00_2016_05_13', 'BR_R002_23KPR00_2020_02_02', 'BR_R002_23KPR00_2016_01_22', 'BR_R002_23KPR00_2014_10_15', 'BR_R002_23KPR00_2018_10_19', 'BR_R002_23KPR00_2016_12_23', 'BR_R002_23KPR00_2020_06_09', 'BR_R002_23KPR00_2021_03_01', 'BR_R002_23KPR00_2019_02_15', 'BR_R002_23KPR00_2016_03_10', 'BR_R002_23KPR00_2020_03_30', 'BR_R002_23KPR00_2019_10_06', 'BR_R002_23KPR00_2015_01_03', 'BR_R002_23KPR00_2015_06_21', 'BR_R002_23KPR00_2016_03_19', 'BR_R002_23KPR00_2014_02_17', 'BR_R002_23KPR00_2015_05_04', 'BR_R002_23KPR00_2015_11_19', 'BR_R002_23KPR00_2019_08_19', 'BR_R002_23KPR00_2014_08_12', 'BR_R002_23KPR00_2015_11_12', 'BR_R002_23KPR00_2017_11_01', 'BR_R002_23KPR00_2018_10_10', 'BR_R002_23KPR00_2014_05_08', 'BR_R002_23KPR00_2020_10_08', 'BR_R002_23KPR00_2016_06_07', 'BR_R002_23KPR00_2021_05_20', 'BR_R002_23KPR00_2020_11_25', 'BR_R002_23KPR00_2020_07_04', 'BR_R002_23KPR00_2019_04_29', 'BR_R002_23KPR00_2021_05_11', 'BR_R002_23KPR00_2015_03_08', 'BR_R002_23KPR00_2016_11_05', 'BR_R002_23KPR00_2017_12_10', 'BR_R002_23KPR00_2020_05_01', 'BR_R002_23KPR00_2017_03_29', 'BR_R002_23KPR00_2014_09_13', 'BR_R002_23KPR00_2019_03_28', 'BR_R002_23KPR00_2020_05_17', 'BR_R002_23KPR00_2017_07_03', 'BR_R002_23KPR00_2016_08_26', 'BR_R002_23KPR00_2015_11_28', 'BR_R002_23KPR00_2021_08_08', 'BR_R002_23KPR00_2020_03_14', 'BR_R002_23KPR00_2016_09_02', 'BR_R002_23KPR00_2014_09_29', 'BR_R002_23KPR00_2015_03_01', 'BR_R002_23KPR00_2017_08_20', 'BR_R002_23KPR00_2015_08_31', 'BR_R002_23KPR00_2018_06_13', 'BR_R002_23KPR00_2018_05_12', 'BR_R002_23KPR00_2017_02_09', 'BR_R002_23KPR00_2019_05_31', 'BR_R002_23KPR00_2019_11_07', 'BR_R002_23KPR00_2019_05_22', 'BR_R002_23KPR00_2015_04_02', 'BR_R002_23KPR00_2018_10_26', 'BR_R002_23KPR00_2020_04_06', 'BR_R002_23KPQ09_2014_02_26', 'BR_R002_23KPQ09_2021_07_23', 'BR_R002_23KPQ09_2015_10_18', 'BR_R002_23KPQ09_2021_02_13', 'BR_R002_23KPQ09_2019_01_30', 'BR_R002_23KPQ09_2015_10_11', 'BR_R002_23KPQ09_2019_11_30', 'BR_R002_23KPQ09_2016_04_27', 'BR_R002_23KPQ09_2020_01_26', 'BR_R002_23KPQ09_2014_05_24', 'BR_R002_23KPQ09_2015_08_24', 'BR_R002_23KPQ09_2021_08_24', 'BR_R002_23KPQ09_2014_10_31', 'BR_R002_23KPQ09_2018_03_16', 'BR_R002_23KPQ09_2017_06_01', 'BR_R002_23KPQ09_2021_01_19', 'BR_R002_23KPQ09_2020_02_11', 'BR_R002_23KPQ09_2018_03_09', 'BR_R002_23KPQ09_2018_07_22', 'BR_R002_23KPQ09_2017_01_24', 'BR_R002_23KPQ09_2018_02_28', 'BR_R002_23KPQ09_2020_04_22', 'BR_R002_23KPQ09_2020_12_27', 'BR_R002_23KPQ09_2017_09_30', 'BR_R002_23KPQ09_2014_08_28', 'BR_R002_23KPQ09_2018_12_06', 'BR_R002_23KPQ09_2021_04_02', 'BR_R002_23KPQ09_2018_05_28', 'BR_R002_23KPQ09_2021_07_30', 'BR_R002_23KPQ09_2019_08_03', 'BR_R002_23KPQ09_2017_04_23', 'BR_R002_23KPQ09_2018_08_16', 'BR_R002_23KPQ09_2018_12_13', 'BR_R002_23KPQ09_2020_11_16', 'BR_R002_23KPQ09_2017_11_24', 'BR_R002_23KPQ09_2018_01_27', 'BR_R002_23KPQ09_2016_09_18', 'BR_R002_23KPQ09_2017_03_22', 'BR_R002_23KPQ09_2020_06_02', 'BR_R002_23KPQ09_2018_04_10', 'BR_R002_23KPQ09_2016_10_04', 'BR_R002_23KPQ09_2016_01_15', 'BR_R002_23KPQ09_2014_01_25', 'BR_R002_23KPQ09_2017_04_07', 'BR_R002_23KPQ09_2015_02_04', 'BR_R002_23KPQ09_2014_10_08', 'BR_R002_23KPQ09_2020_07_27', 'BR_R002_23KPQ09_2020_12_02', 'BR_R002_23KPQ09_2020_07_11', 'BR_R002_23KPQ09_2018_08_23', 'BR_R002_23KPQ09_2014_05_17', 'BR_R002_23KPQ09_2014_09_22', 'BR_R002_23KPQ09_2016_06_14', 'BR_R002_23KPQ09_2019_07_25', 'BR_R002_23KPQ09_2014_11_09', 'BR_R002_23KPQ09_2017_02_18', 'BR_R002_23KPQ09_2020_08_05', 'BR_R002_23KPQ09_2015_04_18', 'BR_R002_23KPQ09_2015_09_25', 'BR_R002_23KPQ09_2015_09_16', 'BR_R002_23KPQ09_2019_02_08', 'BR_R002_23KPQ09_2016_08_17', 'BR_R002_23KPQ09_2016_05_22', 'BR_R002_23KPQ09_2015_10_27', 'BR_R002_23KPQ09_2016_03_26', 'BR_R002_23KPQ09_2015_05_27', 'BR_R002_23KPQ09_2019_07_02', 'BR_R002_23KPQ09_2016_09_27', 'BR_R002_23KPQ09_2014_01_16', 'BR_R002_23KPQ09_2014_03_14', 'BR_R002_23KPQ09_2015_07_30', 'BR_R002_23KPQ09_2015_11_03', 'BR_R002_23KPQ09_2020_09_29', 'BR_R002_23KPQ09_2020_10_15', 'BR_R002_23KPQ09_2018_09_17', 'BR_R002_23KPQ09_2014_06_18', 'BR_R002_23KPQ09_2017_12_03', 'BR_R002_23KPQ09_2017_04_30', 'BR_R002_23KPQ09_2019_03_03', 'BR_R002_23KPQ09_2021_04_18', 'BR_R002_23KPQ09_2015_03_24', 'BR_R002_23KPQ09_2015_02_20', 'BR_R002_23KPQ09_2020_03_21', 'BR_R002_23KPQ09_2015_08_15', 'BR_R002_23KPQ09_2021_04_25', 'BR_R002_23KPQ09_2018_03_25', 'BR_R002_23KPQ09_2015_12_14', 'BR_R002_23KPQ09_2021_06_05', 'BR_R002_23KPQ09_2016_06_23', 'BR_R002_23KPQ09_2017_07_28', 'BR_R002_23KPQ09_2015_06_12', 'BR_R002_23KPQ09_2017_03_13', 'BR_R002_23KPQ09_2016_10_29', 'BR_R002_23KPQ09_2020_09_13', 'BR_R002_23KPQ09_2016_06_30', 'BR_R002_23KPQ09_2017_05_25', 'BR_R002_23KPQ09_2017_10_07', 'BR_R002_23KPQ09_2015_07_07', 'BR_R002_23KPQ09_2017_06_26', 'BR_R002_23KPQ09_2019_06_16', 'BR_R002_23KPQ09_2015_05_20', 'BR_R002_23KPQ09_2015_04_25', 'BR_R002_23KPQ09_2014_04_22', 'BR_R002_23KPQ09_2016_08_01', 'BR_R002_23KPQ09_2019_10_13', 'BR_R002_23KPQ09_2017_10_16', 'BR_R002_23KPQ09_2017_07_19', 'BR_R002_23KPQ09_2018_12_22', 'BR_R002_23KPQ09_2021_07_07', 'BR_R002_23KPQ09_2016_10_20', 'BR_R002_23KPQ09_2021_04_09', 'BR_R002_23KPQ09_2020_01_17', 'BR_R002_23KPQ09_2020_12_18', 'BR_R002_23KPQ09_2015_12_21', 'BR_R002_23KPQ09_2018_01_11', 'BR_R002_23KPQ09_2019_01_07', 'BR_R002_23KPQ09_2015_10_02', 'BR_R002_23KPQ09_2021_06_21', 'BR_R002_23KPQ09_2017_11_08', 'BR_R002_23KPQ09_2018_11_20', 'BR_R002_23KPQ09_2015_05_11', 'BR_R002_23KPQ09_2019_04_13', 'BR_R002_23KPQ09_2016_04_20', 'BR_R002_23KPQ09_2019_12_25', 'BR_R002_23KPQ09_2015_04_09', 'BR_R002_23KPQ09_2016_07_25', 'BR_R002_23KPQ09_2014_03_21', 'BR_R002_23KPQ09_2021_03_24', 'BR_R002_23KPQ09_2016_02_16', 'BR_R002_23KPQ09_2014_08_05', 'BR_R002_23KPQ09_2021_05_27', 'BR_R002_23KPQ09_2016_04_04', 'BR_R002_23KPQ09_2019_08_26', 'BR_R002_23KPQ09_2014_02_10', 'BR_R002_23KPQ09_2020_08_21', 'BR_R002_23KPQ09_2014_07_27', 'BR_R002_23KPQ09_2018_02_12', 'BR_R002_23KPQ09_2016_05_06', 'BR_R002_23KPQ09_2020_11_09', 'BR_R002_23KPQ09_2015_07_23', 'BR_R002_23KPQ09_2020_12_11', 'BR_R002_23KPQ09_2016_07_16', 'BR_R002_23KPQ09_2016_05_29', 'BR_R002_23KPQ09_2019_11_14', 'BR_R002_23KPQ09_2017_06_17', 'BR_R002_23KPQ09_2015_12_30', 'BR_R002_23KPQ09_2014_12_27', 'BR_R002_23KPQ09_2015_01_19', 'BR_R002_23KPQ09_2021_06_28', 'BR_R002_23KPQ09_2014_09_06', 'BR_R002_23KPQ09_2014_11_16', 'BR_R002_23KPQ09_2017_07_12', 'BR_R002_23KPQ09_2017_06_10', 'BR_R002_23KPQ09_2018_09_24', 'BR_R002_23KPQ09_2016_11_14', 'BR_R002_23KPQ09_2019_08_10', 'BR_R002_23KPQ09_2016_01_06', 'BR_R002_23KPQ09_2016_07_09', 'BR_R002_23KPQ09_2017_01_08', 'BR_R002_23KPQ09_2020_10_31', 'BR_R002_23KPQ09_2014_07_11', 'BR_R002_23KPQ09_2019_03_19', 'BR_R002_23KPQ09_2019_11_23', 'BR_R002_23KPQ09_2017_08_29', 'BR_R002_23KPQ09_2014_08_21', 'BR_R002_23KPQ09_2014_06_25', 'BR_R002_23KPQ09_2015_01_28', 'BR_R002_23KPQ09_2014_12_11', 'BR_R002_23KPQ09_2016_04_11', 'BR_R002_23KPQ09_2017_09_21', 'BR_R002_23KPQ09_2020_10_24', 'BR_R002_23KPQ09_2019_07_18', 'BR_R002_23KPQ09_2014_06_02', 'BR_R002_23KPQ09_2017_12_19', 'BR_R002_23KPQ09_2021_02_20', 'BR_R002_23KPQ09_2015_07_14', 'BR_R002_23KPQ09_2021_01_03', 'BR_R002_23KPQ09_2020_06_18', 'BR_R002_23KPQ09_2017_08_04', 'BR_R002_23KPQ09_2018_04_01', 'BR_R002_23KPQ09_2020_01_10', 'BR_R002_23KPQ09_2021_01_12', 'BR_R002_23KPQ09_2021_02_04', 'BR_R002_23KPQ09_2015_03_17', 'BR_R002_23KPQ09_2017_08_13', 'BR_R002_23KPQ09_2019_10_29', 'BR_R002_23KPQ09_2014_12_18', 'BR_R002_23KPQ09_2018_08_07', 'BR_R002_23KPQ09_2019_06_23', 'BR_R002_23KPQ09_2018_12_29', 'BR_R002_23KPQ09_2016_11_21', 'BR_R002_23KPQ09_2019_01_23', 'BR_R002_23KPQ09_2014_12_02', 'BR_R002_23KPQ09_2018_07_31', 'BR_R002_23KPQ09_2021_03_08', 'BR_R002_23KPQ09_2020_06_25', 'BR_R002_23KPQ09_2015_02_13', 'BR_R002_23KPQ09_2015_06_28', 'BR_R002_23KPQ09_2014_07_20', 'BR_R002_23KPQ09_2017_05_09', 'BR_R002_23KPQ09_2018_06_29', 'BR_R002_23KPQ09_2018_02_21', 'BR_R002_23KPQ09_2021_03_17', 'BR_R002_23KPQ09_2019_02_24', 'BR_R002_23KPQ09_2018_06_20', 'BR_R002_23KPQ09_2017_04_14', 'BR_R002_23KPQ09_2019_09_27', 'BR_R002_23KPQ09_2014_04_06', 'BR_R002_23KPQ09_2014_11_25', 'BR_R002_23KPQ09_2018_05_03', 'BR_R002_23KPQ09_2020_03_05', 'BR_R002_23KPQ09_2019_09_04', 'BR_R002_23KPQ09_2017_01_01', 'BR_R002_23KPQ09_2015_08_08', 'BR_R002_23KPQ09_2018_06_04', 'BR_R002_23KPQ09_2016_11_30', 'BR_R002_23KPQ09_2014_05_01', 'BR_R002_23KPQ09_2016_08_10', 'BR_R002_23KPQ09_2020_09_22', 'BR_R002_23KPQ09_2015_01_12', 'BR_R002_23KPQ09_2016_02_23', 'BR_R002_23KPQ09_2016_09_11', 'BR_R002_23KPQ09_2018_09_01', 'BR_R002_23KPQ09_2014_10_24', 'BR_R002_23KPQ09_2019_03_12', 'BR_R002_23KPQ09_2016_12_07', 'BR_R002_23KPQ09_2020_02_27', 'BR_R002_23KPQ09_2019_04_20', 'BR_R002_23KPQ09_2018_01_04', 'BR_R002_23KPQ09_2021_01_28', 'BR_R002_23KPQ09_2017_09_14', 'BR_R002_23KPQ09_2016_10_13', 'BR_R002_23KPQ09_2019_07_09', 'BR_R002_23KPQ09_2019_05_15', 'BR_R002_23KPQ09_2018_01_20', 'BR_R002_23KPQ09_2021_05_04', 'BR_R002_23KPQ09_2018_11_11', 'BR_R002_23KPQ09_2019_10_22', 'BR_R002_23KPQ09_2017_03_06', 'BR_R002_23KPQ09_2019_09_20', 'BR_R002_23KPQ09_2017_01_17', 'BR_R002_23KPQ09_2020_07_20', 'BR_R002_23KPQ09_2017_11_17', 'BR_R002_23KPQ09_2020_01_01', 'BR_R002_23KPQ09_2021_07_14', 'BR_R002_23KPQ09_2014_02_01', 'BR_R002_23KPQ09_2021_08_15', 'BR_R002_23KPQ09_2016_02_07', 'BR_R002_23KPQ09_2019_05_06', 'BR_R002_23KPQ09_2018_11_27', 'BR_R002_23KPQ09_2019_04_04', 'BR_R002_23KPQ09_2017_02_25', 'BR_R002_23KPQ09_2018_09_08', 'BR_R002_23KPQ09_2015_12_05', 'BR_R002_23KPQ09_2016_12_16', 'BR_R002_23KPQ09_2017_12_26', 'BR_R002_23KPQ09_2018_04_17', 'BR_R002_23KPQ09_2014_06_09', 'BR_R002_23KPQ09_2019_12_16', 'BR_R002_23KPQ09_2018_02_05', 'BR_R002_23KPQ09_2018_11_04', 'BR_R002_23KPQ09_2020_09_06', 'BR_R002_23KPQ09_2016_01_31', 'BR_R002_23KPQ09_2014_07_04', 'BR_R002_23KPQ09_2016_03_03', 'BR_R002_23KPQ09_2021_06_12', 'BR_R002_23KPQ09_2019_06_07', 'BR_R002_23KPQ09_2017_10_23', 'BR_R002_23KPQ09_2017_09_05', 'BR_R002_23KPQ09_2014_03_05', 'BR_R002_23KPQ09_2014_01_09', 'BR_R002_23KPQ09_2015_06_05', 'BR_R002_23KPQ09_2020_08_28', 'BR_R002_23KPQ09_2019_01_14', 'BR_R002_23KPQ09_2018_07_15', 'BR_R002_23KPQ09_2020_04_15', 'BR_R002_23KPQ09_2020_08_12', 'BR_R002_23KPQ09_2017_05_16', 'BR_R002_23KPQ09_2018_05_19', 'BR_R002_23KPQ09_2020_02_18', 'BR_R002_23KPQ09_2020_05_24', 'BR_R002_23KPQ09_2019_09_11', 'BR_R002_23KPQ09_2019_12_09', 'BR_R002_23KPQ09_2018_07_06', 'BR_R002_23KPQ09_2018_10_03', 'BR_R002_23KPQ09_2017_02_02', 'BR_R002_23KPQ09_2018_04_26', 'BR_R002_23KPQ09_2015_09_09', 'BR_R002_23KPQ09_2016_05_13', 'BR_R002_23KPQ09_2020_02_02', 'BR_R002_23KPQ09_2016_01_22', 'BR_R002_23KPQ09_2014_10_15', 'BR_R002_23KPQ09_2018_10_19', 'BR_R002_23KPQ09_2016_12_23', 'BR_R002_23KPQ09_2020_06_09', 'BR_R002_23KPQ09_2021_03_01', 'BR_R002_23KPQ09_2019_02_15', 'BR_R002_23KPQ09_2016_03_10', 'BR_R002_23KPQ09_2020_03_30', 'BR_R002_23KPQ09_2019_10_06', 'BR_R002_23KPQ09_2015_01_03', 'BR_R002_23KPQ09_2015_06_21', 'BR_R002_23KPQ09_2016_03_19', 'BR_R002_23KPQ09_2014_02_17', 'BR_R002_23KPQ09_2015_05_04', 'BR_R002_23KPQ09_2015_11_19', 'BR_R002_23KPQ09_2019_08_19', 'BR_R002_23KPQ09_2014_08_12', 'BR_R002_23KPQ09_2015_11_12', 'BR_R002_23KPQ09_2017_11_01', 'BR_R002_23KPQ09_2018_10_10', 'BR_R002_23KPQ09_2014_05_08', 'BR_R002_23KPQ09_2020_10_08', 'BR_R002_23KPQ09_2016_06_07', 'BR_R002_23KPQ09_2021_05_20', 'BR_R002_23KPQ09_2020_11_25', 'BR_R002_23KPQ09_2020_07_04', 'BR_R002_23KPQ09_2019_04_29', 'BR_R002_23KPQ09_2021_05_11', 'BR_R002_23KPQ09_2015_03_08', 'BR_R002_23KPQ09_2016_11_05', 'BR_R002_23KPQ09_2017_12_10', 'BR_R002_23KPQ09_2020_05_01', 'BR_R002_23KPQ09_2017_03_29', 'BR_R002_23KPQ09_2014_09_13', 'BR_R002_23KPQ09_2019_03_28', 'BR_R002_23KPQ09_2020_05_17', 'BR_R002_23KPQ09_2017_07_03', 'BR_R002_23KPQ09_2016_08_26', 'BR_R002_23KPQ09_2015_11_28', 'BR_R002_23KPQ09_2021_08_08', 'BR_R002_23KPQ09_2020_03_14', 'BR_R002_23KPQ09_2016_09_02', 'BR_R002_23KPQ09_2014_09_29', 'BR_R002_23KPQ09_2015_03_01', 'BR_R002_23KPQ09_2017_08_20', 'BR_R002_23KPQ09_2015_08_31', 'BR_R002_23KPQ09_2018_06_13', 'BR_R002_23KPQ09_2018_05_12', 'BR_R002_23KPQ09_2017_02_09', 'BR_R002_23KPQ09_2019_05_31', 'BR_R002_23KPQ09_2019_11_07', 'BR_R002_23KPQ09_2019_05_22', 'BR_R002_23KPQ09_2015_04_02', 'BR_R002_23KPQ09_2018_10_26', 'BR_R002_23KPQ09_2020_04_06'])\n" 48 | ] 49 | } 50 | ], 51 | "source": [ 52 | "mat = sio.loadmat(f'inputs/{name}_fixed.mat')\n", 53 | "print(mat.keys())" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 15, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "# rename/mv fixed file to the original\n", 63 | "os.rename(f'inputs/{name}_fixed.mat', f'inputs/{name}.mat')" 64 | ] 65 | } 66 | ], 67 | "metadata": { 68 | "kernelspec": { 69 | "display_name": "test", 70 | "language": "python", 71 | "name": "python3" 72 | }, 73 | "language_info": { 74 | "codemirror_mode": { 75 | "name": "ipython", 76 | "version": 3 77 | }, 78 | "file_extension": ".py", 79 | "mimetype": "text/x-python", 80 | "name": "python", 81 | "nbconvert_exporter": "python", 82 | "pygments_lexer": "ipython3", 83 | "version": "3.10.10" 84 | }, 85 | "orig_nbformat": 4 86 | }, 87 | "nbformat": 4, 88 | "nbformat_minor": 2 89 | } 90 | --------------------------------------------------------------------------------