fastlowess-wasm 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,21 +2,8 @@
2
2
  # LOWESS Project
3
3
 
4
4
  <p align="center">
5
- <a href="https://crates.io/crates/lowess"><img src="https://img.shields.io/badge/lowess-000000?logo=rust&logoColor=white" alt="lowess"></a>
6
- <a href="https://crates.io/crates/fastLowess"><img src="https://img.shields.io/badge/fastLowess-000000?logo=rust&logoColor=white" alt="fastLowess"></a>
7
- <a href="https://pypi.org/project/fastlowess/"><img src="https://img.shields.io/badge/PyPI-3775A9?logo=pypi&logoColor=white" alt="PyPI"></a>
8
- <a href="https://thisisamirv.r-universe.dev/rfastlowess"><img src="https://img.shields.io/badge/R--universe-276DC3?logo=r&logoColor=white" alt="R-universe"></a>
9
- <a href="https://www.npmjs.com/package/fastlowess"><img src="https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white" alt="npm"></a>
10
- <a href="https://juliahub.com/ui/Packages/General/FastLOWESS"><img src="https://img.shields.io/badge/Julia-9558B2?logo=julia&logoColor=white" alt="Julia"></a>
11
5
  <a href="https://www.npmjs.com/package/fastlowess-wasm"><img src="https://img.shields.io/badge/WASM-654FF0?logo=webassembly&logoColor=white" alt="WASM"></a>
12
- <a href="https://github.com/thisisamirv/lowess-project/releases/latest"><img src="https://img.shields.io/badge/C++-00599C?logo=cplusplus&logoColor=white" alt="C++"></a>
13
- <br>
14
- <a href="https://anaconda.org/conda-forge/fastlowess"><img src="https://img.shields.io/badge/fastlowess_(Python)-44A833?logo=anaconda&logoColor=white" alt="fastlowess (Python)"></a>
15
- <a href="https://anaconda.org/conda-forge/libfastlowess"><img src="https://img.shields.io/badge/libfastlowess_(C++)-44A833?logo=anaconda&logoColor=white" alt="libfastlowess (C++)"></a>
16
- <a href="https://anaconda.org/conda-forge/r-rfastlowess"><img src="https://img.shields.io/badge/rfastlowess_(R)-44A833?logo=anaconda&logoColor=white" alt="rfastlowess (R)"></a>
17
- <br>
18
- <a href="https://github.com/thisisamirv/lowess-project/actions/workflows/ci.yml"><img src="https://github.com/thisisamirv/lowess-project/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
19
- <a href="https://github.com/ropensci/software-review/issues/769"><img src="https://badges.ropensci.org/769_status.svg" alt="Status at rOpenSci Software Peer Review"></a>
6
+ <a href="https://github.com/thisisamirv/lowess-project/actions/workflows/ci-wasm.yml"><img src="https://github.com/thisisamirv/lowess-project/actions/workflows/ci-wasm.yml/badge.svg" alt="CI"></a>
20
7
  </p>
21
8
 
22
9
  <p align="center">
@@ -25,38 +12,17 @@
25
12
  <em>One LOWESS to Rule Them All</em>
26
13
  </p>
27
14
 
28
- The fastest, most robust, and most feature-complete language-agnostic LOWESS (Locally Weighted Scatterplot Smoothing) implementation for **Rust**, **Python**, **R**, **Julia**, **JavaScript**, **C++**, and **WebAssembly**.
15
+ The fastest, most robust, and most feature-complete language-agnostic LOWESS (Locally Weighted Scatterplot Smoothing) implementation for **Rust**, **Python**, **R**, **Julia**, **JavaScript**, **C++**, **Go**, **Java**, and **WebAssembly**.
29
16
 
