Skip to content

Commit

Permalink
Merge pull request #209 from micasense/fix-unit-tests
Browse files Browse the repository at this point in the history
Add GitHub Actions and fix unit tests
  • Loading branch information
sebc06 authored Feb 6, 2024
2 parents eeaf6e8 + dfb1a13 commit 1340440
Show file tree
Hide file tree
Showing 53 changed files with 192 additions and 195 deletions.
47 changes: 47 additions & 0 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Build and run Python unit tests

on: push
permissions:
contents: read
jobs:
test-linux:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v3
with:
python-version: '3.8'
- name: Add system deps and exiftool
run: |
sudo apt-get update
sudo apt-get install libzbar0 make perl
wget https://cpan.metacpan.org/authors/id/E/EX/EXIFTOOL/Image-ExifTool-12.76.tar.gz
tar -xzf Image-ExifTool-12.76.tar.gz
pushd Image-ExifTool-12.76/
perl Makefile.PL
make test
sudo make install
popd
- name: Add conda to system path
run: |
# $CONDA is an environment variable pointing to the root of the miniconda directory
echo $CONDA/bin >> $GITHUB_PATH
- name: Install dependencies
run: |
source "$CONDA/etc/profile.d/conda.sh"
hash -r
conda config --set always_yes yes --set changeps1 no
conda update -q conda
conda update -n base conda
conda info -a
conda env create -f micasense_conda_env.yml
conda activate micasense
- name: Test with pytest
run: |
source "$CONDA/etc/profile.d/conda.sh"
conda activate micasense
git lfs install
git lfs pull
pytest --junit-xml=test-results.xml
41 changes: 0 additions & 41 deletions .travis.yml

This file was deleted.

3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_1.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_10.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_2.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_3.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_4.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_5.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_6.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_7.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_8.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0000_9.tif
Git LFS file not shown
3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_1.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_10.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_2.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_3.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_4.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_5.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_6.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_7.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_8.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0001_9.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_1.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_10.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_2.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_3.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_4.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_5.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_6.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_7.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_8.tif

This file was deleted.

3 changes: 0 additions & 3 deletions data/REDEDGE-MX-DUAL/IMG_0007_9.tif

This file was deleted.

