AcyclePy: Advanced cyclostratigraphy and time series analysis toolkit for Python. Provides programmatic API (Series/detrend/spectral/wavelet/filtering/COCO) and full GUI tools for geological data analysis.
Project description
AcyclePy — Advanced Cyclostratigraphy and Time Series Analysis Toolkit
Version 0.5.0 | Repository | MIT License
AcyclePy is the Python library companion to the Acycle desktop application. It provides a programmatic API for scientific time-series analysis, cyclostratigraphy, spectral analysis, wavelet analysis, filtering, age modeling, and astronomical calculations.
The library follows a Pyleoclim-style fluent design: load a time or depth series, chain preprocessing and analysis calls, then plot or export results — all in a few lines of code.
import acycle as ac
s = ac.Series.from_file("Example-WayaoCarnianGR0.txt", x_unit="m", y_name="GR")
s2 = s.clean(sort=True).interpolate(step=0.33).detrend(window=80, method="lowess")
psd = s2.spectral(method="mtm", nw=2, noise="robust_ar1", fmax=1.0)
psd.plot(xaxis="period")
Note: This package also bundles the full Acycle desktop GUI tools. Use
acycle-imageprocessor,acycle-plot, etc. from the command line.
Table of Contents
- Installation
- Quick Start
- Core API — The Series Object
- Data I/O
- Preprocessing
- Spectral Analysis
- Wavelet Analysis
- Time Series Analysis
- Astronomical Calculations
- Image Processing & Digitizing
- Plotting
- CLI Tools (GUI)
- Result Objects
- Example Datasets
- Contributing
Installation
From PyPI
pip install acycle
Optional extras:
pip install acycle[full] # includes sounddevice, netCDF4, h5py
pip install acycle[dev] # includes pytest, black, flake8
From Source
git clone https://github.com/jnccClub/AcyclePy.git
cd AcyclePy
pip install -e .
Requirements
- Python >= 3.8
- numpy, scipy, pandas, matplotlib, astropy
- PySide6 (for GUI tools), qt-material, Pillow
Quick Start
Load a dataset, clean, interpolate, and compute a power spectrum
import acycle as ac
# Load built-in example data
s = ac.load_example("la2004_etp")
# Chain preprocessing
s2 = (
s.clean(sort=True, dropna=True, duplicate="mean")
.interpolate(step=2.0, method="linear")
.detrend(window=800, method="lowess")
)
# Compute power spectrum
psd = s2.spectral(method="mtm", nw=3, noise="robust_ar1")
psd.plot(xaxis="period")
Generate a synthetic signal and visualize it
import acycle as ac
sig = ac.signal_noise(start=0, stop=1000, step=1, model="sine",
amplitude=5, period=100, bias=0)
sig.plot()
Core API — The Series Object
ac.Series(x, y, **kwargs)
| Parameter | Type | Default | Description |
|---|---|---|---|
x |
array-like | — | Independent variable (time, depth, age) |
y |
array-like | — | Dependent variable (values) |
x_name |
str | "x" |
Name of the x-axis quantity |
x_unit |
str | "" |
Unit label (e.g. "m", "ka") |
y_name |
str | "y" |
Name of the y-axis quantity |
y_unit |
str | "" |
Unit label (e.g. "permil", "W/m^2") |
metadata |
dict | {} |
Arbitrary metadata |
Factory: ac.Series.from_file(path, **kwargs)
s = ac.Series.from_file(
"data.txt",
columns=(0, 1), # x and y column indices (0-based)
delimiter=None, # auto-detect: comma, tab, or whitespace
x_unit="m", y_unit="permil",
sort=True, dropna=True, duplicate="mean",
)
Properties
| Property | Returns | Description |
|---|---|---|
s.x, s.y |
ndarray | Raw data arrays |
s.n |
int | Number of points |
s.dt |
float | Median sampling interval |
s.x_min, s.x_max |
float | X-axis extent |
s.history |
list[dict] | Chain of applied operations |
Chainable Methods (all return a new Series)
| Method | Description |
|---|---|
.clean(sort, duplicate, dropna) |
Sort, de-duplicate, drop NaN |
.interpolate(step, method) |
Uniform resampling |
.interpolate_to(reference) |
Resample onto another Series' grid |
.select(start, stop) |
Extract a sub-range |
.standardize() |
Z-score transformation |
.log10(handle_nonpositive) |
Base-10 logarithm |
.derivative(order) |
Numerical derivative |
.detrend(window, method) |
Remove long-term trend |
.prewhiten(method) |
AR(1) prewhitening |
.spectral(method, nw, noise) |
Power spectral density |
.wavelet(...) |
Continuous wavelet transform |
.filter(kind, method, ...) |
Bandpass/lowpass/highpass filter |
.plot(...) |
Quick matplotlib plot |
.save_series(path) |
Save to delimited text file |
Data I/O
ac.read_series(path, **kwargs)
Read a two-column series from a delimited text file.
s = ac.read_series(
"my_data.csv",
columns=(0, 1),
delimiter=",", # auto, tab, comma, space
x_unit="m", y_name="GR",
sort=True,
)
ac.write_series(series, path, sep="\t")
Save a Series to a text file.
ac.load_example(name)
Load one of the built-in example datasets (see Example Datasets).
ac.load_lr04(start=0, stop=5320, step=None)
Load the LR04 benthic d18O stack.
ac.load_cenogrid(variable="d18o")
Load CENOGRID data ("d18o" or "d13c").
Preprocessing
Cleaning
s2 = s.clean(
sort=True, # sort by ascending x
ascending=True,
duplicate="mean", # "mean" | "first" | "last" | "drop"
dropna=True,
)
Interpolation
# Uniform grid
s2 = s.interpolate(step=0.33, method="linear")
# Or interpolate onto another Series' grid
s2 = s.interpolate_to(reference_series, method="linear")
Detrending
s2 = s.detrend(
window=0.35, # window as fraction of record length
window_unit="fraction", # "fraction" or "axis"
method="lowess", # "linear" | "polynomial" | "lowess" | "loess" | "rlowess" | "rloess" | "moving_mean"
poly_order=None,
return_trend=False, # if True, also returns the trend line
)
Prewhitening
s2 = s.prewhiten(
method="robust_ar1", # "classic_ar1" | "robust_ar1" | "user"
rho=None, # user-specified lag-1 coefficient
diff_when_rho_one=True,
)
Other Preprocessing
s.select(start=10, stop=50) # Sub-range extraction
s.standardize(ddof=0) # Z-score
s.log10(handle_nonpositive="mask") # Base-10 log
s.derivative(order=1, edge_order=1) # Numerical derivative
The following are available via the GUI tools and exposed through the CLI wrappers (see CLI Tools):
- Data clipping by threshold
- Section removal with time adjustment
- Gap insertion
- Peak removal
- Changepoint detection (Bayesian)
- Column manipulation and merging
Spectral Analysis
series.spectral(**kwargs)
Compute the power spectral density.
psd = s.spectral(
method="mtm", # "mtm" | "lomb_scargle" | "periodogram"
nw=2, # time-bandwidth product (MTM only)
n_tapers=None, # auto: 2*nw - 1
pad=None, # zero-padding length
fmin=None, # minimum frequency
fmax="nyquist", # maximum frequency
xaxis="frequency", # "frequency" | "period"
noise="robust_ar1", # "classic_ar1" | "robust_ar1" | "power_law" | "swa" | None
confidence=(0.90, 0.95, 0.99, 0.999),
median_smooth=0.2, # smoothing window (fraction of max freq)
output="power", # "power" | "amplitude" | "ftest"
save=False,
)
Returns: ac.PSD with attributes .frequency, .power, .period,
.noise_power, .smoothed_power, .settings.
Plotting a spectrum
psd.plot(xaxis="period") # period axis (log scale)
psd.plot(xaxis="frequency") # frequency axis
Evolutionary spectral analysis (via GUI)
Launch the full evolutionary spectral analysis tool:
ac.launch_spectral(data_file="data.txt")
Wavelet Analysis
Available through the GUI wavelet analysis tool:
acycle-wavelet (CLI wrapper)
The wavelet API (programmatic access planned for v0.6.0):
# Planned API:
wav = s.wavelet(
mother="MORLET",
period_min=None, period_max=None,
dj=0.1, pad=True,
sig_level=0.05,
)
wav.plot()
Time Series Analysis
Filtering
result = s.filter(
kind="bandpass", # "bandpass" | "lowpass" | "highpass"
method="gaussian", # "gaussian" | "taner" | "butter" | "cheby1" | "ellip"
flow=0.01, fhigh=0.05, # frequency bounds
remove_mean=True,
output_amplitude=True, # include amplitude/phase for taner
)
COCO / eCOCO (Evolutionary Correlation Coefficient)
Available via GUI (programmatic API planned for v0.6.0):
# Planned:
coco = s.coco(
median_age=230,
sed_rate=(4.29, 29.89, 0.2),
n_sim=2000,
astronomical_solution="La2004",
)
coco.plot()
Age Modeling & Tuning
Available via GUI tools. Programmatic API for build_age_model, tune, and sediment rate conversion planned for v0.6.0.
DYNOT / Sediment Noise Models
Available through the GUI acycle-dynot tool.
Astronomical Calculations
ac.insolation(start, stop, **kwargs)
Compute solar insolation from an astronomical solution.
ins = ac.insolation(
0, 1000, step=1,
solution="La2004",
day=80, latitude=65,
solar_constant=1365,
time_unit="ka",
)
ac.astronomical_solution(start, stop, **kwargs)
Retrieve eccentricity, obliquity, precession, and ETP.
ecc = ac.astronomical_solution(0, 1000, step=1, output="eccentricity")
etp = ac.astronomical_solution(0, 1000, step=1, output="ETP",
weights=(1, 1, -1), normalize=True)
ac.milankovitch_calculator(**kwargs)
Compute Milankovitch cycle periods for a given geological age.
result = ac.milankovitch_calculator(model="Waltham2015", age=100)
# result["earth_moon_distance"], result["day_length"], etc.
ac.signal_noise(**kwargs)
Generate synthetic signals for testing.
sine = ac.signal_noise(start=0, stop=1000, model="sine",
amplitude=5, period=100)
red = ac.signal_noise(start=0, stop=1000, model="red_noise",
mean=0, std=1, rho=0.5, seed=42)
Image Processing & Digitizing
Launch the full image processing GUI:
ac.launch_imageprocessor(image="photo.jpg")
Features:
- Image magnification with real-time zoom
- Coordinate calibration (pixel to real-world coordinates)
- Color analysis (dominant color detection, K-means clustering)
- Data point extraction (manual, box-select, freehand drawing)
- Image to grayscale / CIE Lab conversion
- Profile digitization
- Undo/Redo support (Ctrl+Z / Ctrl+Y)
Plotting
series.plot(**kwargs)
Quick visualization of a single series:
s.plot(kind="line", color="steelblue", line_width=1.5,
xlabel="Depth (m)", ylabel="Value", grid=True)
Multi-series plotting
fig, axes = plt.subplots(2, 1, sharex=True)
s1.plot(ax=axes[0], color="red")
s2.plot(ax=axes[1], color="blue")
PlotPro (GUI)
Launch the full interactive PlotPro tool:
ac.launch_plotpro(files=["data1.txt", "data2.txt"])
CLI Tools (GUI)
The package installs these command-line entry points:
| Command | Tool | Description |
|---|---|---|
acycle-imageprocessor |
Image Processor | Image digitizing and analysis |
acycle-plot |
PlotPro | Interactive plotting |
acycle-interpolation [file] |
Interpolation Pro | Advanced interpolation |
acycle-data-extractor [file] |
Data Extractor | Extract data segments |
acycle-section-remover [file] |
Section Remover | Remove with time adjustment |
acycle-gap-adder [file] |
Gap Adder | Insert gaps into series |
acycle-data-clipper [file] |
Data Clipper | Clip by threshold |
acycle-image-analyzer |
Image Analyzer | Advanced image analysis |
From Python:
ac.launch_imageprocessor(image="path/to/image.png")
ac.launch_plotpro(files=["data.txt"])
ac.launch_interpolation(data_file="data.txt", step=0.5)
ac.launch_data_extractor(data_file="data.txt", start=0, stop=100)
Result Objects
All analysis results share a consistent interface:
| Object | Used For | Key Attributes |
|---|---|---|
PSD |
Power spectral density | .frequency, .power, .period, .noise_power, .smoothed_power, .settings |
EvolutiveSpectrum |
Evolutionary spectrogram | .x, .frequency, .power, .settings |
WaveletResult |
Wavelet transform | .x, .period, .power, .coi, .significance |
FilterResult |
Filtered signal | .filtered, .amplitude, .phase |
AgeModel |
Age model | .depth, .age, .sed_rate |
CocoResult |
COCO/eCOCO | .sed_rate, .rho, .p_value |
SedNoiseResult |
DYNOT/rho1 | .age, .median, .quantiles |
Every result object supports:
result.plot(...) # generate a figure
result.to_dataframe() # export to pandas DataFrame
result.save("prefix") # save to files
result.settings # dict of computation parameters
Example Datasets
Bundled example datasets can be loaded with ac.load_example(name):
| Name | File | Content |
|---|---|---|
"wayao_gr" |
Example-WayaoCarnianGR0.txt | Gamma-ray log, Carnian |
"newark_depth_rank" |
Example-LateTriassicNewarkDepthRank.txt | Newark Basin depth ranks |
"la2004_etp" |
Example-La2004-1E.5T-1P-0-2000.txt | La2004 ETP solution |
"petm_logfe" |
Example-SvalbardPETM-logFe.txt | PETM log-Fe data |
"rednoise_0.7_2000" |
Example-Rednoise0.7-2000.txt | Synthetic red noise |
"guandao_gr" |
Example-Guandao2AnisianGR.txt | Guandao Anisian GR |
"lr04" |
LR04stack5320ka.txt | LR04 benthic stack |
"cenogrid_d13c" |
Example-cenogrid-d13c.txt | CENOGRID d13C |
"cenogrid_d18o" |
Example-cenogrid-d18o.txt | CENOGRID d18O |
"launa_loa_co2" |
Example-LaunaLoa-Hawaii-CO2-monthly-mean.txt | Mauna Loa CO2 |
"csa_extinction" |
Example-CSA-extinction.txt | Extinction event data |
Package Structure
acycle/
__init__.py # top-level imports and version
core.py # Series, MultiSeries, PSD, WaveletResult, etc.
io.py # read_series, write_series, load_example, etc.
spectral.py # MTM, Lomb-Scargle, periodogram backends
basic.py # insolation, astronomical_solution, signal_noise
cli.py # CLI compatibility wrappers for GUI tools
plot/ # PlotPro — interactive matplotlib-based plotting
math_menu/ # Data processing tools (interpolation, clipping, etc.)
time_menu/ # Time series analysis (spectral, wavelet, COCO, age, etc.)
series_menu/ # Astronomical series (solutions, Milankovitch)
image/ # Image processing and digitizing
menu/ # Qt menu handler infrastructure
util/ # General utilities
window/ # Multi-pane window layout engine
resources/ # Icons and bundled assets
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
Development setup:
git clone https://github.com/jnccClub/AcyclePy.git
cd AcyclePy
pip install -e ".[dev]"
pytest
License
MIT License — see LICENSE for details.
Citation
If AcyclePy contributes to a scientific publication, please cite the Acycle desktop application:
Li, M., Hinnov, L., & Kump, L. (2019). Acycle: Time-series analysis software for paleoclimate research and education. Computers & Geosciences, 127, 12-22. https://doi.org/10.1016/j.cageo.2019.02.011
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file acycle-0.5.0-py3-none-any.whl.
File metadata
- Download URL: acycle-0.5.0-py3-none-any.whl
- Upload date:
- Size: 822.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36d76730997fda68068f8e05fa43fa56d6724a536aa424cdf58fd32f9175b394
|
|
| MD5 |
ae830ad80ebd53853ba78e4c300b5598
|
|
| BLAKE2b-256 |
93688ddd9dd025b9f57425177c464634ef1e337247ef5f6c46cc7c05f6b4792e
|