Skip to content

Commit

Permalink
Merge pull request #2450 from SasView/2444-parameter-extraction-lines…
Browse files Browse the repository at this point in the history
…-on-corfunc

Improvements to Corfunc
  • Loading branch information
butlerpd authored Mar 14, 2023
2 parents ed77650 + 29cc82c commit 951b732
Show file tree
Hide file tree
Showing 10 changed files with 534 additions and 129 deletions.
65 changes: 56 additions & 9 deletions src/sas/qtgui/Perspectives/Corfunc/CorfuncPerspective.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from numpy.linalg.linalg import LinAlgError


from typing import Optional, List, Tuple
from typing import Optional, List, Tuple, Callable

import logging

Expand All @@ -22,20 +22,20 @@
from sas.qtgui.Perspectives.Corfunc.CorfunSlider import CorfuncSlider
from sas.qtgui.Perspectives.Corfunc.QSpaceCanvas import QSpaceCanvas
from sas.qtgui.Perspectives.Corfunc.RealSpaceCanvas import RealSpaceCanvas
from sas.qtgui.Perspectives.Corfunc.ExtractionCanvas import ExtractionCanvas
from sas.qtgui.Perspectives.Corfunc.IDFCanvas import IDFCanvas
from sas.sascalc.corfunc.extrapolation_data import ExtrapolationParameters, ExtrapolationInteractionState

import sas.qtgui.Utilities.GuiUtils as GuiUtils
from sas.qtgui.Utilities.Reports.reportdata import ReportData
from sas.qtgui.Utilities.Reports import ReportBase
from sas.qtgui.Plotting.PlotterData import Data1D

from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator
# pylint: enable=import-error, no-name-in-module
from sas.sascalc.corfunc.extrapolation_data import ExtrapolationParameters, ExtrapolationInteractionState
from sas.sascalc.corfunc.calculation_data import TransformedData, TangentMethod, LongPeriodMethod

# local
from .UI.CorfuncPanel import Ui_CorfuncDialog
from .util import WIDGETS, safe_float, TransformedData
from .util import WIDGETS, safe_float
from .SaveExtrapolatedPopup import SaveExtrapolatedPopup
from ..perspective import Perspective

Expand Down Expand Up @@ -75,6 +75,8 @@ def __init__(self, parent=None):
self.txtLowerQMin.setText("0.0")
self.txtLowerQMin.setEnabled(False)
self.extrapolation_curve = None
self.long_period_method: Optional[LongPeriodMethod] = None
self.tangent_method: Optional[TangentMethod] = None

# Add slider widget
self.slider = CorfuncSlider()
Expand All @@ -89,6 +91,10 @@ def __init__(self, parent=None):
self.realSpaceLayout.insertWidget(0, self._real_space_plot)
self.realSpaceLayout.insertWidget(1, NavigationToolbar2QT(self._real_space_plot, self))

self._extraction_plot = ExtractionCanvas(self)
self.diagramLayout.insertWidget(0, self._extraction_plot)
self.diagramLayout.insertWidget(1, NavigationToolbar2QT(self._extraction_plot, self))

self._idf_plot = IDFCanvas(self)
self.idfLayout.insertWidget(0, self._idf_plot)
self.idfLayout.insertWidget(1, NavigationToolbar2QT(self._idf_plot, self))
Expand Down Expand Up @@ -150,6 +156,16 @@ def setup_slots(self):
self.txtUpperQMax.textEdited.connect(self.on_extrapolation_text_changed_3)
self.set_text_enable(False)

# Calculation Options
self.radTangentAuto.clicked.connect(self.set_tangent_method(None))
self.radTangentInflection.clicked.connect(self.set_tangent_method(TangentMethod.INFLECTION))
self.radTangentMidpoint.clicked.connect(self.set_tangent_method(TangentMethod.HALF_MIN))

self.radLongPeriodAuto.clicked.connect(self.set_long_period_method(None))
self.radLongPeriodMax.clicked.connect(self.set_long_period_method(LongPeriodMethod.MAX))
self.radLongPeriodDouble.clicked.connect(self.set_long_period_method(LongPeriodMethod.DOUBLE_MIN))

# Slider values
self.slider.valueEdited.connect(self.on_extrapolation_slider_changed)
self.slider.valueEditing.connect(self.on_extrapolation_slider_changing)

Expand All @@ -161,6 +177,20 @@ def set_text_enable(self, state: bool):
self.txtUpperQMin.setEnabled(state)
self.txtUpperQMax.setEnabled(state)

def set_long_period_method(self, value: Optional[LongPeriodMethod]) -> Callable[[bool], None]:
""" Function to set the long period method"""
def setter_function(state: bool):
self.long_period_method = value

return setter_function

def set_tangent_method(self, value: Optional[TangentMethod]) -> Callable[[bool], None]:
""" Function to set the tangent method"""
def setter_function(state: bool):
self.tangent_method = value

return setter_function

def setup_model(self):
"""Populate the model with default data."""
# filename
Expand Down Expand Up @@ -274,14 +304,21 @@ def transform(self):

extrap = self.extrap
background = float(self.model.item(WIDGETS.W_BACKGROUND).text())
q_range = self.data.x[0], self.data.x[-1]

def updatefn(msg):
"""Report progress of transformation."""
self.communicate.statusBarUpdateSignal.emit(msg)

