Skip to content

Commit

Permalink
Updated documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jorge-ramirez-upm committed Dec 17, 2023
1 parent 29d5049 commit c647001
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 90 deletions.
17 changes: 15 additions & 2 deletions RepTate/gui/QApplicationManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,22 @@ def emit(self, record):
self.widget.moveCursor(QTextCursor.End)


# class QApplicationManager(ApplicationManager, QMainWindow, Ui_MainWindow):
class QApplicationManager(QMainWindow, Ui_MainWindow):
"""Main Reptate window and application manager"""
"""Main Reptate window and application manager. It contains the main toolbar from which the user can open the different applications.
.. note:: This class inherits from PySide6 QMainWindow and Ui_MainWindow, which is the class generated by QtDesigner.
.. graphviz::
digraph G {
"QApplicationWindow" [href="../developers/CodeCoreGUI.html#qapplicationwindow", target="_top", shape="box", style="rounded,filled"]
"QApplicationManager" [href="../developers/CodeCoreGUI.html#qapplicationmanager", target="_top", shape="box", style="rounded,filled"]
"QMainWindow" [shape=box,fillcolor=palegreen,href="https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QMainWindow.html", target="_top", style="filled"]
"QMainWindow" -> "QApplicationManager" [color=green];
"QApplicationManager" -> "QApplicationWindow" [color=red];
}
"""

html_help_file = "http://reptate.readthedocs.io/index.html"
# COPIED FROM APPLICATIONMANAGER
Expand Down
20 changes: 18 additions & 2 deletions RepTate/gui/QApplicationWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import sys
import os
import io
import math
import re
import traceback
from numpy import *
Expand Down Expand Up @@ -353,7 +354,21 @@ def __init__(self, parent=None, fnames=None, factorsx=None, factorsy=None):

# class QApplicationWindow(Application, QMainWindow, Ui_AppWindow):
class QApplicationWindow(QMainWindow, Ui_AppWindow):
"""Main abstract class that represents a GUI Application"""
"""Main abstract class that represents a RepTate Application.
.. note:: This class is not meant to be used directly. It is the base class for all RepTate GUI applications. This class inherits from PySide6 QMainWindow and Ui_MainWindow, which is the class generated by QtDesigner.
.. graphviz::
digraph G {
"QApplicationWindow" [href="../developers/CodeCoreGUI.html#qapplicationwindow", target="_top", shape="box", style="rounded,filled"]
"QApplicationManager" [href="../developers/CodeCoreGUI.html#qapplicationmanager", target="_top", shape="box", style="rounded,filled"]
"QMainWindow" [shape=box,fillcolor=palegreen,href="https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QMainWindow.html", target="_top", style="filled"]
"QMainWindow" -> "QApplicationWindow" [color=green];
"QApplicationManager" -> "QApplicationWindow" [color=red];
}
"""

