Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release070 #32

Merged
merged 7 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ and the release date, in year-month-day format (see examples below).
Unreleased
----------

0.7.0 (2023-02-05)
------------------

Changed
^^^^^^^
- The light_records.py table now just records state changes (from 'on' to 'off' or
vice-versa).
- create_image.py's create() method now has an imgtype argument that default to TIFF
(but can be PNG).
- junc_image_req_ldst.py got some additional columns to manage the Science Team
evaluation of images acquired from Image Requests.
- create_pano.py's make_pano_product() function renamed to make_pano_record().
Expand Down Expand Up @@ -73,6 +78,7 @@ Removed
- ldst_verification.py because the evaluation activity reflected here was on a per-image
basis, but it has been revised to be on a per-Image-Request basis.


0.6.1 (2023-09-25)
------------------

Expand Down
7 changes: 3 additions & 4 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ Get Started!
Ready to contribute? Here's how to set up `vipersci` for local development.

At this time, the target version of Python for this library is 3.8 in order to
align with current anticipated mission systems. The intent is to allow this library
to work successfully against Python as early as version 3.6.
align with current anticipated mission systems.

1. Fork the `vipersci` repo on GitHub.
2. Clone your fork locally::
Expand Down Expand Up @@ -89,7 +88,7 @@ to work successfully against Python as early as version 3.6.
<https://www.conventionalcommits.org/>`_ in styling your commit messages.

5. When you're done making changes, check that your changes pass flake8 and the
tests, including testing other Python versions with tox::
tests, including testing other Python versions (optionally with tox)::

$ flake8 src/vipersci tests
$ python setup.py test or pytest
Expand All @@ -116,7 +115,7 @@ Before you submit a pull request, check that it meets these guidelines:
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in CHANGELOG.rst.
3. The pull request should work for Python 3.7, 3.8 and 3.9, and optionally for PyPy.
3. The pull request should work for Python 3.8, 3.9, 3.10 and 3.11, and optionally for PyPy.
And make sure that the tests pass for all supported Python versions.


Expand Down
14 changes: 7 additions & 7 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.7.0-dev
current_version = 0.7.0
commit = True
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?
Expand Down Expand Up @@ -68,29 +68,29 @@ console_scripts =
accrual = vipersci.carto.accrual:main
anaglyph = vipersci.vis.anaglyph:main
anom_pixel = vipersci.vis.anom_pixel:main
bundle_install = vipersci.pds.bundle_install:main
bundle_install = vipersci.pds.bundle_install:main
colorforge = vipersci.carto.colorforge:main
dice_buffer = vipersci.carto.dice_buffer:main
dissolve_dice = vipersci.carto.dissolve_dice:main
get_position = vipersci.carto.get_position:main
image_stats = vipersci.vis.image_statistics:main
labelmaker = vipersci.pds.labelmaker.cli:main
labelmaker = vipersci.pds.labelmaker.cli:main
msolo_simulator = vipersci.carto.msolo_simulator:main
nirvss_simulator = vipersci.carto.nirvss_simulator:main
nss_modeler = vipersci.carto.nss_modeler:main
nss_simulator = vipersci.carto.nss_simulator:main
traverse_interpolator = vipersci.carto.traverse_interpolator:main
tri2gpkg = vipersci.carto.tri2gpkg:main
template_test = vipersci.vis.pds.template_test:main
vis_create_browse = vipersci.vis.pds.create_browse:main
vis_create_browse = vipersci.vis.pds.create_browse:main
vis_create_image = vipersci.vis.create_image:main
vis_create_mmgis_pano = vipersci.vis.create_mmgis_pano:main
vis_create_mmgis_pano = vipersci.vis.create_mmgis_pano:main
vis_create_pano = vipersci.vis.create_pano:main
vis_create_pano_product = vipersci.vis.pds.create_pano_product:main
vis_create_pano_product = vipersci.vis.pds.create_pano_product:main
vis_create_tif = vipersci.vis.create_tif:main
vis_create_raw = vipersci.vis.pds.create_raw:main
vis_create_dbs = vipersci.vis.db.create_vis_dbs:main
vis_pano_check = vipersci.vis.pano_check:main
vis_pano_check = vipersci.vis.pano_check:main
viseer = vipersci.vis.viseer:main

[bdist_wheel]
Expand Down
2 changes: 1 addition & 1 deletion src/vipersci/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

