Skip to content

Commit

Permalink
general SWIFT binary conversions
Browse files Browse the repository at this point in the history
Added instrument modes

SWIFT UVOT binary conversion

small changes
  • Loading branch information
Athish Thiruvengadam committed Nov 1, 2024
1 parent f536181 commit ff4afa4
Show file tree
Hide file tree
Showing 22 changed files with 710 additions and 0 deletions.
34 changes: 34 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_ACTUAL_POINTDIR/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import numpy as np

from ... import utils


def parse_pointdir(bin):
id_record_number_bits = np.flip(np.unpackbits(bin[4:5].view(dtype="u1")))
record_number = np.packbits(np.flip(id_record_number_bits[24:]))
id = id_record_number_bits[:24].dot(2 ** np.arange(24))

lat, lon = bin[16:17].view(dtype=">i2")

soln_status_bits = np.flip(np.unpackbits(bin[19:20].view(dtype="u1")))
return {
"mission": "SWIFT",
"id": [id],
"record_number": record_number,
"trigger_time": utils.datetime_to_iso8601(bin[5], bin[6]),
"ra_pointing": bin[7] * 1e-4,
"dec_pointing": bin[8] * 1e-4,
"roll": bin[9] * 1e-4,
"latitude": lat * 1e-2,
"longitude": lon * 1e-2,
"bright_star_nearby": bool(soln_status_bits[13]),
}


def parse(bin):
bin[10:16] # Spare. According to Docs: '24 bytes for the future'
bin[17:19] # Spare. According to Docs: '8 bytes for the future'
bin[20:22] # Spare. According to Docs: '8 bytes for the future'
bin[22:39] # Unused. According to Docs: 'tgtname; might get added late'

return {**parse_pointdir(bin)}
16 changes: 16 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_ACTUAL_POINTDIR/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"mission": "SWIFT",
"id": [
97524
],
"record_number": [
5
],
"trigger_time": "2024-05-10T07:59:28.960Z",
"ra_pointing": 74.5428,
"dec_pointing": -52.065000000000005,
"roll": 329.2339,
"latitude": -5.44,
"longitude": 88.60000000000001,
"bright_star_nearby": false
}
80 changes: 80 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import numpy as np

from ... import utils

start_tracker_status = ["locked", "not locked"]


def parse_fom(bin):
id_record_number_bits = np.flip(np.unpackbits(bin[4:5].view(dtype="u1")))
record_number = np.packbits(np.flip(id_record_number_bits[24:]))
id = id_record_number_bits[:24].dot(2 ** np.arange(24))

lat, lon = bin[10:11].view(dtype=">i2")

integ_time = bin[15] * 4 / 1000

soln_status_bits = np.flip(np.unpackbits(bin[16:17].view(dtype="u1")))
soln_status_bits[8] # Unused. According to docs: 'ground_catalog_source'.
soln_status_bits[12] # Unused. According to docs: 'blocked_catalog_source'.
if soln_status_bits[11]:
grb_status = (

Check warning on line 21 in gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py#L21

Added line #L21 was not covered by tests
"It is probably not a GRB or transient due to very low image significance"
)
elif soln_status_bits[7]:
grb_status = (

Check warning on line 25 in gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py#L25

Added line #L25 was not covered by tests
"It is probably not a GRB or transient due to low image significance"
)
elif soln_status_bits[9]:
grb_status = (

Check warning on line 29 in gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py#L29

Added line #L29 was not covered by tests
"It is probably not a GRB or transient due to negative background slope"
)
elif soln_status_bits[6]:
grb_status = (

Check warning on line 33 in gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_FOM_OBS/__init__.py#L33

Added line #L33 was not covered by tests
"It is probably not a GRB or transient due to high background level"
)
elif soln_status_bits[1]:
grb_status = "It is a GRB"
else:
grb_status = "It is not a GRB"

at_slew_flags = np.flip(np.unpackbits(bin[18:19].view(dtype="u1")))

image_snr = bin[20]

return {
"mission": "SWIFT",
"id": [id],
"record_number": record_number[0],
"alert_type": "retraction" if soln_status_bits[5] else "initial",
"trigger_time": utils.datetime_to_iso8601(bin[5], bin[6]),
"ra": bin[7] * 1e-4,
"dec": bin[8] * 1e-4,
"roll": bin[9] * 1e-4,
"latitude": lat * 1e-2,
"longitude": lon * 1e-2,
"merit_value": bin[38] * 1e-2,
"grb_status": grb_status,
"point_source": bool(soln_status_bits[0]),
"flaring_known_source": bool(soln_status_bits[2]),
"star_tracker_status": start_tracker_status[soln_status_bits[10]],
"bright_star_nearby": bool(soln_status_bits[13]),
"removed_from_catalog": bool(soln_status_bits[15]),
"galaxy_nearby": bool(soln_status_bits[16]),
"trigger_index": bin[17],
"trigger_type": "image" if soln_status_bits[4] else "rate",
"image_duration": integ_time if soln_status_bits[4] else None,
"rate_duration": integ_time if not soln_status_bits[4] else None,
"rate_snr": bin[21] * 1e-2,
"image_snr": image_snr if soln_status_bits[4] else None,
"new_automated_target": bool(at_slew_flags[0]),
"sufficient_merit": bool(at_slew_flags[1]),
}


