Skip to content

Commit 727bfa0

Browse files
authored
Merge pull request #593 from ngageoint/integration/1.3.61
v1.3.61 release
2 parents bb17d79 + 9fa108d commit 727bfa0

File tree

16 files changed

+629
-43
lines changed

16 files changed

+629
-43
lines changed

.github/workflows/build.yml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: Build packages
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- 'integration/**'
8+
9+
jobs:
10+
build:
11+
# This section builds the distribution for all versions of Python listed in
12+
# the python-version matrix under strategy to confirm that it builds for
13+
# all of those versions. It then uploads the package built by Python 3.9
14+
# for use in later jobs.
15+
name: Build distribution
16+
runs-on: ubuntu-latest
17+
outputs:
18+
version: ${{ steps.extract_version.outputs.raw_version }}
19+
rc_version: ${{ steps.extract_release_candidate_version.outputs.version }}
20+
strategy:
21+
matrix:
22+
python-version: [3.9, 3.10, 3.11, 3.12, 3.13, 3.14]
23+
steps:
24+
# Pull the current branch to build the package from.
25+
- name: Checkout code
26+
uses: actions/checkout@v4
27+
with:
28+
ref: ${{github.ref}}
29+
- name: Set up Python
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: "3.x"
33+
- name: Extract version number from __about__.py
34+
shell: bash
35+
run: echo "raw_version=`sed -n 's/__version__ = \"\(.*\)\"/\1/p' < sarpy/__about__.py`" >> $GITHUB_OUTPUT
36+
id: extract_version
37+
- name: Set version number for release candidate
38+
shell: bash
39+
if: contains(github.ref, 'refs/heads/integration/')
40+
run: |
41+
echo ${{ steps.extract_version.outputs.raw_version }}
42+
rc_version=${{ steps.extract_version.outputs.raw_version }}rc1
43+
sed -i -e "s/__version__ = \"${{ steps.extract_version.outputs.raw_version }}/__version__ = \"$rc_version/g" sarpy/__about__.py
44+
echo "version=$rc_version" >> $GITHUB_OUTPUT
45+
id: extract_release_candidate_version
46+
- name: Install pypa/build
47+
run: >-
48+
python3 -m
49+
pip install
50+
build
51+
--user
52+
- name: Build sarpy binary wheel and a source tarball
53+
run: python3 -m build
54+
- name: Upload all the dists
55+
if: matrix.python-version == 3.9
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: ${{ steps.extract_version.outputs.raw_version }}
59+
path: dist/
60+
overwrite: true
61+
# This job creates a GitHub release and uploads the package contents created
62+
# in the build job to the release.
63+
release:
64+
name: Create release
65+
needs: build
66+
runs-on: ubuntu-latest
67+
steps:
68+
- name: Checkout code
69+
uses: actions/checkout@v4
70+
with:
71+
ref: ${{github.ref}}
72+
- name: Extract version number from __about__.py
73+
shell: bash
74+
run: |
75+
if "${{endswith(github.ref, 'master')}}"
76+
then
77+
echo "version=${{ needs.build.outputs.version }}" >> $GITHUB_OUTPUT
78+
else
79+
echo "version=${{ needs.build.outputs.rc_version }}" >> $GITHUB_OUTPUT
80+
fi
81+
id: extract_version
82+
- name: Download all the dists
83+
uses: actions/download-artifact@v4
84+
with:
85+
name: ${{ needs.build.outputs.version }}
86+
path: dist
87+
- name: Create a release
88+
id: create_release
89+
uses: softprops/action-gh-release@v2
90+
with:
91+
tag_name: v${{ steps.extract_version.outputs.version }}
92+
generate_release_notes: true
93+
name: Version ${{ steps.extract_version.outputs.version }}
94+
draft: false
95+
prerelease: false
96+
target_commitish: ${{github.ref}}
97+
files: dist/*
98+
99+
publish-to-pypi:
100+
name: Publish to PyPI
101+
needs: release
102+
runs-on: ubuntu-latest
103+
environment:
104+
name: development
105+
permissions:
106+
id-token: write
107+
steps:
108+
- name: Download all the dists
109+
uses: actions/download-artifact@v4
110+
with:
111+
name: ${{ needs.build.outputs.version }}
112+
path: dist
113+
merge-multiple: true
114+
- run: ls -R dist
115+
- name: Publish distribution to PyPI
116+
uses: pypa/gh-action-pypi-publish@release/v1
117+
with:
118+
repository-url: https://pypi.org/legacy/

sarpy/__about__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@
2727
'__license__', '__copyright__']
2828

2929
from sarpy.__details__ import __classification__, _post_identifier
30-
_version_number = '1.3.60'
3130

32-
__version__ = _version_number + _post_identifier
31+
__version__ = "1.3.61"
3332

3433
__author__ = "National Geospatial-Intelligence Agency"
3534
__url__ = "https://github.com/ngageoint/sarpy"
36-
__email__ = "richard.m.naething@nga.mil"
35+
__email__ = "SARToolboxDev@nga.mil"
3736

3837

3938
__title__ = "sarpy"

sarpy/io/complex/sicd.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,8 @@ def __init__(
865865
sicd_meta: Optional[SICDType] = None,
866866
sicd_writing_details: Optional[SICDWritingDetails] = None,
867867
check_older_version: bool = False,
868-
check_existence: bool = True):
868+
check_existence: bool = True,
869+
in_memory: bool = None):
869870
"""
870871
871872
Parameters
@@ -878,14 +879,16 @@ def __init__(
878879
NGA applications like SOCET or RemoteView
879880
check_existence : bool
880881
Should we check if the given file already exists?
882+
in_memory : bool
883+
If True force in-memory writing, if False force file writing.
881884
"""
882885

883886
if sicd_meta is None and sicd_writing_details is None:
884887
raise ValueError('One of sicd_meta or sicd_writing_details must be provided.')
885888
if sicd_writing_details is None:
886889
sicd_writing_details = SICDWritingDetails(sicd_meta, check_older_version=check_older_version)
887890
NITFWriter.__init__(
888-
self, file_object, sicd_writing_details, check_existence=check_existence)
891+
self, file_object, sicd_writing_details, check_existence=check_existence, in_memory=in_memory)
889892

890893
@property
891894
def nitf_writing_details(self) -> SICDWritingDetails:

sarpy/io/complex/sicd_elements/blocks.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,12 @@ def get_array(self, dtype=numpy.float64) -> numpy.ndarray:
10901090
"""
10911091

10921092
return numpy.array(self._coefs, dtype=dtype)
1093+
1094+
def __eq__(self, other):
1095+
if not isinstance(other, Poly1DType):
1096+
return TypeError('Provided object is not an Poly1DType.')
1097+
return numpy.array_equal(self.Coefs, other.Coefs) and self.order1 == other.order1
1098+
10931099

10941100
@classmethod
10951101
def from_node(cls, node, xml_ns, ns_key=None, kwargs=None):

sarpy/io/general/data_segment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2053,7 +2053,7 @@ def get_raw_bytes(self, warn: bool = False) -> Union[bytes, Tuple]:
20532053
logger.error(
20542054
'There has been a call to `get_raw_bytes` from {},\n\t'
20552055
'but all pixels are not fully written'.format(self.__class__))
2056-
return self.underlying_array.tobytes()
2056+
return self.underlying_array.view('B').reshape(-1)
20572057

20582058
def flush(self) -> None:
20592059
self._validate_closed()

sarpy/io/general/nitf.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2535,6 +2535,8 @@ def _flatten_bytes(value: Union[bytes, Sequence]) -> bytes:
25352535
return value
25362536
elif isinstance(value, Sequence):
25372537
return b''.join(_flatten_bytes(entry) for entry in value)
2538+
elif isinstance(value, numpy.ndarray) and value.dtype == numpy.uint8:
2539+
return value.reshape(-1)
25382540
else:
25392541
raise TypeError('input must be a bytes object, or a sequence with bytes objects as leaves')
25402542

@@ -3516,7 +3518,8 @@ def __init__(
35163518
self,
35173519
file_object: Union[str, BinaryIO],
35183520
writing_details: NITFWritingDetails,
3519-
check_existence: bool = True):
3521+
check_existence: bool = True,
3522+
in_memory: bool = None):
35203523
"""
35213524
35223525
Parameters
@@ -3525,6 +3528,8 @@ def __init__(
35253528
writing_details : NITFWritingDetails
35263529
check_existence : bool
35273530
Should we check if the given file already exists?
3531+
in_memory : bool
3532+
If True force in-memory writing, if False force file writing.
35283533
35293534
Raises
35303535
------
@@ -3547,13 +3552,17 @@ def __init__(
35473552
raise ValueError('file_object requires a file path or BinaryIO object')
35483553

35493554
self._file_object = file_object
3555+
35503556
if is_real_file(file_object):
35513557
self._file_name = file_object.name
35523558
self._in_memory = False
35533559
else:
35543560
self._file_name = None
35553561
self._in_memory = True
35563562

3563+
if in_memory is not None:
3564+
self._in_memory = in_memory
3565+
35573566
self.nitf_writing_details = writing_details
35583567

35593568
if not self.nitf_writing_details.verify_images_have_no_compression():

sarpy/io/product/sidd.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,8 @@ def __init__(
893893
Sequence[SIDDType2], Sequence[SIDDType1]]] = None,
894894
sicd_meta: Optional[Union[SICDType, Sequence[SICDType]]] = None,
895895
sidd_writing_details: Optional[SIDDWritingDetails] = None,
896-
check_existence: bool = True):
896+
check_existence: bool = True,
897+
in_memory: bool = None):
897898
"""
898899
899900
Parameters
@@ -904,14 +905,16 @@ def __init__(
904905
sidd_writing_details : None|SIDDWritingDetails
905906
check_existence : bool
906907
Should we check if the given file already exists?
908+
in_memory : bool
909+
If True force in-memory writing, if False force file writing.
907910
"""
908911

909912
if sidd_meta is None and sidd_writing_details is None:
910913
raise ValueError('One of sidd_meta or sidd_writing_details must be provided.')
911914
if sidd_writing_details is None:
912915
sidd_writing_details = SIDDWritingDetails(sidd_meta, sicd_meta=sicd_meta)
913916
NITFWriter.__init__(
914-
self, file_object, sidd_writing_details, check_existence=check_existence)
917+
self, file_object, sidd_writing_details, check_existence=check_existence, in_memory=in_memory)
915918

916919
@property
917920
def nitf_writing_details(self) -> SIDDWritingDetails:

sarpy/processing/sidd/sidd_product_creation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
DEFAULT_IMG_REMAP = NRL
4545
DEFAULT_CSI_REMAP = NRL
46-
DEFAULT_DI_REMAP = NRL
46+
DEFAULT_DI_REMAP = NRL
4747

4848
_output_text = 'output_directory `{}`\n\t' \
4949
'does not exist or is not a directory'
@@ -167,7 +167,7 @@ def create_detected_image_sidd(
167167
ortho_bounds = ortho_iterator.ortho_bounds
168168
sidd_structure = create_sidd_structure(
169169
ortho_helper, ortho_bounds,
170-
product_class='Detected Image', pixel_type='MONO{}I'.format(remap_function.bit_depth), version=version)
170+
product_class='Detected Image', pixel_type='MONO{}I'.format(remap_function.bit_depth), version=version, remap_function=remap_function)
171171
# set suggested name
172172
sidd_structure.NITF['SUGGESTED_NAME'] = ortho_helper.sicd.get_suggested_name(ortho_helper.index)+'_IMG'
173173

@@ -256,7 +256,7 @@ def create_csi_sidd(
256256
ortho_bounds = ortho_iterator.ortho_bounds
257257
sidd_structure = create_sidd_structure(
258258
ortho_helper, ortho_bounds,
259-
product_class='Color Subaperture Image', pixel_type='RGB24I', version=version)
259+
product_class='Color Subaperture Image', pixel_type='RGB24I', version=version, remap_function=remap_function)
260260
# set suggested name
261261
sidd_structure.NITF['SUGGESTED_NAME'] = csi_calculator.sicd.get_suggested_name(csi_calculator.index)+'_CSI'
262262

@@ -352,7 +352,7 @@ def create_dynamic_image_sidd(
352352
ortho_bounds = ortho_iterator.ortho_bounds
353353
sidd_structure = create_sidd_structure(
354354
ortho_helper, ortho_bounds,
355-
product_class='Dynamic Image', pixel_type='MONO{}I'.format(remap_function.bit_depth), version=version)
355+
product_class='Dynamic Image', pixel_type='MONO{}I'.format(remap_function.bit_depth), version=version, remap_function=remap_function)
356356
# set suggested name
357357
sidd_structure.NITF['SUGGESTED_NAME'] = subap_calculator.sicd.get_suggested_name(subap_calculator.index)+'__DI'
358358
the_sidds = []

sarpy/processing/sidd/sidd_structure_creation.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def _create_plane_projection_v3(proj_helper, bounds):
209209
#########################
210210
# Version 3 element creation
211211

212-
def create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type):
212+
def create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type, remap_function=None ):
213213
"""
214214
Create a SIDD version 3.0 structure based on the orthorectification helper
215215
and pixel bounds.
@@ -244,9 +244,9 @@ def _create_display_v3():
244244
NonInteractiveProcessing=[NonInteractiveProcessingType3(
245245
ProductGenerationOptions=ProductGenerationOptionsType3(
246246
DataRemapping=NewLookupTableType3(
247-
LUTName='DENSITY',
247+
LUTName=remap_function.name.upper(),
248248
Predefined=PredefinedLookupType3(
249-
DatabaseName='DENSITY'))),
249+
DatabaseName=remap_function.name.upper()))),
250250
RRDS=RRDSType3(DownsamplingMethod='DECIMATE'),
251251
band=i+1) for i in range(bands)],
252252
InteractiveProcessing=[InteractiveProcessingType3(
@@ -326,7 +326,7 @@ def _create_exploitation_v3():
326326
#########################
327327
# Version 2 element creation
328328

329-
def create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type):
329+
def create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type, remap_function=None ):
330330
"""
331331
Create a SIDD version 2.0 structure based on the orthorectification helper
332332
and pixel bounds.
@@ -361,9 +361,9 @@ def _create_display_v2():
361361
NonInteractiveProcessing=[NonInteractiveProcessingType2(
362362
ProductGenerationOptions=ProductGenerationOptionsType2(
363363
DataRemapping=NewLookupTableType(
364-
LUTName='DENSITY',
364+
LUTName=remap_function.name.upper(),
365365
Predefined=PredefinedLookupType(
366-
DatabaseName='DENSITY'))),
366+
DatabaseName=remap_function.name.upper()))),
367367
RRDS=RRDSType2(DownsamplingMethod='DECIMATE'),
368368
band=i+1) for i in range(bands)],
369369
InteractiveProcessing=[InteractiveProcessingType2(
@@ -521,7 +521,7 @@ def _create_exploitation_v1():
521521
##########################
522522
# Switchable version SIDD structure
523523

524-
def create_sidd_structure(ortho_helper, bounds, product_class, pixel_type, version=3):
524+
def create_sidd_structure(ortho_helper, bounds, product_class, pixel_type, version=3, remap_function=None):
525525
"""
526526
Create a SIDD structure, with version specified, based on the orthorectification
527527
helper and pixel bounds.
@@ -550,6 +550,6 @@ def create_sidd_structure(ortho_helper, bounds, product_class, pixel_type, versi
550550
if version == 1:
551551
return create_sidd_structure_v1(ortho_helper, bounds, product_class, pixel_type)
552552
elif version == 2:
553-
return create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type)
553+
return create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type, remap_function=remap_function )
554554
else:
555-
return create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type)
555+
return create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type, remap_function=remap_function )

sarpy/utils/create_product.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ def main(args=None):
5555
parser.add_argument(
5656
'-m', '--method', default='nearest', choices=['nearest', ]+['spline_{}'.format(i) for i in range(1, 6)],
5757
help="The interpolation method.")
58+
parser.add_argument(
59+
'-b', '--bit_depth', default='8', choices=['8', '16' ],
60+
help="SIDD product pixel bit depth.")
5861
parser.add_argument(
5962
'--version', default=2, type=int, choices=[1, 2, 3],
6063
help="The version of the SIDD standard used.")
@@ -80,7 +83,7 @@ def main(args=None):
8083
ortho_helper = NearestNeighborMethod(reader, index=i)
8184
if args.type == 'detected':
8285
create_detected_image_sidd(ortho_helper, args.output_directory,
83-
remap_function=remap.get_registered_remap(args.remap),
86+
remap_function=remap.get_registered_remap(args.remap, bit_depth=args.bit_depth ),
8487
version=args.version, include_sicd=args.sicd)
8588
elif args.type == 'csi':
8689
create_csi_sidd(ortho_helper, args.output_directory,

0 commit comments

Comments
 (0)