-
Notifications
You must be signed in to change notification settings - Fork 295
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
751af03
commit 1367072
Showing
18 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from dask.diagnostics import ProgressBar | ||
from satpy import Scene | ||
from glob import glob | ||
import os | ||
import warnings | ||
import dask | ||
|
||
os.environ['OMP_NUM_THREADS'] = os.environ['MKL_NUM_THREADS'] = '2' | ||
os.environ['PYTROLL_CHUNK_SIZE'] = '1024' | ||
warnings.simplefilter('ignore') | ||
dask.config.set(scheduler='threads', num_workers=4) | ||
|
||
# Get the list of satellite files to open | ||
satellite = "GOES16" | ||
filenames = glob(f'./satellite_data/{satellite}/*.nc') | ||
|
||
scn = Scene(reader='abi_l1b', filenames=filenames) | ||
|
||
# what composites Satpy knows how to make and that it has the inputs for? | ||
print(scn.available_composite_names()) | ||
|
||
composite = 'airmass' | ||
scn.load([composite]) | ||
with ProgressBar(): | ||
scn.save_datasets(writer='simple_image', filename=f'./features/data/reference/reference_image_{satellite}_{composite}.png') | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#!/usr/bin/env python | ||
"""Download test data and ancillary data for running this tutorial.""" | ||
|
||
import os | ||
import math | ||
import requests | ||
from zipfile import ZipFile | ||
from tqdm import tqdm | ||
|
||
TUTORIAL_ROOT = os.path.dirname(os.path.abspath(__file__)) | ||
|
||
|
||
def download_pyspectral_luts(): | ||
print("Downloading lookup tables used by pyspectral...") | ||
from pyspectral.utils import download_luts, download_rsr | ||
download_luts() | ||
download_rsr() | ||
return True | ||
|
||
|
||
def _download_data_zip(url, output_filename): | ||
if os.path.isfile(output_filename): | ||
print("Data zip file already exists, won't re-download: {}".format(output_filename)) | ||
return True | ||
|
||
print("Downloading {}".format(url)) | ||
r = requests.get(url, stream=True) | ||
|
||
# Total size in bytes. | ||
total_size = int(r.headers.get('content-length', 0)) | ||
block_size = 1024 | ||
wrote = 0 | ||
with open(output_filename, 'wb') as f: | ||
for data in tqdm(r.iter_content(block_size), total=math.ceil(total_size//block_size), unit='KB', unit_scale=True): | ||
wrote += len(data) | ||
f.write(data) | ||
if total_size != 0 and wrote != total_size: | ||
print("ERROR: something went wrong downloading {}".format(url)) | ||
return False | ||
return True | ||
|
||
|
||
def _unzip(filename, output_dir): | ||
print("Extracting {}".format(filename)) | ||
try: | ||
with ZipFile(filename, 'r') as zip_obj: | ||
zip_obj.extractall(output_dir) | ||
except (IOError, OSError): | ||
print("FAIL: Could not extract {}".format(filename)) | ||
return False | ||
return True | ||
|
||
|
||
def _download_and_unzip(url, output_dir): | ||
filename = os.path.basename(url) | ||
if _download_data_zip(url, filename): | ||
return _unzip(filename, output_dir) | ||
return False | ||
|
||
|
||
def download_test_data(): | ||
cwd = os.getcwd() | ||
os.chdir(TUTORIAL_ROOT) | ||
|
||
ret = _download_and_unzip( | ||
'https://bin.ssec.wisc.edu/pub/davidh/20180511_texas_fire_abi_l1b_conus.zip', | ||
os.path.join('data', 'abi_l1b') | ||
) | ||
ret &= _download_and_unzip( | ||
'https://bin.ssec.wisc.edu/pub/davidh/20180511_texas_fire_abi_l1b_meso.zip', | ||
os.path.join('data', 'abi_l1b') | ||
) | ||
ret &= _download_and_unzip( | ||
'https://bin.ssec.wisc.edu/pub/davidh/20180511_texas_fire_viirs_sdr.zip', | ||
os.path.join('data', 'viirs_sdr') | ||
) | ||
os.chdir(cwd) | ||
return ret | ||
|
||
|
||
def main(): | ||
import argparse | ||
parser = argparse.ArgumentParser(description="Download data necessary for the Satpy tutorial") | ||
parser.add_argument('--luts-only', action='store_true', | ||
help="Only download LUTs for pyspectral operation") | ||
parser.add_argument('--data-only', action='store_true', | ||
help="Only download test data") | ||
args = parser.parse_args() | ||
|
||
ret = True | ||
if not args.data_only: | ||
ret &= download_pyspectral_luts() | ||
if not args.luts_only: | ||
ret &= download_test_data() | ||
|
||
if ret: | ||
print("Downloaded `.zip` files can now be deleted.") | ||
print("SUCCESS") | ||
else: | ||
print("FAIL") | ||
return int(not ret) | ||
|
||
|
||
if __name__ == "__main__": | ||
import sys | ||
sys.exit(main()) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+40.1 KB
satpy/tests/behave/features/data/comparison_failed/diff_GOES16_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+76.4 KB
satpy/tests/behave/features/data/comparison_failed/diff_GOES17_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+30.4 MB
satpy/tests/behave/features/data/generated/generated_image_GOES16_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+39.8 MB
satpy/tests/behave/features/data/generated/generated_image_GOES17_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+30.4 MB
satpy/tests/behave/features/data/reference/reference_image_GOES16_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+30.4 MB
satpy/tests/behave/features/data/reference/reference_image_GOES16_airmass_old.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+39.8 MB
satpy/tests/behave/features/data/reference/reference_image_GOES17_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+39.8 MB
satpy/tests/behave/features/data/reference/reference_image_GOES17_airmass_old.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+27.2 MB
...sts/behave/features/data/reference_different/reference_image_GOES16_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+43.4 MB
...sts/behave/features/data/reference_different/reference_image_GOES17_airmass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Feature: Image Comparison | ||
|
||
Scenario Outline: Compare generated image with reference image | ||
Given I have a <composite> reference image file from <satellite> | ||
When I generate a new <composite> image file from <satellite> | ||
Then the generated image should be the same as the reference image | ||
|
||
Examples: | ||
|satellite |composite | | ||
|GOES17 |airmass | | ||
|GOES16 |airmass | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import os | ||
import warnings | ||
from glob import glob | ||
from PIL import Image | ||
import cv2 | ||
import dask | ||
import numpy as np | ||
from behave import given, when, then | ||
from satpy import Scene | ||
from datetime import datetime | ||
|
||
# Define a before_all hook to create the timestamp and test results directory | ||
def before_all(context): | ||
context.timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") | ||
context.test_results_dir = f"../test_results/image_comparison/{context.timestamp}" | ||
os.makedirs(os.path.join(context.test_results_dir, 'generated'), exist_ok=True) | ||
os.makedirs(os.path.join(context.test_results_dir, 'difference'), exist_ok=True) | ||
|
||
# Write the timestamp to test_results.txt | ||
results_file = os.path.join(context.test_results_dir, 'test_results.txt') | ||
with open(results_file, 'a') as f: | ||
f.write(f"Test executed at {context.timestamp}.\n\n") | ||
|
||
# Register the before_all hook | ||
def setup_hooks(): | ||
from behave import use_fixture | ||
from behave.runner import Context | ||
|
||
use_fixture(before_all, Context) | ||
|
||
setup_hooks() | ||
@given('I have a {composite} reference image file from {satellite}') | ||
def step_given_reference_image(context, composite, satellite): | ||
reference_image = f"reference_image_{satellite}_{composite}.png" | ||
context.reference_image = cv2.imread(f"./features/data/reference/{reference_image}") | ||
context.reference_different_image = cv2.imread(f"./features/data/reference_different/{reference_image}") | ||
context.satellite = satellite | ||
context.composite = composite | ||
|
||
|
||
@when('I generate a new {composite} image file from {satellite}') | ||
def step_when_generate_image(context, composite, satellite): | ||
os.environ['OMP_NUM_THREADS'] = os.environ['MKL_NUM_THREADS'] = '2' | ||
os.environ['PYTROLL_CHUNK_SIZE'] = '1024' | ||
warnings.simplefilter('ignore') | ||
dask.config.set(scheduler='threads', num_workers=4) | ||
|
||
# Get the list of satellite files to open | ||
filenames = glob(f'./features/data/satellite_data/{satellite}/*.nc') | ||
|
||
scn = Scene(reader='abi_l1b', filenames=filenames) | ||
|
||
scn.load([composite]) | ||
|
||
# Save the generated image in the generated folder | ||
generated_image_path = os.path.join(context.test_results_dir, 'generated', | ||
f'generated_{context.satellite}_{context.composite}.png') | ||
scn.save_datasets(writer='simple_image', filename=generated_image_path) | ||
|
||
# Save the generated image in the context | ||
context.generated_image = cv2.imread(generated_image_path) | ||
|
||
|
||
@then('the generated image should be the same as the reference image') | ||
def step_then_compare_images(context): | ||
threshold = 2000 | ||
# Load the images | ||
imageA = cv2.cvtColor(context.reference_different_image, cv2.COLOR_BGR2GRAY) | ||
imageB = cv2.cvtColor(context.generated_image, cv2.COLOR_BGR2GRAY) | ||
# Ensure both images have the same dimensions | ||
if imageA.shape != imageB.shape: | ||
raise ValueError("Both images must have the same dimensions") | ||
array1 = np.array(imageA) | ||
array2 = np.array(imageB) | ||
# Perform pixel-wise comparison | ||
result_matrix = (array1 != array2).astype(np.uint8) * 255 | ||
|
||
# Save the resulting numpy array as an image in the difference folder | ||
diff_image_path = os.path.join(context.test_results_dir, 'difference', | ||
f'diff_{context.satellite}_{context.composite}.png') | ||
cv2.imwrite(diff_image_path, result_matrix) | ||
|
||
# Count non-zero pixels in the result matrix | ||
non_zero_count = np.count_nonzero(result_matrix) | ||
|
||
# Write the results to a file in the test results directory | ||
results_file = os.path.join(context.test_results_dir, 'test_results.txt') | ||
with open(results_file, 'a') as f: | ||
f.write(f"Test for {context.satellite} - {context.composite}\n") | ||
f.write(f"Non-zero pixel differences: {non_zero_count}\n") | ||
if non_zero_count < threshold: | ||
f.write(f"Result: Passed - {non_zero_count} pixel differences.\n\n") | ||
else: | ||
f.write(f"Result: Failed - {non_zero_count} pixel differences exceed the threshold of {threshold}.\n\n") | ||
|
||
# Assert that the number of differences is below the threshold | ||
assert non_zero_count < threshold, f"Images are not similar enough. {non_zero_count} pixel differences exceed the threshold of {threshold}." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
from PIL import Image, ImageDraw, ImageFont | ||
|
||
|
||
def add_text_to_image(input_path, output_path, text, position=(800, 2200), font_size=700, font_color=(255, 255, 255)): | ||
# Open the image | ||
image = Image.open(input_path) | ||
|
||
# Create a drawing object | ||
draw = ImageDraw.Draw(image) | ||
|
||
# Load a font | ||
font = ImageFont.load_default() | ||
|
||
# Specify font size and color | ||
font = ImageFont.truetype("arial.ttf", font_size) | ||
draw.text(position, text, font=font, fill=font_color) | ||
|
||
# Save the modified image | ||
image.save(output_path) | ||
|
||
|
||
# Example usage | ||
input_image_path = 'C:/Users/sennlaub/IdeaProjects/DWD_Pytroll/img/reference.png' | ||
output_image_path = 'C:/Users/sennlaub/IdeaProjects/DWD_Pytroll/img/reference_different.png' | ||
text_to_add = 'Hello, World!' | ||
|
||
add_text_to_image(input_image_path, output_image_path, text_to_add) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
#!/usr/bin/env python | ||
"""Test that the installation steps for this tutorial were successful. | ||
1. Check that Satpy features are available and all dependencies are importable. | ||
2. Check that data has been downloaded. | ||
""" | ||
|
||
import io | ||
import os | ||
from contextlib import redirect_stdout | ||
|
||
try: | ||
from satpy.utils import check_satpy | ||
except ImportError: | ||
print("FAIL: Satpy is not importable") | ||
raise | ||
|
||
|
||
TUTORIAL_ROOT = os.path.dirname(os.path.abspath(__file__)) | ||
|
||
|
||
def check_satpy_features(): | ||
print("Checking Satpy features...\n") | ||
readers = ['abi_l1b', 'viirs_sdr'] | ||
writers = ['cf', 'geotiff', 'simple_image'] | ||
extras = ['cartopy', 'geoviews'] | ||
out = io.StringIO() | ||
with redirect_stdout(out): | ||
check_satpy(readers=readers, writers=writers, extras=extras) | ||
out_str = out.getvalue() | ||
print(out_str) | ||
|
||
for feature in readers + writers + extras: | ||
if feature + ": ok" not in out_str: | ||
print("FAIL: Missing or corrupt Satpy dependency (see above for details).") | ||
return False | ||
return True | ||
|
||
|
||
def check_data_download(): | ||
print("Checking data directories...\n") | ||
|
||
# base_dirs | ||
abi_dir = os.path.join(TUTORIAL_ROOT, 'data', 'abi_l1b') | ||
viirs_dir = os.path.join(TUTORIAL_ROOT, 'data', 'viirs_sdr') | ||
|
||
# data case dirs | ||
conus_dir = os.path.join(abi_dir, '20180511_texas_fire_abi_l1b_conus') | ||
meso_dir = os.path.join(abi_dir, '20180511_texas_fire_abi_l1b_meso') | ||
viirs_dir = os.path.join(viirs_dir, '20180511_texas_fire_viirs_sdr') | ||
if not os.path.isdir(conus_dir): | ||
print("FAIL: Missing ABI L1B CONUS data: {}".format(conus_dir)) | ||
return False | ||
if not os.path.isdir(meso_dir): | ||
print("FAIL: Missing ABI L1B Mesoscale data: {}".format(meso_dir)) | ||
return False | ||
if not os.path.isdir(viirs_dir): | ||
print("FAIL: Missing VIIRS SDR data: {}".format(viirs_dir)) | ||
return False | ||
|
||
# number of files | ||
if len(os.listdir(conus_dir)) != 16: | ||
print("FAIL: Expected 16 files in {}".format(conus_dir)) | ||
return False | ||
if len(os.listdir(meso_dir)) != 1440: | ||
print("FAIL: Expected 1440 files in {}".format(meso_dir)) | ||
return False | ||
if len(os.listdir(viirs_dir)) != 21: | ||
print("FAIL: Expected 21 files in {}".format(viirs_dir)) | ||
return False | ||
|
||
return True | ||
|
||
|
||
def main(): | ||
ret = True | ||
ret &= check_satpy_features() | ||
ret &= check_data_download() | ||
if ret: | ||
print("SUCCESS") | ||
else: | ||
print("FAIL") | ||
return ret | ||
|
||
|
||
if __name__ == "__main__": | ||
import sys | ||
sys.exit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Test for GOES17 - airmass | ||
Non-zero pixel differences: 6607692 | ||
Result: Failed - 6607692 pixel differences exceed the threshold of 100. | ||
|
||
Test for GOES16 - airmass | ||
Non-zero pixel differences: 1590 | ||
Result: Failed - 1590 pixel differences exceed the threshold of 100. | ||
|