From 170f5901ba6908a5c667f70f4fcc4259ab1a5e07 Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Mon, 9 May 2022 11:59:00 -0500 Subject: [PATCH 01/13] create function hyperspectral write data --- plantcv/plantcv/hyperspectral/write_data.py | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 plantcv/plantcv/hyperspectral/write_data.py diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py new file mode 100644 index 000000000..c684b8990 --- /dev/null +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -0,0 +1,43 @@ +import os +import numpy as np + +def write_data(filename, spectral_data): + """Write hyperspectral image data to a file. + Inputs: + filename = Name of file to write + spectral_data = Hyperspectral data object + + Returns: + + :param filename: str + :param spectral_data: __main__.Spectral_data + """ + + filename = os.path.splitext(filename)[0] + + # create header + lines, samples, bands = spectral_data.array_data.shape + dtype_dict = {'B': "1", 'h': "2", 'i': "3", 'f': "4", 'd': "5", 'F': "6", + 'D': "9", 'H': "12", 'I': "13", 'l': "14", 'L': "15"} + wavelenghths = list(spectral_data.wavelength_dict.keys()) + with open(filename+'.hdr', mode='w') as f: + f.write('ENVI\n') + f.write(f'; this file was created using PlantCV version {pcv.__version__}\n') + f.write('interleave = bil\n') + f.write(f'samples = {samples}\n') + f.write(f'lines = {lines}\n') + f.write(f'bands = {bands}\n') + f.write(f'data type = {dtype_dict[spectral_data.array_data.dtype.char]}\n') + f.write(f'wavelength units = {spectral_data.wavelength_units}\n') + f.write(f'default bands ={spectral_data.default_bands}\n') + f.write('wavelength = {\n') + for wl in wavelenghths[:-1]: + f.write(f'{wl},\n') + f.write(f'{wavelenghths[-1]}\n') + f.write('}') + + # create raw binary file containing the hyperspectral array values + with open(filename+'.raw', mode='w+b') as f: + f.write(spectral_data.array_data.transpose(0,2,1).tobytes(order='C')) + + return True From 6bad11331821cb2c2036bfc5e0f9c28525c4de2f Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Mon, 9 May 2022 13:28:23 -0500 Subject: [PATCH 02/13] add version import to hyperspectral write data --- plantcv/plantcv/hyperspectral/write_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index c684b8990..bdc88b9e7 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -1,6 +1,8 @@ import os import numpy as np +from plantcv.plantcv.__init__ import __version__ + def write_data(filename, spectral_data): """Write hyperspectral image data to a file. Inputs: From 39032ef65a31a14141b06d1b2cbc0ed0c7c556da Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Mon, 9 May 2022 13:35:46 -0500 Subject: [PATCH 03/13] call __version__ without pcv in hs write data --- plantcv/plantcv/hyperspectral/write_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index bdc88b9e7..e45fab5e0 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -24,7 +24,7 @@ def write_data(filename, spectral_data): wavelenghths = list(spectral_data.wavelength_dict.keys()) with open(filename+'.hdr', mode='w') as f: f.write('ENVI\n') - f.write(f'; this file was created using PlantCV version {pcv.__version__}\n') + f.write(f'; this file was created using PlantCV version {__version__}\n') f.write('interleave = bil\n') f.write(f'samples = {samples}\n') f.write(f'lines = {lines}\n') From a279e4861869063c584e3e158db6ceefc5c9c9af Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Mon, 9 May 2022 13:49:44 -0500 Subject: [PATCH 04/13] add hyperspectral write data to init --- plantcv/plantcv/hyperspectral/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plantcv/plantcv/hyperspectral/__init__.py b/plantcv/plantcv/hyperspectral/__init__.py index e8e841fd9..92e6c13bb 100644 --- a/plantcv/plantcv/hyperspectral/__init__.py +++ b/plantcv/plantcv/hyperspectral/__init__.py @@ -7,7 +7,9 @@ from plantcv.plantcv.hyperspectral.calibrate import calibrate from plantcv.plantcv.hyperspectral._avg_reflectance import _avg_reflectance from plantcv.plantcv.hyperspectral._inverse_covariance import _inverse_covariance +from plantcv.plantcv.hyperspectral.write_data import write_data # add new functions to end of lists __all__ = ["read_data", "_find_closest", "analyze_spectral", "analyze_index", "calibrate", - "_make_pseudo_rgb", "extract_wavelength", "_avg_reflectance", "_inverse_covariance"] + "_make_pseudo_rgb", "extract_wavelength", "_avg_reflectance", "_inverse_covariance", + "write_data"] From ebecb035a14cb2666600f6afb6451c64e71e7e1f Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Mon, 9 May 2022 18:49:37 -0500 Subject: [PATCH 05/13] add hyperspectral write data documentation --- docs/write_data.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 docs/write_data.md diff --git a/docs/write_data.md b/docs/write_data.md new file mode 100644 index 000000000..8e9698b1a --- /dev/null +++ b/docs/write_data.md @@ -0,0 +1,42 @@ +## Write data + +Write a hyperspectral image in ENVI format to the specified file. +It creates a text header file with extension .hdr and a binary file with +extension .raw. This function only supports Band-interleaved-by-line (BIL) +interleave. + +**plantcv.hyperspectral.write_data**(*filename, spectral_data*): + +**returns** Bool + +- **Parameters:** + - filename- desired name of the hyperspectral image file. The extensions are ignored and .hdr and .raw are used. + - spectral_data- Hyperspectral data object + +- **Context:** + - Used to save a modified hyperspectral image + +- **Example use:** + +```python +from plantcv import plantcv as pcv + +modified_spectral = pcv.Spectral_data(array_data=modified_array_data, + max_wavelength=list(source_spectral.wavelength_dict.keys())[-1], + min_wavelength=list(source_spectral.wavelength_dict.keys())[0], + max_value=float(np.amax(modified_array_data)), + min_value=float(np.amin(modified_array_data)), + d_type=modified_array_data.dtype, + wavelength_dict=source_spectral.wavelength_dict, + samples=modified_array_data.shape[1], + lines=modified_array_data.shape[0], interleave='bil', + wavelength_units=source_spectral.wavelength_units, + array_type="datacube", + pseudo_rgb=None, + filename=source_spectral.filename, + default_bands=None) + +pcv.hyperspectral.write_data('test-hyperspectral', modified_spectral) +``` + +**Source Code:** [Here](https://github.com/danforthcenter/plantcv/blob/master/plantcv/plantcv/hyperspectral/write_data.py) From e28b574b768832b542e416495d1d5ab043b4ab0e Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Mon, 9 May 2022 18:58:03 -0500 Subject: [PATCH 06/13] add writing filename in header hyperspectral write data --- plantcv/plantcv/hyperspectral/write_data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index e45fab5e0..fd10bf160 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -25,6 +25,7 @@ def write_data(filename, spectral_data): with open(filename+'.hdr', mode='w') as f: f.write('ENVI\n') f.write(f'; this file was created using PlantCV version {__version__}\n') + f.write(f'; original file: {spectral_data.filename}\n') f.write('interleave = bil\n') f.write(f'samples = {samples}\n') f.write(f'lines = {lines}\n') From f2002f5e38b050361ca709431655b5da0906d379 Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Tue, 10 May 2022 11:32:00 -0500 Subject: [PATCH 07/13] add test for hyperspectral write data --- .../plantcv/hyperspectral/test_write_data.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/plantcv/hyperspectral/test_write_data.py diff --git a/tests/plantcv/hyperspectral/test_write_data.py b/tests/plantcv/hyperspectral/test_write_data.py new file mode 100644 index 000000000..749c84396 --- /dev/null +++ b/tests/plantcv/hyperspectral/test_write_data.py @@ -0,0 +1,52 @@ +import os +import pytest +import numpy as np + +from plantcv.plantcv import Spectral_data +from plantcv.plantcv.hyperspectral import read_data +from plantcv.plantcv.hyperspectral import write_data + +def test_write_data_default(tmpdir): + """Test for PlantCV.""" + rng = np.random.default_rng() + + # Create a test tmp directory + cache_dir = tmpdir.mkdir("cache") + + lines = 32 + samples = 32 + bands = 5 + + # Create random array data in the interval [0-65535] and wavelengths in the + # interval [400-1000) + rand_array = rng.integers(0, 65535, size=(lines, samples, bands), dtype=np.uint16, endpoint=True) + rand_wavelengths = np.sort(600.0*rng.random(size=bands) + 400.0) + # Create dictionary of wavelengths + wavelength_dict = {} + for j, wavelength in enumerate(rand_wavelengths): + wavelength_dict.update({wavelength: float(j)}) + + # Create spectral data object + rand_spectral_array = Spectral_data(array_data=rand_array, + max_wavelength=rand_wavelengths[-1], + min_wavelength=rand_wavelengths[0], + max_value=float(np.amax(rand_array)), + min_value=float(np.amin(rand_array)), + d_type=rand_array.dtype, + wavelength_dict=wavelength_dict, + samples=samples, + lines=lines, + interleave='bil', + wavelength_units='nm', + array_type="datacube", + pseudo_rgb=None, + filename='random_hyperspectral_test', + default_bands=None) + + + filename = os.path.join(cache_dir, 'plantcv_hyperspectral_write_data.raw') + out = write_data(filename=filename, spectral_data=rand_spectral_array) + + # Read written hyperspectral image + array_data = read_data(filename=filename) + assert np.shape(array_data.array_data) == (lines, samples, bands) From 47963f9b1e5ec911854a3a1bcbe51680d8668e8d Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Tue, 10 May 2022 13:54:22 -0500 Subject: [PATCH 08/13] add hyperspectral write data to table of contents --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 84e815dbb..c7c19492b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -70,6 +70,7 @@ nav: - 'Spectral Index': spectral_index.md - 'Extract wavelength': extract_wavelength.md - 'Spectral data objects': Spectral_data.md + - 'Write data': write_data.md - 'Image Add': image_add.md - 'Image Subtract': image_subtract.md - 'Image Fusion': image_fusion.md From 2aab6d1ea9e3118dc8200f650f657825278ff338 Mon Sep 17 00:00:00 2001 From: Noah Fahlgren Date: Tue, 10 May 2022 15:28:27 -0500 Subject: [PATCH 09/13] Update plantcv/plantcv/hyperspectral/write_data.py --- plantcv/plantcv/hyperspectral/write_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index fd10bf160..4bca4119b 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -1,7 +1,7 @@ import os import numpy as np -from plantcv.plantcv.__init__ import __version__ +from plantcv.plantcv import __version__ def write_data(filename, spectral_data): """Write hyperspectral image data to a file. From 074b5476735638382a3ff27c5e4c8d57713d59e8 Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Tue, 10 May 2022 16:08:18 -0500 Subject: [PATCH 10/13] change version import in hyperspectral write data --- plantcv/plantcv/hyperspectral/write_data.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index 4bca4119b..3bfa3be1e 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -1,7 +1,9 @@ import os import numpy as np -from plantcv.plantcv import __version__ +from . import _version + +__version__ = _version.get_versions()['version'] def write_data(filename, spectral_data): """Write hyperspectral image data to a file. From a861499a93d6586a1922130ce635e31e4c3f3763 Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Tue, 10 May 2022 16:16:31 -0500 Subject: [PATCH 11/13] change version import in hyperspectral write data --- plantcv/plantcv/hyperspectral/write_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index 3bfa3be1e..34e6dc49a 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -1,7 +1,7 @@ import os import numpy as np -from . import _version +from plantcv.plantcv import _version __version__ = _version.get_versions()['version'] From 3b5ac2b0903fb4beb394a2815fb00733fcd32b96 Mon Sep 17 00:00:00 2001 From: JorgeGtz Date: Tue, 10 May 2022 19:29:07 -0500 Subject: [PATCH 12/13] add hyperspectral write data to docs updating file --- docs/updating.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/updating.md b/docs/updating.md index 18150085e..a3a64a5f0 100644 --- a/docs/updating.md +++ b/docs/updating.md @@ -385,6 +385,11 @@ pages for more details on the input and output variable types. * post v3.7: index_array = **plantcv.hyperspectral.extract_index**(*array, index="NDVI", distance=20*) * post v3.8: DEPRECATED see plantcv.spectral_index +#### plantcv.hyperspectral.write_data + +* pre v4.0: NA +* post v4.0: **plantcv.hyperspectral.write_data**(*filename, spectral_data*) + #### plantcv.image_add * pre v3.0dev2: device, added_img = **plantcv.image_add**(*img1, img2, device, debug=None*) From a3c8f8fae5b4265213643757d4fbd2f8fbc20eec Mon Sep 17 00:00:00 2001 From: Jorge Gutierrez Date: Wed, 15 Jun 2022 14:42:06 -0500 Subject: [PATCH 13/13] Apply suggestions from code review Co-authored-by: David Peery --- docs/write_data.md | 3 +-- plantcv/plantcv/hyperspectral/write_data.py | 1 - tests/plantcv/hyperspectral/test_write_data.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/write_data.md b/docs/write_data.md index 8e9698b1a..502ab7887 100644 --- a/docs/write_data.md +++ b/docs/write_data.md @@ -2,12 +2,11 @@ Write a hyperspectral image in ENVI format to the specified file. It creates a text header file with extension .hdr and a binary file with -extension .raw. This function only supports Band-interleaved-by-line (BIL) +extension .raw. This function only supports Band-Interleaved-by-Line (BIL) interleave. **plantcv.hyperspectral.write_data**(*filename, spectral_data*): -**returns** Bool - **Parameters:** - filename- desired name of the hyperspectral image file. The extensions are ignored and .hdr and .raw are used. diff --git a/plantcv/plantcv/hyperspectral/write_data.py b/plantcv/plantcv/hyperspectral/write_data.py index 34e6dc49a..66afe3ba6 100644 --- a/plantcv/plantcv/hyperspectral/write_data.py +++ b/plantcv/plantcv/hyperspectral/write_data.py @@ -45,4 +45,3 @@ def write_data(filename, spectral_data): with open(filename+'.raw', mode='w+b') as f: f.write(spectral_data.array_data.transpose(0,2,1).tobytes(order='C')) - return True diff --git a/tests/plantcv/hyperspectral/test_write_data.py b/tests/plantcv/hyperspectral/test_write_data.py index 749c84396..1b98105cb 100644 --- a/tests/plantcv/hyperspectral/test_write_data.py +++ b/tests/plantcv/hyperspectral/test_write_data.py @@ -45,7 +45,7 @@ def test_write_data_default(tmpdir): filename = os.path.join(cache_dir, 'plantcv_hyperspectral_write_data.raw') - out = write_data(filename=filename, spectral_data=rand_spectral_array) + write_data(filename=filename, spectral_data=rand_spectral_array) # Read written hyperspectral image array_data = read_data(filename=filename)