Source code for proteindf_bridge.vector

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (C) 2014 The ProteinDF development team.
# see also AUTHORS and README if provided.
#
# This file is a part of the ProteinDF software package.
#
# The ProteinDF 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.
#
# The ProteinDF 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 ProteinDF.  If not, see <http://www.gnu.org/licenses/>.

import copy
import numpy
import numbers


[docs] class Vector(object): """ >>> a = Vector(10) >>> len(a) 10 >>> a.resize(20) >>> len(a) 20 >>> a.resize(5) >>> len(a) 5 >>> a.set(1, 3.14) >>> (a.get(0) - 0.00 < 1.0E-10) True >>> (a.get(1) - 3.14 < 1.0E-10) True >>> (a[1] - 3.14 < 1.0E-10) True >>> a[2] = 1.73 >>> (a[2] - 1.73 < 1.0E-10) True """ __header_struct_little_endian = "<i" __header_struct_big_endian = ">i" __body_struct_little_endian = "<d" __body_struct_big_endian = ">d" __array_priority__ = 100 def __init__(self, obj=None): """ Initialize. The internal variable self._data is of type numpy.array(float). """ if obj is None: obj = [] if isinstance(obj, int): size = obj self._data = numpy.array([0.0 for x in range(size)]) elif isinstance(obj, (list, numpy.ndarray)): self._data = numpy.array(obj) elif isinstance(obj, dict): size = obj.get("size", 0) buf = obj.get("data", None) if buf is not None: if len(buf) != size: raise ValueError( "Vector data length ({}) does not match size ({})".format( len(buf), size ) ) self._data = numpy.array(buf, dtype=float) else: self._data = numpy.array([0.0 for _ in range(size)]) elif isinstance(obj, Vector): self._data = copy.copy(obj._data) else: raise TypeError("Unsupported type for Vector: {}".format(type(obj))) # -------------------------------------------------------------------------- @property def max(self): return self._data.max() @property def min(self): return self._data.min()
[docs] def abs(self): answer = Vector(self) answer._data = numpy.abs(answer._data) return answer
@property def data(self): """ return numpy array """ return self._data # --------------------------------------------------------------------------
[docs] def size(self): return self.__len__()
[docs] def resize(self, new_size): new_data = numpy.array([0.0 for x in range(new_size)]) for i in range(min(self.size(), new_size)): new_data[i] = self._data[i] self._data = new_data
[docs] def get(self, index): return self._data[index]
[docs] def set(self, index, value): self._data[index] = value
[docs] def to_list(self): return self._data.tolist()
[docs] def get_buffer(self): """Return the vector data as raw bytes (float64, native byte order).""" return self._data.tobytes()
[docs] def set_buffer(self, buf): """Set vector data from a byte buffer (float64, native byte order). Raises: ValueError: If the buffer length is not a multiple of 8 bytes. """ buf_len = memoryview(buf).nbytes if buf_len % 8 != 0: raise ValueError( f"Buffer length must be a multiple of 8 bytes, but got {buf_len} bytes" ) self._data = numpy.frombuffer(buf, dtype=float).copy()
[docs] def get_ndarray(self): return copy.deepcopy(self._data)
# --------------------------------------------------------------------------
[docs] def argsort(self): return Vector(self._data.argsort())
[docs] def flip(self): return Vector(numpy.flip(self._data))
# -------------------------------------------------------------------------- def __get_header_struct(self, is_little_endian): if is_little_endian: return self.__header_struct_little_endian else: return self.__header_struct_big_endian def __get_body_struct(self, is_little_endian): if is_little_endian: return self.__body_struct_little_endian else: return self.__body_struct_big_endian def __str__(self): output = "" for order in range(0, len(self), 10): output += "\n" for j in range(order, min(order + 10, len(self))): output += " %5d th" % (j + 1) output += "\n" for j in range(order, min(order + 10, len(self))): output += "-----------" output += "----\n\n" for j in range(order, min(order + 10, len(self))): output += " %10.6lf" % (self[j]) output += "\n" return output def __add__(self, other): assert isinstance(other, Vector) assert len(self) == len(other) answer = Vector(self) answer += other return answer def __iadd__(self, other): assert isinstance(other, Vector) assert len(self) == len(other) self._data += other._data return self def __sub__(self, other): assert isinstance(other, Vector) answer = Vector(self) answer -= other return answer def __isub__(self, other): assert isinstance(other, Vector) self._data -= other._data return self def __mul__(self, other): if isinstance(other, numbers.Real) and not isinstance(other, bool): answer = Vector(self) answer *= other return answer elif isinstance(other, Vector): return float(self._data.dot(other._data)) else: return NotImplemented def __rmul__(self, other): if isinstance(other, numbers.Real) and not isinstance(other, bool): answer = Vector(self) answer *= other return answer else: return NotImplemented def __imul__(self, other): if isinstance(other, numbers.Real) and not isinstance(other, bool): self._data *= other return self else: return NotImplemented def __neg__(self): answer = Vector(self) answer *= -1.0 return answer def __len__(self): return len(self._data) def __getitem__(self, key): return self._data[key] def __setitem__(self, key, value): self._data[key] = value
if __name__ == "__main__": import doctest doctest.testmod()