otswap 0.1.0__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 (99) hide show
  1. otswap-0.1.0/.github/workflows/ci.yml +166 -0
  2. otswap-0.1.0/.github/workflows/docs.yml +64 -0
  3. otswap-0.1.0/.github/workflows/release.yml +116 -0
  4. otswap-0.1.0/.gitignore +22 -0
  5. otswap-0.1.0/CHANGELOG.md +27 -0
  6. otswap-0.1.0/CITATION.cff +55 -0
  7. otswap-0.1.0/CMakeLists.txt +329 -0
  8. otswap-0.1.0/LICENSE +339 -0
  9. otswap-0.1.0/PKG-INFO +169 -0
  10. otswap-0.1.0/README.md +152 -0
  11. otswap-0.1.0/cmake/FindCFITSIO.cmake +59 -0
  12. otswap-0.1.0/cmake/otswapConfig.cmake.in +32 -0
  13. otswap-0.1.0/extern/fdlibm/README.md +84 -0
  14. otswap-0.1.0/extern/fdlibm/msun/src/e_asin.c +113 -0
  15. otswap-0.1.0/extern/fdlibm/msun/src/e_atan2.c +125 -0
  16. otswap-0.1.0/extern/fdlibm/msun/src/e_exp.c +160 -0
  17. otswap-0.1.0/extern/fdlibm/msun/src/e_pow.c +314 -0
  18. otswap-0.1.0/extern/fdlibm/msun/src/e_rem_pio2.c +176 -0
  19. otswap-0.1.0/extern/fdlibm/msun/src/k_cos.c +75 -0
  20. otswap-0.1.0/extern/fdlibm/msun/src/k_rem_pio2.c +439 -0
  21. otswap-0.1.0/extern/fdlibm/msun/src/k_sin.c +66 -0
  22. otswap-0.1.0/extern/fdlibm/msun/src/math_private.h +945 -0
  23. otswap-0.1.0/extern/fdlibm/msun/src/s_atan.c +120 -0
  24. otswap-0.1.0/extern/fdlibm/msun/src/s_cos.c +85 -0
  25. otswap-0.1.0/extern/fdlibm/msun/src/s_log1p.c +176 -0
  26. otswap-0.1.0/extern/fdlibm/msun/src/s_sin.c +85 -0
  27. otswap-0.1.0/extern/fdlibm/otswap_fdlibm.h +96 -0
  28. otswap-0.1.0/extern/fdlibm/shim/machine/endian.h +20 -0
  29. otswap-0.1.0/extern/healpix/COPYING +339 -0
  30. otswap-0.1.0/extern/healpix/Healpix_cxx/healpix_base.cc +1414 -0
  31. otswap-0.1.0/extern/healpix/Healpix_cxx/healpix_base.h +465 -0
  32. otswap-0.1.0/extern/healpix/Healpix_cxx/healpix_map.h +316 -0
  33. otswap-0.1.0/extern/healpix/Healpix_cxx/healpix_tables.cc +143 -0
  34. otswap-0.1.0/extern/healpix/Healpix_cxx/healpix_tables.h +63 -0
  35. otswap-0.1.0/extern/healpix/README.md +17 -0
  36. otswap-0.1.0/extern/healpix/cxxsupport/alloc_utils.h +94 -0
  37. otswap-0.1.0/extern/healpix/cxxsupport/arr.h +660 -0
  38. otswap-0.1.0/extern/healpix/cxxsupport/datatypes.h +318 -0
  39. otswap-0.1.0/extern/healpix/cxxsupport/error_handling.cc +56 -0
  40. otswap-0.1.0/extern/healpix/cxxsupport/error_handling.h +100 -0
  41. otswap-0.1.0/extern/healpix/cxxsupport/geom_utils.cc +72 -0
  42. otswap-0.1.0/extern/healpix/cxxsupport/geom_utils.h +80 -0
  43. otswap-0.1.0/extern/healpix/cxxsupport/lsconstants.h +93 -0
  44. otswap-0.1.0/extern/healpix/cxxsupport/math_utils.h +299 -0
  45. otswap-0.1.0/extern/healpix/cxxsupport/pointing.cc +68 -0
  46. otswap-0.1.0/extern/healpix/cxxsupport/pointing.h +81 -0
  47. otswap-0.1.0/extern/healpix/cxxsupport/rangeset.h +435 -0
  48. otswap-0.1.0/extern/healpix/cxxsupport/string_utils.cc +336 -0
  49. otswap-0.1.0/extern/healpix/cxxsupport/string_utils.h +123 -0
  50. otswap-0.1.0/extern/healpix/cxxsupport/vec3.h +149 -0
  51. otswap-0.1.0/extern/healpix/cxxsupport/xcomplex.h +44 -0
  52. otswap-0.1.0/include/otswap/OT.h +1004 -0
  53. otswap-0.1.0/include/otswap/RSD.h +401 -0
  54. otswap-0.1.0/include/otswap/io.h +366 -0
  55. otswap-0.1.0/pyproject.toml +65 -0
  56. otswap-0.1.0/python/otswap/__init__.py +113 -0
  57. otswap-0.1.0/python/otswap/__init__.pyi +987 -0
  58. otswap-0.1.0/python/otswap/io.py +24 -0
  59. otswap-0.1.0/python/otswap/io.pyi +275 -0
  60. otswap-0.1.0/python/otswap/py.typed +0 -0
  61. otswap-0.1.0/python/otswap_python.cpp +1379 -0
  62. otswap-0.1.0/src/DistanceTable.cpp +407 -0
  63. otswap-0.1.0/src/Lightcone.cpp +713 -0
  64. otswap-0.1.0/src/Mask.cpp +496 -0
  65. otswap-0.1.0/src/Pixel.cpp +429 -0
  66. otswap-0.1.0/src/RSD.cpp +729 -0
  67. otswap-0.1.0/src/Reconstruct.cpp +549 -0
  68. otswap-0.1.0/src/Support.cpp +308 -0
  69. otswap-0.1.0/src/Table.cpp +738 -0
  70. otswap-0.1.0/src/Writers.cpp +446 -0
  71. otswap-0.1.0/src/arc.h +91 -0
  72. otswap-0.1.0/src/detmath.h +67 -0
  73. otswap-0.1.0/src/internal.h +243 -0
  74. otswap-0.1.0/src/pixel.h +137 -0
  75. otswap-0.1.0/tests/check.h +91 -0
  76. otswap-0.1.0/tests/cmake/consumer.cpp +69 -0
  77. otswap-0.1.0/tests/cmake/install/CMakeLists.txt +12 -0
  78. otswap-0.1.0/tests/cmake/subproject/CMakeLists.txt +27 -0
  79. otswap-0.1.0/tests/cpp_reference.cpp +236 -0
  80. otswap-0.1.0/tests/determinism_hashes.json +82 -0
  81. otswap-0.1.0/tests/detmath_reference.h +643 -0
  82. otswap-0.1.0/tests/test_determinism.py +331 -0
  83. otswap-0.1.0/tests/test_detmath.cpp +346 -0
  84. otswap-0.1.0/tests/test_distance_table.cpp +431 -0
  85. otswap-0.1.0/tests/test_mask.cpp +1118 -0
  86. otswap-0.1.0/tests/test_otswap.py +1802 -0
  87. otswap-0.1.0/tests/test_pixel.cpp +145 -0
  88. otswap-0.1.0/tests/test_reconstruct.cpp +693 -0
  89. otswap-0.1.0/tests/test_rsd.cpp +1442 -0
  90. otswap-0.1.0/tests/test_rsd.py +348 -0
  91. otswap-0.1.0/tests/test_support.cpp +277 -0
  92. otswap-0.1.0/tests/test_table.cpp +551 -0
  93. otswap-0.1.0/tests/test_writers.cpp +348 -0
  94. otswap-0.1.0/tools/determinism/edge_values.py +484 -0
  95. otswap-0.1.0/tools/determinism/record.py +51 -0
  96. otswap-0.1.0/tools/wheels/build_deps.sh +130 -0
  97. otswap-0.1.0/tools/wheels/check_dependencies.py +84 -0
  98. otswap-0.1.0/tools/wheels/select_omp.sh +28 -0
  99. otswap-0.1.0/tools/wheels/test_wheel.sh +46 -0