def completefn(transformed_data: Tuple[Data1D, Data1D, Data1D]):
def completefn(transform_result: Tuple[Data1D, Data1D, Data1D]):
"""Extract the values from the transforms and plot"""
self.trigger.emit(TransformedData(*transformed_data)) # TODO: Make this return more structured data earlier
td = TransformedData(
gamma_1=transform_result[0],
gamma_3=transform_result[1],
idf=transform_result[2],
q_range=q_range)

self.trigger.emit(td) # TODO: Make this return more structured data earlier

self._update_calculator()
self._calculator.compute_transform(extrap, method, background,
Expand All @@ -295,6 +332,7 @@ def finish_transform(self, data: TransformedData):
self.transformed_data = data

self._real_space_plot.data = data.gamma_1, data.gamma_3
self._extraction_plot.data = data.gamma_1

# self.update_real_space_plot(transforms)

Expand All @@ -310,9 +348,16 @@ def extract(self):
if self.transformed_data is None:
return

params = self._calculator.extract_parameters(self.transformed_data[0])
extracted = self._calculator.extract_parameters(
transformed_data=self.transformed_data,
long_period_method=self.long_period_method,
tangent_method=self.tangent_method)

if params is not None:
if extracted is not None:

params, supp = extracted

self._extraction_plot.supplementary = supp

self.model.itemChanged.disconnect(self.model_changed)

Expand All @@ -328,6 +373,8 @@ def extract(self):
self.model.itemChanged.connect(self.model_changed)
self.model_changed(None)

self.tabWidget.setCurrentIndex(2)


def setup_mapper(self):
"""Creating mapping between model and gui elements."""
Expand Down
90 changes: 90 additions & 0 deletions src/sas/qtgui/Perspectives/Corfunc/ExtractionCanvas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from typing import Optional
from sas.sascalc.corfunc.corfunc_calculator import SupplementaryParameters

from sas.qtgui.Perspectives.Corfunc.CorfuncCanvas import CorfuncCanvas


class ExtractionCanvas(CorfuncCanvas):
""" Canvas for displaying real space representation"""

def __init__(self, parent, width=5, height=4, dpi=100):
super().__init__(parent, width, height, dpi)
self._supplementary: Optional[SupplementaryParameters] = None

@property
def supplementary(self):
return self._supplementary

@supplementary.setter
def supplementary(self, supplementary_data: SupplementaryParameters):
self._supplementary = supplementary_data

self.draw_data() # Is this needed?

def draw_data(self):
"""
This function draws the real space data onto the plot
The 1d correlation function in self.data, the 3d correlation function
in self.data3, and the interface distribution function in self.data_idf
are all draw in on the plot in linear cooredinates."""

self.fig.clf()

self.axes = self.fig.add_subplot(111)
self.axes.set_xscale("linear")
self.axes.set_yscale("linear")
self.axes.set_xlabel("Z [$\AA$]")
self.axes.set_ylabel("Correlation")
self.axes.set_title("Real Space Correlations")
self.fig.tight_layout()

if self.data is not None:
data = self.data[0]
self.axes.plot(data.x, data.y)

if self.supplementary is not None:
self.axes.axline(
(self.supplementary.tangent_point_z,
self.supplementary.tangent_point_gamma),
slope=self.supplementary.tangent_gradient,
color='k',
linestyle='--',
# transform=self.axes.transAxes,
)

# Interface properties
self.axes.axvline(x=self.supplementary.interface_z, color='k', linestyle=':')
self.axes.axvline(x=self.supplementary.core_z, color='k', linestyle=':')

# Hard block estimation line
self.axes.axhline(y=self.supplementary.hard_block_gamma, color='k', linestyle='--')

x_points = [
self.supplementary.tangent_point_z,
self.supplementary.first_minimum_z,
self.supplementary.first_maximum_z,
self.supplementary.hard_block_z]

y_points = [
self.supplementary.tangent_point_gamma,
self.supplementary.first_minimum_gamma,
self.supplementary.first_maximum_gamma,
self.supplementary.hard_block_gamma]

self.axes.scatter(
x_points,
y_points,
color='k')

y_size = max(data.y) - min(data.y)

self.axes.set_xlim(0, 1.1*max(x_points))
self.axes.set_ylim(min(y_points) - 0.1*y_size, max(data.y) + 0.1*y_size)

else:
self.axes.set_xlim(0, max(data.x) / 4)


self.draw()

8 changes: 8 additions & 0 deletions src/sas/qtgui/Perspectives/Corfunc/RealSpaceCanvas.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
from typing import Optional
from sas.sascalc.corfunc.corfunc_calculator import SupplementaryParameters

from sas.qtgui.Perspectives.Corfunc.CorfuncCanvas import CorfuncCanvas


class RealSpaceCanvas(CorfuncCanvas):
""" Canvas for displaying real space representation"""

def __init__(self, parent, width=5, height=4, dpi=100):
super().__init__(parent, width, height, dpi)
self._supplementary: Optional[SupplementaryParameters] = None


def draw_data(self):
"""
This function draws the real space data onto the plot
Expand All @@ -27,6 +34,7 @@ def draw_data(self):
data1, data3 = self.data[0], self.data[1]
self.axes.plot(data1.x, data1.y, label="1D Correlation")
self.axes.plot(data3.x, data3.y, label="3D Correlation")

self.axes.set_xlim(0, max(data1.x) / 4)
self.legend = self.axes.legend()

Expand Down
Loading

0 comments on commit 951b732

Please sign in to comment.