| # Copyright (c) 2021 The Regents of The University of California |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer; |
| # redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution; |
| # neither the name of the copyright holders nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| from abc import ABC |
| from typing import Any, Iterable, Optional, Union, List |
| |
| from .jsonserializable import JsonSerializable |
| from .storagetype import StorageType |
| |
| class Statistic(ABC, JsonSerializable): |
| """ |
| The abstract base class for all Python statistics. |
| """ |
| |
| value: Any |
| type: Optional[str] |
| unit: Optional[str] |
| description: Optional[str] |
| datatype: Optional[StorageType] |
| |
| def __init__(self, value: Any, type: Optional[str] = None, |
| unit: Optional[str] = None, |
| description: Optional[str] = None, |
| datatype: Optional[StorageType] = None): |
| self.value = value |
| self.type = type |
| self.unit = unit |
| self.description = description |
| self.datatype = datatype |
| |
| class Scalar(Statistic): |
| """ |
| A scalar Python statistic type. |
| """ |
| |
| value: Union[float, int] |
| |
| def __init__(self, value: Any, |
| unit: Optional[str] = None, |
| description: Optional[str] = None, |
| datatype: Optional[StorageType] = None): |
| super().__init__(value=value, type="Scalar", unit=unit, |
| description=description, datatype=datatype) |
| |
| class BaseScalarVector(Statistic): |
| """ |
| An abstract base class for classes containing a vector of Scalar values. |
| """ |
| value: List[Union[int,float]] |
| |
| def __init__(self, value: Iterable[Union[int,float]], |
| type: Optional[str] = None, |
| unit: Optional[str] = None, |
| description: Optional[str] = None, |
| datatype: Optional[StorageType] = None): |
| super().__init__(value=list(value), type=type, unit=unit, |
| description=description, datatype=datatype) |
| |
| def mean(self) -> float: |
| """ |
| Returns the mean of the value vector. |
| |
| Returns |
| ------- |
| float |
| The mean value across all bins. |
| """ |
| assert(self.value != None) |
| assert(isinstance(self.value, List)) |
| |
| from statistics import mean as statistics_mean |
| return statistics_mean(self.value) |
| |
| def count(self) -> float: |
| """ |
| Returns the count across all the bins. |
| |
| Returns |
| ------- |
| float |
| The sum of all bin values. |
| """ |
| assert(self.value != None) |
| return sum(self.value) |
| |
| |
| class Distribution(BaseScalarVector): |
| """ |
| A statistic type that stores information relating to distributions. Each |
| distribution has a number of bins (>=1) |
| between this range. The values correspond to the value of each bin. |
| E.g., value[3]` is the value of the 4th bin. |
| |
| It is assumed each bucket is of equal size. |
| """ |
| |
| min: Union[float, int] |
| max: Union[float, int] |
| num_bins: int |
| bin_size: Union[float, int] |
| sum: Optional[int] |
| sum_squared: Optional[int] |
| underflow: Optional[int] |
| overflow: Optional[int] |
| logs: Optional[float] |
| |
| def __init__(self, value: Iterable[int], |
| min: Union[float, int], |
| max: Union[float, int], |
| num_bins: int, |
| bin_size: Union[float, int], |
| sum: Optional[int] = None, |
| sum_squared: Optional[int] = None, |
| underflow: Optional[int] = None, |
| overflow: Optional[int] = None, |
| logs: Optional[float] = None, |
| unit: Optional[str] = None, |
| description: Optional[str] = None, |
| datatype: Optional[StorageType] = None): |
| super().__init__(value=value, type="Distribution", unit=unit, |
| description=description, datatype=datatype) |
| |
| self.min = min |
| self.max = max |
| self.num_bins = num_bins |
| self.bin_size = bin_size |
| self.sum = sum |
| self.underflow = underflow |
| self.overflow = overflow |
| self.logs = logs |
| self.sum_squared = sum_squared |
| |
| # These check some basic conditions of a distribution. |
| assert(self.bin_size >= 0) |
| assert(self.num_bins >= 1) |
| |
| class Accumulator(BaseScalarVector): |
| """ |
| A statistical type representing an accumulator. |
| """ |
| |
| _count: int |
| min: Union[int, float] |
| max: Union[int, float] |
| sum_squared: Optional[int] |
| |
| def __init__(self, value: Iterable[Union[int,float]], |
| count: int, |
| min: Union[int, float], |
| max: Union[int, float], |
| sum_squared: Optional[int] = None, |
| unit: Optional[str] = None, |
| description: Optional[str] = None, |
| datatype: Optional[StorageType] = None): |
| super().__init__(value=value, type="Accumulator", unit=unit, |
| description=description, datatype=datatype) |
| |
| self._count = count |
| self.min = min |
| self.max = max |
| self.sum_squared = sum_squared |
| |
| def count(self) -> int: |
| return self._count |