Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,49 @@ on:
paths:
- README.Rmd

# Needed for the commit step to push the re-rendered README back
permissions:
contents: write

jobs:
render:
name: Render README
runs-on: macOS-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
- uses: r-lib/actions/setup-pandoc@v2
- name: Install Core Dependencies
run: Rscript -e 'install.packages(c("rmarkdown", "dplyr", "remotes"))'
- name: Install Python

- uses: actions/setup-python@v5
with:
python-version: "3.x"

# README.Rmd imports pyllusion itself, so install the package (which brings in numpy, pandas,
# Pillow and scipy) rather than a hand-listed subset of its dependencies.
- name: Install Python dependencies
run: |
Rscript -e "remotes::install_github('rstudio/reticulate')"
Rscript -e "reticulate::install_miniconda()"
Rscript -e "reticulate::py_install(c('Pillow', 'scipy'), pip = TRUE)"
python -m pip install --upgrade pip
python -m pip install .

# reticulate comes from CRAN. It used to be installed from GitHub via remotes, which failed
# because an unauthenticated install_github() falls back to the bundled PAT and gets rate
# limited; there is no need for the development version here anyway.
- name: Install R dependencies
run: Rscript -e 'install.packages(c("rmarkdown", "reticulate"))'

- name: Render README
env:
# Point reticulate at the interpreter set up above, instead of the local path in README.Rmd
RETICULATE_PYTHON: ${{ env.pythonLocation }}/bin/python
run: Rscript -e 'rmarkdown::render("README.Rmd")'

- name: Commit results
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git commit README.md -m 'Re-build README.Rmd' || echo "No changes to commit"
git push origin || echo "No changes to commit"
git add README.md docs/img
git commit -m 'Re-build README.Rmd' || echo "No changes to commit"
git push origin HEAD:"${GITHUB_REF_NAME}" || echo "Nothing to push"
Comment thread
DominiqueMakowski marked this conversation as resolved.
Resolved
21 changes: 21 additions & 0 deletions NEWS.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
News
=====

1.5
---------

**Fixes**

- ``Delboeuf`` and ``Ebbinghaus``: fixed ``Size_Inner_Difference`` in ``get_parameters()``. An operator
precedence slip (``np.pi * a**2 / np.pi * b**2``, which evaluates as ``(pi * a**2 / pi) * b**2``) made
it return the product of the two squared radii instead of a difference of areas - it reported
0.000244140625 for two circles of *identical* size. It is now the signed difference between the areas
of the two inner circles, positive when the left circle is larger, as its docstring always described.
Both illusions were affected, since ``Ebbinghaus`` reuses the same helper. **Any analysis that used
this value will need re-running.**
- Corrected the name of that entry in the ``Delboeuf`` and ``Ebbinghaus`` docstrings, where it was
listed as ``Sine_Inner_Difference``.

**Misc**

- Repaired the "Render README" workflow, which could not run: it installed reticulate from GitHub
(rate limited without a token), never installed Pyllusion itself although ``README.Rmd`` imports it,
and relied on a hard-coded local path to a Python distribution.

1.4
---------

