Skip to main content

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

  1. Installation
  2. Quick Start
  3. Core API — The Series Object
  4. Data I/O
  5. Preprocessing
  6. Spectral Analysis
  7. Wavelet Analysis
  8. Time Series Analysis
  9. Astronomical Calculations
  10. Image Processing & Digitizing
  11. Plotting
  12. CLI Tools (GUI)
  13. Result Objects
  14. Example Datasets
  15. 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:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

acycle-0.5.0-py3-none-any.whl (822.9 kB view details)

Uploaded Python 3

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

Hashes for acycle-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36d76730997fda68068f8e05fa43fa56d6724a536aa424cdf58fd32f9175b394
MD5 ae830ad80ebd53853ba78e4c300b5598
BLAKE2b-256 93688ddd9dd025b9f57425177c464634ef1e337247ef5f6c46cc7c05f6b4792e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page