Skip to content

Commit

Permalink
Merge pull request #34 from lanl/sammy_param_user
Browse files Browse the repository at this point in the history
Add parser for user defined function card
  • Loading branch information
KedoKudo authored Feb 7, 2025
2 parents ab30e90 + 7f360fa commit 05ba314
Show file tree
Hide file tree
Showing 18 changed files with 1,064 additions and 68 deletions.
4 changes: 1 addition & 3 deletions src/pleiades/core/data_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,7 @@ def get_file_path(self, category: DataCategory, filename: str) -> Path:

file_path = Path(filename)
if file_path.suffix not in self._VALID_EXTENSIONS[category]:
raise ValueError(
f"Invalid file extension for {category}. " f"Allowed extensions: {self._VALID_EXTENSIONS[category]}"
)
raise ValueError(f"Invalid file extension for {category}. " f"Allowed extensions: {self._VALID_EXTENSIONS[category]}")

try:
with resources.path(f"pleiades.data.{self._get_category_path(category)}", filename) as path:
Expand Down
4 changes: 1 addition & 3 deletions src/pleiades/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,7 @@ def areal_density(self) -> float:
if self.thickness_unit == "mm":
thickness_cm /= 10.0

return (
thickness_cm * self.density * CONSTANTS.avogadro_number / self.atomic_mass.value / 1e24
) # Convert to atoms/barn
return thickness_cm * self.density * CONSTANTS.avogadro_number / self.atomic_mass.value / 1e24 # Convert to atoms/barn


# Unit conversion functions
Expand Down
4 changes: 1 addition & 3 deletions src/pleiades/sammy/backends/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ def prepare_environment(self, files: SammyFiles) -> None:
raise EnvironmentPreparationError("Docker not found in PATH")

# Verify docker image exists
result = subprocess.run(
["docker", "image", "inspect", self.config.image_name], capture_output=True, text=True
)
result = subprocess.run(["docker", "image", "inspect", self.config.image_name], capture_output=True, text=True)
if result.returncode != 0:
raise EnvironmentPreparationError(f"Docker image not found: {self.config.image_name}")

Expand Down
5 changes: 1 addition & 4 deletions src/pleiades/sammy/backends/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,7 @@ def execute_sammy(self, files: SammyFiles) -> SammyExecutionResult:

if not success:
logger.error(f"SAMMY execution failed for {execution_id}")
error_message = (
f"SAMMY execution failed with return code {process.returncode}. "
"Check console output for details."
)
error_message = f"SAMMY execution failed with return code {process.returncode}. " "Check console output for details."
else:
logger.info(f"SAMMY execution completed successfully for {execution_id}")
error_message = None
Expand Down
16 changes: 4 additions & 12 deletions src/pleiades/sammy/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ def list_available_backends() -> Dict[BackendType, bool]:
return available