Expand Down
11 changes: 7 additions & 4 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ knitr::opts_chunk$set(



# Setup python - you need to change the path to your python distribution
# Setup python - locally, point `local_python` at your own python distribution. On CI the
# interpreter comes from RETICULATE_PYTHON instead, so the local path is skipped there (it also
# gets skipped if it does not exist, so a wrong path does not break anyone else's render).
library(reticulate)
# reticulate::use_python("D:/Downloads/WPy64-3902/python-3.9.0.amd64/")
reticulate::use_python("C:/Users/Zen Juen/Downloads/WPy64-3850/python-3.8.5.amd64")
# reticulate::use_python("C:/Users/Pham Thanh Tam/Desktop/WPy-3710b/python-3.7.1.amd64")
local_python <- "C:/Users/Zen Juen/Downloads/WPy64-3850/python-3.8.5.amd64"
if (!nzchar(Sys.getenv("CI")) && dir.exists(local_python)) {
reticulate::use_python(local_python)
}


# matplotlib <- import("matplotlib")
Expand Down
2 changes: 1 addition & 1 deletion pyllusion/Delboeuf/Delboeuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def get_parameters(self):
- **Illusion_Type** : `Congruent` if the illusion enhances the perception of the objective difference in the illusion, and `Incongruent` if it reduces the perceived difference.
- **Size_Inner_Left** : Size of the inner left circle.
- **Size_Inner_Right** : Size of the inner right circle.
- **Sine_Inner_Difference** : Difference in areas of the left and right inner circles.
- **Size_Inner_Difference** : Difference in areas of the left and right inner circles (signed, positive when the left circle is larger).
- **Size_Outer_Left** : Size of the outer left rim.
- **Size_Outer_Right** : Size of the outer right rim.
- **Distance** : Distance between the circles, by modifying `distance` of delboeuf_parameters().
Expand Down
9 changes: 8 additions & 1 deletion pyllusion/Delboeuf/delboeuf_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,17 @@ def _delboeuf_parameters_sizeinner(difference=0, size_min=0.25):
inner_size_right = size_bigger
inner_size_left = size_min

# Signed difference between the areas of the two inner circles, positive when the left one is
# larger. Note the parentheses: written as `np.pi * a**2 / np.pi * b**2` this evaluates left to
# right as `(pi * a**2 / pi) * b**2`, i.e. the product of the squared radii, which is what this
# returned before.
area_left = np.pi * (inner_size_left / 2) ** 2
area_right = np.pi * (inner_size_right / 2) ** 2

parameters = {
"Difference": difference,
"Size_Inner_Left": inner_size_left,
"Size_Inner_Right": inner_size_right,
"Size_Inner_Difference": np.pi * (size_bigger / 2) ** 2 / np.pi * (size_min / 2) ** 2,
"Size_Inner_Difference": area_left - area_right,
}
return parameters
2 changes: 1 addition & 1 deletion pyllusion/Ebbinghaus/Ebbinghaus.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def get_parameters(self):
- **Illusion_Type** : `Congruent` if the illusion enhances the perception of the objective difference in the illusion, and `Incongruent` if it reduces the perceived difference.
- **Size_Inner_Left** : Size of the inner left circle.
- **Size_Inner_Right** : Size of the inner right circle.
- **Sine_Inner_Difference** : Difference in areas of the left and right inner circles.
- **Size_Inner_Difference** : Difference in areas of the left and right inner circles (signed, positive when the left circle is larger).
- **Size_Outer_Left** : Size of the surrounding circles around the left inner circle.
- **Size_Outer_Right** : Size of the surrounding circles around the right inner circle.
- **Distance**: Distance between the circles, by modifying `distance` of ebbinghaus_parameters().
Expand Down
2 changes: 1 addition & 1 deletion pyllusion/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
The Pyllusion module.
"""
__version__ = "1.4"
__version__ = "1.5"

from .Autostereogram import *

Expand Down
25 changes: 25 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import numpy as np
import pytest

import pyllusion


Expand Down Expand Up @@ -498,3 +500,26 @@ def test_analyze_luminance():

out = pyllusion.analyze_luminance(image, average=False)
assert out["Luminance"].shape == (50, 50)


def test_size_inner_difference():
# `Size_Inner_Difference` is the signed difference between the areas of the two inner circles.
# It used to be mis-parenthesised (`pi * a**2 / pi * b**2`, which is the product of the squared
# radii) and returned 0.000244140625 for two circles of identical size.
for illusion in [pyllusion.Delboeuf, pyllusion.Ebbinghaus]:
# Identical circles -> no difference
parameters = illusion(difference=0).get_parameters()
assert parameters["Size_Inner_Difference"] == 0

# Positive difference -> left circle larger -> positive area difference
parameters = illusion(difference=1).get_parameters()
area_left = np.pi * (parameters["Size_Inner_Left"] / 2) ** 2
area_right = np.pi * (parameters["Size_Inner_Right"] / 2) ** 2
assert parameters["Size_Inner_Difference"] == pytest.approx(area_left - area_right)
assert parameters["Size_Inner_Difference"] > 0
# difference=1 doubles the area, as the size is scaled by sqrt(1 + abs(difference))
assert area_left == pytest.approx(2 * area_right)

# Sign follows the side the larger circle is on
parameters = illusion(difference=-1).get_parameters()
assert parameters["Size_Inner_Difference"] < 0
Loading