def __init__(
self, name="Application Template", parent=None, nplot_max=4, ncols=2, **kwargs
Expand Down Expand Up @@ -1857,12 +1872,13 @@ def clipboard_coordinates(self, artist):

def new(self, line):
"""Create new empty dataset in the application"""
# TODO: Can this be removed?
self.num_datasets += 1
if line == "":
dsname = "Set%d" % self.num_datasets
else:
dsname = line
ds = DataSet(dsname, self)
ds = QDataSet(dsname, self)
return ds, dsname

def delete(self, ds_name):
Expand Down
5 changes: 2 additions & 3 deletions RepTate/theories/TheoryShanbhagMaxwellModes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2036,9 +2036,8 @@ def getH(self, lam, Gexp, H, kernMat, *argv):
return res_lsq.x

def residualLM(self, H, lam, Gexp, kernMat):
"""
%
% HELPER FUNCTION: Gets Residuals r
"""HELPER FUNCTION: Gets Residuals r
Input: H = guessed H,
lambda = regularization parameter ,
Gexp = experimental data,
Expand Down
59 changes: 21 additions & 38 deletions RepTate/theories/TheoryStickyReptation.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,49 +125,32 @@ def g_descloizeaux(self, x, tol):
return gx

def calculate(self, f=None):
"""
"""STICKY-REPTATION MODEL FOR LINEAR VISCOELASTICITY
* **PARAMETERS:**
- Ge: elastic modulus
- tau_s: sticker dissociation time
- Zs: number of stickers per chain
- Ze: number of entanglements per chain
- alpha: magnitude of the contour-length fluctuations in the double-reptation model. This is principle a universal dimensionless number with a value around ~10.
* **IMPORTANT:**
STICKY-REPTATION MODEL FOR LINEAR VISCOELASTICITY
- I. This sticky-reptation model assumes high Rouse frequencies not to affect the rheology at times of the order of the sticker time, due to which the rheology is independent of both the elementary (non-sticky) Rouse time, tau0, and the degree of polymerisation, N. See below.
PARAMETERS:
> Ge - elastic modulus
> tau_s - sticker dissociation time
> Zs - number of stickers per chain
> Ze - number of entanglements per chain
> alpha - magnitude of the contour-length fluctuations in the
double-reptation model. This is principle a universal
dimensionless number with a value around ~10.
IMPORTANT:
I. This sticky-reptation model assumes high Rouse frequencies
not to affect the rheology at times of the order of the
sticker time, due to which the rheology is independent
of both the elementary (non-sticky) Rouse time, tau0,
and the degree of polymerisation, N. See below.
II. The results may be affected by numerical approximations,
see below.
- II. The results may be affected by numerical approximations, see below.
I. MODEL APPROXIMATION:
1: The reptation time and Rouse relaxation after sticker
dissociation are approximate. After sticker dissociation
a strand of length N/Zs relaxes (a factor of two, to
represent a strand of twice that length relaxes) is
ignored. The reptation time is taken tau_rep=tau_s Zs^2*Ze,
with the prefactor 3 ignored.
2. The model assumes that the sticker dissociation time tau_s
is much larger than tau0*(N/Zs)^2. The shape of the sticker
plateau in G' and G'' is therefore not affected by the
early-time Rouse relaxation, and is independent of tau0 and
N: Including the high frequencies requires tau0 and N as
additional parameters.
* **I. MODEL APPROXIMATION:**
II. NUMERICAL SETTINGS:
Some numerical
1. The infinite sums in the double-reptation model are
truncated using a numerical tolerance level.
2. To transform G(t) to G'(w) and G''(w) a time range with
a finite number of samples is defined. The time range
and number of samples may affect the results."""
- 1: The reptation time and Rouse relaxation after sticker dissociation are approximate. After sticker dissociation a strand of length N/Zs relaxes (a factor of two, to represent a strand of twice that length relaxes) is ignored. The reptation time is taken tau_rep=tau_s Zs^2*Ze, with the prefactor 3 ignored.
- 2. The model assumes that the sticker dissociation time tau_s is much larger than tau0*(N/Zs)^2. The shape of the sticker plateau in G' and G'' is therefore not affected by the early-time Rouse relaxation, and is independent of tau0 and N: Including the high frequencies requires tau0 and N as additional parameters.
* **II. NUMERICAL SETTINGS:**
- 1. The infinite sums in the double-reptation model are truncated using a numerical tolerance level.
- 2. To transform G(t) to G'(w) and G''(w) a time range with a finite number of samples is defined. The time range and number of samples may affect the results.
"""
# ---------------------------------------------
# FUNCTION INPUT
ft = f.data_table
Expand Down
98 changes: 55 additions & 43 deletions RepTate/tools/ToolMaterialsDatabase.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@
QGroupBox,
QFormLayout,
QInputDialog,
QTreeWidgetItemIterator
QTreeWidgetItemIterator,
)
from PySide6.QtCore import QSize, QStandardPaths
from PySide6.QtGui import QStandardItem, QFont, QIcon, QAction, QColor, QDoubleValidator
from pathlib import Path
import RepTate.tools.polymer_data as polymer_data

if getattr(sys, 'frozen', False):
if getattr(sys, "frozen", False):
# If the application is run as a bundle, the PyInstaller bootloader
# extends the sys module by a flag frozen=True and sets the app
# extends the sys module by a flag frozen=True and sets the app
# path into variable _MEIPASS'.
PATH = sys._MEIPASS
else:
Expand All @@ -78,7 +78,9 @@
home_path = str(Path.home())
file_user_database_old = os.path.join(home_path, "user_database.npy")
if os.path.exists(file_user_database_old):
materials_user_database_old = np.load(file_user_database_old, allow_pickle=True).item()
materials_user_database_old = np.load(
file_user_database_old, allow_pickle=True
).item()
else:
materials_user_database_old = {}

Expand Down Expand Up @@ -139,12 +141,12 @@ def createFormGroupBox(self, material, parameterdata):


