riptide-ffa 0.2.4__tar.gz → 0.2.6__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.
Files changed (92) hide show
  1. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/.coveragerc +1 -4
  2. riptide_ffa-0.2.6/.github/workflows/CI.yml +32 -0
  3. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/.gitignore +15 -9
  4. riptide_ffa-0.2.6/.readthedocs.yaml +15 -0
  5. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/CHANGELOG.md +24 -0
  6. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/Makefile +4 -7
  7. riptide_ffa-0.2.6/PKG-INFO +120 -0
  8. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/README.md +3 -3
  9. riptide_ffa-0.2.6/pyproject.toml +60 -0
  10. riptide_ffa-0.2.6/riptide/cpp/transforms_advanced_LEGACY.hpp +248 -0
  11. riptide_ffa-0.2.6/setup.cfg +4 -0
  12. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/setup.py +19 -3
  13. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/__init__.py +17 -27
  14. riptide_ffa-0.2.6/src/riptide/_version.py +24 -0
  15. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/apps/rseek.py +72 -60
  16. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/candidate.py +76 -53
  17. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/clustering.py +5 -8
  18. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/downsample.hpp +7 -3
  19. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/python_bindings.cpp +23 -11
  20. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/ffautils.py +1 -0
  21. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/folding.py +10 -6
  22. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/libffa.py +17 -17
  23. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/metadata.py +35 -29
  24. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/peak_detection.py +50 -32
  25. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/periodogram.py +27 -20
  26. riptide_ffa-0.2.6/src/riptide/pipeline/config_validation.py +259 -0
  27. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/dmiter.py +78 -42
  28. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/harmonic_testing.py +37 -26
  29. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/peak_cluster.py +27 -17
  30. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/pipeline.py +127 -100
  31. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/worker_pool.py +14 -17
  32. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/reading/presto.py +49 -46
  33. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/reading/sigproc.py +38 -33
  34. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/running_medians.py +4 -2
  35. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/search.py +23 -12
  36. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/serialization.py +40 -39
  37. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/time_series.py +70 -54
  38. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/timing.py +3 -2
  39. riptide_ffa-0.2.6/src/riptide_ffa.egg-info/PKG-INFO +120 -0
  40. riptide_ffa-0.2.6/src/riptide_ffa.egg-info/SOURCES.txt +78 -0
  41. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide_ffa.egg-info/entry_points.txt +0 -1
  42. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide_ffa.egg-info/requires.txt +1 -1
  43. riptide_ffa-0.2.6/src/riptide_ffa.egg-info/scm_file_list.json +88 -0
  44. riptide_ffa-0.2.6/src/riptide_ffa.egg-info/scm_version.json +8 -0
  45. riptide_ffa-0.2.6/tests/__init__.py +0 -0
  46. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/presto_generation.py +17 -6
  47. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_ffa_base_functions.py +43 -43
  48. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_ffa_search_pgram.py +25 -22
  49. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_pipeline.py +51 -38
  50. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_rseek.py +27 -14
  51. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_running_median.py +11 -11
  52. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_snr.py +9 -9
  53. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/test_time_series.py +37 -29
  54. riptide-ffa-0.2.4/.readthedocs.yaml +0 -21
  55. riptide-ffa-0.2.4/.travis.yml +0 -30
  56. riptide-ffa-0.2.4/PKG-INFO +0 -287
  57. riptide-ffa-0.2.4/pyproject.toml +0 -11
  58. riptide-ffa-0.2.4/riptide/_version.py +0 -5
  59. riptide-ffa-0.2.4/riptide/pipeline/config_validation.py +0 -198
  60. riptide-ffa-0.2.4/riptide/tests/__init__.py +0 -1
  61. riptide-ffa-0.2.4/riptide/tests/run_tests.py +0 -11
  62. riptide-ffa-0.2.4/riptide_ffa.egg-info/PKG-INFO +0 -287
  63. riptide-ffa-0.2.4/riptide_ffa.egg-info/SOURCES.txt +0 -78
  64. riptide-ffa-0.2.4/riptide_ffa.egg-info/not-zip-safe +0 -1
  65. riptide-ffa-0.2.4/setup.cfg +0 -51
  66. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/LICENSE +0 -0
  67. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6}/MANIFEST.in +0 -0
  68. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/README.md +0 -0
  69. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/block.hpp +0 -0
  70. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/kernels.hpp +0 -0
  71. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/periodogram.hpp +0 -0
  72. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/running_median.hpp +0 -0
  73. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/snr.hpp +0 -0
  74. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/cpp/transforms.hpp +0 -0
  75. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/__init__.py +0 -0
  76. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/pipeline/config/example.yaml +0 -0
  77. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide/reading/__init__.py +0 -0
  78. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide_ffa.egg-info/dependency_links.txt +0 -0
  79. {riptide-ffa-0.2.4 → riptide_ffa-0.2.6/src}/riptide_ffa.egg-info/top_level.txt +0 -0
  80. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/README.md +0 -0
  81. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_presto_radio.dat +0 -0
  82. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_presto_radio.inf +0 -0
  83. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_presto_radio_breaks.dat +0 -0
  84. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_presto_radio_breaks.inf +0 -0
  85. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_presto_xray.dat +0 -0
  86. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_presto_xray.inf +0 -0
  87. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_sigproc_float32.tim +0 -0
  88. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_sigproc_int8.tim +0 -0
  89. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_sigproc_uint8.tim +0 -0
  90. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/data/fake_sigproc_uint8_nosignedkey.tim +0 -0
  91. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/pipeline_config_A.yml +0 -0
  92. {riptide-ffa-0.2.4/riptide → riptide_ffa-0.2.6}/tests/pipeline_config_B.yml +0 -0
