Example usage#
To run the examples, install the package using the examples
extras requirement:
pip install -e pupil-core-network-client[examples]
Connect, and start and stop a recording#
1import argparse
2import time
3
4import pupil_labs.pupil_core_network_client as pcnc
5
6
7def main(address: str, port: int):
8 device = pcnc.Device(address, port)
9
10 print("Version:", device.request_version())
11 print("Start recording:", device.request_recording_start())
12 print("Waiting 5 seconds..")
13 time.sleep(5.0)
14 print("Stop recording:", device.request_recording_stop())
15
16
17if __name__ == "__main__":
18 parser = argparse.ArgumentParser()
19 parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
20 parser.add_argument("-p", "--port", type=int, default=50020)
21 args = parser.parse_args()
22
23 main(args.address, args.port)
Print the estimated clock offset and current Pupil time#
1import argparse
2
3import pupil_labs.pupil_core_network_client as pcnc
4
5
6def main(address: str, port: int):
7 device = pcnc.Device(address, port)
8
9 print(
10 f"Measured offset between client clock ({device.client_clock}) and pupil "
11 f"time:\n\t{device.clock_offset_statistics}"
12 )
13
14 print("Current pupil time:", device.current_pupil_time())
15
16
17if __name__ == "__main__":
18 parser = argparse.ArgumentParser()
19 parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
20 parser.add_argument("-p", "--port", type=int, default=50020)
21 args = parser.parse_args()
22
23 main(args.address, args.port)
Start the Annotation Plugin and send custom annotions#
1import argparse
2import time
3
4import pupil_labs.pupil_core_network_client as pcnc
5
6
7def main(address: str, port: int):
8 device = pcnc.Device(address, port)
9
10 print(
11 "Requesting annotation plugin start...",
12 device.request_plugin_start("Annotation_Capture"),
13 )
14 print("Wait a second for the request to be processed...")
15 time.sleep(1.0)
16
17 print(
18 "Sending annotation with automatic timestamp",
19 device.send_annotation(label="automatic timestamp"),
20 )
21
22 print(
23 "Sending annotation with custom timestamp",
24 # Timestamps should be in Pupil time. By subtracting 5 seconds, the annotation
25 # will be associated with a point in time 5 seconds ago.
26 device.send_annotation(
27 label="custom timestamp", timestamp=device.current_pupil_time() - 5.0
28 ),
29 )
30
31 print(
32 "Sending annotation with custom fields",
33 # Custom fields can be passed as keyword arguments and will be saved to their
34 # dedicated column during the Pupil Player export
35 device.send_annotation(
36 label="custom fields", trial=5, subject="me", condition="eye tracking"
37 ),
38 )
39
40
41if __name__ == "__main__":
42 parser = argparse.ArgumentParser()
43 parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
44 parser.add_argument("-p", "--port", type=int, default=50020)
45 args = parser.parse_args()
46
47 main(args.address, args.port)
Stream Video From Pupil Capture#
1import argparse
2import contextlib
3import logging
4import time
5
6import pupil_labs.pupil_core_network_client as pcnc
7
8
9def main(address: str, port: int, max_frame_rate_hz: int):
10 device = pcnc.Device(address, port)
11 device.send_notification(
12 {"subject": "frame_publishing.set_format", "format": "bgr"}
13 )
14
15 with contextlib.suppress(KeyboardInterrupt):
16 with device.subscribe_in_background("frame.world", buffer_size=1) as sub:
17 while True:
18 message = sub.recv_new_message()
19 print(
20 f"[{message.payload['timestamp']}] {message.payload['topic']} "
21 f"{message.payload['index']}"
22 )
23 time.sleep(1 / max_frame_rate_hz)
24
25
26if __name__ == "__main__":
27 parser = argparse.ArgumentParser()
28 parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
29 parser.add_argument("-p", "--port", type=int, default=50020)
30 parser.add_argument("-fps", "--max-frame-rate", type=int, default=10)
31 parser.add_argument("--debug", action="store_true")
32 args = parser.parse_args()
33 logging.basicConfig(level=logging.DEBUG if args.debug else logging.WARNING)
34
35 main(args.address, args.port, args.max_frame_rate)
Stream Video to Pupil Capture#
This example shows how start world and eye plugins and streaming BGR data to Pupil Capture’s HMD Streaming backend.
1import argparse
2import contextlib
3import time
4
5import numpy as np
6
7import pupil_labs.pupil_core_network_client as pcnc
8
9current_image = np.zeros((400, 600, 3), dtype=np.uint8)
10
11
12def main(address: str, port: int, frame_rate_hz: int):
13 device = pcnc.Device(address, port)
14
15 source_class_name = "HMD_Streaming_Source"
16 frame_topic = "hmd_streaming.custom"
17 device.request_plugin_start(source_class_name, args={"topics": (frame_topic,)})
18 for eye_id in range(2):
19 device.request_plugin_start_eye_process(
20 eye_id, source_class_name, args={"topics": (frame_topic,)}
21 )
22
23 with contextlib.suppress(KeyboardInterrupt):
24 # Enable sending messages directly to the IPC backbone instead of having
25 # Pupil Remote forward every message one by one and waiting for a response each
26 # time. This allows sending messages with a much higher rate.
27 with device.high_frequency_message_sending():
28 increasing_index = 0
29 while True:
30 send_image(
31 device,
32 gray_image(increasing_index),
33 frame_topic,
34 increasing_index,
35 timestamp=device.current_pupil_time(),
36 )
37 increasing_index += 1
38 time.sleep(1 / frame_rate_hz)
39
40
41def send_image(device: pcnc.Device, image, topic: str, index: int, timestamp: float):
42 height, width, depth = image.shape
43 device.send_message(
44 {
45 "format": "bgr",
46 "projection_matrix": [ # dummy pin-hole camera intrinsics
47 [1000, 0.0, width / 2.0],
48 [0.0, 1000, height / 2.0],
49 [0.0, 0.0, 1.0],
50 ],
51 "topic": topic,
52 "width": width,
53 "height": height,
54 "index": index,
55 "timestamp": timestamp,
56 "__raw_data__": [image],
57 }
58 )
59
60
61def gray_image(color_seed: int):
62 """Return an image with a gray value between 85 and 170"""
63 return current_image + (color_seed % 85) + 85
64
65
66if __name__ == "__main__":
67 parser = argparse.ArgumentParser()
68 parser.add_argument("-a", "--address", type=str, default="127.0.0.1")
69 parser.add_argument("-p", "--port", type=int, default=50020)
70 parser.add_argument("-fps", "--frame-rate", type=int, default=60)
71 args = parser.parse_args()
72
73 main(args.address, args.port, args.frame_rate)