Skip to content

Commit 8b8a956

Browse files
Merge pull request #513 from ICB-DCM/develop
Release 0.11.6
2 parents baf8c59 + 85c7651 commit 8b8a956

21 files changed

+95
-86
lines changed

.readthedocs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ sphinx:
1111

1212
# python requirements
1313
python:
14-
version: 3.7
14+
version: 3.8
1515
install:
1616
- method: pip
1717
path: .

CHANGELOG.rst

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ Release Notes
88
...........
99

1010

11+
0.11.6 (2021-11-05)
12+
-------------------
13+
14+
* Unfix sphinx version for documentation (#509)
15+
* Streamline function wrapper objects (#511)
16+
* Remove rpy2 warning upon import of `pyabc.external` (#512)
17+
* Move ot distance to scipy due to bug in pot 0.8.0 (#512)
18+
19+
1120
0.11.5 (2021-10-29)
1221
-------------------
1322

pyabc/__init__.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
from . import settings, visualization
2828
from .acceptor import (
2929
Acceptor,
30+
FunctionAcceptor,
3031
ScaledPDFNorm,
31-
SimpleFunctionAcceptor,
3232
StochasticAcceptor,
3333
UniformAcceptor,
3434
pdf_norm_from_kernel,
@@ -42,6 +42,8 @@
4242
BinomialKernel,
4343
Distance,
4444
DistanceWithMeasureList,
45+
FunctionDistance,
46+
FunctionKernel,
4547
IndependentLaplaceKernel,
4648
IndependentNormalKernel,
4749
InfoWeightedPNormDistance,
@@ -54,7 +56,6 @@
5456
PNormDistance,
5557
PoissonKernel,
5658
RangeEstimatorDistance,
57-
SimpleFunctionDistance,
5859
SlicedWassersteinDistance,
5960
StochasticKernel,
6061
WassersteinDistance,
@@ -80,7 +81,7 @@
8081
TemperatureScheme,
8182
)
8283
from .inference import ABCSMC
83-
from .model import IntegratedModel, Model, ModelResult, SimpleModel
84+
from .model import FunctionModel, IntegratedModel, Model, ModelResult
8485
from .parameters import Parameter
8586
from .population import Particle, Population, Sample
8687
from .populationstrategy import AdaptivePopulationSize, ConstantPopulationSize

pyabc/acceptor/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .acceptor import (
1111
Acceptor,
1212
AcceptorResult,
13-
SimpleFunctionAcceptor,
13+
FunctionAcceptor,
1414
StochasticAcceptor,
1515
UniformAcceptor,
1616
)

pyabc/acceptor/acceptor.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def get_epsilon_config(self, t: int) -> dict:
206206
return {}
207207

208208

209-
class SimpleFunctionAcceptor(Acceptor):
209+
class FunctionAcceptor(Acceptor):
210210
"""
211211
Initialize from function.
212212
@@ -224,7 +224,7 @@ def __call__(self, distance_function, eps, x, x_0, t, par):
224224
return self.fun(distance_function, eps, x, x_0, t, par)
225225

226226
@staticmethod
227-
def assert_acceptor(maybe_acceptor: Union[Acceptor, Callable]):
227+
def to_acceptor(maybe_acceptor: Union[Acceptor, Callable]) -> Acceptor:
228228
"""
229229
Create an acceptor object from input.
230230
@@ -242,7 +242,7 @@ def assert_acceptor(maybe_acceptor: Union[Acceptor, Callable]):
242242
if isinstance(maybe_acceptor, Acceptor):
243243
return maybe_acceptor
244244
else:
245-
return SimpleFunctionAcceptor(maybe_acceptor)
245+
return FunctionAcceptor(maybe_acceptor)
246246

247247

248248
def accept_use_current_time(distance_function, eps, x, x_0, t, par):

pyabc/distance/__init__.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,7 @@
1111
"""
1212

1313
from .aggregate import AdaptiveAggregatedDistance, AggregatedDistance
14-
from .base import (
15-
AcceptAllDistance,
16-
Distance,
17-
NoDistance,
18-
SimpleFunctionDistance,
19-
to_distance,
20-
)
14+
from .base import AcceptAllDistance, Distance, FunctionDistance, NoDistance
2115
from .distance import (
2216
DistanceWithMeasureList,
2317
MinMaxDistance,
@@ -30,12 +24,12 @@
3024
SCALE_LIN,
3125
SCALE_LOG,
3226
BinomialKernel,
27+
FunctionKernel,
3328
IndependentLaplaceKernel,
3429
IndependentNormalKernel,
3530
NegativeBinomialKernel,
3631
NormalKernel,
3732
PoissonKernel,
38-
SimpleFunctionKernel,
3933
StochasticKernel,
4034
)
4135
from .ot import SlicedWassersteinDistance, WassersteinDistance

pyabc/distance/aggregate.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from ..population import Sample
99
from ..storage import save_dict_to_json
10-
from .base import Distance, to_distance
10+
from .base import Distance, FunctionDistance
1111
from .scale import span
1212

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

2626
def __init__(
2727
self,
28-
distances: List[Distance],
28+
distances: List[Union[Distance, Callable]],
2929
weights: Union[List, dict] = None,
3030
factors: Union[List, dict] = None,
3131
):
@@ -52,10 +52,10 @@ def __init__(
5252
"""
5353
super().__init__()
5454

55-
if not isinstance(distances, list):
55+
if isinstance(distances, (Distance, Callable)):
5656
distances = [distances]
5757
self.distances: List[Distance] = [
58-
to_distance(distance) for distance in distances
58+
FunctionDistance.to_distance(distance) for distance in distances
5959
]
6060

6161
self.weights = weights

pyabc/distance/base.py

+18-18
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import json
44
from abc import ABC, abstractmethod
5-
from typing import Callable
5+
from typing import Callable, Union
66

77
from ..population import Sample
88

@@ -209,7 +209,7 @@ def __call__(
209209
return -1
210210

211211

212-
class SimpleFunctionDistance(Distance):
212+
class FunctionDistance(Distance):
213213
"""
214214
This is a wrapper around a simple function which calculates the distance.
215215
If a function/callable is passed to the ABCSMC class, which is not
@@ -249,22 +249,22 @@ def get_config(self):
249249
pass
250250
return conf
251251

252+
@staticmethod
253+
def to_distance(maybe_distance: Union[Callable, Distance]) -> Distance:
254+
"""
255+
Parameters
256+
----------
257+
maybe_distance: either a Callable as in FunctionDistance, or a
258+
pyabc.Distance object.
252259
253-
def to_distance(maybe_distance):
254-
"""
255-
Parameters
256-
----------
257-
maybe_distance: either a Callable as in SimpleFunctionDistance, or a
258-
pyabc.Distance object.
259-
260-
Returns
261-
-------
262-
A Distance instance.
263-
"""
264-
if maybe_distance is None:
265-
return NoDistance()
260+
Returns
261+
-------
262+
A Distance instance.
263+
"""
264+
if maybe_distance is None:
265+
return NoDistance()
266266

267-
if isinstance(maybe_distance, Distance):
268-
return maybe_distance
267+
if isinstance(maybe_distance, Distance):
268+
return maybe_distance
269269

270-
return SimpleFunctionDistance(maybe_distance)
270+
return FunctionDistance(maybe_distance)

pyabc/distance/kernel.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Stochastic kernels."""
2-
2+
from abc import ABC
33
from typing import Callable, List, Sequence, Union
44

55
import numpy as np
@@ -13,7 +13,7 @@
1313
SCALES = [SCALE_LIN, SCALE_LOG]
1414

1515

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

8181

82-
class SimpleFunctionKernel(StochasticKernel):
82+
class FunctionKernel(StochasticKernel):
8383
"""
8484
This is a wrapper around a simple function which calculates the
8585
probability density.

pyabc/distance/ot.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import numpy as np
88
import scipy.linalg as la
9+
import scipy.spatial as spat
910

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

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

166167
# pairwise cost matrix, shape (n, n0)
167-
m = self.dist(x1=s, x2=s0)
168+
m = self.dist(XA=s, XB=s0)
168169

169170
# weights (could also be passed/learned?)
170171
w, w0 = np.ones((n,)) / n, np.ones((n0,)) / n0

pyabc/external/r_rpy2.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@
3535
pandas2ri,
3636
r,
3737
)
38-
except ImportError: # in Python 3.6 ModuleNotFoundError can be used
39-
logger.error("Install rpy2 to enable simple support for the R language.")
38+
except ImportError:
39+
ListVector = conversion = r = None
40+
default_converter = numpy2ri = pandas2ri = None
4041

4142

4243
__all__ = ["R"]
@@ -84,6 +85,8 @@ class R:
8485
"""
8586

8687
def __init__(self, source_file: str):
88+
if r is None:
89+
raise ImportError("Install rpy2, e.g. via `pip install pyabc[R]`")
8790
warnings.warn("The support of R via rpy2 is considered experimental.")
8891
self.source_file = source_file
8992
self._read_source()

pyabc/inference/smc.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99

1010
from pyabc.acceptor import (
1111
Acceptor,
12-
SimpleFunctionAcceptor,
12+
FunctionAcceptor,
1313
StochasticAcceptor,
1414
UniformAcceptor,
1515
)
1616
from pyabc.distance import (
1717
Distance,
18+
FunctionDistance,
1819
PNormDistance,
1920
StochasticKernel,
20-
to_distance,
2121
)
2222
from pyabc.epsilon import Epsilon, MedianEpsilon, TemperatureBase
2323
from pyabc.inference_util import (
@@ -29,7 +29,7 @@
2929
create_transition_pdf,
3030
termination_criteria_fulfilled,
3131
)
32-
from pyabc.model import Model, SimpleModel
32+
from pyabc.model import FunctionModel, Model
3333
from pyabc.platform_factory import DefaultSampler
3434
from pyabc.population import Population, Sample
3535
from pyabc.populationstrategy import ConstantPopulationSize, PopulationStrategy
@@ -185,7 +185,7 @@ def __init__(
185185
):
186186
if not isinstance(models, list):
187187
models = [models]
188-
models = list(map(SimpleModel.assert_model, models))
188+
models = list(map(FunctionModel.to_model, models))
189189
self.models = models
190190

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

201201
if distance_function is None:
202202
distance_function = PNormDistance()
203-
self.distance_function = to_distance(distance_function)
203+
self.distance_function = FunctionDistance.to_distance(
204+
distance_function,
205+
)
204206

205207
self.summary_statistics = summary_statistics
206208

@@ -234,7 +236,7 @@ def __init__(
234236

235237
if acceptor is None:
236238
acceptor = UniformAcceptor()
237-
self.acceptor = SimpleFunctionAcceptor.assert_acceptor(acceptor)
239+
self.acceptor = FunctionAcceptor.to_acceptor(acceptor)
238240

239241
self.stop_if_only_single_model_alive = stop_if_only_single_model_alive
240242
self.max_nr_recorded_particles = max_nr_recorded_particles

pyabc/model.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
A model defines how input parameters relate to output simulated data.
66
"""
77

8-
from typing import Any, Callable
8+
from typing import Any, Callable, Union
99

1010
from .acceptor import Acceptor
1111
from .distance import Distance
@@ -218,7 +218,7 @@ def accept(
218218
return result
219219

220220

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

249249
@staticmethod
250-
def assert_model(model_or_function):
250+
def to_model(maybe_model: Union[Callable, Model]) -> Model:
251251
"""
252252
Alternative constructor. Accepts either a Model instance or a
253253
function and returns always a Model instance.
254254
255255
Parameters
256256
----------
257-
model_or_function: Model, function
257+
maybe_model:
258258
Constructs a SimpleModel instance if a function is passed.
259259
If a Model instance is passed, the Model instance itself is
260260
returned.
261261
262262
Returns
263263
-------
264-
model: SimpleModel or Model
265-
264+
model: A valid model instance
266265
"""
267-
if isinstance(model_or_function, Model):
268-
return model_or_function
266+
if isinstance(maybe_model, Model):
267+
return maybe_model
269268
else:
270-
return SimpleModel(model_or_function)
269+
return FunctionModel(maybe_model)
271270

272271

273272
class IntegratedModel(Model):

0 commit comments

Comments
 (0)