astrox-python 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,552 @@
1
+ """Coverage analysis functions and coverage-owned grid fragments."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+ from dataclasses import dataclass
7
+ from numbers import Integral, Real
8
+ from typing import Any, TypeAlias
9
+
10
+ from astrox import components
11
+ from astrox._http import raw
12
+
13
+ __all__ = [
14
+ "CbLatLonGrid",
15
+ "CoverageGrid",
16
+ "GlobalGrid",
17
+ "LatitudeGrid",
18
+ "LatLonGrid",
19
+ "cb_lat_lon_grid",
20
+ "compute",
21
+ "coverage_by_asset",
22
+ "global_grid",
23
+ "grid_points",
24
+ "lat_lon_grid",
25
+ "latitude_grid",
26
+ "percent_coverage",
27
+ ]
28
+
29
+
30
+ def _include_if_supplied(payload: dict[str, Any], wire_key: str, value: Any) -> None:
31
+ if value is not None:
32
+ payload[wire_key] = value
33
+
34
+
35
+ def _real_number(value: float, *, parameter: str) -> float:
36
+ if not isinstance(value, Real) or isinstance(value, bool):
37
+ raise TypeError(f"{parameter} must be a number")
38
+ return value
39
+
40
+
41
+ def _optional_real(value: float | None, *, parameter: str) -> float | None:
42
+ if value is None:
43
+ return None
44
+ return _real_number(value, parameter=parameter)
45
+
46
+
47
+ def _optional_bool(value: bool | None, *, parameter: str) -> bool | None:
48
+ if value is None:
49
+ return None
50
+ if not isinstance(value, bool):
51
+ raise TypeError(f"{parameter} must be a bool")
52
+ return value
53
+
54
+
55
+ def _optional_string(value: str | None, *, parameter: str) -> str | None:
56
+ if value is None:
57
+ return None
58
+ if not isinstance(value, str):
59
+ raise TypeError(f"{parameter} must be a string")
60
+ return value
61
+
62
+
63
+ def _optional_asset_count(value: int | None, *, parameter: str) -> int | None:
64
+ if value is None:
65
+ return None
66
+ if not isinstance(value, Integral) or isinstance(value, bool):
67
+ raise TypeError(f"{parameter} must be an integer")
68
+ return int(value)
69
+
70
+
71
+ def _include_grid_options(
72
+ payload: dict[str, Any],
73
+ *,
74
+ central_body: str | None,
75
+ resolution_deg: float | None,
76
+ height_m: float | None,
77
+ use_cell_surface_area_for_weight: bool | None,
78
+ ) -> None:
79
+ _include_if_supplied(payload, "CentralBodyName", central_body)
80
+ _include_if_supplied(payload, "Resolution", resolution_deg)
81
+ _include_if_supplied(payload, "Height", height_m)
82
+ _include_if_supplied(
83
+ payload,
84
+ "UseCellSurfaceAreaForWeight",
85
+ use_cell_surface_area_for_weight,
86
+ )
87
+
88
+
89
+ @dataclass(frozen=True, kw_only=True)
90
+ class GlobalGrid:
91
+ """Global central-body coverage grid definition."""
92
+
93
+ central_body: str | None = None
94
+ resolution_deg: float | None = None
95
+ height_m: float | None = None
96
+ use_cell_surface_area_for_weight: bool | None = None
97
+
98
+ def to_wire(self) -> dict[str, Any]:
99
+ """Lower to an ASTROX Global coverage grid fragment."""
100
+ payload: dict[str, Any] = {"$type": "Global"}
101
+ _include_grid_options(
102
+ payload,
103
+ central_body=self.central_body,
104
+ resolution_deg=self.resolution_deg,
105
+ height_m=self.height_m,
106
+ use_cell_surface_area_for_weight=self.use_cell_surface_area_for_weight,
107
+ )
108
+ return payload
109
+
110
+
111
+ @dataclass(frozen=True, kw_only=True)
112
+ class LatitudeGrid:
113
+ """Latitude-bounded central-body coverage grid definition."""
114
+
115
+ min_latitude_deg: float
116
+ max_latitude_deg: float
117
+ central_body: str | None = None
118
+ resolution_deg: float | None = None
119
+ height_m: float | None = None
120
+ use_cell_surface_area_for_weight: bool | None = None
121
+
122
+ def to_wire(self) -> dict[str, Any]:
123
+ """Lower to an ASTROX LatitudeBounds coverage grid fragment."""
124
+ payload: dict[str, Any] = {
125
+ "$type": "LatitudeBounds",
126
+ "MinLatitude": self.min_latitude_deg,
127
+ "MaxLatitude": self.max_latitude_deg,
128
+ }
129
+ _include_grid_options(
130
+ payload,
131
+ central_body=self.central_body,
132
+ resolution_deg=self.resolution_deg,
133
+ height_m=self.height_m,
134
+ use_cell_surface_area_for_weight=self.use_cell_surface_area_for_weight,
135
+ )
136
+ return payload
137
+
138
+
139
+ @dataclass(frozen=True, kw_only=True)
140
+ class LatLonGrid:
141
+ """Latitude/longitude-bounded central-body coverage grid definition."""
142
+
143
+ min_latitude_deg: float
144
+ max_latitude_deg: float
145
+ min_longitude_deg: float
146
+ max_longitude_deg: float
147
+ central_body: str | None = None
148
+ resolution_deg: float | None = None
149
+ height_m: float | None = None
150
+ use_cell_surface_area_for_weight: bool | None = None
151
+
152
+ def to_wire(self) -> dict[str, Any]:
153
+ """Lower to an ASTROX LatLonBounds coverage grid fragment."""
154
+ payload: dict[str, Any] = {
155
+ "$type": "LatLonBounds",
156
+ "MinLatitude": self.min_latitude_deg,
157
+ "MaxLatitude": self.max_latitude_deg,
158
+ "MinLongitude": self.min_longitude_deg,
159
+ "MaxLongitude": self.max_longitude_deg,
160
+ }
161
+ _include_grid_options(
162
+ payload,
163
+ central_body=self.central_body,
164
+ resolution_deg=self.resolution_deg,
165
+ height_m=self.height_m,
166
+ use_cell_surface_area_for_weight=self.use_cell_surface_area_for_weight,
167
+ )
168
+ return payload
169
+
170
+
171
+ @dataclass(frozen=True, kw_only=True)
172
+ class CbLatLonGrid:
173
+ """Server-traceable CbLatLonBounds coverage grid definition."""
174
+
175
+ min_latitude_deg: float
176
+ max_latitude_deg: float
177
+ min_longitude_deg: float
178
+ max_longitude_deg: float
179
+ central_body: str | None = None
180
+ resolution_deg: float | None = None
181
+ height_m: float | None = None
182
+ use_cell_surface_area_for_weight: bool | None = None
183
+
184
+ def to_wire(self) -> dict[str, Any]:
185
+ """Lower to an ASTROX CbLatLonBounds coverage grid fragment."""
186
+ payload: dict[str, Any] = {
187
+ "$type": "CbLatLonBounds",
188
+ "MinLatitude": self.min_latitude_deg,
189
+ "MaxLatitude": self.max_latitude_deg,
190
+ "MinLongitude": self.min_longitude_deg,
191
+ "MaxLongitude": self.max_longitude_deg,
192
+ }
193
+ _include_grid_options(
194
+ payload,
195
+ central_body=self.central_body,
196
+ resolution_deg=self.resolution_deg,
197
+ height_m=self.height_m,
198
+ use_cell_surface_area_for_weight=self.use_cell_surface_area_for_weight,
199
+ )
200
+ return payload
201
+
202
+
203
+ CoverageGrid: TypeAlias = GlobalGrid | LatitudeGrid | LatLonGrid | CbLatLonGrid
204
+ _GRID_TYPES = (GlobalGrid, LatitudeGrid, LatLonGrid, CbLatLonGrid)
205
+ _SENSOR_TYPES = (components.ConicSensor, components.RectangularSensor)
206
+ _CONSTRAINT_TYPES = (
207
+ components.ElevationConstraint,
208
+ components.RangeConstraint,
209
+ components.AzElMaskConstraint,
210
+ )
211
+
212
+
213
+ def global_grid(
214
+ *,
215
+ central_body: str | None = None,
216
+ resolution_deg: float | None = None,
217
+ height_m: float | None = None,
218
+ use_cell_surface_area_for_weight: bool | None = None,
219
+ ) -> GlobalGrid:
220
+ """Create a global coverage grid definition."""
221
+ return GlobalGrid(
222
+ central_body=_optional_string(central_body, parameter="central_body"),
223
+ resolution_deg=_optional_real(resolution_deg, parameter="resolution_deg"),
224
+ height_m=_optional_real(height_m, parameter="height_m"),
225
+ use_cell_surface_area_for_weight=_optional_bool(
226
+ use_cell_surface_area_for_weight,
227
+ parameter="use_cell_surface_area_for_weight",
228
+ ),
229
+ )
230
+
231
+
232
+ def latitude_grid(
233
+ *,
234
+ min_latitude_deg: float,
235
+ max_latitude_deg: float,
236
+ central_body: str | None = None,
237
+ resolution_deg: float | None = None,
238
+ height_m: float | None = None,
239
+ use_cell_surface_area_for_weight: bool | None = None,
240
+ ) -> LatitudeGrid:
241
+ """Create a latitude-bounded coverage grid definition."""
242
+ return LatitudeGrid(
243
+ min_latitude_deg=_real_number(
244
+ min_latitude_deg,
245
+ parameter="min_latitude_deg",
246
+ ),
247
+ max_latitude_deg=_real_number(
248
+ max_latitude_deg,
249
+ parameter="max_latitude_deg",
250
+ ),
251
+ central_body=_optional_string(central_body, parameter="central_body"),
252
+ resolution_deg=_optional_real(resolution_deg, parameter="resolution_deg"),
253
+ height_m=_optional_real(height_m, parameter="height_m"),
254
+ use_cell_surface_area_for_weight=_optional_bool(
255
+ use_cell_surface_area_for_weight,
256
+ parameter="use_cell_surface_area_for_weight",
257
+ ),
258
+ )
259
+
260
+
261
+ def lat_lon_grid(
262
+ *,
263
+ min_latitude_deg: float,
264
+ max_latitude_deg: float,
265
+ min_longitude_deg: float,
266
+ max_longitude_deg: float,
267
+ central_body: str | None = None,
268
+ resolution_deg: float | None = None,
269
+ height_m: float | None = None,
270
+ use_cell_surface_area_for_weight: bool | None = None,
271
+ ) -> LatLonGrid:
272
+ """Create a latitude/longitude-bounded coverage grid definition."""
273
+ return LatLonGrid(
274
+ min_latitude_deg=_real_number(
275
+ min_latitude_deg,
276
+ parameter="min_latitude_deg",
277
+ ),
278
+ max_latitude_deg=_real_number(
279
+ max_latitude_deg,
280
+ parameter="max_latitude_deg",
281
+ ),
282
+ min_longitude_deg=_real_number(
283
+ min_longitude_deg,
284
+ parameter="min_longitude_deg",
285
+ ),
286
+ max_longitude_deg=_real_number(
287
+ max_longitude_deg,
288
+ parameter="max_longitude_deg",
289
+ ),
290
+ central_body=_optional_string(central_body, parameter="central_body"),
291
+ resolution_deg=_optional_real(resolution_deg, parameter="resolution_deg"),
292
+ height_m=_optional_real(height_m, parameter="height_m"),
293
+ use_cell_surface_area_for_weight=_optional_bool(
294
+ use_cell_surface_area_for_weight,
295
+ parameter="use_cell_surface_area_for_weight",
296
+ ),
297
+ )
298
+
299
+
300
+ def cb_lat_lon_grid(
301
+ *,
302
+ min_latitude_deg: float,
303
+ max_latitude_deg: float,
304
+ min_longitude_deg: float,
305
+ max_longitude_deg: float,
306
+ central_body: str | None = None,
307
+ resolution_deg: float | None = None,
308
+ height_m: float | None = None,
309
+ use_cell_surface_area_for_weight: bool | None = None,
310
+ ) -> CbLatLonGrid:
311
+ """Create a server-traceable CbLatLonBounds coverage grid definition."""
312
+ return CbLatLonGrid(
313
+ min_latitude_deg=_real_number(
314
+ min_latitude_deg,
315
+ parameter="min_latitude_deg",
316
+ ),
317
+ max_latitude_deg=_real_number(
318
+ max_latitude_deg,
319
+ parameter="max_latitude_deg",
320
+ ),
321
+ min_longitude_deg=_real_number(
322
+ min_longitude_deg,
323
+ parameter="min_longitude_deg",
324
+ ),
325
+ max_longitude_deg=_real_number(
326
+ max_longitude_deg,
327
+ parameter="max_longitude_deg",
328
+ ),
329
+ central_body=_optional_string(central_body, parameter="central_body"),
330
+ resolution_deg=_optional_real(resolution_deg, parameter="resolution_deg"),
331
+ height_m=_optional_real(height_m, parameter="height_m"),
332
+ use_cell_surface_area_for_weight=_optional_bool(
333
+ use_cell_surface_area_for_weight,
334
+ parameter="use_cell_surface_area_for_weight",
335
+ ),
336
+ )
337
+
338
+
339
+ def grid_points(
340
+ *,
341
+ grid: CoverageGrid,
342
+ text: str | None = None,
343
+ ) -> dict[str, Any]:
344
+ """Generate coverage grid points from a grid definition."""
345
+ payload: dict[str, Any] = {"Grid": _grid_to_wire(grid)}
346
+ _include_if_supplied(payload, "Text", _optional_string(text, parameter="text"))
347
+ return raw.post("/Coverage/GetGridPoints", json=payload)
348
+
349
+
350
+ def compute(
351
+ *,
352
+ start: str,
353
+ stop: str,
354
+ grid: CoverageGrid,
355
+ assets: Sequence[components.Entity],
356
+ minimum_assets: int | None = None,
357
+ exactly_assets: int | None = None,
358
+ grid_point_sensor: components.EntitySensor | None = None,
359
+ grid_point_constraints: Sequence[components.Constraint] | None = None,
360
+ include_asset_access_results: bool | None = None,
361
+ include_coverage_points: bool | None = None,
362
+ step_s: float | None = None,
363
+ description: str | None = None,
364
+ ) -> dict[str, Any]:
365
+ """Compute coverage over a grid for one or more entity assets."""
366
+ payload = _coverage_input_payload(
367
+ start=start,
368
+ stop=stop,
369
+ grid=grid,
370
+ assets=assets,
371
+ minimum_assets=minimum_assets,
372
+ exactly_assets=exactly_assets,
373
+ grid_point_sensor=grid_point_sensor,
374
+ grid_point_constraints=grid_point_constraints,
375
+ include_asset_access_results=include_asset_access_results,
376
+ include_coverage_points=include_coverage_points,
377
+ step_s=step_s,
378
+ description=description,
379
+ )
380
+ return raw.post("/Coverage/ComputeCoverage", json=payload)
381
+
382
+
383
+ def percent_coverage(
384
+ *,
385
+ start: str,
386
+ stop: str,
387
+ grid: CoverageGrid,
388
+ assets: Sequence[components.Entity],
389
+ minimum_assets: int | None = None,
390
+ exactly_assets: int | None = None,
391
+ grid_point_sensor: components.EntitySensor | None = None,
392
+ grid_point_constraints: Sequence[components.Constraint] | None = None,
393
+ include_asset_access_results: bool | None = None,
394
+ include_coverage_points: bool | None = None,
395
+ step_s: float | None = None,
396
+ description: str | None = None,
397
+ ) -> dict[str, Any]:
398
+ """Compute the ASTROX percent-coverage report."""
399
+ payload = _coverage_input_payload(
400
+ start=start,
401
+ stop=stop,
402
+ grid=grid,
403
+ assets=assets,
404
+ minimum_assets=minimum_assets,
405
+ exactly_assets=exactly_assets,
406
+ grid_point_sensor=grid_point_sensor,
407
+ grid_point_constraints=grid_point_constraints,
408
+ include_asset_access_results=include_asset_access_results,
409
+ include_coverage_points=include_coverage_points,
410
+ step_s=step_s,
411
+ description=description,
412
+ )
413
+ return raw.post("/Coverage/Report/PercentCoverage", json=payload)
414
+
415
+
416
+ def coverage_by_asset(
417
+ *,
418
+ start: str,
419
+ stop: str,
420
+ grid: CoverageGrid,
421
+ assets: Sequence[components.Entity],
422
+ minimum_assets: int | None = None,
423
+ exactly_assets: int | None = None,
424
+ grid_point_sensor: components.EntitySensor | None = None,
425
+ grid_point_constraints: Sequence[components.Constraint] | None = None,
426
+ include_asset_access_results: bool | None = None,
427
+ include_coverage_points: bool | None = None,
428
+ step_s: float | None = None,
429
+ description: str | None = None,
430
+ ) -> dict[str, Any]:
431
+ """Compute the ASTROX coverage-by-asset report."""
432
+ payload = _coverage_input_payload(
433
+ start=start,
434
+ stop=stop,
435
+ grid=grid,
436
+ assets=assets,
437
+ minimum_assets=minimum_assets,
438
+ exactly_assets=exactly_assets,
439
+ grid_point_sensor=grid_point_sensor,
440
+ grid_point_constraints=grid_point_constraints,
441
+ include_asset_access_results=include_asset_access_results,
442
+ include_coverage_points=include_coverage_points,
443
+ step_s=step_s,
444
+ description=description,
445
+ )
446
+ return raw.post("/Coverage/Report/CoverageByAsset", json=payload)
447
+
448
+
449
+ def _coverage_input_payload(
450
+ *,
451
+ start: str,
452
+ stop: str,
453
+ grid: CoverageGrid,
454
+ assets: Sequence[components.Entity],
455
+ minimum_assets: int | None,
456
+ exactly_assets: int | None,
457
+ grid_point_sensor: components.EntitySensor | None,
458
+ grid_point_constraints: Sequence[components.Constraint] | None,
459
+ include_asset_access_results: bool | None,
460
+ include_coverage_points: bool | None,
461
+ step_s: float | None,
462
+ description: str | None,
463
+ ) -> dict[str, Any]:
464
+ payload: dict[str, Any] = {
465
+ "Start": start,
466
+ "Stop": stop,
467
+ "Grid": _grid_to_wire(grid),
468
+ "Assets": _assets_to_wire(assets),
469
+ }
470
+ _include_if_supplied(
471
+ payload,
472
+ "Description",
473
+ _optional_string(description, parameter="description"),
474
+ )
475
+ _include_resource_count_rule(
476
+ payload,
477
+ minimum_assets=minimum_assets,
478
+ exactly_assets=exactly_assets,
479
+ )
480
+ if grid_point_sensor is not None:
481
+ payload["GridPointSensor"] = _sensor_to_wire(grid_point_sensor)
482
+ if grid_point_constraints is not None:
483
+ payload["GridPointConstraints"] = _constraints_to_wire(grid_point_constraints)
484
+ _include_if_supplied(
485
+ payload,
486
+ "ContainAssetAccessResults",
487
+ _optional_bool(
488
+ include_asset_access_results,
489
+ parameter="include_asset_access_results",
490
+ ),
491
+ )
492
+ _include_if_supplied(
493
+ payload,
494
+ "ContainCoveragePoints",
495
+ _optional_bool(include_coverage_points, parameter="include_coverage_points"),
496
+ )
497
+ _include_if_supplied(payload, "Step", _optional_real(step_s, parameter="step_s"))
498
+ return payload
499
+
500
+
501
+ def _include_resource_count_rule(
502
+ payload: dict[str, Any],
503
+ *,
504
+ minimum_assets: int | None,
505
+ exactly_assets: int | None,
506
+ ) -> None:
507
+ minimum = _optional_asset_count(minimum_assets, parameter="minimum_assets")
508
+ exactly = _optional_asset_count(exactly_assets, parameter="exactly_assets")
509
+ if minimum is not None and exactly is not None:
510
+ raise ValueError("minimum_assets and exactly_assets cannot both be supplied")
511
+ if minimum is not None:
512
+ payload["FilterType"] = "AtLeastN"
513
+ payload["NumberOfAssets"] = minimum
514
+ if exactly is not None:
515
+ payload["FilterType"] = "ExactlyN"
516
+ payload["NumberOfAssets"] = exactly
517
+
518
+
519
+ def _grid_to_wire(grid: CoverageGrid) -> dict[str, Any]:
520
+ if not isinstance(grid, _GRID_TYPES):
521
+ raise TypeError("grid must be an astrox.coverage grid value")
522
+ return grid.to_wire()
523
+
524
+
525
+ def _assets_to_wire(values: Sequence[components.Entity]) -> list[dict[str, Any]]:
526
+ if isinstance(values, (str, bytes)) or not isinstance(values, Sequence):
527
+ raise TypeError("assets must be a sequence of astrox.components.Entity values")
528
+ items = tuple(values)
529
+ if not all(isinstance(item, components.Entity) for item in items):
530
+ raise TypeError("assets must be a sequence of astrox.components.Entity values")
531
+ return [item.to_wire() for item in items]
532
+
533
+
534
+ def _sensor_to_wire(sensor: components.EntitySensor) -> dict[str, Any]:
535
+ if not isinstance(sensor, _SENSOR_TYPES):
536
+ raise TypeError("grid_point_sensor must be an astrox.components sensor value")
537
+ return sensor.to_wire()
538
+
539
+
540
+ def _constraints_to_wire(
541
+ values: Sequence[components.Constraint],
542
+ ) -> list[dict[str, Any]]:
543
+ if isinstance(values, (str, bytes)) or not isinstance(values, Sequence):
544
+ raise TypeError(
545
+ "grid_point_constraints must be a sequence of astrox.components constraint values"
546
+ )
547
+ items = tuple(values)
548
+ if not all(isinstance(item, _CONSTRAINT_TYPES) for item in items):
549
+ raise TypeError(
550
+ "grid_point_constraints must be a sequence of astrox.components constraint values"
551
+ )
552
+ return [item.to_wire() for item in items]
@@ -0,0 +1,125 @@
1
+ """Shared lowering helpers for Coverage FOM metric modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+ from typing import Any
7
+
8
+ from astrox import components
9
+ from astrox._http import raw
10
+
11
+ from ._core import (
12
+ CoverageGrid,
13
+ _coverage_input_payload,
14
+ _include_if_supplied,
15
+ _optional_string,
16
+ )
17
+
18
+
19
+ def post_coverage_input(
20
+ endpoint: str,
21
+ *,
22
+ start: str,
23
+ stop: str,
24
+ grid: CoverageGrid,
25
+ assets: Sequence[components.Entity],
26
+ minimum_assets: int | None = None,
27
+ exactly_assets: int | None = None,
28
+ grid_point_sensor: components.EntitySensor | None = None,
29
+ grid_point_constraints: Sequence[components.Constraint] | None = None,
30
+ include_asset_access_results: bool | None = None,
31
+ include_coverage_points: bool | None = None,
32
+ step_s: float | None = None,
33
+ description: str | None = None,
34
+ ) -> dict[str, Any]:
35
+ payload = _coverage_input_payload(
36
+ start=start,
37
+ stop=stop,
38
+ grid=grid,
39
+ assets=assets,
40
+ minimum_assets=minimum_assets,
41
+ exactly_assets=exactly_assets,
42
+ grid_point_sensor=grid_point_sensor,
43
+ grid_point_constraints=grid_point_constraints,
44
+ include_asset_access_results=include_asset_access_results,
45
+ include_coverage_points=include_coverage_points,
46
+ step_s=step_s,
47
+ description=description,
48
+ )
49
+ return raw.post(endpoint, json=payload)
50
+
51
+
52
+ def post_value_by_grid_point_input(
53
+ endpoint: str,
54
+ *,
55
+ start: str,
56
+ stop: str,
57
+ grid: CoverageGrid,
58
+ assets: Sequence[components.Entity],
59
+ compute_type: str | None = None,
60
+ minimum_assets: int | None = None,
61
+ exactly_assets: int | None = None,
62
+ grid_point_sensor: components.EntitySensor | None = None,
63
+ grid_point_constraints: Sequence[components.Constraint] | None = None,
64
+ include_asset_access_results: bool | None = None,
65
+ include_coverage_points: bool | None = None,
66
+ step_s: float | None = None,
67
+ description: str | None = None,
68
+ ) -> dict[str, Any]:
69
+ payload = _coverage_input_payload(
70
+ start=start,
71
+ stop=stop,
72
+ grid=grid,
73
+ assets=assets,
74
+ minimum_assets=minimum_assets,
75
+ exactly_assets=exactly_assets,
76
+ grid_point_sensor=grid_point_sensor,
77
+ grid_point_constraints=grid_point_constraints,
78
+ include_asset_access_results=include_asset_access_results,
79
+ include_coverage_points=include_coverage_points,
80
+ step_s=step_s,
81
+ description=description,
82
+ )
83
+ _include_if_supplied(
84
+ payload,
85
+ "ComputeType",
86
+ _optional_string(compute_type, parameter="compute_type"),
87
+ )
88
+ return raw.post(endpoint, json=payload)
89
+
90
+
91
+ def post_time_value_by_grid_point_input(
92
+ endpoint: str,
93
+ *,
94
+ time: str,
95
+ start: str,
96
+ stop: str,
97
+ grid: CoverageGrid,
98
+ assets: Sequence[components.Entity],
99
+ minimum_assets: int | None = None,
100
+ exactly_assets: int | None = None,
101
+ grid_point_sensor: components.EntitySensor | None = None,
102
+ grid_point_constraints: Sequence[components.Constraint] | None = None,
103
+ include_asset_access_results: bool | None = None,
104
+ include_coverage_points: bool | None = None,
105
+ step_s: float | None = None,
106
+ description: str | None = None,
107
+ ) -> dict[str, Any]:
108
+ if not isinstance(time, str):
109
+ raise TypeError("time must be a string")
110
+ payload = _coverage_input_payload(
111
+ start=start,
112
+ stop=stop,
113
+ grid=grid,
114
+ assets=assets,
115
+ minimum_assets=minimum_assets,
116
+ exactly_assets=exactly_assets,
117
+ grid_point_sensor=grid_point_sensor,
118
+ grid_point_constraints=grid_point_constraints,
119
+ include_asset_access_results=include_asset_access_results,
120
+ include_coverage_points=include_coverage_points,
121
+ step_s=step_s,
122
+ description=description,
123
+ )
124
+ payload["Time"] = time
125
+ return raw.post(endpoint, json=payload)