def parse(bin):
bin[11:15] # Spare. According to Docs: '16 bytes for the future'
bin[22:38] # Spare. According to Docs: '64 bytes for the future'
bin[19] # Unused. Flags are either internal or equivalent to bin[16]

return {**parse_fom(bin)}
30 changes: 30 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_FOM_OBS/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"mission": "SWIFT",
"id": [
1227767
],
"record_number": 0,
"alert_type": "initial",
"trigger_time": "2024-05-11T18:06:53.220Z",
"ra": 336.66450000000003,
"dec": 8.5135,
"roll": 0.0,
"latitude": -11.14,
"longitude": 151.31,
"merit_value": 100.0,
"grb_status": "It is a GRB",
"point_source": true,
"flaring_known_source": false,
"star_tracker_status": "locked",
"bright_star_nearby": false,
"removed_from_catalog": false,
"galaxy_nearby": false,
"trigger_index": 262,
"trigger_type": "rate",
"image_duration": null,
"rate_duration": 2.048,
"rate_snr": 14.89,
"image_snr": null,
"new_automated_target": true,
"sufficient_merit": true
}
22 changes: 22 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_POINTDIR/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from ... import utils
from ..SWIFT_ACTUAL_POINTDIR import parse_pointdir


def parse(bin):
bin[10] # Spare. According to Docs: '4 bytes for the future'
bin[17:19] # Spare. According to Docs: '8 bytes for the future'
bin[20:22] # Spare. According to Docs: '8 bytes for the future'

_, bat_mode = bin[11:12].view(dtype=">i2")
_, xrt_mode = bin[12:13].view(dtype=">i2")
_, uvot_mode = bin[13:14].view(dtype=">i2")

return {
**parse_pointdir(bin),
"bat_mode": hex(bat_mode),
"xrt_mode": hex(xrt_mode),
"uvot_mode": hex(uvot_mode),
"observation_time": bin[14] * 1e-2,
"merit_value": bin[15] * 1e-2,
"target_name": utils.binary_to_string(bin[22:39]),
}
22 changes: 22 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_POINTDIR/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"mission": "SWIFT",
"id": [
97317
],
"record_number": [
2
],
"trigger_time": "2024-05-09T23:16:00.000Z",
"ra_pointing": 213.1096,
"dec_pointing": 47.3553,
"roll": 342.3806,
"latitude": 14.19,
"longitude": 16.12,
"bright_star_nearby": false,
"bat_mode": "0x0",
"xrt_mode": "0x7",
"uvot_mode": "0x18c",
"observation_time": 360.0,
"merit_value": 51.0,
"target_name": "URAT1-687234652 "
}
89 changes: 89 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import numpy as np

from ... import utils

start_tracker_status = ["locked", "not locked"]
slew_return_options = [
"The slew will be executed.",
"The slew will not be executed. Sun constraint.",
"The slew will not be executed. Earth_limb constraint.",
"The slew will not be executed. Moon constraint.",
"The slew will not be executed. Ram_vector constraint.",
"The slew will not be executed. Invalid slew_request parameter.",
]


def parse_slew(bin):
id_record_number_bits = np.flip(np.unpackbits(bin[4:5].view(dtype="u1")))
record_number = np.packbits(np.flip(id_record_number_bits[24:]))
id = id_record_number_bits[:24].dot(2 ** np.arange(24))

lat, lon = bin[10:11].view(dtype=">i2")

integ_time = bin[15] * 4 / 1000

soln_status_bits = np.flip(np.unpackbits(bin[16:17].view(dtype="u1")))
soln_status_bits[8] # Unused. According to docs: 'ground_catalog_source'.
soln_status_bits[12] # Unused. According to docs: 'blocked_catalog_source'.
if soln_status_bits[11]:
grb_status = (

Check warning on line 29 in gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py#L29

Added line #L29 was not covered by tests
"It is probably not a GRB or transient due to very low image significance"
)
elif soln_status_bits[7]:
grb_status = (

Check warning on line 33 in gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py#L33

Added line #L33 was not covered by tests
"It is probably not a GRB or transient due to low image significance"
)
elif soln_status_bits[9]:
grb_status = (

Check warning on line 37 in gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py#L37

Added line #L37 was not covered by tests
"It is probably not a GRB or transient due to negative background slope"
)
elif soln_status_bits[6]:
grb_status = (

Check warning on line 41 in gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py

View check run for this annotation

Codecov / codecov/patch

gcn_classic_to_json/notices/SWIFT_SC_SLEW/__init__.py#L41

Added line #L41 was not covered by tests
"It is probably not a GRB or transient due to high background level"
)
elif soln_status_bits[1]:
grb_status = "It is a GRB"
else:
grb_status = "It is not a GRB"

