Skip to content

Commit

Permalink
setup: bump dclab to 0.61.3 (replace rpy2 with wrapper) (close #73, c…
Browse files Browse the repository at this point in the history
…lose #161)
  • Loading branch information
paulmueller committed Sep 13, 2024
1 parent a1b3157 commit 59f9d0d
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 36 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ jobs:
uses: r-lib/actions/setup-r@v2
with:
r-version: '4.1.2'
- name: Install R packages for lme4
if: matrix.extras == 'all'
shell: bash
run: |
R --version
R -e "install.packages(c('statmod','nloptr','lme4'),repos='http://cran.rstudio.org')"
- name: Install Python dependencies
run: |
# prerequisites
Expand Down
2 changes: 0 additions & 2 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ build:
jobs:
post_checkout:
- git fetch --unshallow || true
pre_install:
- RPY2_CFFI_MODE=ABI
python:
install:
- requirements: docs/requirements.txt
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
2.18.1
- setup: bump dclab to 0.61.3 (replace rpy2 with wrapper) (#73 #161)
2.18.0
- BREAKING CHANGE: set default viscosity model for Young's modulus
computation to "buyukurganci-2022", because it is more accurate
Expand Down
2 changes: 0 additions & 2 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ dclab>=0.58.2
h5py
matplotlib
numpy
# Don't forget to set the environment variable RPY2_CFFI_MODE=ABI on rtd!
rpy2
pyqt5
scipy
sphinx
Expand Down
16 changes: 3 additions & 13 deletions docs/sec_qg_lme4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,15 @@ Statistical significance testing (R and lme4)
Since version 2.5.0, Shape-Out 2 allows you to quantify the statistical
significance (p-value) when comparing two measurement groups. For this to
work, you need to have R installed (tested with
`R 3.6.3 <https://cran.r-project.org/bin/windows/base/old/3.6.3/>`_ ).
`R 4.1.2 <https://cran.r-project.org>`_ ).
The analysis uses linear mixed effects models (LMM) as described
in :cite:`Herbig2018` and yields results identical to those obtained
with Shape-Out 1.

.. warning::
Unfortunately, LMM analysis currently does not work with the .app or
.pkg bundle on macOS or the Windows installer. This problem is tracked in
`issue #73
<https://github.com/ZELLMECHANIK-DRESDEN/ShapeOut2/issues/73>`_ and
`issue #161
<https://github.com/ZELLMECHANIK-DRESDEN/ShapeOut2/issues/161>`_.
If you are using macOS and you would like to use LMM analysis, you have to
install Shape-Out 2 as a Python package (see :ref:`sec_installation`).

The LMM analysis is performed using the lme4 R package
and is based on the :ref:`implementation in dclab <dclab:sec_av_lme4>`
(please read for more information on the options available) which uses
`rpy2 <https://github.com/rpy2/rpy2/>`_ to connect to R.
(please read for more information on the options available) which implements
a wrapper calling ``Rscript``.
Here, we make use of the dataset :cite:`FigshareLMM` to illustrate this
functionality.

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ classifiers = [
license = {text = "GPL v3"}
dependencies = [
"fcswrite>=0.5.1",
"dclab[dcor,http]>=0.60.1",
"dclab[dcor,http]>=0.61.3",
"h5py>=2.8.0",
"numpy>=1.21", # CVE-2021-33430
"pyqt5",
Expand Down
7 changes: 7 additions & 0 deletions shapeout2/gui/compute/comp_lme4_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ def __init__(self, parent, rlme4_results, *args, **kwargs):

# summary text
summary = []
if res["lme4 messages"]:
summary += ["lme4 messages"]
summary += ["-------------"]
summary += str(res["lme4 messages"]).split("\n")
summary += "\n"
summary += ["Model summary"]
summary += ["-------------"]
summary += self.parse_r_model_summary(
str(res["r model summary"]).split("\n"))
summary += "\n"
summary += ["Coefficient table"]
summary += ["-----------------"]
summary += str(res["r model coefficients"]).split("\n")
summary += "\n"
summary += ["Anova test"]
summary += ["----------"]
summary += str(res["r anova"]).split("\n")
Expand Down
7 changes: 1 addition & 6 deletions shapeout2/gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import webbrowser

import dclab
from dclab.lme4.rlibs import rpy2, MockRPackage
from dclab.lme4 import rsetup
import h5py
import numpy
Expand Down Expand Up @@ -126,8 +125,6 @@ def __init__(self, *arguments):
self.on_action_compute_statistics)
self.actionComputeSignificance.triggered.connect(
self.on_action_compute_significance)
self.actionComputeSignificance.setVisible(
not isinstance(rpy2, MockRPackage)) # only show if rpy2 is there
# Export menu
# data
self.actionExportData.triggered.connect(self.on_action_export_data)
Expand Down Expand Up @@ -607,7 +604,7 @@ def on_action_compute_significance(self):
else:
QtWidgets.QMessageBox.critical(
self, "R not found!",
"The R executable was not found by rpy2. Please add it "
"The R executable was not found. Please add it "
+ "to the PATH variable or define it manually in the "
+ "Shape-Out preferences.")

Expand Down Expand Up @@ -837,8 +834,6 @@ def on_action_software(self):
pg,
scipy,
]
if not isinstance(rpy2, MockRPackage):
libs.append(rpy2)

sw_text = f"Shape-Out {version}\n\n"
sw_text += f"Python {sys.version}\n\n"
Expand Down
15 changes: 4 additions & 11 deletions shapeout2/gui/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,16 @@
import pkg_resources
import platform

from dclab.lme4.rlibs import (
rpy2, MockRPackage, RPY2UnavailableError, RUnavailableError)
from dclab.rtdc_dataset.fmt_dcor import access_token
from dclab.lme4 import rsetup
from PyQt5 import uic, QtCore, QtWidgets
from PyQt5.QtCore import QStandardPaths

from dclab.lme4.rsetup import RNotFoundError
from .widgets import show_wait_cursor
from ..extensions import ExtensionManager, SUPPORTED_FORMATS


if isinstance(rpy2, MockRPackage):
RPY2_AVAILABLE = not isinstance(rpy2.exception, RPY2UnavailableError)
else:
RPY2_AVAILABLE = True


class ExtensionErrorWrapper:
def __init__(self, ehash):
self.ehash = ehash
Expand Down Expand Up @@ -55,13 +48,13 @@ def __init__(self, parent, *args, **kwargs):
self.parent = parent

# Get default R path
if RPY2_AVAILABLE and rsetup.has_r():
if rsetup.has_r():
rdefault = rsetup.get_r_path()
else:
rdefault = ""

# disable R settings
self.tab_r.setEnabled(RPY2_AVAILABLE)
self.tab_r.setEnabled(rsetup.has_r())

#: configuration keys, corresponding widgets, and defaults
self.config_pairs = [
Expand Down Expand Up @@ -160,7 +153,7 @@ def reload_lme4(self, install=False):
if pathlib.Path(binary).is_file():
try:
rsetup.set_r_path(binary)
except RUnavailableError as exc:
except RNotFoundError as exc:
QtWidgets.QMessageBox.information(
self,
"No compatible R version found",
Expand Down
5 changes: 4 additions & 1 deletion tests/test_gui_compute_lme4.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
import pathlib
import socket

from dclab.lme4 import Rlme4, bootstrapped_median_distributions, rsetup
from shapeout2.gui.main import ShapeOut2
from shapeout2 import session
from shapeout2.gui.compute.comp_lme4 import ComputeSignificance
import pytest

pytest.importorskip("rpy2")

if not (rsetup.has_r() and rsetup.has_lme4()):
pytest.skip(allow_module_level=True)

data_path = pathlib.Path(__file__).parent / "data"
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
Expand Down

0 comments on commit 59f9d0d

Please sign in to comment.