Skip to content

Commit

Permalink
Merge pull request wichmann-lab#179 from otizonaizit/reinstate-parame…
Browse files Browse the repository at this point in the history
…ter-estimate

Reinstate `Result.parameter_estimate`
  • Loading branch information
otizonaizit authored Dec 5, 2024
2 parents 4c1457f + 6d3964f commit 710f9f7
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 86 deletions.
4 changes: 2 additions & 2 deletions docs/basic-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ and the confidence intervals:
jupyter:
outputs_hidden: False
---
print(result.get_parameters_estimate())
print(result.parameter_estimate)
```

This returns a python dictionary containing the estimated parameters.
Expand All @@ -132,7 +132,7 @@ The parameters estimated by psignifit are:
Then, to obtain the threhsold you run

```{code-cell} ipython3
print(result.get_parameters_estimate()['threshold'])
print(result.parameter_estimate['threshold'])
```


Expand Down
12 changes: 6 additions & 6 deletions docs/examples/parameter_recovery_demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,15 @@ res = psignifit.psignifit(data, **options)

+++ {"nteract": {"transient": {"deleting": false}}}

Lastly, we can ensure that the values in our `res.get_parameters_estimate()` dictionary are equal to the values that we used to simulate them
Lastly, we can ensure that the values in our `res.parameter_estimate` dictionary are equal to the values that we used to simulate them

```{code-cell} ipython3
---
nteract:
transient:
deleting: false
---
assert np.isclose(res.get_parameters_estimate()['lambda'], lambda_, atol=1e-2)
assert np.isclose(res.parameter_estimate['lambda'], lambda_, atol=1e-2)
```

```{code-cell} ipython3
Expand All @@ -159,7 +159,7 @@ nteract:
transient:
deleting: false
---
assert np.isclose(res.get_parameters_estimate()['gamma'], gamma, atol=1e-2)
assert np.isclose(res.parameter_estimate['gamma'], gamma, atol=1e-2)
```

```{code-cell} ipython3
Expand All @@ -168,9 +168,9 @@ nteract:
transient:
deleting: false
---
assert np.isclose(res.get_parameters_estimate()['eta'], 0, atol=1e-2)
assert np.isclose(res.get_parameters_estimate()['threshold'], threshold, atol=1e-2)
assert np.isclose(res.get_parameters_estimate()['width'], width, atol=1e-2)
assert np.isclose(res.parameter_estimate['eta'], 0, atol=1e-2)
assert np.isclose(res.parameter_estimate['threshold'], threshold, atol=1e-2)
assert np.isclose(res.parameter_estimate['width'], width, atol=1e-2)
```

```{code-cell} ipython3
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/priors.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ res = ps.psignifit(data, experiment_type='2AFC')
First lets have a look at the results with the standard prior strength:

```{code-cell} ipython3
print('Fit:', res.get_parameters_estimate())
print('Fit:', res.parameter_estimate)
print('confidence Intervals:', res.confidence_intervals)
```

Expand All @@ -211,8 +211,8 @@ First see that the only parameter whose fit changes by this is the
beta-variance parameter eta (the 5th)

```{code-cell} ipython3
print('Fit with beta prior = 1: ', res1.get_parameters_estimate())
print('Fit with beta prior = 200: ', res200.get_parameters_estimate())
print('Fit with beta prior = 1: ', res1.parameter_estimate)
print('Fit with beta prior = 200: ', res200.parameter_estimate)
```

Now we have a look at the confidence intervals
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/results-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ The most important result are the fitted parameters of the psychometric
function. They can be found in a dictionary format.

```{code-cell} ipython3
print(res.get_parameters_estimate())
print(res.parameter_estimate)
```

For each of these parameters, also the confidence interval is contained
Expand Down Expand Up @@ -77,7 +77,7 @@ otherdata[:, 0] = otherdata[:, 0] + 0.01
other_res = ps.psignifit(otherdata, res.configuration)
# the difference in threshold should return the introduced shift
print(other_res.get_parameters_estimate()['threshold'] - res.get_parameters_estimate()['threshold'])
print(other_res.parameter_estimate['threshold'] - res.parameter_estimate['threshold'])
```

## Saving to JSON
Expand All @@ -94,7 +94,7 @@ It can be loaded again to be used at a later time, for example for plotting

```{code-cell} ipython3
loaded_res = ps.Result.load_json(file_name)
print(loaded_res.get_parameters_estimate())
print(loaded_res.parameter_estimate)
```

```{code-cell} ipython3
Expand Down
2 changes: 1 addition & 1 deletion docs/how_to/How-to-Fix-Parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ res = ps.psignifit(data, **options)
We print the parameter estimates to check that lambda was indeed fixed

