def rank_by_w_correl(self): ''' find optimal rank by: 2) calculate summ of correlations for each row of self.w_correl 3) find index where those summ is minimal. This is a rank @return pair of (calculated rank of SVD, w-correlation for that rank)) Note: rank >= 1 ''' # w-correlation matrix has simmetry about main diagonal. # Coefficients at main diagonal always 1(self correlation). # Coefficients at (i+1,j) where j=1(close to main diagonal) can # be viewed as correlation of cos/sin of the same frequency # when coefficient more 0.5 and as noise in other case. # Assumptions: # - calculation is made in one half of matrix, # - main diagonal excluded from calculation. # - for element (i,i) calculation made for elements (i+1, i+wd), where # wd is a w-correlation depth. # - No more than wlen elements analyzed. Assume rank of S no more # than rank_max. # - according to condition above, size of analized SVD is # wd + rank_max. # - correlations should be calculated at early step because # the same value is used ofter more than one time. if not self.ssa: return 0, 0 # calc w-correl limit rank_max = min(len(self.s_svd()) - 5, self.SSA_RANK_MAX) if rank_max < 0: self.log.error("Could not calc w-correl - S too short") if rank_max + self.W_MIN_DEPTH > len(self.s_svd()): m_size = len(self.s_svd()) else: m_size = rank_max + self.W_MIN_DEPTH if rank_max > len(self.s_svd()): rank_max = len(self.s_svd()) if self.w_correl is None: self.calc_w_unit_correl_matrix(rank_max, m_size) weights = self.calc_w_unit_correl_weights(rank_max) log_array(weights, "weights of w-correlation") if self.USE_W_CORR_WEIGHTS: self.log.info("correction weights by square") for i in range(weights.size): square = (i + 1) * (m_size - i) weights[i] /= square log_array(weights, "normalized by square weights of w-correlation") w_min = 1e10 rank = -1 # first and second values excluded, because: # 1) anyway, this value in most cases in small; # 2) rank = 1 is not interested in most cases. if weights.size < 3: imin = 1 else: imin = 3 for i in range(imin, weights.size): if weights[i] < w_min: rank = i w_min = weights[i] return (rank + 1, w_min)
def debug_array(self, m, title): if self.loglevel <= logging.DEBUG: log_array(m, title)