@classmethod
def create_runner(
cls, backend_type: str, working_dir: Path, output_dir: Optional[Path] = None, **kwargs
) -> SammyRunner:
def create_runner(cls, backend_type: str, working_dir: Path, output_dir: Optional[Path] = None, **kwargs) -> SammyRunner:
"""
Create a SAMMY runner with the specified backend and configuration.
Expand Down Expand Up @@ -295,9 +293,7 @@ def process_config(cfg):
backend_config = config.get(backend_type, {})

# Create runner using create_runner
return cls.create_runner(
backend_type=backend_type, working_dir=working_dir, output_dir=output_dir, **backend_config
)
return cls.create_runner(backend_type=backend_type, working_dir=working_dir, output_dir=output_dir, **backend_config)

except Exception as e:
if not isinstance(e, (ConfigurationError, BackendNotAvailableError)):
Expand Down Expand Up @@ -347,9 +343,7 @@ def auto_select(
preferred = BackendType(preferred_backend.lower())
if available[preferred]:
logger.info(f"Using preferred backend: {preferred.value}")
return cls.create_runner(
backend_type=preferred.value, working_dir=working_dir, output_dir=output_dir, **kwargs
)
return cls.create_runner(backend_type=preferred.value, working_dir=working_dir, output_dir=output_dir, **kwargs)
else:
logger.warning(f"Preferred backend {preferred.value} not available, " "trying alternatives")
except ValueError:
Expand All @@ -367,9 +361,7 @@ def auto_select(
if available[backend]:
try:
logger.info(f"Attempting to use {backend.value} backend")
return cls.create_runner(
backend_type=backend.value, working_dir=working_dir, output_dir=output_dir, **kwargs
)
return cls.create_runner(backend_type=backend.value, working_dir=working_dir, output_dir=output_dir, **kwargs)
except Exception as e:
logger.warning(f"Failed to configure {backend.value} backend: {str(e)}")
errors.append(f"{backend.value}: {str(e)}")
Expand Down
3 changes: 3 additions & 0 deletions src/pleiades/sammy/parameters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from pleiades.sammy.parameters.broadening import BroadeningParameterCard # noqa: F401
from pleiades.sammy.parameters.data_reduction import DataReductionCard # noqa: F401
from pleiades.sammy.parameters.external_r import ExternalREntry # noqa: F401
from pleiades.sammy.parameters.isotope import IsotopeCard # noqa: F401
from pleiades.sammy.parameters.normalization import NormalizationBackgroundCard # noqa: F401
from pleiades.sammy.parameters.orres import ORRESCard # noqa: F401
from pleiades.sammy.parameters.paramagnetic import ParamagneticParameters # noqa: F401
from pleiades.sammy.parameters.radius import RadiusCard # noqa: F401
from pleiades.sammy.parameters.resonance import ResonanceEntry # noqa: F401
from pleiades.sammy.parameters.unused_var import UnusedCorrelatedCard # noqa: F401
from pleiades.sammy.parameters.user_resolution import UserResolutionParameters # noqa: F401
73 changes: 71 additions & 2 deletions src/pleiades/sammy/parameters/background.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,74 @@
#!/usr/bin/env python
"""Background function card for SAMMY.
"""Parsers and containers for SAMMY's Card Set 13 background function parameters.
TODO: This card will be implemented in the future.
This module implements parsers and containers for Card Set 13 background parameters
which can appear in either the PARameter or INPut file.
Format specification from Table VI B.2:
Card Set 13 contains background function parameters with distinct formats:
1. CONST - Constant background
2. EXPON - Exponential background
3. POWER - Power law background
4. EXPLN - Exponential with logarithmic terms
5. T-PNT - Point-wise linear function of time
6. E-PNT - Point-wise linear function of energy
7. TFILE - File-based time function
8. EFILE - File-based energy function
9. AETOB - Power of energy
Currently unimplemented - placeholder for future development.
"""

from enum import Enum
from typing import List

from pydantic import BaseModel, Field


class BackgroundType(str, Enum):
"""Types of background functions available."""

CONST = "CONST" # Constant background
EXPON = "EXPON" # Exponential background
POWER = "POWER" # Power law background
EXPLN = "EXPLN" # Exponential with logarithmic terms
T_PNT = "T-PNT" # Point-wise linear in time
E_PNT = "E-PNT" # Point-wise linear in energy
TFILE = "TFILE" # Time function from file
EFILE = "EFILE" # Energy function from file
AETOB = "AETOB" # Power of energy


class BackgroundParameters(BaseModel):
"""Container for Card Set 13 background function parameters.
Currently unimplemented - placeholder for future development.
Format specification from Table VI B.2:
Cols Format Variable Description
1-80 A WHAT "BACKGround functions"
Followed by one or more background function definitions.
"""

type: BackgroundType = Field(..., description="Type of background function")

@classmethod
def from_lines(cls, lines: List[str]) -> "BackgroundParameters":
"""Parse background parameters from fixed-width format lines.
Args:
lines: List of input lines for background parameters
Raises:
NotImplementedError: This class is not yet implemented
"""
raise NotImplementedError("Card Set 13 background parameter parsing is not yet implemented")

