Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove hard dependency of the DeerLab's installation routine and scripts on MKL #330

Merged
merged 23 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from 15 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
10 changes: 4 additions & 6 deletions .github/workflows/ci_PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.8]
python-version: [3.9]
steps:
- uses: actions/checkout@v2

Expand All @@ -24,9 +24,8 @@ jobs:
if: startsWith(runner.os, 'Windows')
with:
path: |
~\pipwin
~\AppData\Local\pip\Cache
key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }}
key: cache-${{ runner.os }}-${{ hashFiles('**/setup.py') }}
restore-keys: |
{{ runner.os }}-pip-

Expand All @@ -35,7 +34,7 @@ jobs:
with:
path: |
~/Library/Caches/pip
key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }}
key: cache-${{ runner.os }}-${{ hashFiles('**/setup.py') }}
restore-keys: |
{{ runner.os }}-pip-

Expand All @@ -44,7 +43,7 @@ jobs:
with:
path: |
~/.cache/pip
key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }}
key: cache-${{ runner.os }}-${{ hashFiles('**/setup.py') }}
restore-keys: |
{{ runner.os }}-pip-

Expand All @@ -53,7 +52,6 @@ jobs:
run: |
python -m pip install --upgrade pip
python setup.py install
python -m pip install pytest

- name: Test with pytest
run: pytest
2 changes: 0 additions & 2 deletions .github/workflows/ci_scheduled.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
if: startsWith(runner.os, 'Windows')
with:
path: |
~\pipwin
~\AppData\Local\pip\Cache
key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }}
restore-keys: |
Expand Down Expand Up @@ -54,7 +53,6 @@ jobs:
run: |
python -m pip install --upgrade pip
python setup.py install
python -m pip install pytest

- name: Test with pytest
run: pytest
1 change: 1 addition & 0 deletions .github/workflows/package_upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
- name: Build distribution
run: |
python setup.py sdist
./setup.py bdist_wheel
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
Expand Down
14 changes: 7 additions & 7 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ requirements:
- numpy
- scipy
- cvxopt
- dill
- pytest

about:
home: https://jeschkelab.github.io/DeerLab/index.html
license: MIT
summary: 'Comprehensive package for data analysis of dipolar EPR spectroscopy'
description: |
DeerLab is a Python package for the analysis of dipolar EPR (electron paramagnetic resonance)
spectroscopy data. Dipolar EPR spectroscopy techniques include DEER (double electron-electron resonance),
RIDME (relaxation-induced dipolar modulation enhancement), and others.
DeerLab consists of a collection of functions for modelling, data processing, and least-squares fitting.
They can be combined in scripts to build custom data analysis workflows. DeerLab supports both classes of
distance distribution models: non-parametric (Tikhonov regularization and related) and parametric
(multi-Gaussians etc). It also provides a selection of background and experiment models.
DeerLab is a comprehensive free scientific software package for Python focused on modelling,
penalized least-squares regression, and uncertainty quantification. It provides highly
specialized on the analysis of dipolar EPR (electron paramagnetic resonance) spectroscopy data.
Dipolar EPR spectroscopy techniques include DEER (double electron-electron resonance),
RIDME (relaxation-induced dipolar modulation enhancement), and others.
dev_url: https://jeschkelab.github.io/DeerLab
2 changes: 1 addition & 1 deletion deerlab/dd_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def _nonparametric():
dd_nonparametric = Model(_nonparametric,constants='r')
dd_nonparametric.description = 'Non-parametric distribution model'
# Parameters
dd_nonparametric.addlinear('P',vec=len(r),lb=0,par0=0,description='Non-parametric distance distribution',unit="nm⁻¹", normalization=lambda P: P/np.trapz(P,r))
dd_nonparametric.addlinear('P',vec=len(r),lb=0,par0=0,description='Non-parametric distance distribution',unit="nm⁻¹", normalization=lambda P: _normalize(r,P))
return dd_nonparametric


Expand Down
21 changes: 15 additions & 6 deletions docsrc/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ DeerLab installs the following packages:
* `tqdm <https://github.com/tqdm/tqdm>`_ - A lightweight package for smart progress meters.
* `dill <https://github.com/uqfoundation/dill>`_ - An extension of Python's pickle module for serializing and de-serializing python objects.

The installed numerical computing packages (numpy, scipy, cvxopt) are linked against different BLAS libraries depending on the OS:

* Windows: linked against the Intel Matrix Kernel Library (MKL)
* Linux: linked against OpenBLAS
* Mac: linked against BLAS/LAPACK from the Accelerate framework

Installing from Anaconda
*************************

Expand Down Expand Up @@ -125,6 +119,21 @@ In order to install DeerLab but be able to edit the code or update frequently wi

Any changes made to the source code will then immediate effect.


Linking against BLAS libraries
*******************************

The installed numerical computing packages (numpy, scipy, cvxopt) are automatically linked against different BLAS libraries depending on the OS:

* Linux: OpenBLAS
* Mac: BLAS/LAPACK from the Accelerate framework

In Windows systems, these packages can be linked against the Intel MKL libraries. To do so, DeerLab provides a script ``mkl_link.py`` that can be used to link against the Intel MKL libraries automatically::

