def test_calibration_domain_range(): """Test setting the domain and range of a calibration.""" cal = Calibration("p[0] + p[1] * x", [5.0, 4.0]) # set the domain and range to defaults cal.domain = None cal.range = None # cannot set domain or range to infinite values with pytest.raises(CalibrationError): cal.domain = [-np.inf, np.inf] with pytest.raises(CalibrationError): cal.range = [-np.inf, np.inf] # set the domain and range to specific values x0 = 1 cal.domain = [x0 - 1, x0 + 1] cal.range = [-1e6, 1e6] # evaluate for x inside domain and result inside range y0 = cal(x0) # evaluate for x outside domain (fails) x1 = cal.domain[1] + 3 with pytest.raises(CalibrationError): cal(x1) # expand domain and reevaluate cal.domain = (cal.domain[0], x1 + 1) cal(x1) # evaluate for x inside domain and result outside range (warns) cal.domain = [x0 - 1, x0 + 1] cal.range = [y0 + 10, y0 + 20] with pytest.warns(CalibrationWarning): y2 = cal(x0) # y value is not clipped to the range so should be the same as before assert np.isclose(y0, y2) # expand range and reevaluate cal.range = [y0 - 1, y0 + 1] cal(x0)
def test_calibration_inverse(): """Test calibrations with and without inverse expression.""" fname = os.path.join(TEST_OUTPUTS, "calibration__inverse.h5") # cal1 has an explicit inverse expression, cal2 does not cal1 = Calibration("p[0] + p[1] * x", [5.0, 4.0], inv_expression="(y - p[0]) / p[1]") cal2 = Calibration(cal1.expression, [5.0, 4.0]) assert cal1 == cal2 # evaluate the inverse for a scalar y = 100.0 x1 = cal1.inverse(y) x2 = cal2.inverse(y) assert np.isclose(x1, (y - 5.0) / 4.0) assert np.isclose(x1, x2) # evaluate the inverse for a scalar with initial guess x1 = cal1.inverse(y, x0=25.0) x2 = cal2.inverse(y, x0=25.0) assert np.isclose(x1, (y - 5.0) / 4.0) assert np.isclose(x1, x2) # evaluate the inverse for an array y = np.linspace(20.0, 500.0, num=100) x1 = cal1.inverse(y) x2 = cal2.inverse(y) assert np.allclose(x1, (y - 5.0) / 4.0) assert np.allclose(x1, x2) # evaluate the inverse for an array with initial guesses y = np.linspace(20.0, 500.0, num=100) x0 = np.arange(len(y)) / 4.0 x1 = cal1.inverse(y, x0=x0) x2 = cal2.inverse(y, x0=x0) assert np.allclose(x1, (y - 5.0) / 4.0) assert np.allclose(x1, x2) # evaluate inverse for values inside the range with result inside domain cal1.domain = [0, 1] cal1.range = [-1e6, 1e6] x0 = 0.5 y0 = cal1(x0) cal1.range = [y0 - 1, y0 + 1] cal1.inverse(y0) # evaluate inverse for values inside the range with result outside domain cal1.domain = [0, 2] cal1.range = [-1e6, 1e6] x0 = 2.0 y0 = cal1(x0) cal1.domain = [0, 1] cal1.range = [y0 - 1, y0 + 1] with pytest.raises(CalibrationError): cal1(x0) with pytest.raises(CalibrationError): cal1.inverse(y0) # evaluate the inverse for a value outside the range and the domain cal1.domain = [0, 2] cal1.range = [-1e6, 1e6] x0 = 2.0 y0 = cal1(x0) cal1.domain = [x0 - 2, x0 - 1] cal1.range = [y0 - 2, y0 - 1] with pytest.raises(CalibrationError): cal1(x0) with pytest.raises(CalibrationError): cal1.inverse(y0) # test __str__() and __repr__() str(cal1) repr(cal1) # test write() and read() cal1.write(fname) cal3 = Calibration.read(fname) assert cal3.inv_expression is not None assert cal3.inv_expression == cal1.inv_expression