Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,3 @@ jobs:
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

1 change: 0 additions & 1 deletion .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,3 @@ jobs:
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
pathlength

# Output data
*.csv
*.csv
2 changes: 1 addition & 1 deletion .go-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.24.4
1.25.4
36 changes: 36 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-added-large-files
- id: check-executables-have-shebangs
- id: check-json
- id: check-merge-conflict
- id: check-shebang-scripts-are-executable
- id: check-toml
- id: check-xml
- id: check-yaml
args: [--allow-multiple-documents]
- id: detect-private-key
- id: end-of-file-fixer
- id: no-commit-to-branch
- id: pretty-format-json
- id: trailing-whitespace

# Go-specific hooks
- repo: https://github.com/tekwizely/pre-commit-golang
rev: v1.0.0-rc.3
hooks:
# Format Go code
- id: go-fmt
args: [-w]

# Run go vet for static analysis
- id: go-vet-repo-mod

# Run tests before committing
- id: go-test-repo-mod
args: [-v]

# Ensure go.mod and go.sum are tidy
- id: go-mod-tidy-repo
183 changes: 183 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# CLAUDE.md

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

## Project Overview

PathLength is a ray tracing model that calculates the resolution and sensitivity of reflective superposition compound eyes (found in crustaceans like Nephrops norvegicus). It's a Go rewrite of an original QBASIC program from 1995, ported from a Python version.

## Development Commands

### Build
```bash
go build
```
This creates an executable named `pathlength` in the current directory.

### Run from source
```bash
go run .
```
Note: The program requires a `-f` flag with a CSV parameter file path.

### Run with parameter file
```bash
go run . -f example_data/nephrops_parameters.txt
# or with built binary:
./pathlength -f example_data/nephrops_parameters.txt
```

### Test
```bash
# Run all tests
go test -v

# Run a specific test
go test -v -run TestParseInputParameters
go test -v -run TestCalculateRessens
```

### Display help
```bash
./pathlength -h
```

## Development Workflow

**IMPORTANT: Always run tests before committing changes.**

This project uses pre-commit hooks to automatically enforce code quality. The hooks will:
- Format Go code with `go fmt`
- Run static analysis with `go vet`
- Run all tests with `go test`
- Ensure `go.mod` and `go.sum` are tidy
- Check for common issues (merge conflicts, large files, etc.)

### Setup pre-commit (first time only)

```bash
# Install pre-commit (if not already installed)
pip install pre-commit
# or: brew install pre-commit

# Install the git hooks
pre-commit install
```

### Manual test run

You can manually run tests before committing:

```bash
go test -v
```

If tests fail, fix the issues before committing. This ensures the codebase remains stable and the scientific calculations remain accurate.

### Commit Message Format

Use conventional commit format for all commit messages:

```
<type>(<scope>): <description>

[optional body]

[optional footer]
```

**Types:**
- `feat`: New feature
- `fix`: Bug fix
- `refactor`: Code refactoring (no functional changes)
- `test`: Adding or updating tests
- `docs`: Documentation changes
- `chore`: Maintenance tasks (dependencies, build config, etc.)
- `perf`: Performance improvements

**Examples:**
```
feat(model): add support for pointy-ended rhabdoms
fix(csv): handle malformed records gracefully
test(parser): add edge case tests for parameter validation
docs: update README with installation instructions
refactor(model): simplify ray tracing calculation logic
```

## Code Architecture

### Core Components

The codebase is organized into 4 main Go files in a single package:

1. **pathlength.go** - Entry point with CLI argument parsing
- Handles flags: `-f` (file), `-h` (help), `-v` (version), `-c` (citation), `-l` (license)
- Parses parameter file and orchestrates simulation runs
- Main loop iterates over each parameter set from CSV input

2. **model.go** - Simulation engine and data structures
- `Parameters` struct: Holds 10 eye-specific configuration values from CSV
- `Model` struct: Contains calculated parameters and simulation state
- `NewModel()`: Initializes model from parameters
- `initialCalculations()`: Computes derived values (eye radius, critical angle, facet counts, etc.)
- `runModel()`: Main simulation loop implementing ray tracing logic
- Iterates over pigment combinations (tapetal and shielding)
- For each combination, iterates over facets in the eyeshine patch
- Calculates light paths through rhabdoms based on angle of incidence
- Four main cases: perpendicular ray, no reflection, edge reflection, base bounce
- Outputs pathlengths to CSV file

