Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9e64be3
Optimize memory management in file write
brianhendee May 5, 2025
57ab912
Allow memory management to be turned on
brianhendee May 7, 2025
a0b8188
Update setup.py
petersontex Jun 17, 2025
e0edb5f
Merge pull request #588 from brianhendee/optimize-file-write
petersontex Jun 18, 2025
078bf76
Update dependencies in setup.py 02
petersontex Jun 20, 2025
05c4ca9
First in memory write test attempt
Jun 20, 2025
c1aa88f
First in memory write test attempt 02
Jun 20, 2025
a3d3d63
Merge pull request #589 from petersontex/optimize-file-write
petersontex Jun 23, 2025
9b071a3
Update sidd_product_creation.py
jonlorax Jun 26, 2025
61da4cb
Update sidd_structure_creation.py
jonlorax Jun 26, 2025
c05d8c4
Update create_product.py
jonlorax Jun 26, 2025
89ee214
Update remap.py
jonlorax Jun 26, 2025
62ed593
Merge pull request #590 from jonlorax/16bit_work_staging
petersontex Jun 26, 2025
466fbd1
Update __about__.py
petersontex Jun 27, 2025
7877e7b
Create build.yml
petersontex Jun 27, 2025
84ed587
Update sidd_product_creation.py
jonlorax Jul 2, 2025
ddcb86c
Update remap.py
jonlorax Jul 2, 2025
96945ee
Update test_remap.py
jonlorax Jul 2, 2025
b94303d
Added testing for SICDWriter.
Jul 4, 2025
9732028
Incremental improvement to SICDWriter tests and added __eq__ to Poly1…
Jul 4, 2025
f6b2ac6
Update remap.py
jonlorax Jul 7, 2025
6bb5a8b
Update remap.py
jonlorax Jul 7, 2025
174c2a3
Updated sicdwriter tests.
Jul 8, 2025
e52a26c
Updated sicdwriter tests' names.
Jul 8, 2025
d1b9df4
Update sidd_product_creation.py
jonlorax Jul 8, 2025
0d60bc9
Update sidd_structure_creation.py
jonlorax Jul 8, 2025
310bb10
Update remap.py
jonlorax Jul 8, 2025
1b6925c
Moved SICDWriter tests to individual test file.
Jul 9, 2025
8dcfece
Update test_remap.py
jonlorax Jul 10, 2025
6d6cff9
Update remap.py
jonlorax Jul 10, 2025
5911f6a
Update test_remap.py
jonlorax Jul 10, 2025
8860dc9
Update remap.py
jonlorax Jul 10, 2025
68b6083
Merge pull request #591 from jonlorax/16bit_work_staging
petersontex Jul 11, 2025
bd5fa5c
Merge branch 'ngageoint:staging' into staging
petersontex Jul 11, 2025
28c06e3
Merge pull request #592 from petersontex/staging
petersontex Jul 11, 2025
9fa108d
Update build.yml
petersontex Jul 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: Build packages

on:
push:
branches:
- master
- 'integration/**'