@@ -2,11 +2,8 @@
2
2
  branch = True
3
3
  parallel = True
4
4
  concurrency = multiprocessing
5
- include =
6
- riptide/*
7
5
  omit =
8
- riptide/tests/*
9
- riptide/_version.py
6
+ src/riptide/_version.py
10
7
 
11
8
  [report]
12
9
  exclude_lines =
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ - push
5
+ - pull_request
6
+
7
+ jobs:
8
+ # See: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#example-running-a-job-within-a-container
9
+ continuous-integration:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
14
+
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v4
18
+ - name: Set up Python ${{ matrix.python-version }}
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ - name: Install
23
+ run: |
24
+ python -m pip install --upgrade pip
25
+ make install
26
+ - name: Test
27
+ run: |
28
+ make tests
29
+ - name: Upload coverage reports to Codecov
30
+ uses: codecov/codecov-action@v5
31
+ env:
32
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -1,13 +1,19 @@
1
- *.o
2
- *.so
3
- *.pyc
4
- __pycache__
1
+ dist
2
+ build
3
+ .egg
4
+ .nox
5
5
  .vscode
6
- *.egg-info
7
6
  .coverage
8
- .eggs
7
+ __pycache__
8
+ .mypy_cache
9
+ docs/_build
9
10
  .pytest_cache
10
- tmp
11
- build
12
- dist
13
11
  pip-wheel-metadata
12
+ .ipynb_checkpoints
13
+ src/riptide/_version.py
14
+
15
+ *.o
16
+ *.so
17
+ *.egg
18
+ *.py[cod]
19
+ *.egg-info
@@ -0,0 +1,15 @@
1
+ # Read the Docs configuration file for Sphinx projects
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+ version: 2
4
+
5
+ build:
6
+ os: ubuntu-22.04
7
+ tools:
8
+ python: "3.12"
9
+
10
+ python:
11
+ install:
12
+ - requirements: docs/requirements.txt
13
+
14
+ sphinx:
15
+ configuration: docs/source/conf.py
@@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 0.2.6 - 2026-09-10
8
+
9
+ This version modernises the project layout and packaging, and fixes issues in candidate plotting and downsampled variance calculations.
10
+
11
+ ### Fixed
12
+
13
+ - Candidate plots now normalise each sub-integration independently for better contrast,
14
+ contributed by Dejiang Yin.
15
+ - Corrected the downsampled variance calculation for factors very close to an integer,
16
+ thanks to Francesco Coti Zelati for reporting the issue.
17
+
18
+
19
+ ## 0.2.5 - 2023-12-23
20
+
21
+ This version fixes an installation error on recent OSX versions, and a segmentation fault that triggers in some edge cases.
22
+
23
+ Thanks to Francesco Coti Zelati for [reporting the original issue](https://github.com/v-morello/riptide/issues/4) that led to both fixes.
24
+
25
+ ### Fixed
26
+
27
+ - Fixed a serious bug where some intermediate output arrays were unexpectedly allocated with a size one element smaller than expected, causing segmentation faults. This was found to be a side effect of the compilation flag `-freciprocal-math`. See issue [#4](https://github.com/v-morello/riptide/issues/4) for a detailed explanation. The set of compilation flags for the C++ extensions has been reviewed and adjusted.
28
+ - The C++ extensions can now be built with the C++17 standard enabled without throwing any errors or warnings. Recent `clang` versions (the default compiler on OSX) would throw a number of narrowing conversion errors, which would in turn make the installation of riptide fail with a cryptic error message.
29
+
30
+
7
31
  ## 0.2.4 - 2022-02-03
8
32
 
9
33
  This version fixes a bug where all the functions in the python bindings to the C++ code (exposed in `riptide.libcpp` on the Python side) assume that their input numpy arrays are contiguous in memory. In practice, passing a column slice of a two-dimensional `float32` array to `fast_running_median` was found to produce incorrect results: the rather than reading `data[:, col_index]`, the code read `data[0, col_index:col_index+num_cols]`. The issue would only trigger on the `float32` type, because otherwise an implicit copy (contiguous in memory) of the input was created.
@@ -4,13 +4,10 @@ PKG = riptide-ffa
4
4
  dist: ## Build source distribution, must have installed 'develop' extra dependencies
5
5
  python -m build --sdist
6
6
 
7
- docker: ## Build riptide-ffa docker image
8
- docker build --file docker/Dockerfile --tag ${PKG} .
9
-
10
7
  # NOTE: -e installs in "Development Mode"
11
8
  # See: https://packaging.python.org/tutorials/installing-packages/
12
- install: ## Install the package in development mode
13
- pip install -e .
9
+ install: ## Install the package in editable mode with dev dependencies
10
+ pip install -e .[dev]
14
11
 
15
12
  # NOTE: remove the .egg-info directory
16
13
  uninstall: ## Uninstall the package
@@ -35,6 +32,6 @@ clean: ## Remove all python cache and build files
35
32
  rm -f .coverage
36
33
 
37
34
  tests: ## Run the unit tests and print a coverage report
38
- pytest --cov --verbose --cov-report term-missing riptide/tests
35
+ pytest --cov --verbose --cov-report term-missing tests
39
36
 
40
- .PHONY: dist docker install uninstall help clean upload upload_test tests
37
+ .PHONY: dist install uninstall help clean tests
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: riptide-ffa
3
+ Version: 0.2.6
4
+ Summary: Pulsar searching with the Fast Folding Algorithm (FFA)
5
+ Author-email: Vincent Morello <vmorello@gmail.com>
6
+ Maintainer-email: Vincent Morello <vmorello@gmail.com>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2017-2021 Vincent Morello
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: homepage, https://github.com/vmorello/riptide
30
+ Project-URL: documentation, https://riptide-ffa.readthedocs.io
31
+ Classifier: Programming Language :: Python :: 3 :: Only
32
+ Classifier: Programming Language :: Python :: 3.9
33
+ Classifier: Programming Language :: Python :: 3.10
34
+ Classifier: Programming Language :: Python :: 3.11
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Programming Language :: C
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Operating System :: Unix
39
+ Classifier: Operating System :: MacOS :: MacOS X
40
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
41
+ Requires-Python: >=3.9
42
+ Description-Content-Type: text/markdown
43
+ License-File: LICENSE
44
+ Requires-Dist: astropy
45
+ Requires-Dist: pandas
46
+ Requires-Dist: schema
47
+ Requires-Dist: pyyaml
48
+ Requires-Dist: threadpoolctl
49
+ Requires-Dist: pytest
50
+ Requires-Dist: pytest-cov
51
+ Requires-Dist: matplotlib
52
+ Requires-Dist: numpy
53
+ Provides-Extra: dev
54
+ Requires-Dist: build; extra == "dev"
55
+ Requires-Dist: twine; extra == "dev"
56
+ Dynamic: license-file
57
+
58
+ [![arXiv](http://img.shields.io/badge/astro.ph-2004.03701-B31B1B.svg)](https://arxiv.org/abs/2004.03701) ![License](https://img.shields.io/badge/License-MIT-green.svg) ![Python versions](https://img.shields.io/pypi/pyversions/riptide-ffa.svg) ![CI status](https://github.com/v-morello/riptide/actions/workflows/CI.yml/badge.svg?branch=master) [![codecov](https://codecov.io/gh/v-morello/riptide/branch/master/graph/badge.svg)](https://codecov.io/gh/v-morello/riptide)
59
+
60
+ # riptide
61
+
62
+ __riptide__ ("sea**r**ch**i**ng for **p**ulsars in the **ti**me **d**omain") is a pulsar searching package implementing the Fast Folding Algorithm (FFA), the theoretically optimal search method for periodic signals. Its interface is entirely in python while the core algorithms are implemented in C. riptide provides:
63
+
64
+ * A library of functions and classes to use interactively to process dedispersed time series
65
+ * A pipeline executable to process a set of DM trials and output a list of candidate files and other useful data products
66
+
67
+ ## Citation
68
+
69
+ If using ``riptide`` contributes to a project that leads to a scientific publication, please cite the article:
70
+ ["Optimal periodicity searching: Revisiting the Fast Folding Algorithm for large scale pulsar surveys"](https://arxiv.org/abs/2004.03701)
71
+
72
+
73
+ ## Sensitivity of the FFA
74
+
75
+ The article covers the topic of the FFA's sensitivity in theory, here is a practical example on a faint source. Below is an L-band observation of [PSR J1932-3655](https://www.atnf.csiro.au/people/joh414/ppdata/1932-3655.html) from the [SUPERB survey](https://arxiv.org/abs/1706.04459), significantly offset from the true position of the source. The first plot was obtained by folding the observation using the known ephemeris of the pulsar with [PSRCHIVE](http://psrchive.sourceforge.net/). This is one of the faintest known pulsar instances identifiable in the survey.
76
+
77
+ ![psrchive_plot](docs/source/images/J1932-3655_psrchive_small.png "PSRCHIVE direct ephemeris folding")
78
+
79
+ And below is a blind detection of the pulsar, running `riptide` on the same observation:
80
+ ![riptide_plot](docs/source/images/J1932-3655_blind_detection.png "riptide blind detection")
81
+
82
+
83
+ ## Documentation
84
+
85
+ A quickstart guide, a pipeline configuration tutorial and the full API documentation can be found [here](https://riptide-ffa.readthedocs.io).
86
+
87
+ ## Installation
88
+
89
+ The easiest method is to use pip install, which pulls the latest release from the python package index and installs all required dependencies:
90
+ ```
91
+ pip install riptide-ffa
92
+ ```
93
+
94
+ The alternative is to clone the repository, especially if you want the absolute latest version:
95
+ ```bash
96
+ git clone https://github.com/v-morello/riptide
97
+ ```
98
+
99
+ And then in the base directory of `riptide` run
100
+
101
+ ```bash
102
+ make install
103
+ ```
104
+
105
+ This simply runs ``pip install`` in [editable mode](https://pip.pypa.io/en/latest/reference/pip_install/#editable-installs), which means you can freely edit the code. It also installs any required dependencies with ``pip`` that are not present already. The installer also adds links to two command-line apps in your python environment using [console_scripts entry points](https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html):
106
+
107
+ * `rffa`: The full end-to-end pipeline to search multiple DM trials, see below for details on how to use it.
108
+ * `rseek`: A lightweight app to search a single time series and print significant candidates found, useful for quick data checks.
109
+
110
+ You may check that it all works by typing:
111
+ ```
112
+ rffa -h
113
+ rseek -h
114
+ ```
115
+ And you should see the full help of both applications.
116
+
117
+
118
+
119
+
120
+
@@ -1,4 +1,4 @@
1
- [![arXiv](http://img.shields.io/badge/astro.ph-2004.03701-B31B1B.svg)](https://arxiv.org/abs/2004.03701) ![License](https://img.shields.io/badge/License-MIT-green.svg) ![Python versions](https://img.shields.io/pypi/pyversions/riptide-ffa.svg) [![Build Status](https://travis-ci.com/v-morello/riptide.svg?branch=master)](https://travis-ci.com/v-morello/riptide) [![codecov](https://codecov.io/gh/v-morello/riptide/branch/master/graph/badge.svg)](https://codecov.io/gh/v-morello/riptide)
1
+ [![arXiv](http://img.shields.io/badge/astro.ph-2004.03701-B31B1B.svg)](https://arxiv.org/abs/2004.03701) ![License](https://img.shields.io/badge/License-MIT-green.svg) ![Python versions](https://img.shields.io/pypi/pyversions/riptide-ffa.svg) ![CI status](https://github.com/v-morello/riptide/actions/workflows/CI.yml/badge.svg?branch=master) [![codecov](https://codecov.io/gh/v-morello/riptide/branch/master/graph/badge.svg)](https://codecov.io/gh/v-morello/riptide)
2
2
 
3
3
  # riptide
4
4
 
@@ -17,10 +17,10 @@ If using ``riptide`` contributes to a project that leads to a scientific publica
17
17
 
18
18
  The article covers the topic of the FFA's sensitivity in theory, here is a practical example on a faint source. Below is an L-band observation of [PSR J1932-3655](https://www.atnf.csiro.au/people/joh414/ppdata/1932-3655.html) from the [SUPERB survey](https://arxiv.org/abs/1706.04459), significantly offset from the true position of the source. The first plot was obtained by folding the observation using the known ephemeris of the pulsar with [PSRCHIVE](http://psrchive.sourceforge.net/). This is one of the faintest known pulsar instances identifiable in the survey.
19
19
 
20
- ![psrchive_plot](images/J1932-3655_psrchive_small.png "PSRCHIVE direct ephemeris folding")
20
+ ![psrchive_plot](docs/source/images/J1932-3655_psrchive_small.png "PSRCHIVE direct ephemeris folding")
21
21
 
22
22
  And below is a blind detection of the pulsar, running `riptide` on the same observation:
23
- ![riptide_plot](images/J1932-3655_blind_detection.png "riptide blind detection")
23
+ ![riptide_plot](docs/source/images/J1932-3655_blind_detection.png "riptide blind detection")
24
24
 
25
25
 
26
26
  ## Documentation
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = [
4
+ "setuptools>=42",
5
+ "wheel",
6
+ "setuptools_scm[toml]>=3.4",
7
+ "pybind11>=2.6.0",
8
+ ]
9
+
10
+ [project]
11
+ name = "riptide-ffa"
12
+ authors = [{name = "Vincent Morello", email = "vmorello@gmail.com"}]
13
+ description = "Pulsar searching with the Fast Folding Algorithm (FFA)"
14
+ dynamic = ["version"]
15
+ license = {file = "LICENSE"}
16
+ maintainers = [{name = "Vincent Morello", email = "vmorello@gmail.com"}]
17
+ readme = "README.md"
18
+ requires-python = ">=3.9"
19
+
20
+ classifiers = [
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: C",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Operating System :: Unix",
29
+ "Operating System :: MacOS :: MacOS X",
30
+ "Topic :: Scientific/Engineering :: Astronomy",
31
+ ]
32
+
33
+ dependencies = [
34
+ "astropy",
35
+ "pandas",
36
+ "schema",
37
+ "pyyaml",
38
+ "threadpoolctl",
39
+ "pytest",
40
+ "pytest-cov",
41
+ "matplotlib",
42
+ "numpy",
43
+ ]
44
+
45
+ [project.optional-dependencies]
46
+ dev = [
47
+ "build",
48
+ "twine",
49
+ ]
50
+
51
+ [project.scripts]
52
+ rffa = "riptide.pipeline.pipeline:main"
53
+ rseek = "riptide.apps.rseek:main"
54
+
55
+ [project.urls]
56
+ homepage = "https://github.com/vmorello/riptide"
57
+ documentation = "https://riptide-ffa.readthedocs.io"
58
+
59
+ [tool.setuptools_scm]
60
+ write_to = "src/riptide/_version.py"
@@ -0,0 +1,248 @@
1
+ #ifndef TRANSFORMS_ADVANCED_HPP
2
+ #define TRANSFORMS_ADVANCED_HPP
3
+
4
+ #include <cstddef> // size_t
5
+
6
+ #include "transforms_blocked.hpp"
7
+
8
+ namespace riptide::advanced
9
+ {
10
+ using riptide::direct::merge_radix2;
11
+ using riptide::blocked::integer_log2;
12
+
13
+ constexpr size_t SMALL_INPUT_MAX_SIZE = 1UL << 18;
14
+
15
+ size_t head_size(const size_t rows)
16
+ {
17
+ return rows / 2;
18
+ }
19
+
20
+ size_t tail_size(const size_t rows)
21
+ {
22
+ return rows - head_size(rows);
23
+ }
24
+
25
+ /// @brief Represents a 2D vertical slice of a TransformCube.
26
+ /// @tparam DataType Numerical type of the data being wrapped.
27
+ template <typename DataType>
28
+ class VerticalSlice
29
+ {
30
+ public:
31
+ // Pointer to the start of the first row of the slice
32
+ DataType *data;
33
+
34
+ // number of planes within the original TransformCube spanned by this vertical slice
35
+ const size_t planes;
36
+
37
+ // number of bins across the pulse profiles (last dimension)
38
+ const size_t cols;
39
+
40
+ // offset between consecutive planes in number of data points
41
+ const size_t stride;
42
+
43
+ // the row index along which this slice was taken within the original TransformCube
44
+ const size_t row_index;
45
+
46
+ // The plane index within the original TransformCube where this slice starts.
47
+ const size_t plane_index;
48
+
49
+ public:
50
+ /// @brief Create a new VerticalSlice from a raw data pointer
51
+ /// Note that plane_index = 0 by default. Non-zero plane indices are
52
+ /// only used during the recursion of small FFA transforms.
53
+ VerticalSlice(DataType *data, size_t planes, size_t cols, size_t stride, size_t row_index, size_t plane_index = 0)
54
+ : data(data), planes(planes), cols(cols), stride(stride), row_index(row_index), plane_index(plane_index)
55
+ {
56
+ }
57
+
58
+ VerticalSlice<DataType> head() const
59
+ {
60
+ return VerticalSlice<DataType>(
61
+ data, head_size(planes), cols, stride, row_index, plane_index);
62
+ }
63
+
64
+ VerticalSlice<DataType> tail() const
65
+ {
66
+ const size_t h = head_size(planes);
67
+ const size_t t = tail_size(planes);
68
+ return VerticalSlice<DataType>(
69
+ data + h * stride, t, cols, stride, row_index, plane_index + h);
70
+ }
71
+
72
+ }; // class VerticalPlane
73
+
74
+ /// @brief Represents a 2D horizontal plane of a TransformCube
75
+ /// @tparam DataType
76
+ template <typename DataType>
77
+ class Plane
78
+ {
79
+ public:
80
+ DataType *data;
81
+ const size_t rows;
82
+ const size_t cols;
83
+
84
+ public:
85
+ Plane(DataType *data, size_t rows, size_t cols)
86
+ : data(data), rows(rows), cols(cols)
87
+ {
88
+ }
89
+
90
+ Plane<DataType> head() const
91
+ {
92
+ return Plane<DataType>(data, head_size(rows), cols);
93
+ }
94
+
95
+ Plane<DataType> tail() const
96
+ {
97
+ return Plane<DataType>(data + head_size(rows) * cols, tail_size(rows), cols);
98
+ }
99
+
100
+ }; // class Plane
101
+
102
+ /// @brief Represents data that has been FFA transformed by blocks.
103
+ /// 'planes' is the number of blocks of data that have been FFA transformed independently.
104
+ /// 'rows' is the number of rows inside each transformed block.
105
+ /// 'cols' is the number of columns = number bins across a pulse profile.
106
+ /// Special cases:
107
+ /// planes = N, rows = 1 is raw data, pre-transform.
108
+ /// planes = 1, rows = N is fully FFA-transformed data.
109
+ /// @tparam DataType Numerical type of the data being wrapped.
110
+ template <typename DataType>
111
+ class TransformCube
112
+ {
113
+ public:
114
+ DataType *data;
115
+ const size_t planes;
116
+ const size_t rows;
117
+ const size_t cols;
118
+ const size_t plane_stride;
119
+
120
+ public:
121
+ TransformCube(DataType *data, size_t planes, size_t rows, size_t cols)
122
+ : data(data), planes(planes), rows(rows), cols(cols), plane_stride(rows * cols)
123
+ {
124
+ }
125
+
126
+ /// @brief Return a view of one of the planes
127
+ Plane<DataType> getPlane(size_t index) const
128
+ {
129
+ return Plane<DataType>(data + index * plane_stride, rows, cols);
130
+ }
131
+
132
+ /// @brief Return a view of a group of rows within a given plane
133
+ Plane<DataType> getSubPlane(size_t plane_index, size_t start_row_index, size_t num_rows) const
134
+ {
135
+ const size_t offset = plane_index * plane_stride + start_row_index * cols;
136
+ return Plane<DataType>(data + offset, num_rows, cols);
137
+ }
138
+
139
+ /// @brief Return a VerticalSlice spanning all the planes, along given row index
140
+ VerticalSlice<DataType> getVerticalSlice(size_t row_index) const
141
+ {
142
+ return VerticalSlice<DataType>(
143
+ data + row_index * cols, planes, cols, plane_stride, row_index);
144
+ }
145
+
146
+ /// @brief Return a view of a group of consecutive planes
147
+ TransformCube<DataType> getSubCube(size_t start_plane_index, size_t num_planes) const
148
+ {
149
+ const size_t offset = start_plane_index * plane_stride;
150
+ return TransformCube<DataType>(data + offset, num_planes, rows, cols);
151
+ }
152
+ }; // class TransformCube
153
+
154
+ template <typename DataType>
155
+ void transform_vertical_slice(
156
+ VerticalSlice<DataType> vslice,
157
+ DataType *__restrict__ swap,
158
+ DataType *__restrict__ out)
159
+ {
160
+ if (vslice.planes == 1)
161
+ {
162
+ const size_t shift = vslice.plane_index * vslice.row_index;
163
+ rollback(vslice.data, vslice.cols, shift, out);
164
+ return;
165
+ }
166
+
167
+ // NOTE: Use output as swap space, and swap space as intermediate
168
+ // storage
169
+ const size_t offset = head_size(vslice.planes) * vslice.cols;
170
+ transform_vertical_slice(vslice.head(), out, swap);
171
+ transform_vertical_slice(vslice.tail(), out + offset, swap + offset);
172
+ merge_radix2(swap, swap + offset, vslice.planes / 2, vslice.cols, out);
173
+ }
174
+
175
+ /// @brief The maximum number of rows that should be transformed
176
+ /// within a small FFA transform. It is chosen such that the small FFA
177
+ /// input size does not exceed SMALL_INPUT_MAX_SIZE.
178
+ /// Returns a power of two that is >= 2.
179
+ template <typename DataType>
180
+ size_t small_transform_num_rows(const size_t cols)
181
+ {
182
+ const size_t max_size_elements = SMALL_INPUT_MAX_SIZE / sizeof(DataType);
183
+ const size_t max_rows = 1UL << integer_log2(max_size_elements / cols);
184
+ return std::max(max_rows, 2UL);
185
+ }
186
+
187
+ template <typename DataType>
188
+ TransformCube<DataType> transform_until(
189
+ TransformCube<DataType> incube, // 8 planes, 32 rows/plane
190
+ const size_t target_num_planes, // 2
191
+ DataType *__restrict__ swap,
192
+ DataType *__restrict__ temp,
193
+ DataType *__restrict__ out) // 2 planes, 256 rows/plane
194
+ {
195
+ if (incube.planes <= target_num_planes)
196
+ {
197
+ return incube;
198
+ }
199
+ const size_t merge_factor = std::min(
200
+ small_transform_num_rows<DataType>(incube.cols),
201
+ incube.planes / target_num_planes); // 4
202
+
203
+ // First obtain a cube whose number of planes is 'merge_factor' times
204
+ // larger than the target
205
+ // NOTE: use 'out' as the intermediate storage for the recursion level below
206
+ TransformCube<DataType> midcube = transform_until(incube, target_num_planes * merge_factor, swap, out, temp);
207
+
208
+ // Prepare output cube view with adequate dimensions
209
+ TransformCube<DataType> outcube = TransformCube(out, target_num_planes, midcube.rows * merge_factor, midcube.cols);
210
+
211
+ // Group planes of 'midcube' by groups of 'merge_factor' planes
212
+ // In other words, split 'midcube' into 'merge_factor' sub-cubes
213
+ // Each sub-cube can be directly transformed into an output plane
214
+ for (size_t i = 0; i < target_num_planes; ++i)
215
+ {
216
+ TransformCube<DataType> sub_midcube = midcube.getSubCube(i * merge_factor, merge_factor);
217
+
218
+ for (size_t j = 0; j < sub_midcube.rows; ++j)
219
+ {
220
+ transform_vertical_slice(
221
+ sub_midcube.getVerticalSlice(j),
222
+ swap,
223
+ outcube.getSubPlane(i, j * merge_factor, merge_factor).data);
224
+ }
225
+ }
226
+ return outcube;
227
+ }
228
+
229
+ template <typename DataType>
230
+ void transform(
231
+ DataType *__restrict__ data,
232
+ const size_t total_rows,
233
+ const size_t cols,
234
+ DataType *__restrict__ swap,
235
+ DataType *__restrict__ temp,
236
+ DataType *__restrict__ out)
237
+ {
238
+ transform_until(
239
+ TransformCube<DataType>(data, total_rows, 1, cols),
240
+ 1,
241
+ swap,
242
+ temp,
243
+ out);
244
+ }
245
+
246
+ } // namespace riptide
247
+
248
+ #endif // TRANSFORMS_ADVANCED_HPP
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -3,6 +3,22 @@ from setuptools import setup
3
3
  # Available at setup time due to pyproject.toml
4
4
  from pybind11.setup_helpers import Pybind11Extension, build_ext
5
5
 
6
+ # WARNING: Enabling -freciprocal-math (which is also enabled by
7
+ # -funsafe-math-optimizations or -ffast-math) causes surprising inconsistencies
8
+ # when calculating the size of the output periodogram, and the size of the
9
+ # buffers to store data downsampled by a real-valued factor.
10
+ # In turn, this can cause segmentation faults (code attempts to write past the
11
+ # end of these arrays).
12
+ # The flags below provide the same speedups as -ffast-math, without the risks.
13
+ SAFE_FAST_MATH_FLAGS = [
14
+ "-fassociative-math",
15
+ "-fno-math-errno",
16
+ "-ffinite-math-only",
17
+ "-fno-rounding-math",
18
+ "-fno-signed-zeros",
19
+ "-fno-trapping-math",
20
+ ]
21
+
6
22
  # The main interface is through Pybind11Extension.
7
23
  # * You can add cxx_std=11/14/17, and then build_ext can be removed.
8
24
  # * You can set include_pybind11=false to add the include directory yourself,
@@ -13,9 +29,9 @@ from pybind11.setup_helpers import Pybind11Extension, build_ext
13
29
  # reproducible builds (https://github.com/pybind/python_example/pull/53)
14
30
  ext_modules = [
15
31
  Pybind11Extension(
16
- 'riptide.libcpp',
17
- sorted(['riptide/cpp/python_bindings.cpp']),
18
- extra_compile_args=['-O3', '-ffast-math', '-march=native']
32
+ "riptide.libcpp",
33
+ sorted(["src/riptide/cpp/python_bindings.cpp"]),
34
+ extra_compile_args=["-O3", "-march=native"] + SAFE_FAST_MATH_FLAGS,
19
35
  ),
20
36
  ]
21
37