Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@ tests.log
/installers/dist
*.exe
installers/credits.html

# Local Cursor IDE config
.cursor/
3 changes: 2 additions & 1 deletion docs/sphinx-docs/source/user/menu_bar.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ The File option allows you load data into *SasView* for analysis, or to save the
Data can be loaded one file at a time, or by selecting multiple files, or by loading an entire folder of
files (in which case *SasView* will attempt to make an intelligent guess as to what to load based on the
file formats it recognises in the folder!). Data can also be loaded by dragging and dropping files directly
onto Data Explorer.
onto Data Explorer. Additionally, datasets can be downloaded directly from the SASBDB (Small Angle Scattering
Biological Data Bank) using **File > Load from SASBDB...** (see :ref:`SASBDB_Download` for details).

A *SasView* session can also be saved and reloaded as an 'Analysis' (an individual model fit or invariant
calculation, etc), or as a 'Project' (everything you have done since starting your *SasView* session).
Expand Down
2 changes: 2 additions & 0 deletions docs/sphinx-docs/source/user/tools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ Tools & Utilities

MuMag Tool <qtgui/Utilities/MuMag/mumag_help>

SASBDB Download <qtgui/Utilities/SASBDB/sasbdb_download_help>

18 changes: 18 additions & 0 deletions src/sas/qtgui/MainWindow/GuiManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
from sas.qtgui.Utilities.Preferences.PreferencesPanel import PreferencesPanel
from sas.qtgui.Utilities.Reports.ReportDialog import ReportDialog
from sas.qtgui.Utilities.ResultPanel import ResultPanel
from sas.qtgui.Utilities.SASBDB.sasbdb_loader import load_downloaded_dataset
from sas.qtgui.Utilities.SASBDB.SASBDBDownloadDialog import SASBDBDownloadDialog

# General SAS imports
from sas.qtgui.Utilities.SasviewLogger import setup_qt_logging
Expand Down Expand Up @@ -668,6 +670,7 @@ def addTriggers(self):
# File
self._workspace.actionLoadData.triggered.connect(self.actionLoadData)
self._workspace.actionLoad_Data_Folder.triggered.connect(self.actionLoad_Data_Folder)
self._workspace.actionLoad_SASBDB.triggered.connect(self.actionLoad_SASBDB)
self._workspace.actionOpen_Project.triggered.connect(self.actionOpen_Project)
self._workspace.actionOpen_Analysis.triggered.connect(self.actionOpen_Analysis)
self._workspace.actionSave.triggered.connect(self.actionSave_Project)
Expand Down Expand Up @@ -765,6 +768,21 @@ def actionLoad_Data_Folder(self):
"""
self.filesWidget.loadFolder()

def actionLoad_SASBDB(self):
"""
Menu File/Load from SASBDB

Opens a dialog to download and load a dataset from SASBDB.
"""
dialog = SASBDBDownloadDialog(parent=self._workspace)
if dialog.exec():
load_downloaded_dataset(
self.filesWidget,
self._workspace,
dialog.getDownloadedFilepath(),
dialog.getDatasetInfo(),
)

def actionOpen_Project(self):
"""
Menu Open Project
Expand Down
9 changes: 9 additions & 0 deletions src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
</property>
<addaction name="actionLoadData"/>
<addaction name="actionLoad_Data_Folder"/>
<addaction name="actionLoad_SASBDB"/>
<addaction name="separator"/>
<addaction name="actionOpen_Project"/>
<addaction name="actionOpen_Analysis"/>
Expand Down Expand Up @@ -310,6 +311,14 @@
<string>Load Data Folder</string>
</property>
</action>
<action name="actionLoad_SASBDB">
<property name="text">
<string>Load from SASBDB...</string>
</property>
<property name="toolTip">
<string>Download and load dataset from SASBDB</string>
</property>
</action>
<action name="actionOpen_Project">
<property name="text">
<string>Open Project</string>
Expand Down
7 changes: 5 additions & 2 deletions src/sas/qtgui/Utilities/GuiUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from sas.qtgui.Plotting.Plottables import Chisq, Plottable, PlottableFit1D, PlottableTheory1D, Text, View
from sas.qtgui.Plotting.PlotterData import Data1D, Data2D, DataRole
from sas.qtgui.Utilities.BackgroundColor import BG_DEFAULT, BG_WARNING
from sas.qtgui.Utilities.SASBDB.sasbdb_display import append_sasbdb_data_summary
from sas.sascalc.fit.AbstractFitEngine import FitData1D, FitData2D, FResult
from sas.system import HELP_SYSTEM
from sas.system.user import PATH_LIKE
Expand Down Expand Up @@ -549,7 +550,8 @@ def retrieveData1d(data):
#logger.error(msg)
raise ValueError(msg)

text = data.__str__()
text = append_sasbdb_data_summary(data.__str__(), data)

text += 'Data Min Max:\n'
text += 'X_min = %s: X_max = %s\n' % (xmin, max(data.x))
text += 'Y_min = %s: Y_max = %s\n' % (ymin, max(data.y))
Expand Down Expand Up @@ -593,7 +595,8 @@ def retrieveData2d(data):
msg = "Incorrect type passed to retrieveData2d"
raise AttributeError(msg)

text = data.__str__()
text = append_sasbdb_data_summary(data.__str__(), data)

text += 'Data Min Max:\n'
text += 'I_min = %s\n' % min(data.data)
text += 'I_max = %s\n\n' % max(data.data)
Expand Down
105 changes: 105 additions & 0 deletions src/sas/qtgui/Utilities/SASBDB/SASBDBDownloadDialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""
SASBDB Dataset Download Dialog.
"""

import logging
import os
import tempfile

from PySide6 import QtWidgets

from sas.qtgui.Utilities import GuiUtils
from sas.qtgui.Utilities.SASBDB.sasbdb_api import (
downloadDataset,
validateDatasetId,
)
from sas.qtgui.Utilities.SASBDB.sasbdb_display import metadata_summary
from sas.qtgui.Utilities.SASBDB.sasbdb_parse import SASBDBDatasetInfo
from sas.qtgui.Utilities.SASBDB.UI.SASBDBDownloadDialogUI import (
Ui_SASBDBDownloadDialogUI,
)

logger = logging.getLogger(__name__)


class SASBDBDownloadDialog(QtWidgets.QDialog, Ui_SASBDBDownloadDialogUI):
"""Dialog for downloading datasets from SASBDB."""

def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.downloaded_filepath: str | None = None
self.dataset_info: SASBDBDatasetInfo | None = None

self.cmdDownload.clicked.connect(self.onDownload)
self.cmdCancel.clicked.connect(self.reject)
self.cmdHelp.clicked.connect(self.onHelp)
self.txtDatasetId.returnPressed.connect(self.onDownload)
self.txtDatasetId.setFocus()

def onDownload(self):
dataset_id = self.txtDatasetId.text().strip()
if not dataset_id:
self._showError("Please enter a dataset identifier.")
return

normalized_id, validation_error = validateDatasetId(dataset_id)
if validation_error:
self._showError(validation_error)
return

self._set_busy(True)
self.lblStatus.setText("Downloading dataset...")

try:
filepath, dataset_info = downloadDataset(
normalized_id, tempfile.gettempdir()
)
self.dataset_info = dataset_info

if filepath and os.path.exists(filepath):
self.downloaded_filepath = filepath
summary = metadata_summary(dataset_info) if dataset_info else ""
status = f"Successfully downloaded dataset {normalized_id}"
if summary:
status += f"\n{summary}"
self.lblStatus.setText(status)
self.accept()
else:
self._showError(
f"Failed to download dataset {normalized_id}.\n"
"Please check the dataset identifier and try again."
)
except Exception as e:
logger.error(
"Error downloading dataset %s: %s",
normalized_id,
e,
exc_info=True,
)
self._showError(f"Error downloading dataset:\n{e}")
finally:
self._set_busy(False)

def _set_busy(self, busy: bool):
self.cmdDownload.setEnabled(not busy)
self.cmdCancel.setEnabled(not busy)
self.progressBar.setVisible(busy)
if busy:
self.progressBar.setRange(0, 0)
QtWidgets.QApplication.processEvents()

def _showError(self, message: str):
self.lblStatus.setText(f"<span style='color: red;'>{message}</span>")
QtWidgets.QMessageBox.warning(self, "Download Error", message)

def getDownloadedFilepath(self) -> str | None:
return self.downloaded_filepath

def getDatasetInfo(self) -> SASBDBDatasetInfo | None:
return self.dataset_info

def onHelp(self):
GuiUtils.showHelp(
"user/qtgui/Utilities/SASBDB/sasbdb_download_help.html"
)
123 changes: 123 additions & 0 deletions src/sas/qtgui/Utilities/SASBDB/UI/SASBDBDownloadDialogUI.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SASBDBDownloadDialogUI</class>
<widget class="QDialog" name="SASBDBDownloadDialogUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>450</width>
<height>200</height>
</rect>
</property>
<property name="windowTitle">
<string>Load from SASBDB</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblInstructions">
<property name="text">
<string>Enter SASBDB Dataset Identifier:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="txtDatasetId">
<property name="placeholderText">
<string>e.g., SASDN24</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblStatus">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cmdDownload">
<property name="text">
<string>Download and Load</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cmdHelp">
<property name="text">
<string>Help</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cmdCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>cmdCancel</sender>
<signal>clicked()</signal>
<receiver>SASBDBDownloadDialogUI</receiver>
<slot>reject()</slot>
</connection>
</connections>
</ui>

4 changes: 4 additions & 0 deletions src/sas/qtgui/Utilities/SASBDB/UI/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""
UI components for SASBDB utilities.
"""

Loading
Loading