Source code for RepTate.tools.ToolMaterialsDatabase

# RepTate: Rheology of Entangled Polymers: Toolkit for the Analysis of Tool and Experiments
# --------------------------------------------------------------------------------------------------------
#
# Authors:
#     Jorge Ramirez, jorge.ramirez@upm.es
#     Victor Boudara, victor.boudara@gmail.com
#
# Useful links:
#     http://blogs.upm.es/compsoftmatter/software/reptate/
#     https://github.com/jorge-ramirez-upm/RepTate
#     http://reptate.readthedocs.io
#
# --------------------------------------------------------------------------------------------------------
#
# Copyright (2018-2023): Jorge Ramirez, Victor Boudara, Universidad Politécnica de Madrid, University of Leeds
#
# This file is part of RepTate.
#
# RepTate is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RepTate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RepTate.  If not, see <http://www.gnu.org/licenses/>.
#
# --------------------------------------------------------------------------------------------------------
"""Module ToolMaterialsDatabase

MaterialsDatabase Viewer
"""
import sys
import os
import numpy as np
from RepTate.core.Parameter import Parameter, ParameterType
from RepTate.gui.QTool import QTool
from PySide6.QtWidgets import (
    QComboBox,
    QLabel,
    QToolBar,
    QLineEdit,
    QMessageBox,
    QDialog,
    QDialogButtonBox,
    QVBoxLayout,
    QGroupBox,
    QFormLayout,
    QInputDialog,
    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 the application is run as a bundle, the PyInstaller bootloader
    # extends the sys module by a flag frozen=True and sets the app
    # path into variable _MEIPASS'.
    PATH = sys._MEIPASS
else:
    PATH = os.path.dirname(os.path.abspath(__file__))

# The following two lines are temporary. They can be removed after the database is pickeld with RepTate.ttols.polymer_data instead of polymer_data
# sys.path.append(os.path.dirname(os.path.realpath(__file__)))
# dir_path = os.path.dirname(os.path.realpath(__file__))
sys.path.append(PATH)
materials_database = np.load(
    os.path.join(PATH, "materials_database.npy"), allow_pickle=True
).item()

# search user material database in the (old) location "HOME"
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()
else:
    materials_user_database_old = {}

# search user material database in the (new) location "AppData"
AppData_path = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
file_user_database = os.path.join(AppData_path, "user_database.npy")
if os.path.exists(file_user_database):
    materials_user_database = np.load(file_user_database, allow_pickle=True).item()
else:
    materials_user_database = {}

materials_user_database.update(materials_user_database_old)
materials_db = [materials_user_database, materials_database]


[docs] class EditMaterialParametersDialog(QDialog): """Create the form that is used to edit/modify the material parameters""" def __init__(self, parent, material, parameterdata): super().__init__(parent) self.parent_dataset = parent self.material = material self.createFormGroupBox(material, parameterdata) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(self.formGroupBox) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("Edit Material Parameters")
[docs] def createFormGroupBox(self, material, parameterdata): """Create a form to set the new values of the material parameters""" self.formGroupBox = QGroupBox( 'Parameters of material "%s"' % material.data["name"] ) layout = QFormLayout() parameters = material.data self.param_dict = {} self.p_new = [] for i, pname in enumerate(material.data.keys()): self.p_new.append(QLineEdit()) if isinstance(material.data[pname], str): # the parameter is a string self.p_new[i].setText("%s" % material.data[pname]) else: # parameter is a number: self.p_new[i].setValidator(QDoubleValidator()) # prevent letters self.p_new[i].setText("%.4g" % material.data[pname]) self.p_new[i].setToolTip(parameterdata[pname].description) if pname == "name": self.p_new[i].setReadOnly(True) layout.addRow("%s:" % pname, self.p_new[i]) self.param_dict[pname] = self.p_new[i] self.formGroupBox.setLayout(layout)
[docs] def check_chemistry(chem): """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 elif chem in materials_database.keys(): return 1 else: return -1
[docs] def get_all_parameters(chem, theory, fparam, dbindex): """Gets all possible parameters from the corresponding materials database. The function check_chemistry must be involed before this one, to get chem and dbindex. Arguments: - chem {str} -- Chemistry - theory {Theory} -- A given theory - file_parameters {dict} -- Parameters of the file - dbindex {int} -- Index of the database to use (0 user, 1 general) Returns: - nothing """ for p in theory.parameters.keys(): if p in materials_db[dbindex][chem].data.keys(): value, success = get_single_parameter(chem, p, fparam, dbindex) if success: theory.set_param_value(p, value)
[docs] def get_single_parameter(chem, param, fparam, dbindex): """Returns the parameter 'param' of the chemistry 'chem' using the database given by dbindex (0 user, 1 general) and taking into account the parameters of fparam (for example, T and Mw). The parameter 'param' must exist in the database. This is done when this function is invoked from get_all_parameters. If this function is invoked directly, the condition must be chedked beforehand. Arguments: - chem {str} -- Chemistry - param -- The theory parameter that we want to set - file_parameters {dict} -- Parameters of the file - dbindex {int} -- Index of the database to use (0 user, 1 general) Returns: - value -- The value of the parameter - success {bool} -- A success flag """ if param == "tau_e": try: T = float(fparam["T"]) except: # T was not found in the file parameters return 0, False tau_e = materials_db[dbindex][chem].data["tau_e"] B1 = materials_db[dbindex][chem].data["B1"] B2 = materials_db[dbindex][chem].data["B2"] Te = materials_db[dbindex][chem].data["Te"] aT = np.power(10.0, -B1 * (Te - T) / (B2 + T) / (B2 + Te)) tau_e /= aT # We don´t consider the effect of Tg in this estimate return tau_e, True elif param == "Ge": try: T = float(fparam["T"]) except: # T was not found in the file parameters return 0, False logalpha = materials_db[dbindex][chem].data["logalpha"] Ge = materials_db[dbindex][chem].data["Ge"] Te = materials_db[dbindex][chem].data["Te"] alpha = np.power(10.0, logalpha) bT = (1 + alpha * Te) * (T + 273.15) / (1 + alpha * T) / (Te + 273.15) Ge /= bT return Ge, True elif param == "rho0": try: T = float(fparam["T"]) except: # T was not found in the file parameters return 0, False rho0 = materials_db[dbindex][chem].data["rho0"] logalpha = materials_db[dbindex][chem].data["logalpha"] alpha = np.power(10.0, logalpha) rho = rho0 / (1.0 + alpha * T) return rho, True else: value = materials_db[dbindex][chem].data[param] return value, True
[docs] class ToolMaterialsDatabase(QTool): """A special Tool to store the material parameters. Many apps and theories rely on the parameters stored in this database. There are two copies of the database: i) a general one that is distributed with RepTate, is stored in the software installation folder and contains well established values of the parameters and ii) a user database that contains material parameters introduced by the user and is stored in the user HOME folder. """ toolname = "Materials Database" description = "Materials Database Explorer" citations = [] # html_help_file = 'http://reptate.readthedocs.io/manual/Tools/MaterialsDatabase.html' def __init__(self, name="", parent_app=None): """**Constructor**""" super().__init__(name, parent_app) self.parameters["name"] = Parameter( name="name", description="Name of polymer", type=ParameterType.string, display_flag=False, ) self.parameters["long"] = Parameter( name="long", description="Long name of polymer", type=ParameterType.string, display_flag=False, ) self.parameters["author"] = Parameter( name="author", description="Who added the data to the database?", type=ParameterType.string, display_flag=False, ) self.parameters["date"] = Parameter( name="date", description="Date when the data was added", type=ParameterType.string, display_flag=False, ) self.parameters["source"] = Parameter( name="source", description="Source of the data", type=ParameterType.string, display_flag=False, ) self.parameters["comment"] = Parameter( name="comment", description="Additional comments", type=ParameterType.string, display_flag=False, ) self.parameters["B1"] = Parameter(name="B1", description="WLF TTS parameter 1") self.parameters["B2"] = Parameter(name="B2", description="WLF TTS parameter 2") self.parameters["logalpha"] = Parameter( name="logalpha", description="Log_10 of the thermal expansion coefficient at 0 °C", ) self.parameters["CTg"] = Parameter( name="CTg", description="Molecular weight dependence of Tg" ) self.parameters["tau_e"] = Parameter( name="tau_e", description="Entanglement time (s)" ) self.parameters["Ge"] = Parameter( name="Ge", description="Entanglement modulus (Pa)" ) self.parameters["Me"] = Parameter( name="Me", description="Entanglement molecular weight (kDa)" ) self.parameters["c_nu"] = Parameter( name="c_nu", description="Constraint release parameter" ) self.parameters["rho0"] = Parameter( name="rho0", description="Density of the polymer melt (g/cm3) at 0 °C" ) self.parameters["chem"] = Parameter( name="chem", description="Repeating unit", type=ParameterType.string ) self.parameters["Te"] = Parameter( name="Te", description="Temperature at which the tube parameters have been determined (°C)", ) self.parameters["M0"] = Parameter( name="M0", description="Mass of Repeating unit (g/mol)" ) self.parameters["MK"] = Parameter( name="MK", description="Molecular weight of Kuhn step (Da)" ) self.parameters["C_inf"] = Parameter( name="C_inf", description="Characteristic ratio" ) # 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: ds = parent_app.datasets[list(parent_app.datasets)[0]] if len(ds.files) > 0: f = ds.files[0] if "chem" in f.file_parameters: self.init_chem = f.file_parameters["chem"] self.update_parameter_table() # self.parent_application.update_all_ds_plots() # add widgets specific to the Tool here: self.active = True self.applytotheory = False self.actionActive.setVisible(True) self.actionApplyToTheory.setVisible(False) self.cbmaterial = QComboBox() self.cbmaterial.setToolTip("Choose a Material from the database") self.model = self.cbmaterial.model() i = 0 for polymer in materials_database.keys(): item = QStandardItem(polymer) item.setToolTip(materials_database[polymer].data["long"]) self.model.appendRow(item) i += 1 self.num_materials_base = i # self.cbmaterial.insertSeparator(i) for polymer in materials_user_database.keys(): item = QStandardItem(polymer) item.setToolTip(materials_user_database[polymer].data["long"]) item.setForeground(QColor("red")) self.model.appendRow(item) self.tb.addWidget(self.cbmaterial) connection_id = self.cbmaterial.currentIndexChanged.connect( self.change_material ) self.actionCalculate = QAction( QIcon(":/Icon8/Images/new_icons/icons8-ok.png"), "Calculate stuff with selected Mw/T", self, ) self.tb.addAction(self.actionCalculate) self.actionNew = QAction( QIcon(":/Icon8/Images/new_icons/icons8-add-file.png"), "New Material", self ) self.tb.addAction(self.actionNew) self.actionEdit = QAction( QIcon(":/Icon8/Images/new_icons/icons8-edit-property.png"), "Edit/View Material Properties", self, ) self.tb.addAction(self.actionEdit) self.actionCopy = QAction( QIcon(":/Icon8/Images/new_icons/icons8-copy-96.png"), "Duplicate Material", self, ) self.tb.addAction(self.actionCopy) self.actionDelete = QAction( QIcon(":/Icon8/Images/new_icons/icons8-delete-document-96.png"), "Delete Material", self, ) self.tb.addAction(self.actionDelete) self.actionSave = QAction( QIcon(":/Icon8/Images/new_icons/icons8-save.png"), "Save User Material Database", self, ) self.tb.addAction(self.actionSave) connection_id = self.actionCalculate.triggered.connect(self.calculate_stuff) connection_id = self.actionNew.triggered.connect(self.new_material) connection_id = self.actionEdit.triggered.connect(self.edit_material) connection_id = self.actionCopy.triggered.connect(self.copy_material) connection_id = self.actionDelete.triggered.connect(self.delete_material) connection_id = self.actionSave.triggered.connect(self.save_usermaterials) self.labelPolymer = QLabel("None") self.labelPolymer.setFont(QFont("Times", weight=QFont.Bold)) self.verticalLayout.insertWidget(1, self.labelPolymer) self.tbMwT = QToolBar() self.tbMwT.setIconSize(QSize(24, 24)) lbl1 = QLabel("Mw (kDa)") lbl1.setFont(QFont("Times", weight=QFont.Bold)) self.tbMwT.addWidget(lbl1) self.editMw = QLineEdit("1") self.editMw.setStyleSheet("QLineEdit { background: rgb(255, 255, 205);}") self.editMw.setFixedWidth(40) self.tbMwT.addWidget(self.editMw) lbl2 = QLabel("T (°C)") lbl2.setFont(QFont("Times", weight=QFont.Bold)) self.tbMwT.addWidget(lbl2) self.editT = QLineEdit("0") self.editT.setStyleSheet("QLineEdit { background: rgb(255, 255, 205);}") self.editT.setFixedWidth(40) self.tbMwT.addWidget(self.editT) self.verticalshift = self.tbMwT.addAction( QIcon(":/Icon8/Images/new_icons/icons8-vertical-shift.png"), "Vertical shift", ) self.verticalshift.setCheckable(True) self.verticalshift.setChecked(True) self.isofrictional = self.tbMwT.addAction( QIcon(":/Icon8/Images/new_icons/icons8-iso.png"), "Shift to isofrictional state", ) self.isofrictional.setCheckable(True) 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", ) 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: self.cbmaterial.setCurrentIndex(init_chem_index) self.change_material()
[docs] def handle_vert_and_iso(self): self.do_plot()
[docs] 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 += "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( self, "Shift all data", msg, buttons=(QMessageBox.Yes | QMessageBox.No), ) if ans != QMessageBox.Yes: return # Calculate shift factors B1 = self.parameters["B1"].value B2 = self.parameters["B2"].value logalpha = self.parameters["logalpha"].value alpha = np.power(10.0, logalpha) CTg = self.parameters["CTg"].value iso = self.isofrictional.isChecked() vert = self.verticalshift.isChecked() # Get current dataset ds = self.parent_application.DataSettabWidget.currentWidget() if not ds: return # Loop over files for f in ds.files: # Get file Current Temperature Tf = f.file_parameters["T"] Mw = f.file_parameters["Mw"] if "iso" in f.file_parameters: iso_file = f.file_parameters["iso"].upper() == "TRUE" elif "isof" in f.file_parameters: iso_file = f.file_parameters["isof"].upper() == "TRUE" else: iso_file = False if iso and not iso_file: B2corrected = B2 + CTg / Mw # - 68.7 * dx12 Trcorrected = Tr - CTg / Mw # + 68.7 * dx12 else: B2corrected = B2 Trcorrected = Tr 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 # 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: 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 self.do_plot()
[docs] def change_material(self): selected_material_name = self.cbmaterial.currentText() if self.cbmaterial.currentIndex() < self.num_materials_base: dbindex = 1 else: dbindex = 0 self.labelPolymer.setText( materials_db[dbindex][selected_material_name].data["long"] ) for k in materials_db[dbindex][selected_material_name].data.keys(): self.set_param_value( k, materials_db[dbindex][selected_material_name].data[k] ) self.update_parameter_table() self.do_plot()
[docs] def new_material(self): # Dialog to ask for short name. Repeat until the name is not in the user's database or CANCEL ok = False while not ok: name, ok = QInputDialog.getText( self, "New name", "Enter the short name of the new material:" ) if not ok: return if name in materials_user_database: QMessageBox.warning( self, "New name", "Error: The name already exists in your database" ) ok = False # Create new material with empty parameters and open the edit dialog newmaterial = polymer_data.polymer( name=name, long="Long Name", author="Author", date="dd/mm/yyyy", source="lab", comment="comment", B1=900, B2=100, logalpha=-3, CTg=0, tau_e=1.0e-6, Ge=1.0e6, Me=1.6, c_nu=0.1, rho0=1.0, chem="C6H6", Te=25, M0=0, ) newmaterial.data["name"] = name materials_user_database[name] = newmaterial item = QStandardItem(name) item.setToolTip(materials_user_database[name].data["long"]) item.setForeground(QColor("red")) self.model.appendRow(item) self.cbmaterial.setCurrentText(name) self.edit_material()
""" Edit the parameters of a user material. - dbindex {int} -- Index of the database to use (0 user, 1 general) """
[docs] def edit_material(self): selected_material_name = self.cbmaterial.currentText() if self.cbmaterial.currentIndex() < self.num_materials_base: QMessageBox.warning( self, "Edit material parameters", "Error: Only user materials can be edited.", ) return material = materials_user_database[selected_material_name] d = EditMaterialParametersDialog(self, material, self.parameters) if d.exec_(): for p in d.param_dict: if isinstance(material.data[p], str): material.data[p] = d.param_dict[p].text() else: try: material.data[p] = float(d.param_dict[p].text()) except Exception as e: print(e) self.set_param_value(p, material.data[p]) self.change_material()
[docs] def save_usermaterials(self): AppData_path = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation) 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)
[docs] def copy_material(self): # Dialog to ask for short name. Repeat until the name is not in the user's database or CANCEL name = "" ok = False while not ok: name, ok = QInputDialog.getText( self, "New name", "Enter the name of the new parameter:" ) if not ok: return if name in materials_user_database: QMessageBox.warning( self, "New name", "Error: The name already exists in your database" ) ok = False # Create new user material with same parameters as source material and new NAME # newpar= selected_material_name = self.cbmaterial.currentText() if self.cbmaterial.currentIndex() < self.num_materials_base: dbindex = 1 else: dbindex = 0 aux = materials_db[dbindex][selected_material_name].data newmaterial = polymer_data.polymer( name=name, long=aux["long"], author="Alexei Likhtman", date="17/03/2006", source=aux["source"], comment=aux["comment"], B1=aux["B1"], B2=aux["B2"], logalpha=aux["logalpha"], CTg=aux["CTg"], tau_e=aux["tau_e"], Ge=aux["Ge"], Me=aux["Me"], c_nu=aux["c_nu"], rho0=aux["rho0"], chem=aux["chem"], Te=aux["Te"], M0=aux["M0"], ) materials_user_database[name] = newmaterial item = QStandardItem(name) item.setToolTip(materials_user_database[name].data["long"]) item.setForeground(QColor("red")) self.model.appendRow(item)
[docs] def delete_material(self): # Check that the material is in the user database selected_material_name = self.cbmaterial.currentText() if self.cbmaterial.currentIndex() < self.num_materials_base: QMessageBox.warning( self, "Dekete material parameters", "Error: Only user materials can be deleted.", ) return # Dialog to ask for confimarion ans = QMessageBox.question( self, "Delete material parameters", "Do you want to delete the material %s?" % selected_material_name, buttons=(QMessageBox.Yes | QMessageBox.No), ) # Delete from ComboBox and User Material dictionary if ans == QMessageBox.Yes: self.cbmaterial.removeItem(self.cbmaterial.currentIndex()) materials_user_database.pop(selected_material_name)
[docs] def calculate_stuff(self, line="", file_parameters=[]): if "Mw" in file_parameters: Mw = float(file_parameters["Mw"]) else: Mw = float(self.editMw.text()) if Mw == 0: Mw = 1 if "T" in file_parameters: T = float(file_parameters["T"]) else: T = float(self.editT.text()) B1 = self.parameters["B1"].value B2 = self.parameters["B2"].value logalpha = self.parameters["logalpha"].value alpha = np.power(10.0, logalpha) CTg = self.parameters["CTg"].value tau_e = self.parameters["tau_e"].value Ge = self.parameters["Ge"].value Me = self.parameters["Me"].value c_nu = self.parameters["c_nu"].value rho0 = self.parameters["rho0"].value Te = self.parameters["Te"].value iso = self.isofrictional.isChecked() vert = self.verticalshift.isChecked() if iso: B2 += CTg / Mw # - 68.7 * dx12 Trcorrected = T - CTg / Mw # + 68.7 * dx12 else: Trcorrected = T aT = np.power(10.0, -B1 * (Te - Trcorrected) / (B2 + Trcorrected) / (B2 + Te)) if vert: bT = (1 + alpha * Te) * (T + 273.15) / (1 + alpha * T) / (Te + 273.15) else: bT = 1 tab_data = [ ["<b>Material &</b>", "<b>Temperature</b>"], ] tab_data.append(["<b>Chemistry</b>", self.parameters["long"].value]) tab_data.append(["<b>Mw</b>", "%g" % Mw]) tab_data.append(["<b>T</b>", "%g" % T]) tab_data.append(["<b>WLF Shift</b>", "<b>Factors</b>"]) tab_data.append(["<b>C1</b>", "%g" % (B1 / (B2 + T))]) tab_data.append(["<b>C2</b>", "%g" % (B2 + T)]) tab_data.append(["<b>Polymer &</b>", "<b>Tube dynamics</b>"]) Ge /= bT tau_e /= aT tab_data.append(["<b>tau_e</b>", "%g" % tau_e]) tab_data.append(["<b>Ge</b>", "%g" % Ge]) CC1 = 1.69 CC2 = 4.17 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) 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)
[docs] 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
[docs] 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 Mw=35.4 T=240 isofrictional=True verticalshift=True""" items = line.split() if len(items) == 4: Mw = float(items[0]) T = float(items[1]) iso = bool(items[2]) vert = bool(items[3]) B1 = self.parameters["B1"].value B2 = self.parameters["B2"].value logalpha = self.parameters["logalpha"].value alpha = np.power(10.0, logalpha) CTg = self.parameters["CTg"].value tau_e = self.parameters["tau_e"].value Ge = self.parameters["Ge"].value Me = self.parameters["Me"].value c_nu = self.parameters["c_nu"].value rho0 = self.parameters["rho0"].value Te = self.parameters["Te"].value if iso: B2 += CTg / Mw # - 68.7 * dx12 Trcorrected = T - CTg / Mw # + 68.7 * dx12 else: Trcorrected = T aT = np.power( 10.0, -B1 * (Te - Trcorrected) / (B2 + Trcorrected) / (B2 + Te) ) if vert: bT = (1 + alpha * Te) * (T + 273.15) / (1 + alpha * T) / (Te + 273.15) else: bT = 1 self.Qprint("<hr><h3>WLF TTS Shift Factors</h3>") # Need T1 (to shift from) and T2 (to shift to), if we want to report aT and bT self.Qprint("<b>C1</b> = %g" % (B1 / (B2 + T))) self.Qprint("<b>C2</b> = %g<br>" % (B2 + T)) self.Qprint("<h3>Tube Theory parameters</h3>") Ge /= bT tau_e /= aT self.Qprint("<b>tau_e</b> = %g" % tau_e) self.Qprint("<b>Ge</b> = %g<br>" % Ge) self.Qprint("<h3>Other Results</h3>") CC1 = 1.69 CC2 = 4.17 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) ) self.Qprint("<b>Z</b> = %g" % Z) self.Qprint("<b>tau_R</b> = %g" % tR) self.Qprint("<b>tau_D</b> = %g<br>" % tD) else: print("Wrong number of parameters.") print(" Usage: calculate_stuff Mw T isofrictional verticalshift")
[docs] 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""" newxy = [] lenx = 1e9 for i in range(n): self.Qprint("<b>Series %d</b>" % (i + 1)) xcopy = x[:, i] ycopy = y[:, i] if i == 0: xcopy, ycopy = self.calculate(xcopy, ycopy, ax, color, file_parameters) newxy.append([xcopy, ycopy]) lenx = min(lenx, len(xcopy)) x = np.resize(x, (lenx, n)) y = np.resize(y, (lenx, n)) for i in range(n): x[:, i] = np.resize(newxy[i][0], lenx) y[:, i] = np.resize(newxy[i][1], lenx) return x, y