Skip to content

Commit efcc1e6

Browse files
authored
Merge pull request #606 from ngageoint/integration/1.3.62
Release v1.3.62
2 parents abbd570 + 706b6ca commit efcc1e6

18 files changed

Lines changed: 2246 additions & 31 deletions

File tree

sarpy/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
from sarpy.__details__ import __classification__, _post_identifier
3030

31-
__version__ = "1.3.61.1"
31+
__version__ = "1.3.62"
3232

3333
__author__ = "National Geospatial-Intelligence Agency"
3434
__url__ = "https://github.com/ngageoint/sarpy"

sarpy/io/DEM/DTED.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ def from_reference_point(cls, ref_point, dted_list, dem_type=None, geoid_file=No
651651
DTEDInterpolator
652652
"""
653653

654-
pad_value = float(pad_value)
654+
pad_value = abs( float(pad_value) )
655655
if pad_value > 0.5:
656656
pad_value = 0.5
657657
if pad_value < 0.05:
@@ -660,7 +660,7 @@ def from_reference_point(cls, ref_point, dted_list, dem_type=None, geoid_file=No
660660
lat_max = min(ref_point[0] + lat_diff, 90)
661661
lat_min = max(ref_point[0] - lat_diff, -90)
662662

663-
lon_diff = min(15, lat_diff/(numpy.sin(numpy.deg2rad(ref_point[0]))))
663+
lon_diff = min(15, abs( lat_diff/(numpy.cos(numpy.deg2rad(ref_point[0])))))
664664
lon_max = ref_point[1] + lon_diff
665665
if lon_max > 180:
666666
lon_max -= 360

sarpy/io/general/nitf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2693,7 +2693,9 @@ def item_bytes(self, value: Union[bytes, Sequence]) -> None:
26932693
'item_bytes input has size {},\n\t'
26942694
'but item_size has been defined as {}.'.format(len(value), self._item_size))
26952695
self._item_bytes = value
2696-
self.item_size = len(value)
2696+
if self._item_size is None or self.item_size != len(value):
2697+
self.item_size = len(value)
2698+
26972699

26982700
@property
26992701
def item_written(self) -> bool:
@@ -4125,9 +4127,7 @@ def get_data_segments(self) -> List[DataSegment]:
41254127

41264128
def flush(self, force: bool = False) -> None:
41274129
self._validate_closed()
4128-
41294130
BaseWriter.flush(self, force=force)
4130-
41314131
try:
41324132
if self._in_memory:
41334133
if self._image_segment_data_segments is not None:

sarpy/io/general/slice_parsing.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,12 @@ def verify_subscript(
147147
subscript = subscript[:ellipsis_location]
148148
elif ellipsis_location == 0:
149149
init_pad = ndim - len(subscript) + 1
150-
subscript = tuple([None, ]*init_pad) + subscript[1:]
150+
subscript = tuple([None, ]*init_pad) + tuple(subscript[1:])
151151
else: # ellipsis in the middle
152152
middle_pad = ndim - len(subscript) + 1
153-
subscript = subscript[:ellipsis_location] + tuple([None, ]*middle_pad) + subscript[ellipsis_location+1:]
153+
subscript = tuple(subscript[:ellipsis_location]) + \
154+
tuple([None, ]*middle_pad) + \
155+
tuple(subscript[ellipsis_location+1:])
154156

155157
if len(subscript) > ndim:
156158
raise ValueError('More subscript entries ({}) than shape dimensions ({}).'.format(len(subscript), ndim))

sarpy/io/product/sidd.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,17 @@ def _get_ftitle(self, index: int = 0) -> str:
656656
ftitle = 'SIDD: Unknown'
657657
return ftitle
658658

659+
# File Creation DateTime
659660
def _get_fdt(self, index: int) -> Optional[str]:
661+
sidd = self.sidd_meta[index]
662+
if sidd.ProductCreation.ProcessorInformation.ProcessingDateTime is not None:
663+
the_time = sidd.ProductCreation.ProcessorInformation.ProcessingDateTime.astype('datetime64[s]')
664+
return re.sub(r'[^0-9]', '', str(the_time))
665+
else:
666+
return None
667+
668+
# Image Acquisition (Collection) Datetime
669+
def _get_collection_datetime(self, index: int) -> Optional[str]:
660670
sidd = self.sidd_meta[index]
661671
if sidd.ExploitationFeatures.Collections[0].Information.CollectionDateTime is not None:
662672
the_time = sidd.ExploitationFeatures.Collections[0].Information.CollectionDateTime.astype('datetime64[s]')
@@ -730,7 +740,7 @@ def _create_image_segment_for_sidd(
730740
'IC': 'NC',
731741
'IID2': self._get_iid2(sidd_index),
732742
'ISORCE': self._get_isorce(sidd_index),
733-
'IDATIM': self._get_fdt(sidd_index)
743+
'IDATIM': self._get_collection_datetime(sidd_index)
734744
}
735745

736746
if sidd.Display.PixelType == 'MONO8I':

sarpy/io/product/sidd2_elements/Compression.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from typing import Union
99

10+
import xml.etree.ElementTree
1011
import numpy
1112

1213
from sarpy.io.xml.base import Serializable
@@ -16,6 +17,8 @@
1617
from .base import DEFAULT_STRICT, FLOAT_FORMAT
1718

1819

20+
# default_strict is set to False which is why invalid types don't throw an error for NumWaveletLevels, NumBands, or LayerInfo
21+
1922
class J2KSubtype(Serializable):
2023
"""
2124
The Jpeg 2000 subtype.
@@ -55,9 +58,38 @@ def __init__(self, NumWaveletLevels=None, NumBands=None, LayerInfo=None, **kwarg
5558
self._xml_ns_key = kwargs['_xml_ns_key']
5659
self.NumWaveletLevels = NumWaveletLevels
5760
self.NumBands = NumBands
58-
self.LayerInfo = LayerInfo
61+
self.setLayerInfoType(LayerInfo)
5962
super(J2KSubtype, self).__init__(**kwargs)
6063

64+
def setLayerInfoType(self, obj):
65+
"""
66+
Since the LayerInfo is defined as an array of bit rates in the definition above and SarPy returns an
67+
element tree with the bit rates nested within different layers, this function is used to parse and return
68+
LayerInfo as an array of bit rates
69+
"""
70+
# if LayerInfo is an ElementTree as expected, then it gets parsed to return an array of bit rates
71+
ET = xml.etree.ElementTree
72+
if isinstance( obj, ET.Element):
73+
numLayers = int(obj.attrib['numLayers'])
74+
if (numLayers == 0):
75+
return
76+
bitrates = numpy.zeros(numLayers)
77+
78+
for i in range(numLayers):
79+
bitrates[i] = float(obj[i][0].text)
80+
self.LayerInfo = bitrates
81+
82+
# if LayerInfo is a numpy.ndarray, a list, or a tuple per the above definition, return LayerInfo
83+
elif isinstance(obj, (list, tuple, numpy.ndarray)):
84+
self.LayerInfo = obj
85+
86+
# none object handler since it states that LayerInfo can be None in the definition above and it isn't a required field
87+
elif obj is None:
88+
self.LayerInfo = None
89+
90+
# throw an error if LayerInfo is an invalid type and an array of bitrates is unable to be generated
91+
else:
92+
raise TypeError(f'Invalid input type for LayerInfo: {type(obj)}. Must be an ElementTree, list, tuple, ndarray, or None.')
6193

6294
class J2KType(Serializable):
6395
"""
@@ -110,4 +142,4 @@ def __init__(self, J2K=None, **kwargs):
110142
if '_xml_ns_key' in kwargs:
111143
self._xml_ns_key = kwargs['_xml_ns_key']
112144
self.J2K = J2K
113-
super(CompressionType, self).__init__(**kwargs)
145+
super(CompressionType, self).__init__(**kwargs)

0 commit comments

Comments
 (0)