Skip to content

Commit

Permalink
Initial functionality
Browse files Browse the repository at this point in the history
- Start/stop recordings
- Start/stop calibrations
- Request version
- Estimate clock offsets
- Send messages/notifications/annotations
- Start plugins
  • Loading branch information
papr committed Feb 25, 2022
1 parent 6ee9eaf commit eefb0d5
Show file tree
Hide file tree
Showing 14 changed files with 459 additions and 26 deletions.
11 changes: 11 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
1.0.0a1 (2020-02-25)
####################

Initial functionality:

- Start/stop recordings
- Start/stop calibrations
- Request version
- Estimate clock offsets
- Send messages/notifications/annotations
- Start plugins
20 changes: 20 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,23 @@
.. image:: https://img.shields.io/badge/skeleton-2021-informational
:target: https://blog.jaraco.com/skeleton

Pupil Core Network API Client
#############################

This Python module is a client for the `Pupil Core Network API`_. It implements many of
the functionalities demonstrated in the `Pupil Helpers`_.

.. _Pupil Core Network API: https://docs.pupil-labs.com/developer/core/network-api/
.. _Pupil Helpers: https://github.com/pupil-labs/pupil-helpers/tree/master/python

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

We recommend installing the pre-packaged binary wheels from PyPI:

.. code-block:: console
pip install pupil-core-network-client
For more information see the `documentation <https://pupil-core-network-client.readthedocs.io>`_.
42 changes: 42 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
:tocdepth: 2

.. _api:

Module API
**********

The main entrypoint of the API is the
:py:class:`Device <pupil_labs.pupil_core_network_client.Device>` class. You can use it
to

- connect to a Pupil Capture or Pupil Service instance,
- start and stop `recordings`_
- start and stop `calibrations`_
- start `plugins`_
- send messages to the `IPC backend`_
- send `notifications`_
- send `annotations`_

.. _recordings: https://docs.pupil-labs.com/core/software/pupil-capture/#recording
.. _calibrations: https://docs.pupil-labs.com/core/software/pupil-capture/#calibration
.. _plugins: https://docs.pupil-labs.com/core/software/pupil-capture/#plugins
.. _IPC backend: https://docs.pupil-labs.com/developer/core/network-api/#ipc-backbone
.. _notifications: https://docs.pupil-labs.com/developer/core/network-api/#notification-message
.. _annotations: https://docs.pupil-labs.com/developer/core/network-api/#remote-annotations

.. autoclass:: pupil_labs.pupil_core_network_client.Device
:members:
:undoc-members:
:show-inheritance:

The device class calculates the clock offset between the
:py:attr:`client clock <pupil_labs.pupil_core_network_client.Device.client_clock>` and
the pupil time base of the connected Pupil Core software. To account for varying network
delay, it performs multiple measurements. The resulting statistics are exposed via the
:py:attr:`clock_offset_statistics <pupil_labs.pupil_core_network_client.Device.clock_offset_statistics>`
attibute.

.. autoclass:: pupil_labs.pupil_core_network_client.ClockOffsetStatistics
:members:
:undoc-members:
:show-inheritance:
8 changes: 7 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#!/usr/bin/env python3

extensions = ['sphinx.ext.autodoc', 'jaraco.packaging.sphinx', 'rst.linker']
extensions = [
'sphinx.ext.autodoc',
'jaraco.packaging.sphinx',
'rst.linker',
'sphinx.ext.viewcode',
]

master_doc = "index"

Expand Down Expand Up @@ -33,3 +38,4 @@
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
}
html_theme = "furo"
30 changes: 30 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
:tocdepth: 2

.. _examples:

Example usage
*************

Connect, and start and stop a recording
"""""""""""""""""""""""""""""""""""""""

.. literalinclude:: ../examples/basic.py
:language: python
:linenos:
:emphasize-lines: 8,10,11,14

Print the estimated clock offset and current Pupil time
"""""""""""""""""""""""""""""""""""""""""""""""""""""""

.. literalinclude:: ../examples/estimated_clock_offset.py
:language: python
:linenos:
:emphasize-lines: 10,11,14

Start the Annotation Plugin and send custom annotions
"""""""""""""""""""""""""""""""""""""""""""""""""""""

.. literalinclude:: ../examples/send_annotations.py
:language: python
:linenos:
:emphasize-lines: 12,19,26-28,35-37
16 changes: 10 additions & 6 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
Welcome to |project| documentation!
===================================