__author__ = """vipersci Developers"""
__email__ = "[email protected]"
__version__ = "0.7.0-dev"
__version__ = "0.7.0"
3 changes: 1 addition & 2 deletions src/vipersci/carto/colorforge.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,7 @@ def example_plot(palette: Palette, output=None):
x = np.arange(-3.0, 3.0, dx)
x_grid, y_grid = np.meshgrid(x, x)
z = rescale(
(1 - x_grid / 2 + x_grid**5 + y_grid**3)
* np.exp(-(x_grid**2 + y_grid**2)),
(1 - x_grid / 2 + x_grid**5 + y_grid**3) * np.exp(-(x_grid**2 + y_grid**2)),
palette.vmin,
palette.vmax,
)
Expand Down
2 changes: 1 addition & 1 deletion src/vipersci/carto/traverse_interpolator.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def arg_parser():
parser.add_argument(
"json",
type=Path,
help="The JSON file that contains a traverse."
help="The JSON file that contains a traverse.",
# Assumed to be GeoJSON from the Map Server.
)

Expand Down
77 changes: 47 additions & 30 deletions src/vipersci/pds/labelmaker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,41 +83,58 @@ def get_common_label_info(element: ET.Element, area="pds:Observation_Area"):
d = {
"lid": lid,
"vid": find_text(element, "./pds:Identification_Area/pds:version_id"),
"start_date_time": None
if area is None
else fromisozformat(
find_text(element, f"./{area}/pds:Time_Coordinates/pds:start_date_time")
"start_date_time": (
None
if area is None
else fromisozformat(
find_text(element, f"./{area}/pds:Time_Coordinates/pds:start_date_time")
)
),
"stop_date_time": (
None
if area is None
else fromisozformat(
find_text(element, f"./{area}/pds:Time_Coordinates/pds:stop_date_time")
)
),
"investigation_name": (
None
if area is None
else find_text(element, f"./{area}/pds:Investigation_Area/pds:name")
),
"stop_date_time": None
if area is None
else fromisozformat(
find_text(element, f"./{area}/pds:Time_Coordinates/pds:stop_date_time")
"investigation_type": (
None
if area is None
else find_text(element, f"./{area}/pds:Investigation_Area/pds:type")
),
"investigation_name": None
if area is None
else find_text(element, f"./{area}/pds:Investigation_Area/pds:name"),
"investigation_type": None
if area is None
else find_text(element, f"./{area}/pds:Investigation_Area/pds:type"),
"investigation_lid": None
if area is None
else find_text(
element,
f"./{area}/pds:Investigation_Area/pds:Internal_Reference/pds:lid_reference",
"investigation_lid": (
None
if area is None
else find_text(
element,
f"./{area}/pds:Investigation_Area/pds:Internal_Reference/"
"pds:lid_reference",
)
),
"host_name": host_name,
"host_lid": host_lid,
"target_name": None
if area is None
else find_text(element, ".//pds:Target_Identification/pds:name"),
"target_type": None
if area is None
else find_text(element, ".//pds:Target_Identification/pds:type"),
"target_lid": None
if area is None
else find_text(
element,
".//pds:Target_Identification/pds:Internal_Reference/pds:lid_reference",
"target_name": (
None
if area is None
else find_text(element, ".//pds:Target_Identification/pds:name")
),
"target_type": (
None
if area is None
else find_text(element, ".//pds:Target_Identification/pds:type")
),
"target_lid": (
None
if area is None
else find_text(
element,
".//pds:Target_Identification/pds:Internal_Reference/pds:lid_reference",
)
),
"instruments": instruments,
"purposes": purposes,
Expand Down
78 changes: 58 additions & 20 deletions src/vipersci/vis/create_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

import numpy as np
import numpy.typing as npt
from PIL import Image
from PIL.PngImagePlugin import PngInfo
from skimage.io import imread, imsave # maybe just imageio here?
from skimage.util import img_as_ubyte, img_as_uint
Expand Down Expand Up @@ -143,7 +144,7 @@
outdir: Path = Path.cwd(),
session: Optional[Session] = None,
json: bool = True,
png: bool = False,
imgtype="tif",
):
"""
Creates a TIFF file / JSON file pair in *outdir* based on the provided
Expand Down Expand Up @@ -171,7 +172,7 @@
# db insert (otherwise the outfile-writing would need to happen in the
# context of the session). However, if the db insert fails, the files
# already exist on disk. Is that a problem? Maybe that's fine?
rp = make_image_record(metadata, image, outdir, png)
rp = make_image_record(metadata, image, outdir, imgtype)

Check warning on line 175 in src/vipersci/vis/create_image.py

View check run for this annotation

Codecov / codecov/patch

src/vipersci/vis/create_image.py#L175

Added line #L175 was not covered by tests

if json:
write_json(rp.asdict(), outdir)
Expand Down Expand Up @@ -227,35 +228,46 @@
metadata: dict,
image: Union[ImageType, Path, None] = None,
outdir: Path = Path.cwd(),
make_png=False,
imgtype="tif",
) -> ImageRecord:
"""
Returns an ImageRecord created from the provided meta-data, and
if *image* is a numpy array, it will also use write_tiff() to
create a TIFF file in *outdir* (defaults to current
working directory).
if *image* is a numpy array, it will write out an image file
in TIFF format (default or if *imgtype* is "tif") or PNG format
(if *imgtype* is "png") in *outdir* (defaults to current
working directory). The *imgtype* is ignored if *image* is
a Path to an existing image file.
"""
ir = ImageRecord(**metadata)
pid = pds.VISID(ir.product_id)

if image is not None:
if isinstance(image, Path):
tif_d = tif_info(image)
if image.suffix.casefold() in (".tif", ".tiff"):
img_d = tif_info(image)
elif image.suffix.casefold() == ".png":
img_d = png_info(image)
else:
raise ValueError(f"Don't know how to evaluate {image}")
else:
tif_d = tif_info(write_tiff(pid, image, outdir))
if make_png:
write_png(pid, image, outdir)
if imgtype.casefold() == "tif":
img_d = tif_info(write_tiff(pid, image, outdir))
elif imgtype.casefold() == "png":
img_d = png_info(write_png(pid, image, outdir))
else:
raise ValueError(f"The value {imgtype} is not a recognized imgtype.")

for k in ("lines", "samples"):
if getattr(ir, k) != tif_d[k]:
if getattr(ir, k) != img_d[k]:
raise ValueError(
f"The value of {k} from the TIFF ({tif_d[k]}) does not "
f"The value of {k} from the image ({img_d[k]}) does not "
f"match the value from the metadata ({getattr(ir, k)})"
)

check_bit_depth(pid, tif_d["file_data_type"])
if "file_data_type" in img_d:
check_bit_depth(pid, img_d["file_data_type"])

ir.update(tif_d)
ir.update(img_d)
else:
ir.update(
{
Expand All @@ -278,13 +290,41 @@
return ir


def file_info(p: Path) -> dict:
"""
Returns a dict containing meta-data from a file at the provided path, *p*.
"""
dt = datetime.fromtimestamp(p.stat().st_mtime, timezone.utc)

d = {
"file_creation_datetime": dt,
"file_md5_checksum": util.md5(p),
"file_path": p.name,
}
return d


def png_info(p: Path) -> dict:
"""
Returns a dict containing meta-data from the PNG file at the
provided path, *p*.
"""
im = Image.open(p)

d = {
# "file_data_type": f"Unsigned{dt_end}",
"lines": im.size[1],
"samples": im.size[0],
}
d.update(file_info(p))
return d


def tif_info(p: Path) -> dict:
"""
Returns a dict containing meta-data from the TIFF file at the
provided path, *p*.
"""
dt = datetime.fromtimestamp(p.stat().st_mtime, timezone.utc)

info = read_tiff(str(p))
tags = info["ifds"][0]["tags"]

Expand All @@ -300,13 +340,11 @@

d = {
"file_byte_offset": tags[273]["data"][0], # Tag 273 is StripOffsets
"file_creation_datetime": dt,
"file_data_type": f"Unsigned{dt_end}",
"file_md5_checksum": util.md5(p),
"file_path": p.name,
"lines": tags[257]["data"][0], # Tag 257 is ImageWidth,
"samples": tags[256]["data"][0], # Tag 256 is ImageWidth,
}
d.update(file_info(p))
return d


Expand Down Expand Up @@ -361,5 +399,5 @@
logger.debug(desc)
outpath = (outdir / str(pid)).with_suffix(".png")

imsave(str(outpath), image, check_contrast=False, pnginfo=info, compress_level=0)
imsave(str(outpath), image, check_contrast=False, pnginfo=info)
return outpath
4 changes: 2 additions & 2 deletions src/vipersci/vis/db/image_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class ImageRecord(Base):
capture_id = mapped_column(
Integer,
nullable=False,
doc="The captureId from the command sequence."
doc="The captureId from the command sequence.",
# TODO: learn more about captureIds to provide better doc here.
)
captureId = synonym("capture_id")
Expand Down Expand Up @@ -284,7 +284,7 @@ class ImageRecord(Base):
stereo = mapped_column(
Boolean,
nullable=False,
doc="The stereo parameter from the Yamcs imageHeader."
doc="The stereo parameter from the Yamcs imageHeader.",
# TODO: learn more about stereo to provide better doc here.
)
stop_time = mapped_column(DateTime(timezone=True), nullable=False)
Expand Down
6 changes: 3 additions & 3 deletions src/vipersci/vis/pds/create_browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@
parser.error(str(err))

metadata["source_lidvid"] = metadata["lid"] + "::" + metadata["vid"]
metadata[
"source_product_type"
] = f"data_to_{metadata['type'].lower()}_source_product"
metadata["source_product_type"] = (

Check warning on line 99 in src/vipersci/vis/pds/create_browse.py

View check run for this annotation

Codecov / codecov/patch

src/vipersci/vis/pds/create_browse.py#L99

Added line #L99 was not covered by tests
f"data_to_{metadata['type'].lower()}_source_product"
)

# Adjust LID
lid_tokens = metadata["lid"].split(":")
Expand Down
Loading
Loading