```{code-cell} ipython3
print(res.get_parameters_estimate())
print(res.parameter_estimate)
```

2 changes: 1 addition & 1 deletion docs/how_to/How-to-Get-Thresholds-and-Slopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ res.threshold(0.5, unscaled=True)
which should be 0.0046, which is exactly the definition of the threshold we use in the fitting.

```{code-cell} ipython3
res.get_parameters_estimate()['threshold']
res.parameter_estimate['threshold']
```

The function also returns worst-case credible intervals for the
Expand Down
20 changes: 11 additions & 9 deletions psignifit/_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def default(self, obj):

@dataclasses.dataclass
class Result:
parameters_estimate_MAP: Dict[str, float]
parameters_estimate_mean: Dict[str, float]
parameter_estimate_MAP: Dict[str, float]
parameter_estimate_mean: Dict[str, float]
configuration: Configuration
confidence_intervals: Dict[str, List[Tuple[float, float]]]
data: NDArray[float]
Expand Down Expand Up @@ -68,7 +68,7 @@ def load_json(cls, file: Union[TextIO, str, Path], **kwargs: Any):
result_dict['data'] = np.asarray(result_dict['data'])
return cls.from_dict(result_dict)

def get_parameters_estimate(self, estimate_type: Optional[EstimateType]=None):
def get_parameter_estimate(self, estimate_type: Optional[EstimateType]=None):
""" Get the estimate of the parameters by type.
Args:
Expand All @@ -81,14 +81,16 @@ def get_parameters_estimate(self, estimate_type: Optional[EstimateType]=None):
estimate_type = self.configuration.estimate_type

if estimate_type == 'MAP':
estimate = self.parameters_estimate_MAP
estimate = self.parameter_estimate_MAP
elif estimate_type == 'mean':
estimate = self.parameters_estimate_mean
estimate = self.parameter_estimate_mean
else:
raise ValueError("`estimate_type` must be either 'MAP' or 'mean'")

return estimate

parameter_estimate = property(get_parameter_estimate)

def threshold(self, proportion_correct: np.ndarray, unscaled: bool = False, return_ci: bool = True,
estimate_type: Optional[EstimateType]=None) -> Union[np.ndarray, List[Tuple[np.ndarray, np.ndarray]]]:
""" Threshold stimulus value and confidence interval for a different proportion correct cutoff.
Expand Down Expand Up @@ -116,7 +118,7 @@ def threshold(self, proportion_correct: np.ndarray, unscaled: bool = False, retu
proportion_correct = np.asarray(proportion_correct)
sigmoid = self.configuration.make_sigmoid()

estimate = self.get_parameters_estimate(estimate_type)
estimate = self.get_parameter_estimate(estimate_type)
if unscaled: # set asymptotes to 0 for everything.
lambd, gamma = 0, 0
else:
Expand Down Expand Up @@ -152,7 +154,7 @@ def slope(self, stimulus_level: np.ndarray, estimate_type: Optional[EstimateType
Returns:
Slopes of the psychometric function at the stimulus levels.
"""
stimulus_level, param = np.asarray(stimulus_level), self.get_parameters_estimate(estimate_type)
stimulus_level, param = np.asarray(stimulus_level), self.get_parameter_estimate(estimate_type)
sigmoid = self.configuration.make_sigmoid()
return sigmoid.slope(stimulus_level, param['threshold'], param['width'], param['gamma'], param['lambda'])

Expand All @@ -174,7 +176,7 @@ def slope_at_proportion_correct(self, proportion_correct: np.ndarray, unscaled:
stimulus_levels = self.threshold(proportion_correct, unscaled, return_ci=False, estimate_type=estimate_type)
return self.slope(stimulus_levels)

def standard_parameters_estimate(self, estimate_type: Optional[EstimateType]=None):
def standard_parameter_estimate(self, estimate_type: Optional[EstimateType]=None):
""" Get the parameters of the psychometric function in the standard format.
`psignifit` uses the same intuitive parametrization, threshold and width, for all
Expand All @@ -192,6 +194,6 @@ def standard_parameters_estimate(self, estimate_type: Optional[EstimateType]=Non
Standard parameters (loc, scale) for the sigmoid subclass.
"""
sigmoid = self.configuration.make_sigmoid()
estimate = self.get_parameters_estimate(estimate_type)
estimate = self.get_parameter_estimate(estimate_type)
loc, scale = sigmoid.standard_parameters(estimate['threshold'], estimate['width'])
return loc, scale
9 changes: 4 additions & 5 deletions psignifit/demos/parameters_estimates.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false,
"source_hidden": false
Expand Down Expand Up @@ -310,7 +309,7 @@
],
"source": [
"# This gives the default estimate, in this case the mean estimate since we set it in the options.\n",
"result.get_parameters_estimate() "
"result.parameter_estimate "
]
},
{
Expand All @@ -334,8 +333,8 @@
}
],
"source": [
"# We can overwrite the default setting by specifying the `estimate_type` parameter\n",
"result.get_parameters_estimate(estimate_type='MAP') "
"# We can overwrite the default setting by specifying the `estimate_type` parameter in the method get_parameter_estimate\n",
"result.get_parameter_estimate(estimate_type='MAP') "
]
},
{
Expand Down Expand Up @@ -469,7 +468,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.8"
},
"nteract": {
"version": "0.28.0"
Expand Down
4 changes: 2 additions & 2 deletions psignifit/psignifit.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ def psignifit(data: np.ndarray, conf: Optional[Configuration] = None,
debug_dict['priors'] = priors
debug_dict['bounds'] = bounds

return Result(parameters_estimate_MAP=estimate_MAP_dict,
parameters_estimate_mean=estimate_mean_dict,
return Result(parameter_estimate_MAP=estimate_MAP_dict,
parameter_estimate_mean=estimate_mean_dict,
configuration=conf,
confidence_intervals=intervals_dict,
parameter_values=grid,
Expand Down
12 changes: 6 additions & 6 deletions psignifit/psigniplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def plot_psychometric_function(result: Result, # noqa: C901, this function is t
if ax is None:
ax = plt.gca()

params = result.get_parameters_estimate(estimate_type=estimate_type)
params = result.get_parameter_estimate(estimate_type=estimate_type)
data = np.asarray(result.data)
config = result.configuration

Expand Down Expand Up @@ -106,7 +106,7 @@ def _plot_residuals(x_values: np.ndarray,
estimate_type: EstimateType = None):
if ax is None:
ax = plt.gca()
params = result.get_parameters_estimate(estimate_type=estimate_type)
params = result.get_parameter_estimate(estimate_type=estimate_type)
data = result.data
sigmoid = result.configuration.make_sigmoid()

Expand Down Expand Up @@ -245,7 +245,7 @@ def plot_marginal(result: Result,
ci_x = np.r_[CI[0], x[(x >= CI[0]) & (x <= CI[1])], CI[1]]
ax.fill_between(ci_x, np.zeros_like(ci_x), np.interp(ci_x, x, marginal), color=line_color, alpha=0.5)

estimate = result.get_parameters_estimate(estimate_type=estimate_type)
estimate = result.get_parameter_estimate(estimate_type=estimate_type)
param_value = estimate[parameter]
ax.plot([param_value] * 2, [0, np.interp(param_value, x, marginal)], color='#000000')

Expand Down Expand Up @@ -306,7 +306,7 @@ def plot_prior(result: Result,

data = result.data
bounds = result.debug['bounds']
estimate = result.get_parameters_estimate(estimate_type=estimate_type)
estimate = result.get_parameter_estimate(estimate_type=estimate_type)
sigmoid = result.configuration.make_sigmoid()

sigmoid_x = np.linspace(bounds['threshold'][0], bounds['threshold'][1], 1000)
Expand Down Expand Up @@ -369,8 +369,8 @@ def plot_2D_margin(result: Result,
if result.debug=={}:
raise ValueError("Expects priors and marginals saved. Try running psignifit(....., debug=True).")

parameters_keys = result.parameters_estimate_MAP.keys()
parameter_indices = {param: i for i, param in enumerate(sorted(parameters_keys))}
parameter_keys = result.parameter_estimate_MAP.keys()
parameter_indices = {param: i for i, param in enumerate(sorted(parameter_keys))}
other_param_ix = tuple(i for param, i in parameter_indices.items()
if param != first_param and param != second_param)
marginal_2d = np.sum(result.debug['posteriors'], axis=other_param_ix)
Expand Down
4 changes: 2 additions & 2 deletions psignifit/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_std_options():
def test_fit_basic(data):
options = get_std_options()
res = psignifit(data, **options)
param = res.parameters_estimate_MAP
param = res.parameter_estimate_MAP
assert isclose(param['threshold'], 0.0046, abs_tol=0.0001)
assert isclose(param['width'], 0.0045, abs_tol=0.0001)
assert isclose(param['lambda'], 0.01, abs_tol=0.0001)
Expand Down Expand Up @@ -80,7 +80,7 @@ def test_bias_analysis(data):
def test_fixed_parameters(data):
options = get_std_options()
res = psignifit(data, **options)
estim_param = res.parameters_estimate_MAP
estim_param = res.parameter_estimate_MAP
fixed_param = res.configuration.fixed_parameters
all_param_values = res.parameter_values

Expand Down
Loading

0 comments on commit 710f9f7

Please sign in to comment.