python mkl_link.py

The script will download the binaries from the Gohlke repository and override any currently installed version of the mentioned packages.

Installation failed
--------------------

Expand Down
82 changes: 12 additions & 70 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,4 @@
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.develop import develop
from sys import executable
import platform
import subprocess

# Custom OS-specific installation script
def install_dependencies(develop_mode=False):
#-----------------------------------------------------------------------

# At the moment the dependencies must be handled manually this way due to
# the dependency of Windows systems on the external Gohlke binaries. This
# also means that the package must be distributed as a source tarball instead
# of the commonly used wheels.
# As soon as Numpy, Scipy and CVXOpt start distributing their own binaries for
# Windows systems this will no longer be necessary and all dependencies will be
# able to be handled by pip automatically.

# DeerLab dependencies on the PyPI
dependencies = ["memoization","matplotlib","tqdm","joblib","dill"]

if platform.system() == 'Windows':
# Use own forked pipwin repo for self-patched fixes
dependencies += ["git+https://github.com/luisfabib/pipwin"]
else:
dependencies += ["numpy","scipy","cvxopt"]
if develop_mode:
dependencies += ["pytest"]

# Commands for pip installation of dependencies
pipinstall = [executable,'-m','pip','install']
userlevel = ['--user']

# Easier to Ask Forgiveness than Permission Principle:
# try to install dependencies system-wide, if fails then at user-level
for dependency in dependencies:
try:
subprocess.run(pipinstall+[dependency],check=True)
except:
subprocess.run(pipinstall+userlevel+[dependency],check=False)

# Download and install pre-compiled binaries for Windows-systems
if platform.system() == 'Windows':
# Refresh the pipwin cache to get the latest repo status
subprocess.run([executable,'-m','pipwin','refresh'],check=False)
# Install Numpy,SciPy, CVXopt linked to MKL from Gohlken's repository
subprocess.run([executable,'-m','pipwin','install','numpy','--filter=mkl'],check=False)
subprocess.run([executable,'-m','pipwin','install','scipy'],check=False)
subprocess.run([executable,'-m','pipwin','install','cvxopt'],check=False)
#-----------------------------------------------------------------------

class install_routine(install):
#-----------------------------------------------------------------------
"""Customized setuptools install command"""
def run(self):
install.run(self)
install_dependencies()
#-----------------------------------------------------------------------

class develop_routine(develop):
#-----------------------------------------------------------------------
"""Customized setuptools install command"""
def run(self):
develop.run(self)
install_dependencies(develop_mode=True)
#-----------------------------------------------------------------------

setup(
name='DeerLab',
Expand All @@ -85,10 +19,18 @@ def run(self):
description='Comprehensive package for data analysis of dipolar EPR spectroscopy',
long_description=open('README.md', encoding='utf-8').read(),
long_description_content_type="text/markdown",
cmdclass={
'install': install_routine,
'develop': develop_routine
},
install_requires = [
'numpy>=1.21.0',
'cvxopt>=1.0.0',
'scipy>=1.6.3',
'joblib>-1.0.0',
'dill>=0.3.0',
'tqdm>=4.51.0',
'matplotlib>=3.3.4',
'memoization>=0.3.1',
'pytest>=6.2.2',
'setuptools>=53.0.0',
],
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Science/Research',
Expand Down
2 changes: 1 addition & 1 deletion test/test_dipolarmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def test_ex_3pdeer_fit():

assert np.allclose(V3pdeer,result.model,atol=1e-1) and ovl(result.P/1e5,Pr)>0.975
# ======================================================================
test_ex_3pdeer_fit()

# ======================================================================
def test_ex_4pdeer_type():
"Check the 4-pulse DEER experimental model."
Expand Down
33 changes: 33 additions & 0 deletions upgrade_mkl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from sys import executable
import platform
import subprocess
import os

MKL_LINKED = os.environ.get('MKL_LINKED', False)

# Custom OS-specific installation script
def install_MKL_dependencies():
#-----------------------------------------------------------------------

if platform.system() != 'Windows':
raise SystemError('MKL dependencies are only available on Windows systems.')

# At the moment the dependencies must be handled manually this way
subprocess.run([executable,'-m','pip','install','git+https://github.com/luisfabib/pipwin'],check=False)

try:
# Install Numpy,SciPy, CVXopt linked to MKL from Gohlken's repository
subprocess.run([executable,'-m','pipwin','install','numpy','--filter=mkl'],check=False)
subprocess.run([executable,'-m','pipwin','install','scipy'],check=False)
subprocess.run([executable,'-m','pipwin','install','cvxopt'],check=False)
except:
subprocess.run([executable,'-m','pipwin','install','numpy','--filter=mkl','--user'],check=False)
subprocess.run([executable,'-m','pipwin','install','scipy','--user'],check=False)
subprocess.run([executable,'-m','pipwin','install','cvxopt','--user'],check=False)
#-----------------------------------------------------------------------


if __name__ == "__main__":
print("Installing MKL-linked packages from the Gohlke repository...")
install_MKL_dependencies()
print("Finished installing MKL-linked packages from the Gohlke repository.")