sergiev commited on
Commit
7cf8164
·
verified ·
1 Parent(s): e77ae4b

Upload folder using huggingface_hub

Browse files
Files changed (7) hide show
  1. .gitignore +177 -0
  2. Bistatic_Radar_Calc.ipynb +0 -0
  3. Bistatic_radar.jpg +0 -0
  4. README.md +3 -9
  5. app_backend.py +567 -0
  6. app_gradio.py +223 -0
  7. requirements.txt +1 -0
.gitignore ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CUSTOM
2
+ .gradio
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # UV
101
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ #uv.lock
105
+
106
+ # poetry
107
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
108
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
109
+ # commonly ignored for libraries.
110
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
111
+ #poetry.lock
112
+
113
+ # pdm
114
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
115
+ #pdm.lock
116
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
117
+ # in version control.
118
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
119
+ .pdm.toml
120
+ .pdm-python
121
+ .pdm-build/
122
+
123
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
124
+ __pypackages__/
125
+
126
+ # Celery stuff
127
+ celerybeat-schedule
128
+ celerybeat.pid
129
+
130
+ # SageMath parsed files
131
+ *.sage.py
132
+
133
+ # Environments
134
+ .env
135
+ .venv
136
+ env/
137
+ venv/
138
+ ENV/
139
+ env.bak/
140
+ venv.bak/
141
+
142
+ # Spyder project settings
143
+ .spyderproject
144
+ .spyproject
145
+
146
+ # Rope project settings
147
+ .ropeproject
148
+
149
+ # mkdocs documentation
150
+ /site
151
+
152
+ # mypy
153
+ .mypy_cache/
154
+ .dmypy.json
155
+ dmypy.json
156
+
157
+ # Pyre type checker
158
+ .pyre/
159
+
160
+ # pytype static type analyzer
161
+ .pytype/
162
+
163
+ # Cython debug symbols
164
+ cython_debug/
165
+
166
+ # PyCharm
167
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
168
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
169
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
170
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
171
+ #.idea/
172
+
173
+ # Ruff stuff:
174
+ .ruff_cache/
175
+
176
+ # PyPI configuration file
177
+ .pypirc
Bistatic_Radar_Calc.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
Bistatic_radar.jpg ADDED
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: Radar Image Quality
3
- emoji: 🔥
4
- colorFrom: yellow
5
- colorTo: green
6
  sdk: gradio
7
- sdk_version: 5.25.2
8
- app_file: app.py
9
- pinned: false
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: radar_image_quality
3
+ app_file: app_gradio.py
 
 
4
  sdk: gradio
5
+ sdk_version: 5.23.3
 
 
6
  ---
 
 
