Advanced Usage — yaflux documentation

Skip to main content
`Ctrl`+`K`

# Advanced Usage

## Analysis Inheritance

One of `yaflux`’s powerful features is its natural support for Python class inheritance. This allows you to:

- Build complex analyses by extending simpler ones

- Override and customize base analysis steps

- Create reusable analysis templates

- Share common functionality across multiple analyses

### Basic Inheritance

Let’s look at a simple example of analysis inheritance:

    import yaflux as yf

    class SimpleAnalysis(yf.Base):
        """A basic analysis pipeline."""

        @yf.step(creates="data")
        def load_data(self):
            return [i for i in range(100)]

        @yf.step(creates="proc_a", requires="data")
        def process_a(self):
            return [i * 2 for i in self.results.data]

        @yf.step(creates="proc_b", requires="proc_a")
        def process_b(self):
            return [i + 1 for i in self.results.proc_a]

    class ExtendedAnalysis(SimpleAnalysis):
        """An extended analysis that builds on SimpleAnalysis."""

        def __init__(self):
            super().__init__()

        @yf.step(creates="proc_c", requires=["proc_a", "proc_b"])
        def process_c(self):
            return [a + b for a, b in zip(self.results.proc_a, self.results.proc_b)]

    # Create and use the extended analysis
    analysis = ExtendedAnalysis()
    analysis.load_data()       # Inherited from SimpleAnalysis
    analysis.process_a()       # Inherited from SimpleAnalysis
    analysis.process_b()       # Inherited from SimpleAnalysis
    analysis.process_c()       # Defined in ExtendedAnalysis

### Inheritance Features

#### Access to Parent Steps

When you inherit from an analysis class, you get access to all of its steps. These steps:

- Maintain their original dependencies

- Can be called directly from the child class

- Are tracked in the child’s completed_steps

- Appear in the child’s available_steps

#### Step Dependencies

Dependencies work seamlessly across inheritance boundaries:

    class AdvancedAnalysis(SimpleAnalysis):
        @yf.step(creates="advanced_result", requires=["proc_a", "proc_b"])
        def advanced_step(self):
            # Can use results from parent class steps
            return [a * b for a, b in zip(
                self.results.proc_a,
                self.results.proc_b
            )]

#### Method Overriding

You can override parent steps to customize their behavior:

    class CustomAnalysis(SimpleAnalysis):
        @yf.step(creates="data")  # Same creates/requires as parent
        def load_data(self):
            # Custom implementation
            return [i * 10 for i in range(100)]

#### Multi-level Inheritance

`yaflux` supports Python’s standard multiple inheritance:

    class BaseAnalysis(yf.Base):
        @yf.step(creates="base_data")
        def load_base(self): ...

    class MixinAnalysis(yf.Base):
        @yf.step(creates="mixin_data")
        def load_mixin(self): ...

    class ComplexAnalysis(BaseAnalysis, MixinAnalysis):
        @yf.step(creates="final", requires=["base_data", "mixin_data"])
        def process_all(self): ...

#### Visualization Support

The `visualize_dependencies()` method shows the complete dependency graph, including:

- Steps from all parent classes

- Dependencies between inherited steps

- Custom steps in the child class

- Cross-inheritance dependencies

### Best Practices

When using inheritance with `yaflux`:

1. Clear Dependencies: Always explicitly declare dependencies using `requires`, even if they come from parent classes

2. Consistent Naming: Use clear, consistent names for results to avoid conflicts between parent and child classes

3. Documentation: Document dependencies on parent class steps in your docstrings:

       @yf.step(creates="final", requires=["base_data"])
       def final_step(self):
           """Process the final result.

           Requires parent class's load_base_data() to be run first.
           """
           ...

4. Modular Design: Design base classes to be independently useful while allowing for extension