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

Ewm7732 normalize by direct beam monitor #550

Open
wants to merge 8 commits into
base: next
Choose a base branch
from

Conversation

walshmm
Copy link
Collaborator

@walshmm walshmm commented Feb 21, 2025

Description of work

This adds a toggle to tell snapred to normalize by events from the monitor rather than proton charge.

Explanation of work

I refactored GroceryService to remove the two complex case statements, and instead model a more accurate fallback structure for loading native/lite/live data.

I then added the loading of monitor workspaces to the end, save the total events of the processed monitor workspace as a log, and use said log in normalization calculations down the line.

To test

Run each workflow, ensure that they still work with the toggle off.
Record results as far as normalization by current is concerned( like the log 'NormalizationFactor')
Run them again, ensure that they work with the toggle on.
Observe the monitor workspace get loaded and then quickly deleted during load.
Compare the normalization factor this time around, confirm that they are different and that the toggle was effective.

Ensure the results of each workflow are as expected, no out of the ordinary graphs for the normal testing data.

Link to EWM item

EWM#7732

Verification

  • the author has read the EWM story and acceptance critera
  • the reviewer has read the EWM story and acceptance criteria
  • the reviewer certifies the acceptance criteria below reflect the criteria in EWM

Acceptance Criteria

This list is for ease of reference, and does not replace reading the EWM story as part of the review. Verify this list matches the EWM story before reviewing.

  • There is a toggle in the application.yml for enabling this flow, and a config for which monitor to use (defaults false, and 0)
  • Workspaces have additional logs indicating that this was their method of normalization
  • The workspaces are in fact normalized this way (i.e. different results in the case of reduction, normalization, ect)
  • The story mentions needing different 'width'/'L1'/'particleBouncs' for the RemovePromptPulse on the monitor workspace but did not provide a location for said width, however using the same ones provided normally seemed to yield decent results.

@walshmm walshmm force-pushed the ewm7732_normalize_by_direct_beam_monitor branch 2 times, most recently from bdf41fe to fb99283 Compare February 24, 2025 17:31
Copy link

codecov bot commented Feb 24, 2025

Codecov Report

Attention: Patch coverage is 99.23077% with 1 line in your changes missing coverage. Please review.

Project coverage is 96.09%. Comparing base (eca6ddc) to head (cc056d9).
Report is 1 commits behind head on next.

Files with missing lines Patch % Lines
src/snapred/backend/data/GroceryService.py 99.21% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next     #550      +/-   ##
==========================================
- Coverage   96.10%   96.09%   -0.01%     
==========================================
  Files          71       71              
  Lines        5466     5458       -8     
==========================================
- Hits         5253     5245       -8     
  Misses        213      213              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@walshmm walshmm force-pushed the ewm7732_normalize_by_direct_beam_monitor branch 3 times, most recently from c753f3e to 16526a1 Compare February 25, 2025 19:50
rebase and fix unit tests

cleanup reabse

[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

implement normalize by monitor

fix some tests after a rebase

missed a test

completed reduction with normalizebymonitor

fix existing tests
@walshmm walshmm force-pushed the ewm7732_normalize_by_direct_beam_monitor branch from 82e17dd to 22fa04c Compare February 26, 2025 17:00
@walshmm walshmm marked this pull request as ready for review February 27, 2025 16:15
Copy link
Contributor

@rboston628 rboston628 left a comment

Choose a reason for hiding this comment

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

I still need to look at the GroceryService changes

@ekapadi
Copy link
Contributor

ekapadi commented Feb 28, 2025

One question about how you recommend to compare the normalization factors? A step-by-step might be useful. -- Thanks!

@ekapadi
Copy link
Contributor

ekapadi commented Feb 28, 2025

Monitor WNG workspace-name format is coming up as monitor_false... which is inconsistent with how the "lite-mode" token is formafted for run -- I think the solution is to initialize your WNG.monitor method in exactly the same way as the run method. (And possibly, not to fix anything beyond that for this PR... :) )

@ekapadi
Copy link
Contributor

ekapadi commented Feb 28, 2025

Without using monitor: NormalizationFactor = 2777.79

With monitor: NormalizationFactor = 1.465e-7 ??? This seems way too large of a change to me. Do you have a simple way to explain why this is what I should be expecting?
NormalizationFactor * ..normalizeByMonitorFactor ~= 1.0

@walshmm
Copy link
Collaborator Author

walshmm commented Feb 28, 2025

Without using monitor: NormalizationFactor = 2777.79

With monitor: NormalizationFactor = 1.465e-7 ??? This seems way to0 large of a change to me. Do you have a simple way to explain why this is what I should be expecting? NormalizationFactor * ..normalizeByMonitorFactor ~= 1.0

I could be recording the wrong value? I may have mistook NormalizeByCurrent as saving the actual scaling factor used as opposed to proton charge(?) I'll take a look.

@walshmm
Copy link
Collaborator Author

walshmm commented Feb 28, 2025

Though this is a little weird as far as the background workspace is concerned, as we are not doing a typical normalization? its some ratio of background to vanadium run monitor counts. This would be difficult to record in a number close to 2777 I think?

