diff --git a/installers/sasview.spec b/installers/sasview.spec index f3c463ce24..ac9701e381 100644 --- a/installers/sasview.spec +++ b/installers/sasview.spec @@ -18,6 +18,7 @@ datas = [ ('../src/sas/qtgui/Utilities/Reports/report_style.css', 'sas/qtgui/Utilities/Reports'), ('../src/sas/qtgui/Perspectives/Fitting/plugin_models', 'plugin_models'), ('../src/sas/qtgui/Utilities/WhatsNew/messages', 'sas/qtgui/Utilities/WhatsNew/messages'), + ('../src/sas/qtgui/Utilities/WhatsNew/css/style.css', 'sas/qtgui/Utilities/WhatsNew/css'), ('../src/sas/qtgui/Utilities/About/images', 'sas/qtgui/Utilities/About/images'), ('../src/sas/system/log.ini', 'sas/system/'), ('../../sasmodels/sasmodels','sasmodels'), diff --git a/src/sas/qtgui/MainWindow/GuiManager.py b/src/sas/qtgui/MainWindow/GuiManager.py index f4e006f5aa..f505297451 100644 --- a/src/sas/qtgui/MainWindow/GuiManager.py +++ b/src/sas/qtgui/MainWindow/GuiManager.py @@ -662,6 +662,7 @@ def actionWelcome(self): self.welcomePanel.show() def actionWhatsNew(self): + self.WhatsNew = WhatsNew(strictly_newer=False) self.WhatsNew.show() def showWelcomeMessage(self): diff --git a/src/sas/qtgui/Perspectives/ParticleEditor/datamodel/calculation.py b/src/sas/qtgui/Perspectives/ParticleEditor/datamodel/calculation.py index c55ce7f1e1..60b29574e7 100644 --- a/src/sas/qtgui/Perspectives/ParticleEditor/datamodel/calculation.py +++ b/src/sas/qtgui/Perspectives/ParticleEditor/datamodel/calculation.py @@ -1,6 +1,5 @@ -from typing import Optional, Callable, Tuple, Protocol, List +from typing import Optional, Tuple, List import numpy as np -from enum import Enum from dataclasses import dataclass from abc import ABC, abstractmethod @@ -32,7 +31,12 @@ def __call__(self): class SpatialDistribution(ABC): - """ Base class for point generators """ + """ Base class for point generators + + Batches need to be usable for bootstrapping, the run needs to be split into + n_bootstrap sections, and the output saved for each section, so that it can + be rebuilt in different combinations to establish a variance. + """ def __init__(self, radius: float, n_points: int, n_desired_points): self.radius = radius @@ -40,7 +44,11 @@ def __init__(self, radius: float, n_points: int, n_desired_points): self.n_points = n_points @property - def info(self): + def allows_bootstrap(self) -> bool: + return False + + @property + def info(self) -> str: """ Information to be displayed in the settings window next to the point number input """ return "" @@ -56,6 +64,7 @@ def bounding_surface_check_points(self) -> VectorComponents3: pts = self._bounding_surface_check_points() return pts[:, 0], pts[:, 1], pts[:, 2] + class AngularDistribution(ABC): """ Base class for angular distributions """ @@ -126,6 +135,8 @@ class SamplingDistribution: class QSpaceScattering: abscissa: QSample ordinate: np.ndarray + upper_error: np.ndarray | None = None + lower_error: np.ndarray | None = None @dataclass class RealSpaceScattering: diff --git a/src/sas/qtgui/Perspectives/ParticleEditor/sampling/points.py b/src/sas/qtgui/Perspectives/ParticleEditor/sampling/points.py index b07f41eb35..2f438d95ef 100644 --- a/src/sas/qtgui/Perspectives/ParticleEditor/sampling/points.py +++ b/src/sas/qtgui/Perspectives/ParticleEditor/sampling/points.py @@ -2,6 +2,8 @@ Instances of the spatial sampler + + """ import math @@ -72,6 +74,9 @@ def __init__(self, radius: float, desired_points: int, seed=None): # Accessing this will generate random seeds if they don't exist and store them to be accessed if they do self.seeds = defaultdict(lambda: self._seed_rng.integers(0, 0x7fff_ffff_ffff_ffff)) + def allows_bootstrap(self) -> bool: + return True + def generate(self, start_index: int, end_index: int) -> VectorComponents3: # This method of tracking seeds only works if the same start_indices are used each time points # in a region are requested - i.e. if they're chunks form a grid @@ -90,9 +95,10 @@ def generate(self, start_index: int, end_index: int) -> VectorComponents3: class PointGeneratorStepper: - """ Generate batches of step_size points from a PointGenerator instance""" + """ Generate batches of step_size points from a PointGenerator instance + """ - def __init__(self, point_generator: SpatialDistribution, step_size: int): + def __init__(self, point_generator: SpatialDistribution, step_size: int, bootstrap_sections: int): self.point_generator = point_generator self.step_size = step_size diff --git a/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py b/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py index c271e506a6..bc8205db4d 100644 --- a/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py +++ b/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py @@ -1,7 +1,9 @@ from collections import defaultdict from PySide6 import QtWidgets +from PySide6.QtGui import QImage, QPixmap from PySide6.QtWidgets import QDialog, QWidget, QTextBrowser, QVBoxLayout, QHBoxLayout, QPushButton, QCheckBox +from PySide6.QtCore import QUrl from sas.system.version import __version__ as sasview_version import importlib.resources as resources @@ -11,8 +13,14 @@ from sas.qtgui.Utilities.WhatsNew.newer import strictly_newer_than, reduced_version, newest -def whats_new_messages(): - """ Accumulate all files that are newer than the value in the config""" + + +def whats_new_messages(strictly_newer=True): + """ Accumulate all files that are newer than the value in the config + + :param strictly_newer: require strictly newer stuff, strictness is needed for showing new things + when there is an update, non-strictness is needed for the menu access. + """ out = defaultdict(list) message_dir = resources.files("sas.qtgui.Utilities.WhatsNew.messages") @@ -23,7 +31,11 @@ def whats_new_messages(): newer = False try: - newer = strictly_newer_than(message_dir.name, config.LAST_WHATS_NEW_HIDDEN_VERSION) + if strictly_newer: + newer = strictly_newer_than(message_dir.name, config.LAST_WHATS_NEW_HIDDEN_VERSION) + else: + # Include current version + newer = not strictly_newer_than(config.LAST_WHATS_NEW_HIDDEN_VERSION, message_dir.name) except ValueError: pass @@ -36,6 +48,44 @@ def whats_new_messages(): return out +class WhatsNewBrowser(QTextBrowser): + def __init__(self, parent=None): + super().__init__(parent) + + css = resources.read_text("sas.qtgui.Utilities.WhatsNew.css", "style.css") + self.css_data = "" + + def setHtml(self, text: str) -> None: + """ Overriden to inject CSS into HTML files - very, very ugly""" + super().setHtml(text.replace("", self.css_data)) + + def loadResource(self, kind: int, url: QUrl | str): + + """ Override the resource discovery to get the images we need """ + + if isinstance(url, QUrl): + name = url.toString() + else: + name = url + + if kind == 2: + + # This is pretty nasty, there's probably a better way + if name.startswith("whatsnew/"): + parts = name.split("/")[1:] + + location = resources.files("sas.qtgui.Utilities.WhatsNew.messages") + + for part in parts: + location = location.joinpath(part) + + im = QPixmap(str(location)) + + return im + + return super().loadResource(kind, url) + + class WhatsNew(QDialog): """ What's New window: displays messages about what is new in this version of SasView @@ -46,12 +96,12 @@ class WhatsNew(QDialog): To add new messages, just dump a (self-contained) html file into the appropriate folder """ - def __init__(self, parent=None): + def __init__(self, parent=None, strictly_newer=True): super().__init__() self.setWindowTitle(f"What's New in SasView {sasview_version}") - self.browser = QTextBrowser() + self.browser = WhatsNewBrowser() self.browser.setOpenLinks(True) self.browser.setOpenExternalLinks(True) @@ -67,15 +117,23 @@ def __init__(self, parent=None): self.closeButton = QPushButton("Close") self.nextButton = QPushButton("Next") - self.showAgain = QCheckBox("Show on Startup") - self.showAgain.setChecked(True) + # Only show the show on startup checkbox if we're not up-to-date + self.buttonLayout.addWidget(self.closeButton) + + if strictly_newer_than(sasview_version, config.LAST_WHATS_NEW_HIDDEN_VERSION): + + self.showAgain = QCheckBox("Show on Startup") + self.showAgain.setChecked(True) + self.buttonLayout.addWidget(self.showAgain) - # add a horizontal spacer - self.buttonLayout.addWidget(self.showAgain) + else: + self.showAgain = None + + # other buttons self.buttonLayout.addSpacerItem(QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)) - self.buttonLayout.addWidget(self.closeButton) self.buttonLayout.addWidget(self.nextButton) + # Viewer self.setLayout(self.mainLayout) self.mainLayout.addWidget(self.browser) @@ -86,7 +144,7 @@ def __init__(self, parent=None): self.nextButton.clicked.connect(self.next_file) # # Gather new files - new_messages = whats_new_messages() + new_messages = whats_new_messages(strictly_newer=strictly_newer) new_message_directories = [key for key in new_messages.keys()] new_message_directories.sort(key=reduced_version) @@ -100,6 +158,7 @@ def __init__(self, parent=None): self.show_file() + self.setFixedSize(800, 600) self.setModal(True) def next_file(self): @@ -112,14 +171,15 @@ def show_file(self): filename = self.all_messages[self.current_index] with open(filename, 'r') as fid: data = fid.read() - self.browser.setText(data) + self.browser.setHtml(data) else: - self.browser.setText("

You should not see this!!!

") + self.browser.setHtml("

You should not see this!!!

") def close_me(self): - if not self.showAgain.isChecked(): - # We choose the newest, for backwards compatability, i.e. we never reduce the last version - config.LAST_WHATS_NEW_HIDDEN_VERSION = newest(sasview_version, config.LAST_WHATS_NEW_HIDDEN_VERSION) + if self.showAgain is not None: + if not self.showAgain.isChecked(): + # We choose the newest, for backwards compatability, i.e. we never reduce the last version + config.LAST_WHATS_NEW_HIDDEN_VERSION = newest(sasview_version, config.LAST_WHATS_NEW_HIDDEN_VERSION) self.close() @@ -129,25 +189,16 @@ def has_new_messages(self) -> bool: -def maybe_show_whats_new(): - global whats_new_window - """ Show the What's New dialogue if it is wanted """ - - if whats_new_messages(): - whats_new_window = WhatsNew() - whats_new_window.show() - def main(): """ Demo/testing window""" from sas.qtgui.convertUI import main - main() - app = QtWidgets.QApplication([]) - maybe_show_whats_new() + whats_new_window = WhatsNew() + whats_new_window.show() app.exec_() diff --git a/src/sas/qtgui/Utilities/WhatsNew/css/__init__.py b/src/sas/qtgui/Utilities/WhatsNew/css/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sas/qtgui/Utilities/WhatsNew/css/style.css b/src/sas/qtgui/Utilities/WhatsNew/css/style.css new file mode 100644 index 0000000000..7826e6ec65 --- /dev/null +++ b/src/sas/qtgui/Utilities/WhatsNew/css/style.css @@ -0,0 +1,4 @@ + body { + text-align: center; + font-size: 14pt; + } diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/5.0.6/1.html b/src/sas/qtgui/Utilities/WhatsNew/messages/5.0.6/1.html deleted file mode 100644 index 4eb04b0e81..0000000000 --- a/src/sas/qtgui/Utilities/WhatsNew/messages/5.0.6/1.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - -

- Version 5.0.6 -

-
-What's New in v5.0.6 - - \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/1.html b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/1.html index 83c62844f8..92805eb319 100644 --- a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/1.html +++ b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/1.html @@ -1,11 +1,19 @@ - + + +

- Some Handy Tips + What's New: Preferences

-Have you tried randomly pressing buttons? + +

SasView is now more configurable, and a preference dialog is available though the File menu.

+ +

+ +

There are settings for graphics, GPU utilisation and more!

+ \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/2.html b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/2.html index b9f937665f..e1c4067bc9 100644 --- a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/2.html +++ b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/2.html @@ -1,10 +1,27 @@ - + + + +

- Welcome to SasView - What's New + What's New: Correlation Function Analysis

-Lot's of things +

Correlation function analysis calculations have been made more robust and the interface has been greatly simplified, + with more visual feedback, including...

+ + +

Single Click Interface

+ +

+ +

Feedback on Parameter Extraction

+ +

+ + + + \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/3.html b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/3.html new file mode 100644 index 0000000000..3741776342 --- /dev/null +++ b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/3.html @@ -0,0 +1,20 @@ + + + + + + + +

+ What's New: General Scattering Calculator +

+ +

Calculating scattering curves from atomic level descriptions is much faster and supports + different structure factors. + +

+ +

You can now fit them to data too.

+ + + \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/4.html b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/4.html new file mode 100644 index 0000000000..d99398860a --- /dev/null +++ b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/4.html @@ -0,0 +1,17 @@ + + + + + + +

+ What's New: Plotting Enhancements +

+ +

Plot legends are now more configurable via the preferences window, allowing users to limit the size and number of displayed characters.

+

+ +

Plotting preferences now include legend sizing options, the ability to disable automatic ancillary plot display, and whether to show/hide the toolbar when new plots are created.

+ + + \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/5.html b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/5.html new file mode 100644 index 0000000000..c3c3e61f17 --- /dev/null +++ b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/5.html @@ -0,0 +1,29 @@ + + + + + + + +

+ What's New: Slicer Enhancements +

+ +

Slicing now includes a angular wedge option and + box slices can now be made anywhere on the image.

+

+ + + + + + + + + +
Draggable Box SlicerWedge Slicer
+ +

With so many new slicing options, we've rearranged the menu to make things easier!

+ + + \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/6.html b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/6.html new file mode 100644 index 0000000000..c2bf2e97a2 --- /dev/null +++ b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/6.html @@ -0,0 +1,176 @@ + + + + + + + +

New in Version 6.0.0

+

This is a major release with a number of new features, enhancements, and bug fixes as described below.

+

This version of SasView is built with Sasmodels v1.0.7, Sasdata v0.9.0, and bumps main.

+ +

What's Changed

+ +

New Features

+ + +

Feature Enhancements

+

Log Explorer Enhancements

+ +

Tool Enhancements

+ +

Plotting Enhancements

+ +

General GUI Enhancements

+ +

Fitting Enhancements

+ + +

Bug Fixes

+

General GUI Fixes

+ +

Plotting Fixes

+ +

Fitting and Other Perspective Fixes

+ +

Other Fixes

+ +

Documentation Changes

+ + +

Infrastructure Changes

+

Build System

+ +

Python Dependencies

+ +

Developer Enhancements

+ + +

New Contributors

+ +

Full Changelog: v5.0.6...v6.0.0-beta-1

+ + + \ No newline at end of file diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/__init__.py b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/box-slicer-center-point.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/box-slicer-center-point.png new file mode 100644 index 0000000000..05a69cef0b Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/box-slicer-center-point.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/corfunc-extraction.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/corfunc-extraction.png new file mode 100644 index 0000000000..0f5d45b3ea Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/corfunc-extraction.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/corfunc-interaction.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/corfunc-interaction.png new file mode 100644 index 0000000000..ed1ff987a3 Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/corfunc-interaction.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/plotting.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/plotting.png new file mode 100644 index 0000000000..a6e64b4c8e Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/plotting.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/preferences.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/preferences.png new file mode 100644 index 0000000000..7f867136f7 Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/preferences.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/rhodopsin.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/rhodopsin.png new file mode 100644 index 0000000000..17d6c9f463 Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/rhodopsin.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/wedge-slicer.png b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/wedge-slicer.png new file mode 100644 index 0000000000..abd55e8fa6 Binary files /dev/null and b/src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/wedge-slicer.png differ diff --git a/src/sas/qtgui/Utilities/WhatsNew/newer.py b/src/sas/qtgui/Utilities/WhatsNew/newer.py index 0adff7cd15..5963c30a8d 100644 --- a/src/sas/qtgui/Utilities/WhatsNew/newer.py +++ b/src/sas/qtgui/Utilities/WhatsNew/newer.py @@ -32,6 +32,7 @@ def strictly_newer_than(version_a: str, version_b: str) -> bool: return False + def newest(version_a: str, version_b: str) -> str: """Return the newest of two versions by the comparison used in the what's new box, if they are equally new, return the first one.