Files
style_code_lisad/Gin-Config Strict Pattern Reference Examples.md
Pikaliov 3278322a17 Initial commit — gin-config strict-pattern coding standard
Code-style guide and reference patterns for DL/CV research at the
ЛИСАД laboratory (NADEZHDA / SOFIA CVGL projects).

Files:
- Стандарт написания кода для DL CV исследований (CVGL).md
- Правила написания Python-кода (Gin-Config Strict Pattern).md
- REQUIREMENTS_GIN_STYLE.md
- Gin-Config Strict Pattern Reference Examples.md
- Переход от argparse и dataclass к gin-config.md
- gin-parse.md
- Рекомендуемые gin-config категории.md
- config_loader_reference.py
- README.md (this commit)
- .gitignore (Python artifacts)
2026-04-27 17:12:38 +03:00

7.8 KiB

Gin-Config Strict Pattern: Reference Examples

Example 1: Config class + loader + .gin file

src/conf/pipeline_conf.py


from __future__ import annotations

  

import gin

  
  

@gin.configurable

class PipelineConfig:

    """Configuration for the augmentation pipeline stages and output."""

  

    def __init__(

        self,

        input_root: str = "/data/UAV-GeoLoc",

        output_root: str = "/data/UAV-GeoLoc-aug",

        stages: list[str] | None = None,

        save_npy: bool = True,

        save_vis: bool = True,

        save_concat: bool = False,

        resume: bool = True,

        subset: str | None = None,

        source: str | None = None,

        log_level: str = "INFO",

    ) -> None:

        self.input_root = input_root

        self.output_root = output_root

        self.stages = stages or ["depth", "edges", "segmentation"]

        self.save_npy = save_npy

        self.save_vis = save_vis

        self.save_concat = save_concat

        self.resume = resume

        self.subset = subset

        self.source = source

        self.log_level = log_level

  
  

def get_pipeline_cfg(path2cfg: str) -> PipelineConfig:

    """Load pipeline config from gin file.

  

    Args:

        path2cfg: Path to config directory (with trailing slash).

  

    Returns:

        Instantiated PipelineConfig with values from gin file.

    """

    gin.parse_config_file(f"{path2cfg}pipeline.gin")

    return PipelineConfig()

in/config_files/pipeline.gin


# Pipeline configuration

PipelineConfig.input_root = '/data/UAV-GeoLoc'

PipelineConfig.output_root = '/data/UAV-GeoLoc-aug'

PipelineConfig.stages = ['depth', 'edges', 'segmentation']

PipelineConfig.save_npy = True

PipelineConfig.save_vis = True

PipelineConfig.save_concat = False

PipelineConfig.resume = True

PipelineConfig.subset = 'Rot'

PipelineConfig.source = None

PipelineConfig.log_level = 'INFO'

Example 2: Model config with fallback IDs

src/conf/models_conf.py


from __future__ import annotations

  

import gin

  
  

@gin.configurable

class ModelsConfig:

    """Model identifiers and fallback strategy."""

  

    def __init__(

        self,

        depth_model_id: str = "depth-anything/DA3-BASE",

        depth_fallback_id: str = "depth-anything/Depth-Anything-V2-Large-hf",

        seg_model_type: str = "segearth-ov3",

        seg_fallback_type: str = "segformer-b5",

        seg_fallback_id: str = "nvidia/segformer-b5-finetuned-ade-640-640",

    ) -> None:

        self.depth_model_id = depth_model_id

        self.depth_fallback_id = depth_fallback_id

        self.seg_model_type = seg_model_type

        self.seg_fallback_type = seg_fallback_type

        self.seg_fallback_id = seg_fallback_id

  
  

def get_models_cfg(path2cfg: str) -> ModelsConfig:

    """Load models config from gin file."""

    gin.parse_config_file(f"{path2cfg}models.gin")

    return ModelsConfig()

Example 3: Main entry point

src/main.py


from __future__ import annotations

  

import gc

import logging

import time

from pathlib import Path

  

import numpy as np

import torch

  

from conf.pipeline_conf import get_pipeline_cfg, PipelineConfig

from conf.hardware_conf import get_hardware_cfg, HardwareConfig

from conf.models_conf import get_models_cfg, ModelsConfig

from conf.input_conf import get_input_cfg, InputConfig

