Skip to content

Conversation

@qian-chu
Copy link
Collaborator

@qian-chu qian-chu commented Dec 29, 2025

Epochs

Developers and users have found the old Epochs class quite unintuitive and operationally hard to use (e.g., nested DataFrame). This PR aims to reorganize the class.

Current features:

  • Slight change of Events class, where now event IDs (e.g., "fixation id") are now used as index. For messages and custom events, the index is name "event id"
  • event_times is renamed to epochs_info for easier comprehension
  • Creating an Epochs instance will not compute the epochs or annotated data automatically.
  • epochs is now a cached property in the form of a dictionary. Keys are indices of epochs_info and values are Stream/Events instances.
  • Annotated data now available through annotate_epochs.
  • (in progress) added a pupillary light reflex (PLR) dataset (2 participants, data in cloud and native formats). Currently exploring options to host data on FigShare vs OSF

Marker mapping

Per suggestions, this PR also aims to expand the marker mapping from AprilTags to also ArUco markers (using OpenCV's aruco module). This direct interface also allows us to get rid of the optional dependency of pupil-apriltags. API and documentations are improved along the way.

qian-chu and others added 15 commits December 19, 2025 15:34
Refactored the Epochs class to use a dictionary of epochs indexed by epoch index, added properties for empty epochs, and improved overlap checking and warnings. Updated the to_numpy method to support flexible sampling rates and interpolation, and improved baseline correction error handling. Modified plot_epochs and its helpers to work with the new Epochs API, and updated the pupil_size_and_epoching tutorial to use the new sample data and API.
Expanded and clarified docstrings for epoching functions and the Epochs class, including detailed parameter and return value descriptions. Refactored Dataset to automatically handle native data without requiring a 'custom' flag, and improved section construction for native recordings. Updated tutorials to use consistent event naming and native data examples. Minor bugfixes and doc improvements in export and utility modules.
@qian-chu qian-chu requested a review from JGHartel December 29, 2025 13:54
@qian-chu
Copy link
Collaborator Author

@JGHartel Currently the baseline correction method is not updated yet. What do you think would be the best API/code for it? For operability with other methods such as plot(), I think it makes the most sense to modify the data in epochs property

Copy link
Collaborator

@JGHartel JGHartel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I welcome the suggested changes. In particular, the rename towards epoch_info and the unified access to epochs data as epoch.epochs, rather than the previous mixed access, is appreciated. Still, I would like to invite some discussions on the assumed datatypes, e.g. epochs.epochs and epochs.annotate being a dictionary. This would especially futureproof the development, if dataset level operations should be introduced

pyneon/epochs.py Outdated
# Create epochs
self.epochs, self.data = _create_epochs(source, times_df)
@cached_property
def epochs(self) -> dict[int, Stream | Events | None]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flagging this in case we ever want to support multi-recording functionality. It would be good to have a Unique ID for each event, so that one can easily concat these dicts between recordings. Alternatively, we could then construct an implicit multiindex (recording, epoch_number), which would require a custom concat function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit of an advanced user case and also in principle should apply to other classes (e.g. streams and events). My evaluation would be it would require another PR if we see value in supporting multi-recording concatenation

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a major refactoring of the Epochs class to make it more intuitive and easier to use. The key changes include moving away from nested DataFrames to a dictionary-based structure, renaming methods for clarity, and introducing lazy computation of epochs using cached properties.

Changes:

  • Refactored Epochs class to use epochs_dict (cached property returning a dictionary) instead of nested DataFrames
  • Renamed event_times to epochs_info and events_to_times_df to events_to_epochs_info for better comprehension
  • Changed Events class to use event IDs as DataFrame index instead of separate columns
  • Added new filter_by_name method to Events class and updated filter_by_duration behavior
  • Added PLR sample dataset support with Figshare hosting
  • Consolidated CI workflows (removed separate tests.yml, integrated into main.yml)

Reviewed changes

Copilot reviewed 19 out of 22 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
pyneon/epochs.py Major refactoring of Epochs class with new dictionary-based structure, cached properties, and helper functions renamed
pyneon/events.py Modified to use event IDs as index, added filter_by_name method, updated filter_by_duration
pyneon/stream.py Added stub for detect_events_from_derivative method, updated docstrings with reusable doc snippets
pyneon/vis/vis.py Updated plot_epochs to work with new epochs_dict structure
pyneon/dataset.py Made sections.csv optional, improved error handling for missing recordings
pyneon/utils/doc_decorators.py Added reusable documentation snippets for common return types and parameters
pyneon/utils/sample_data.py Added PLR dataset URL and test
tests/conftest.py Added simple_events fixture for testing Events functionality
tests/test_events.py Added (empty) test stub for crop functionality
tests/test_streams.py Added tests for interpolation and concatenation methods
.github/workflows/main.yml Consolidated CI workflows, added test job dependencies
source/tutorials/*.ipynb Updated tutorial notebooks to use new API names
README.md Added information about sample datasets on Figshare
Comments suppressed due to low confidence (1)

pyneon/epochs.py:223

  • The properties columns and dtypes (lines 216-223) reference self.data which no longer exists in the new Epochs class structure. These properties need to be updated or removed.
    @property
    def columns(self) -> pd.Index:
        return self.data.columns[:-3]

    @property
    def dtypes(self) -> pd.Series:
        """The data types of the epoched data."""
        return self.data.dtypes[:-3]

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

JGHartel and others added 21 commits January 15, 2026 17:54
Standardized AprilTag detection output to use flat columns (e.g., 'frame id', 'tag id', 'corner 0 x [px]') instead of nested arrays. Updated all related code, docstrings, and type definitions to match the new format, and revised downstream usages in pose estimation, homography computation, visualization, and tutorials. This improves data interoperability and simplifies downstream processing.
Replaces all AprilTag-specific detection code and APIs with a unified marker detection interface supporting both AprilTag and ArUco markers. Renames functions and parameters (e.g., detect_apriltags → detect_markers), updates documentation, and introduces a utility for mapping marker names to OpenCV dictionaries. Updates all usages, docstrings, and tutorial code to reflect the new marker-agnostic approach.
Changed 'tag id' data type from Int32 to str in variables.py for consistency. Fixed marker detection logic in detect_marker.py to handle None values for all_ids. Updated pyproject.toml to require opencv-python>=4.7. Minor update to surface_mapping.ipynb output.
Renamed 'detect_marker.py' to 'marker_mapping.py' and 'mapping.py' to 'scanpath.py' for improved clarity in the video module structure. Updated the surface_mapping.ipynb tutorial output to reflect new error messages and improved performance, including a change from a KeyError to a TypeCheckError in homography upsampling.
Moved estimate_camera_pose to a new file (estimate_pose.py) and updated imports across the video module to reflect this change. Renamed internal methods in recording.py for clarity. Fixed type hints and docstrings in scanpath.py. Minor formatting and docstring improvements in marker_mapping.py and video.py. Updated surface_mapping tutorial for improved readability.
Standardizes terminology from 'tag' to 'marker' across the codebase, including function arguments, variable names, and documentation. Updates marker detection to use 'marker_family' instead of 'marker_name', and refactors related utility functions and docstrings. Improves random/sequential frame access for marker detection, updates homography and camera pose estimation interfaces, and revises tutorial notebook code and comments for consistency.
Replaces generic corner indices with named corners (top left, top right, bottom right, bottom left) throughout marker detection, pose estimation, and homography mapping. Updates related docstrings, plotting utilities, and adds a new plot_detected_markers method to Video and visualization modules. This improves code clarity and consistency for marker handling.
Standardizes marker detection and layout columns, adds marker family and name fields, and updates related functions and visualizations to use the new schema. Introduces a new plot_marker_layout visualization and updates the surface mapping tutorial for improved clarity and consistency.
Standardizes all references from 'frame id' to 'frame index' across the codebase, including function arguments, DataFrame columns, and documentation. Updates marker detection to support multiple marker families, refines homography output to use flattened matrix columns, and improves interpolation with a max_gap_ms parameter. Also adds a new example script (pg.py) and updates the surface mapping tutorial to match the new API.
Replaced outdated sample data keys and URLs in sample_data.py, updated the default sample in the main block, and removed 'labels.csv' from expected cloud files. Enhanced the cloud-format tutorial notebook with clearer explanations, updated directory structure, and improved code and output to use the new 'simple' sample dataset. Added 'seedir' to documentation dependencies in pyproject.toml.
Introduces an optional detector_parameters argument to marker detection functions in pyneon, allowing custom cv2.aruco.DetectorParameters to be passed for all marker families. Updates docstrings and documentation to reflect this new parameter, improves code formatting, and fixes minor typos in docstrings. Also updates sample data utility to support format selection and makes minor tutorial and import order adjustments.
Refactored the find_homographies function to accept explicit parameters for method, ransacReprojThreshold, maxIters, and confidence instead of a settings dictionary. Updated docstrings and documentation decorators to reflect the new parameters and improve clarity. Adjusted Recording.find_homographies to match the new API and updated its documentation accordingly.
@qian-chu qian-chu changed the title New epochs class New epochs class and marker mapping Jan 29, 2026
Expanded and clarified docstrings for marker mapping, homography, and stream manipulation functions. Updated documentation to include pyneon.find_homographies in the public API and Sphinx docs. Improved tutorial on interpolation and concatenation to cover cropping, restriction, and stream alignment. Minor docstring formatting and consistency improvements throughout.
…ting

Replaced repeated docstring sections with shared snippets via %(...)s formatting for axis and show parameters, marker layout, and return values. Added plot_marker_layout to visualization API and implemented its plotting logic, including marker image orientation handling and name overlay. Updated surface mapping tutorial to demonstrate marker layout plotting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants