Swift TOO API
Swift MOC

swift_too module

Swift_VisQuery Example - Querying the visibility for a given target

API version = 1.2, swifttools version = 2.4

Author: Jamie A. Kennea (Penn State)

Introduction

This example shows how we can use the swift_too module to give us predicted long term visibility for targets. Note that long term visibility calculates if a target can be observed on Swift based on Sun, Moon and Pole constraints. It does not calculate the visibility due to Earth occultations.

Visibility is based on the most up to date TLE derived prediction of the spacecraft location into the future. Although this will not affect Sun and Moon constraints, Pole constraint accuracy may get worse the further into the future we look.

Setting up the Query

First step, import the Swift_VisQuery class from TOO API, and whatever supporting Python modules we might need along the way. Note: As of swifttools 2.3, we can use shorthand for class names, by omitting the Swift_, so in this case, just VisQuery will do.

from swifttools.swift_too import VisQuery
from datetime import datetime, timedelta
from time import sleep

As of swifttools 2.2 username and shared_secret default to anonymous, so you do not have to give them any more.

query = VisQuery()

Coordinate formats

We set up the parameters for the query, the minimum required parameters are RA/Dec coordinates, and the number of days to calculate the visibility over in days. RA/Dec are given in decimal degrees in J2000.

query.ra, query.dec = 19.27144, -73.44334

Of if you want to just use the name of the source, Swift_VisQuery will automatically resolve it for you, like so:

query.name = "SMC X-1"
query.resolve
Name RA (J2000) Dec (J2000) Resolver
SMC X-1 19.27144 -73.44334 Simbad

You can see here that the resolve attribute shows the coordinates of SMC X-1 as resolved by Simbad. These values are automatically copied to ra and dec, and also skycoord (if astropy is installed).

query.skycoord
<SkyCoord (FK5: equinox=J2000.000): (ra, dec) in deg
    (19.27143625, -73.4433375)>

Or for convenience we can use Astropy SkyCoord object to submit the coordinates in any format you like. They will just be converted into J2000 / FK5 RA/Dec upon submission. The following example shows how to submit a request based on Galactic Coordinates, in our case, the Galactic Center (lII/bII = 0,0).

from astropy.coordinates import SkyCoord

query.skycoord = SkyCoord("0.0", "0.0", frame="galactic", unit="deg")

If we print out RA / Dec now, we'll see it reflects the SkyCoord in the previous line.

print(
    f"SkyCoord should be the equivalent of RA/Dec(J2000) = {query.ra:.4f}, {query.dec:.4f}"
)
SkyCoord should be the equivalent of RA/Dec(J2000) = 266.4050, -28.9362

Note if you modify the RA/Dec values after setting a skycoord, the skycoord variable is altered to match the new coordinates. Note that the frame will default to FK5. If astropy is installed, swifttools 2.2 and above will allow you to access skycoord version of RA/Dec using the skycoord attribute.

query.ra = 19.2714
query.dec = -73.4433
print(query.skycoord)
<SkyCoord (FK5: equinox=J2000.000): (ra, dec) in deg
    (19.2714, -73.4433)>

Visibility Period

Final parameter, we set the length of time we wish to calculate the visibility for. Note we haven't set a start time, it will default to now. The default value is 7 days, so if you want to search for a week, then this value is isn't required. We'll set it anyway.

query.length = 7  # days

Submitting the Query for processing

Now we submit the request to the Swift TOO API server. The following code is a bit overcooked, you can just do query.submit() and it achieves the same thing, but you will have to check it for any errors.

if query.queue():
    while not query.complete:
        print(f"Waiting for job #{query.status.jobnumber} to be processed ...")
        sleep(2)
    print(f"Done. Job #{query.status.jobnumber} complete")
else:
    print(f"Request rejected. Error: {query.status.errors}")
Done. Job #280956 complete

Examining the returned results

Assuming success let's see what we get from the TOO API server in response to this request. We'll do this by typing in the name of the query object, which in a Jupyter Notebook will display the results as a table.

query
Begin Time End Time Window length
2022-03-28 17:01:00 2022-04-04 17:01:00 7 days, 0:00:00

You'll notice the API starts calculating the visibility from when the submission was sent, or at least to the nearest minute, if the begin property is not set. If the target is still visibile window after the amount of time you specified by length has ended, it will report that as the end of the visibility window, because it does not calculate beyond that.

