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

Slicer extension 1344 #1919

Merged
merged 38 commits into from
Apr 26, 2024
Merged

Slicer extension 1344 #1919

merged 38 commits into from
Apr 26, 2024

Conversation

butlerpd
Copy link
Member

@butlerpd butlerpd commented Oct 4, 2021

This PR attempts to allow the box slicers to take slices whose center is not 0,0. if using the full q range of the long dimension this would be the same as giving slices at constant qx yielding I(qy|qx=constant) for example.

@butlerpd butlerpd added this to the SasView 5.0.5 milestone Oct 4, 2021
@butlerpd
Copy link
Member Author

butlerpd commented Oct 4, 2021

ready for testing on Win

@butlerpd
Copy link
Member Author

It now mostly works!! Remaining things to address that I found through testing on a (slow) Windows 10 machine.

  • We need to add the Qcenter (e.g. [Qx_center, Qy_center]) to the slicer parameter editor.
  • Now that Qcenter is not alwayas [0,0], we need to change the xmax and ymax to no longer be relative to [0,0]. I can think of two possibilities. I think the second is more useful for the typical user:
    • make them relative to Qcenter
    • change the to be a delta Q. In other words the width of the slab in Q
  • Minor issue that may not be possible to fix easily and could easily be punted to a future ticket is that depending on the data set the Qcenter handle is not obvious till you move the cursor over it.
  • The Q center handle is not cleaned up when a new slicer is called. If one brings up the x slicer and moves the center around then decides to switch to the y slicer (or any other slicer for that matter), the center handle at the time of the change seems to remain permanently fixed on the plot. It cannot be removed by toggling log/lin or changing the color scale even. The result can be quite interesting if switching back and forth between x and y slicers: It starts to look like the plot has chickenpox 😄
  • There are two, perhaps related perhaps not, issues with the graphical motion of the center handle
    • when using the cursor to move the box center, the center moves to the last captured cursor position BEFORE the current position. Thus when letting up on the mouse (drag) button, the center position will jump to the final cursor position. This makes precise positioning very difficult.
    • While not 100% reproducible it seems to be 80% reproducible that if moving the Qcenter in the negative part of the plot (negative Qx for the x slab or negative Qy for the y slab), the GUI seems to miss the unclick action of the mouse if the cursor is still moving before the center handle can "jump" to its final location. Stopping the motion and left clicking while the cursor is motionless seems to resolve the issue though every once in a while it requires several clicks to let go.
  • Finally, unit tests probably need to be updated and/or added for the new functionality?

@rozyczko
Copy link
Member

I get the following two errors when testing the functionality:

  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Binder.py", line 291, in _onMotion
    self.trigger(self._hasclick, 'drag', event)
  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Binder.py", line 217, in trigger
    processed = self._actions[action][artist](ev)
  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Slicers\BaseInteractor.py", line 142, in onDrag
    self.restore(ev)
TypeError: restore() takes 1 positional argument but 2 were given
File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Slicers\BaseInteractor.py", line 129, in onRelease
    self.moveend(ev)
  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Slicers\BoxSlicer.py", line 538, in moveend
    self.base.moveend(ev)
  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Slicers\BoxSlicer.py", line 248, in moveend
    self._post_data()
  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Slicers\BoxSlicer.py", line 747, in _post_data
    self.post_data(SlabX, direction="X")
  File "C:\Users\piotr\projects\sasview\src\sas\qtgui\Plotting\Slicers\BoxSlicer.py", line 198, in post_data
    boxavg = box(self.data)
  File "C:\Users\piotr\projects\sasview\src\sas\sascalc\dataloader\manipulations.py", line 460, in __call__
    return self._avg(data2D, 'x')
  File "C:\Users\piotr\projects\sasview\src\sas\sascalc\dataloader\manipulations.py", line 430, in _avg
    raise ValueError(msg)
ValueError: Average Error: No points inside ROI to average...

@butlerpd
Copy link
Member Author

