File size: 4,205 Bytes
2b9ff22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
Substrate settings for force map prediction.
Loads from config/substrate_settings.json - users can edit this file to add/modify substrates.
"""
import os
import json


def _default_config_path():
    """Default path to substrate settings config (S2F/config/substrate_settings.json)."""
    this_dir = os.path.dirname(os.path.abspath(__file__))
    project_root = os.path.dirname(this_dir)  # S2F root
    return os.path.join(project_root, 'config', 'substrate_settings.json')


def load_substrate_config(config_path=None):
    """
    Load substrate settings from config file.

    Args:
        config_path: Path to JSON config. If None, uses config/substrate_settings.json in S2F root.

    Returns:
        dict: Config with 'substrates', 'default_substrate'
    """
    path = config_path or _default_config_path()
    if not os.path.exists(path):
        raise FileNotFoundError(
            f"Substrate config not found at {path}. "
            "Create config/substrate_settings.json or pass config_path."
        )
    with open(path, 'r') as f:
        return json.load(f)


def resolve_substrate(name, config=None, config_path=None):
    """
    Resolve substrate name to a canonical substrate key.

    Args:
        name: Substrate key (e.g. 'fibroblasts_PDMS', 'PDMS_10kPa')
        config: Pre-loaded config dict. If None, loads from config_path.
        config_path: Path to config file (used if config is None).

    Returns:
        str: Canonical substrate key
    """
    if config is None:
        config = load_substrate_config(config_path)

    s = (name or '').strip()
    if not s:
        return config.get('default_substrate', 'fibroblasts_PDMS')

    substrates = config.get('substrates', {})
    s_lower = s.lower()
    for key in substrates:
        if key.lower() == s_lower:
            return key
    for key in substrates:
        if s_lower.startswith(key.lower()) or key.lower().startswith(s_lower):
            return key

    return config.get('default_substrate', 'fibroblasts_PDMS')


def get_settings_of_category(substrate_name, config=None, config_path=None):
    """
    Get pixelsize and young's modulus for a substrate.

    Args:
        substrate_name: Substrate or folder name (case-insensitive)
        config: Pre-loaded config dict. If None, loads from config_path.
        config_path: Path to config file (used if config is None).

    Returns:
        dict: {'name': str, 'pixelsize': float, 'young': float}
    """
    if config is None:
        config = load_substrate_config(config_path)

    substrate_key = resolve_substrate(substrate_name, config=config)
    substrates = config.get('substrates', {})
    default = config.get('default_substrate', 'fibroblasts_PDMS')

    if substrate_key in substrates:
        return substrates[substrate_key].copy()

    default_settings = substrates.get(default, {'name': 'Fibroblasts on PDMS', 'pixelsize': 3.0769, 'young': 6000})
    return default_settings.copy()


def list_substrates(config=None, config_path=None):
    """
    Return list of available substrate keys for user selection.

    Returns:
        list: Substrate keys
    """
    if config is None:
        config = load_substrate_config(config_path)
    return list(config.get('substrates', {}).keys())


def compute_settings_normalization(config=None, config_path=None):
    """
    Compute min-max normalization parameters from all substrates in config.

    Returns:
        dict: {'pixelsize': {'min', 'max'}, 'young': {'min', 'max'}}
    """
    if config is None:
        config = load_substrate_config(config_path)

    substrates = config.get('substrates', {})
    all_pixelsizes = [s['pixelsize'] for s in substrates.values()]
    all_youngs = [s['young'] for s in substrates.values()]

    if not all_pixelsizes or not all_youngs:
        pixelsize_min, pixelsize_max = 3.0769, 9.8138
        young_min, young_max = 1000.0, 10000.0
    else:
        pixelsize_min, pixelsize_max = min(all_pixelsizes), max(all_pixelsizes)
        young_min, young_max = min(all_youngs), max(all_youngs)

    return {
        'pixelsize': {'min': pixelsize_min, 'max': pixelsize_max},
        'young': {'min': young_min, 'max': young_max}
    }