Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1ac814a
adding claude file
EiffL Jun 26, 2025
efe5535
Modernize package for NumPy 2.x and modern Python packaging
EiffL Jun 26, 2025
ffe0d3b
updates
EiffL Jun 26, 2025
229975b
Complete NumPy 2.x compatibility and testing infrastructure
EiffL Jun 26, 2025
e805334
Fix GitHub Actions build environment for C extensions
EiffL Jun 26, 2025
5c7cc79
Fix GitHub Actions Python 3.8/NumPy 2.x compatibility issue
EiffL Jun 26, 2025
34eb4bd
Fix Python 3.9 NumPy compatibility in GitHub Actions
EiffL Jun 26, 2025
fd89d23
Fix test data download and enable comprehensive testing
EiffL Jun 26, 2025
c00fff4
Fix all deprecated NumPy aliases and emcee compatibility
EiffL Jun 26, 2025
650a586
Remove continue-on-error from GitHub Actions tests
EiffL Jun 26, 2025
aa98f59
removing test data
EiffL Jun 26, 2025
61571c8
updating gitignore
EiffL Jun 26, 2025
6dd4990
Prevent test data and outputs from being committed
EiffL Jun 26, 2025
ae88209
Claude PR Assistant workflow
EiffL Jun 26, 2025
6e5eba1
Merge pull request #2 from EiffL/add-claude-github-actions-1750930069689
EiffL Jun 26, 2025
660f765
Fix matplotlib and NumPy 2.x compatibility issues
claude[bot] Jun 26, 2025
954d916
Fix NumPy 2.x array assertion compatibility issues
claude[bot] Jun 26, 2025
d3fd109
Update test.yml
EiffL Jun 26, 2025
56b32b4
Fix remaining NumPy 2.x and scipy compatibility issues
claude[bot] Jun 26, 2025
30b704c
Fix remaining NumPy 2.x and modern Python compatibility issues
claude[bot] Jun 26, 2025
de73afd
additional fixes
EiffL Jun 26, 2025
ebb3c3a
Fix pandas merge compatibility in database operations
EiffL Jun 26, 2025
38dc642
removing support for old pythons
EiffL Jun 26, 2025
373d288
minor edit
EiffL Jun 26, 2025
88b09c3
small updates
EiffL Jun 26, 2025
33976e3
minor edit to readme
EiffL Jun 26, 2025
4e75286
Merge pull request #1 from EiffL/modernize-numpy2-packaging
EiffL Jun 26, 2025
216cdc4
Update README.rst
EiffL Jun 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
# model: "claude-opus-4-20250514"

# Optional: Customize the trigger phrase (default: @claude)
# trigger_phrase: "/claude"

# Optional: Trigger when specific user is assigned to an issue
# assignee_trigger: "claude-bot"

# Optional: Allow Claude to run specific commands
# allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"

# Optional: Add custom instructions for Claude to customize its behavior for your project
# custom_instructions: |
# Follow our coding standards
# Ensure all new code has tests
# Use TypeScript for new files

# Optional: Custom environment variables for Claude
# claude_env: |
# NODE_ENV: test

110 changes: 110 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Tests