Thanks @rozyczko I just noticed the second error on exiting the application but failed to see the first. Looking more closely I too get that error. This could easily solve a couple of the GUI problems I'm guessing?

Copy link
Member

@rozyczko rozyczko left a comment

Choose a reason for hiding this comment

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

Code looks very good, there are some very minor stylistic issues left.
If the errors seen in my local build test are reproducible, then those will have to be addressed.

src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Outdated Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Outdated Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Outdated Show resolved Hide resolved
@kmothander
Copy link
Contributor

I've tested this locally on Linux.

The errors that occurred previously are fixed, sometimes I get the error "ValueError: Average Error: No points inside ROI to average...", but not 100% reproducible, and only happens at -Qx. I'm not really sure where this error comes from or how to fix it...

I've also fixed so that the box is placed in the middle of the plot not just at Qx = Qy = 0. However, if the plot only contains data at negative Qx (and negative Qy) then I get the same error as above.

I've added a x_center and y_center to the parameter list. The parameters can be edited through the Edit slicer parameter window.

Question:
As @butlerpd mentioned, should there be other parameters then x_max, y_max, x_center and y_center? I think it should be possible to have x/y_center and then an sizes of the box, in the same way as for the BoxSum. Or should the size and placement of the box be defined in some other way?

@butlerpd
Copy link
Member Author

LOL .. I see that it looks like these commits break all the unit tests .. which makes sense since the behavior has been altered. Those will need to be adjust clearly to reflect the new correct behavior.

Regarding the question about how to present the width variables that is a question of what might be easier/more intuitive for a user. My thinking was that for the purpose at hand my guess is that the user will more likely be thinking in terms of delta Q around the center rather than qmax?

Another usability question that has come to mind is whether for the boxslicer as opposed to boxsum, it would not make much more sense (and be less confusing to a new user) if the default box was not drawn as a square from -.5 imagedQ to +.5 imagedQ in both directions. I would think something like -3/4 imagedQ to + 3/4 imagedQ (or even -1 to 1) in the direction of the q being scanned and maybe -.2 to +.2 in the direction of q being integrated.

Note that by imagedQ I mean qmax-qcenter of the displayed data (image)

@kmothander
Copy link
Contributor

@butlerpd
I have no idea how to change the unit test...

To your other questions I can change and add the new functionality. Changing the parameter list and see if I can change the initial size of the box!

@butlerpd butlerpd changed the base branch from main to release_5.0.5 November 20, 2021 22:39
@wpotrzebowski wpotrzebowski added the Discuss At The Call Issues to be discussed at the fortnightly call label Nov 22, 2021
@wpotrzebowski
Copy link
Contributor

@butlerpd will look at it

@wpotrzebowski wpotrzebowski removed the Discuss At The Call Issues to be discussed at the fortnightly call label Nov 23, 2021
@butlerpd butlerpd modified the milestones: SasView 5.0.5, SasView 5.1.0 Jan 4, 2022
@butlerpd butlerpd added the Discuss At The Call Issues to be discussed at the fortnightly call label May 23, 2022
@butlerpd
Copy link
Member Author

See if @butlerpd can address at June hackathon otherwise remove PR and wait till someone has time

@butlerpd butlerpd removed the Discuss At The Call Issues to be discussed at the fortnightly call label May 24, 2022
@lucas-wilkins lucas-wilkins added the Stale Mark for potential close: issue no longer seems relevant / probably complete / probably not doable. label Oct 29, 2022
@butlerpd butlerpd removed the Stale Mark for potential close: issue no longer seems relevant / probably complete / probably not doable. label Oct 31, 2022
@butlerpd
Copy link
Member Author

There is a difference between very limited resources on a complex project and a stale project :-)

@lucas-wilkins lucas-wilkins added the Stale Mark for potential close: issue no longer seems relevant / probably complete / probably not doable. label Nov 25, 2022
@lucas-wilkins
Copy link
Contributor

This branch is 9 commits ahead, 1374 commits behind main.

@lucas-wilkins
Copy link
Contributor

lucas-wilkins commented Nov 25, 2022