jobs:
build:
# This section builds the distribution for all versions of Python listed in
# the python-version matrix under strategy to confirm that it builds for
# all of those versions. It then uploads the package built by Python 3.9
# for use in later jobs.
name: Build distribution
runs-on: ubuntu-latest
outputs:
version: ${{ steps.extract_version.outputs.raw_version }}
rc_version: ${{ steps.extract_release_candidate_version.outputs.version }}
strategy:
matrix:
python-version: [3.9, 3.10, 3.11, 3.12, 3.13, 3.14]
steps:
# Pull the current branch to build the package from.
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{github.ref}}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Extract version number from __about__.py
shell: bash
run: echo "raw_version=`sed -n 's/__version__ = \"\(.*\)\"/\1/p' < sarpy/__about__.py`" >> $GITHUB_OUTPUT
id: extract_version
- name: Set version number for release candidate
shell: bash
if: contains(github.ref, 'refs/heads/integration/')
run: |
echo ${{ steps.extract_version.outputs.raw_version }}
rc_version=${{ steps.extract_version.outputs.raw_version }}rc1
sed -i -e "s/__version__ = \"${{ steps.extract_version.outputs.raw_version }}/__version__ = \"$rc_version/g" sarpy/__about__.py
echo "version=$rc_version" >> $GITHUB_OUTPUT
id: extract_release_candidate_version
- name: Install pypa/build
run: >-
python3 -m
pip install
build
--user
- name: Build sarpy binary wheel and a source tarball
run: python3 -m build
- name: Upload all the dists
if: matrix.python-version == 3.9
uses: actions/upload-artifact@v4
with:
name: ${{ steps.extract_version.outputs.raw_version }}
path: dist/
overwrite: true
# This job creates a GitHub release and uploads the package contents created
# in the build job to the release.
release:
name: Create release
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{github.ref}}
- name: Extract version number from __about__.py
shell: bash
run: |
if "${{endswith(github.ref, 'master')}}"
then
echo "version=${{ needs.build.outputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${{ needs.build.outputs.rc_version }}" >> $GITHUB_OUTPUT
fi
id: extract_version
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.version }}
path: dist
- name: Create a release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.extract_version.outputs.version }}
generate_release_notes: true
name: Version ${{ steps.extract_version.outputs.version }}
draft: false
prerelease: false
target_commitish: ${{github.ref}}
files: dist/*

publish-to-pypi:
name: Publish to PyPI
needs: release
runs-on: ubuntu-latest
environment:
name: development
permissions:
id-token: write
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.version }}
path: dist
merge-multiple: true
- run: ls -R dist
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://pypi.org/legacy/
5 changes: 2 additions & 3 deletions sarpy/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@
'__license__', '__copyright__']

from sarpy.__details__ import __classification__, _post_identifier
_version_number = '1.3.60'

__version__ = _version_number + _post_identifier
__version__ = "1.3.61"

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


__title__ = "sarpy"
Expand Down
7 changes: 5 additions & 2 deletions sarpy/io/complex/sicd.py
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,8 @@ def __init__(
sicd_meta: Optional[SICDType] = None,
sicd_writing_details: Optional[SICDWritingDetails] = None,
check_older_version: bool = False,
check_existence: bool = True):
check_existence: bool = True,
in_memory: bool = None):
"""

Parameters
Expand All @@ -878,14 +879,16 @@ def __init__(
NGA applications like SOCET or RemoteView
check_existence : bool
Should we check if the given file already exists?
in_memory : bool
If True force in-memory writing, if False force file writing.
"""

if sicd_meta is None and sicd_writing_details is None:
raise ValueError('One of sicd_meta or sicd_writing_details must be provided.')
if sicd_writing_details is None:
sicd_writing_details = SICDWritingDetails(sicd_meta, check_older_version=check_older_version)
NITFWriter.__init__(
self, file_object, sicd_writing_details, check_existence=check_existence)
self, file_object, sicd_writing_details, check_existence=check_existence, in_memory=in_memory)

@property
def nitf_writing_details(self) -> SICDWritingDetails:
Expand Down
6 changes: 6 additions & 0 deletions sarpy/io/complex/sicd_elements/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,12 @@ def get_array(self, dtype=numpy.float64) -> numpy.ndarray:
"""

return numpy.array(self._coefs, dtype=dtype)

def __eq__(self, other):
if not isinstance(other, Poly1DType):
return TypeError('Provided object is not an Poly1DType.')
return numpy.array_equal(self.Coefs, other.Coefs) and self.order1 == other.order1


@classmethod
def from_node(cls, node, xml_ns, ns_key=None, kwargs=None):
Expand Down
2 changes: 1 addition & 1 deletion sarpy/io/general/data_segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -2053,7 +2053,7 @@ def get_raw_bytes(self, warn: bool = False) -> Union[bytes, Tuple]:
logger.error(
'There has been a call to `get_raw_bytes` from {},\n\t'
'but all pixels are not fully written'.format(self.__class__))
return self.underlying_array.tobytes()
return self.underlying_array.view('B').reshape(-1)

def flush(self) -> None:
self._validate_closed()
Expand Down
11 changes: 10 additions & 1 deletion sarpy/io/general/nitf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2535,6 +2535,8 @@ def _flatten_bytes(value: Union[bytes, Sequence]) -> bytes:
return value
elif isinstance(value, Sequence):
return b''.join(_flatten_bytes(entry) for entry in value)
elif isinstance(value, numpy.ndarray) and value.dtype == numpy.uint8:
return value.reshape(-1)
else:
raise TypeError('input must be a bytes object, or a sequence with bytes objects as leaves')

Expand Down Expand Up @@ -3516,7 +3518,8 @@ def __init__(
self,
file_object: Union[str, BinaryIO],
writing_details: NITFWritingDetails,
check_existence: bool = True):
check_existence: bool = True,
in_memory: bool = None):
"""

Parameters
Expand All @@ -3525,6 +3528,8 @@ def __init__(
writing_details : NITFWritingDetails
check_existence : bool
Should we check if the given file already exists?
in_memory : bool
If True force in-memory writing, if False force file writing.

Raises
------
Expand All @@ -3547,13 +3552,17 @@ def __init__(
raise ValueError('file_object requires a file path or BinaryIO object')

self._file_object = file_object

if is_real_file(file_object):
self._file_name = file_object.name
self._in_memory = False
else:
self._file_name = None
self._in_memory = True

if in_memory is not None:
self._in_memory = in_memory

self.nitf_writing_details = writing_details

if not self.nitf_writing_details.verify_images_have_no_compression():
Expand Down
7 changes: 5 additions & 2 deletions sarpy/io/product/sidd.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,8 @@ def __init__(
Sequence[SIDDType2], Sequence[SIDDType1]]] = None,
sicd_meta: Optional[Union[SICDType, Sequence[SICDType]]] = None,
sidd_writing_details: Optional[SIDDWritingDetails] = None,
check_existence: bool = True):
check_existence: bool = True,
in_memory: bool = None):
"""

Parameters
Expand All @@ -904,14 +905,16 @@ def __init__(
sidd_writing_details : None|SIDDWritingDetails
check_existence : bool
Should we check if the given file already exists?
in_memory : bool
If True force in-memory writing, if False force file writing.
"""

if sidd_meta is None and sidd_writing_details is None:
raise ValueError('One of sidd_meta or sidd_writing_details must be provided.')
if sidd_writing_details is None:
sidd_writing_details = SIDDWritingDetails(sidd_meta, sicd_meta=sicd_meta)
NITFWriter.__init__(
self, file_object, sidd_writing_details, check_existence=check_existence)
self, file_object, sidd_writing_details, check_existence=check_existence, in_memory=in_memory)

@property
def nitf_writing_details(self) -> SIDDWritingDetails:
Expand Down
8 changes: 4 additions & 4 deletions sarpy/processing/sidd/sidd_product_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

DEFAULT_IMG_REMAP = NRL
DEFAULT_CSI_REMAP = NRL
DEFAULT_DI_REMAP = NRL
DEFAULT_DI_REMAP = NRL

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

Expand Down Expand Up @@ -256,7 +256,7 @@ def create_csi_sidd(
ortho_bounds = ortho_iterator.ortho_bounds
sidd_structure = create_sidd_structure(
ortho_helper, ortho_bounds,
product_class='Color Subaperture Image', pixel_type='RGB24I', version=version)
product_class='Color Subaperture Image', pixel_type='RGB24I', version=version, remap_function=remap_function)
# set suggested name
sidd_structure.NITF['SUGGESTED_NAME'] = csi_calculator.sicd.get_suggested_name(csi_calculator.index)+'_CSI'

Expand Down Expand Up @@ -352,7 +352,7 @@ def create_dynamic_image_sidd(
ortho_bounds = ortho_iterator.ortho_bounds
sidd_structure = create_sidd_structure(
ortho_helper, ortho_bounds,
product_class='Dynamic Image', pixel_type='MONO{}I'.format(remap_function.bit_depth), version=version)
product_class='Dynamic Image', pixel_type='MONO{}I'.format(remap_function.bit_depth), version=version, remap_function=remap_function)
# set suggested name
sidd_structure.NITF['SUGGESTED_NAME'] = subap_calculator.sicd.get_suggested_name(subap_calculator.index)+'__DI'
the_sidds = []
Expand Down
18 changes: 9 additions & 9 deletions sarpy/processing/sidd/sidd_structure_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def _create_plane_projection_v3(proj_helper, bounds):
#########################
# Version 3 element creation

def create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type):
def create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type, remap_function=None ):
"""
Create a SIDD version 3.0 structure based on the orthorectification helper
and pixel bounds.
Expand Down Expand Up @@ -244,9 +244,9 @@ def _create_display_v3():
NonInteractiveProcessing=[NonInteractiveProcessingType3(
ProductGenerationOptions=ProductGenerationOptionsType3(
DataRemapping=NewLookupTableType3(
LUTName='DENSITY',
LUTName=remap_function.name.upper(),
Predefined=PredefinedLookupType3(
DatabaseName='DENSITY'))),
DatabaseName=remap_function.name.upper()))),
RRDS=RRDSType3(DownsamplingMethod='DECIMATE'),
band=i+1) for i in range(bands)],
InteractiveProcessing=[InteractiveProcessingType3(
Expand Down Expand Up @@ -326,7 +326,7 @@ def _create_exploitation_v3():
#########################
# Version 2 element creation

def create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type):
def create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type, remap_function=None ):
"""
Create a SIDD version 2.0 structure based on the orthorectification helper
and pixel bounds.
Expand Down Expand Up @@ -361,9 +361,9 @@ def _create_display_v2():
NonInteractiveProcessing=[NonInteractiveProcessingType2(
ProductGenerationOptions=ProductGenerationOptionsType2(
DataRemapping=NewLookupTableType(
LUTName='DENSITY',
LUTName=remap_function.name.upper(),
Predefined=PredefinedLookupType(
DatabaseName='DENSITY'))),
DatabaseName=remap_function.name.upper()))),
RRDS=RRDSType2(DownsamplingMethod='DECIMATE'),
band=i+1) for i in range(bands)],
InteractiveProcessing=[InteractiveProcessingType2(
Expand Down Expand Up @@ -521,7 +521,7 @@ def _create_exploitation_v1():
##########################
# Switchable version SIDD structure

def create_sidd_structure(ortho_helper, bounds, product_class, pixel_type, version=3):
def create_sidd_structure(ortho_helper, bounds, product_class, pixel_type, version=3, remap_function=None):
"""
Create a SIDD structure, with version specified, based on the orthorectification
helper and pixel bounds.
Expand Down Expand Up @@ -550,6 +550,6 @@ def create_sidd_structure(ortho_helper, bounds, product_class, pixel_type, versi
if version == 1:
return create_sidd_structure_v1(ortho_helper, bounds, product_class, pixel_type)
elif version == 2:
return create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type)
return create_sidd_structure_v2(ortho_helper, bounds, product_class, pixel_type, remap_function=remap_function )
else:
return create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type)
return create_sidd_structure_v3(ortho_helper, bounds, product_class, pixel_type, remap_function=remap_function )
5 changes: 4 additions & 1 deletion sarpy/utils/create_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def main(args=None):
parser.add_argument(
'-m', '--method', default='nearest', choices=['nearest', ]+['spline_{}'.format(i) for i in range(1, 6)],
help="The interpolation method.")
parser.add_argument(
'-b', '--bit_depth', default='8', choices=['8', '16' ],
help="SIDD product pixel bit depth.")
parser.add_argument(
'--version', default=2, type=int, choices=[1, 2, 3],
help="The version of the SIDD standard used.")
Expand All @@ -80,7 +83,7 @@ def main(args=None):
ortho_helper = NearestNeighborMethod(reader, index=i)
if args.type == 'detected':
create_detected_image_sidd(ortho_helper, args.output_directory,
remap_function=remap.get_registered_remap(args.remap),
remap_function=remap.get_registered_remap(args.remap, bit_depth=args.bit_depth ),
version=args.version, include_sicd=args.sicd)
elif args.type == 'csi':
create_csi_sidd(ortho_helper, args.output_directory,
Expand Down
Loading
Loading