# Gin-Config Strict Pattern: Reference Examples ## Example 1: Config class + loader + .gin file ### `src/conf/pipeline_conf.py` ```python 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` ```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` ```python 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` ```python 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 ```python 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) ```python # 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 ```