Skip to content

Commit

Permalink
Merge pull request #513 from ICB-DCM/develop
Browse files Browse the repository at this point in the history
Release 0.11.6
  • Loading branch information
yannikschaelte authored Nov 5, 2021
2 parents baf8c59 + 85c7651 commit 8b8a956
Show file tree
Hide file tree
Showing 21 changed files with 95 additions and 86 deletions.
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sphinx:

# python requirements
python:
version: 3.7
version: 3.8
install:
- method: pip
path: .
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ Release Notes
...........


0.11.6 (2021-11-05)
-------------------

* Unfix sphinx version for documentation (#509)
* Streamline function wrapper objects (#511)
* Remove rpy2 warning upon import of `pyabc.external` (#512)
* Move ot distance to scipy due to bug in pot 0.8.0 (#512)


0.11.5 (2021-10-29)
-------------------

Expand Down
7 changes: 4 additions & 3 deletions pyabc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
from . import settings, visualization
from .acceptor import (
Acceptor,
FunctionAcceptor,
ScaledPDFNorm,
SimpleFunctionAcceptor,
StochasticAcceptor,
UniformAcceptor,
pdf_norm_from_kernel,
Expand All @@ -42,6 +42,8 @@
BinomialKernel,
Distance,
DistanceWithMeasureList,
FunctionDistance,
FunctionKernel,
IndependentLaplaceKernel,
IndependentNormalKernel,
InfoWeightedPNormDistance,
Expand All @@ -54,7 +56,6 @@
PNormDistance,
PoissonKernel,
RangeEstimatorDistance,
SimpleFunctionDistance,
SlicedWassersteinDistance,
StochasticKernel,
WassersteinDistance,
Expand All @@ -80,7 +81,7 @@
TemperatureScheme,
)
from .inference import ABCSMC
from .model import IntegratedModel, Model, ModelResult, SimpleModel
from .model import FunctionModel, IntegratedModel, Model, ModelResult
from .parameters import Parameter
from .population import Particle, Population, Sample
from .populationstrategy import AdaptivePopulationSize, ConstantPopulationSize
Expand Down
2 changes: 1 addition & 1 deletion pyabc/acceptor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .acceptor import (
Acceptor,
AcceptorResult,
SimpleFunctionAcceptor,
FunctionAcceptor,
StochasticAcceptor,
UniformAcceptor,
)
Expand Down
6 changes: 3 additions & 3 deletions pyabc/acceptor/acceptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def get_epsilon_config(self, t: int) -> dict:
return {}


class SimpleFunctionAcceptor(Acceptor):
class FunctionAcceptor(Acceptor):
"""
Initialize from function.
Expand All @@ -224,7 +224,7 @@ def __call__(self, distance_function, eps, x, x_0, t, par):
return self.fun(distance_function, eps, x, x_0, t, par)

@staticmethod
def assert_acceptor(maybe_acceptor: Union[Acceptor, Callable]):
def to_acceptor(maybe_acceptor: Union[Acceptor, Callable]) -> Acceptor:
"""
Create an acceptor object from input.
Expand All @@ -242,7 +242,7 @@ def assert_acceptor(maybe_acceptor: Union[Acceptor, Callable]):
if isinstance(maybe_acceptor, Acceptor):
return maybe_acceptor
else:
return SimpleFunctionAcceptor(maybe_acceptor)
return FunctionAcceptor(maybe_acceptor)


def accept_use_current_time(distance_function, eps, x, x_0, t, par):
Expand Down
10 changes: 2 additions & 8 deletions pyabc/distance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@
"""

from .aggregate import AdaptiveAggregatedDistance, AggregatedDistance
from .base import (
AcceptAllDistance,
Distance,
NoDistance,
SimpleFunctionDistance,
to_distance,
)
from .base import AcceptAllDistance, Distance, FunctionDistance, NoDistance
from .distance import (
DistanceWithMeasureList,
MinMaxDistance,
Expand All @@ -30,12 +24,12 @@
SCALE_LIN,
SCALE_LOG,
BinomialKernel,
FunctionKernel,
IndependentLaplaceKernel,
IndependentNormalKernel,
NegativeBinomialKernel,
NormalKernel,
PoissonKernel,
SimpleFunctionKernel,
StochasticKernel,
)
from .ot import SlicedWassersteinDistance, WassersteinDistance
Expand Down
8 changes: 4 additions & 4 deletions pyabc/distance/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from ..population import Sample
from ..storage import save_dict_to_json
from .base import Distance, to_distance
from .base import Distance, FunctionDistance
from .scale import span

logger = logging.getLogger("ABC.Distance")
Expand All @@ -25,7 +25,7 @@ class AggregatedDistance(Distance):

def __init__(
self,
distances: List[Distance],
distances: List[Union[Distance, Callable]],
weights: Union[List, dict] = None,
factors: Union[List, dict] = None,
):
Expand All @@ -52,10 +52,10 @@ def __init__(
"""
super().__init__()

if not isinstance(distances, list):
if isinstance(distances, (Distance, Callable)):
distances = [distances]
self.distances: List[Distance] = [
to_distance(distance) for distance in distances
FunctionDistance.to_distance(distance) for distance in distances
]

self.weights = weights
Expand Down
36 changes: 18 additions & 18 deletions pyabc/distance/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import json
from abc import ABC, abstractmethod
from typing import Callable
from typing import Callable, Union

from ..population import Sample

Expand Down Expand Up @@ -209,7 +209,7 @@ def __call__(
return -1


class SimpleFunctionDistance(Distance):
class FunctionDistance(Distance):
"""
This is a wrapper around a simple function which calculates the distance.
If a function/callable is passed to the ABCSMC class, which is not
Expand Down Expand Up @@ -249,22 +249,22 @@ def get_config(self):
pass
return conf

@staticmethod
def to_distance(maybe_distance: Union[Callable, Distance]) -> Distance:
"""
Parameters
----------
maybe_distance: either a Callable as in FunctionDistance, or a
pyabc.Distance object.
def to_distance(maybe_distance):
"""
Parameters
----------
maybe_distance: either a Callable as in SimpleFunctionDistance, or a
pyabc.Distance object.
Returns
-------
A Distance instance.
"""
if maybe_distance is None:
return NoDistance()
Returns
-------
A Distance instance.
"""
if maybe_distance is None:
return NoDistance()

if isinstance(maybe_distance, Distance):
return maybe_distance
if isinstance(maybe_distance, Distance):
return maybe_distance

return SimpleFunctionDistance(maybe_distance)
return FunctionDistance(maybe_distance)
6 changes: 3 additions & 3 deletions pyabc/distance/kernel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Stochastic kernels."""

from abc import ABC
from typing import Callable, List, Sequence, Union

import numpy as np
Expand All @@ -13,7 +13,7 @@
SCALES = [SCALE_LIN, SCALE_LOG]


class StochasticKernel(Distance):
class StochasticKernel(Distance, ABC):
"""
A stochastic kernel assesses the similarity between observed and
simulated summary statistics or data via a probability measure.
Expand Down Expand Up @@ -79,7 +79,7 @@ def initialize_keys(self, x):
self.keys = sorted(x)


class SimpleFunctionKernel(StochasticKernel):
class FunctionKernel(StochasticKernel):
"""
This is a wrapper around a simple function which calculates the
probability density.
Expand Down
5 changes: 3 additions & 2 deletions pyabc/distance/ot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import numpy as np
import scipy.linalg as la
import scipy.spatial as spat

from ..population import Sample
from ..sumstat import Sumstat
Expand Down Expand Up @@ -106,7 +107,7 @@ def __init__(
# of course, we could permit arbitrary norms here if needed
raise ValueError(f"Cannot translate p={p} into a distance.")
if isinstance(dist, str):
dist = partial(ot.dist, metric=dist)
dist = partial(spat.distance.cdist, metric=dist)
self.dist: Callable = dist

if emd_args is None:
Expand Down Expand Up @@ -164,7 +165,7 @@ def __call__(
n, n0 = s.shape[0], s0.shape[0]

# pairwise cost matrix, shape (n, n0)
m = self.dist(x1=s, x2=s0)
m = self.dist(XA=s, XB=s0)

# weights (could also be passed/learned?)
w, w0 = np.ones((n,)) / n, np.ones((n0,)) / n0
Expand Down
7 changes: 5 additions & 2 deletions pyabc/external/r_rpy2.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
pandas2ri,
r,
)
except ImportError: # in Python 3.6 ModuleNotFoundError can be used
logger.error("Install rpy2 to enable simple support for the R language.")
except ImportError:
ListVector = conversion = r = None
default_converter = numpy2ri = pandas2ri = None


__all__ = ["R"]
Expand Down Expand Up @@ -84,6 +85,8 @@ class R:
"""

def __init__(self, source_file: str):
if r is None:
raise ImportError("Install rpy2, e.g. via `pip install pyabc[R]`")
warnings.warn("The support of R via rpy2 is considered experimental.")
self.source_file = source_file
self._read_source()
Expand Down
14 changes: 8 additions & 6 deletions pyabc/inference/smc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@

from pyabc.acceptor import (
Acceptor,
SimpleFunctionAcceptor,
FunctionAcceptor,
StochasticAcceptor,
UniformAcceptor,
)
from pyabc.distance import (
Distance,
FunctionDistance,
PNormDistance,
StochasticKernel,
to_distance,
)
from pyabc.epsilon import Epsilon, MedianEpsilon, TemperatureBase
from pyabc.inference_util import (
Expand All @@ -29,7 +29,7 @@
create_transition_pdf,
termination_criteria_fulfilled,
)
from pyabc.model import Model, SimpleModel
from pyabc.model import FunctionModel, Model
from pyabc.platform_factory import DefaultSampler
from pyabc.population import Population, Sample
from pyabc.populationstrategy import ConstantPopulationSize, PopulationStrategy
Expand Down Expand Up @@ -185,7 +185,7 @@ def __init__(
):
if not isinstance(models, list):
models = [models]
models = list(map(SimpleModel.assert_model, models))
models = list(map(FunctionModel.to_model, models))
self.models = models

if not isinstance(parameter_priors, list):
Expand All @@ -200,7 +200,9 @@ def __init__(

if distance_function is None:
distance_function = PNormDistance()
self.distance_function = to_distance(distance_function)
self.distance_function = FunctionDistance.to_distance(
distance_function,
)

self.summary_statistics = summary_statistics

Expand Down Expand Up @@ -234,7 +236,7 @@ def __init__(

if acceptor is None:
acceptor = UniformAcceptor()
self.acceptor = SimpleFunctionAcceptor.assert_acceptor(acceptor)
self.acceptor = FunctionAcceptor.to_acceptor(acceptor)

self.stop_if_only_single_model_alive = stop_if_only_single_model_alive
self.max_nr_recorded_particles = max_nr_recorded_particles
Expand Down
17 changes: 8 additions & 9 deletions pyabc/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
A model defines how input parameters relate to output simulated data.
"""

from typing import Any, Callable
from typing import Any, Callable, Union

from .acceptor import Acceptor
from .distance import Distance
Expand Down Expand Up @@ -218,7 +218,7 @@ def accept(
return result


class SimpleModel(Model):
class FunctionModel(Model):
"""
A model which is initialized with a function which generates the samples.
For most cases this class will be adequate.
Expand Down Expand Up @@ -247,27 +247,26 @@ def sample(self, pars: Parameter):
return self.sample_function(pars)

@staticmethod
def assert_model(model_or_function):
def to_model(maybe_model: Union[Callable, Model]) -> Model:
"""
Alternative constructor. Accepts either a Model instance or a
function and returns always a Model instance.
Parameters
----------
model_or_function: Model, function
maybe_model:
Constructs a SimpleModel instance if a function is passed.
If a Model instance is passed, the Model instance itself is
returned.
Returns
-------
model: SimpleModel or Model
model: A valid model instance
"""
if isinstance(model_or_function, Model):
return model_or_function
if isinstance(maybe_model, Model):
return maybe_model
else:
return SimpleModel(model_or_function)
return FunctionModel(maybe_model)


class IntegratedModel(Model):
Expand Down
Loading

0 comments on commit 8b8a956

Please sign in to comment.