def to_lines(self) -> List[str]:
"""Convert parameters to fixed-width format lines.
Raises:
NotImplementedError: This class is not yet implemented
"""
raise NotImplementedError("Card Set 13 background parameter formatting is not yet implemented")
67 changes: 65 additions & 2 deletions src/pleiades/sammy/parameters/det_efficiency.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,68 @@
#!/usr/bin/env python
"""Detector efficiency function card for SAMMY.
"""Parsers and containers for SAMMY's Card Set 15 detector efficiency parameters.
TODO: This card will be implemented in the future.
This module implements parsers and containers for Card Set 15 detector efficiency parameters
which can appear in either the PARameter or INPut file.
Format specification from Table VI B.2:
Card Set 15 contains detector efficiency parameters for specific spin groups.
Each efficiency value can be assigned to multiple spin groups, with any unassigned
groups taking the final efficiency in the list.
Currently unimplemented - placeholder for future development.
"""

from typing import List

from pydantic import BaseModel


class DetectorEfficiencyParameters(BaseModel):
"""Container for Card Set 15 detector efficiency parameters.
Currently unimplemented - placeholder for future development.
Format specification from Table VI B.2:
Cols Format Variable Description
1-80 A WHAT "DETECtor efficiencies"
Followed by one or more efficiency definitions:
1-10 F PARDET Detector efficiency
11-20 F DELDET Uncertainty on efficiency
21-22 I IFLDET Flag to vary efficiency
23-24 I IGRDET First spin group number
25-26 I IGRDET Second spin group number
...etc.
Notes:
- If more than 29 spin groups needed, insert "-1" in cols 79-80
and continue on next line
- When more than 99 spin groups total, use 5 columns per group number
- Any spin groups not included use the final efficiency in the list
Attributes:
efficiencies: List of efficiency values
uncertainties: List of uncertainty values
flags: List of vary flags
group_assignments: List of lists containing group numbers for each efficiency
"""

@classmethod
def from_lines(cls, lines: List[str]) -> "DetectorEfficiencyParameters":
"""Parse detector efficiency parameters from fixed-width format lines.
Args:
lines: List of input lines for efficiency parameters
Raises:
NotImplementedError: This class is not yet implemented
"""
raise NotImplementedError("Card Set 15 detector efficiency parameter parsing is not yet implemented")

def to_lines(self) -> List[str]:
"""Convert parameters to fixed-width format lines.
Raises:
NotImplementedError: This class is not yet implemented
"""
raise NotImplementedError("Card Set 15 detector efficiency parameter formatting is not yet implemented")
133 changes: 131 additions & 2 deletions src/pleiades/sammy/parameters/resolution.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,134 @@
#!/usr/bin/env python
"""Resolution function card for SAMMY.
"""Parsers and containers for SAMMY's Card Set 14 resolution function parameters.
TODO: This module will be implemented in the future.
This module implements parsers and containers for Card Set 14 resolution parameters
which can appear in either the PARameter or INPut file.
Format specification from Table VI B.2:
Card Set 14 contains resolution function parameters with distinct formats:
1. RPI Resolution function
2. GEEL resolution function
3. GELINA resolution function
4. NTOF resolution function
5. User-defined resolution function
Each type has its own multi-line parameter structure.
Currently unimplemented - placeholder for future development.
"""

from enum import Enum
from typing import List

from pydantic import BaseModel, Field


class ResolutionType(str, Enum):
"""Types of resolution functions available."""

RPI = "RPI Resolution"
GEEL = "GEEL resolution"
GELINA = "GELINa resolution"
NTOF = "NTOF resolution"
USER = "USER-Defined resolution function"


class ResolutionParameters(BaseModel):
"""Container for Card Set 14 resolution function parameters.
Currently unimplemented - placeholder for future development.
Format specification from Table VI B.2:
Different resolution types have different parameter structures:
RPI Resolution:
- Optional burst width
- Optional tau parameters
- Optional lambda parameters
- Optional A1 parameters
- Optional exponential parameters
- Optional channel parameters
GEEL Resolution:
- Similar structure with different defaults
GELINA Resolution:
- Similar structure with different defaults
NTOF Resolution:
- Similar structure with different defaults
User-Defined Resolution:
- Custom file-based definition
"""

type: ResolutionType = Field(..., description="Type of resolution function")

@classmethod
def from_lines(cls, lines: List[str]) -> "ResolutionParameters":
"""Parse resolution parameters from fixed-width format lines.
Args:
lines: List of input lines for resolution parameters
Raises:
NotImplementedError: This class is not yet implemented
"""
raise NotImplementedError("Card Set 14 resolution parameter parsing is not yet implemented")

def to_lines(self) -> List[str]:
"""Convert parameters to fixed-width format lines.
Raises:
NotImplementedError: This class is not yet implemented
"""
raise NotImplementedError("Card Set 14 resolution parameter formatting is not yet implemented")


class RPIResolutionParameters(ResolutionParameters):
"""Container for RPI resolution function parameters.
Currently unimplemented - placeholder for future development.
Format includes burst width, tau, lambda, A1, exponential and channel parameters.
"""

type: ResolutionType = ResolutionType.RPI


class GEELResolutionParameters(ResolutionParameters):
"""Container for GEEL resolution function parameters.
Currently unimplemented - placeholder for future development.
Similar format to RPI with different defaults.
"""

type: ResolutionType = ResolutionType.GEEL


class GELINAResolutionParameters(ResolutionParameters):
"""Container for GELINA resolution function parameters.
Currently unimplemented - placeholder for future development.
Similar format to RPI with different defaults.
"""

type: ResolutionType = ResolutionType.GELINA


class NTOFResolutionParameters(ResolutionParameters):
"""Container for NTOF resolution function parameters.
Currently unimplemented - placeholder for future development.
Similar format to RPI with different defaults.
"""

type: ResolutionType = ResolutionType.NTOF


class UserResolutionParameters(ResolutionParameters):
"""Container for user-defined resolution function parameters.
Currently unimplemented - placeholder for future development.
Includes file-based definition capability.
"""

type: ResolutionType = ResolutionType.USER
Loading

0 comments on commit 05ba314

Please sign in to comment.