pkft 0.1.0a1__tar.gz
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.
Potentially problematic release.
This version of pkft might be problematic. Click here for more details.
- pkft-0.1.0a1/.github/workflows/docs.yml +41 -0
- pkft-0.1.0a1/.github/workflows/release.yml +109 -0
- pkft-0.1.0a1/.gitignore +9 -0
- pkft-0.1.0a1/.prettierrc +7 -0
- pkft-0.1.0a1/.readthedocs.yaml +17 -0
- pkft-0.1.0a1/.ruff.toml +5 -0
- pkft-0.1.0a1/.zenodo.json +8 -0
- pkft-0.1.0a1/LICENSE +21 -0
- pkft-0.1.0a1/MANIFEST.in +7 -0
- pkft-0.1.0a1/Makefile +97 -0
- pkft-0.1.0a1/PKG-INFO +132 -0
- pkft-0.1.0a1/README.md +104 -0
- pkft-0.1.0a1/assets/images/repo-banner.png +0 -0
- pkft-0.1.0a1/docs/Makefile +42 -0
- pkft-0.1.0a1/docs/_static/css/console.css +97 -0
- pkft-0.1.0a1/docs/_static/css/darkmode.css +33 -0
- pkft-0.1.0a1/docs/_static/js/darkmode.js +43 -0
- pkft-0.1.0a1/docs/api.rst +66 -0
- pkft-0.1.0a1/docs/conf.py +71 -0
- pkft-0.1.0a1/docs/index.rst +33 -0
- pkft-0.1.0a1/docs/installation.rst +8 -0
- pkft-0.1.0a1/docs/make.bat +35 -0
- pkft-0.1.0a1/docs/pkft-logo.svg +7 -0
- pkft-0.1.0a1/docs/requirements.txt +8 -0
- pkft-0.1.0a1/docs/usage.rst +73 -0
- pkft-0.1.0a1/environment.yml +10 -0
- pkft-0.1.0a1/pkft/__init__.py +3 -0
- pkft-0.1.0a1/pkft/api.py +114 -0
- pkft-0.1.0a1/pkft/curves.py +56 -0
- pkft-0.1.0a1/pkft/data/__init__.py +0 -0
- pkft-0.1.0a1/pkft/data/demo-trayler-2020.csv +49 -0
- pkft-0.1.0a1/pkft/mixture.py +194 -0
- pkft-0.1.0a1/pkft/models.py +62 -0
- pkft-0.1.0a1/pkft/static/app.css +338 -0
- pkft-0.1.0a1/pkft/static/app.js +492 -0
- pkft-0.1.0a1/pkft/static/index.html +94 -0
- pkft-0.1.0a1/pkft/static/pkft-logo.svg +7 -0
- pkft-0.1.0a1/pkft.egg-info/PKG-INFO +132 -0
- pkft-0.1.0a1/pkft.egg-info/SOURCES.txt +49 -0
- pkft-0.1.0a1/pkft.egg-info/dependency_links.txt +1 -0
- pkft-0.1.0a1/pkft.egg-info/entry_points.txt +2 -0
- pkft-0.1.0a1/pkft.egg-info/requires.txt +10 -0
- pkft-0.1.0a1/pkft.egg-info/scm_file_list.json +45 -0
- pkft-0.1.0a1/pkft.egg-info/scm_version.json +8 -0
- pkft-0.1.0a1/pkft.egg-info/top_level.txt +1 -0
- pkft-0.1.0a1/pyproject.toml +48 -0
- pkft-0.1.0a1/pyrightconfig.json +14 -0
- pkft-0.1.0a1/pytest.ini +11 -0
- pkft-0.1.0a1/setup.cfg +4 -0
- pkft-0.1.0a1/tests/test_api.py +90 -0
- pkft-0.1.0a1/tests/test_mixture.py +50 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Build and Check Docs
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
jobs:
|
|
9
|
+
docs:
|
|
10
|
+
name: Test on ${{ matrix.os }} with Python ${{ matrix.python-version }}
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-24.04]
|
|
16
|
+
python-version: ["3.13"]
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v6
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v6
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
cache: "pip"
|
|
27
|
+
- name: Install documentation dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install -e ".[dev]"
|
|
31
|
+
pip install -r docs/requirements.txt
|
|
32
|
+
- name: Build documentation
|
|
33
|
+
run: |
|
|
34
|
+
cd docs
|
|
35
|
+
make html
|
|
36
|
+
- name: Upload docs as artifact
|
|
37
|
+
uses: actions/upload-artifact@v6
|
|
38
|
+
with:
|
|
39
|
+
name: html-docs-${{ matrix.os }}-python-${{ matrix.python-version }}
|
|
40
|
+
path: docs/_build/html
|
|
41
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Test and Release
|
|
3
|
+
permissions:
|
|
4
|
+
contents: write
|
|
5
|
+
packages: write
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
pull_request:
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Test on ${{ matrix.os }} with Python ${{ matrix.python-version }}
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
os: [ubuntu-24.04, macos-latest, windows-latest]
|
|
19
|
+
python-version: ["3.12", "3.13"]
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout repository
|
|
22
|
+
uses: actions/checkout@v6
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v6
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
cache: "pip"
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade pip
|
|
33
|
+
pip install -e ".[dev]"
|
|
34
|
+
- name: Run tests and generate coverage report
|
|
35
|
+
run: |
|
|
36
|
+
pytest --cov=pkft --cov-branch --cov-report=xml
|
|
37
|
+
- name: Upload coverage reports to Codecov
|
|
38
|
+
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1, node24 (v5 tag still nests github-script v7/node20)
|
|
39
|
+
with:
|
|
40
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
41
|
+
check-version:
|
|
42
|
+
name: Check if major or minor version
|
|
43
|
+
needs: test
|
|
44
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
45
|
+
runs-on: ubuntu-24.04
|
|
46
|
+
outputs:
|
|
47
|
+
is_major_minor: ${{ steps.check_tag.outputs.is_major_minor }}
|
|
48
|
+
steps:
|
|
49
|
+
- name: Check tag format
|
|
50
|
+
id: check_tag
|
|
51
|
+
run: |
|
|
52
|
+
TAG=${GITHUB_REF#refs/tags/}
|
|
53
|
+
VERSION=${TAG#v}
|
|
54
|
+
VERSION_CORE=$(echo $VERSION | cut -d'-' -f1 | cut -d'+' -f1)
|
|
55
|
+
IFS='.' read -ra VERSION_PARTS <<< "$VERSION_CORE"
|
|
56
|
+
if [[ ${#VERSION_PARTS[@]} -eq 3 && ${VERSION_PARTS[2]} != "0" ]]; then
|
|
57
|
+
echo "Tag $TAG is a patch version"
|
|
58
|
+
echo "is_major_minor=false" >> $GITHUB_OUTPUT
|
|
59
|
+
elif [[ "$VERSION" == *"-"* ]]; then
|
|
60
|
+
echo "Tag $TAG is a prerelease version"
|
|
61
|
+
echo "is_major_minor=false" >> $GITHUB_OUTPUT
|
|
62
|
+
else
|
|
63
|
+
echo "Tag $TAG is a major or minor version"
|
|
64
|
+
echo "is_major_minor=true" >> $GITHUB_OUTPUT
|
|
65
|
+
fi
|
|
66
|
+
build:
|
|
67
|
+
name: Build and Upload to PyPI
|
|
68
|
+
needs: check-version
|
|
69
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
70
|
+
runs-on: ubuntu-24.04
|
|
71
|
+
steps:
|
|
72
|
+
- name: Checkout repository
|
|
73
|
+
uses: actions/checkout@v6
|
|
74
|
+
with:
|
|
75
|
+
fetch-depth: 0
|
|
76
|
+
- name: Set up Python
|
|
77
|
+
uses: actions/setup-python@v6
|
|
78
|
+
with:
|
|
79
|
+
python-version: "3.13"
|
|
80
|
+
- name: Install build tools
|
|
81
|
+
run: |
|
|
82
|
+
python -m pip install --upgrade pip
|
|
83
|
+
pip install setuptools wheel twine build setuptools-scm
|
|
84
|
+
- name: Verify version
|
|
85
|
+
run: python -m setuptools_scm
|
|
86
|
+
- name: Build distribution
|
|
87
|
+
run: |
|
|
88
|
+
rm -rf dist build *.egg-info
|
|
89
|
+
python -m build
|
|
90
|
+
- name: Check dist artifacts
|
|
91
|
+
run: |
|
|
92
|
+
ls -lh dist
|
|
93
|
+
test -f dist/*.whl
|
|
94
|
+
test -f dist/*.tar.gz
|
|
95
|
+
- name: Upload to Test PyPI
|
|
96
|
+
run: twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*
|
|
97
|
+
env:
|
|
98
|
+
TWINE_USERNAME: "__token__"
|
|
99
|
+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
|
100
|
+
- name: Upload to PyPI
|
|
101
|
+
run: twine upload --verbose dist/*
|
|
102
|
+
env:
|
|
103
|
+
TWINE_USERNAME: "__token__"
|
|
104
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
105
|
+
- name: Upload dist to GitHub release
|
|
106
|
+
uses: softprops/action-gh-release@v3
|
|
107
|
+
with:
|
|
108
|
+
files: dist/*
|
|
109
|
+
prerelease: ${{ needs.check-version.outputs.is_major_minor != 'true' }}
|
pkft-0.1.0a1/.gitignore
ADDED
pkft-0.1.0a1/.prettierrc
ADDED
pkft-0.1.0a1/.ruff.toml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "pkft: Peakfit Explorer",
|
|
3
|
+
"description": "A FastAPI service for Gaussian mixture peak finding in 1D data with uncertainties.",
|
|
4
|
+
"creators": [{ "name": "Kerswell, Buchanan" }],
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": ["peak-finding", "mixture-model", "uncertainty", "fastapi"],
|
|
7
|
+
"upload_type": "software"
|
|
8
|
+
}
|
pkft-0.1.0a1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Buchanan Kerswell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pkft-0.1.0a1/MANIFEST.in
ADDED
pkft-0.1.0a1/Makefile
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Top-level dirs
|
|
2
|
+
PROJECT_ROOT := $(CURDIR)
|
|
3
|
+
APP := $(PROJECT_ROOT)/pkft
|
|
4
|
+
TESTS := $(PROJECT_ROOT)/tests
|
|
5
|
+
DOCS := $(PROJECT_ROOT)/docs
|
|
6
|
+
|
|
7
|
+
# Conda config
|
|
8
|
+
CONDA_ENV_ID := pkft
|
|
9
|
+
CONDA_ENV_YML := environment.yml
|
|
10
|
+
CONDA_PYTHON = $$(conda run -n $(CONDA_ENV_ID) which python)
|
|
11
|
+
|
|
12
|
+
# Server
|
|
13
|
+
APP_MODULE := pkft.api:app
|
|
14
|
+
|
|
15
|
+
# Targets
|
|
16
|
+
.PHONY: run docs test format environment clean deep-clean
|
|
17
|
+
|
|
18
|
+
all: environment test run
|
|
19
|
+
|
|
20
|
+
run:
|
|
21
|
+
@$(CONDA_PYTHON) -m uvicorn $(APP_MODULE) --host 127.0.0.1 --port 8000 --reload
|
|
22
|
+
|
|
23
|
+
# Cleanup directory
|
|
24
|
+
CLEAN := $(APP)/**/__pycache__ $(APP)/**/*.pyc $(TESTS)/**/__pycache__ $(CURDIR)/.pytest_cache $(CURDIR)/build $(CURDIR)/dist $(CURDIR)/*.egg-info $(CURDIR)/.coverage $(CURDIR)/coverage.xml
|
|
25
|
+
DEEP_CLEAN :=
|
|
26
|
+
|
|
27
|
+
docs:
|
|
28
|
+
@$(MAKE) -C docs html
|
|
29
|
+
|
|
30
|
+
test:
|
|
31
|
+
@$(CONDA_PYTHON) -m pytest --cov=pkft --cov-branch --cov-report=xml
|
|
32
|
+
|
|
33
|
+
format:
|
|
34
|
+
@$(CONDA_PYTHON) -m ruff format .
|
|
35
|
+
@npx --yes prettier --write "pkft/static/*.js" "pkft/static/*.css"
|
|
36
|
+
|
|
37
|
+
environment: $(CONDA_ENV_YML)
|
|
38
|
+
@if conda info --envs | awk '{print $$1}' | grep -qx "$(CONDA_ENV_ID)"; then \
|
|
39
|
+
echo "Environment '$$name' already exists. Skipping..."; \
|
|
40
|
+
else \
|
|
41
|
+
echo "Creating environment: $(CONDA_ENV_ID) from $(CONDA_ENV_YML)"; \
|
|
42
|
+
conda env create -n "$(CONDA_ENV_ID)" -f "$(CONDA_ENV_YML)"; \
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
clean:
|
|
46
|
+
@echo "==> Cleaning ..."
|
|
47
|
+
@for item in $(CLEAN); do \
|
|
48
|
+
safe_rm() { \
|
|
49
|
+
if [ -e "$$1" ]; then \
|
|
50
|
+
ABS_PATH=$$(realpath "$$1"); \
|
|
51
|
+
case "$$ABS_PATH" in \
|
|
52
|
+
$(PROJECT_ROOT)*) \
|
|
53
|
+
echo "-> Safely removing\n $$ABS_PATH"; \
|
|
54
|
+
rm -rf "$$ABS_PATH";; \
|
|
55
|
+
*) \
|
|
56
|
+
echo "!! Skipping (outside project root)\n $$ABS_PATH";; \
|
|
57
|
+
esac; \
|
|
58
|
+
else \
|
|
59
|
+
echo "-- Skipping (not found)\n $$1"; \
|
|
60
|
+
fi; \
|
|
61
|
+
}; \
|
|
62
|
+
safe_rm "$$item"; \
|
|
63
|
+
done
|
|
64
|
+
@$(MAKE) -C docs clean || true
|
|
65
|
+
@find . -name ".DS_Store" -type f -delete
|
|
66
|
+
|
|
67
|
+
deep-clean:
|
|
68
|
+
@echo "==> Deep cleaning ..."
|
|
69
|
+
@for item in $(DEEP_CLEAN); do \
|
|
70
|
+
safe_rm() { \
|
|
71
|
+
if [ -e "$$1" ]; then \
|
|
72
|
+
ABS_PATH=$$(realpath "$$1"); \
|
|
73
|
+
case "$$ABS_PATH" in \
|
|
74
|
+
$(PROJECT_ROOT)*) \
|
|
75
|
+
echo "-> Safely removing\n $$ABS_PATH"; \
|
|
76
|
+
rm -rf "$$ABS_PATH";; \
|
|
77
|
+
*) \
|
|
78
|
+
echo "!! Skipping (outside project root)\n $$ABS_PATH";; \
|
|
79
|
+
esac; \
|
|
80
|
+
else \
|
|
81
|
+
echo "-- Skipping (not found)\n $$1"; \
|
|
82
|
+
fi; \
|
|
83
|
+
}; \
|
|
84
|
+
safe_rm "$$item"; \
|
|
85
|
+
done
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
help:
|
|
89
|
+
@echo "Available targets:"
|
|
90
|
+
@echo " run Run pkft app locally"
|
|
91
|
+
@echo " docs Build documentation"
|
|
92
|
+
@echo " test Run unit tests"
|
|
93
|
+
@echo " format Format code to 150 columns (ruff + prettier)"
|
|
94
|
+
@echo " environment Create Conda environment"
|
|
95
|
+
@echo " clean Cleanup unnecessary files and directories (safe)"
|
|
96
|
+
@echo " deep-clean Deep clean figures and results (use with caution!)"
|
|
97
|
+
@echo " help Show this help message"
|
pkft-0.1.0a1/PKG-INFO
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pkft
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: A FastAPI service for Gaussian mixture peak finding in 1D geochronological data
|
|
5
|
+
Author-email: Buchanan Kerswell <buck.kerswell@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/buchanankerswell/pkft
|
|
8
|
+
Classifier: Natural Language :: English
|
|
9
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: fastapi>=0.115
|
|
19
|
+
Requires-Dist: uvicorn>=0.30
|
|
20
|
+
Requires-Dist: pydantic>=2.0
|
|
21
|
+
Requires-Dist: numpy
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
25
|
+
Requires-Dist: httpx; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# pkft: Peakfit Explorer
|
|
30
|
+
|
|
31
|
+
📚 See the [documentation](https://pkft.readthedocs.io/en/latest/) for details.
|
|
32
|
+
|
|
33
|
+
Peak finding for 1D data with uncertainties by discrete Gaussian mixture
|
|
34
|
+
modelling (Galbraith & Laslett, 1993) in the spirit of IsoplotR
|
|
35
|
+
`peakfit` (Vermeesch, 2018), served as a FastAPI service with a minimal
|
|
36
|
+
dependency-free web UI.
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
*Figure: mixture fit for the bundled Trayler et al. 2020 demo dataset.*
|
|
41
|
+
|
|
42
|
+
## Prerequisite software
|
|
43
|
+
|
|
44
|
+
This project is written in [python](https://www.python.org). For most users, I recommend installing the [miniforge](https://github.com/conda-forge/miniforge) python distribution. This distributions includes a minimal installation of python and the package manager [conda](https://docs.conda.io/en/latest/), which is required to build the necessary python environment for this software.
|
|
45
|
+
|
|
46
|
+
For macOS users, miniforge can be installed with [homebrew](https://brew.sh):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
brew install miniforge
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For Window's users, miniforge can be installed from a binary .exe. Follow the instructions for miniconda, anaconda, or miniforge (recommended) [here](https://docs.conda.io/projects/conda/en/stable/user-guide/install/windows.html).
|
|
53
|
+
|
|
54
|
+
## Installation Guide
|
|
55
|
+
|
|
56
|
+
To install with Conda (recommended):
|
|
57
|
+
|
|
58
|
+
``` bash
|
|
59
|
+
# Create conda environment
|
|
60
|
+
conda create -n pkft python=3.13 pip
|
|
61
|
+
|
|
62
|
+
# Activate conda environment
|
|
63
|
+
conda activate pkft
|
|
64
|
+
|
|
65
|
+
# Install pkft
|
|
66
|
+
pip install pkft
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
If you want to install the development version for local testing in "editable" mode:
|
|
70
|
+
|
|
71
|
+
``` bash
|
|
72
|
+
# Clone repo
|
|
73
|
+
git clone https://github.com/buchanankerswell/pkft.git
|
|
74
|
+
cd pkft
|
|
75
|
+
|
|
76
|
+
# Checkout develop branch
|
|
77
|
+
git checkout develop
|
|
78
|
+
|
|
79
|
+
# Create conda environment and install pkft locally in editable mode
|
|
80
|
+
# including optional development and documentation dependencies
|
|
81
|
+
make environment
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Usage Guide
|
|
85
|
+
|
|
86
|
+
After installing pkft using either method above, launch the server from the command line:
|
|
87
|
+
|
|
88
|
+
``` bash
|
|
89
|
+
# Activate conda environment
|
|
90
|
+
conda activate pkft
|
|
91
|
+
|
|
92
|
+
# Launch server (UI at http://127.0.0.1:8000/)
|
|
93
|
+
pkft
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The same JSON serves browsers and agents:
|
|
97
|
+
|
|
98
|
+
``` bash
|
|
99
|
+
curl -X POST http://127.0.0.1:8000/fit \
|
|
100
|
+
-H 'Content-Type: application/json' \
|
|
101
|
+
-d '{"observations": [{"value": 17.634, "standard_error": 0.016}], "peak_count": 1}'
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Open http://127.0.0.1:8000/ for the data explorer, http://127.0.0.1:8000/mixture for the mixture tab, or click **Load demo** for the bundled Trayler et al. 2020 dataset.
|
|
105
|
+
|
|
106
|
+
## Method
|
|
107
|
+
|
|
108
|
+
Each observation `x[i]` with analytical variance `s[i]**2` contributes
|
|
109
|
+
`sum_j pi[j] * N(x[i] | mu[j], s[i]**2)` to the likelihood (Galbraith &
|
|
110
|
+
Laslett, 1993, discrete mixture; IsoplotR `peakfit` with `log=FALSE`).
|
|
111
|
+
Expectation–maximisation (10 restarts) maximises the log-likelihood;
|
|
112
|
+
`peak_count = 0` selects 1..5 components by BIC. Results maximise
|
|
113
|
+
the same likelihood as IsoplotR `peakfit` with `log=FALSE`, with small
|
|
114
|
+
numerical differences from the different optimiser and starting points.
|
|
115
|
+
See the docs for the full API reference.
|
|
116
|
+
|
|
117
|
+
## Citation
|
|
118
|
+
|
|
119
|
+
Cite the app as Kerswell, B. (2023). Peakfit Explorer.
|
|
120
|
+
https://doi.org/10.17605/OSF.IO/2BU3C
|
|
121
|
+
|
|
122
|
+
## Acknowledgement
|
|
123
|
+
|
|
124
|
+
I gratefully acknowledge feedback and suggestions provided by
|
|
125
|
+
[Matthew Kohn](https://scholar.google.com/citations?user=xSyB1KQAAAAJ&hl=en&oi=ao)
|
|
126
|
+
and [Kayleigh Harvey](https://www.linkedin.com/in/kayleigh-harvey-phd-98471952).
|
|
127
|
+
Peak modelling follows [IsoplotR](https://github.com/pvermees/IsoplotR/)
|
|
128
|
+
(Vermeesch, 2018); demo data from Trayler et al. (2020).
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT License — see [LICENSE](LICENSE).
|
pkft-0.1.0a1/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# pkft: Peakfit Explorer
|
|
2
|
+
|
|
3
|
+
📚 See the [documentation](https://pkft.readthedocs.io/en/latest/) for details.
|
|
4
|
+
|
|
5
|
+
Peak finding for 1D data with uncertainties by discrete Gaussian mixture
|
|
6
|
+
modelling (Galbraith & Laslett, 1993) in the spirit of IsoplotR
|
|
7
|
+
`peakfit` (Vermeesch, 2018), served as a FastAPI service with a minimal
|
|
8
|
+
dependency-free web UI.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
*Figure: mixture fit for the bundled Trayler et al. 2020 demo dataset.*
|
|
13
|
+
|
|
14
|
+
## Prerequisite software
|
|
15
|
+
|
|
16
|
+
This project is written in [python](https://www.python.org). For most users, I recommend installing the [miniforge](https://github.com/conda-forge/miniforge) python distribution. This distributions includes a minimal installation of python and the package manager [conda](https://docs.conda.io/en/latest/), which is required to build the necessary python environment for this software.
|
|
17
|
+
|
|
18
|
+
For macOS users, miniforge can be installed with [homebrew](https://brew.sh):
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
brew install miniforge
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For Window's users, miniforge can be installed from a binary .exe. Follow the instructions for miniconda, anaconda, or miniforge (recommended) [here](https://docs.conda.io/projects/conda/en/stable/user-guide/install/windows.html).
|
|
25
|
+
|
|
26
|
+
## Installation Guide
|
|
27
|
+
|
|
28
|
+
To install with Conda (recommended):
|
|
29
|
+
|
|
30
|
+
``` bash
|
|
31
|
+
# Create conda environment
|
|
32
|
+
conda create -n pkft python=3.13 pip
|
|
33
|
+
|
|
34
|
+
# Activate conda environment
|
|
35
|
+
conda activate pkft
|
|
36
|
+
|
|
37
|
+
# Install pkft
|
|
38
|
+
pip install pkft
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If you want to install the development version for local testing in "editable" mode:
|
|
42
|
+
|
|
43
|
+
``` bash
|
|
44
|
+
# Clone repo
|
|
45
|
+
git clone https://github.com/buchanankerswell/pkft.git
|
|
46
|
+
cd pkft
|
|
47
|
+
|
|
48
|
+
# Checkout develop branch
|
|
49
|
+
git checkout develop
|
|
50
|
+
|
|
51
|
+
# Create conda environment and install pkft locally in editable mode
|
|
52
|
+
# including optional development and documentation dependencies
|
|
53
|
+
make environment
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage Guide
|
|
57
|
+
|
|
58
|
+
After installing pkft using either method above, launch the server from the command line:
|
|
59
|
+
|
|
60
|
+
``` bash
|
|
61
|
+
# Activate conda environment
|
|
62
|
+
conda activate pkft
|
|
63
|
+
|
|
64
|
+
# Launch server (UI at http://127.0.0.1:8000/)
|
|
65
|
+
pkft
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The same JSON serves browsers and agents:
|
|
69
|
+
|
|
70
|
+
``` bash
|
|
71
|
+
curl -X POST http://127.0.0.1:8000/fit \
|
|
72
|
+
-H 'Content-Type: application/json' \
|
|
73
|
+
-d '{"observations": [{"value": 17.634, "standard_error": 0.016}], "peak_count": 1}'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Open http://127.0.0.1:8000/ for the data explorer, http://127.0.0.1:8000/mixture for the mixture tab, or click **Load demo** for the bundled Trayler et al. 2020 dataset.
|
|
77
|
+
|
|
78
|
+
## Method
|
|
79
|
+
|
|
80
|
+
Each observation `x[i]` with analytical variance `s[i]**2` contributes
|
|
81
|
+
`sum_j pi[j] * N(x[i] | mu[j], s[i]**2)` to the likelihood (Galbraith &
|
|
82
|
+
Laslett, 1993, discrete mixture; IsoplotR `peakfit` with `log=FALSE`).
|
|
83
|
+
Expectation–maximisation (10 restarts) maximises the log-likelihood;
|
|
84
|
+
`peak_count = 0` selects 1..5 components by BIC. Results maximise
|
|
85
|
+
the same likelihood as IsoplotR `peakfit` with `log=FALSE`, with small
|
|
86
|
+
numerical differences from the different optimiser and starting points.
|
|
87
|
+
See the docs for the full API reference.
|
|
88
|
+
|
|
89
|
+
## Citation
|
|
90
|
+
|
|
91
|
+
Cite the app as Kerswell, B. (2023). Peakfit Explorer.
|
|
92
|
+
https://doi.org/10.17605/OSF.IO/2BU3C
|
|
93
|
+
|
|
94
|
+
## Acknowledgement
|
|
95
|
+
|
|
96
|
+
I gratefully acknowledge feedback and suggestions provided by
|
|
97
|
+
[Matthew Kohn](https://scholar.google.com/citations?user=xSyB1KQAAAAJ&hl=en&oi=ao)
|
|
98
|
+
and [Kayleigh Harvey](https://www.linkedin.com/in/kayleigh-harvey-phd-98471952).
|
|
99
|
+
Peak modelling follows [IsoplotR](https://github.com/pvermees/IsoplotR/)
|
|
100
|
+
(Vermeesch, 2018); demo data from Trayler et al. (2020).
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT License — see [LICENSE](LICENSE).
|
|
Binary file
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Top-level dirs
|
|
2
|
+
PROJECT_ROOT := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))/..)
|
|
3
|
+
DOCS := $(PROJECT_ROOT)/docs
|
|
4
|
+
|
|
5
|
+
# Python config
|
|
6
|
+
SPHINX_BUILD := sphinx-build
|
|
7
|
+
|
|
8
|
+
# Sphinx build
|
|
9
|
+
SPHINX_OPTS ?=
|
|
10
|
+
SOURCE_DIR := $(DOCS)
|
|
11
|
+
BUILD_DIR := $(DOCS)/_build
|
|
12
|
+
|
|
13
|
+
# Cleanup directory
|
|
14
|
+
CLEAN := $(BUILD_DIR)/*
|
|
15
|
+
|
|
16
|
+
# Targets
|
|
17
|
+
.PHONY: help Makefile
|
|
18
|
+
|
|
19
|
+
help:
|
|
20
|
+
@$(SPHINX_BUILD) -M help "$(SOURCE_DIR)" "$(BUILD_DIR)" $(SPHINX_OPTS) $(O)
|
|
21
|
+
|
|
22
|
+
%: Makefile
|
|
23
|
+
@$(SPHINX_BUILD) -M $@ "$(SOURCE_DIR)" "$(BUILD_DIR)" $(SPHINX_OPTS) $(O)
|
|
24
|
+
|
|
25
|
+
clean:
|
|
26
|
+
@for item in $(CLEAN); do \
|
|
27
|
+
safe_rm() { \
|
|
28
|
+
if [ -e "$$1" ]; then \
|
|
29
|
+
ABS_PATH=$$(realpath "$$1"); \
|
|
30
|
+
case "$$ABS_PATH" in \
|
|
31
|
+
$(PROJECT_ROOT)*) \
|
|
32
|
+
echo "-> Safely removing\n $$ABS_PATH"; \
|
|
33
|
+
rm -rf "$$ABS_PATH";; \
|
|
34
|
+
*) \
|
|
35
|
+
echo "!! Skipping (outside project root)\n $$ABS_PATH";; \
|
|
36
|
+
esac; \
|
|
37
|
+
else \
|
|
38
|
+
echo "-- Skipping (not found)\n $$1"; \
|
|
39
|
+
fi; \
|
|
40
|
+
}; \
|
|
41
|
+
safe_rm "$$item"; \
|
|
42
|
+
done
|