General Machine Learning Packages > jSciPy
A Java port of SciPy's signal processing module, offering filters, transformations, and other scientific computing utilities.
jSciPy is a comprehensive Java Scientific Computing and Signal Processing Library designed for Machine Learning on the JVM and Android. Inspired by Python's SciPy, it provides high-performance implementations of essential algorithms.
It currently includes modules for:
- Signal Processing: Butterworth, Chebyshev, Elliptic, Bessel, and FIR (
firwin) filters, Window Functions, 2D Convolution, 2D Cross-Correlation, Savitzky-Golay smoothing, Peak detection, Detrending, Median Filter. - Transformations: FFT (Fast Fourier Transform), Hilbert Transform, Welch PSD, Spectrogram, Periodogram, Convolution, DCT/IDCT.
- Math & Analysis: RK4 ODE Solver, Interpolation (Linear, Cubic Spline, Quadratic, B-Spline), Resampling, Polynomial fitting.
In modern machine learning workflows, most signal processing tasks rely on Python's SciPy utilities. However, there is no Java library that replicates SciPy's behavior with comparable completeness and consistency. This creates a significant gap for teams building ML or signal processing pipelines on the JVM. jSciPy aims to fill this gap, and the demand for such a library is higher than ever.
Table of Contents
- Why jSciPy?
- Features
- Accuracy & Precision
- Documentation
- Getting Started
- How to Include as a Dependency
- Demo Android Application
- Comparison Graphs
- Butterworth Filter
- Chebyshev Filter
- Elliptic Filter
- Bessel Filter
- RK4 Solver
- FindPeaks
- Interpolation
- FFT
- Welch's Method
- Spectrogram
- STFT/ISTFT
- Periodogram
- Resample
- Savitzky-Golay
- Detrend
- MedFilt
- 1D Convolve
- 2D Convolve
- Cross-Correlation
- 2D Cross-Correlation
- DCT
- Polynomial Fit
- 2D FFT
- Hilbert Transform
- SOS Filtering
- Window Functions
- Usage Examples
- Contributing
- License
Why jSciPy?
The table below compares jSciPy’s signal processing and scientific computing features with several other popular Java libraries, highlighting areas where jSciPy provides more comprehensive functionality.
View full size (light) | View full size (dark)
Features
- Advanced Filtering: Butterworth, Chebyshev, Elliptic, Bessel, FIR Design (
firwin). Supports zero-phase (filtfilt), causal (lfilter), and Second-Order Sections (sosfilt) modes. - 2D Processing:
convolve2d,correlate2d(Full/Same/Valid),fft2,ifft2. - Transforms: standard 1D
fft/ifft, real-optimizedrfft/irfft,dct/idct(Discrete Cosine Transform),stft/istft,hilberttransform. - Smoothing & Analysis: Savitzky-Golay,
medfilt(Median Filter),find_peaks,peakProminences,peakWidths, Welch's PSD,spectrogram,detrend,resample. - Correlation & Convolution:
correlate,convolve(Cross-Correlation and convolution with FULL/SAME/VALID modes). - Polynomials:
polyfit,polyval,polyder. - Window Functions: Hamming, Hanning, Blackman, Kaiser, Bartlett, Flat-top, Parzen, Bohman, Triangle.
- Numerical Methods: Interpolation (Linear, Quadratic, Cubic Spline, B-Spline), RK4 ODE Solver.
Accuracy & Precision
jSciPy is rigorously tested against Python's SciPy using a "Golden Master" approach. Below is a summary of the precision (RMSE) achieved across various modules:
View full size (light) | View full size (dark)
Documentation
You can access full documentation javadoc of the jscipy library HERE.
Getting Started
No prerequisites needed to use jSciPy in your project - just add the dependency below.
For contributing to jSciPy development, see CONTRIBUTING.md.
How to Include as a Dependency
Maven Central (Recommended)
jSciPy is published to Maven Central for stable releases. Simply add the dependency to your build.gradle:
dependencies {
implementation 'io.github.hissain:jscipy:3.1.7'
}
Maven Central is automatically included in Gradle projects, so no additional repository configuration is needed.
JitPack (Alternative for Latest Commits)
If you need bleeding-edge features or the latest unreleased commits, use JitPack:
// Add JitPack repository
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.hissain:jscipy:3.1.7' // Note: com.github for JitPack
}
Note: JitPack uses com.github.<username>, while Maven Central uses io.github.<username>. Choose one based on your needs.
Demo Android Application
A seperate demo android application is built on this library that might be helpful to understand how to consume this library. The application can be accessed here.
Comparison Graphs
Butterworth Filter Comparison
Chebyshev Filter Comparison
Type I:
Type II:
Elliptic Filter Comparison
Bessel Filter Comparison
RK4 Solver Comparison
FindPeaks Comparison
Interpolation Comparison
FFT Comparison
Welch's Method Comparison
Spectrogram Comparison
STFT/ISTFT Comparison
Periodogram Comparison
Resample Comparison
Savitzky-Golay Comparison
Smoothing:
Differentiation:
Detrend Comparison
MedFilt Comparison
1D Convolve Comparison
2D Convolve Comparison
Cross-Correlation Comparison
2D Cross-Correlation Comparison
DCT Comparison
FIR Filter Design
Polynomial Fit Comparison
2D FFT Comparison
Hilbert Transform Comparison
SOS Filtering Comparison
Window Functions Comparison
Usage Examples
Digital Filters
All standard IIR filters (Butterworth, Chebyshev I/II, Elliptic, Bessel) are supported with consistent APIs.
import com.hissain.jscipy.Signal;
public class FilterExample {
public static void main(String[] args) {
double[] signal = {/*... input data ...*/};
double fs = 100.0;
double fc = 10.0;
int order = 4;
// 1. Butterworth: Zero-phase vs Causal
double[] zeroPhase = Signal.filtfilt(signal, fs, fc, order);
double[] causal = Signal.lfilter(signal, fs, fc, order);
// 2. Chebyshev Type I (Ripple 1dB) & Type II (Stopband 20dB)
double[] cheby1 = Signal.cheby1_filtfilt(signal, fs, fc, order, 1.0);
double[] cheby2 = Signal.cheby2_filtfilt(signal, fs, fc, order, 20.0);
// 3. Elliptic (Ripple 1dB, Stopband 40dB)
double[] ellip = Signal.ellip_filtfilt(signal, fs, fc, order, 1.0, 40.0);
// 4. Bessel (Linear Phase)
double[] bessel = Signal.bessel_filtfilt(signal, fs, fc, order);
// Filter Modes: High-pass, Band-pass, Band-stop
// Available for all filter types (suffix: _highpass, _bandpass, _bandstop)
double[] bandPass = Signal.filtfilt_bandpass(signal, fs, 8.0, 4.0, order); // Center=10, Width=4
// 5. Second-Order Sections (SOS) Filtering
// If you have SOS coefficients (e.g., from Python/SciPy)
double[][] sos = { /* ... 6 coefficients per section ... */ };
double[] sosFiltered = Signal.sosfilt(signal, sos);
}
}
Correlation & Polynomials
Cross-correlation and polynomial fitting/evaluation.
import com.hissain.jscipy.Signal;
import com.hissain.jscipy.Math;
import com.hissain.jscipy.signal.ConvolutionMode;
public class MathSignalExample {
public static void main(String[] args) {
// 1. Cross-Correlation
double[] x = {1, 2, 3};
double[] target = {0, 1, 0.5};
// equivalent to convolve(x, reverse(target), mode)
double[] corr = Signal.correlate(x, target, ConvolutionMode.FULL);
// 2. Discrete Cosine Transform (DCT Type-II)
double[] dct = Signal.dct(x); // Standard
double[] dctOrtho = Signal.dct(x, true); // Ortho-normalized
// 3. Polynomials
// Fit a 2nd degree polynomial to (x, y) points
double[] xPoints = {0, 1, 2, 3};
double[] yPoints = {1, 2, 5, 10}; // roughly x^2 + 1
// Coefficients: [1.0, 0.0, 1.0] (for x^2 + 1)
double[] coeffs = Math.polyfit(xPoints, yPoints, 2);
// Evaluate polynomial at new points
double[] val = Math.polyval(coeffs, new double[]{4, 5});
// Compute derivative: [2.0, 0.0] (2x)
double[] deriv = Math.polyder(coeffs);
}
}
Spectral Analysis & Transforms
Includes 1D/2D FFT, DCT/IDCT, STFT/ISTFT, Welch's Method, Periodogram, spectrogram, and Hilbert Transform.
import com.hissain.jscipy.Signal;
import com.hissain.jscipy.signal.JComplex;
import com.hissain.jscipy.signal.fft.Welch;
import com.hissain.jscipy.signal.fft.Spectrogram;
import com.hissain.jscipy.signal.fft.Hilbert;
public class SpectralExample {
public static void main(String[] args) {
double[] signal = {/*... input data ...*/};
double fs = 1000.0;
// 1. FFT / IFFT
JComplex[] fft = Signal.fft(signal);
JComplex[] ifft = Signal.ifft(fft);
// 2. Real-optimized FFT (RFFT)
JComplex[] rfft = Signal.rfft(signal);
// 3. Welch's Method (PSD)
Welch.WelchResult psd = Signal.welch(signal, fs, 256);
// Access: psd.f (frequencies), psd.Pxx (power spectrum)
// 4. Spectrogram
Spectrogram.SpectrogramResult spec = Signal.spectrogram(signal, fs);
// Access: spec.frequencies, spec.times, spec.Sxx
// 5. Hilbert Transform (Analytic Signal)
Hilbert h = new Hilbert();
JComplex[] analytic = h.hilbert(signal);
// 6. Short-Time Fourier Transform (STFT)
JComplex[][] stft = Signal.stft(signal); // Uses default nperseg=256, noverlap=128
// 7. Inverse STFT
double[] reconstructed = Signal.istft(stft);
}
}
Smoothing & Signal Operations
Common operations for signal conditioning and feature extraction.
import com.hissain.jscipy.Signal;
import com.hissain.jscipy.signal.filter.SavitzkyGolay;
import com.hissain.jscipy.signal.filter.MedFilt;
public class OperationsExample {
public static void main(String[] args) {
double[] signal = {/*... data ...*/};
// 1. Savitzky-Golay Smoothing
SavitzkyGolay sg = new SavitzkyGolay();
double[] smoothed = sg.savgol_filter(signal, 5, 2); // Window=5, PolyOrder=2
double[] deriv = sg.savgol_filter(signal, 5, 2, 1, 1.0); // 1st Derivative
// 2. Peak Detection
// Min Height=0.5, Min Distance=10, Min Prominence=0.2
int[] peaks = Signal.find_peaks(signal, 0.5, 10, 0.2);
// 3. Median Filter
double[] med = new MedFilt().medfilt(signal, 3); // Kernel=3
// 4. Convolution (Mode: SAME, FULL, VALID)
double[] window = {0.25, 0.5, 0.25};
double[] conv = Signal.convolve(signal, window, ConvolutionMode.SAME);
// 5. Detrending (Linear)
double[] detrended = Signal.detrend(signal, DetrendType.LINEAR);
// 6. Resampling (Up/Down sampling)
// Note: Resampling is part of the Math module
double[] resampled = com.hissain.jscipy.Math.resample(signal, NEW_LENGTH);
}
}
Math & Interpolation
General-purpose numerical utilities.
import com.hissain.jscipy.math.RK4Solver;
import com.hissain.jscipy.Math;
public class MathExample {
public static void main(String[] args) {
// 1. Interpolation (Linear & Cubic)
double[] x = {0, 1, 2}, y = {0, 1, 4};
double[] query = {0.5, 1.5};
double[] lin = Math.interp1d_linear(x, y, query);
double[] quad = Math.interp1d_quadratic(x, y, query);
double[] cub = Math.interp1d_cubic(x, y, query);
double[] bspline = Math.interp1d_bspline(x, y, query, 3); // B-spline with degree k=3
// 2. RK4 ODE Solver (dy/dt = -y)
RK4Solver solver = new RK4Solver();
RK4Solver.Solution sol = solver.solve((t, y) -> -y, y0, t0, tf, step);
}
}
Contributing
Contributions are welcome! Please read our Contribution Guidelines for details on our workflow and coding standards. Feel free to submit issues or pull requests.
Areas for Contribution (Help Wanted)
We are actively looking for contributors to help with:
- Performance Benchmarking: Creating benchmarks for large datasets to compare Java's performance vs NumPy/SciPy.
- Feature Expansion: Implementing missing window functions or additional filter types.
- Edge Case Robustness: Improving handling of
NaN,Infinity, and edge cases in signal processing algorithms. - Documentation: Adding more usage examples and javadocs.
Want to join in community discord? click here
License
This project is licensed under the MIT License.