Source code for aquaduct.geom.pca

# -*- coding: utf-8 -*-

# Aqua-Duct, a tool facilitating analysis of the flow of solvent molecules in molecular dynamic simulations
# Copyright (C) 2016-2017  Tomasz Magdziarz, Alicja Płuciennik, Michał Stolarczyk <info@aquaduct.pl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import numpy as np
import scipy.linalg


[docs]class Center(object):
[docs] def __init__(self, X): self.mean = np.mean(X, 0)
[docs] def __call__(self, X): return X - self.mean
[docs] def undo(self, X): return X + self.mean
[docs]class Normalize(object):
[docs] def __init__(self, X): self.std = np.std(X, 0)
[docs] def __call__(self, X): return X / self.std
[docs] def undo(self, X): return X * self.std
[docs]class Standartize(Center, Normalize):
[docs] def __init__(self, X): Center.__init__(self, X) Normalize.__init__(self, X)
[docs] def __call__(self, X): return Normalize.__call__(self, Center.__call__(self, X))
[docs] def undo(self, X): return Center.undo(self, Normalize.undo(self.X))
[docs]class PCA(object):
[docs] def __init__(self, X, prepro=None): self.preprocess_method = prepro # SVD self.U, self.d, self.Pt = scipy.linalg.svd(self.preprocess(X), full_matrices=False) assert np.all(self.d[:-1] >= self.d[1:]), "SVD error." # sorted # PCA self.T = self.U * self.d self.eigen = self.d ** 2 self.sumvariance = np.cumsum(self.eigen) self.sumvariance /= self.sumvariance[-1]
@property def P(self): return self.Pt.T
[docs] def preprocess(self, X): if self.preprocess_method is None: return X return self.preprocess_method(X)
[docs] def preprocess_undo(self, X): if self.preprocess_method is None: return X return self.preprocess_method.undo(X)
[docs] def __call__(self, X): return np.dot(self.preprocess(X), self.P)
[docs] def undo(self, T): return self.preprocess_undo(np.dot(T, self.Pt))