@@ -0,0 +1,166 @@
1
+ name: CI
2
+
3
+ # Builds and tests the C++ library, the Python module and the CMake package
4
+ # on every push and pull request: with GCC and clang on Linux and with Apple
5
+ # clang on macOS, warnings as errors.
6
+
7
+ on: [push, pull_request]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ build:
14
+ name: ${{ matrix.name }}
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ include:
20
+ - name: Linux GCC
21
+ os: ubuntu-24.04
22
+ cc: gcc
23
+ cxx: g++
24
+ - name: Linux clang
25
+ os: ubuntu-24.04
26
+ cc: clang
27
+ cxx: clang++
28
+ - name: macOS Apple clang
29
+ os: macos-latest
30
+ cc: clang
31
+ cxx: clang++
32
+
33
+ env:
34
+ CC: ${{ matrix.cc }}
35
+ CXX: ${{ matrix.cxx }}
36
+
37
+ steps:
38
+ - uses: actions/checkout@v7
39
+
40
+ - uses: actions/setup-python@v7
41
+ with:
42
+ python-version: "3.12"
43
+
44
+ # GCC brings libgomp; clang on Linux needs libomp.
45
+ - name: Install cfitsio and OpenMP
46
+ if: runner.os == 'Linux'
47
+ run: sudo apt-get update && sudo apt-get install --yes libcfitsio-dev libomp-dev
48
+
49
+ # Homebrew's libomp is keg-only: otswap, and its installed package,
50
+ # find it without OpenMP_ROOT.
51
+ - name: Install cfitsio and libomp
52
+ if: runner.os == 'macOS'
53
+ run: |
54
+ brew install cfitsio libomp
55
+ echo "CFITSIO_ROOT=$(brew --prefix cfitsio)" >> "$GITHUB_ENV"
56
+
57
+ - name: Configure
58
+ run: |
59
+ cmake -S . -B build -DCMAKE_COMPILE_WARNING_AS_ERROR=ON | tee configure.log
60
+ # without OpenMP every test would still pass, serially
61
+ grep -q "Found OpenMP_CXX" configure.log
62
+
63
+ - name: Build
64
+ run: cmake --build build --parallel
65
+
66
+ - name: Test
67
+ run: ctest --test-dir build --output-on-failure
68
+
69
+ - name: Every translation unit is compiled without FP contraction
70
+ run: |
71
+ python3 - <<'PY'
72
+ import json, sys
73
+ entries = json.load(open("build/compile_commands.json"))
74
+ bad = [e["file"] for e in entries
75
+ if "-ffp-contract=off" not in e.get("command", " ".join(e.get("arguments", [])))]
76
+ print(len(entries), "translation units;", len(bad), "without -ffp-contract=off")
77
+ sys.exit(1 if bad or not entries else 0)
78
+ PY
79
+
80
+ # The bit-identity tests compare the module with the C++ library built
81
+ # above; test_determinism.py compares both thread counts with the
82
+ # hashes recorded in tests/determinism_hashes.json.
83
+ - name: Build and install the module
84
+ run: pip install ".[test]"
85
+
86
+ - name: Python tests
87
+ env:
88
+ OTSWAP_CPP_REFERENCE: ${{ github.workspace }}/build/cpp_reference
89
+ run: >-
90
+ python -m pytest tests/test_otswap.py tests/test_rsd.py tests/test_determinism.py
91
+ -p no:cacheprovider -rs
92
+
93
+ # The C++ install rules are off under scikit-build-core.
94
+ - name: The module installs no C++ library, header or CMake file
95
+ run: |
96
+ if pip show -f otswap | grep -E '\.(a|h|cmake)$'; then
97
+ exit 1
98
+ fi
99
+
100
+ # The package must work from wherever its prefix ends up.
101
+ - name: Install, then move the prefix
102
+ run: |
103
+ cmake --install build --prefix "$RUNNER_TEMP/prefix"
104
+ mv "$RUNNER_TEMP/prefix" "$RUNNER_TEMP/moved"
105
+
106
+ - name: The installed files
107
+ working-directory: ${{ runner.temp }}/moved
108
+ run: |
109
+ headers=$(find include -type f | LC_ALL=C sort | tr '\n' ' ')
110
+ expected="include/meshsearch/MeshGrid.h include/otswap/OT.h include/otswap/RSD.h include/otswap/io.h "
111
+ if [ "$headers" != "$expected" ]; then
112
+ echo "installed headers: $headers"
113
+ exit 1
114
+ fi
115
+ # no path of this machine: the checkout, the build, the prefix, cfitsio
116
+ if grep -rlF -e "$GITHUB_WORKSPACE" -e "$RUNNER_TEMP" -e libcfitsio lib/cmake; then
117
+ echo "the files above hold a build-machine path"
118
+ exit 1
119
+ fi
120
+ # the vendored Healpix is the tests' reference only
121
+ if nm -C lib/libotswap.a | grep -E "T_Healpix_Base|Healpix_Tables|PlanckError"; then
122
+ echo "libotswap.a holds Healpix code"
123
+ exit 1
124
+ fi
125
+
126
+ # find_package(otswap CONFIG) against the moved tree
127
+ - name: Consume the installed package
128
+ run: |
129
+ cmake -S tests/cmake/install -B build-install-consumer -DCMAKE_PREFIX_PATH="$RUNNER_TEMP/moved"
130
+ cmake --build build-install-consumer
131
+ ./build-install-consumer/consumer
132
+
133
+ # Each example is a project of its own, built against the moved package.
134
+ - name: Build the C++ examples
135
+ run: |
136
+ for d in box lightcone full_recons_lightcone full_recons_box; do
137
+ cmake -S examples/$d -B build-examples/$d -DCMAKE_PREFIX_PATH="$RUNNER_TEMP/moved" \
138
+ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DCMAKE_CXX_FLAGS="-Wall -Wextra"
139
+ cmake --build build-examples/$d
140
+ done
141
+
142
+ # With a fixed seed the C++ and the Python examples write the same files.
143
+ - name: Run the examples, C++ then Python, and compare their outputs
144
+ run: |
145
+ for d in box lightcone full_recons_lightcone full_recons_box; do
146
+ "./build-examples/$d/$d"
147
+ mv "examples/$d/output" "examples/$d/output-cpp"
148
+ python "examples/$d/$d.py"
149
+ diff -r "examples/$d/output-cpp" "examples/$d/output"
150
+ done
151
+
152
+ # add_subdirectory on the source tree: no tests, no example, no build type
153
+ - name: Consume the source tree as a subproject
154
+ run: |
155
+ cmake -S tests/cmake/subproject -B build-subproject-consumer -DOTSWAP_SOURCE_DIR="$GITHUB_WORKSPACE"
156
+ cmake --build build-subproject-consumer --parallel
157
+ ./build-subproject-consumer/consumer
158
+
159
+ # An installed meshsearch of the same minor version is used, not fetched.
160
+ - name: Build against an installed meshsearch
161
+ run: |
162
+ cmake -S . -B build-found -DOTSWAP_BUILD_TESTS=OFF -DCMAKE_PREFIX_PATH="$RUNNER_TEMP/moved" \
163
+ | tee found.log
164
+ grep -q "otswap: using meshsearch 0.2" found.log
165
+ test ! -d build-found/_deps/meshsearch-src
166
+ cmake --build build-found --parallel
@@ -0,0 +1,64 @@
1
+ name: Docs
2
+
3
+ # Builds the documentation on every push and pull request, so a broken
4
+ # reference or a malformed docstring fails here and not silently. Publishing to
5
+ # Pages happens only from main. Deliberately separate from release.yml: a docs
6
+ # failure must never stand between a tag and PyPI.
7
+
8
+ on:
9
+ push:
10
+ pull_request:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: pages
17
+ cancel-in-progress: false
18
+
19
+ jobs:
20
+ build:
21
+ name: build
22
+ runs-on: ubuntu-24.04
23
+
24
+ steps:
25
+ - uses: actions/checkout@v7
26
+
27
+ - uses: actions/setup-python@v7
28
+ with:
29
+ python-version: "3.12"
30
+
31
+ - name: Install Doxygen
32
+ run: sudo apt-get update && sudo apt-get install --yes doxygen
33
+
34
+ # The package is not built: the Python reference is read from the type
35
+ # stubs, and the C++ one from the headers.
36
+ - name: Install the documentation toolchain
37
+ run: pip install -r docs/requirements.txt
38
+
39
+ - name: Build
40
+ # -W: a warning is a failure. An unresolved reference or a docstring
41
+ # Sphinx cannot parse should break the build, not reach the site.
42
+ run: sphinx-build -W --keep-going -b html docs docs/_build/html
43
+
44
+ - uses: actions/upload-pages-artifact@v5
45
+ with:
46
+ path: docs/_build/html
47
+
48
+ deploy:
49
+ name: deploy to Pages
50
+ needs: build
51
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
52
+ runs-on: ubuntu-24.04
53
+
54
+ environment:
55
+ name: github-pages
56
+ url: ${{ steps.deployment.outputs.page_url }}
57
+
58
+ permissions:
59
+ pages: write
60
+ id-token: write
61
+
62
+ steps:
63
+ - id: deployment
64
+ uses: actions/deploy-pages@v5
@@ -0,0 +1,116 @@
1
+ name: Release
2
+
3
+ # Publishes to PyPI when a v* tag is pushed. Run it from the Actions tab
4
+ # (workflow_dispatch) to build and test the artefacts without publishing.
5
+
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ sdist:
16
+ name: sdist
17
+ runs-on: ubuntu-24.04
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+
21
+ - uses: actions/setup-python@v7
22
+ with:
23
+ python-version: "3.12"
24
+
25
+ # The version lives in pyproject.toml and in CMakeLists.txt; on a tag
26
+ # push the tag must name it too.
27
+ - name: The versions agree
28
+ run: |
29
+ version=$(python -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
30
+ cmake_version=$(sed -nE 's/^project\(otswap VERSION ([0-9.]+).*/\1/p' CMakeLists.txt)
31
+ if [ "$version" != "$cmake_version" ]; then
32
+ echo "pyproject.toml says $version and CMakeLists.txt $cmake_version"
33
+ exit 1
34
+ fi
35
+ if [ "$GITHUB_EVENT_NAME" = push ] && [ "${GITHUB_REF_NAME#v}" != "$version" ]; then
36
+ echo "tag $GITHUB_REF_NAME does not match version $version"
37
+ exit 1
38
+ fi
39
+
40
+ - name: Build
41
+ run: pipx run build --sdist
42
+
43
+ - name: The sdist holds no example
44
+ run: |
45
+ if tar -tzf dist/*.tar.gz | grep '/examples/'; then
46
+ exit 1
47
+ fi
48
+
49
+ - name: Check the metadata PyPI will render
50
+ run: pipx run twine check dist/*
51
+
52
+ - uses: actions/upload-artifact@v7
53
+ with:
54
+ name: dist-sdist
55
+ path: dist/*.tar.gz
56
+
57
+ wheels:
58
+ name: wheels on ${{ matrix.os }}
59
+ runs-on: ${{ matrix.os }}
60
+ strategy:
61
+ fail-fast: false
62
+ matrix:
63
+ os: [ubuntu-24.04, ubuntu-24.04-arm, macos-latest]
64
+
65
+ # The configuration is in pyproject.toml: every wheel is repaired,
66
+ # checked by tools/wheels/check_dependencies.py and tested by
67
+ # tools/wheels/test_wheel.sh, the bit-identity and determinism tests
68
+ # included.
69
+ steps:
70
+ - uses: actions/checkout@v7
71
+
72
+ - uses: pypa/cibuildwheel@v4.2.1
73
+ with:
74
+ output-dir: wheelhouse
75
+
76
+ # The C++ install rules are off under scikit-build-core.
77
+ - name: The wheels hold no C++ library, header, CMake file or example
78
+ run: |
79
+ python3 - <<'PY'
80
+ import glob, sys, zipfile
81
+ wheels = glob.glob("wheelhouse/*.whl")
82
+ bad = [f"{w}: {name}" for w in wheels for name in zipfile.ZipFile(w).namelist()
83
+ if name.endswith((".a", ".h", ".cmake")) or "examples/" in name]
84
+ print(len(wheels), "wheels;", len(bad), "C++ library, header, CMake or example files")
85
+ print("\n".join(bad))
86
+ sys.exit(1 if bad or not wheels else 0)
87
+ PY
88
+
89
+ - uses: actions/upload-artifact@v7
90
+ with:
91
+ name: dist-${{ matrix.os }}
92
+ path: wheelhouse/*.whl
93
+
94
+ publish:
95
+ name: publish to PyPI
96
+ needs: [sdist, wheels]
97
+ if: github.event_name == 'push'
98
+ runs-on: ubuntu-24.04
99
+
100
+ # The trusted publisher on PyPI is configured against this environment name
101
+ # and this workflow's filename. Changing either means changing it there.
102
+ environment:
103
+ name: pypi
104
+ url: https://pypi.org/p/otswap
105
+
106
+ permissions:
107
+ id-token: write # mints the OIDC token PyPI checks; no API token
108
+
109
+ steps:
110
+ - uses: actions/download-artifact@v8
111
+ with:
112
+ pattern: dist-*
113
+ merge-multiple: true
114
+ path: dist
115
+
116
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,22 @@
1
+
2
+ build/
3
+ build-*/
4
+ _build/
5
+ docs/_build/
6
+ docs/doxygen/
7
+ dist/
8
+ *.egg-info/
9
+ CMakeCache.txt
10
+ CMakeFiles/
11
+ cmake_install.cmake
12
+ *.o
13
+ *.a
14
+ *.so
15
+ *.dylib
16
+ __pycache__/
17
+ *.pyc
18
+ .pytest_cache/
19
+ .DS_Store
20
+ .venv/
21
+ examples/*/output/
22
+ wheelhouse/
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — 2026-10-08
4
+
5
+ First release.
6
+
7
+ ### Compared with CosmoBolognaLib's OTreconstruction
8
+
9
+ - The same algorithm and inputs: seeding on a mesh, then local search that
10
+ tries every permutation of the partners of four neighbouring tracers.
11
+ - With a fixed seed, the result does not depend on the number of threads, and
12
+ is the same bit for bit on every supported platform and compiler: the
13
+ assignment of the randoms, their draw, the seeding and the swap loop each
14
+ draw from their own random stream.
15
+ - Every tracer is examined in every sweep.
16
+ - The seeding radius (8 mean particle separations) and the number of swap
17
+ neighbours (113) are named constants, not parameters.
18
+ - Mask crossings: the adaptive search along the arc, with a limit on the
19
+ distinct unobserved pixels crossed (0 rejects at the first), and validity
20
+ kept per realization.
21
+ - Cosmology enters as a table of redshift, comoving distance and growth rate,
22
+ computed from a flat w0-wa cosmology or given by the caller; no GSL.
23
+ - The redshift-space correction is a library function for each geometry, with
24
+ its four steps also available on their own.
25
+ - Table writers for every product, ASCII and FITS, with column descriptions,
26
+ units and header keywords.
27
+ - A Python package on the same code.
@@ -0,0 +1,55 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use otswap, please cite the paper below and CosmoBolognaLib."
3
+ title: otswap
4
+ abstract: >-
5
+ Optimal transport reconstruction of the displacement field of a tracer
6
+ catalogue, by local swapping.
7
+ type: software
8
+ authors:
9
+ - family-names: Sartori
10
+ given-names: Simone
11
+ email: simone.sartori@inaf.it
12
+ version: 0.1.0
13
+ date-released: 2026-10-08
14
+ license: GPL-2.0-or-later
15
+ repository-code: "https://github.com/SimoSartori/otswap"
16
+ url: "https://simosartori.github.io/otswap/"
17
+ preferred-citation:
18
+ type: article
19
+ title: "The Back-in-time Void Finder: dynamical identification of cosmic voids through optimal transport reconstruction"
20
+ authors:
21
+ - family-names: Sartori
22
+ given-names: Simone
23
+ - family-names: Contarini
24
+ given-names: Sofia
25
+ - family-names: Sarpa
26
+ given-names: Elena
27
+ - family-names: Degni
28
+ given-names: Giulia
29
+ - family-names: Marulli
30
+ given-names: Federico
31
+ - family-names: Escoffier
32
+ given-names: Stephanie
33
+ - family-names: Moscardini
34
+ given-names: Lauro
35
+ year: 2026
36
+ identifiers:
37
+ - type: other
38
+ value: "arXiv:2601.15378"
39
+ url: "https://arxiv.org/abs/2601.15378"
40
+ references:
41
+ - type: article
42
+ title: "CosmoBolognaLib: C++ libraries for cosmological calculations"
43
+ authors:
44
+ - family-names: Marulli
45
+ given-names: Federico
46
+ - family-names: Veropalumbo
47
+ given-names: Alfonso
48
+ - family-names: Moresco
49
+ given-names: Michele
50
+ journal: Astronomy and Computing
51
+ volume: 14
52
+ start: 35
53
+ end: 42
54
+ year: 2016
55
+ doi: 10.1016/j.ascom.2016.01.005