mvdh7 / PyCO2SYS

Marine carbonate system calculations in Python

Home Page:https://PyCO2SYS.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add input validation to `PyCO2SYS.constants.RGasConstant`

davidclemens opened this issue · comments

The code of RGasConstant suggests that the function argument WhichR can be supplied as an array and that the returned variable RGas will be of the same shape as WhichR.

However, if WhichR is an array the isequal test (e.g. WhichR == 1) will always return false, leaving the default value in RGas, which is nan.
Examples

import PyCO2SYS as pyco2
import numpy as np

# As expected:
pyco2.constants.RGasConstant(1) # returns array(83.1451) as expected
pyco2.constants.RGasConstant(2) # returns array(83.14472) as expected
pyco2.constants.RGasConstant(np.array([1,1])) # returns array([83.1451, 83.1451]) as expected

# Not as expected:
pyco2.constants.RGasConstant([1]) # returns array([nan]), expected array([83.1451])
pyco2.constants.RGasConstant([1,2]) # returns array([nan, nan]), expected array([83.1451, 83.14472])
pyco2.constants.RGasConstant(None) # returns array(nan), expected array([83.1451, 83.14472])

# Expected a default value or an error:
pyco2.constants.RGasConstant(5) #  WhichR is out of range, this should error or return the default
pyco2.constants.RGasConstant() # The input argument should really be optional and the function should return the default value if none is supplied
pyco2.constants.RGasConstant(np.array([1.3, 2.345])) # The inputs are no valid integers

So input checks are necessary:

  1. All WhichR inputs that are not scalar need to be numpy arrays of integers in the range from 1 to 3
  2. For invalid inputs it might be sensible to return a default value

Please correct me, if this behaviour is intentional or I misunderstood anything.

Thanks for maintaining this awesome tool!

I ran into this because of an error in calkulate. But I just noticed that you fixed that one in calculate in this commit.

Hey @davidclemens, thanks for looking into this!

At this point the intention is really that most users of PyCO2SYS will use only the top-level pyco2.sys function (which is deliberately the only part of the package that has its API documented). This function (in theory) takes care of all the checks that you describe above, for all the arguments, before calling these 'smaller' functions, rather than having individual checks built in to all the smaller functions themselves. Essentially, the current attitude is, if someone is advanced enough to dig into the undocumented part of the code, then they need to take care of their own variable types (i.e. use Numpy arrays, not lists, and make sure to use valid values).

So if you run all the examples through pyco2.sys(opt_gas_constant=...)['gas_constant'] instead, then I think you'll get the 'expected' behaviour.

(And yes, there was an error there, but Calkulate v23.3 should now play nicely with PyCO2SYS v1.8.1!)