There is a difference between very limited resources on a complex project and a stale project :-)

Unlike issues, branches get behind main and merging them gets harder and harder. If you don't want a stale label, please keep it up to date with main, preferably with log10(commit_difference) < 2.

@lucas-wilkins lucas-wilkins added Coal Star Award for 500+ Commits Behind 'main' This PR runs on a fossil version of main and removed Stale Mark for potential close: issue no longer seems relevant / probably complete / probably not doable. labels Nov 25, 2022
Changes were made to release 5.0.5 branch and attempted to be reverted 2 years ago. For reasons lost in the mists of time, 3 months later branch 5.0.5 was merged into this branch even though it was based on main and not being released?  This led to 4 files from @dehoni work in a completely different branch becoming part of the changes in this branch compared to main. By usind checkout main --file, I've now updated the offending files with what is currently in main (the base) so that they should no longer be part of the pull request.
@butlerpd butlerpd changed the base branch from main to release_6.0.0 March 25, 2024 19:43
* Fixed numerous typos in comments
* Deleted unused (commented out) code
* Fixed issue regarding question of default for fold param
* Fixed issue of if statement not capturing incorrect value being passed for self.direction (added elif)
* Fixed an unreported problem in numbper of parameters in a remove function (def restore(self, ev) instead of def restore(self)
The _post_data method calculates the bin widths to pass to manipulations.py. This probably should not be how it is done but is currently. This was still using the simple calculation based on a fixed center at 0,0 and thus caused havoc when moving the center around.
* The validate function was done twice. It has been moved from BoxInteractorX(Y) to BoxInteractor.
* The validate function was expanded to minimize the chance of
creating an ROI with no data in it (which would throw an error)
* Added/simplified code in the move(ev) method of both horizontal
and vertical lines interactor to prevent negative widths (which leads to no points in the ROI and thus throws an error)
As suggested by reviewer. The values should never be negative but it is unclear whether if they end up negative (should not be possible at this point) that absoluting them will yield the correct answer. Thus better for it to fail.

Also fixed a couple more typos
The review comments asked for the dictionary set params for x and y widths be standardized. In fact it turned out that a) the widths were actually half widths and b) there was a variety of words used. The entire BoxSlicer.py code now uses half_width and half_height (and half_width_min etc).

Also as per review, the abs(half_width/height) from set params was removed. It turns out the values should never be negative but it is unclear whether absoluting them if they end up negative (which should not be possible at this point)  will yield the correct answer. Thus better for it to fail.

also corrected the nbins calculation in _post_data for direction="Y" (the plus should have been a minus)
@dehoni
Copy link
Contributor

dehoni commented Apr 6, 2024

Side note - There are changes to sas_gen.py and associated unit tests in here. Is this a merge-related issue? I think @dehoni should take a look to be sure we don't remove necessary functionality.

Indeed these were spurious commits that came in from a couple of poorly executed merging/reverting/munging 2 years ago. This was fixed by my last commit cd3e7fd (see commit notes for more details). The files mentioned are no longer part of the changes in this PR

These files are part of main. It must have been part of an update of the branch. Anyway, the files are unrelated to this PR feature and only work on the general scattering calculator.