3. **csv.go** - File I/O and data processing
- `parseInputParameters()`: Reads CSV parameter file, returns slice of Parameters
- `calculateRessens()`: Post-processes pathlengths to calculate resolution and sensitivity
- Reads `{species}_pathlengths.csv`
- Calculates absorbance, accumulates values across rhabdoms
- Outputs `{species}_summary_res.csv` and `{species}_summary_sen.csv`

4. **csv_test.go** - Test suite
- `TestParseInputParameters`: Tests CSV parsing with valid, nonexistent, and malformed files
- `TestCalculateRessens`: Tests resolution/sensitivity calculation

### Data Flow

1. CSV parameter file → `parseInputParameters()` → slice of `Parameters`
2. For each Parameters → `NewModel()` → `Model` with calculated values
3. `Model.runModel()` → writes `{species}_pathlengths.csv` and `{species}_debug.csv`
4. `Model.calculateRessens()` → reads pathlengths → writes summary CSV files

### Input File Format

CSV files in `example_data/` directory with 10 comma-separated fields per row:
```
species_name, rhabdom_length, rhabdom_width, eye_diameter, facet_width,
aperture_diameter, cytoplasm_refractive_index, rhabdom_refractive_index,
blur_circle_extent, proximal_rhabdom_angle
```

Each row represents a separate simulation run. Multiple rows can be processed in one execution.

### Output Files

For each parameter set with species name "X", generates:
- `X_debug.csv` - Debug information from simulation
- `X_pathlengths.csv` - Raw pathlength data for each facet/pigment combination
- `X_summary_res.csv` - Calculated resolution values
- `X_summary_sen.csv` - Calculated sensitivity values

## Key Implementation Notes

- The ray tracing simulation handles refraction at the cornea using empirical regression equations for different angle ranges
- The critical angle for total internal reflection is calculated using Snell's law
- Pigment migration is simulated by incrementing tapetal and shielding pigment values through the rhabdom length
- The blur circle feature adds additional facets to account for optical aberrations
- The Python version this was ported from had complex nested loops and state management; the Go version attempts to preserve this logic while using more idiomatic Go

## Dependencies

- Go 1.25.4 (specified in go.mod)
- No external dependencies required

## Citation

When using this program, cite:
Gaten, E., Moss, S., Johnson, M. 2013. The Reniform Reflecting Superposition Compound Eyes of Nephrops Norvegicus: Optics, Susceptibility to Light-Induced Damage, Electrophysiology and a Ray Tracing Model. In: M. L. Johnson and M. P. Johnson, ed(s). Advances in Marine Biology: The Ecology and Biology of Nephrops norvegicus. Oxford: Academic Press, 107:148.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -616,4 +616,4 @@ above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
copy of the Program in return for a fee.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ Email: [email protected]
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

# Install Golang
brew install go@1.24
brew install go@1.25
```

### Linux (Debian/Ubuntu)

```bash
# Download tarball
wget -P /tmp https://dl.google.com/go/go1.24.4.linux-amd64.tar.gz
wget -P /tmp https://dl.google.com/go/go1.25.4.linux-amd64.tar.gz

# Extract tarball
sudo tar -zxvf /tmp/go1.24.4.linux-amd64.tar.gz -C /usr/local
sudo tar -zxvf /tmp/go1.25.4.linux-amd64.tar.gz -C /usr/local

# Setup environment
echo "export GOROOT=/usr/local/go" >> ~/.profile
Expand Down
2 changes: 1 addition & 1 deletion example_data/acanthephyra_parameters.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
acanthephyra,127,15.8,2480,22.5,870,1.34,1.37,1,0
acanthephyra_bce3,127,15.8,2480,22.5,870,1.34,1.37,3,0
acanthephyra_bce6,127,15.8,2480,22.5,870,1.34,1.37,6,0
acanthephyra_bce6,127,15.8,2480,22.5,870,1.34,1.37,6,0
2 changes: 1 addition & 1 deletion example_data/astacodes_parameters.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
astacodes,84,16,890,32,445,1.34,1.37,18,0
astacodes,84,16,890,32,445,1.34,1.37,18,0
2 changes: 1 addition & 1 deletion example_data/nephrops_parameters.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
nephropsfl,180,25,7800,50,3200,1.34,1.37,18,0
nephropspl,180,25,7800,50,3200,1.34,1.37,18,12.5
nephropsfa,180,25,6760,50,3060,1.34,1.37,10,0
nephropspa,180,25,6760,50,3060,1.34,1.37,10,12.5
nephropspa,180,25,6760,50,3060,1.34,1.37,10,12.5
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module pathlength

go 1.24.4

require github.com/stretchr/testify v1.10.0 // indirect
go 1.25.4
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
Loading