Skip to content

Single kernel call for volume and intensity#3963

Open
jellybean2004 wants to merge 1 commit into
SD_calc_reformatfrom
SD_remove_hardcode
Open

Single kernel call for volume and intensity#3963
jellybean2004 wants to merge 1 commit into
SD_calc_reformatfrom
SD_remove_hardcode

Conversation

@jellybean2004
Copy link
Copy Markdown
Member

Description

Removes hard-coded/duplicated volume math and ensures intensities/volumes come from the model kernel.

Replaces the previous per-bin DirectModel/analytic volume approach with a kernel-based single call.
Builds the sasmodels kernel (from model info) and calls call_Fq for each bin to retrieve Fsq and volume. Compute intensity per bin as intensity = (scale/volume) * Fsq + background and store per-bin volumes in self._volumes.

Fixes #3418

How Has This Been Tested?

Tested functionality -- same as before.

Review Checklist:

Documentation

  • There is nothing that needs documenting
  • Documentation changes are in this PR
  • There is an issue open for the documentation (link?)

Installers

  • There is a chance this will affect the installers, if so
    • Windows installer (GH artifact) has been tested (installed and worked)
    • MacOSX installer (GH artifact) has been tested (installed and worked)
    • Wheels installer (GH artifact) has been tested (installed and worked)

Licensing

  • The introduced changes comply with SasView license (BSD 3-Clause)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the size distribution model-matrix generation so that both per-bin intensity and volume are obtained via a single sasmodels kernel call, removing the prior duplicated/hard-coded volume math path.

Changes:

  • Replaces load_model/DirectModel usage with load_model_info + build_model and call_Fq in generate_model_matrix.
  • Computes per-bin intensity from returned kernel outputs and stores per-bin volumes on the class for later use.
Comments suppressed due to low confidence (1)

src/sas/sascalc/size_distribution/SizeDistribution.py:193

  • self._volumes is initialized twice in __init__ (once untyped, then again with a type annotation). This duplication is redundant and can confuse readers/type checkers; remove the earlier self._volumes = None assignment and keep the single typed initialization.
        self.model_matrix: np.ndarray | None = None
        self._volumes = None

        # Advanced parameters for MaxEnt
        self._iterMax: int = 5000
        self._skyBackground: float = 1e-6
        self._weightType: str = "dI"
        self._weightFactor: float = 1.0
        self._weightPercent: float = 1.0
        self._weights: np.ndarray | None = np.array(data.dy)

        self._bin_edges: np.ndarray = np.array([])
        self._binDiff: np.ndarray = np.array([])
        self._volumes: np.ndarray | None = None

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +508 to +509
call_pars = p.copy()
_, Fsq, _, volume, volume_ratio = call_Fq(calculator, call_pars)

# Build a single Kernel to compute both intensity and volume per bin
model_info = load_model_info(self.model)
model_obj = build_model(model_info)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 486: model = load_model(self.model) is equivalent to line 499-500. Use model_obj = load_model(self.model) instead.


# Volume ratio is 1 for solid particles
if volume_ratio is not None:
volume *= volume_ratio
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

volume_ratio from call_Fq is never None.

call_pars = p.copy()
_, Fsq, _, volume, volume_ratio = call_Fq(calculator, call_pars)

# Compute intensity using kernel convention: combined_scale = scale / shell_volume
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicating code from within sasmodels.kernel.Kernel.Iq. This isn't avoidable in the current implementation, but we should consider this use case when addressing sasmodels #182.

The idea is to return intermediate and derived values from the calculation back to the caller. The current hack to get $P(Q)$ and $S(Q)$ from P@S is that sasmodels.product sets up a kernel.results() function that returns a dictionary with keys P(Q), S(Q), volume, volume_ratio and radius_effective after calling kernel.Iq(). We could extend this to the base Kernel class in sasmodels. Then using call_kernel instead of call_Fq we can get the volume and volume ratio from calculator.results().

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

Successfully merging this pull request may close these issues.

3 participants