chandra_aca.maude_decom¶
Classes and functions to help fetching ACA telemetry data using MAUDE.
Telemetry Specification¶
Aspect telemetry is described in chapter 5 of the User’s Manual. This module deals mostly with Aspect telemetry, specified in section 5.3 of the user’s manual and section 3.2.1.15.12 of the ACA specification document EQ7-278 F.
In general, the telemetry data is specified in the following documents (available on the Aspect Twiki page):
MSFC-STD-1274B. MSFC HOSC Telemetry Format Standard
MSFC-DOC-1949. MSFC HOSC Database Definitions
Timing¶
Timing in MAUDE Telemetry¶
What follows is a summary from the user’s guide section 6, and EQ7-278 F section 3.2.1.7. Check there for more details, especially Figures 6-1 to 6-4 in the user’s manual and Figure 7 in EQ7-278 F.
The ACA updates its output in regular 1.025 second periods that either begin or end at the time of an RCTU science header pulse (which occur every 2.05 seconds). These are called update periods, following the convention in the user manual section 6.1.
The ACA CCD operating cycle starts with a flush of charge from the CCD, followed by CCD integration, CCD readout, and ends with an idle period. The start/end of the update period does not coincide with the start/end of the CCD cycle. Instead, the end of the integration coincides with the start/end of the update period. This is accomplished by adjusting the idle period.
The data from and integration period is available to the OBC at the end of the following update period (EQ7-278 F Figure 7). That is 1.025 sec after the end of integration. This is the VCDU time seen in MAUDE telemetry:
TIME = END_INTEG_TIME + 1.025
In the case of 6x6 and 8x8 images, the entire image cannot be updated in a single update period, because Aspect pixel telemetry contains only eight pixels per update. 6x6 images take two update periods, and 8x8 images take four. The end of the integration interval is the same for all the sub-images, and corresponds to:
END_INTEG_TIME = TIME - 1.025
When the choice of integration time causes the CCD cycle to last longer than the time it takes to update a full image (1.025 seconds for a 4x4 image, 2.05 seconds for a 6x6 image or 4.1 seconds for an 8x8 image) the most recent image is repeated until new pixel data is available.
Timing in level0 Data Products¶
The times for pixel telemetry in level0 data products is adjusted to coincide with the middle of the integration interval:
TIME = END_INTEG_TIME - INTEG / 2
This means that the difference between the time in telemetry and the time in the level0 data products is:
TIME<telem> - TIME<l0> = 1.025 + INTEG / 2
Global variables in this module¶
These include the following global variables
MAX_VCDU: the maximum possible VCDU frame counter value
MAX_MJF: the maximum possible major frame counter value
MAX_MNF: the maximum possible minor frame counter value
PIXEL_MAP: dict of np.array, with values mapping integer pixel indices to pixel string ID
PIXEL_MAP_INV: dict of dict, with values mapping pixel string ID to integer pixel indices.
PIXEL_MASK: dict of np.array. Values are boolean masks that apply to images of different sizes
ACA_MSID_LIST: dictionary of commonly-used ACA telemetry MSIDs.
ACA_SLOT_MSID_LIST: dictionary of ACA image telemetry MSIDs.
PIXEL_MAP contains maps between pixel indices and pixel IDm depending on the image size. In the following tables, column index increases to the right and row index increases to the top (c.f. ACA User Manual Figs 1.8 and 1.9 ):
- Size 4X41:
-----------------------------------------
| -- | -- | -- | -- | -- | -- | -- | -- |
-----------------------------------------
| -- | -- | -- | -- | -- | -- | -- | -- |
-----------------------------------------
| -- | -- | D1 | H1 | L1 | P1 | -- | -- |
-----------------------------------------
| -- | -- | C1 | G1 | K1 | O1 | -- | -- |
-----------------------------------------
| -- | -- | B1 | F1 | J1 | N1 | -- | -- |
-----------------------------------------
| -- | -- | A1 | E1 | I1 | M1 | -- | -- |
-----------------------------------------
| -- | -- | -- | -- | -- | -- | -- | -- |
-----------------------------------------
| -- | -- | -- | -- | -- | -- | -- | -- |
-----------------------------------------
- Size 6X61 or 6X62:
-----------------------------------------
| -- | -- | -- | -- | -- | -- | -- | -- |
-----------------------------------------
| -- | -- | E2 | F2 | G2 | H2 | -- | -- |
-----------------------------------------
| -- | D2 | D1 | H1 | L1 | P1 | I2 | -- |
-----------------------------------------
| -- | C2 | C1 | G1 | K1 | O1 | J2 | -- |
-----------------------------------------
| -- | B2 | B1 | F1 | J1 | N1 | K2 | -- |
-----------------------------------------
| -- | A2 | A1 | E1 | I1 | M1 | L2 | -- |
-----------------------------------------
| -- | -- | P2 | O2 | N2 | M2 | -- | -- |
-----------------------------------------
| -- | -- | -- | -- | -- | -- | -- | -- |
-----------------------------------------
- Size 8X81, 8X82, 8X83 or 8X84:
-----------------------------------------
| H1 | P1 | H2 | P2 | H3 | P3 | H4 | P4 |
-----------------------------------------
| G1 | O1 | G2 | O2 | G3 | O3 | G4 | O4 |
-----------------------------------------
| F1 | N1 | F2 | N2 | F3 | N3 | F4 | N4 |
-----------------------------------------
| E1 | M1 | E2 | M2 | E3 | M3 | E4 | M4 |
-----------------------------------------
| D1 | L1 | D2 | L2 | D3 | L3 | D4 | L4 |
-----------------------------------------
| C1 | K1 | C2 | K2 | C3 | K3 | C4 | K4 |
-----------------------------------------
| B1 | J1 | B2 | J2 | B3 | J3 | B4 | J4 |
-----------------------------------------
| A1 | I1 | A2 | I2 | A3 | I3 | A4 | I4 |
-----------------------------------------
- chandra_aca.maude_decom.blob_to_aca_image_dict(blob, imgnum, pea=1)[source]¶
Assemble ACA image MSIDs from a blob into a dictionary.
This does to blobs what unpack_aca_telemetry does to frames, but for a single image.
- Parameters:
- blob
- imgnum
- pea
- Returns:
- chandra_aca.maude_decom.filter_vcdu_jumps(vcdu_counters)[source]¶
Return a boolean mask to filter VCDU counters that are not continuous.
The returned mask ensures that:
- VCDU counters are a strictly monotonic sequence. - VCDU counters come in packets of four, with each group starting with a multiple of 4.
- chandra_aca.maude_decom.get_aca_images(start, stop, **maude_kwargs)[source]¶
Fetch ACA image telemetry
- Parameters:
- start
timestamp interpreted as a Chandra.Time.DateTime
- stop
timestamp interpreted as a Chandra.Time.DateTime
- maude_kwargs
keyword args passed to maude
- Returns:
- astropy.table.Table
- chandra_aca.maude_decom.get_aca_packets(start, stop, level0=False, combine=False, adjust_time=False, calibrate=False, blobs=None, frames=None, dtype=None, **maude_kwargs)[source]¶
Fetch VCDU 1025-byte frames, extract ACA packets, unpack them and store them in a table.
Incomplete ACA packets (if there is a minor frame missing) can be combined or not into records with complete ACA telemetry. Compare these to calls to the function:
>>> from chandra_aca import maude_decom >>> img = maude_decom.get_aca_packets(684089000, 684089016, combine=True) >>> img = img[img['IMGNUM'] == 0] >>> img['TIME', 'MJF', 'MNF', 'COMMCNT', 'GLBSTAT', 'IMGTYPE', 'IMGROW0', 'IMGCOL0', >>> 'TEMPCCD', 'TEMPHOUS'] <Table masked=True length=4> TIME MJF MNF COMMCNT GLBSTAT IMGTYPE IMGROW0 IMGCOL0 TEMPCCD TEMPHOUS float64 uint32 uint32 uint8 uint8 uint8 int16 int16 int16 int16 ------------- ------ ------ ------- ------- ------- ------- ------- ------- -------- 684089001.869 78006 32 0 0 4 469 -332 -20 83 684089005.969 78006 48 0 0 4 469 -332 -20 83 684089010.069 78006 64 0 0 4 469 -332 -20 83 684089014.169 78006 80 0 0 4 469 -332 -20 83
Using combined=False, results in records with incomplete images. In this case, data can be missing from some records. For example, with 8X8 images, IMGROW0 and IMGCOL0 are present in the first ACA packet (image type 4) while the temperature is present in the second (image type 5):
>>> from chandra_aca import maude_decom >>> img = maude_decom.get_aca_packets(684089000, 684089016, combine=False) >>> img = img[img['IMGNUM'] == 0] >>> img['TIME', 'MJF', 'MNF', 'COMMCNT', 'GLBSTAT', 'IMGTYPE', 'IMGROW0', 'IMGCOL0', >>> 'TEMPCCD', 'TEMPHOUS'] <Table masked=True length=15> TIME MJF MNF COMMCNT GLBSTAT IMGTYPE IMGROW0 IMGCOL0 TEMPCCD TEMPHOUS float64 uint32 uint32 uint8 uint8 uint8 int16 int16 int16 int16 ------------- ------ ------ ------- ------- ------- ------- ------- ------- -------- 684089000.844 78006 28 0 0 7 -- -- -- -- 684089001.869 78006 32 0 0 4 469 -332 -- -- 684089002.894 78006 36 0 0 5 -- -- -20 83 684089003.919 78006 40 0 0 6 -- -- -- -- 684089004.944 78006 44 0 0 7 -- -- -- -- 684089005.969 78006 48 0 0 4 469 -332 -- -- 684089006.994 78006 52 0 0 5 -- -- -20 83 684089008.019 78006 56 0 0 6 -- -- -- -- 684089009.044 78006 60 0 0 7 -- -- -- -- 684089010.069 78006 64 0 0 4 469 -332 -- -- 684089011.094 78006 68 0 0 5 -- -- -20 83 684089012.119 78006 72 0 0 6 -- -- -- -- 684089013.144 78006 76 0 0 7 -- -- -- -- 684089014.169 78006 80 0 0 4 469 -332 -- -- 684089015.194 78006 84 0 0 5 -- -- -20 83
>>> img['IMG'].data[1] masked_BaseColumn(data = [[60.0 97.0 70.0 120.0 74.0 111.0 103.0 108.0] [67.0 90.0 144.0 96.0 88.0 306.0 82.0 67.0] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --]], mask = [[False False False False False False False False] [False False False False False False False False] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True]], fill_value = 1e+20)
>>> img['IMG'].data[2] masked_BaseColumn(data = [[-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [76.0 81.0 160.0 486.0 449.0 215.0 88.0 156.0] [68.0 91.0 539.0 483.0 619.0 412.0 105.0 77.0] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --]], mask = [[ True True True True True True True True] [ True True True True True True True True] [False False False False False False False False] [False False False False False False False False] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True]], fill_value = 1e+20)
>>> img['IMG'].data[3] masked_BaseColumn(data = [[-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [86.0 101.0 408.0 344.0 556.0 343.0 122.0 67.0] [196.0 195.0 114.0 321.0 386.0 115.0 69.0 189.0] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --]], mask = [[ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [False False False False False False False False] [False False False False False False False False] [ True True True True True True True True] [ True True True True True True True True]], fill_value = 1e+20)
>>> img['IMG'].data[4] Out[10]: masked_BaseColumn(data = [[-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [-- -- -- -- -- -- -- --] [67.0 61.0 67.0 176.0 99.0 72.0 79.0 88.0] [70.0 62.0 101.0 149.0 163.0 89.0 60.0 76.0]], mask = [[ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [ True True True True True True True True] [False False False False False False False False] [False False False False False False False False]], fill_value = 1e+20)
- Parameters:
- start
timestamp interpreted as a Chandra.Time.DateTime
- stop
timestamp interpreted as a Chandra.Time.DateTime
- level0bool.
Implies combine=True, adjust_time=True, calibrate=True
- combinebool.
If True, ACA subimages are combined to form a full image (depending on size), If False, ACA subimages are not combined, resulting in multiple rows for 6x6 and 8x8 images.
- adjust_timebool
If True, TIME is at the middle of the integration window. If False, TIME is the VCDU time in telemetry of the packet frame (combine=False) or the VCDU time of the first sub-image of the combined image (combine=True).
- calibratebool
If True, pixel values will be ‘value * imgscale / 32 - 50’ and temperature values will be: 0.4 * value + 273.15
- blobsbool or dict
If set, data is assembled from MAUDE blobs. If it is a dictionary, it must be the output of maude.get_blobs ({‘blobs’: … }).
- framesbool or dict
If set, data is assembled from MAUDE frames. If it is a dictionary, it must be the output of maude.get_frames ({‘data’: … }).
- dtypenp.dtype. Optional.
the dtype to use when creating the resulting table. This is useful to add columns including MSIDs that are present in blobs. If used with frames, most probably you will get and empty column. This option is intended to augment the default dtype. If a more restrictive dtype is used, a KeyError can be raised.
- maude_kwargs
keyword args passed to maude
- Returns:
- astropy.table.Table
- chandra_aca.maude_decom.get_raw_aca_blobs(start, stop, maude_result=None, **maude_kwargs)[source]¶
Fetch MAUDE blobs and group them according to the underlying 225-byte ACA packets.
If the first minor frame in a group of four ACA packets is within (start, stop), the three following minor frames are included if present.
returns a dictionary with keys [‘TIME’, ‘MNF’, ‘MJF’, ‘packets’, ‘flags’]. These correspond to the minor frame time, minor frame count, major frame count, the list of packets, and flags returned by MAUDE respectively.
This is to blobs what get_raw_aca_packets is to frames.
- Parameters:
- start
timestamp interpreted as a Chandra.Time.DateTime
- stop
timestamp interpreted as a Chandra.Time.DateTime
- maude_result
the result of calling maude.get_blobs. Optional.
- maude_kwargs
keyword args passed to maude.get_frames()
- Returns:
- dict
- {‘blobs’: [], ‘names’: np.array([]), ‘types’: np.array([])}
- chandra_aca.maude_decom.get_raw_aca_packets(start, stop, maude_result=None, **maude_kwargs)[source]¶
Fetch 1025-byte VCDU frames using MAUDE and extract a list of 225-byte ACA packets.
If the first minor frame in a group of four ACA packets is within (start, stop), the three following minor frames are included if present.
returns a dictionary with keys [‘TIME’, ‘MNF’, ‘MJF’, ‘packets’, ‘flags’]. These correspond to the minor frame time, minor frame count, major frame count, the list of packets, and flags returned by MAUDE respectively.
This function raises an exception if the VCDU frames in maude_result are not contiguous, which can also happen if the frames are corrupted in some way.
- Parameters:
- start
timestamp interpreted as a Chandra.Time.DateTime
- stop
timestamp interpreted as a Chandra.Time.DateTime
- maude_result
the result of calling maude.get_frames. Optional.
- maude_kwargs
keyword args passed to maude.get_frames()
- Returns:
- dict
- {‘flags’: int, ‘packets’: [],
- ‘TIME’: np.array([]), ‘MNF’: np.array([]), ‘MJF’: np.array([])}