image_snr = bin[20]

return {
"id": [id],
"record_number": record_number,
"alert_type": "retraction" if soln_status_bits[5] else "initial",
"trigger_time": utils.datetime_to_iso8601(bin[5], bin[6]),
"ra": bin[7] * 1e-4,
"dec": bin[8] * 1e-4,
"roll": bin[9] * 1e-4,
"latitude": lat * 1e-2,
"longitude": lon * 1e-2,
"wait_time": bin[13] * 1e-2,
"observation_time": bin[14] * 1e-2,
"grb_status": grb_status,
"point_source": bool(soln_status_bits[0]),
"flaring_known_source": bool(soln_status_bits[2]),
"star_tracker_status": start_tracker_status[soln_status_bits[10]],
"bright_star_nearby": bool(soln_status_bits[13]),
"removed_from_catalog": bool(soln_status_bits[15]),
"galaxy_nearby": bool(soln_status_bits[16]),
"trigger_index": bin[17],
"merit_value": bin[38] * 1e-2,
"trigger_type": "image" if soln_status_bits[4] else "rate",
"image_duration": integ_time if soln_status_bits[4] else None,
"rate_duration": integ_time if not soln_status_bits[4] else None,
"rate_snr": bin[21] * 1e-2,
"image_snr": image_snr if soln_status_bits[4] else None,
"slew_return_code": slew_return_options[bin[18]],
"bat_mode": hex(bin[22]),
"xrt_mode": hex(bin[23]),
"uvot_mode": hex(bin[24]),
}


def parse(bin):
bin[11:13] # Spare. According to Docs: '8 bytes for the future'
bin[25:38] # Spare. According to Docs: '52 bytes for the future'
bin[19] # Unused. Flags are either internal or equivalent to bin[16]

return {**parse_slew(bin)}
35 changes: 35 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_SC_SLEW/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"id": [
1227767
],
"record_number": [
0
],
"alert_type": "initial",
"trigger_time": "2024-05-11T18:06:53.220Z",
"ra": 336.66450000000003,
"dec": 8.5135,
"roll": 73.6649,
"latitude": -11.14,
"longitude": 151.31,
"wait_time": 0.0,
"observation_time": 1890.0,
"grb_status": "It is a GRB",
"point_source": true,
"flaring_known_source": false,
"star_tracker_status": "locked",
"bright_star_nearby": false,
"removed_from_catalog": false,
"galaxy_nearby": false,
"trigger_index": 262,
"merit_value": 100.0,
"trigger_type": "rate",
"image_duration": null,
"rate_duration": 2.048,
"rate_snr": 14.89,
"image_snr": null,
"slew_return_code": "The slew will be executed.",
"bat_mode": "0x0",
"xrt_mode": "0x0",
"uvot_mode": "0x8000"
}
9 changes: 9 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_TOO_FOM/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ..SWIFT_FOM_OBS import parse_fom


def parse(bin):
bin[11:15] # Spare. According to Docs: '16 bytes for the future'
bin[22:38] # Spare. According to Docs: '64 bytes for the future'
bin[19] # Unused. Flags are either internal or equivalent to bin[16]

return {**parse_fom(bin)}
30 changes: 30 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_TOO_FOM/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"mission": "SWIFT",
"id": [
1228797
],
"record_number": 1,
"alert_type": "initial",
"trigger_time": "2024-05-16T03:35:54.540Z",
"ra": 212.8069,
"dec": -63.4878,
"roll": 194.42100000000002,
"latitude": 16.72,
"longitude": 228.03,
"merit_value": 100.0,
"grb_status": "It is not a GRB",
"point_source": false,
"flaring_known_source": false,
"star_tracker_status": "locked",
"bright_star_nearby": false,
"removed_from_catalog": false,
"galaxy_nearby": false,
"trigger_index": 0,
"trigger_type": "rate",
"image_duration": null,
"rate_duration": 0.0,
"rate_snr": 0.0,
"image_snr": null,
"new_automated_target": true,
"sufficient_merit": true
}
9 changes: 9 additions & 0 deletions gcn_classic_to_json/notices/SWIFT_TOO_SC_SLEW/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ..SWIFT_SC_SLEW import parse_slew


def parse(bin):
bin[11:13] # Spare. According to Docs: '8 bytes for the future'
bin[25:38] # Spare. According to Docs: '52 bytes for the future'
bin[19] # Unused. Flags are either internal or equivalent to bin[16]

return {**parse_slew(bin)}
Loading

0 comments on commit ff4afa4

Please sign in to comment.