blob: 0b4e26f8a4d578cf106f4e7d3f860be1ed8d2141 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
'''
Classes:
Metric - Abstract Base Class from which all metrics must inherit.
'''
from abc import ABCMeta, abstractmethod
import ocw.utils as utils
import numpy
from scipy import stats
class Metric(object):
'''Base Metric Class'''
__metaclass__ = ABCMeta
class UnaryMetric(Metric):
'''Abstract Base Class from which all unary metrics inherit.'''
__metaclass__ = ABCMeta
@abstractmethod
def run(self, target_dataset):
'''Run the metric for a given target dataset.
:param target_dataset: The dataset on which the current metric will
be run.
:returns: The result of evaluating the metric on the target_dataset.
'''
class BinaryMetric(Metric):
'''Abstract Base Class from which all binary metrics inherit.'''
__metaclass__ = ABCMeta
@abstractmethod
def run(self, ref_dataset, target_dataset):
'''Run the metric for the given reference and target datasets.
:param ref_dataset: The Dataset to use as the reference dataset when
running the evaluation.
:type ref_dataset: Dataset
:param target_dataset: The Dataset to use as the target dataset when
running the evaluation.
:returns: The result of evaluation the metric on the reference and
target dataset.
'''
class Bias(BinaryMetric):
'''Calculate the bias between a reference and target dataset.'''
def run(self, ref_dataset, target_dataset):
'''Calculate the bias between a reference and target dataset.
.. note::
Overrides BinaryMetric.run()
:param ref_dataset: The reference dataset to use in this metric run.
:type ref_dataset: Dataset.
:param target_dataset: The target dataset to evaluate against the
reference dataset in this metric run.
:type target_dataset: Dataset.
:returns: The difference between the reference and target datasets.
:rtype: Numpy Array
'''
return ref_dataset.values - target_dataset.values
class TemporalStdDev(UnaryMetric):
'''Calculate the standard deviation over the time.'''
def run(self, target_dataset):
'''Calculate the temporal std. dev. for a datasets.
.. note::
Overrides UnaryMetric.run()
:param target_dataset: The target_dataset on which to calculate the
temporal standard deviation.
:type target_dataset: Dataset
:returns: The temporal standard deviation of the target dataset
:rtype: Numpy Array
'''
return target_dataset.values.std(axis=0, ddof=1)
class SpatialStdDevRatio(BinaryMetric):
'''Calculate the ratio of spatial standard deviation (model standard
deviation)/(observed standard deviation)'''
def run(self, ref_dataset, target_dataset):
'''Calculate the ratio of spatial std. dev. between a reference and
target dataset.
.. note::
Overrides BinaryMetric.run()
:param ref_dataset: The reference dataset to use in this metric run.
:type ref_dataset: Dataset.
:param target_dataset: The target dataset to evaluate against the
reference dataset in this metric run.
:type target_dataset: Dataset.
:returns: The ratio of standard deviation of the reference and target
dataset.
'''
# This is calcClimYear function for ref_dataset
reshaped_ref_data = utils.reshape_monthly_to_annually(ref_dataset)
ref_t_series = reshaped_ref_data.mean(axis=1)
ref_means = ref_t_series.mean(axis=0)
# This is calcClimYear function for target_dataset
reshaped_target_data = utils.reshape_monthly_to_annually(target_dataset)
target_t_series = reshaped_target_data.mean(axis=1)
target_means = target_t_series.mean(axis=0)
return numpy.std(ref_means) / numpy.std(target_means)
class PatternCorrelation(BinaryMetric):
'''Calculate the spatial correlation'''
def run(self, ref_dataset, target_dataset):
'''Calculate the spatial correlation between a reference and target dataset.
Using: scipy.stats.pearsonr
.. note::
Overrides BinaryMetric.run()
:param ref_dataset: The reference dataset to use in this metric run.
:type ref_dataset: Dataset.
:param target_dataset: The target dataset to evaluate against the
reference dataset in this metric run.
:type target_dataset: Dataset.
:returns: The spatial correlation between a reference and target dataset.
'''
# This is calcClimYear function for ref_dataset
reshaped_ref_data = utils.reshape_monthly_to_annually(ref_dataset)
ref_t_series = reshaped_ref_data.mean(axis=1)
ref_means = ref_t_series.mean(axis=0)
# This is calcClimYear function for target_dataset
reshaped_target_data = utils.reshape_monthly_to_annually(target_dataset)
target_t_series = reshaped_target_data.mean(axis=1)
target_means = target_t_series.mean(axis=0)
pattern_correlation, p_value = stats.pearsonr(target_means.flatten(),ref_means.flatten())
return pattern_correlation, p_value