Skip to content
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

pure python valid region does not behave as shown in docs #577

Open
butlerpd opened this issue Aug 16, 2023 · 2 comments
Open

pure python valid region does not behave as shown in docs #577

butlerpd opened this issue Aug 16, 2023 · 2 comments

Comments

@butlerpd
Copy link
Member

butlerpd commented Aug 16, 2023

If there are regions of parameter space which are not valid, a model function can exclude them from fitting according to the docs. However the C models do it differently and require a valid = (Boolean expression) while the python model is told to return np.nan.

Recent attempts at using this second version shows it does not actually work for fitting. Upon investigation @pkienzle believes that the following code placed at line 225 of kernelpy.py] might fix the problem

total = form()
if np.isnan(total).any():
    total = np.zeros(nq, 'd')

That said, a preferred solution would be to make the two interfaces the same. That however would require parsing a C style Boolean expression.

@pkienzle
Copy link
Contributor

Should avoid computing the form volume and form radius since they are also likely to be invalid. The code becomes:

if call_details.num_active == 0:
    weight_norm = 1.0
    total = form()
    if np.isnan(total).any():
        total = np.zeros(nq, 'd')
        weighted_shell = weighted_form = weighted_radius = 0
    else:
        weighted_shell, weighted_form = form_volume()
        weighted_radius = form_radius()

@pkienzle
Copy link
Contributor

Current code looks like returning NaN should work:

Iq = np.asarray(form(), 'd')
if np.isnan(Iq).any():
continue
# Update value and norm.
total += weight * Iq
weight_norm += weight
unweighted_shell, unweighted_form = form_volume()
weighted_shell += weight * unweighted_shell
weighted_form += weight * unweighted_form
weighted_radius += weight * form_radius()

For valid = ... we could do a simple string substitution with "!"=>" not ", "&&" => " and ", and "||" => " or ", then use eval() on the expression. If the result is true then proceed with the loop otherwise continue. Various checkers will raise flags that eval() is unsafe; we ought to ignore them since the rest of the model is running arbitrary python code supplied by the user, but they can be persistent.

Note that this is the same place we would need to insert a call to transform the function arguments if we want reparameterize() to support python models.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants