{"id":27102457,"url":"https://github.com/iot-salzburg/nearest-advocate","last_synced_at":"2025-04-06T15:39:55.314Z","repository":{"id":64399060,"uuid":"571548927","full_name":"iot-salzburg/nearest-advocate","owner":"iot-salzburg","description":"A time delay estimation method for event-based time-series data. Time delay estimation is also known as the correction of time offsets and time lags as well as time synchronization.","archived":false,"fork":false,"pushed_at":"2024-04-06T18:09:44.000Z","size":54366,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-17T05:46:22.747Z","etag":null,"topics":["event-based","python","synchronization","time-delay-estimation","time-lag","time-series","time-synchronization"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iot-salzburg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-11-28T11:27:31.000Z","updated_at":"2024-09-18T09:36:35.000Z","dependencies_parsed_at":"2023-11-29T14:41:43.299Z","dependency_job_id":null,"html_url":"https://github.com/iot-salzburg/nearest-advocate","commit_stats":{"total_commits":47,"total_committers":2,"mean_commits":23.5,"dds":"0.021276595744680882","last_synced_commit":"883031bdf596d3967c00e25b85733a3074600816"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iot-salzburg%2Fnearest-advocate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iot-salzburg%2Fnearest-advocate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iot-salzburg%2Fnearest-advocate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iot-salzburg%2Fnearest-advocate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iot-salzburg","download_url":"https://codeload.github.com/iot-salzburg/nearest-advocate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247506152,"owners_count":20949971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["event-based","python","synchronization","time-delay-estimation","time-lag","time-series","time-synchronization"],"created_at":"2025-04-06T15:39:54.644Z","updated_at":"2025-04-06T15:39:55.308Z","avatar_url":"https://github.com/iot-salzburg.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nearest-Advocate\n\n**A time delay estimation method for event-based time-series.**\n\n[![PyPi version](https://badgen.net/pypi/v/nearest_advocate/)](https://pypi.org/project/nearest_advocate)\n[![PyPI download month](https://img.shields.io/pypi/dm/nearest_advocate.svg)](https://pypi.org/project/nearest-advocate/)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)\n[![DOI](https://zenodo.org/badge/DOI/10.1186/s13634-024-01143-1.svg)](https://doi.org/10.1186/s13634-024-01143-1)\n\nThis repository contains the source code, demonstration data, unit tests, benchmarks as well as research experiments for the Nearest Advocate Algorithm.\n\n- Github-Repository: [https://github.com/iot-salzburg/nearest-advocate](https://github.com/iot-salzburg/nearest-advocate)\n- Pip-Package: [https://pypi.org/project/nearest-advocate/](https://pypi.org/project/nearest-advocate/).\n\n\n## Scope of the package\n\nThis package focuses on the time delay estimation between two event-based time-series that are relatively shifted by an unknown time offset. An event-based time-series is given by a set of timestamps of certain events.\nIf you want to guarantee synchronous measurements in advance or estimate the time delay of continuous measurements sampled at a constant rate, you might want to use other methods.\nHowever, in some use cases, performing an event detection and then estimating the relative time delay has advantages.\nThe Nearest Advocate method provides a **precise time delay estimation in event-based time-series** that is **robust against imprecise timestamps, a high fraction of missing events, and clock drift**.\nTime delay estimation also known as the correction of time offsets and time lags as well as time synchronization.\n\n\n## Quickstart\n\nInstall the package with:\n\n```bash\npip install nearest_advocate\n```\n\nOpen Python and import and use it for time delay estimation of event-based time-series:\n\n```python\nimport numpy as np\nimport nearest_advocate\n```\n\nCreate a reference array whose inter-event intervals are sampled from a normal distribution. The signal array is a clone of the reference´, shifted by `np.pi` and added Gaussian noise. The event's timestamps of both arrays must be sorted.\n\n```python\narr_ref = np.sort(np.cumsum(np.random.normal(loc=1, scale=0.25, size=1000)))\narr_sig = np.sort(arr_ref + np.pi + np.random.normal(loc=0, scale=0.1, size=1000))\n```\n\nThe function `nearest_advocate.nearest_advocate` returns a two-columned array with all investigated time-shifts and their mean distances, i.e., the measure of the synchronicity between both arrays (lower is better).\n\n```python\ntime_shifts = nearest_advocate.nearest_advocate(arr_ref=arr_ref, arr_sig=arr_sig, td_min=-60, td_max=60, sps=20)\ntime_shift, min_mean_dist = time_shifts[np.argmin(time_shifts[:,1])]\nprint(f\"Found an optimum at {time_shift:.4f}s with a minimal mean distance of {min_mean_dist:.6f}s\")\n#\u003e Found an optimum at 3.15s with a minimal mean distance of 0.079508s\n```\nThe time delay estimation is 3.15 seconds which is pretty close to the true one.\nCreate a plot of the resulting characteristic curve of Nearest Advocate, the global minimum of the curve is used as time delay estimation.\n\n```python\nimport matplotlib.pyplot as plt\nplt.plot(time_shifts[:,0], time_shifts[:,1], color=\"steelblue\", label=\"Mean distance\")\nplt.vlines(x=time_shift, ymin=min_mean_dist, ymax=np.mean(time_shifts[:,1]), color=\"firebrick\", label=f\"Shift = {time_shift:.2f}s\")\nplt.xlim(time_shift-4, time_shift+4)\nplt.xlabel(\"Time delay (s)\")\nplt.ylabel(\"Mean distance (s)\")\nplt.legend(loc=\"lower right\")\nplt.show()\n```\n\n\n![](https://raw.githubusercontent.com/iot-salzburg/nearest-advocate/main/time_delay_estimation.png \"Time Delay Estimation\")\n\n\n## Functionality\n\n### Symmetric Nearest Advocate\n\nTo apply the Nearest Advocate algorithm symmetrically, just pass the flag `symmetric=True` in the method:\n\n```python\ntime_shifts = nearest_advocate.nearest_advocate(arr_ref=arr_ref, arr_sig=arr_sig, td_min=-60, td_max=60, sps=20, symmetric=True)\ntime_shift, min_mean_dist = time_shifts[np.argmin(time_shifts[:,1])]\nprint(f\"Found an optimum at {time_shift:.4f}s with a minimal mean distance of {min_mean_dist:.6f}s\")\n#\u003e Found an optimum at 3.15s with a minimal mean distance of 0.079508s\n```\n\n\n### Clock-drift correction\n\nUsing the NAd in sliding windows, it is possible to estimate the linear or non-linear trend of the relatve clock drift between two clocks. To do so, both event time-series should be very long in terms of their number of elements.\nA Jupyter notebook is provided to adapt this functionality to other applications [experiments/application_nonlinear_correction.ipynb](https://github.com/iot-salzburg/nearest-advocate/blob/main/experiments/application_nonlinear_correction.ipynb).\n\n**Example of a linear clock-drift correction:**\n![](https://raw.githubusercontent.com/iot-salzburg/nearest-advocate/main/experiments/fig/linear_correction_1.png \"Linear clock-drift correction\")\n\n**Example of a subsequent nonlinear clock-drift correction:**\n![](https://raw.githubusercontent.com/iot-salzburg/nearest-advocate/main/experiments/fig/nonlinear_correction_1.png \"Nonlinear clock-drift correction\")\n\n\n\n### Time Delay Estimation based on Different Observations\n\nThis algorithm is so robust against data quality issues, that it is even possible to estimate the time-delay between two event-based measurements of different observations. In [experiments/application_different_observations.ipynb](https://github.com/iot-salzburg/nearest-advocate/blob/main/experiments/application_different_observations.ipynb) it is demonstrated how to apply the NAd for breathing and step events from the same participant, that uses the fact that both frequencies are slightly interdependent.\n\n![](https://raw.githubusercontent.com/iot-salzburg/nearest-advocate/main/experiments/fig/P07_1_plot.png \"Nonlinear Different Observations\")\n\n\n\n### Functionality\n\nApplied methods for windowed Nearest Advocate, linear and nonlinear clock-drift correction and advanced plotting is provided in [experiments/nearest_advocate_windowed](https://github.com/iot-salzburg/nearest-advocate/blob/main/experiments/nearest_advocate_windowed) with sample Jupyter notebooks of how to use them in the parent directory.\n\n\n\n## Building from source\n\n### Setup\n\n```bash\ncd /go/to/path\ngit clone https://github.com/iot-salzburg/nearest-advocate\ncd nearest-advocate\npip install -r requirements.txt\n```\n\nFor reproducibility, the experiments were run in Python 3.9 inside a container environment using the Docker orchestration software with the image `cschranz/gpu-jupyter` and tag `v1.4\\_cuda-11.0\\_ubuntu-20.04`, available on Dockerhub.\n\nBuild the Cython-version of the algorithm with:\n\n```bash\ncd src\npython setup.py build_ext --inplace\n```\n\n\n### Run the tests\n\nCurrently, the Cython-version is under development and will be available soon.\n\nRun the test scripts:\n\n```bash\npython tests/test_algorithm.py\n#\u003e Testing numba-version:          ok\n#\u003e Testing Cython-version:         ok\n#\u003e Testing Python-version:         ok\n\npython tests/test_performances.py\n#\u003e ################# Test and compare shifts ##################\n#\u003e Numba:          0.01329827 s,    detected time shift: 3.15 s,    minimal mean distance: 0.084238 s\n#\u003e Cython:         0.01338649 s,    detected time shift: 3.15 s,    minimal mean distance: 0.084238 s\n#\u003e Python:         3.06915808 s,    detected time shift: 3.15 s,    minimal mean distance: 0.084238 s\n#\u003e\n#\u003e ########## Compare versions for multiple lengths ###########\n#\u003e Method      10       100       1000     10000     100000\n#\u003e Numba:   0.000157  0.000786  0.013276  0.138520  1.402027\n```\n\n\n## Reproduce the research experiments\n\nIn the directory [nearest_advocate/experiments](https://github.com/iot-salzburg/nearest-advocate/tree/main/experiments), multiple Jupyter Notebooks contain experiments based on data in the `data` directory.\n\n\n\u003c!-- ## Development of Scipy\n\nRead the the [build-README.md](#scipydev/REAMDE.md)\n --\u003e\n\n\n## Citation\n\nWhen using in academic works please cite:\n\n\n\u003eSchranz, C., Mayr, S., Bernhart, S. et al. Nearest advocate: a novel event-based time delay estimation algorithm for multi-sensor time-series data synchronization. EURASIP J. Adv. Signal Process. 2024, 46 (2024). https://doi.org/10.1186/s13634-024-01143-1\n\nor:\n\n\u003eSchranz, C., \u0026 Mayr, S. (2022, September 29). Ein neuer Algorithmus zur Zeitsynchronisierung von Ereignis- basierten Zeitreihendaten als Alternative zur Kreuzkorrelation. Proceedings of the 14th Symposium of the Section Sport Informatics and Engineering of the German Society of Sport Science (dvs) (spinfortec2022), Chemnitz. https://doi.org/10.5281/zenodo.7370958\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiot-salzburg%2Fnearest-advocate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiot-salzburg%2Fnearest-advocate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiot-salzburg%2Fnearest-advocate/lists"}