print(
    f"Time between start of first window and end of last window = {query[-1][1] - query[0][0]}"
)
Time between start of first window and end of last window = 7 days, 0:00:00

Time formats

Window start / stop times are datetime structures and values are UTC.

query[0].begin
datetime.datetime(2022, 3, 28, 17, 1)

astropy fans can convert these to a Time class easily.

from astropy.time import Time

tbegins = Time([q.begin for q in query], scale="utc")
tends = Time([q.end for q in query], scale="utc")
tbegins[0]
<Time object: scale='utc' format='datetime' value=2022-03-28 17:01:00>

Which of course makes things like converting into other formats easy!

print(f"MJD Visibility Periods for RA/Dec(J2000) = {query.ra}, {query.dec}:\n")
for i in range(len(tbegins)):
    print(f"MJD {tbegins[i].mjd:.3f} - MJD {tends[i].mjd:.3f}")
MJD Visibility Periods for RA/Dec(J2000) = 19.2714, -73.4433:

MJD 59666.709 - MJD 59673.709

High resolution visibility

Swift is in a low Earth orbit, so visibility of a target depends on not just the relative positions of the Sun and Moon, but also on whether the target is occulted by the Earth. As Swift's orbit is approximately 96 minutes long, these Earth occultations regularly occur. As you can see from the visibility period above, it does not take these into account.

In addition Swift cannot observe while the spacecraft is passing through the South Atlantic Anomaly, and so these periods must be blocked out.

You can calculate visiblity windows including these constraints using the hires flag.

Let's set up a new VisQuery, using the hires flag. This time we'll use a more compact argument based to call it. Note that here we explicity set a begin and end time for the visibility period. Note that length can also be used in place of end.

hvq = VisQuery(
    ra=19.2714,
    dec=-73.4433,
    begin=datetime(2021, 2, 1),
    end=datetime(2021, 2, 2),
    hires=True,
)

Note that using this form, we don't have to use the submit() method, it is called automatically. Still we should still check that the request was successful.

if hvq.status.status == "Accepted":
    print("All Good!")
else:
    print(f"Not good: {hvq.status}")
All Good!

OK, let's see how our visibility windows look now:

hvq
Begin Time End Time Window length
2021-02-01 00:27:00 2021-02-01 00:37:00 0:10:00
2021-02-01 02:02:00 2021-02-01 02:17:00 0:15:00
2021-02-01 03:38:00 2021-02-01 03:58:00 0:20:00
2021-02-01 05:13:00 2021-02-01 05:41:00 0:28:00
2021-02-01 06:49:00 2021-02-01 07:20:00 0:31:00
2021-02-01 08:24:00 2021-02-01 08:55:00 0:31:00
2021-02-01 10:00:00 2021-02-01 10:31:00 0:31:00
2021-02-01 11:35:00 2021-02-01 12:07:00 0:32:00
2021-02-01 13:11:00 2021-02-01 13:42:00 0:31:00
2021-02-01 14:46:00 2021-02-01 15:18:00 0:32:00
2021-02-01 16:22:00 2021-02-01 16:53:00 0:31:00
2021-02-01 17:57:00 2021-02-01 18:29:00 0:32:00
2021-02-01 19:32:00 2021-02-01 19:34:00 0:02:00
2021-02-01 19:49:00 2021-02-01 20:04:00 0:15:00
2021-02-01 21:08:00 2021-02-01 21:12:00 0:04:00
2021-02-01 21:36:00 2021-02-01 21:40:00 0:04:00
2021-02-01 22:43:00 2021-02-01 22:51:00 0:08:00

As you can see, despite only being for a period covering one day, the number of windows is much greater, and the windows are shorter. These windows are the true visibility of a target to Swift. Note however, that although windows can be up to 45 minutes long, the maximum that Swift can observed a pre-planned target for is 30 minutes.

Another thing to note: Maximum length that can be calculated in high resolution is 20 days. This is because it is computationally expensive to make this calculation. In addition, these windows are calculated based on a contemporary Swift ephemeris derived from a Two Line Element. This means that if you go too far into the future, the accuracy of the orbit prediction will suffer. We therefore recommend that you treat predictions of high resolution visibility that go more than 20 days into the future with caution.

A note about clock correction

New in swifttools 2.4.