def check_chemistry(chem):
"""Check if the file contains chemistry. If so, check if the chemistry appears in
the user or general materials database.
Arguments:
- chem {str} -- Chemistry
Returns:
- code {integer} -- -1 (not found) 0 (found in user's) 1 (found in general database)
"""Check if the file contains chemistry. If so, check if the chemistry appears in the user or general materials database.
:param chem: Chemistry
:type chem: str
:return: code -1 (not found) 0 (found in user's) 1 (found in general database)
:rtype: int
"""
if chem in materials_user_database.keys():
return 0
Expand Down Expand Up @@ -325,12 +327,12 @@ def __init__(self, name="", parent_app=None):

# Search for the chemistry in the first file of the first dataset (OR CURRENT DATASET?)
self.init_chem = None
if len(parent_app.datasets)>0:
if len(parent_app.datasets) > 0:
ds = parent_app.datasets[list(parent_app.datasets)[0]]
if len(ds.files)>0:
if len(ds.files) > 0:
f = ds.files[0]
if 'chem' in f.file_parameters:
self.init_chem=f.file_parameters['chem']
if "chem" in f.file_parameters:
self.init_chem = f.file_parameters["chem"]

self.update_parameter_table()
# self.parent_application.update_all_ds_plots()
Expand Down Expand Up @@ -436,15 +438,15 @@ def __init__(self, name="", parent_app=None):
self.isofrictional.setChecked(True)
self.shiftdata = self.tbMwT.addAction(
QIcon(":/Icon8/Images/new_icons/icons8-vertical-shift-data.png"),
"Shift all Files in the current Application"
"Shift all Files in the current Application",
)
self.verticalLayout.insertWidget(2, self.tbMwT)
connection_id = self.isofrictional.triggered.connect(self.handle_vert_and_iso)
connection_id = self.verticalshift.triggered.connect(self.handle_vert_and_iso)
connection_id = self.shiftdata.triggered.connect(self.handle_shift_data)

init_chem_index = self.cbmaterial.findText(self.init_chem)
if init_chem_index>-1:
if init_chem_index > -1:
self.cbmaterial.setCurrentIndex(init_chem_index)
self.change_material()

Expand All @@ -454,7 +456,7 @@ def handle_vert_and_iso(self):
def handle_shift_data(self):
Tr = float(self.editT.text())
chem = self.cbmaterial.currentText()
msg = "Selected T=%g\nSelected material=%s\n"%(Tr, chem)
msg = "Selected T=%g\nSelected material=%s\n" % (Tr, chem)
msg += "Do you want to shift all Tables in the current Dataset "
msg += "to the chosen temperature using the WLF parameters for the chosen material?"
ans = QMessageBox.question(
Expand All @@ -465,8 +467,8 @@ def handle_shift_data(self):
)
if ans != QMessageBox.Yes:
return
# Calculate shift factors

# Calculate shift factors

B1 = self.parameters["B1"].value
B2 = self.parameters["B2"].value
Expand All @@ -487,11 +489,11 @@ def handle_shift_data(self):
Tf = f.file_parameters["T"]
Mw = f.file_parameters["Mw"]
if "iso" in f.file_parameters:
iso_file = (f.file_parameters["iso"].upper() == "TRUE")
iso_file = f.file_parameters["iso"].upper() == "TRUE"
elif "isof" in f.file_parameters:
iso_file = (f.file_parameters["isof"].upper() == "TRUE")
iso_file = f.file_parameters["isof"].upper() == "TRUE"
else:
iso_file=False
iso_file = False

if iso and not iso_file:
B2corrected = B2 + CTg / Mw # - 68.7 * dx12
Expand All @@ -500,35 +502,46 @@ def handle_shift_data(self):
B2corrected = B2
Trcorrected = Tr

aT = np.power(10.0, -B1 * (Tf - Trcorrected) / (B2corrected + Trcorrected) / (B2corrected + Tf))
aT = np.power(
10.0,
-B1
* (Tf - Trcorrected)
/ (B2corrected + Trcorrected)
/ (B2corrected + Tf),
)
if vert:
bT = (1 + alpha * Tf) * (Tr + 273.15) / (1 + alpha * Tr) / (Tf + 273.15)
else:
bT = 1

# Loop over file type columns
for i, c in enumerate(f.file_type.col_names):
if c in ["t", "time"]: # Shift horizontally to the left
f.data_table.data[:, i] = f.data_table.data[:, i]/aT
elif c in ["w"]: # Shift horizontally to the right
f.data_table.data[:, i] = f.data_table.data[:, i]*aT
elif c in ["G'", "G''", "Gt", "sigma_xy", "N1", "sigma"]: # Shift vertically up
f.data_table.data[:, i] = f.data_table.data[:, i]*bT

if c in ["t", "time"]: # Shift horizontally to the left
f.data_table.data[:, i] = f.data_table.data[:, i] / aT
elif c in ["w"]: # Shift horizontally to the right
f.data_table.data[:, i] = f.data_table.data[:, i] * aT
elif c in [
"G'",
"G''",
"Gt",
"sigma_xy",
"N1",
"sigma",
]: # Shift vertically up
f.data_table.data[:, i] = f.data_table.data[:, i] * bT

# Change file parameter T to target Temperature
f.file_parameters["T"] = Tr

it = QTreeWidgetItemIterator(ds.DataSettreeWidget)
while it.value():
if (it.value().text(0)==f.file_name_short):
if it.value().text(0) == f.file_name_short:
for i in range(ds.DataSettreeWidget.columnCount()):
if "T" == ds.DataSettreeWidget.headerItem().text(i):
it.value().setText(i, str(f.file_parameters["T"]))
it+=1;
it += 1

self.do_plot()



def change_material(self):
selected_material_name = self.cbmaterial.currentText()
Expand Down Expand Up @@ -624,7 +637,7 @@ def save_usermaterials(self):
file_user_database = os.path.join(AppData_path, "user_database.npy")
np.save(file_user_database, materials_user_database)
msg = "Saved user database in '%s'" % file_user_database
QMessageBox.information(self, 'Saved', msg)
QMessageBox.information(self, "Saved", msg)

def copy_material(self):
# Dialog to ask for short name. Repeat until the name is not in the user's database or CANCEL
Expand Down Expand Up @@ -753,24 +766,23 @@ def calculate_stuff(self, line="", file_parameters=[]):
CC3 = -1.55
Z = Mw / Me
tR = tau_e * Z * Z
tD = 3 * tau_e * Z ** 3 * (1 - 2 * CC1 / np.sqrt(Z) + CC2 / Z + CC3 / Z ** 1.5)
tD = 3 * tau_e * Z**3 * (1 - 2 * CC1 / np.sqrt(Z) + CC2 / Z + CC3 / Z**1.5)
tab_data.append(["<b>Z</b>", "%g" % Z])
tab_data.append(["<b>tau_R</b>", "%g" % tR])
tab_data.append(["<b>tau_D</b>", "%g" % tD])
self.Qprint(tab_data)


def calculate(self, x, y, ax=None, color=None, file_parameters=[]):
"""Calculate some results related to the selected material or the file material"""
self.calculate_stuff("", file_parameters)
return x, y

def do_calculate_stuff(self, line=""):
"""Given the values of Mw (in kDa) and T (in °C), as well as a flag for isofrictional state and vertical shift, it returns some calculations for the current chemistry.
Example:
calculate_stuff 35.4 240 1 1
Example:
calculate_stuff 35.4 240 1 1
Mw=35.4 T=240 isofrictional=True verticalshift=True"""
Mw=35.4 T=240 isofrictional=True verticalshift=True"""
items = line.split()
if len(items) == 4:
Mw = float(items[0])
Expand Down Expand Up @@ -823,8 +835,8 @@ def do_calculate_stuff(self, line=""):
tD = (
3
* tau_e
* Z ** 3
* (1 - 2 * CC1 / np.sqrt(Z) + CC2 / Z + CC3 / Z ** 1.5)
* Z**3
* (1 - 2 * CC1 / np.sqrt(Z) + CC2 / Z + CC3 / Z**1.5)
)
self.Qprint("<b>Z</b> = %g" % Z)
self.Qprint("<b>tau_R</b> = %g" % tR)
Expand All @@ -834,7 +846,7 @@ def do_calculate_stuff(self, line=""):
print(" Usage: calculate_stuff Mw T isofrictional verticalshift")

def calculate_all(self, n, x, y, ax=None, color=None, file_parameters=[]):
"""Calculate the tool for all views - In MatDB, only first view is needed """
"""Calculate the tool for all views - In MatDB, only first view is needed"""
newxy = []
lenx = 1e9
for i in range(n):
Expand Down
Loading

0 comments on commit c647001

Please sign in to comment.