Skip to content

Commit

Permalink
Add BurstCube TOO API endpoints
Browse files Browse the repository at this point in the history
Add Validation to AstropyTime

Add FOV check to BurstCubeTOO and other fixes

Change healpix_order to healpix_scheme

Compare ephem times in unix time as comparing freeform astropy time object can cause this to fail due to minute differences that create an out of bounds issue with the assertion in get_slice

Fixes for modified_on/by

Remove history table stuff for now

Fix security for burstcube TOO

Updates for mypy and cleanups

Update import sorts

Import sort

Remove debug print statement

Simplify database write/update

Simplify database write/update

Fix check for existing TOO

Change BurstCubeTOO PUT to have the same arguments as POST, so we can use it to upload updated HEALPix

Remove excess docstring from schema

Reconfigure BurstCubeTOO to redo constraints check if PUT updates coordinates

Change how uploads are done in the API

Update TOO PUT schema

Trap uploads of bad HEALPix files

Fix bug

Make schema and api return astropy native values

Simplify requests.py

Move to astropy native in schema. Clean up docstrings

Clean up code reuse in BurstCubeTOO

Json email selections (#1977)

Bump usehooks-ts from 2.15.0 to 2.15.1

Bumps [usehooks-ts](https://github.com/juliencrn/usehooks-ts) from 2.15.0 to 2.15.1.
- [Release notes](https://github.com/juliencrn/usehooks-ts/releases)
- [Commits](https://github.com/juliencrn/usehooks-ts/compare/[email protected]@2.15.1)

---
updated-dependencies:
- dependency-name: usehooks-ts
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

Bump tiny-invariant from 1.3.1 to 1.3.3

Bumps [tiny-invariant](https://github.com/alexreardon/tiny-invariant) from 1.3.1 to 1.3.3.
- [Release notes](https://github.com/alexreardon/tiny-invariant/releases)
- [Commits](alexreardon/tiny-invariant@v1.3.1...v1.3.3)

---
updated-dependencies:
- dependency-name: tiny-invariant
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

Support for reading gzipped fits files. Refactor reused code.

Remove superfluous entries in app.arc

Make BurstCubeTOO a dataclass to remove the init stuff

Differentiate username and created by

Back to username

Remove a space in a comment.

Compare jd instead of unix as it should always be consistent

Put table into a property that can be set for pytest

Don't hardcode TOO table name

Clean up docstring

Move table write into BurstCubeTOO

Move BurstCubeTOOModel into schema.py

Fix imports

Remove types in docstrings

Adds a confirmation alert (#1957)

* Adds a confirmation alert

* Return intent and rename newItem to newCircular

Better sentence text, adds heading

Bump es5-ext from 0.10.61 to 0.10.63

Bumps [es5-ext](https://github.com/medikoo/es5-ext) from 0.10.61 to 0.10.63.
- [Release notes](https://github.com/medikoo/es5-ext/releases)
- [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md)
- [Commits](medikoo/es5-ext@v0.10.61...v0.10.63)

---
updated-dependencies:
- dependency-name: es5-ext
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>

Announcement template (#1958)

Code of Conduct (#1635)

Docstring cleanups

Fix use of old style Config in Pydantic model

Add pytest to check CRUD operations on BurstCubeTOO

Add check for SPACETRACK credentials

Fix reject_reason

Add old TOO rejection pytest

Add test for double submission

Add test for double submission

Mock BurstCubeTLE so that we don't have to spam celestak or spacetrack

Add pytest-mock requirement for testing

Revert tle.py

Mypy fixes

Docstring fix

Fix test time to a value that matches the test TLE

Remove epoch for TLE

Revert to Time.now() otherwise toos will get rejected a few days from now

Move assert for time being within ephem to ephindex

Try something to kick Github workflow

Fix return type

Co-authored-by: Leo Singer <[email protected]>

Remove a comment

Co-authored-by: Leo Singer <[email protected]>

Add black in to check

Change length to duration

Add sub-types to u.Quantity return types

Fix return quantity

Remove black from workflow

Propogate the length -> duration change

Move depends into depends.py. Remove unused depend from BurstCube api.py.

Put BurstCubeTOORequests into toorequest.py

Switch to pytest-dynamodb for pytests

Stuff to run pytest-dynamodb in the workflow

Remove JsonStr as it's not needed. Update how DyDB puts work. Fix bug in definition of error_radius.

Remove unncessary model_validator

Need isot format dates for DynamoDB

Fix pytests. Add tests for BurstCubeTOORequests.

Remove debug code

Update ephindex to assert on index value

Put back BurstCubeTrigger model_validator

Fix format

Remove unnecessary round_times

Remove unused schema

Remove tests for another PR

Remove test requirements

Implement GSI on burstcube_too to do limit and date range queries

Revert to using just arc.tables

Remove try/except around db calls

Remove debug print statement

Change username to sub

TOORequests get never returns False

Explanation for python-multipart dependency

Co-authored-by: Leo Singer <[email protected]>

Add FIXME with link to astropy issue on compression handling

Update scope for BurstCube TOO submit/update/delete

Remove incorrect "Raises" from schema docstrings.
  • Loading branch information
jak574 authored and lpsinger committed Mar 7, 2024
1 parent c2a0ff7 commit be9de0e
Show file tree
Hide file tree
Showing 11 changed files with 1,109 additions and 29 deletions.
8 changes: 8 additions & 0 deletions app.arc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ acrossapi_tle
tle1 String
tle2 String

burstcube_too
id *String

sessions
_idx *String
_ttl TTL
Expand Down Expand Up @@ -105,6 +108,11 @@ legacy_users
PointInTimeRecovery true

@tables-indexes
burstcube_too
gsipk *String
created_on **String
name byCreatedOn

email_notification_subscription
topic *String
name byTopic
Expand Down
3 changes: 2 additions & 1 deletion python/across_api/base/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

"""
Base API definitions for ACROSS API. This module is imported by all other API
modules. Contains the FastAPI app definition.
modules.
"""

from fastapi import FastAPI


# FastAPI app definition
app = FastAPI(
title="ACROSS API",
Expand Down
10 changes: 0 additions & 10 deletions python/across_api/base/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,10 @@ def get_slice(time: Time, ephem: EphemBase) -> slice:
"""
# If we're just passing a single time, we can just find the index for that
if time.isscalar:
# Check that the time is within the ephemeris range, this should never
# happen as the ephemeris is generated based on this range.
assert (
time >= ephem.begin and time <= ephem.end
), "Time outside of ephemeris of range"
# Find the index for the time and return a slice for that index
index = ephem.ephindex(time)
return slice(index, index + 1)
else:
# Check that the time range is within the ephemeris range, as above.
assert (
time[0] >= ephem.begin and time[-1] <= ephem.end
), "Time outside of ephemeris of range"

# Find the indices for the start and end of the time range and return a
# slice for that range
return slice(ephem.ephindex(time[0]), ephem.ephindex(time[-1]) + 1)
Expand Down
172 changes: 172 additions & 0 deletions python/across_api/base/depends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Copyright © 2023 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.

from datetime import datetime
from typing import Annotated, Optional

import astropy.units as u # type: ignore[import]
from astropy.time import Time # type: ignore[import]
from fastapi import Depends, Path, Query


# Depends functions for FastAPI calls.
async def optional_daterange(
begin: Annotated[
Optional[datetime],
Query(
description="Start time of period to be calculated.",
title="Begin",
),
] = None,
end: Annotated[
Optional[datetime],
Query(
description="Start time of period to be calculated.",
title="End",
),
] = None,
) -> dict:
"""
Helper function to convert begin and end to datetime objects.
"""
if begin is None or end is None:
return {"begin": None, "end": None}
return {"begin": Time(begin), "end": Time(end)}


OptionalDateRangeDep = Annotated[dict, Depends(optional_daterange)]


# Depends functions for FastAPI calls.
async def optional_duration(
duration: Annotated[
Optional[float],
Query(
description="Duration of time (days).",
title="Duration",
),
] = None,
) -> Optional[u.Quantity[u.day]]:
"""
Helper function to convert a float duration in days to a u.Quantity
"""
if duration is None:
return None
return duration * u.day


OptionalDurationDep = Annotated[dict, Depends(optional_duration)]


async def optional_limit(
limit: Annotated[
Optional[int],
Query(
ge=0,
title="Limit",
description="Maximum number of results to return.",
),
] = None,
) -> Optional[int]:
return limit


LimitDep = Annotated[Optional[int], Depends(optional_limit)]


async def error_radius(
error_radius: Annotated[
Optional[float],
Query(
ge=0,
title="Error Radius",
description="Error radius in degrees.",
),
] = None,
) -> Optional[u.Quantity[u.deg]]:
if error_radius is None:
return None
return error_radius * u.deg


ErrorRadiusDep = Annotated[float, Depends(error_radius)]


async def exposure(
exposure: Annotated[
float,
Query(
ge=0,
title="Exposure",
description="Exposure time in seconds.",
),
] = 200,
) -> u.Quantity[u.s]:
return exposure * u.s


ExposureDep = Annotated[float, Depends(exposure)]


async def offset(
offset: Annotated[
float,
Query(
ge=-200,
le=200,
title="Offset",
description="Offset start of dump window from T0 by this amount (seconds).",
),
] = -50,
) -> u.Quantity[u.s]:
return offset * u.s


OffsetDep = Annotated[float, Depends(offset)]


async def optional_ra_dec(
ra: Annotated[
Optional[float],
Query(
ge=0,
lt=360,
title="RA (J2000)",
description="Right Ascenscion in J2000 coordinates and units of decimal degrees.",
),
] = None,
dec: Annotated[
Optional[float],
Query(
ge=-90,
le=90,
title="Dec (J2000)",
description="Declination in J2000 coordinates in units of decimal degrees.",
),
] = None,
) -> Optional[dict]:
if ra is None or dec is None:
return {"ra": None, "dec": None}
return {"ra": ra * u.deg, "dec": dec * u.deg}


OptionalRaDecDep = Annotated[dict, Depends(optional_ra_dec)]


IdDep = Annotated[str, Path(description="TOO ID string")]


async def trigger_time(
trigger_time: Annotated[
datetime,
Query(
title="Trigger Time",
description="Time of trigger in UTC or ISO format.",
),
],
) -> Optional[Time]:
return Time(trigger_time)


TriggerTimeDep = Annotated[datetime, Depends(trigger_time)]
6 changes: 5 additions & 1 deletion python/across_api/base/ephem.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ def ephindex(self, t: Time) -> int:
-------
The index of the nearest time in the ephemeris.
"""
return int(np.argmin(np.abs((self.timestamp.datetime - t.datetime))))
index = np.round(
(t.jd - self.timestamp[0].jd) // self.stepsize.to_value(u.day)
).astype(int)
assert index >= 0 and index < len(self), "Time outside of ephemeris of range"
return index

def __init__(self, begin: Time, end: Time, stepsize: u.Quantity = 60 * u.s):
# Check if TLE is loaded
Expand Down
Loading

0 comments on commit be9de0e

Please sign in to comment.