{"id":18607012,"url":"https://github.com/gwbres/allan-tools","last_synced_at":"2025-08-10T08:44:20.852Z","repository":{"id":57483523,"uuid":"441101367","full_name":"gwbres/allan-tools","owner":"gwbres","description":":chart_with_upwards_trend: Allantools portage to Rust","archived":false,"fork":false,"pushed_at":"2022-03-13T11:24:34.000Z","size":498,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T04:20:12.327Z","etag":null,"topics":["frequency","frequency-analysis","mathematics","maths","rust","statistics","system-analysis","time","time-frequency","time-frequency-analysis","time-series-analysis"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/gwbres.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-23T07:39:02.000Z","updated_at":"2023-07-31T03:41:01.000Z","dependencies_parsed_at":"2022-08-27T20:03:01.560Z","dependency_job_id":null,"html_url":"https://github.com/gwbres/allan-tools","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwbres%2Fallan-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwbres%2Fallan-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwbres%2Fallan-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwbres%2Fallan-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gwbres","download_url":"https://codeload.github.com/gwbres/allan-tools/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248290041,"owners_count":21078923,"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":["frequency","frequency-analysis","mathematics","maths","rust","statistics","system-analysis","time","time-frequency","time-frequency-analysis","time-series-analysis"],"created_at":"2024-11-07T02:27:59.047Z","updated_at":"2025-04-10T20:32:05.631Z","avatar_url":"https://github.com/gwbres.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# allan-tools\n\n[![crates.io](https://img.shields.io/crates/v/allan-tools.svg)](https://crates.io/crates/allan-tools)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/gwbres/allan-tools/blob/main/LICENSE-APACHE)\n[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/gwbres/allan-tools/blob/main/LICENSE-MIT) \n[![crates.io](https://img.shields.io/crates/d/allan-tools.svg)](https://crates.io/crates/allan-tools)   \n[![Rust](https://github.com/gwbres/allan-tools/actions/workflows/rust.yml/badge.svg)](https://github.com/gwbres/allan-tools/actions/workflows/rust.yml)\n[![crates.io](https://docs.rs/allan-tools/badge.svg)](https://docs.rs/allan-tools/badge.svg)\n\nAllantools (python lib) portage to Rust\n\nThis library allows easy computations of Allan deviation \u0026 similar statistics.   \nThese statistical methods are mostly used in system stability studies.\n\n## Allan and other deviations\n\nCompute Allan deviation over raw data:\n\n```rust\n  use allantools::*;\n  let taus = tau::generator(tau::TauAxis::Octave, 2, 128); // [2, 4, 8, ... 128]\n  let sampling_rate = 1.0_f64; // [Hz]\n  let (dev, errs) = deviation(\u0026data, \u0026taus, Deviation::Allan, sampling_rate, false, false).unwrap();\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/model.png\" alt=\"alt text\" width=\"500\"/\u003e\n\nThis lib against `Time Lab`. \n\n### Known calculations\n\n* Deviation::Allan `adev`\n* Deviation::Modified `mdev`\n* Deviation::Time `tdev` (not fully tested yet)\n* Deviation::Hadamard `hdev` (not fully tested yet)\n* Deviation::Gcov `gcov` allan covariances (not tested yet)\n\n### Error bars\n\nOnly basic (biased) error bars following the 1/√N decay are currently produced\n\n### Overlapping\n\nImprove statiscal confidence by using _overlapped_ formulae \n\n```rust\n  let data: Vec\u003cf64\u003e = some_data();\n  let taus = tau::generator(tau::TauAxis::Octave, 128);\n  let overlapping = true;\n  let sampling_rate = 1.0_f64; // [Hz]\n  let (var, errs) = deviation(\u0026data, \u0026taus, Deviation::Allan, sampling_rate, false, overlapping).unwrap();\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/oadev-white-pm.png\" width=\"500\"/\u003e\n\n### Fractionnal data\n`is fractional` can be used to compute statistics over fractional\n(n.a) data:\n\n```rust\n  let data: Vec\u003cf64\u003e = some_data();\n  let taus = tau::generator(tau::TauAxis::Octave, 10000);\n  let is_fractional = true;\n  let sampling_rate = 1.0_f64; // [Hz]\n  let ( adev, errs) = deviation(\u0026data, \u0026taus, Deviation::Allan, sampling_rate, is_fractional, false).unwrap();\n  let (oadev, errs) = deviation(\u0026data, \u0026taus, Deviation::Allan, sampling_rate, is_fractional, true).unwrap();\n```\n\n### Tau axis generator\n\nThe user can pass any \u0026#964; serie to all computation methods.   \n\nThis lib integrates a \u0026#964; axis generator too, which is a convenient\nmethod to quickly pass a standard axis to a computation method.\nSeveral axis are known:  \n\n* TauAxis::Octave is the most efficient\n* TauAxis::Decade is the standard and is efficient\n* TauAxis::All requires more computation\n\n```rust\n  let taus = tau::generator(tau::TauAxis::Decade, 1.0, 10000.0); // [1.0, 10.0, 100.0, ..., 10000.0]\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/adev-white-fm.png\" alt=\"alt text\" width=\"500\"/\u003e\n\nUsing TauAxis::All requires more computation but gives a total\ntime granularity \n\n```rust\n  let taus = tau::generator(tau::TauAxis::All, 1.0, 100.0); // [1.0, 2.0, 3.0, ..., 99.0, 100.0]\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/adev-pink-pm.png\" alt=\"alt text\" width=\"500\"/\u003e\n\n### Tau offset and error management\n \nThis library computes the requested statistics for all \u0026#964; values, as long as \n$#964;(n) can be evaluated.   \nIf \u0026#964; (n) cannot be evaluated, computation stops and returns all\npreviously evaluated offsets.\n\nIf not a single \u0026#964; value is feasible, the lib returns Error::NotEnoughSamplesError\n\nThe user must pass a valid \u0026#964; serie, otherwise:\n\n* TauAxis::NullTauValue: is returned when \u0026#964; = 0 (non sense) is requested\n* TauAxis::NegativeTauValue: is return when \u0026#964; \u003c 0 (non physical) is requested\n* TauAxis::InvalidTauShape: shape is not an increasing (not necessarily steady) shape\n\n### Data \u0026 Noise generators\n\nSome data generators were integrated or develpped for testing purposes:\n\n* White noise generator\n\n```rust\n  let x = allantools::noise::white_noise(\n    -140.0_f64, // dBc/Hz\n    1.0_f64, // (Hz)\n    10000); // 10k samples\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/white-noise.png\" alt=\"alt text\" width=\"200\"/\u003e\n\n* Pink noise generator\n\n```rust\n  let x = allantools::noise::pink_noise(\n    -140.0_f64, // dBc @ 1Hz\n    1.0_f64, // (Hz)\n    1024); // 1k samples\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/pink-noise.png\" alt=\"alt text\" width=\"200\"/\u003e\n\n|  Noise |          White PM         |        Flicker PM        |   White FM   |  Flicker FM |\n|:------:|:-------------------------:|:------------------------:|:------------:|:-----------:|\n|  adev  |             -1            |            -1            |     -1/2     |      0      |\n|  mdev  |            -3/2           |            -1            |     -1/2     |      0      |\n| method | utils::diff(noise::white) | utils::diff(noise::pink) | noise::white | noise::pink |\n\n### Power Law Identification\n\n#### NIST LAG1D autocorrelation\n[NIST Power Law identification method[[46]]](https://www.nist.gov/publications/handbook-frequency-stability-analysis)   \n\nThis macro works well on data serie where one noise process is very dominant.\n\n```rust\n  let r = allantools::nist_lag1d_autocorr(\u0026some_data);\n```\n\n#### Bias1 + R(n) identification method\nTODO\n\n### Three Cornered Hat\n\nThree cornered hat fashion statistics, to estimate\na/b/c from a against b, b against c and c against a measurements.\n\n```rust\n   let a_against_b = some_measurements(\"a\", \"b\");\n   let b_against_c = some_measurements(\"b\", \"c\");\n   let c_against_a = some_measurements(\"c\", \"a\");\n   \n   let taus = tau::tau_generator(tau::TauAxis::Octave, 10000.0);\n   let sampling_rate = 1.0;\n   let is_fractionnal = false;\n   let overlapping = true;\n\n   let ((dev_a, err_a),(dev_b,err_b),(dev_c,err_c)) =\n      three_cornered_hat(\u0026a_against_b, \u0026b_against_c, \u0026c_against_a,\n         \u0026taus, sampling_rate, is_fractionnal, overlapping, Deviation::Allan).unwrap();\n```\n\n\u003cimg src=\"https://github.com/gwbres/allan-tools/blob/main/tests/3corner.png\" alt=\"alt text\" width=\"450\"/\u003e\n\n### Tools \u0026 utilities\n\n__cumsum__ : (python::numpy like) returns cummulative sum of a serie\n```rust\n   let data: Vec\u003cf64\u003e = some_data();\n   allantools::utilities::cumsum(data, None);\n   allantools::utilities::cumsum(data, Some(10E6_f64)); // opt. normalization\n```\n\n__diff__ : (python::numpy like) returns 1st order derivative of a serie\n```rust\n   let data: Vec\u003cf64\u003e = some_data();\n   allantools::utilities::diff(data, None);\n   allantools::utilities::diff(data, Some(10E6_f64)); // opt. normalization\n```\n\n__random__ : generates a pseudo random sequence 0 \u003c x \u003c= 1.0\n```rust\n   let data = allantools::utilities::random(1024); // 1k symbols \n   println!(\"{:#?}\", data);\n```\n\n__normalize__ : normalizes a sequence to 1/norm :\n```rust\n   let data: Vec\u003cf64\u003e = somedata(); \n   let normalized = allantools::utilities::normalize(\n       data, \n       2.0_f64 * std::f64::consts::PI); // 1/(2pi)\n```\n\n__to\\_fractional\\_frequency__ : converts a raw data serie\nto fractional data.   \n```rust\n   let data: Vec\u003cf64\u003e = somedata(); // sampled @ 10kHz\n   let fract = allantools::utilities::to_fractional_frequency(data, 10E3); // :)\n```\n\n__fractional_integral__ : converts a serie of fractional measurements\nto integrated measurements (like fractional frequency (n.a) to phase time (s)).\n```rust\n   let data: Vec\u003cf64\u003e = somedata(); // (n.a) \n   let fract = allantools::utilities::fractional_integral(data, 1.0); // sampled @ 1Hz :)\n```\n\n__fractional\\_freq\\_to\\_phase\\_time__ : macro wrapper of previous function\n\n__phase\\_to\\_radians__ : converts phase time (s) to phase radians (rad)\n```rust\n   let data: Vec\u003cf64\u003e = somedata(); // (s)\n   let data_rad = allantools::utilities::phase_to_radians(data);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgwbres%2Fallan-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgwbres%2Fallan-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgwbres%2Fallan-tools/lists"}