30
- > [!IMPORTANT]
31
- >
32
- > The `lowess-project` contains a complete ecosystem for LOWESS smoothing:
33
- >
34
- > - **[`lowess`](https://crates.io/crates/lowess)** - Core single-threaded Rust implementation with `no_std` support
35
- > - **[`fastLowess`](https://crates.io/crates/fastLowess)** - Parallel CPU and GPU-accelerated Rust wrapper with ndarray integration
36
- > - **[`R bindings`](https://thisisamirv.r-universe.dev/rfastlowess)** - extendr-based R binding
37
- > - **[`Python bindings`](https://pypi.org/project/fastlowess/)** - PyO3-based Python binding
38
- > - **[`Julia bindings`](https://juliahub.com/ui/Packages/General/FastLOWESS)** - Native Julia binding with C FFI
39
- > - **[`JavaScript bindings`](https://www.npmjs.com/package/fastlowess)** - Node.js binding
40
- > - **[`WebAssembly bindings`](https://www.npmjs.com/package/fastlowess-wasm)** - WASM binding
41
- > - **[`C++ bindings`](https://github.com/thisisamirv/lowess-project/releases/latest)** - Native C++ binding with CMake integration
17
+ The `lowess-project` also offers bindings for Rust, Python, R, Julia, Node.js, WebAssembly, C++, Go, and Java — see the [full repository](https://github.com/thisisamirv/lowess-project).
42
18
 
43
19
  ---
44
20
 
45
- ## Installation
46
-
47
- > [!NOTE]
48
- >
49
- > Currently available for R, Python, Rust, Julia, Node.js, WebAssembly, and C++. See the [Installation Guide](https://lowess.readthedocs.io/getting-started/installation/) for detailed installation instructions.
50
-
51
- ### GPU Backend
21
+ ## Installation & Documentation
52
22
 
53
- In addition to `parallel = true` (multi-core CPU), the batch `Lowess` class in every binding — except WebAssembly — as well as the `fastLowess` Rust crate itself, can run on the GPU via `wgpu` (Vulkan/Metal/DX12). It's opt-in and worth enabling for high-throughput processing of large datasets (roughly 10k+ points); for smaller inputs the CPU backend is typically faster. `StreamingLowess`/`OnlineLowess` remain CPU-only. See the [GPU Backend guide](https://lowess.readthedocs.io/en/latest/user-guide/gpu-backend/) for installation instructions and usage.
54
-
55
- ## Documentation
56
-
57
- > [!NOTE]
23
+ > Currently available for R, Python, Rust, Julia, Node.js, WebAssembly, and C++. See the [Installation Guide](https://thisisamirv.github.io/lowess-project/wasm/introduction/installation/) for detailed installation instructions.
58
24
  >
59
- > ### 📚 [View the full documentation](https://lowess.readthedocs.io/)
25
+ > ### 📚 [View the full documentation](https://thisisamirv.github.io/lowess-project/wasm/)
60
26
 
61
27
  ---
62
28
 
@@ -69,7 +35,8 @@ In addition to `parallel = true` (multi-core CPU), the batch `Lowess` class in e
69
35
  | **Flexibility** | High (Distance metrics) | Standard |
70
36
  | **Complexity** | Higher (Matrix inversion) | Lower (Weighted average/slope) |
71
37
 
72
- > [!TIP]
38
+ Read more about how LOWESS works in the [Concepts](https://thisisamirv.github.io/lowess-project/wasm/introduction/concepts/).
39
+
73
40
  > **Note:** For a **LOESS** implementation, use [`loess-project`](https://github.com/thisisamirv/loess-project).
74
41
 
75
42
  ---
@@ -80,7 +47,7 @@ In addition to `parallel = true` (multi-core CPU), the batch `Lowess` class in e
80
47
 
81
48
  The `lowess` project beats the competition in terms of speed, whether in single-threaded or multi-threaded parallel execution. It is on average **200-327x faster** than Python's `statsmodels.lowess` and **2-3x faster** than R's `lowess`.
82
49
 
83
- For more details on the performance comparison, see the [Benchmarks](https://lowess.readthedocs.io/benchmarks/) page.
50
+ For more details on the performance comparison, see the [Benchmarks](https://thisisamirv.github.io/lowess-project/wasm/benchmarks/) page.
84
51
 
85
52
  ### Robustness
86
53
 
@@ -149,342 +116,11 @@ All implementations are **numerical twins** of R's `lowess`:
149
116
  | **Consistency** | ✅ PERFECT | Multiple scenarios pass with strict tolerance |
150
117
  | **Robustness** | ✅ VERIFIED | Robust smoothing matches R exactly |
151
118
 
152
- ## API Reference
153
-
154
- **R:**
155
-
156
- ```r
157
- library(rfastlowess)
158
-
159
- model <- Lowess(
160
- fraction = 0.5,
161
- iterations = 3L,
162
- delta = 0.01,
163
- weight_function = "tricube",
164
- robustness_method = "bisquare",
165
- scaling_method = "mad",
166
- zero_weight_fallback = "use_local_mean",
167
- boundary_policy = "extend",
168
- confidence_intervals = 0.95,
169
- prediction_intervals = 0.95,
170
- return_diagnostics = TRUE,
171
- return_residuals = TRUE,
172
- return_robustness_weights = TRUE,
173
- return_se = TRUE,
174
- cv_fractions = c(0.3, 0.5, 0.7),
175
- cv_method = "kfold",
176
- cv_k = 5L,
177
- cv_seed = 123L,
178
- auto_converge = 1e-4,
179
- parallel = TRUE
180
- )
181
- custom_weights <- rep(1, length(x))
182
- result <- fit(model, x, y, custom_weights = custom_weights)
183
-
184
- # Result structure:
185
- result$x,
186
- result$y,
187
- result$standard_errors,
188
- result$confidence_lower,
189
- result$confidence_upper,
190
- result$prediction_lower,
191
- result$prediction_upper,
192
- result$residuals,
193
- result$robustness_weights,
194
- result$diagnostics,
195
- result$iterations_used,
196
- result$fraction_used,
197
- result$cv_scores
198
- ```
199
-
200
- **Python:**
201
-
202
- ```python
203
- from fastlowess import Lowess
204
-
205
- model = Lowess(
206
- fraction=0.5,
207
- iterations=3,
208
- delta=0.01,
209
- weight_function="tricube",
210
- robustness_method="bisquare",
211
- scaling_method="mad",
212
- zero_weight_fallback="use_local_mean",
213
- boundary_policy="extend",
214
- confidence_intervals=0.95,
215
- prediction_intervals=0.95,
216
- return_diagnostics=True,
217
- return_residuals=True,
218
- return_robustness_weights=True,
219
- return_se=True,
220
- cv_fractions=[0.3, 0.5, 0.7],
221
- cv_method="kfold",
222
- cv_k=5,
223
- cv_seed=123,
224
- auto_converge=1e-4,
225
- parallel=True
226
- )
227
- custom_weights = [1.0] * len(x)
228
- result = model.fit(x, y, custom_weights=custom_weights)
229
-
230
- # Result structure:
231
- result.x,
232
- result.y,
233
- result.standard_errors,
234
- result.confidence_lower,
235
- result.confidence_upper,
236
- result.prediction_lower,
237
- result.prediction_upper,
238
- result.residuals,
239
- result.robustness_weights,
240
- result.diagnostics,
241
- result.iterations_used,
242
- result.fraction_used,
243
- result.cv_scores
244
- ```
245
-
246
- **Rust:**
247
-
248
- ```rust
249
- use lowess::prelude::*;
250
-
251
- let model = Lowess::new()
252
- .fraction(0.5)
253
- .iterations(3)
254
- .delta(0.01)
255
- .weight_function("tricube")
256
- .robustness_method("bisquare")
257
- .scaling_method("mad")
258
- .zero_weight_fallback("use_local_mean")
259
- .boundary_policy("extend")
260
- .return_se()
261
- .confidence_intervals(0.95)
262
- .prediction_intervals(0.95)
263
- .return_diagnostics()
264
- .return_residuals()
265
- .return_robustness_weights()
266
- .cv_method("kfold")
267
- .cv_k(5)
268
- .cv_fractions(vec![0.3, 0.5, 0.7])
269
- .cv_seed(123)
270
- .auto_converge(1e-4)
271
- .custom_weights(vec![1.0; x.len()])
272
- .build()?;
273
-
274
- let result = model.fit(&x, &y)?;
275
-
276
- // Result structure:
277
- pub struct LowessResult<T> {
278
- pub x: Vec<T>, // Sorted x values
279
- pub y: Vec<T>, // Smoothed y values
280
- pub standard_errors: Option<Vec<T>>,
281
- pub confidence_lower: Option<Vec<T>>,
282
- pub confidence_upper: Option<Vec<T>>,
283
- pub prediction_lower: Option<Vec<T>>,
284
- pub prediction_upper: Option<Vec<T>>,
285
- pub residuals: Option<Vec<T>>,
286
- pub robustness_weights: Option<Vec<T>>,
287
- pub diagnostics: Option<Diagnostics<T>>,
288
- pub iterations_used: Option<usize>,
289
- pub fraction_used: T,
290
- pub cv_scores: Option<Vec<T>>,
291
- }
292
- ```
293
-
294
- **Julia:**
295
-
296
- ```julia
297
- using FastLOWESS
298
-
299
- model = Lowess(;
300
- fraction=0.5,
301
- iterations=3,
302
- delta=NaN, # NaN for auto
303
- weight_function="tricube",
304
- robustness_method="bisquare",
305
- scaling_method="mad",
306
- zero_weight_fallback="use_local_mean",
307
- boundary_policy="extend",
308
- confidence_intervals=NaN,
309
- prediction_intervals=NaN,
310
- return_diagnostics=true,
311
- return_residuals=true,
312
- return_robustness_weights=true,
313
- return_se=true,
314
- cv_fractions=Float64[], # e.g. [0.3, 0.5]
315
- cv_method="kfold",
316
- cv_k=5,
317
- cv_seed=123,
318
- auto_converge=NaN,
319
- parallel=true
320
- )
321
- custom_weights = ones(length(x))
322
- result = fit(model, x, y; custom_weights=custom_weights)
323
-
324
- # Result structure:
325
- result.x,
326
- result.y,
327
- result.standard_errors,
328
- result.confidence_lower,
329
- result.confidence_upper,
330
- result.prediction_lower,
331
- result.prediction_upper,
332
- result.residuals,
333
- result.robustness_weights,
334
- result.diagnostics,
335
- result.iterations_used,
336
- result.fraction_used,
337
- result.cv_scores
338
- ```
339
-
340
- **Node.js:**
341
-
342
- ```javascript
343
- import { Lowess } from "fastlowess"
344
-
345
- const model = new Lowess({
346
- fraction: 0.5,
347
- iterations: 3,
348
- delta: 0.01,
349
- weight_function: "tricube",
350
- robustness_method: "bisquare",
351
- scaling_method: "mad",
352
- zero_weight_fallback: "use_local_mean",
353
- boundary_policy: "extend",
354
- return_se: true,
355
- confidence_intervals: 0.95,
356
- prediction_intervals: 0.95,
357
- return_diagnostics: true,
358
- return_residuals: true,
359
- return_robustness_weights: true,
360
- cv_fractions: [0.3, 0.5, 0.7],
361
- cv_method: "kfold",
362
- cv_k: 5,
363
- cv_seed: 123,
364
- auto_converge: 1e-4,
365
- parallel: true
366
- })
367
- const custom_weights = Array(x.length).fill(1.0)
368
- const result = model.fit(x, y, custom_weights)
369
-
370
- // Result structure:
371
- result.x,
372
- result.y,
373
- result.standard_errors,
374
- result.confidence_lower,
375
- result.confidence_upper,
376
- result.prediction_lower,
377
- result.prediction_upper,
378
- result.residuals,
379
- result.robustness_weights,
380
- result.diagnostics,
381
- result.iterations_used,
382
- result.fraction_used,
383
- result.cv_scores
384
- ```
385
-
386
- **WebAssembly:**
387
-
388
- ```javascript
389
- import { Lowess } from "fastlowess-wasm"
390
-
391
- const model = new Lowess({
392
- fraction: 0.5,
393
- iterations: 3,
394
- delta: 0.01,
395
- weight_function: "tricube",
396
- robustness_method: "bisquare",
397
- scaling_method: "mad",
398
- zero_weight_fallback: "use_local_mean",
399
- boundary_policy: "extend",
400
- return_se: true,
401
- confidence_intervals: 0.95,
402
- prediction_intervals: 0.95,
403
- return_diagnostics: true,
404
- return_residuals: true,
405
- return_robustness_weights: true,
406
- cv_fractions: [0.3, 0.5, 0.7],
407
- cv_method: "kfold",
408
- cv_k: 5,
409
- cv_seed: 123,
410
- auto_converge: 1e-4,
411
- parallel: true
412
- })
413
- const custom_weights = new Float64Array(x.length).fill(1)
414
- const result = model.fit(x, y, custom_weights)
415
-
416
- // Result structure:
417
- result.x,
418
- result.y,
419
- result.standard_errors,
420
- result.confidence_lower,
421
- result.confidence_upper,
422
- result.prediction_lower,
423
- result.prediction_upper,
424
- result.residuals,
425
- result.robustness_weights,
426
- result.diagnostics,
427
- result.iterations_used,
428
- result.fraction_used,
429
- result.cv_scores
430
- ```
431
-
432
- **C++:**
433
-
434
- ```cpp
435
- #include "fastlowess.hpp"
436
-
437
- fastlowess::LowessOptions options;
438
- options.fraction = 0.5;
439
- options.iterations = 3;
440
- options.delta = 0.01;
441
- options.weight_function = "tricube";
442
- options.robustness_method = "bisquare";
443
- options.scaling_method = "mad";
444
- options.zero_weight_fallback = "use_local_mean";
445
- options.boundary_policy = "extend";
446
- options.confidence_intervals = 0.95;
447
- options.prediction_intervals = 0.95;
448
- options.return_diagnostics = true;
449
- options.return_residuals = true;
450
- options.return_robustness_weights = true;
451
- options.return_se = true;
452
- options.cv_fractions = {0.3, 0.5, 0.7};
453
- options.cv_method = "kfold";
454
- options.cv_k = 5;
455
- options.cv_seed = 123;
456
- options.auto_converge = 1e-4;
457
- options.parallel = true;
458
-
459
- fastlowess::Lowess model(options);
460
- std::vector<double> custom_weights(x.size(), 1.0);
461
- const auto result = model.fit(x, y, custom_weights).value();
462
-
463
- // Result structure:
464
- result.x_vector(),
465
- result.y_vector(),
466
- result.standard_errors(),
467
- result.confidence_lower(),
468
- result.confidence_upper(),
469
- result.prediction_lower(),
470
- result.prediction_upper(),
471
- result.residuals(),
472
- result.robustness_weights(),
473
- result.diagnostics(),
474
- result.iterations_used(),
475
- result.fraction_used(),
476
- result.cv_scores()
477
- ```
478
-
479
119
  ---
480
120
 
481
121
  ## Contributing
482
122
 
483
- Contributions are welcome! Please see the [Contributing Guide](https://lowess.readthedocs.io/en/latest/contributing/) for more information.
484
-
485
- ## Changelog
486
-
487
- See the [Changelog](https://lwoess.readthedocs.io/en/latest/changelog/) for a history of changes.
123
+ Contributions are welcome! Please see [CONTRIBUTING.md](https://github.com/thisisamirv/lowess-project/blob/main/CONTRIBUTING.md) for more information.
488
124
 
489
125
  ## License
490
126
 
@@ -25,7 +25,7 @@ export interface SmoothOptions {
25
25
  return_residuals?: boolean;
26
26
  /** Include robustness weights in result. Default: false. */
27
27
  return_robustness_weights?: boolean;
28
- /** Compute diagnostics (RMSE, MAE, R², etc.). Default: false. */
28
+ /** Compute diagnostics (RMSE, MAE, R2, etc.). Default: false. */
29
29
  return_diagnostics?: boolean;
30
30
  /** Include standard errors in result. Default: false. */
31
31
  return_se?: boolean;
Binary file
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "Amir Valizadeh <thisisamirv@gmail.com>"
6
6
  ],
7
7
  "description": "High-performance LOWESS (Locally Weighted Scatterplot Smoothing)",
8
- "version": "3.0.0",
8
+ "version": "3.2.0",
9
9
  "license": "MIT OR Apache-2.0",
10
10
  "repository": {
11
11
  "type": "git",
@@ -29,4 +29,4 @@
29
29
  "regression",
30
30
  "bioinformatics"
31
31
  ]
32
- }
32
+ }