3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_1.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_10.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_2.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_3.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_4.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_5.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_6.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_7.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_8.tif
Git LFS file not shown
3 changes: 3 additions & 0 deletions data/REDEDGE-MX-DUAL/IMG_0431_9.tif
Git LFS file not shown
6 changes: 3 additions & 3 deletions micasense/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Image(object):
band of multispectral information
"""

def __init__(self, image_path, exiftool_obj=None, allow_uncalibrated=False):
def __init__(self, image_path: str, exiftool_obj=None, allow_uncalibrated=False):
if not os.path.isfile(image_path):
raise IOError("Provided path is not a file: {}".format(image_path))
self.path = image_path
Expand Down Expand Up @@ -191,7 +191,7 @@ def compute_horizontal_irradiance_dls1(self):
return self.horizontal_irradiance_from_direct_scattered()

def compute_horizontal_irradiance_dls2(self):
""" Compute the proper solar elevation, solar azimuth, and horizontal irradiance
""" Compute the proper solar elevation, solar azimuth, and horizontal irradiance
for cases where the camera system did not do it correctly """
_, _, _, \
self.solar_elevation, \
Expand Down Expand Up @@ -373,7 +373,7 @@ def vignette(self):
yv = y.T / y_dim
k = self.vignette_polynomial2D
e = self.vignette_polynomial2Dexponents
p2 = np.zeros_like(xv, dtype=np.float)
p2 = np.zeros_like(xv, dtype=float)
for i, c in enumerate(k):
ex = e[2 * i]
ey = e[2 * i + 1]
Expand Down
2 changes: 1 addition & 1 deletion micasense/imageset.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def from_directory(cls, directory, progress_callback=None, exiftool_path=None, a
if exiftool_path is None and os.environ.get('exiftoolpath') is not None:
exiftool_path = os.path.normpath(os.environ.get('exiftoolpath'))

with exiftool.ExifTool(exiftool_path) as exift:
with exiftool.ExifToolHelper(exiftool_path) as exift:
for i, path in enumerate(matches):
images.append(image.Image(path, exiftool_obj=exift, allow_uncalibrated=allow_uncalibrated))
if progress_callback is not None:
Expand Down
8 changes: 4 additions & 4 deletions micasense/imageutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ def min_max(pts):

def map_points(pts, image_size, warpMatrix, distortion_coeffs, camera_matrix, warp_mode=cv2.MOTION_HOMOGRAPHY):
# extra dimension makes opencv happy
pts = np.array([pts], dtype=np.float)
pts = np.array([pts], dtype=float)
new_cam_mat, _ = cv2.getOptimalNewCameraMatrix(camera_matrix, distortion_coeffs, image_size, 1)
new_pts = cv2.undistortPoints(pts, camera_matrix, distortion_coeffs, P=new_cam_mat)
if warp_mode == cv2.MOTION_AFFINE:
Expand Down Expand Up @@ -584,7 +584,7 @@ def radiometric_pan_sharpen(capture, warp_matrices=None, panchro_band=5, irradia
# this function performs a radiometrically accurate pansharpening on the input capture
# if no warp matrices are supplied to align the multispec images to the pan band
# the camera calibration is used (which produces reasonably well aligned imagers in most cases)
# in addition to the pan sharpened stack, the equivalent upsampled stack is also produced
# in addition to the pan sharpened stack, the equivalent upsampled stack is also produced
# for comparison
# use the warp matrices we have for the stack, if not user supplied
if warp_matrices is None:
Expand Down Expand Up @@ -654,9 +654,9 @@ def radiometric_pan_sharpen(capture, warp_matrices=None, panchro_band=5, irradia
def prepare_exif_for_stacks(thecapture, thefilename):
lat, lon, alt = thecapture.location()
resolution = thecapture.images[0].focal_plane_resolution_px_per_mm
# eventually it would be nice to add the capture ID, flight ID,
# eventually it would be nice to add the capture ID, flight ID,
# and yaw/pitch/roll, but these are non-standard exif tags,
# so it is more difficult.
# so it is more difficult.
attitude = thecapture.dls_pose()
theid = thecapture.uuid
flightid = thecapture.flightid
Expand Down
16 changes: 8 additions & 8 deletions micasense/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
class Metadata(object):
""" Container for Micasense image metadata"""

def __init__(self, filename, exiftool_path=None, exiftool_obj=None):
def __init__(self, filename: str, exiftool_path=None, exiftool_obj=None):
if exiftool_obj is not None:
self.exif = exiftool_obj.get_metadata(filename)
return
Expand All @@ -48,7 +48,7 @@ def __init__(self, filename, exiftool_path=None, exiftool_obj=None):
self.exiftoolPath = None
if not os.path.isfile(filename):
raise IOError("Input path is not a file")
with exiftool.ExifTool(self.exiftoolPath) as exift:
with exiftool.ExifToolHelper() as exift:
self.exif = exift.get_metadata(filename)

def get_all(self):
Expand All @@ -59,10 +59,11 @@ def get_item(self, item, index=None):
""" Get metadata item by Namespace:Parameter"""
val = None
try:
val = self.exif[item]
assert len(self.exif) > 0
val = self.exif[0][item]
if index is not None:
try:
if isinstance(val, unicode):
if isinstance(val, pytz.unicode):
val = val.encode('ascii', 'ignore')
except NameError:
# throws on python 3 where unicode is undefined
Expand All @@ -83,7 +84,7 @@ def size(self, item):
"""get the size (length) of a metadata item"""
val = self.get_item(item)
try:
if isinstance(val, unicode):
if isinstance(val, pytz.unicode):
val = val.encode('ascii', 'ignore')
except NameError:
# throws on python 3 where unicode is undefined
Expand Down Expand Up @@ -132,7 +133,6 @@ def utc_time(self):
if subsec < 0:
negative = -1.0
subsec *= -1.0
subsec = float('0.{}'.format(int(subsec)))
subsec *= negative
ms = subsec * 1e3
utc_time += timedelta(milliseconds=ms)
Expand Down Expand Up @@ -336,7 +336,7 @@ def horizontal_irradiance_valid(self):
return version.parse(version_string) >= version.parse(good_version)

def spectral_irradiance(self):
""" Raw spectral irradiance measured by an irradiance sensor.
""" Raw spectral irradiance measured by an irradiance sensor.
Calibrated to W/m^2/nm using irradiance_scale_factor, but not corrected for angles """
return self.__float_or_zero(self.get_item('XMP:SpectralIrradiance')) * self.irradiance_scale_factor()

Expand Down Expand Up @@ -379,7 +379,7 @@ def auto_calibration_image(self):
self.panel_serial() is not None

def panel_albedo(self):
""" Surface albedo of the active portion of the reflectance panel as calculated by the camera
""" Surface albedo of the active portion of the reflectance panel as calculated by the camera
(usually from the information in the panel QR code) """
albedo = self.get_item('XMP:Albedo')
if albedo is not None:
Expand Down
6 changes: 3 additions & 3 deletions micasense/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ def correct_lens_distortion(meta, image):
ndistortion = meta.size('XMP:PerspectiveDistortion')
distortion_parameters = np.array([float(meta.get_item('XMP:PerspectiveDistortion', i)) for i in range(ndistortion)])
# get the two principal points
pp = np.array(meta.get_item('XMP:PrincipalPoint').split(',')).astype(np.float)
pp = np.array(meta.get_item('XMP:PrincipalPoint').split(',')).astype(float)
# values in pp are in [mm] and need to be rescaled to pixels
focal_plane_x_resolution = float(meta.get_item('EXIF:focal_plane_x_resolution'))
focal_plane_y_resolution = float(meta.get_item('EXIF:focal_plane_y_resolution'))
focal_plane_x_resolution = float(meta.get_item('EXIF:FocalPlaneXResolution'))
focal_plane_y_resolution = float(meta.get_item('EXIF:FocalPlaneYResolution'))

cX = pp[0] * focal_plane_x_resolution
cY = pp[1] * focal_plane_y_resolution
Expand Down
Loading

0 comments on commit 1340440

Please sign in to comment.