.. include:: ../README.rst
:start-line: 25
:end-line: 40

You can find the source code on `Github`_.

.. _Github: https://github.com/papr/pupil-core-network-client

.. toctree::
:maxdepth: 1

examples
api
history


.. automodule:: skeleton
:members:
:undoc-members:
:show-inheritance:


Indices and tables
==================

Expand Down
23 changes: 23 additions & 0 deletions examples/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import argparse
import time

import pupil_labs.pupil_core_network_client as pcnc


def main(address: str, port: int):
device = pcnc.Device(address, port)

print("Version:", device.request_version())
print("Start recording:", device.request_recording_start())
print("Waiting 5 seconds..")
time.sleep(5.0)
print("Stop recording:", device.request_recording_stop())


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
parser.add_argument("-p", "--port", type=int, default=50020)
args = parser.parse_args()

main(args.address, args.port)
23 changes: 23 additions & 0 deletions examples/estimated_clock_offset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import argparse

import pupil_labs.pupil_core_network_client as pcnc


def main(address: str, port: int):
device = pcnc.Device(address, port)

print(
f"Measured offset between client clock ({device.client_clock}) and pupil "
f"time:\n\t{device.clock_offset_statistics}"
)

print("Current pupil time:", device.current_pupil_time())


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
parser.add_argument("-p", "--port", type=int, default=50020)
args = parser.parse_args()

main(args.address, args.port)
47 changes: 47 additions & 0 deletions examples/send_annotations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import argparse
import time

import pupil_labs.pupil_core_network_client as pcnc


def main(address: str, port: int):
device = pcnc.Device(address, port)

print(
"Requesting annotation plugin start...",
device.request_plugin_start("Annotation_Capture"),
)
print("Wait a second for the request to be processed...")
time.sleep(1.0)

print(
"Sending annotation with automatic timestamp",
device.send_annotation(label="automatic timestamp"),
)

print(
"Sending annotation with custom timestamp",
# Timestamps should be in Pupil time. By subtracting 5 seconds, the annotation
# will be associated with a point in time 5 seconds ago.
device.send_annotation(
label="custom timestamp", timestamp=device.current_pupil_time() - 5.0
),
)

print(
"Sending annotation with custom fields",
# Custom fields can be passed as keyword arguments and will be saved to their
# dedicated column during the Pupil Player export
device.send_annotation(
label="custom fields", trial=5, subject="me", condition="eye tracking"
),
)


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
parser.add_argument("-p", "--port", type=int, default=50020)
args = parser.parse_args()

main(args.address, args.port)
11 changes: 7 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[metadata]
name = pupil_labs_project_name
description = Project description
name = pupil_core_network_client
description = A Python client for the Pupil Core Network API
long_description = file: README.rst
long_description_content_type = text/x-rst
url = https://github.com/pupil-labs/python-module-skeleton
url = https://github.com/papr/pupil-core-network-client
author = Pupil Labs GmbH
author_email = [email protected]
license = MIT
license_file = LICENSE
classifiers =
Development Status :: 5 - Production/Stable
Development Status :: 3 - Alpha
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Programming Language :: Python :: 3
Expand All @@ -22,6 +22,8 @@ classifiers =
[options]
packages = find_namespace:
install_requires =
msgpack>=1.0.0
pyzmq
importlib-metadata;python_version<"3.8"
python_requires = >=3.7
include_package_data = true
Expand All @@ -38,6 +40,7 @@ exclude =

[options.extras_require]
docs =
furo
jaraco.packaging>=8.2
rst.linker>=1.9
sphinx<4.4 # 4.4 does not detect TypeVars correctly
Expand Down
14 changes: 0 additions & 14 deletions src/pupil_labs/project_name/__init__.py

This file was deleted.

22 changes: 22 additions & 0 deletions src/pupil_labs/pupil_core_network_client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Top-level entry-point for the <project_name> package"""

try:
from importlib.metadata import PackageNotFoundError, version
except ImportError:
from importlib_metadata import PackageNotFoundError, version

try:
__version__ = version("pupil-core-network-client")
except PackageNotFoundError:
# package is not installed
__version__ = None

from .device import ClockFunction, ClockOffsetStatistics, Device, NotConnectedError

__all__ = [
"__version__",
"ClockFunction",
"ClockOffsetStatistics",
"Device",
"NotConnectedError",
]
Loading

0 comments on commit eefb0d5

Please sign in to comment.