-
Notifications
You must be signed in to change notification settings - Fork 279
Write hyperspectral data #889
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
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
170f590
create function hyperspectral write data
JorgeGtz 6bad113
add version import to hyperspectral write data
JorgeGtz 39032ef
call __version__ without pcv in hs write data
JorgeGtz a279e48
add hyperspectral write data to init
JorgeGtz ebecb03
add hyperspectral write data documentation
JorgeGtz e28b574
add writing filename in header hyperspectral write data
JorgeGtz f2002f5
add test for hyperspectral write data
JorgeGtz 73156b3
Merge branch '4.x' into write-hyperspectral-data
JorgeGtz 47963f9
add hyperspectral write data to table of contents
JorgeGtz 2aab6d1
Update plantcv/plantcv/hyperspectral/write_data.py
nfahlgren 074b547
change version import in hyperspectral write data
JorgeGtz a861499
change version import in hyperspectral write data
JorgeGtz 3b5ac2b
add hyperspectral write data to docs updating file
JorgeGtz 0cf1163
Merge branch '4.x' into write-hyperspectral-data
nfahlgren c51e166
Merge branch '4.x' into write-hyperspectral-data
HaleySchuhl a3c8f8f
Apply suggestions from code review
JorgeGtz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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,41 @@ | ||
| ## 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*): | ||
|
|
||
|
|
||
| - **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) |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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,47 @@ | ||
| import os | ||
| import numpy as np | ||
|
|
||
| from plantcv.plantcv import _version | ||
|
|
||
| __version__ = _version.get_versions()['version'] | ||
|
|
||
| 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 {__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') | ||
| 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')) | ||
|
|
This file contains hidden or 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,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') | ||
| 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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would going beyond checking if the dimensions are the same to see if some of the values are the same be helpful? Or is just checking that they're the same shape usually sufficient |
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would going beyond checking if the dimensions are the same to see if some of the values are the same be helpful? Or is just checking that they're the same shape usually sufficient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a good question. We could check some values or also verify that it's the exact array. I think it depends on what can go wrong. Since the array is vectorized and written as a binary array, in order to have the correct dimensions the data type and the interleave format should be correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok cool, would just a simple
assert np.array_equal(array_data.array_data, rand_spectral_array)be good or do you think that would take up more time than it's worth?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both ways are good options