Skip to content

Commit

Permalink
finished up development for radii card
Browse files Browse the repository at this point in the history
  • Loading branch information
KedoKudo committed Jan 22, 2025
1 parent be6e341 commit 0ea0069
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 43 deletions.
78 changes: 35 additions & 43 deletions src/pleiades/sammy/parameters/radius.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
for radius parameters in SAMMY parameter files.
"""

import logging
import re
from enum import Enum
from typing import List, Optional, Tuple, Union
Expand Down Expand Up @@ -76,7 +75,7 @@ class RadiusParameters(BaseModel):
of input format.
"""

effective_radius: float = Field(description="Radius for potential scattering (Fermi)")
effective_radius: float = Field(description="Radius for potential scattering (Fermi)", ge=0)
true_radius: float = Field(description="Radius for penetrabilities and shifts (Fermi)")
channel_mode: int = Field(
description="Channel specification mode (0: all channels, 1: specific channels)",
Expand Down Expand Up @@ -914,59 +913,52 @@ def from_values(
true_radius: Optional[float] = None,
spin_groups: List[int] = None,
channels: Optional[List[int]] = None,
particle_pair: Optional[str] = None,
orbital_momentum: Optional[List[Union[int, str]]] = None,
relative_uncertainty: Optional[float] = None,
absolute_uncertainty: Optional[float] = None,
**kwargs,
) -> "RadiusCard":
"""Create a new radius card from parameter values.
A convenience method for creating cards directly from values.
Args:
effective_radius: Radius for potential scattering
true_radius: Radius for penetrabilities and shifts (defaults to effective_radius)
spin_groups: List of spin group numbers
channels: Optional list of channel numbers
particle_pair: Optional particle pair specification
orbital_momentum: Optional orbital angular momentum values
relative_uncertainty: Optional relative uncertainty for radii
absolute_uncertainty: Optional absolute uncertainty for radii
**kwargs: Additional parameters to pass to RadiusParameters
Returns:
RadiusCard: Created card instance
"""
# Separate parameters and extras
params = {
"effective_radius": effective_radius,
"true_radius": true_radius or effective_radius,
"spin_groups": spin_groups or [],
"channel_mode": 1 if channels else 0,
"channels": channels,
}
params.update(kwargs) # Allow setting other parameters

return cls(parameters=RadiusParameters(**params))
params.update(kwargs) # Only parameter-specific kwargs

# Create card with both parameters and extras
return cls(
parameters=RadiusParameters(**params),
particle_pair=particle_pair,
orbital_momentum=orbital_momentum,
relative_uncertainty=relative_uncertainty,
absolute_uncertainty=absolute_uncertainty,
)


if __name__ == "__main__":
# Enable logging for debugging
logging.basicConfig(level=logging.DEBUG)

# Test Targets:
# 1. Fixed-Width Format Tests (Default Format)
# - Basic single line (effective_radius, true_radius, single spin group)
# - Multiple spin groups on one line
# - Spin groups with continuation (-1 marker)
# - Channel specification with IX=0 marker
# - Error case: Invalid format/missing required fields

# 2. Alternate Format Tests (>99 spin groups)
# - Basic alternate format parsing (5-column integers)
# - Multiple spin groups in alternate format
# - Channel specification in alternate format
# - Error case: Invalid alternate format

# 3. Keyword Format Tests
# - Basic radius specification (single value)
# - Separate effective/true radius values
# - Uncertainty specifications (relative and absolute)
# - Particle pair and orbital momentum
# - Groups with channel specifications
# - Error case: Invalid keyword format

# 4. Format Detection and Conversion
# - Detect and parse default format
# - Detect and parse alternate format
# - Detect and parse keyword format
# - Convert between formats
# - Error case: Invalid/ambiguous format

# 5. Direct Parameter Creation
# - Create from minimal values
# - Create with full parameter set
# - Create with keyword format extras
# - Error case: Invalid parameter combinations
# Example usage
card = RadiusCard.from_values(effective_radius=3.2, true_radius=3.2, spin_groups=[1, 2, 3])
lines = card.to_lines(radius_format=RadiusFormat.KEYWORD)
print("\n".join(lines))
print("Format:", RadiusCard.detect_format(lines))
print("Parsed card:", RadiusCard.from_lines(lines))
102 changes: 102 additions & 0 deletions tests/unit/pleiades/sammy/parameters/test_radius.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,5 +301,107 @@ def test_invalid_keyword_format():
RadiusCard.from_lines(invalid_input.splitlines())


def test_minimal_radius_creation():
"""Test creating RadiusCard with minimal required parameters."""

print("\nTest minimal parameter creation:")
# Create with just effective radius and spin groups
card = RadiusCard.from_values(effective_radius=3.200, spin_groups=[1, 2, 3])

print(f"Card parameters: {card.parameters}")

# Verify defaults
assert card.parameters.effective_radius == pytest.approx(3.200)
assert card.parameters.true_radius == pytest.approx(3.200) # Should equal effective_radius
assert card.parameters.spin_groups == [1, 2, 3]
assert card.parameters.channel_mode == 0 # Default
assert card.parameters.vary_effective == VaryFlag.NO # Default
assert card.parameters.vary_true == VaryFlag.NO # Default
assert card.parameters.channels is None # Default


def test_full_radius_creation():
"""Test creating RadiusCard with full parameter set."""

print("\nTest full parameter creation:")
card = RadiusCard.from_values(
effective_radius=3.200,
true_radius=3.400,
spin_groups=[1, 2],
channels=[1, 2, 3],
vary_effective=VaryFlag.YES,
vary_true=VaryFlag.PUP,
)

print(f"Card parameters: {card.parameters}")

# Verify all parameters
assert card.parameters.effective_radius == pytest.approx(3.200)
assert card.parameters.true_radius == pytest.approx(3.400)
assert card.parameters.spin_groups == [1, 2]
assert card.parameters.channel_mode == 1 # Auto-set when channels provided
assert card.parameters.channels == [1, 2, 3]
assert card.parameters.vary_effective == VaryFlag.YES
assert card.parameters.vary_true == VaryFlag.PUP


def test_radius_with_extras():
"""Test creating RadiusCard with keyword format extras."""

print("\nTest creation with extras:")
card = RadiusCard.from_values(
effective_radius=3.200,
spin_groups=[1],
particle_pair="n+16O",
orbital_momentum=["all"],
relative_uncertainty=0.05,
absolute_uncertainty=0.002,
)

print(f"Card parameters: {card.parameters}")
print(
f"Card extras: particle_pair={card.particle_pair}, "
f"orbital_momentum={card.orbital_momentum}, "
f"uncertainties={card.relative_uncertainty}, {card.absolute_uncertainty}"
)

# Verify core parameters
assert card.parameters.effective_radius == pytest.approx(3.200)
assert card.parameters.true_radius == pytest.approx(3.200)
assert card.parameters.spin_groups == [1]

# Verify extras
assert card.particle_pair == "n+16O"
assert card.orbital_momentum == ["all"]
assert card.relative_uncertainty == pytest.approx(0.05)
assert card.absolute_uncertainty == pytest.approx(0.002)


def test_invalid_radius_creation():
"""Test error cases for direct parameter creation."""

print("\nTesting invalid parameter combinations:")

# Missing required parameters
with pytest.raises(TypeError) as exc_info:
RadiusCard.from_values()
print(f"Missing params error: {exc_info.value}")

# Invalid radius value
with pytest.raises(ValueError) as exc_info:
RadiusCard.from_values(effective_radius=-1.0, spin_groups=[1])
print(f"Invalid radius error: {exc_info.value}")

# Inconsistent vary flags with radii
with pytest.raises(ValueError) as exc_info:
RadiusCard.from_values(
effective_radius=3.200,
true_radius=3.400,
spin_groups=[1],
vary_true=VaryFlag.USE_FROM_PARFILE, # Can't use -1 when radii differ
)
print(f"Inconsistent flags error: {exc_info.value}")


if __name__ == "__main__":
pytest.main(["-v", __file__])

0 comments on commit 0ea0069

Please sign in to comment.