Skip to content

Commit

Permalink
WIP, ENH: Ship platform specific edfapi shared library files (#14)
Browse files Browse the repository at this point in the history
* WIP: Add libedfapi (for Macos and Linux)

* WIP: Add ability to use shipped edfapi shared library (macos and linux)

* FIX: command

* FIX: run

* FIX: try

* FIX: dont ignore shared library

* FIX: OK now add the .so file that was being ignored

* FIX: Remove unnecessary framework files

* Add GHA to run tests on MacOS & Linux

* FIX: flake

* FIX: update lib path

* FIX: version

* FIX: dont trigger tests when pushed to non-main branches

* WIP: launch macos job on circle

* FIX: format error

* FIX: version

* Revert "FIX: update lib path"

This reverts commit f6a674c.

* Revert "FIX: Remove unnecessary framework files"

This reverts commit 72d38fb.

* Tell git not to parse files in libedfapi/macos

* use -diff instead of binary

* WIP: try without Headers

* WIP: try without Versions subdir in MacOS libedfapi

* FIX: path

* TST: Add Intel Mac Runner

* Do I need to specify Xcode?

* Revert "Do I need to specify Xcode?"

This reverts commit 9a0f963.

* MAINT: Switch build backend to setuptools

The reason is that I would like to use setuptools to build wheels instead of hatch. This is because I want to keep this package design in line with other similar packages in my community/field, i.e. antio

* MAINT: Move from flat-layout -> src-layout package structure

Since we now have the libedfapi folder, I think it is cleaner to keep this and eyelinkio in a src folder instead of at the root directory. This also mimics antio, and helps setuptools work automagically

* FIX: Point ruff to src/eyelinkio

* MAINT: Remove hatch configuration options from pyproject.toml

Since we switched the build backend to setuptools in #47c5627

* Add Manifest.IN file

This should make surethat src/libedfapi is distributed along with src/eyelinkio in tarballs and wheels

* Remove .gitattributes

* Add windows shared libraries and add a windows CI

* FIX: Dont use export command on Windows runner

* FIX: pathlib WindowsPath not compatible with ctypes.CDLL ??

* WIP: Try without windows static files (.lib)

* WIP: Ok now try dropping the shippzed Zlib dynamic library on Windows

* Revert "WIP: Ok now try dropping the shippzed Zlib dynamic library on Windows"

This reverts commit 1b9f4d2.

* MAINT: Replace MacOS libedfapi with the latest release...

Latest release is:

'4.2.1197.0 MacOS X   standalone Sep 27 2024'

But I initially added the previous release to the repository:

'4.2.762.0 MacOS X   standalone Jul 20 2023'

* TST, WIP: Add Windows Runner on CircleCI

* FIX: format

* FIX: config

* FIX: orb

* MAINT: Use most up to date version of libedfapi on windows.

The initial files I used were from a version of libedfapi released in 2015.

These files are from the most current release: EyeLink Developers Kit / API v2.1.1197, Released October 1st 2024

* FIX: Include updated ZLIB dynamic library, too

* DOC: Update docs

* rename CI

* FIX: update test name and no need to install edf-api for doc build

* FIX: Markdown flakes
  • Loading branch information
scott-huberty authored Dec 11, 2024
1 parent 1901330 commit a6d2c1d
Show file tree
Hide file tree
Showing 31 changed files with 274 additions and 62 deletions.
62 changes: 51 additions & 11 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
version: 2.1


orbs:
win: circleci/windows@4.1.1 # The Windows orb gives you everything you need to start using the Windows executor

jobs:
test:
Test-Installed-SDK:
docker:
- image: circleci/python:3.10

Expand All @@ -21,12 +25,54 @@ jobs:
sudo ldconfig
python -m pip install --upgrade pip
pip install -e ".[dev]"
- run:
name: Set environment variables
command: |
export EYELINKIO_USE_INSTALLED_EDFAPI=true
- run:
name: Run tests
command: |
pytest
test-macos:
macos:
xcode: 14.2.0
steps:
- checkout

- run:
name: Install dependencies
command: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- run:
name: Set environment variables
command: |
export EYELINKIO_USE_INSTALLED_EDFAPI=false
- run:
name: Run tests
command: |
pytest
test-windows:
executor: win/server-2022
steps:
- checkout
- run:
name: Install dependencies
command: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- run:
name: Set environment variables
command: |
set EYELINKIO_USE_INSTALLED_EDFAPI=false
- run:
name: Run tests
command: |
pytest
build-docs:
docker:
- image: circleci/python:3.10
Expand All @@ -35,14 +81,6 @@ jobs:
- run:
name: Install dependencies
command: |
sudo apt-get update
sudo apt install software-properties-common
sudo apt-get update
sudo add-apt-repository "deb http://download.sr-support.com/software SRResearch main"
wget -O - "http://download.sr-support.com/software/SRResearch_key" | sudo apt-key add -
sudo apt-get update
sudo apt-get install eyelink-edfapi
sudo ldconfig
python -m pip install --upgrade pip
pip install -e ".[dev]"
- run:
Expand Down Expand Up @@ -79,11 +117,13 @@ workflows:
version: 2
test:
jobs:
- test
- Test-Installed-SDK
- build-docs
- test-macos
- test-windows
- docs-deploy:
requires:
- test
- Test-Installed-SDK
- build-docs
filters:
branches:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ jobs:
with:
python-version: '3.11'
- run: pip install -e ".[dev]"
- run: ruff check eyelinkio
- run: ruff check src/eyelinkio
42 changes: 42 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Run Tests (No SDK)

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest # Latest Apple Silicon macOS
- macos-13 # Latest Intel-based macOS
- windows-latest
python-version: ['3.10']

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
- name: Set environment variables On macOS and Linux
if: runner.os != 'Windows'
run: |
export EYELINKIO_USE_INSTALLED_EDFAPI=false
- name: Run tests
run: pytest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ __pycache__/

# C extensions
*.so
# Except for the following files
!libedfapi/linux/libedfapi.so

# Distribution / packaging
.Python
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
recursive-include src *
recursive-exclude tests *
46 changes: 40 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

A lightweight library to import SR Research EDF files into Python.

**This Software is currenly pre-alpha, meaning it is currently being developed**: Changes to the API (function names, etc.) may occur without warning. This library has been tested with MacOS and Linux, but not Windows.
**This Software is currenly pre-alpha, meaning it is currently being developed**: Changes to the API (function names, etc.) may occur without warning.

## About the Eyelink Data Format

The EyeLink Data Format (EDF; not to be confused with the [European Data Format](<https://www.edfplus.info>)) is used for storing eyetracking data from EyeLink eyetrackers. It was put forward by the company [SR Research](<https://www.sr-research.com>). SR Research EDF files store data in a binary format, and reading these files currently requires the ``eyelink-edfapi`` C library that is included in the EyeLink Software Development Kit.
The EyeLink Data Format (EDF; not to be confused with the
[European Data Format](<https://www.edfplus.info>)) is used for storing eyetracking data
from EyeLink eyetrackers. It was put forward by the company
[SR Research](<https://www.sr-research.com>). SR Research EDF files store data in a
binary format, and reading these files requires interfacing with ``eyelink-edfapi`` C
library that is typically included in the EyeLink Software Development Kit. EyeLinkIO
Includes the necessary binaries to read EDF files, but can also be configured to use the
EDF API library that is installed on your computer.

## Dependencies

Strictly speaking, EyeLinkIO only requires Numpy. For converting data to pandas ``DataFrames`` or MNE-Python ``Raw`` instances, you must have those respective packages installed.

> [!IMPORTANT]
> - You must have the [EyeLink Software Development Kit](<https://www.sr-research.com/support/forum-3.html>) installed on your computer
> - You must register an account on the forum to access the download (registration is free)
> [!NOTE]
>
> - EyeLinkIO includes the Eyelink EDF API binary files that are needed to read EDF files.
> - [See](#using-the-eyelink-developers-kit-edf-api-to-read-edf-files) If you want to use the EyeLink Developers Kit's EDF API library that is installed on your computer.
## Installation

Expand All @@ -39,9 +47,11 @@ pip install -e ./eyelinkio
```

> [!IMPORTANT]
> To use the editable installation, you should:
>
>- Fork the repository on GitHub first.
>- Clone your forked repository to your local machine.
>- Make sure you're in the directory *containing* the cloned `eyelinkio` folder when you run the command above
>- Make sure you're in the directory *containing* the cloned `eyelinkio` folder when you run the command provided above
This package is not currently available on Conda.

Expand Down Expand Up @@ -108,6 +118,30 @@ raw, calibration = edf_file.to_mne()

See the [documentation](https://scott-huberty.github.io/eyelinkio/) for more.

#### Using The EyeLink Developers Kit (EDF API) to read EDF files

EyeLinkIO includes the Eyelink EDF API binary files that are needed to read EDF files,
and by default it will rely on these files when reading reading your EDF files. However,
if you have the
[Eyelink Developers Kit](https://www.sr-research.com/support/forum-9.html)
installed on your computer, you can explicitly direct
EyeLinkIO to rely on the EDF API library that is included in the EyeLink Developers Kit,
by setting the environment variable `EYELINKIO_USE_INSTALLED_EDFAPI` to `true` *before*
importing the package:

```python
import os
os.environ["EYELINKIO_USE_INSTALLED_EDFAPI"] = "true"

import eyelinkio
edf = eyelinkio.read_edf("path/to/edf/file")
```

> [!NOTE]
>
> - First download the [EyeLink Software Development Kit](<https://www.sr-research.com/support/forum-3.html>)
> - You must register an account on the forum to access the download (registration is free)
## Acknowledgements

This package was originally adapted from the [pyeparse](<https://github.com/pyeparse/pyeparse>) package (created by several of the core developers of [MNE-Python](<https://mne.tools/dev/index.html>)). It copies much of the EDF (Eyelink Data Format) reading code.
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ following command from the root of the package:
.. code-block:: bash
$ ruff check eyelinkio
$ ruff check src/eyelinkio
To build the docs:

Expand Down
9 changes: 5 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ A lightweight library to import SR Research EDF files into Python.

.. important::
**This Software is pre-alpha, meaning it is currently being developed**: Changes to the
API (function names, etc.) may occur without warning. This library has been tested with
MacOS and Linux, but not Windows.
API (function names, etc.) may occur without warning.

About the EyeLink Data Format
=============================
Expand All @@ -15,8 +14,10 @@ The EyeLink Data Format (EDF; not to be confused with the
`European Data Format <https://www.edfplus.info>`_) is used for storing eyetracking data
from EyeLink eyetrackers. It was put forward by the company
`SR Research <https://www.sr-research.com>`_. SR Research EDF files store data in a
binary format, and reading these files currently requires the `eyelink-edfapi` C
library that is included in the Eyelink Software Developers Kit.
binary format, and reading these files currently relies on the `eyelink-edfapi` C
library that is included in the Eyelink Developers Kit. EyeLinkIO includes
the binary files necessary to read EDF files, so the end-user does not need to install
the Eyelink Software Developers Kit to use EyeLinkIO.

Dependencies
============
Expand Down
39 changes: 32 additions & 7 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
User Guide
==========

.. important::
- You must have the `EyeLink Software Development Kit <https://www.sr-research.com/support/forum-3.html>`_ installed on your computer
- You must register an account on the forum to access the download (registration is free)


Installation
------------

Expand Down Expand Up @@ -44,9 +39,12 @@ For contributors to EyeLinkIO:
pip install --editable ./eyelinkio
.. important::

To install the package in editable mode, you must:

- Fork the repository on GitHub first.
- Clone your forked repository to your computer.
- Make sure you're in the directory *containing* the cloned ``eyelinkio`` folder when you run the command above.
- Make sure you're in the directory *containing* the cloned ``eyelinkio`` folder when you run the command provided above.

Example Usage
-------------
Expand Down Expand Up @@ -133,4 +131,31 @@ You can convert an instance of EDF to a pandas DataFrame or an MNE Raw instance
.. seealso::

`Working with eyetracking data in MNE <https://mne.tools/stable/auto_tutorials/preprocessing/90_eyetracking_data.html>`_
`Working with eyetracking data in MNE <https://mne.tools/stable/auto_tutorials/preprocessing/90_eyetracking_data.html>`_


Using the EDF API Library installed on your system
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you have the EDF API Library installed on your system, you can explicitly direct
EyeLinkIO to rely on it when reading your EDF files. This can be done by setting the
``EYELINKIO_USE_INSTALLED_EDFAPI`` parameter to ``true`` before importing EyeLinkIO.

.. code:: python
import os
os.environ["EYELINKIO_USE_INSTALLED_EDFAPI"] = "true"
from eyelinkio.io import read_edf
fname = _get_test_fnames()[0] # Replace this function with the path to your EDF file
edf_file = read_edf(fname)
print(edf_file)
Otherwise, EyeLinkIO will rely on the EDF API Library that comes with the package.

.. note::

If you want to install the EyeLink Developers Kit, you can download it from the
`SR Research website <https://www.sr-research.com/support/forum-3.html>`_. You will
need to register an account to access the download page (registration is free).
31 changes: 5 additions & 26 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
requires = ["setuptools >= 64.0.0"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
package-dir = {""= "src"}

[project]
name = "eyelinkio"
Expand Down Expand Up @@ -67,30 +70,6 @@ dev = ["eyelinkio[test,doc,build,full]"]
# Forum = "https://mne.discourse.group/"
# "Source Code" = "https://github.com/mne-tools/mne-python/"

[tool.hatch.build]
exclude = [
"/.*",
"/*.yml",
"/*.yaml",
"/*.toml",
"/*.txt",
"/eyelinkio/**/tests",
"/logo",
"/doc",
"/tools",
"/tutorials",
"/examples",
"/codemeta.json",
"/ignore_words.txt",
"/Makefile",
"/CITATION.cff",
"/CONTRIBUTING.md",
] # tracked by git, but we don't want to ship those files

[tool.hatch.version]
source = "vcs"
raw-options = { version_scheme = "release-branch-semver" }

[tool.codespell]
ignore-words = "ignore_words.txt"
builtin = "clear,rare,informal,names,usage"
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit a6d2c1d

Please sign in to comment.