from conf.seg_conf import get_seg_cfg, SegConfig

  

logger = logging.getLogger(__name__)

  
  

def get_proj_dir() -> str:

    """Return project root directory with trailing slash."""

    return str(Path(__file__).resolve().parent.parent) + "/"

  
  

def run_pipeline(

    pipeline_conf: PipelineConfig,

    hardware_conf: HardwareConfig,

    models_conf: ModelsConfig,

    input_conf: InputConfig,

    seg_conf: SegConfig,

) -> None:

    """Execute the full augmentation pipeline.

  

    Args:

        pipeline_conf: Pipeline stage configuration.

        hardware_conf: GPU hardware profile.

        models_conf: Model identifiers and fallbacks.

        input_conf: Image preprocessing parameters.

        seg_conf: Segmentation prompts and thresholds.

    """

    torch.manual_seed(42)

    np.random.seed(42)

  

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

  

    for stage in pipeline_conf.stages:

        logger.info("Running stage: %s", stage)

        t0 = time.perf_counter()

  

        if stage == "depth":

            run_depth_stage(pipeline_conf, hardware_conf, models_conf, input_conf, device)

        elif stage == "edges":

            run_edges_stage(pipeline_conf, input_conf)

        elif stage == "segmentation":

            run_seg_stage(pipeline_conf, hardware_conf, models_conf, seg_conf, device)

  

        logger.info("Stage %s done in %.1f s", stage, time.perf_counter() - t0)

  
  

def main() -> None:

    """Entry point: load gin configs and run pipeline."""

    proj_dir = get_proj_dir()

    path2cfg = f"{proj_dir}in/config_files/"

  

    pipeline_conf = get_pipeline_cfg(path2cfg)

    hardware_conf = get_hardware_cfg(path2cfg)

    models_conf = get_models_cfg(path2cfg)

    input_conf = get_input_cfg(path2cfg)

    seg_conf = get_seg_cfg(path2cfg)

  

    run_pipeline(pipeline_conf, hardware_conf, models_conf, input_conf, seg_conf)

  
  

if __name__ == "__main__":

    main()

Example 4: Model loading with config object


from __future__ import annotations

  

import gc

import logging

from typing import Any

  

import torch

import torch.nn as nn

  

logger = logging.getLogger(__name__)

  
  

def load_depth_model(

    models_conf: ModelsConfig,

    hardware_conf: HardwareConfig,

    device: torch.device,

) -> nn.Module:

    """Load depth estimation model based on config.

  

    Args:

        models_conf: Model IDs from gin config.

        hardware_conf: FP16 and device settings.

        device: Target CUDA device.

  

    Returns:

        Loaded depth model on device.

    """

    model_id = models_conf.depth_model_id

    logger.info("Loading depth: %s", model_id)

  

    try:

        from depth_anything_3 import DepthAnything3

        model = DepthAnything3.from_pretrained(model_id)

        if hardware_conf.use_fp16:

            model = model.half()

        return model.to(device).eval()

    except ImportError:

        logger.warning("DA3 not found, falling back to %s", models_conf.depth_fallback_id)

        from transformers import AutoModelForDepthEstimation

        dtype = torch.float16 if hardware_conf.use_fp16 else torch.float32

        model = AutoModelForDepthEstimation.from_pretrained(

            models_conf.depth_fallback_id, torch_dtype=dtype,

        )

        return model.to(device).eval()

  
  

def unload_model(model: Any) -> None:

    """Free GPU memory after model use."""

    del model

    gc.collect()

    if torch.cuda.is_available():

        torch.cuda.empty_cache()

Anti-patterns (DO NOT)


# BAD: dataclass + gin

@gin.configurable

@dataclass  # ← FORBIDDEN

class Config:

    param: int = 1

  

# BAD: argparse

parser = argparse.ArgumentParser()  # ← FORBIDDEN, use gin

  

# BAD: global gin state inside function

def process():

    val = gin.query_parameter("Config.param")  # ← FORBIDDEN

  

# BAD: gin.constant / macros

LEARNING_RATE = gin.constant("lr", 0.001)  # ← FORBIDDEN

  

# BAD: hardcoded model ID

model = AutoModel.from_pretrained("depth-anything/DA3-BASE")  # ← move to gin