ROI has no data error is impossible to catch without checking to see if any of the data are in the ROI. This is effectively done in manipulations.py as part of deciding what to average. Rather than check twice, use a try except to capture the ValueError that manipulations.py raises and report it in the log then negate the move.
Apply same checks to the Parameter editor data entry as is applied when entering slicer parameters graphically.
* Make the validate function fully robust
* As for the graphical interface, let manipulations.py check for no data in ROI and negate the entry if the error is flagged.
* Note, we have added that the full ROI must remain on the plot not just the center point as was done originally and still is the case graphically. This might be something to fix graphically as well.
* Removed "restore" from onDrag in baseinteractor. It should never be needed since the illegal move is never recorded. Replaced it with a log message that attempt was made to go out of bounds.
* Removed unused qmax variables from BoxInteractor where they do not seem to ever have been used.
* In BoxInteractor, changed default self.half_height to 1.0 instead of 0.9 when direction = Y to match default self.half_width when direction = X (was leftover from old testing).
* Removed super()._post_data from the inialization of the BoxInteractorX/Y. It was duplicating what was done in BaseInteractor (and didn't fail only because BaseInteractor had already run it properly).
* Fixed bug in BoxInteractor._post_data that reversed the limits (ymin is from horizontal_lines not vertical_lines). Mostly OK due to redundancy but not totally robust.
 One of the super()._post_data from the inialization of the BoxInteractorX/Y was accidentally ommitted in the previous commit.
Added code in the mov(ev) methods for all three objects (vertical and horizontal lines and the center point) to check that the move does not cause any part of the ROI to exit the data window.
@butlerpd
Copy link
Member Author

All comments and concerns should now have been addressed. Also in testing a few new bugs were discovered and fixed and all user inputs now checked to avoid failures as documented in each of the commit messages.

One question: The tests now log warning when the user tries to provide an invalid ROI. However, Warnings do not trigger opening the GUI console. Only Error level logging does. However the warning is meant as an aid to the user. Can we have warnings bring up the console? or should these messages be labelled as error even though I would argue they technically do not rise to the error level at this point?

connect the top and right lines (those with the markers) so they can be moved without "catching" the marker. Particularly useful if the box becomes very narrow so that the center marker and line marker are on top of each other.  This also matches the behavior of the sector slicer so also part of making slicers consistent.
Testing if latest PyInstaller fixes startup problem
Copy link
Contributor

@krzywon krzywon left a comment

Choose a reason for hiding this comment

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

This is looking much better. I think almost there.

.github/workflows/ci.yml Outdated Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BaseInteractor.py Outdated Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Show resolved Hide resolved
src/sas/qtgui/Plotting/Slicers/BoxSlicer.py Show resolved Hide resolved
# Conflicts:
#	.github/workflows/ci.yml
Implemented a self.move_valid flag in order to only throw 1 logging.warning message until a valid move occurs to reset the flag.  Unfortuantely this cannot be implemented yet in the onDrag of BaseInteractor as that would change the interface for all other classes deriving from BaseInteractor. Instead have removed the logging for now. In fact this check is no longer necessary for box interactor and not sure any other interactor except boxsum perhaps? So probably eventually remove that check from BaseInteractor.py altogether.

Also changed the logging.error to logging.warning on the try except catch. TODO: either change all to loggin.error, lower the leve at which it starts the console log ... or decide not telling the user is OK.
Copy link
Contributor

@krzywon krzywon left a comment

Choose a reason for hiding this comment

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

Minor nitpick at this point: The graphical box interactors won't allow me to extend/move to the edge of the data anymore, but that is mostly a visual issue.

Instead of ignoring moves that move an edge of the ROI box outside the data, reset the edge to the datamin or datamax as appropriate. This makes it easier to move a box to the edge of the data box and also makes it possible to vertically move a horizontal strip going from xmin to xmax etc.
@krzywon
Copy link
Contributor

krzywon commented Apr 26, 2024

I just tested the latest changes (from code, not the installer) and the user experience is much better. The box sides are coerced to the data limits and no warnings.

Assuming the installers work, I think this can be merged.

@butlerpd
Copy link
Member Author

It still needs to have the ci.yml reverted. before merging. Will do after my meeting.

We probably should also say something in the docs. The coercion to the edge worked a bit better for me the old way but the big advantage here that I think trumps all minor differences in usage is the fact that now you can slide the initial box up and down (or sideways depending on which slicer it is) without shrinking the box.

Note I plan to update the docs in another PR. A lot of the changes will need documentation updates as well.

@butlerpd butlerpd merged commit 77d7a32 into release_6.0.0 Apr 26, 2024
36 checks passed
@butlerpd butlerpd deleted the SlicerExtension_1344 branch April 26, 2024 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
SasView 6.0.0 Required for 6.0.0 release
Projects
None yet