The times reported by VisQuery are in UTC. However, Swift observations are scheduled using time defined by the Swift onboard clock. This clock not only does not include leap seconds, but also is drifting slightly over time. In order to convert UTC visibility times to Swift times, you can perform a clock correction using the clock_correction() method.

hvq.clock_correct()
hvq
Begin Time (UTC) End Time (UTC) Window length
2021-02-01 00:27:00.000001 2021-02-01 00:37:00 0:09:59.999999
2021-02-01 02:02:00 2021-02-01 02:17:00 0:15:00
2021-02-01 03:38:00 2021-02-01 03:58:00 0:20:00
2021-02-01 05:13:00 2021-02-01 05:41:00 0:28:00
2021-02-01 06:49:00 2021-02-01 07:20:00 0:31:00
2021-02-01 08:24:00 2021-02-01 08:55:00 0:31:00
2021-02-01 10:00:00 2021-02-01 10:31:00 0:31:00
2021-02-01 11:35:00 2021-02-01 12:07:00 0:32:00
2021-02-01 13:11:00 2021-02-01 13:42:00 0:31:00
2021-02-01 14:46:00 2021-02-01 15:18:00 0:32:00
2021-02-01 16:22:00 2021-02-01 16:53:00 0:31:00
2021-02-01 17:57:00 2021-02-01 18:29:00 0:32:00
2021-02-01 19:31:59.999999 2021-02-01 19:34:00 0:02:00.000001
2021-02-01 19:49:00 2021-02-01 20:04:00 0:15:00
2021-02-01 21:08:00 2021-02-01 21:12:00 0:04:00
2021-02-01 21:36:00 2021-02-01 21:40:00 0:04:00
2021-02-01 22:43:00 2021-02-01 22:51:00 0:08:00

You can now see that the times are explicitely stated to be in UTC. You can convert the above table to give times in the Swift internal clock format, but using the to_swifttime() method, e.g.:

hvq.to_swifttime()
hvq
Begin Time (Swift) End Time (Swift) Window length
2021-02-01 00:27:26.428442 2021-02-01 00:37:26.428481 0:10:00.000039
2021-02-01 02:02:26.428819 2021-02-01 02:17:26.428878 0:15:00.000059
2021-02-01 03:38:26.429200 2021-02-01 03:58:26.429279 0:20:00.000079
2021-02-01 05:13:26.429577 2021-02-01 05:41:26.429688 0:28:00.000111
2021-02-01 06:49:26.429958 2021-02-01 07:20:26.430081 0:31:00.000123
2021-02-01 08:24:26.430335 2021-02-01 08:55:26.430458 0:31:00.000123
2021-02-01 10:00:26.430716 2021-02-01 10:31:26.430840 0:31:00.000124
2021-02-01 11:35:26.431094 2021-02-01 12:07:26.431221 0:32:00.000127
2021-02-01 13:11:26.431475 2021-02-01 13:42:26.431598 0:31:00.000123
2021-02-01 14:46:26.431852 2021-02-01 15:18:26.431971 0:32:00.000119
2021-02-01 16:22:26.432225 2021-02-01 16:53:26.432348 0:31:00.000123
2021-02-01 17:57:26.432602 2021-02-01 18:29:26.432729 0:32:00.000127
2021-02-01 19:32:26.432979 2021-02-01 19:34:26.432987 0:02:00.000008
2021-02-01 19:49:26.433047 2021-02-01 20:04:26.433107 0:15:00.000060
2021-02-01 21:08:26.433361 2021-02-01 21:12:26.433377 0:04:00.000016
2021-02-01 21:36:26.433472 2021-02-01 21:40:26.433488 0:04:00.000016
2021-02-01 22:43:26.433738 2021-02-01 22:51:26.433770 0:08:00.000032

As you can see above, the times are now slightly different and the table has changed to indicate that the times are Swift times. Note that for planning purposes, Swift does not schedule at resolution higher than 1 minute, so these clock corrections are not crucial.

Swift Mission Operations Center

The Pennsylvania State University
301 Science Park Road,
Building 2 Suite 332,
State College, PA 16801
USA
☎ +1 (814) 865-6834
📧 swiftods@swift.psu.edu

Swift MOC Team Leads

Mission Director: John Nousek
Science Operations: Jamie Kennea
Flight Operations: Mark Hilliard
UVOT: Michael Siegel
XRT: Jamie Kennea