on:
push:
branches: [ master, main ]
pull_request:
branches: [ master, main ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install all system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgsl-dev libfftw3-dev gcc build-essential pkg-config

- name: Install build dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install "numpy>=2.0.0" "Cython>=0.29.0"
pip install pytest pytest-cov

- name: Configure for Ubuntu system libraries
run: |
# Create Ubuntu-specific setup.cfg for CI
cat > setup.cfg << EOF
[gsl]
installation_path = /usr

[fftw3]
installation_path = /usr

[nicaea]
install_python_bindings = False
installation_path = /usr/local
EOF

# Check what GSL libraries are actually available
find /usr -name "*gsl*" -type f 2>/dev/null | head -10
echo "GSL pkg-config info:"
pkg-config --libs gsl || echo "pkg-config GSL info not available"

- name: Verify system dependencies
run: |
pkg-config --exists gsl
pkg-config --cflags gsl
pkg-config --libs gsl
ls -la /usr/include/gsl/
ls -la /usr/lib/*/libgsl.*

- name: Install package with all C extensions
run: |
python setup.py build_ext --inplace
pip install -e .

- name: Verify all C extensions are working
run: |
python -c "
import lenstools
print('LensTools version:', lenstools.__version__)
print('NumPy version:', __import__('numpy').__version__)

# Test all C extensions
from lenstools.extern import _topology, _gadget2, _nbody, _pixelize
print('✓ All core C extensions loaded successfully')

# Test optional C extensions
try:
from lenstools.extern import _design
print('✓ _design C extension loaded (GSL)')
except ImportError as e:
print(f'⚠ _design C extension failed: {e}')

try:
from lenstools.extern import _nicaea
print('✓ _nicaea C extension loaded (NICAEA)')
except ImportError as e:
print(f'⚠ _nicaea C extension failed: {e}')

# Test C extension functionality with NumPy 2.x
import numpy as np
test_data = np.random.rand(50, 50).astype(np.float64)
grad = _topology.gradient(test_data, None, None)
print('✓ C extensions working with NumPy', np.__version__)
"

- name: Download test data
run: |
echo "Downloading test data..."
export LENSTOOLS_DATA="./test_data"
python -c "import lenstools; lenstools.dataExtern()"
echo "✓ Test data downloaded successfully"

- name: Run comprehensive test suite
run: |
echo "Running full test suite with external data..."
export LENSTOOLS_DATA="./test_data"
python -m pytest --pyargs lenstools.tests -v --tb=short
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,38 @@ coverage.xml
# Sphinx documentation
docs/_build/

# Test data and outputs (should not be committed)
LT_Data/
SimTest/
test_data/
test_data_download/
test_env/
test_output/
*.tar.gz
*.png
*.pdf
*.eps
*.txt
*.pkl
*.fits
*.fit
gadget*
ensemble_saved*
!requirements.txt
!setup.cfg
!README.txt
!LICENSE.txt
!HISTORY.txt

# Pytest cache
.pytest_cache/

# Jupyter notebook checkpoints
.ipynb_checkpoints/

# Mac OS
.DS_Store

# IDE files
.vscode/
.idea/
123 changes: 123 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

LensTools is a scientific Python package for **Weak Gravitational Lensing analysis** used in astrophysics and cosmology research. It provides tools for convergence maps, shear analysis, N-body simulations, ray tracing, and statistical analysis of cosmic structure.

## Development Commands

### Installation and Build
```bash
# Modern installation (preferred method)
pip install -e .

# Or with dependencies from requirements file
pip install -r requirements.txt
pip install -e .

# Legacy installation with C extensions (if GSL/FFTW3 available)
python setup.py build_ext -i --gsl=/usr/local --fftw3=/usr/local
python setup.py install --gsl=/usr/local --fftw3=/usr/local
```

### Testing
```bash
# Test C extensions and NumPy 2.x compatibility (recommended)
python -m pytest test_cextensions.py -v

# Test specific working functionality
python -m pytest lenstools/tests/test_contours.py -v

# Run all tests (many require external data files and will fail)
python -m pytest lenstools/tests/ -v --tb=short

# Manual verification of C extensions
python -c "
import lenstools
from lenstools.extern import _topology, _gadget2, _nbody, _pixelize
import numpy as np
test_data = np.random.rand(50, 50).astype(np.float64)
grad = _topology.gradient(test_data, None, None)
print('✓ All C extensions working with NumPy', np.__version__)
"
```

**Note on Testing**: Most tests in `lenstools/tests/` require external data files that are downloaded from Dropbox. The `test_cextensions.py` file provides comprehensive testing of C extensions and NumPy 2.x compatibility without external dependencies.

### GitHub Actions CI/CD
The repository includes a comprehensive GitHub Actions workflow that tests:
- **All Python versions**: 3.10 through 3.13
- **All dependencies**: GSL, FFTW3, and all system dependencies installed
- **All C extensions enabled**: Tests that all C extensions compile and work correctly
- **NumPy 2.x compatibility**: Verifies C extensions work with modern NumPy
- **Pytest testing**: Uses modern pytest framework for all tests

### Modernization Status ✅ COMPLETE

The package has been successfully modernized with the following improvements:

- **Modern packaging**: Added `pyproject.toml` with modern build system
- **NumPy 2.x compatibility**: ✅ COMPLETE - All C extensions now work with NumPy 2.0+
- **Updated dependencies**: Modern versions of scipy, matplotlib, astropy, emcee
- **C extensions**: ✅ WORKING - All C extensions compile and run correctly
- **Cross-platform Python support**: Python 3.10+ compatibility
- **Modern Python support**: Requires Python 3.10 or later

**C Extensions Status**:
- ✅ All C extensions (_topology, _gadget2, _nbody, _pixelize, _design, _nicaea) are enabled and working
- ✅ NumPy 2.x C API compatibility issues resolved using compatibility macros
- ✅ All PyArray_DATA, PyArray_DIM calls updated for NumPy 2.x

**Testing & Compatibility**:
- ✅ All deprecated NumPy aliases (np.float, np.complex) have been updated
- ✅ Database compatibility issues with pandas merges resolved
- ✅ SQLAlchemy 2.0 compatibility implemented
- ✅ All tests passing with NumPy 2.x and modern pandas
- Minor: pkg_resources warnings can be addressed by migrating to importlib.resources

### External Dependencies
The package requires these external C libraries:
- **GSL** (GNU Scientific Library) - for mathematical functions
- **FFTW3** - for fast Fourier transforms
- **NICAEA** (optional) - for cosmological calculations

Configure library paths in `setup.cfg` if not in `/usr/local`.

## Architecture

### Core Package Structure
- **`image/`** - Convergence maps, shear maps, flexion maps, CMB analysis
- **`statistics/`** - Ensemble analysis, constraints, contours, MCMC samplers
- **`simulations/`** - N-body simulation I/O (Gadget2, FastPM), ray tracing engine
- **`catalog/`** - Galaxy catalog handling and mock generation
- **`pipeline/`** - Simulation pipeline management, cluster computing, MPI support
- **`observations/`** - Real survey data handling (CFHT lens survey)
- **`utils/`** - FFT utilities, MPI helpers, algorithms
- **`extern/`** - C extensions for performance-critical computations
- **`tests/`** - Comprehensive test suite using nose framework

### Key Classes and Concepts
- **`ConvergenceMap`** - Primary class for weak lensing convergence field analysis
- **`ShearMap`/`FlexionMap`** - Shear and higher-order lensing field handling
- **`Catalog`** classes - Galaxy catalog management with astropy integration
- **`Ensemble`** - Statistical ensemble analysis framework for parameter estimation
- **`RayTracer`** - Ray tracing through simulated dark matter structures
- **`Design`** - Optimal experimental design for cosmological surveys

### External Integrations
- **N-body simulations:** Gadget2, FastPM format support
- **Cosmological codes:** CAMB, NICAEA parameter calculations
- **Observational data:** CFHT lens survey, DES-like mock catalogs
- **Parallel computing:** MPI support for cluster environments

### Performance Features
- C extensions in `extern/` for computationally intensive operations (topology analysis, Gadget I/O, pixelization)
- MPI parallelization throughout the codebase
- Efficient FFT implementations via FFTW3
- NumPy/SciPy vectorized operations

## Testing Framework

Uses **nose** testing framework with coverage reporting. Tests are organized by functionality and located in `lenstools/tests/`. The CI system (Travis) runs tests on Python 3.6/3.7 with external library dependencies.
6 changes: 4 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Welcome to LensTools!
+++++++++++++++++++++

.. image:: https://travis-ci.org/apetri/LensTools.svg?branch=master
:target: https://travis-ci.org/apetri/LensTools
.. image:: https://github.com/EiffL/LensTools/actions/workflows/test.yml/badge.svg
:target: https://github.com/EiffL/LensTools/actions/workflows/test.yml
.. image:: https://coveralls.io/repos/github/apetri/LensTools/badge.svg?branch=master
:target: https://coveralls.io/github/apetri/LensTools?branch=master
.. image:: http://img.shields.io/pypi/dm/lenstools.svg?style=flat
Expand All @@ -16,3 +16,5 @@ Welcome to LensTools!
:alt: Documentation Status

This python package collects together a suite of widely used analysis tools in Weak Gravitational Lensing. For more information visit `the project official page <http://lenstools.readthedocs.io>`_. If you make use of this code in your work, please `cite it! <http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=2016A%26C....17...73P&data_type=BIBTEX&db_key=AST&nocookieset=1>`_

**Note**: this package has been automatically updated to support Python 3.10 and above using **Claude Code**. Tests have been run to ensure compatibility, but please report any issues you encounter.
2 changes: 1 addition & 1 deletion lenstools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def dataExtern():
#Download the test data into path
def getTestData(path="."):

data_url = "https://www.dropbox.com/s/oh526rkrhiy3m8u/data.tar.gz"
data_url = "https://www.dropbox.com/s/oh526rkrhiy3m8u/data.tar.gz?dl=1"
data_filename = os.path.join(path,"data.tar.gz")

#Download the file
Expand Down
6 changes: 3 additions & 3 deletions lenstools/catalog/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"""

import numpy as np
from scipy.ndimage.filters import gaussian_filter
from scipy.ndimage import gaussian_filter
import astropy.table as tbl
import astropy.units as u

Expand Down Expand Up @@ -157,12 +157,12 @@ def pixelize(self,map_size,npixel=256,field_quantity=None,origin=np.zeros(2)*u.d

if type(field_quantity)==str:
assert field_quantity in self.columns,"There is no {0} field in the catalog!".format(field_quantity)
scalar = self.columns[field_quantity].astype(np.float)
scalar = self.columns[field_quantity].astype(np.float64)
elif type(field_quantity)==np.ndarray:
assert len(field_quantity)==len(self),"You should provide a scalar property for each record!!"
scalar = field_quantity
elif type(field_quantity) in [int,float]:
scalar = np.empty(len(self),dtype=np.float)
scalar = np.empty(len(self),dtype=np.float64)
scalar.fill(field_quantity)
else:
raise TypeError("field_quantity format not recognized!")
Expand Down
Loading