app_backend.py ADDED
@@ -0,0 +1,567 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Модуль для расчета параметров РЛС по модели бистатической РЛС
3
+ Автор кода: Владислав Калинников
4
+ """
5
+
6
+ import math as mt
7
+ from typing import List
8
+
9
+ # скорость света в вакууме, м|с
10
+ C = 299792458
11
+ # постоянная Больцмана, Дж/К
12
+ BOLTZMANN = 1.38 * 10 ** (-23)
13
+ # температура предатчика/приемника, К
14
+ RADAR_TEMPERATURE = 290
15
+
16
+ # ширина антенны, м
17
+ # ANTENNA_WIDTH = 0.08
18
+ # длина антенны, м
19
+ # ANTENNA_LENGTH = 0.25
20
+ # коэффициент усиления антенны, дБ
21
+ # ANTENNA_GAIN = 14
22
+ # длина волны, м
23
+ # WAVELENGTH = 0.032
24
+ # пиковая мощность, ВТ
25
+ # PEAK_POWER = 10
26
+ # полоса пропускания, МГц
27
+ # BANDWIDTH = 1000
28
+ # шум-фактор, дБ
29
+ # NOISE_FACTOR = 3
30
+
31
+ # коэффициент заполнения
32
+ # q_fill = 0.08
33
+ # угол поляризации, град. 0 - горизонтальная поляризация, 90 - вертикальная поляризация
34
+ # POLATIZATION_TILT_ANGLE = 0
35
+
36
+
37
+ # функция определяет координаты углов области пересечения проекций на земную поверхность главных лепестков
38
+ # point_name - имя точки (A,B,C,D), по умолчанию равно A
39
+ # h - высота полета в м, uav_interval - размер базы между РЛС, м
40
+ # psi_t - угол курса оси главного лепестка ДНА на излучение (по часовой стрелке>0, против часовой <0), град
41
+ # psi_r - угол курса оси главного лепестка ДНА на прием (по часовой стрелке>0, против часовой <0), град
42
+ def footprint_corner_crd(
43
+ point_name: str,
44
+ h: float,
45
+ uav_interval: float,
46
+ psi_t: float,
47
+ psi_r: float,
48
+ wavelength: float,
49
+ antenna_length: float,
50
+ ):
51
+ # угловой размер главного главного лепестка по азимуту
52
+ theta = wavelength / antenna_length
53
+ # угол курса главного лепестка ДНА на излучение в радианах
54
+ psi_t = psi_t * mt.pi / 180
55
+ # угол курса главного лепестка ДНА на прием в радианах
56
+ psi_r = psi_r * mt.pi / 180
57
+ if psi_r - psi_t > theta:
58
+ # начальные значения поправок угла курса точки относительно РЛС1 и РЛС2
59
+ dpsi_1 = 0.1
60
+ dpsi_2 = 0.1
61
+ # начальные обновленные значения поправок угла курса точки относительно РЛС1 и РЛС2
62
+ dpsi_1upd = 0
63
+ dpsi_2upd = 0
64
+ # коэффициенты для расчета углов места и углов курса точки относительно РЛС1 и РЛС2
65
+ k1 = 1
66
+ k2 = 1
67
+ if point_name == "B":
68
+ k1 = 1
69
+ k2 = -1
70
+ elif point_name == "C":
71
+ k1 = -1
72
+ k2 = -1
73
+ elif point_name == "D":
74
+ k1 = -1
75
+ k2 = 1
76
+ # определение углов места и углов курса точки относительно РЛС1 и РЛС2 методом последовательных приближений
77
+ while abs(dpsi_1upd - dpsi_1) > 0.01 or abs(dpsi_2upd - dpsi_2) > 0.01:
78
+ dpsi_1 = dpsi_1upd
79
+ dpsi_2 = dpsi_2upd
80
+ psi_1 = psi_t + dpsi_1
81
+ psi_2 = psi_r + dpsi_2
82
+ phi_1 = mt.atan(uav_interval / h * mt.cos(psi_2) / mt.sin(psi_2 - psi_1))
83
+ phi_2 = mt.atan(uav_interval / h * mt.cos(psi_1) / mt.sin(psi_2 - psi_1))
84
+ if (
85
+ abs(mt.sin(theta / 2) / mt.sin(phi_1)) > 1
86
+ or abs(mt.sin(theta / 2) / mt.sin(phi_2)) > 1
87
+ ):
88
+ return "none"
89
+ dpsi_1upd = k1 * mt.asin(mt.sin(theta / 2) / mt.sin(phi_1))
90
+ dpsi_2upd = k2 * mt.asin(mt.sin(theta / 2) / mt.sin(phi_2))
91
+ # итоговые значения углов места и углов курса точки относительно РЛС1 и РЛС2
92
+ dpsi_1 = dpsi_1upd
93
+ dpsi_2 = dpsi_2upd
94
+ psi_1 = psi_t + dpsi_1
95
+ psi_2 = psi_r + dpsi_2
96
+ phi_1 = mt.atan(uav_interval / h * mt.cos(psi_2) / mt.sin(psi_2 - psi_1))
97
+ phi_2 = mt.atan(uav_interval / h * mt.cos(psi_1) / mt.sin(psi_2 - psi_1))
98
+ # координаты точки
99
+ x = h * mt.tan(phi_2) * mt.cos(psi_2)
100
+ y = h * mt.tan(phi_2) * mt.sin(psi_2)
101
+ return [x, y]
102
+ else:
103
+ return "none"
104
+
105
+
106
+ # функция определяет водность облаков, г|м3
107
+ # cloud_thickness - толщина облаков
108
+ def cloud_liquid_water_content(cloud_thickness: float) -> float:
109
+ if cloud_thickness != 0:
110
+ W = 0.132574 * (cloud_thickness / 1000) ** 2.30215
111
+ return W / cloud_thickness * 1000
112
+ else:
113
+ return 0
114
+
115
+
116
+ # функция определяет ординтаты точек пересечения выпуклого многоугольника (polygon) с лучом, имеющем ординату x
117
+ def polygon_cross_points(polygon: List[float], x: float) -> List[float]:
118
+ y1 = "none"
119
+ y2 = "none"
120
+ for i in range(0, len(polygon[0])):
121
+ if i < len(polygon[0]) - 1:
122
+ k = i + 1
123
+ else:
124
+ k = 0
125
+ if x >= min(polygon[0][i], polygon[0][k]) and x <= max(
126
+ polygon[0][i], polygon[0][k]
127
+ ):
128
+ if polygon[0][i] != polygon[0][k]:
129
+ if y1 == "none":
130
+ y1 = (polygon[1][k] - polygon[1][i]) / (
131
+ polygon[0][k] - polygon[0][i]
132
+ ) * (x - polygon[0][i]) + polygon[1][i]
133
+ else:
134
+ y2 = (polygon[1][k] - polygon[1][i]) / (
135
+ polygon[0][k] - polygon[0][i]
136
+ ) * (x - polygon[0][i]) + polygon[1][i]
137
+ else:
138
+ y1 = polygon[1][i]
139
+ y2 = polygon[1][k]
140
+ return [min(y1, y2), max(y1, y2)]
141
+
142
+
143
+ # функция определяет координаты углов РЛИ
144
+ # h - высота полета в м, uav_interval - размер базы между РЛС, м
145
+ # psi_t - угол курса оси главного лепестка ДНА на излучение (по часовой стрелке>0, против часовой <0), град
146
+ # psi_r - угол курса оси главного лепестка ДНА на прием (по часовой стрелке>0, против часовой <0), град
147
+ def frame_corner_crd(
148
+ h: float,
149
+ uav_interval: float,
150
+ psi_t: float,
151
+ psi_r: float,
152
+ wavelength: float,
153
+ antenna_length: float,
154
+ ):
155
+ # координаты области пересечения проекций на земную поверхность главных лепестков
156
+ crd_A = footprint_corner_crd(
157
+ point_name="A",
158
+ h=h,
159
+ uav_interval=uav_interval,
160
+ psi_t=psi_t,
161
+ psi_r=psi_r,
162
+ wavelength=wavelength,
163
+ antenna_length=antenna_length,
164
+ )
165
+ crd_B = footprint_corner_crd(
166
+ point_name="B",
167
+ h=h,
168
+ uav_interval=uav_interval,
169
+ psi_t=psi_t,
170
+ psi_r=psi_r,
171
+ wavelength=wavelength,
172
+ antenna_length=antenna_length,
173
+ )
174
+ crd_C = footprint_corner_crd(
175
+ point_name="C",
176
+ h=h,
177
+ uav_interval=uav_interval,
178
+ psi_t=psi_t,
179
+ psi_r=psi_r,
180
+ wavelength=wavelength,
181
+ antenna_length=antenna_length,
182
+ )
183
+ crd_D = footprint_corner_crd(
184
+ point_name="D",
185
+ h=h,
186
+ uav_interval=uav_interval,
187
+ psi_t=psi_t,
188
+ psi_r=psi_r,
189
+ wavelength=wavelength,
190
+ antenna_length=antenna_length,
191
+ )
192
+ if crd_A != "none" and crd_B != "none" and crd_C != "none" and crd_D != "none":
193
+ polygon = [
194
+ [crd_A[0], crd_B[0], crd_C[0], crd_D[0]],
195
+ [crd_A[1], crd_B[1], crd_C[1], crd_D[1]],
196
+ ]
197
+ # максимальное и минимальное значение абсциисы области пересечения проекций на земную поверхность главных лепестков
198
+ x_min = min(polygon[0])
199
+ x_max = max(polygon[0])
200
+ # точность оценики координат углов РЛИ
201
+ accuracy = 20
202
+ # число итераций для поиска максимальной площади РЛИ
203
+ N = 1 + int((x_max - x_min) / accuracy)
204
+ # шаг по оси абсцисс при поиске максимальной плоащади РЛИ
205
+ dx = (x_max - x_min) / N
206
+ # начальные значения коориднат углов и площади РЛИ
207
+ s_upd = 0
208
+ # dq_upd = 100
209
+ x1_upd = "none"
210
+ x2_upd = "none"
211
+ y1_upd = "none"
212
+ y2_upd = "none"
213
+ # поиск макисальной площади и углов РЛИ
214
+ for i in range(0, N - 1):
215
+ x1 = x_min + i * dx
216
+ for j in range(i + 1, N):
217
+ x2 = x_min + j * dx
218
+ y11 = polygon_cross_points(polygon, x1)[0]
219
+ y12 = polygon_cross_points(polygon, x1)[1]
220
+ y21 = polygon_cross_points(polygon, x2)[0]
221
+ y22 = polygon_cross_points(polygon, x2)[1]
222
+ if y11 >= y21 and y12 <= y22:
223
+ y1 = y11
224
+ y2 = y12
225
+ elif y11 <= y21 and y12 >= y21 and y12 <= y22:
226
+ y1 = y21
227
+ y2 = y12
228
+ elif y11 <= y22 and y11 >= y21 and y12 >= y22:
229
+ y1 = y11
230
+ y2 = y22
231
+ elif y11 <= y21 and y12 >= y22:
232
+ y1 = y21
233
+ y2 = y22
234
+ else:
235
+ y1 = "none"
236
+ y2 = "none"
237
+ if y1 != "none" and y2 != "none":
238
+ s = (x2 - x1) * (y2 - y1)
239
+ # dq = abs((y2-y1)/(x2-x1)-q)
240
+ if s > s_upd: # dq < dq_upd:
241
+ s_upd = s
242
+ # dq_upd = dq
243
+ x1_upd = x1
244
+ x2_upd = x2
245
+ y1_upd = y1
246
+ y2_upd = y2
247
+ # возврат массива координат углов РЛК (точек T1,T2,T3,T4)
248
+ return [[x1_upd, x1_upd, x2_upd, x2_upd], [y1_upd, y2_upd, y2_upd, y1_upd]]
249
+ else:
250
+ return "none"
251
+
252
+
253
+ # параметры a1, a2, a3 модели Кулемина для расчета УЭПР разных типов подстилающих поверхностей, дБ
254
+ kulemin_parameters = {
255
+ "лес летом": [-20, 10, 6],
256
+ "лес зимой": [-40, 10, 6],
257
+ "луг высокотравный": [-21, 10, 6],
258
+ "луг низкотравный": [-28, 10, 6],
259
+ "пашня": [-37, 18, 15],
260
+ "снег": [-34, 25, 15],
261
+ }
262
+
263
+
264
+ # функция определеяет УЭПР поверхности в дБ согласно модели Кулемина
265
+ # surface_type - тип подстилающей поверхности (пашня, снег и т.д.), phi - угол падения, град
266
+ # если задан неизвестный тип подстилающей поверхности, функция вернет значение -20 дБ
267
+ def kulemin_specific_rcs(surface_type, phi, wavelength):
268
+ # частота зондирования в ГГц
269
+ f = C / wavelength * 10 ** (-9)
270
+ # угол скольжения в град
271
+ slip = 90 - phi
272
+ if kulemin_parameters.get(surface_type) != None:
273
+ a1, a2, a3 = kulemin_parameters[surface_type]
274
+ return a1 + a2 * mt.log(slip / 20, 10) + a3 * mt.log(f / 10, 10)
275
+ else:
276
+ return -20
277
+
278
+
279
+ # функция определяет коэффициент погонного ослабления в облаке, дБ/км/(г/м3)
280
+ def itu_cloud_attenuation(wavelength):
281
+ # частота зондирования в ГГц
282
+ f = C / wavelength * 10 ** (-9)
283
+ theta = 300 / 273.15
284
+ eps0 = 77.66 + 103.3 * (theta - 1)
285
+ eps1 = 0.0671 * eps0
286
+ eps2 = 3.52
287
+ fp = 20.20 - 146 * (theta - 1) + 316 * (theta - 1) ** 2
288
+ fs = 39.8 * fp
289
+ eps_prime = f * (eps0 - eps1) / fp / (1 + (f / fp) ** 2) + f * (
290
+ eps1 - eps2
291
+ ) / fs / (1 + (f / fs) ** 2)
292
+ eps_double_prime = (
293
+ (eps0 - eps1) / (1 + (f / fp) ** 2) + (eps1 - eps2) / (1 + (f / fs) ** 2) + eps2
294
+ )
295
+ nabla = (2 + eps_prime) / eps_double_prime
296
+ return 0.819 * f / eps_double_prime / (1 + nabla**2)
297
+
298
+
299
+ # параметры kh, ah, kv, av модели погонного ослабления в дожде МСЭ-R P.838-3 для частот 7 - 12 ГГц
300
+ itu_rain_parameters = {
301
+ 7: [0.001915, 1.4810, 0.001425, 1.4745],
302
+ 8: [0.004115, 1.3905, 0.003450, 1.3797],
303
+ 9: [0.007535, 1.3155, 0.006691, 1.2895],
304
+ 10: [0.012170, 1.2571, 0.011290, 1.2156],
305
+ 11: [0.017720, 1.2140, 0.017310, 1.1617],
306
+ 12: [0.023860, 1.1825, 0.024550, 1.1216],
307
+ }
308
+
309
+ # классификация погодных условий по интенсивности осадков, мм/ч
310
+ rain_rate_classes = {
311
+ "ясно": 0,
312
+ "слабый дождь": 5,
313
+ "умеренный дождь": 12,
314
+ "сильный дождь": 30,
315
+ "ливень": 40,
316
+ }
317
+
318
+
319
+ # функция определяет коэффициент погонного ослабления в дожде в дБ/км для диапазона X согласно модели МСЭ-R P.838-3
320
+ # rain_rate - интенсивность дождя в мм/ч, phi- угол падения, град
321
+ # если длина волны зондирования лежит не в диапазоне X, функция вернет 0
322
+ def itu_rain_attenuation(
323
+ rain_rate: float, phi: float, wavelength: float, polarization_tilt_angle: float
324
+ ) -> float:
325
+ # частота зондирования в ГГц
326
+ f = C / wavelength * 10 ** (-9)
327
+ # угол скольжения в радианах
328
+ slip = (90 - phi) * mt.pi / 180
329
+ # угол поляризации в радианах
330
+ tilt = polarization_tilt_angle * mt.pi / 180
331
+ # целочисленные значения частот вокруг частоты зондирования
332
+ f1 = int(f)
333
+ f2 = int(f) + 1
334
+ if (itu_rain_parameters.get(f1) != None) and (itu_rain_parameters.get(f2) != None):
335
+ # параметры модели для частоты f1
336
+ kh1 = itu_rain_parameters[f1][0]
337
+ ah1 = itu_rain_parameters[f1][1]
338
+ kv1 = itu_rain_parameters[f1][2]
339
+ av1 = itu_rain_parameters[f1][3]
340
+ # ��араметры модели для частоты f2
341
+ kh2 = itu_rain_parameters[f2][0]
342
+ ah2 = itu_rain_parameters[f2][1]
343
+ kv2 = itu_rain_parameters[f2][2]
344
+ av2 = itu_rain_parameters[f2][3]
345
+ # интерполяция параметров модели на частоту зондирования f
346
+ kh = kh1 + (kh2 - kh1) / (f2 - f1) * (f - f1)
347
+ ah = ah1 + (ah2 - ah1) / (f2 - f1) * (f - f1)
348
+ kv = kv1 + (kv2 - kv1) / (f2 - f1) * (f - f1)
349
+ av = av1 + (av2 - av1) / (f2 - f1) * (f - f1)
350
+ # параметры модели для заданной поляризации
351
+ k = (kh + kv + (kh - kv) * (mt.cos(slip)) ** 2 * mt.cos(2 * tilt)) / 2
352
+ a = (
353
+ (
354
+ kh * ah
355
+ + kv * av
356
+ + (kh * ah - kv * av) * (mt.cos(slip)) ** 2 * mt.cos(2 * tilt)
357
+ )
358
+ / 2
359
+ / k
360
+ )
361
+ return k * (rain_rate) ** a
362
+ else:
363
+ return 0
364
+
365
+
366
+ # входные параметры модели:
367
+ # v - скорость полета, м/с
368
+ # h - высота полета, м
369
+ # uav_interval - размер базы между РЛС, м
370
+ # psi_t - угол курса оси главного лепестка ДНА на излучение (по часовой стрелке>0, против часовой <0), град
371
+ # psi_r - угол курса оси главного лепестка ДНА на прием (по часовой стрелке>0, против часовой <0), град
372
+ # srcs - УЭПР фона, дБ или тип поверхности по модели Кулемина
373
+ # cloud_base - высота нижней границы облаков, м
374
+ # cloud_thickness - толщина облаков, м
375
+ # rain_rate - интенсивность дождя, мм/ч
376
+
377
+ # выходные параметры модели:
378
+ # dx - предельное разрешение по горизонтальной дальности в центре РЛК, м
379
+ # dy - предельное разрешение по азимуту в центре РЛК, м
380
+ # snr - отношение сигнал/шум фона в центре РЛК, дБ
381
+ # tau - длина импульса, с
382
+ # tau_echo - длина эхо-сигнала, с
383
+ # t_repeat - период повторения импульсов, с
384
+ # t_synthesis_max - максимальное время синтеза апертуры, с
385
+
386
+
387
+ def bistatic_radar_model(
388
+ v: float,
389
+ h: float,
390
+ uav_interval: float,
391
+ psi_t: float,
392
+ psi_r: float,
393
+ srcs: str | float,
394
+ cloud_base: float,
395
+ cloud_thickness: float,
396
+ rain_rate: float,
397
+ q_fill: float,
398
+ bandwidth: float,
399
+ wavelength: float,
400
+ antenna_gain: float,
401
+ antenna_length: float,
402
+ noise_factor: float,
403
+ peak_power: float,
404
+ polarization_tilt_angle: float,
405
+ ):
406
+ # координаты РЛС1
407
+ x1 = 0
408
+ y1 = uav_interval
409
+ # координаты РЛС2
410
+ x2 = 0
411
+ y2 = 0
412
+ # коодинаты точки T1
413
+ frame_crd = frame_corner_crd(
414
+ h=h,
415
+ uav_interval=uav_interval,
416
+ psi_t=psi_t,
417
+ psi_r=psi_r,
418
+ wavelength=wavelength,
419
+ antenna_length=antenna_length,
420
+ )
421
+ if frame_crd != "none":
422
+ x_t1 = frame_crd[0][0]
423
+ y_t1 = frame_crd[1][0]
424
+ # коодинаты точки T2
425
+ x_t2 = frame_crd[0][1]
426
+ y_t2 = frame_crd[1][1]
427
+ # коодинаты точки T3
428
+ x_t3 = frame_crd[0][2]
429
+ y_t3 = frame_crd[1][2]
430
+ # коодинаты точки T4
431
+ x_t4 = frame_crd[0][3]
432
+ y_t4 = frame_crd[1][3]
433
+ # коодинаты центра РЛК
434
+ xo = (x_t2 + x_t3) / 2
435
+ yo = (y_t1 + y_t2) / 2
436
+ # наклонные дальности от РЛС1 до углов и центра РЛК
437
+ r1_t1 = mt.sqrt((x_t1 - x1) ** 2 + (y_t1 - y1) ** 2 + h**2)
438
+ r1_t2 = mt.sqrt((x_t2 - x1) ** 2 + (y_t1 - y1) ** 2 + h**2)
439
+ r1_t3 = mt.sqrt((x_t3 - x1) ** 2 + (y_t1 - y1) ** 2 + h**2)
440
+ r1_t4 = mt.sqrt((x_t4 - x1) ** 2 + (y_t1 - y1) ** 2 + h**2)
441
+ r1_o = mt.sqrt((xo - x1) ** 2 + (yo - y1) ** 2 + h**2)
442
+ # наклонные дальности от РЛС2 до углов и центра РЛК
443
+ r2_t1 = mt.sqrt((x_t1 - x2) ** 2 + (y_t1 - y2) ** 2 + h**2)
444
+ r2_t2 = mt.sqrt((x_t2 - x2) ** 2 + (y_t1 - y2) ** 2 + h**2)
445
+ r2_t3 = mt.sqrt((x_t3 - x2) ** 2 + (y_t1 - y2) ** 2 + h**2)
446
+ r2_t4 = mt.sqrt((x_t4 - x2) ** 2 + (y_t1 - y2) ** 2 + h**2)
447
+ r2_o = mt.sqrt((xo - x2) ** 2 + (yo - y2) ** 2 + h**2)
448
+ # угол падения импульса от РЛС1 в центр РЛК
449
+ phi1_o = mt.atan(h / r1_o) * 180 / mt.pi
450
+ # угол отражения импульса от центра РЛК к РЛС2
451
+ phi2_o = mt.atan(h / r2_o) * 180 / mt.pi
452
+ # модуль градиента от суммы наклонных дальностей от РЛС1 �� РЛС2 до центра РЛК
453
+ grad_r = mt.sqrt((xo / r1_o + xo / r2_o) ** 2 + (yo / r1_o + yo / r2_o) ** 2)
454
+ # модуль градиента от суммы доплеровских частот на трассах от РЛС1 до центра РЛК и от центра РЛК до РЛС2
455
+ grad_f = (
456
+ v
457
+ / wavelength
458
+ * mt.sqrt(
459
+ (1 / r1_o + 1 / r2_o - xo**2 / r1_o**3 - xo**2 / r2_o**3) ** 2
460
+ + (xo * yo / r1_o**3 + xo * yo / r2_o**3) ** 2
461
+ )
462
+ )
463
+ # длина импульса
464
+ tau = min(r1_t1 + r2_t1, r1_t2 + r2_t2) / C
465
+ # длина эхо-сигнала
466
+ tau_echo = (
467
+ tau
468
+ + max(r1_t3 + r2_t3, r1_t4 + r2_t4) / C
469
+ - min(r1_t1 + r2_t1, r1_t2 + r2_t2) / C
470
+ )
471
+ # период повторения импульсов
472
+ t_repeat = tau / q_fill
473
+ # максимальный коэффициент сжатия
474
+ k_compression_max = bandwidth * 1000000 * tau
475
+ # максимальное время синтеза апертуры
476
+ t_synthesis_max = 2 * (x_t3 - x_t2) / v
477
+ # максимальное число когерентных импульсов
478
+ n_coh_max = 1 + int(t_synthesis_max / t_repeat)
479
+ # разрешение по горизонтальной дальности
480
+ dx = C * tau / k_compression_max / grad_r
481
+ # разрешение по азимуту
482
+ dy = 1 / t_synthesis_max / grad_f
483
+ # УЭПР фона
484
+ if type(srcs) == str:
485
+ srcs = kulemin_specific_rcs(surface_type=srcs, phi=(phi1_o + phi2_o) / 2, wavelength=wavelength)
486
+ # ЭПР точечного отражателя фона
487
+ sigma = 10 ** (srcs / 10) * dx * dy
488
+ # эффективная площадь антенны
489
+ antenna_area = 10 ** (antenna_gain / 10) * wavelength**2 / 4 / mt.pi
490
+ # мощность эхо-сигнала от центра РЛК
491
+ p_echo = (
492
+ peak_power
493
+ * 10 ** (antenna_gain / 10)
494
+ * antenna_area
495
+ / (4 * mt.pi * r1_o * r2_o) ** 2
496
+ * sigma
497
+ * k_compression_max
498
+ * n_coh_max
499
+ )
500
+ # мощность шума
501
+ p_noise = (
502
+ BOLTZMANN
503
+ * 10 ** (noise_factor / 10)
504
+ * RADAR_TEMPERATURE
505
+ * bandwidth
506
+ * 1000000
507
+ )
508
+ # отношение сигнал/шум без учета погоды
509
+ snr = 10 * mt.log(p_echo / p_noise, 10)
510
+ # протяженность наклонных дальностей в облаках и дожде, км
511
+ if cloud_thickness != 0:
512
+ cloud_path1 = (
513
+ r1_o
514
+ / 1000
515
+ * (min(h, cloud_base + cloud_thickness) - min(h, cloud_base))
516
+ / h
517
+ )
518
+ cloud_path2 = (
519
+ r2_o
520
+ / 1000
521
+ * (min(h, cloud_base + cloud_thickness) - min(h, cloud_base))
522
+ / h
523
+ )
524
+ rain_path1 = r1_o / 1000 * min(h, cloud_base) / h
525
+ rain_path2 = r2_o / 1000 * min(h, cloud_base) / h
526
+ else:
527
+ cloud_path1 = 0
528
+ cloud_path2 = 0
529
+ rain_path1 = 0
530
+ rain_path2 = 0
531
+ # водность облаков
532
+ w = cloud_liquid_water_content(cloud_thickness=cloud_thickness)
533
+ # ослабление в облаках по модели МСЭ-R P.840-7
534
+ cloud_att1 = itu_cloud_attenuation(wavelength=wavelength) * w * cloud_path1
535
+ cloud_att2 = itu_cloud_attenuation(wavelength=wavelength) * w * cloud_path2
536
+ # ослабление в дожде по модели МСЭ-R P.838-3
537
+ rain_att1 = (
538
+ itu_rain_attenuation(
539
+ rain_rate=rain_rate,
540
+ phi=phi1_o,
541
+ wavelength=wavelength,
542
+ polarization_tilt_angle=polarization_tilt_angle,
543
+ )
544
+ * rain_path1
545
+ )
546
+ rain_att2 = (
547
+ itu_rain_attenuation(
548
+ rain_rate=rain_rate,
549
+ phi=phi2_o,
550
+ wavelength=wavelength,
551
+ polarization_tilt_angle=polarization_tilt_angle,
552
+ )
553
+ * rain_path2
554
+ )
555
+ # отношение сигнал/шум с учетом погодных условий
556
+ snr = snr - cloud_att1 - cloud_att2 - rain_att1 - rain_att2
557
+ return {
558
+ "dx": dx,
559
+ "dy": dy,
560
+ "snr": snr,
561
+ "tau": tau,
562
+ "tau_echo": tau_echo,
563
+ "t_repeat": t_repeat,
564
+ "t_synthesis_max": t_synthesis_max,
565
+ }
566
+ else:
567
+ return "none"
app_gradio.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import app_backend
3
+
4
+ BG_CHOICES = ("Задать значение", "Из модели Кулемина")
5
+ KULEMIN = {
6
+ "лес летом": [-20, 10, 6],
7
+ "лес зимой": [-40, 10, 6],
8
+ "луг высокотравный": [-21, 10, 6],
9
+ "луг низкотравный": [-28, 10, 6],
10
+ "пашня": [-37, 18, 15],
11
+ "снег": [-34, 25, 15],
12
+ }
13
+
14
+ def main(i):
15
+ out = app_backend.bistatic_radar_model(
16
+ v=i[speed],
17
+ h=i[height],
18
+ uav_interval=i[uav_interval],
19
+ psi_t=i[psit],
20
+ psi_r=i[psir],
21
+ srcs=i[bg_type] if i[bg_mode] == BG_CHOICES[1] else i[bg_value],
22
+ cloud_base=i[cloud_base],
23
+ cloud_thickness=i[cloud_thickness],
24
+ rain_rate=i[rain_intensivity],
25
+ q_fill=i[q_fill],
26
+ bandwidth=i[bandwidth],
27
+ wavelength=i[wavelength],
28
+ antenna_gain=i[antenna_gain],
29
+ antenna_length=i[antenna_length],
30
+ noise_factor=i[noise_factor],
31
+ peak_power=i[peak_power],
32
+ polarization_tilt_angle=0 if i[polar_type] == "H" else 90,
33
+ )
34
+ return out["dx"], out["dy"], out["snr"]
35
+
36
+
37
+
38
+
39
+ def update_visibility(radio):
40
+ if radio == BG_CHOICES[0]:
41
+ return gr.update(visible=True), gr.update(visible=False)
42
+ return gr.update(visible=False), gr.update(visible=True)
43
+
44
+
45
+ input_set = set()
46
+ # Create the Gradio pyinterface
47
+ with gr.Blocks(
48
+ title="РЛС-калькулятор"
49
+ ) as demo: # css="footer{display:none !important}"
50
+ gr.Markdown(
51
+ "# Оценка параметров качества радиолокационного изображения двухпозиционной РЛС"
52
+ )
53
+ with gr.Row():
54
+ with gr.Column():
55
+ gr.Markdown(
56
+ """
57
+ Калькулятор позволяет рассчитать параметры качества радиолокационного изображения (РЛИ), формируемого в передней зоне обзора двухпозиционной полуактивной радиолокационной станции (РЛС) авиационного базирования.
58
+
59
+ В рассматриваемой схеме главный лепесток диаграммы направленности антенны (ДНА) на излучение активной компоненты РЛС подсвечивает область в передней зоне обзора, тогда как главный лепесток ДНА на приём направлен так, чтобы существовала возможность фиксации отраженного эхо-сигнала. Формирование РЛИ происходит на пересечении областей земной поверхности в пределах главных лепестков ДНА на излучение и на приём.
60
+
61
+ Каждая одиночная РЛС использует одинаковую передающую и приёмную антенны, вследствие чего равны угловые размеры главных лепестков на излучение и на приём.
62
+ """
63
+ )
64
+ with gr.Column():
65
+ gr.HTML(
66
+ "<img src='gradio_api/file=./Bistatic_radar.jpg' alt='Схема БВС и РЛС' width=640>"
67
+ )
68
+ # v - скорость полета, h - высота полета, dl - размер базы между РЛС, psir - угол курса оси главного лепестка ДНА на приём
69
+ with gr.Row():
70
+ with gr.Column():
71
+ gr.Markdown("## Параметры бортовой РЛС")
72
+ psir = gr.Slider(
73
+ minimum=10,
74
+ maximum=60,
75
+ value=30,
76
+ step=0.1,
77
+ label="Угол курса оси главного лепестка ДНА на приём, град",
78
+ )
79
+ input_set.add(psir)
80
+ psit = gr.Slider(
81
+ minimum=-60,
82
+ maximum=-10,
83
+ value=-30,
84
+ step=0.1,
85
+ label="Угол курса оси главного лепестка ДНА на излучение, град",
86
+ )
87
+ input_set.add(psit)
88
+ antenna_length = gr.Slider(
89
+ minimum=0.05,
90
+ maximum=0.3,
91
+ value=0.1,
92
+ step=0.01,
93
+ label="Длина антенны, м",
94
+ )
95
+ input_set.add(antenna_length)
96
+ antenna_gain = gr.Slider(
97
+ minimum=5,
98
+ maximum=20,
99
+ value=10,
100
+ step=0.1,
101
+ label="Коэффициент усиления антенны, дБ",
102
+ )
103
+ input_set.add(antenna_gain)
104
+ wavelength = gr.Slider(
105
+ minimum=0.02,
106
+ maximum=0.04,
107
+ value=0.03,
108
+ step=0.001,
109
+ label="Длина волны, м",
110
+ )
111
+ input_set.add(wavelength)
112
+ peak_power = gr.Slider(
113
+ minimum=1,
114
+ maximum=10,
115
+ value=5,
116
+ step=0.1,
117
+ label="Пиковая мощность, ВТ",
118
+ )
119
+ input_set.add(peak_power)
120
+ bandwidth = gr.Slider(
121
+ minimum=500,
122
+ maximum=2000,
123
+ value=1000,
124
+ step=1,
125
+ label="Полоса пропускания, МГц",
126
+ )
127
+ input_set.add(bandwidth)
128
+ noise_factor = gr.Slider(
129
+ minimum=1,
130
+ maximum=3,
131
+ value=2,
132
+ step=0.01,
133
+ label="Шум-фактор, дБ",
134
+ )
135
+ input_set.add(noise_factor)
136
+
137
+ gr.Markdown("## Параметры режима работы РЛС")
138
+ with gr.Row():
139
+ q_fill = gr.Slider(
140
+ minimum=0.05,
141
+ maximum=0.25,
142
+ value=0.1,
143
+ step=0.001,
144
+ label="Коэффициент заполнения",
145
+ )
146
+ input_set.add(q_fill)
147
+ polar_type = gr.Radio(
148
+ choices=["H", "V"], label="Тип поляризации", value="H"
149
+ )
150
+ input_set.add(polar_type)
151
+ with gr.Column():
152
+ gr.Markdown("## Траекторные параметры")
153
+ speed = gr.Slider(
154
+ minimum=5,
155
+ maximum=30,
156
+ value=20,
157
+ step=0.1,
158
+ label="Скорость полёта, м/с",
159
+ )
160
+ input_set.add(speed)
161
+ height = gr.Slider(
162
+ minimum=200,
163
+ maximum=2000,
164
+ value=1000,
165
+ step=1,
166
+ label="Высота полёта, м",
167
+ )
168
+ input_set.add(height)
169
+ uav_interval = gr.Slider(
170
+ minimum=200,
171
+ maximum=2000,
172
+ value=1000,
173
+ step=1,
174
+ label="Длина базы между РЛС, м",
175
+ )
176
+ input_set.add(uav_interval)
177
+ gr.Markdown("## Параметры условий местности")
178
+ cloud_base = gr.Slider(
179
+ minimum=0,
180
+ maximum=1500,
181
+ value=750,
182
+ step=1,
183
+ label="Высота нижней границы облаков, м",
184
+ )
185
+ input_set.add(cloud_base)
186
+ cloud_thickness = gr.Slider(
187
+ minimum=0, maximum=6000, value=3000, step=1, label="Толщина облаков, м"
188
+ )
189
+ input_set.add(cloud_thickness)
190
+ rain_intensivity = gr.Slider(
191
+ minimum=0,
192
+ maximum=80,
193
+ value=40,
194
+ step=1,
195
+ label="Интенсивность дождя, мм/ч",
196
+ )
197
+ input_set.add(rain_intensivity)
198
+ bg_mode = gr.Radio(choices=BG_CHOICES, label="УЭПР фона поверхности")
199
+ input_set.add(bg_mode)
200
+ bg_value = gr.Slider(
201
+ minimum=-30, maximum=10, value=0, step=0.1, label="", visible=False
202
+ )
203
+ input_set.add(bg_value)
204
+ bg_type = gr.Dropdown(choices=KULEMIN.keys(), visible=False, label="")
205
+ input_set.add(bg_type)
206
+
207
+ with gr.Column():
208
+ gr.Markdown("## Предельные параметры качества РЛИ")
209
+ # Output displays
210
+ output_hr = gr.Number(
211
+ label="Разрешение по горизонтальной дальности, м",
212
+ precision=3,
213
+ )
214
+ output_ar = gr.Number(label="Разрешение по азимуту, м", precision=3)
215
+ output_snr = gr.Number(label="Отношение сигнал/шум, дБ", precision=1)
216
+
217
+ # Set up the event listeners for real-time updates
218
+ output_list = [output_hr, output_ar, output_snr]
219
+ bg_mode.change(update_visibility, inputs=bg_mode, outputs=[bg_value, bg_type])
220
+ for inp in input_set:
221
+ inp.change(fn=main, inputs=input_set, outputs=output_list)
222
+ if __name__ == "__main__":
223
+ demo.launch(share=True, allowed_paths=["."])
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio