-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathconstants.py
More file actions
145 lines (125 loc) · 5.58 KB
/
constants.py
File metadata and controls
145 lines (125 loc) · 5.58 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
Centralized constants for RF Spectrum Interference Calculator.
Single source of truth for colors, risk styles, version, and other
shared constants used across modules.
"""
VERSION = "2.2.0"
# Product type color scheme for Plotly charts
# Harmonics: warm colors (progressive severity by order)
# IMD products: blue family
PRODUCT_TYPE_COLORS = {
'2H': '#FFD700', # Gold - 2nd harmonic
'3H': '#FFA500', # Orange - 3rd harmonic
'4H': '#FF6347', # Tomato - 4th harmonic
'5H': '#DC143C', # Crimson - 5th harmonic
'IM2': '#87CEEB', # Sky Blue - IM2
'IM3': '#4169E1', # Royal Blue - IM3
'IM4': '#0000CD', # Medium Blue - IM4
'IM5': '#000080', # Navy - IM5
'IM7': '#191970', # Midnight Blue - IM7
}
# Risk level definitions: (emoji, label, css_bg, css_color)
RISK_LEVELS = {
'critical': ('🔴', 'Critical', '#ffebee', '#c62828'),
'high': ('🟠', 'High', '#fff3e0', '#ef6c00'),
'medium': ('🟡', 'Medium', '#fffde7', '#f57f17'),
'low': ('🔵', 'Low', '#e3f2fd', '#1565c0'),
'safe': ('✅', 'Safe', '#e8f5e8', '#2e7d32'),
}
# Mapping from emoji to risk level name
RISK_EMOJI_TO_NAME = {
'🔴': 'Critical',
'🟠': 'High',
'🟡': 'Medium',
'🔵': 'Low',
'✅': 'Safe',
}
# Sort order for risk levels (lower = more severe = sorted first)
RISK_SORT_ORDER = {'🔴': 0, '🟠': 1, '🟡': 2, '🔵': 3, '✅': 4}
# Row styling for risk-highlighted DataFrames
RISK_STYLES = {
'🔴': 'background-color: #ffebee; color: #c62828; font-weight: bold',
'🟠': 'background-color: #fff3e0; color: #ef6c00; font-weight: bold',
'🟡': 'background-color: #fffde7; color: #f57f17; font-weight: bold',
'🔵': 'background-color: #e3f2fd; color: #1565c0',
'✅': 'background-color: #e8f5e8; color: #2e7d32',
}
# Altair/Plotly unified risk color scales
RISK_COLOR_DOMAIN = ['Critical', 'High', 'Medium', 'Low', 'Safe']
RISK_COLOR_RANGE = ['#c62828', '#ef6c00', '#f57f17', '#1976d2', '#388e3c']
# Altair/Plotly risk color scales keyed by emoji (for donut/pie charts)
RISK_EMOJI_DOMAIN = ['🔴', '🟠', '🟡', '🔵', '✅']
RISK_EMOJI_COLOR_RANGE = ['#c62828', '#ef6c00', '#f57f17', '#1976d2', '#388e3c']
# Plotly pie chart color map (risk_level_name -> color)
RISK_PIE_COLOR_MAP = {
'Critical': '#c62828',
'High': '#ef6c00',
'Medium': '#f57f17',
'Low': '#1976d2',
'Safe': '#388e3c',
}
# Technology-dependent desensitization thresholds (dB)
# Based on receiver sensitivity requirements and link budget margins per technology
TECHNOLOGY_RISK_THRESHOLDS = {
'GNSS': {'critical': 8.0, 'high': 3.0, 'medium': 1.0, 'low': 0.5},
'GPS': {'critical': 8.0, 'high': 3.0, 'medium': 1.0, 'low': 0.5},
'PUBLIC_SAFETY': {'critical': 6.0, 'high': 3.0, 'medium': 1.0, 'low': 0.5},
'WIFI': {'critical': 6.0, 'high': 3.0, 'medium': 1.0, 'low': 0.5},
'BLE': {'critical': 6.0, 'high': 3.0, 'medium': 1.0, 'low': 0.5},
'LORA': {'critical': 3.0, 'high': 1.0, 'medium': 0.5, 'low': 0.1},
'HALOW': {'critical': 6.0, 'high': 3.0, 'medium': 1.0, 'low': 0.5},
'LTE': {'critical': 12.0, 'high': 6.0, 'medium': 3.0, 'low': 1.0},
'NR': {'critical': 12.0, 'high': 6.0, 'medium': 3.0, 'low': 1.0},
'DEFAULT': {'critical': 12.0, 'high': 6.0, 'medium': 3.0, 'low': 1.0},
}
# === RF Physics Constants (GH #24) ===
# PA class harmonic correction factors (dB)
# Ref: PA linearity characteristics by class
PA_CLASS_CORRECTIONS = {
'A': 5.0, # Class A: best linearity, highest power
'AB': 0.0, # Class AB: reference (most common)
'B': -3.0, # Class B: moderate efficiency
'C': -8.0, # Class C: high efficiency, poor linearity
}
# Harmonic engineering limits (dBc below fundamental)
# Conservative limits for typical RF systems
HARMONIC_ENGINEERING_LIMITS = {
2: -15.0, # 2nd harmonic: -15 dBc
3: -25.0, # 3rd harmonic: -25 dBc
4: -35.0, # 4th harmonic: -35 dBc
5: -45.0, # 5th harmonic: -45 dBc
}
# IMD saturation limit offset (dB above input power)
# IM products cannot exceed this relative to fundamental
IMD_SATURATION_OFFSET_DB = 10.0
# Desensitization negligibility threshold (dB below noise floor)
# Interference this far below noise floor is considered negligible
DESENSE_NEGLIGIBILITY_THRESHOLD_DB = 20.0
# Filter maximum rejection limits by type (dB)
FILTER_MAX_REJECTION = {
'butterworth': 60.0,
'chebyshev': 70.0,
'saw': 50.0,
'baw': 55.0,
}
def get_technology_thresholds(victim_code: str) -> dict:
"""Look up risk thresholds based on victim band code pattern matching."""
victim_upper = victim_code.upper()
# Check in priority order (most specific first)
if 'GNSS' in victim_upper or 'GPS' in victim_upper:
return TECHNOLOGY_RISK_THRESHOLDS['GNSS']
if any(ps in victim_upper for ps in ['B13', 'B14', 'FIRSTNET', 'PUBLIC', 'TETRA', 'P25']):
return TECHNOLOGY_RISK_THRESHOLDS['PUBLIC_SAFETY']
if 'LORA' in victim_upper:
return TECHNOLOGY_RISK_THRESHOLDS['LORA']
if 'HALOW' in victim_upper:
return TECHNOLOGY_RISK_THRESHOLDS['HALOW']
if 'WIFI' in victim_upper or 'WI-FI' in victim_upper or 'WiFi' in victim_code:
return TECHNOLOGY_RISK_THRESHOLDS['WIFI']
if 'BLE' in victim_upper or 'BLUETOOTH' in victim_upper:
return TECHNOLOGY_RISK_THRESHOLDS['BLE']
if 'NR_' in victim_upper or 'NR_N' in victim_upper:
return TECHNOLOGY_RISK_THRESHOLDS['NR']
if 'LTE' in victim_upper:
return TECHNOLOGY_RISK_THRESHOLDS['LTE']
return TECHNOLOGY_RISK_THRESHOLDS['DEFAULT']