spectralpython / spectral

Python module for hyperspectral image processing
MIT License
573 stars 139 forks source link

Add option for forcing lower case in key names when reading in ENVI header #63

Closed jmsuomal closed 7 years ago

jmsuomal commented 7 years ago

First of all, big thanks for providing an excellent spectral python module!

In our use we are acquiring images with some custom metadata and then storing them in ENVI BSQ format. The metadata contains a lot of fields that are non-standard for ENVI format such as exposure and synchronization timing details. We are writing the files using _spectral.envi.saveimage() method and then later in post processing phase reading them back in using spectral.envi.open() and _spectral.envi.read_enviheader() methods. Everything gets written perfectly fine, but when reading the header data back in the _envi.read_enviheader()-method forces all the key names to lower case. I understand why this has been implemented, but in our user case it causes issues as the field names in MetaDataDictIn do not match perfectly those originally in MetaDataDictOut.

It would be an easy to give user option if the lower case is applied or not. Currently the function contains lines:

def read_envi_header(file):
...
            key = key.strip().lower()
...

I propose these lines to be replaced with:

def read_envi_header(file, lowercasekeys=True):
...
            key = key.strip()
            if lowercasekeys:
                key = key.lower()
...

...then the user would have an option to disable the lower case if needed, and it would have no effect for the users who are happy with lower case formatting.

tboggs commented 7 years ago

I think we can make this happen but it won't be quite as simple as updating read_envi_header because users don't typically call that function directly. Rather, there are multiple other functions that call it so the new argument would need to propagate up to the calling functions as well. Since ENVI header keywords are case-insensitive, I'm a bit hesitant to propagate up a special arg to all the calling functions to accommodate special behavior because it will be a potential source of problems if/when changes to the standard format need to be addressed.

How would you feel about having a module-level variable that you would set to enable mixed-case header keywords? You would do something like this:

spectral.envi.allow_mixed_case_headers = True

Or it could be put in the package-level settings object:

spectral.settings.envi_allow_mixed_keywords = True

I realize it's a bit more effort for you because you would need to set the variable but it would keep the code simpler and avoid confusion with regard to the standard format. To support this, there could also be a check in read_envi_header that gives a warning if a mixed-case keyword name is read but the appropriate setting is not enabled (e.g., "warning: mixed case ENVI keyword <> converted to lower case. To enable mixed-case keywords, set ......").

jmsuomal commented 7 years ago

For me, using a module level variable would be also a perfectly good solution. It is not a problem at all to set that when importing the module.

tboggs commented 7 years ago

Great. I'm busy for about the next week but I'll plan to add this as a feature. In the mean time, you can always edit read_envi_header in your local copy of envi.py. You'll see this issue close when the change is done.

tboggs commented 7 years ago

This feature was added by commit f4731e7822fd34aa53fea74b6733152eb1bf4342.

The default behavior is as before (parameter names are all converted to lower case) except a warning will be given if a parameter is converted to lowercase. To retain non-lowercase parameter names when opening ENVI files, do the following before opening any files:

import spectral
spectral.settings.envi_support_nonlowercase_params = True

Then any headers with uppercase or mixed-case parameters names will have their parameters read into the image metadata as-is.