Repository: spacetelescope/jwst

Issue:
subarray bounding boxes are 1 pixel too small
_Issue [JP-1818](https://jira.stsci.edu/browse/JP-1818) was created on JIRA by [James Davies](https://jira.stsci.edu/secure/ViewProfile.jspa?name=jdavies):_

Testing of

#5507

found a bug in `jwst.assign_wcs` where NIRCam time-series subarrays of 64x64 were getting bounding boxes of size

```
In [9]: result
Out[9]: <CubeModel(4, 64, 64) from jw00312006001_02102_00001-seg001_nrcb1_rateints.fits>

In [11]: result.meta.subarray.instance
Out[11]: 
{'fastaxis': 1,
 'name': 'SUB64P',
 'slowaxis': -2,
 'xsize': 64,
 'xstart': 1985,
 'ysize': 64,
 'ystart': 1985}

In [12]: result.meta.wcs.bounding_box
Out[12]: ((-0.5, 62.5), (-0.5, 62.5))
```

It looks like this is a general problem for all subarray bounding boxes.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=h1) Report
> Merging [#5543](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=desc) (8b06fea) into [master](https://codecov.io/gh/spacetelescope/jwst/commit/c129fee33dbdd7c99a427e4425b81b940ab49dd0?el=desc) (c129fee) will **increase** coverage by `0.01%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/spacetelescope/jwst/pull/5543/graphs/tree.svg?width=650&height=150&src=pr&token=Utf5Zs9g7z)](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #5543      +/-   ##
==========================================
+ Coverage   71.25%   71.26%   +0.01%     
==========================================
  Files         410      410              
  Lines       36426    36462      +36     
  Branches     5677     5683       +6     
==========================================
+ Hits        25954    25985      +31     
- Misses       8826     8831       +5     
  Partials     1646     1646              
```

| Flag | Coverage Δ | | *Carryforward flag |
|---|---|---|---|
| nightly | `71.24% <0.00%> (ø)` | | Carriedforward from [c129fee](https://codecov.io/gh/spacetelescope/jwst/commit/c129fee33dbdd7c99a427e4425b81b940ab49dd0) |
| unit | `51.82% <100.00%> (ø)` | | |

*This pull request uses carry forward flags. [Click here](https://docs.codecov.io/docs/carryforward-flags) to find out more.

| [Impacted Files](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [jwst/assign\_wcs/util.py](https://codecov.io/gh/spacetelescope/jwst/pull/5543/diff?src=pr&el=tree#diff-andzdC9hc3NpZ25fd2NzL3V0aWwucHk=) | `72.42% <100.00%> (+1.25%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=footer). Last update [c129fee...b30d74b](https://codecov.io/gh/spacetelescope/jwst/pull/5543?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index d594dd381..62e506adc 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -17,6 +17,8 @@ assign_wcs
 
 - Added SIP approximation to WCS for imaging modes. FITS WCS keywords added to meta.wcsinfo. [#5507]
 
+- Fix bug where subarray bounding boxes were 1 pixel too small. [#5543]
+
 associations
 ------------
 
@@ -163,6 +165,7 @@ set_telescope_pointing
 ----------------------
 
 - Add logging of the found quaternion information [#5495]
+- Handle cases where engineering database's pointing mnemonics are all zero over the requested time range [#5540]
 
 skymatch
 --------
diff --git a/jwst/assign_wcs/util.py b/jwst/assign_wcs/util.py
index 8be97bfec..f3c6870ca 100644
--- a/jwst/assign_wcs/util.py
+++ b/jwst/assign_wcs/util.py
@@ -830,10 +830,9 @@ def bounding_box_from_subarray(input_model):
     bb_yend = -0.5
 
     if input_model.meta.subarray.xsize is not None:
-        # Implicitely there's bb_xstart + 0.5 and xsize -1 - 0.5
-        bb_xend = input_model.meta.subarray.xsize - 1 - 0.5
+        bb_xend = input_model.meta.subarray.xsize - 0.5
     if input_model.meta.subarray.ysize is not None:
-        bb_yend = input_model.meta.subarray.ysize - 1 - 0.5
+        bb_yend = input_model.meta.subarray.ysize - 0.5
 
     bbox = ((bb_ystart, bb_yend), (bb_xstart, bb_xend))
     return bbox
diff --git a/jwst/lib/set_telescope_pointing.py b/jwst/lib/set_telescope_pointing.py
index e710e7657..0038eb5ff 100644
--- a/jwst/lib/set_telescope_pointing.py
+++ b/jwst/lib/set_telescope_pointing.py
@@ -592,8 +592,12 @@ def calc_wcs_over_time(obsstart, obsend, engdb_url=None, tolerance=60, reduce_fu
     vinfos = list()
 
     # Calculate WCS
-    pointings = get_pointing(obsstart, obsend, engdb_url=engdb_url,
+    try:
+        pointings = get_pointing(obsstart, obsend, engdb_url=engdb_url,
                              tolerance=tolerance, reduce_func=reduce_func)
+    except ValueError:
+        logger.warning("Cannot get valid engineering mnemonics from engineering database")
+        raise
     if not isinstance(pointings, list):
         pointings = [pointings]
     for pointing in pointings:
@@ -1546,17 +1550,41 @@ def pointing_from_average(mnemonics):
         eng_param.obstime.unix
         for eng_param in mnemonics['SA_ZATTEST1']
     ]
-    obstime = Time(np.average(times), format='unix')
-
+    goodtimes = []
+    for this_time in times:
+        if this_time != 0.0:
+            goodtimes.append(this_time)
+    if len(goodtimes) > 0:
+        obstime = Time(np.average(goodtimes), format='unix')
+    else:
+        raise ValueError("No valid times in range")
     # Get averages for all the mnemonics.
     mnemonic_averages = {}
+    zero_mnemonics = []
     for mnemonic in mnemonics:
         values = [
             eng_param.value
             for eng_param in mnemonics[mnemonic]
         ]
-        mnemonic_averages[mnemonic] = np.average(values)
-
+        # Weed out mnemonic entries that are zero
+        # 'SA_ZADUCMDX' and 'SA_ZADUCMDY' can be zero
+        if mnemonic not in ['SA_ZADUCMDX', 'SA_ZADUCMDY']:
+            good_mnemonic = []
+            for this_value in values:
+                if this_value != 0.0:
+                    good_mnemonic.append(this_value)
+            if len(good_mnemonic) > 0:
+                mnemonic_averages[mnemonic] = np.average(good_mnemonic)
+            else:
+                zero_mnemonics.append(mnemonic)
+        else:
+            mnemonic_averages[mnemonic] = np.average(values)
+    # Raise exception if there are mnemonics with only zeros in the time range
+    if len(zero_mnemonics):
+        logger.warning("The following engineering mnemonics only contained zeros in the requested time interval:")
+        badmnemonicsstring = ' '.join(zero_mnemonics)
+        logger.info(badmnemonicsstring)
+        raise ValueError("Bad telemetry values")
     # Fill out the pointing matrices.
     q = np.array([
         mnemonic_averages['SA_ZATTEST1'],


Test patch:
diff --git a/jwst/assign_wcs/tests/test_util.py b/jwst/assign_wcs/tests/test_util.py
index 763a939e5..9ffb3a119 100644
--- a/jwst/assign_wcs/tests/test_util.py
+++ b/jwst/assign_wcs/tests/test_util.py
@@ -101,4 +101,4 @@ def test_bounding_box_from_subarray():
     im.meta.subarray.ystart = 6
     im.meta.subarray.xsize = 400
     im.meta.subarray.ysize = 600
-    assert bounding_box_from_subarray(im) == ((-.5, 598.5), (-.5, 398.5))
+    assert bounding_box_from_subarray(im) == ((-.5, 599.5), (-.5, 399.5))