Skip to main content
You can leverage the TACT infrastructure to create custom adjustment models by extending the base AdjustmentMethod class. This guide will show you how to create and register your own model.

Overview

A valid adjustment method must:
  • Define required input parameters
  • Specify required data columns
  • Implement the adjustment logic
  • Register with TACT’s registry system

Creating Your Custom Model Package

The recommended way to create custom models is to keep them in your own project, separate from the TACT installation. Here’s a typical project structure:
your_project/
├── custom_adjustments/
│   ├── __init__.py
│   └── my_method.py    # Your custom method
├── examples/
│   └── use_custom_method.py
├── README.md
└── setup.py           # Optional, if you want to package your models

Creating a Custom Model

Here’s an example of creating a simple custom adjustment model:
# custom_adjustments/my_method.py

from typing import Dict, Any, List
import pandas as pd
from tact.core.base import AdjustmentMethod
from tact.core.registry import AdjustmentRegistry

@AdjustmentRegistry.register("my-custom-method")
class CustomAdjustment(AdjustmentMethod):
    """Custom turbulence intensity adjustment method.
    
    This method implements a custom adjustment algorithm for 
    turbulence intensity measurements.
    
    Parameters
    ----------
    config_path : str
        Path to configuration file
    custom_param : float
        Custom scaling factor for adjustment
    """
    
    def required_model_parameters(self) -> Dict[str, List]:
        return {
            "config_path": str,  # Path to configuration file
            "custom_param": float  # Your custom parameter
        }
    
    def required_data_columns(self) -> List[str]:
        return [
            "reference.wind_speed",
            "reference.turbulence_intensity",
            "rsd.height_1.wind_speed",
            "rsd.height_1.turbulence_intensity"
        ]
    
    def adjust(self, data: pd.DataFrame, parameters: Dict[str, Any]) -> Dict[str, Any]:
        # Validate inputs
        self.validate_parameters(parameters)
        self.validate_data(data, parameters["config_path"])
        
        # Your adjustment logic here
        adjusted_data = data.copy()
        custom_factor = parameters["custom_param"]
        
        # Example adjustment
        adjusted_data["adjusted_ti"] = data["rsd.height_1.turbulence_intensity"] * custom_factor
        
        return {
            "adjusted_data": adjusted_data,
            "metrics": {"custom_factor": custom_factor}
        }

Using Your Custom Model

To use your custom model, simply import and register it before using TACT:
# examples/use_custom_method.py

# Import your custom method
from custom_adjustments.my_method import CustomAdjustment

# Now import and use TACT as normal
from tact import TACT

# Initialize TACT
tact = TACT()

# Your custom method is now available
results = tact.adjust(
    data=data,
    method="my-custom-method",
    parameters={
        "config_path": "path/to/config.json",
        "custom_param": 1.2
    }
)
The registration system will automatically make your method available to TACT when it’s imported. You don’t need to modify the TACT package itself.

Optional: Packaging Your Models

If you want to share your custom models, you can package them:
  1. Create a setup.py:
from setuptools import setup, find_packages

setup(
    name="tact-custom-methods",
    version="0.1.0",
    packages=find_packages(),
    install_requires=[
        "tact",  # This will ensure TACT is installed
    ],
)
  1. Install your package:
pip install -e .

Implementation Guide

Class Structure

Your adjustment method class needs three core methods:
@AdjustmentRegistry.register("method-name")
class YourMethod(AdjustmentMethod):
    def required_model_parameters(self) -> Dict[str, List]:
        """Define expected configuration parameters"""
        pass

    def required_data_columns(self) -> List[str]:
        """Specify required data columns"""
        pass

    def adjust(self, data: pd.DataFrame, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """Implement the adjustment logic"""
        pass

Return Format

The adjust method should return a dictionary with:
{
    "adjusted_data": pd.DataFrame,  # Your adjusted dataset
    "metrics": {                    # Method-specific metrics
        "metric1": value1,
        "metric2": value2
    }
}

Troubleshooting

Method Registration

If your method isn’t available:
# Check registration
from tact import TACT
tact = TACT()
print(tact.list_available_methods())  # Should include your method

Data Validation

Common data issues and solutions:
# Missing columns
required = self.required_data_columns()
missing = [col for col in required if col not in data.columns]
if missing:
    raise ValueError(f"Missing columns: {missing}")

# Invalid data types
if not pd.api.types.is_numeric_dtype(data["wind_speed"]):
    raise TypeError("Wind speed must be numeric")

Performance Issues

If your method is slow:
  • Use pandas vectorized operations
  • Pre-compute repeated values
  • Consider data preprocessing
  • Profile your code with cProfile
For more examples, see the SSSF and Baseline implementations.