@walshmm
Copy link
Collaborator Author

walshmm commented Feb 28, 2025

The purpose of saving it to NormalizationFactor is so that later down the line it is not normalized again...

Copy link
Contributor

@ekapadi ekapadi left a comment

Choose a reason for hiding this comment

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

I added a few comments as "one offs" so I could do the review a little bit at a time. So far the only issues are with the WNG-formatted name of the monitor workspace, and with the extreme difference between the NormalizationFactor in the two modes. All of the workflows work as expected (including the live-data workflow). I'm looking at the grocery-service changes next...

@ekapadi
Copy link
Contributor

ekapadi commented Feb 28, 2025

Now I'm also wondering if this monitor-based normalization mode applies to the "art norm" workflow as well?

@walshmm
Copy link
Collaborator Author

walshmm commented Feb 28, 2025

Now I'm also wondering if this monitor-based normalization mode applies to the "art norm" workflow as well?

I dont think so? The art norm is cloned off the reduction input workspace after normalizeByCurrent/Monitor, so there is no background and its already normalized I think?

Copy link
Contributor

@ekapadi ekapadi left a comment

Choose a reason for hiding this comment

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

I really like the new flow-control changes in GroceryService -- it tremendously simplifies things! I left a few comments about remaining questions that I have, but once those are dealt with I am fine with all of these changes. (Provided we set "liveData.enabled" to False for the moment -- I don't think the mutex error is caused by anything in this PR.)

@@ -56,6 +56,7 @@ class GroceryListItem(BaseModel):
"",
"LoadCalibrationWorkspaces",
"LoadEventNexus",
"LoadNexusMonitors",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest: in alphabetical order -- that's what I had been doing here. :)

convertToLiteMode = False
# 1. check cache
# 2. check if file exists
# e. cannot find data.
Copy link
Contributor

Choose a reason for hiding this comment

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

'e.' or '3.'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

e for error, fallback case.


self._updateNeutronCacheFromADS(runNumber, useLiteMode)
data["workspace"] = workspaceName
# NOTE: When would it ever be false? If the workspace is not found, it should raise an error.
Copy link
Contributor

Choose a reason for hiding this comment

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

We are not necessarily consistent about this. Sometimes the return value is used, and sometimes it's not. This is not a good thing!

data = self.grocer.executeRecipe(str(nativeModeFilePath), workspaceName, loader)
success = True
def _fetchNeutronDataNative(self, item: GroceryListItem) -> Dict[str, Any]:
item.useLiteMode = False
Copy link
Contributor

Choose a reason for hiding this comment

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

Changing the value on the incoming item isn't a good idea. Definitely you need to make a copy here!

return self._fetchNeutronDataSingleUse(item, tryLiveData)

def _fetchNeutronDataLite(self, item: GroceryListItem, export=False) -> Dict[str, Any]:
item.useLiteMode = True
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as previous. It makes it really difficult to trace what is happening. So definitely make a copy of the item before modifying it.

workspaceName = self._createMonitorWorkspaceName(runNumber, useLiteMode)

# TODO: Cache if necessary
if self.workspaceDoesExist(workspaceName):
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we do this type of caching for any other type of workspace? If not, I think we need to be consistent about how we cache. That is, you probably need a _loadedMonitors dict.

@@ -1490,7 +1432,7 @@ def getResidentWorkspaces(self, excludeCache: bool):
workspaces = workspaces.difference(self.getCachedWorkspaces())
return list(workspaces)

def _processNeutronDataCopy(self, runNumber, workspaceName):
def _filterEvents(self, runNumber, workspaceName):
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we moving the removePromptPulse here as well, or is that part of another story?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

prompt pulse has already been moved here, that change is in next.

@@ -34,6 +34,9 @@ def unique_name(self, n=5, prefix="", suffix=""):
def unique_hidden_name(self):
return mtd.unique_hidden_name()

def getSNAPRedLog(self, wsName, logname):
return self[wsName].getRun().getLogData(f"{Config['metadata.tagPrefix']}{logname}").value
Copy link
Contributor

Choose a reason for hiding this comment

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

I really, really want this to throw a KeyError if the log isn't there. If I'm remembering correcty, that's not what mantid.api.Run does. Can we please wrap this in a try?

@@ -1,13 +1,17 @@
from mantid.api import AlgorithmFactory, MatrixWorkspaceProperty, PropertyMode, PythonAlgorithm
from mantid.kernel import Direction
from mantid.simpleapi import CloneWorkspace, NormaliseByCurrent, mtd
from mantid.simpleapi import CloneWorkspace, NormaliseByCurrent, Scale
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we using MantidSnapper inconsistently here?

@@ -157,6 +157,9 @@ reduction:

mantid:
workspace:
monitor:
normalizeByBeam: false
normID: 0
Copy link
Contributor

Choose a reason for hiding this comment

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

**I suggest expanding these names slightly (e.g.) normalizeByBeamMonitor and normalizationMonitorID (**or just monitorId). Also we should check whether it's "Id" or "ID", to be consistent.

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