Giter VIP home page Giter VIP logo

tadz-io / hydropt Goto Github PK

View Code? Open in Web Editor NEW
18.0 2.0 4.0 25.76 MB

HYDROPT is an open-source framework for forward and inverse modelling of multi- and hyperspectral observations from oceans, coastal and inland waters. Our framework is based on radiative transfer principles and is sensor agnostic .

License: GNU Affero General Public License v3.0

Python 100.00%
python ocean-color remote-sensing inverse-modelling hyperspectral

hydropt's Introduction

HYDROPT: a Python Framework for Fast Inverse Modelling of Multi- and Hyperspectral Ocean Color Data

GitHub release (latest SemVer) license DOI Python package codecov

Description

HYDROPT is an open-source framework for forward and inverse modelling of multi- and hyperspectral observations from oceans, coastal and inland waters. The remote sensing reflectance, Rrs, is calculated by specifying the inherent optical properties (IOP) of the water column, the sensor viewing geometry and solar zenith angle. Our framework is based on radiative transfer principles and is sensor agnostic allowing Rrs to be calculated for any wavelength in the 400 - 710 nm range.

Inversion of Rrs spectra is achieved by minimizing the difference between the HYDROPT forward calculations and the reflectance measured by the sensor. Different optimization routines can be selected to minimize the cost function. An extensive description of the theoretical basis of the framework as well as applications are provided in the following scientific papers:

Holtrop, T., & Van Der Woerd, H. J. (2021). HYDROPT: An Open-Source Framework for Fast Inverse Modelling of Multi- and Hyperspectral Observations from Oceans, Coastal and Inland Waters. Remote Sensing, 13(15), 3006. doi:10.3390/rs13153006

Van Der Woerd, H.J. & Pasterkamp, R. (2008). HYDROPT: A fast and flexible method to retrieve chlorophyll-a from multispectral satellite observations of optically complex coastal waters. Remote Sensing of Environment, 112, 1795โ€“1807. doi:10.1016/j.rse.2007.09.001

Please cite our latest publication if you decide to use HYDROPT in your research:

@article{
    Holtrop_2021,
    title={HYDROPT: An Open-Source Framework for Fast Inverse Modelling of Multi- and Hyperspectral Observations from Oceans, Coastal and Inland Waters},
    author={Holtrop, Tadzio and Van Der Woerd, Hendrik Jan},
    journal={Remote Sensing}, 
    volume={13},
    number={15}, 
    month={Jul}, 
    pages={3006},
    year={2021}, 
    DOI={10.3390/rs13153006}, 
    publisher={MDPI AG}
}

Features

  • Specification of IOP models for forward and inverse modelling
  • Sensor agnostic calculations of Rrs in 400 - 710 nm range
  • Calculation of Rrs at nadir; off-nadir angles will be implemented in the future
  • Specification of solar zenith angle will be implemented in the future (30 degrees sza by default)
  • Levenberg-Marquardt optimization is used for the inversion; future versions will be able to select the full range of optimization routines offered in SciPy and LMFIT libraries.

Installation

Install HYDROPT using pip:

pip install hydropt-oc

Getting started

An example of how to create a case-I bio-optical model and perform forward and inverse calculations. First import the HYDROPT framework:

import hydropt.hydropt as hd

Let's run the forward and inverse calculations at every 5 nm between 400 and 710 nm. First specify the wavebands:

import numpy as np

wavebands = np.arange(400, 711, 5)

We can import the inherent optical properties (IOP) of water from the bio_optics module and create an optical model for this component as follows:

from hydropt.bio_optics import H2O_IOP_DEFAULT

def clear_nat_water(*args):
    return H2O_IOP_DEFAULT.T.values

Every optical component should be constructed as a Python function that returns the IOPs as a 2xn numpy array where n is the number of wavebands. The first row (arr[0]) should list the absorption values, the second row (arr[1]) lists the backscatter values. For phytoplankton we define the optical model in a similair way, importing the absorption values from the bio_optics module and specifying a constant spectral backscatter:

from hydropt.bio_optics import a_phyto_base_HSI

def phytoplankton(*args):
    chl = args[0]
    # basis vector - according to Ciotti&Cullen (2002)
    a = a_phyto_base_HSI.absorption.values
    # constant spectral backscatter with backscatter ratio of 1.4%
    bb = np.repeat(.014*0.18, len(a))

    return chl*np.array([a, bb])

For colored dissolved organic matter (CDOM) we do the following:

def cdom(*args):
    # absorption at 440 nm
    a_440 = args[0]
    # spectral absorption
    a = np.array(np.exp(-0.017*(wavebands-440)))
    # no backscatter
    bb = np.zeros(len(a))

    return a_440*np.array([a, bb])

The IOPs of all optical components should be specified at the same wavebands. Now that all optical components are created lets add them to an instance of the BioOpticalModel class:

bio_opt = hd.BioOpticalModel()
# set optical models
bio_opt.set_iop(
    wavebands=wavebands,
    water=clear_nat_water,
    phyto=phytoplankton,
    cdom=cdom)

It is important that the keyword for the water optical model argument is called water. We can check if everything works correctly by plotting the mass specific IOPs for these components:

bio_opt.plot(water=None, phyto=1, cdom=1)

Now we can initialize the HYDROPT forward model with the bio-optical model, bio_opt, that we have just created and calculate Rrs when the phytoplankton concentration is 0.15 mg/m3 and CDOM absorption is 0.02 m-1:

# the HYDROPT polynomial forward model
fwd_model = hd.PolynomialForward(bio_opt)
# calculate Rrs
rrs = fwd_model.forward(phyto=.15, cdom=.02)

Lets invert the Rrs spectrum we just calculated with the specified forward model fwd_model. At this point HYDROPT only supports the Levenberg-Marquardt routine from the LMFIT library (lmfit.minimize). Please refer to the LMFIT documentation for more information.

Specify an initial guess for the phytoplankton concentration and CDOM absorption used for the Levenberg-Marquardt routine. Lower bounds should be set for all retrieval parameters. HYDROPT is not able to handle negative or zero values due to log-transformations. Lower bounds should be greater than zero.

import lmfit
# set initial guess parameters for LM
x0 = lmfit.Parameters()
# some initial guess
x0.add('phyto', value=.5,  min=1E-9)
x0.add('cdom', value=.01, min=1E-9)

Now invert Rrs to retrieve the concentration and absorption of phytoplankton and CDOM respectively:

# initialize an inversion model
inv_model = hd.InversionModel(
    fwd_model=fwd_model,
    minimizer=lmfit.minimize)
# estimate parameters
xhat = inv_model.invert(y=rrs, x=x0)

That's it!

Documentation

Documentation will be available soon. For questions please reach out!

License

AGPL-3.0

hydropt's People

Contributors

tadz-io avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

hydropt's Issues

AttributeError: 'BioOpticalModel' object has no attribute 'set_iops'

Hi Tadzio,

I have just stumbled upon HYDROPT and am excited to give it a try.
Currently, I follow the Get Started section and everything runs smoothly until I set the model's IOPs;

bio_opt.set_iops( wavebands=wavebands, water=clear_nat_water, phyto=phytoplankton, cdom=cdom)

where I get following error:

AttributeError: 'BioOpticalModel' object has no attribute 'set_iops'

Any ideas? I am running Python 3.7.13 in Anaconda on a Windows machine and used pip to install HYDROPT.

Many thanks and keep up the good work :)
Marcel

Value Error: Traceback (most recent call last) for line: xhat = inv_model.invert(y=rrs, x=x0)

Hi again,

the code is now running except for the last line:

xhat = inv_model.invert(y=rrs, x=x0)

Here, I receive the following:

`---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_3728\1455539996.py in
4 minimizer=lmfit.minimize)
5 # estimate parameters
----> 6 xhat = inv_model.invert(y=rrs, x=x0)

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\hydropt\hydropt.py in invert(self, y, x, w, jac, **kwargs)
275 args = self._band_model((y, self._fwd_model.forward))
276 # do optimization
--> 277 xhat = self._minimizer(loss_fun, x, args=args, Dfun=jac_fun, **kwargs)
278 # warnings.warn('''no band transformation is applied to jacobian -
279 # o.k. when band_model = 'rrs' ''')

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\lmfit\minimizer.py in minimize(fcn, params, method, args, kws, iter_cb, scale_covar, nan_policy, reduce_fcn, calc_covar, max_nfev, **fit_kws)
2581 nan_policy=nan_policy, reduce_fcn=reduce_fcn,
2582 calc_covar=calc_covar, max_nfev=max_nfev, **fit_kws)
-> 2583 return fitter.minimize(method=method)

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\lmfit\minimizer.py in minimize(self, method, params, **kws)
2350 val.lower().startswith(user_method)):
2351 kwargs['method'] = val
-> 2352 return function(**kwargs)
2353
2354

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\lmfit\minimizer.py in leastsq(self, params, max_nfev, **kws)
1687 result.call_kws = lskws
1688 try:
-> 1689 lsout = scipy_leastsq(self.__residual, variables, **lskws)
1690 except AbortFitException:
1691 pass

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\scipy\optimize\minpack.py in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
422 maxfev = 200*(n + 1)
423 retval = _minpack._lmdif(func, x0, args, full_output, ftol, xtol,
--> 424 gtol, maxfev, epsfcn, factor, diag)
425 else:
426 if col_deriv:

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\lmfit\minimizer.py in __residual(self, fvars, apply_bounds_transformation)
600 else:
601 return _nan_policy(np.asarray(out).ravel(),
--> 602 nan_policy=self.nan_policy)
603
604 def __jacobian(self, fvars):

~\Anaconda3\envs\CarbonMapper_py3713\lib\site-packages\lmfit\minimizer.py in _nan_policy(arr, nan_policy, handle_inf)
2434 'handle this! Please read https://lmfit.github.io/lmfit-py/faq.html#i-get-errors-from-nan-in-my-fit-what-can-i-do '
2435 'for more information.')
-> 2436 raise ValueError(msg)
2437 return arr
2438

ValueError: NaN values detected in your input data or the output of your objective/model function - fitting algorithms cannot handle this! Please read https://lmfit.github.io/lmfit-py/faq.html#i-get-errors-from-nan-in-my-fit-what-can-i-do for more information.`

Any thoughts?

Thanks and best regards,
Marcel

**Xarray support**

  • inherit from np.ndarray and create labeled multi-dimensional array capability
  • apply_along_axis() should copy xarray coordinates and dimensions

#Issue with lmfit minimizer()

Couldn't map the Xarray data array using inversionmodel.invert function

Getting an Attribute error: 'MinimizerResult' has no attribute 'dims'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.