forked from IPKM/nmreval
added Gaussian, Lorentzian, Pseudo-Voigt
This commit is contained in:
parent
531eac22b7
commit
74dacd0180
@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/basewindow.ui'
|
# Form implementation generated from reading ui file 'resources/_ui/basewindow.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.9.2
|
# Created by: PyQt5 UI code generator 5.12.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
class Ui_BaseWindow(object):
|
class Ui_BaseWindow(object):
|
||||||
def setupUi(self, BaseWindow):
|
def setupUi(self, BaseWindow):
|
||||||
BaseWindow.setObjectName("BaseWindow")
|
BaseWindow.setObjectName("BaseWindow")
|
||||||
@ -355,6 +357,8 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionTetris.setObjectName("actionTetris")
|
self.actionTetris.setObjectName("actionTetris")
|
||||||
self.actionUpdate = QtWidgets.QAction(BaseWindow)
|
self.actionUpdate = QtWidgets.QAction(BaseWindow)
|
||||||
self.actionUpdate.setObjectName("actionUpdate")
|
self.actionUpdate.setObjectName("actionUpdate")
|
||||||
|
self.actionMine = QtWidgets.QAction(BaseWindow)
|
||||||
|
self.actionMine.setObjectName("actionMine")
|
||||||
self.menuSave.addAction(self.actionSave)
|
self.menuSave.addAction(self.actionSave)
|
||||||
self.menuSave.addAction(self.actionExportGraphic)
|
self.menuSave.addAction(self.actionExportGraphic)
|
||||||
self.menuSave.addAction(self.action_save_fit_parameter)
|
self.menuSave.addAction(self.action_save_fit_parameter)
|
||||||
@ -444,6 +448,7 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuStuff.addAction(self.actionSnake)
|
self.menuStuff.addAction(self.actionSnake)
|
||||||
self.menuStuff.addAction(self.actionLife)
|
self.menuStuff.addAction(self.actionLife)
|
||||||
self.menuStuff.addAction(self.actionTetris)
|
self.menuStuff.addAction(self.actionTetris)
|
||||||
|
self.menuStuff.addAction(self.actionMine)
|
||||||
self.menubar.addAction(self.menuFile.menuAction())
|
self.menubar.addAction(self.menuFile.menuAction())
|
||||||
self.menubar.addAction(self.menuWindow.menuAction())
|
self.menubar.addAction(self.menuWindow.menuAction())
|
||||||
self.menubar.addAction(self.menuData.menuAction())
|
self.menubar.addAction(self.menuData.menuAction())
|
||||||
@ -594,12 +599,12 @@ class Ui_BaseWindow(object):
|
|||||||
self.action_no_range.setText(_translate("BaseWindow", "None"))
|
self.action_no_range.setText(_translate("BaseWindow", "None"))
|
||||||
self.action_x_range.setText(_translate("BaseWindow", "Visible x range"))
|
self.action_x_range.setText(_translate("BaseWindow", "Visible x range"))
|
||||||
self.action_custom_range.setText(_translate("BaseWindow", "Custom"))
|
self.action_custom_range.setText(_translate("BaseWindow", "Custom"))
|
||||||
self.actionSnake.setText(_translate("BaseWindow", "Worms"))
|
self.actionSnake.setText(_translate("BaseWindow", "Worm"))
|
||||||
self.actionFunction_editor.setText(_translate("BaseWindow", "Function editor..."))
|
self.actionFunction_editor.setText(_translate("BaseWindow", "Function editor..."))
|
||||||
self.actionLife.setText(_translate("BaseWindow", "Life..."))
|
self.actionLife.setText(_translate("BaseWindow", "Life..."))
|
||||||
self.actionTetris.setText(_translate("BaseWindow", "Not Tetris"))
|
self.actionTetris.setText(_translate("BaseWindow", "Not Tetris"))
|
||||||
self.actionUpdate.setText(_translate("BaseWindow", "Look for updates"))
|
self.actionUpdate.setText(_translate("BaseWindow", "Look for updates"))
|
||||||
|
self.actionMine.setText(_translate("BaseWindow", "Mine"))
|
||||||
from ..data.datawidget.datawidget import DataWidget
|
from ..data.datawidget.datawidget import DataWidget
|
||||||
from ..data.point_select import PointSelectWidget
|
from ..data.point_select import PointSelectWidget
|
||||||
from ..data.signaledit.editsignalwidget import EditSignalWidget
|
from ..data.signaledit.editsignalwidget import EditSignalWidget
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import random
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
@ -144,9 +145,9 @@ class Board(QtWidgets.QFrame):
|
|||||||
|
|
||||||
|
|
||||||
class SnakeBoard(Board):
|
class SnakeBoard(Board):
|
||||||
SPEED = 100
|
SPEED = 125
|
||||||
WIDTH = 30
|
WIDTH = 35
|
||||||
HEIGHT = 30
|
HEIGHT = 35
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@ -155,6 +156,9 @@ class SnakeBoard(Board):
|
|||||||
[int(SnakeBoard.WIDTH//2)+1, int(SnakeBoard.HEIGHT//2)]]
|
[int(SnakeBoard.WIDTH//2)+1, int(SnakeBoard.HEIGHT//2)]]
|
||||||
self.current_x_head, self.current_y_head = self.snake[0]
|
self.current_x_head, self.current_y_head = self.snake[0]
|
||||||
self.direction = 'l'
|
self.direction = 'l'
|
||||||
|
self.next_direction = []
|
||||||
|
|
||||||
|
self._direction_pairs = {'l': 'r', 'u': 'd', 'r': 'l', 'd': 'u'}
|
||||||
|
|
||||||
self.food = None
|
self.food = None
|
||||||
self.grow_snake = False
|
self.grow_snake = False
|
||||||
@ -176,6 +180,12 @@ class SnakeBoard(Board):
|
|||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def snake_move(self):
|
def snake_move(self):
|
||||||
|
print(self.next_direction)
|
||||||
|
if self.next_direction:
|
||||||
|
turn = self.next_direction.pop()
|
||||||
|
if self.direction != self._direction_pairs[turn]:
|
||||||
|
self.direction = turn
|
||||||
|
|
||||||
if self.direction == 'l':
|
if self.direction == 'l':
|
||||||
self.current_x_head -= 1
|
self.current_x_head -= 1
|
||||||
elif self.direction == 'r':
|
elif self.direction == 'r':
|
||||||
@ -187,7 +197,7 @@ class SnakeBoard(Board):
|
|||||||
elif self.direction == 'd':
|
elif self.direction == 'd':
|
||||||
self.current_y_head += 1
|
self.current_y_head += 1
|
||||||
|
|
||||||
head = [self.current_x_head, self.current_y_head]
|
head = (self.current_x_head, self.current_y_head)
|
||||||
self.snake.insert(0, head)
|
self.snake.insert(0, head)
|
||||||
|
|
||||||
if not self.grow_snake:
|
if not self.grow_snake:
|
||||||
@ -207,11 +217,11 @@ class SnakeBoard(Board):
|
|||||||
x = random.randint(3, SnakeBoard.WIDTH-3)
|
x = random.randint(3, SnakeBoard.WIDTH-3)
|
||||||
y = random.randint(3, SnakeBoard.HEIGHT-3)
|
y = random.randint(3, SnakeBoard.HEIGHT-3)
|
||||||
|
|
||||||
while [x, y] == self.snake[0]:
|
while (x, y) in self.snake:
|
||||||
x = random.randint(3, SnakeBoard.WIDTH-3)
|
x = random.randint(3, SnakeBoard.WIDTH-3)
|
||||||
y = random.randint(3, SnakeBoard.HEIGHT-3)
|
y = random.randint(3, SnakeBoard.HEIGHT-3)
|
||||||
|
|
||||||
self.food = [x, y]
|
self.food = (x, y)
|
||||||
|
|
||||||
def check_death(self):
|
def check_death(self):
|
||||||
rip_message = ''
|
rip_message = ''
|
||||||
@ -234,20 +244,16 @@ class SnakeBoard(Board):
|
|||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
key = event.key()
|
key = event.key()
|
||||||
if key in (QtCore.Qt.Key_Left, QtCore.Qt.Key_A):
|
if key in (QtCore.Qt.Key_Left, QtCore.Qt.Key_A):
|
||||||
if self.direction != 'r':
|
self.next_direction.append('l')
|
||||||
self.direction = 'l'
|
|
||||||
|
|
||||||
elif key in (QtCore.Qt.Key_Right, QtCore.Qt.Key_D):
|
elif key in (QtCore.Qt.Key_Right, QtCore.Qt.Key_D):
|
||||||
if self.direction != 'l':
|
self.next_direction.append('r')
|
||||||
self.direction = 'r'
|
|
||||||
|
|
||||||
elif key in (QtCore.Qt.Key_Down, QtCore.Qt.Key_S):
|
elif key in (QtCore.Qt.Key_Down, QtCore.Qt.Key_S):
|
||||||
if self.direction != 'u':
|
self.next_direction.append('d')
|
||||||
self.direction = 'd'
|
|
||||||
|
|
||||||
elif key in (QtCore.Qt.Key_Up, QtCore.Qt.Key_W):
|
elif key in (QtCore.Qt.Key_Up, QtCore.Qt.Key_W):
|
||||||
if self.direction != 'd':
|
self.next_direction.append('u')
|
||||||
self.direction = 'u'
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return super().keyPressEvent(event)
|
return super().keyPressEvent(event)
|
||||||
@ -493,3 +499,280 @@ class MirrorL(Tetromino):
|
|||||||
SHAPE = np.array([[1, 0, 0, 0],
|
SHAPE = np.array([[1, 0, 0, 0],
|
||||||
[-1, -1, 0, 1]])
|
[-1, -1, 0, 1]])
|
||||||
color = 'lightGray'
|
color = 'lightGray'
|
||||||
|
|
||||||
|
|
||||||
|
class Field(QtWidgets.QToolButton):
|
||||||
|
NUM_COLORS = {
|
||||||
|
1: '#1e46a4',
|
||||||
|
2: '#f28e2b',
|
||||||
|
3: '#e15759',
|
||||||
|
4: '#76b7b2',
|
||||||
|
5: '#59a14f',
|
||||||
|
6: '#edc948',
|
||||||
|
7: '#b07aa1',
|
||||||
|
8: '#ff9da7',
|
||||||
|
'X': '#ff0000',
|
||||||
|
}
|
||||||
|
|
||||||
|
flag_change = QtCore.pyqtSignal(bool)
|
||||||
|
|
||||||
|
def __init__(self, x, y, parent=None):
|
||||||
|
super(Field, self).__init__(parent=parent)
|
||||||
|
|
||||||
|
self.setFixedSize(QtCore.QSize(30, 30))
|
||||||
|
f = self.font()
|
||||||
|
f.setPointSize(24)
|
||||||
|
f.setWeight(75)
|
||||||
|
self.setFont(f)
|
||||||
|
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
self.neighbors = []
|
||||||
|
self.grid = self.parent()
|
||||||
|
|
||||||
|
_size = self.grid.gridsize
|
||||||
|
for x_i in range(max(0, self.x-1), min(self.x+2, _size[0])):
|
||||||
|
for y_i in range(max(0, self.y-1), min(self.y+2, _size[1])):
|
||||||
|
if (x_i, y_i) == (self.x, self.y):
|
||||||
|
continue
|
||||||
|
self.neighbors.append((x_i, y_i))
|
||||||
|
|
||||||
|
self.is_mine = False
|
||||||
|
self.is_flagged = False
|
||||||
|
self.is_known = False
|
||||||
|
self.has_died = False
|
||||||
|
|
||||||
|
def mousePressEvent(self, evt: QtGui.QMouseEvent) -> None:
|
||||||
|
if self.grid.status == 'finished':
|
||||||
|
return
|
||||||
|
|
||||||
|
if evt.button() == QtCore.Qt.RightButton:
|
||||||
|
self.set_flag()
|
||||||
|
elif evt.button() == QtCore.Qt.LeftButton:
|
||||||
|
self.select()
|
||||||
|
else:
|
||||||
|
super().mousePressEvent(evt)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
if self.is_mine:
|
||||||
|
return 'X'
|
||||||
|
else:
|
||||||
|
return str(self.visible_mines)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def visible_mines(self) -> int:
|
||||||
|
return sum(self.grid.map[x_i][y_i].is_mine for x_i, y_i in self.neighbors)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot()
|
||||||
|
def select(self):
|
||||||
|
if self.is_flagged:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.is_mine:
|
||||||
|
self.setText('X')
|
||||||
|
num = 'X'
|
||||||
|
self.has_died = True
|
||||||
|
self.setStyleSheet(f'color: {self.NUM_COLORS[num]}')
|
||||||
|
else:
|
||||||
|
self.is_known = True
|
||||||
|
self.setEnabled(False)
|
||||||
|
self.setAutoRaise(True)
|
||||||
|
|
||||||
|
num = self.visible_mines
|
||||||
|
if num != 0:
|
||||||
|
self.setText(str(num))
|
||||||
|
self.setStyleSheet(f'color: {self.NUM_COLORS[num]}')
|
||||||
|
else:
|
||||||
|
self.grid.reveal_neighbors(self)
|
||||||
|
|
||||||
|
self.clicked.emit()
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot()
|
||||||
|
def set_flag(self):
|
||||||
|
if self.is_flagged:
|
||||||
|
self.setText('')
|
||||||
|
else:
|
||||||
|
self.setText('!')
|
||||||
|
self.is_flagged = not self.is_flagged
|
||||||
|
self.has_died = False
|
||||||
|
|
||||||
|
self.clicked.emit()
|
||||||
|
self.flag_change.emit(self.is_flagged)
|
||||||
|
|
||||||
|
|
||||||
|
class QMines(QtWidgets.QMainWindow):
|
||||||
|
LEVELS = {
|
||||||
|
'easy': ((9, 9), 10),
|
||||||
|
'middle': ((16, 16), 40),
|
||||||
|
'hard': ((16, 30), 99),
|
||||||
|
'very hard': ((16, 30), 10),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
self.map = []
|
||||||
|
|
||||||
|
self.status = 'waiting'
|
||||||
|
self.open_fields = 0
|
||||||
|
self.num_flags = 0
|
||||||
|
|
||||||
|
self._start = 0
|
||||||
|
|
||||||
|
self.gridsize, self.mines = (1, 1), 1
|
||||||
|
|
||||||
|
self._init_ui()
|
||||||
|
|
||||||
|
def _init_ui(self):
|
||||||
|
layout = QtWidgets.QGridLayout()
|
||||||
|
layout.setSpacing(0)
|
||||||
|
self.central = QtWidgets.QWidget()
|
||||||
|
self.setCentralWidget(self.central)
|
||||||
|
|
||||||
|
layout.addItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding),
|
||||||
|
0, 0)
|
||||||
|
|
||||||
|
self.grid_layout = QtWidgets.QGridLayout()
|
||||||
|
self.grid_layout.setSpacing(0)
|
||||||
|
self.map_widget = QtWidgets.QFrame()
|
||||||
|
self.map_widget.setFrameStyle(2)
|
||||||
|
self.map_widget.setLayout(self.grid_layout)
|
||||||
|
layout.addWidget(self.map_widget, 1, 1)
|
||||||
|
|
||||||
|
self.new_game = QtWidgets.QPushButton('New game')
|
||||||
|
self.new_game.pressed.connect(self._init_map)
|
||||||
|
layout.addWidget(self.new_game, 0, 1)
|
||||||
|
|
||||||
|
layout.addItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding),
|
||||||
|
2, 2)
|
||||||
|
|
||||||
|
self.central.setLayout(layout)
|
||||||
|
|
||||||
|
self.timer = QtCore.QTimer()
|
||||||
|
self.timer.setInterval(1000)
|
||||||
|
self.timer.timeout.connect(self.update_time)
|
||||||
|
|
||||||
|
self.timer_message = QtWidgets.QLabel('0 s')
|
||||||
|
self.statusBar().addWidget(self.timer_message)
|
||||||
|
|
||||||
|
self.mine_message = QtWidgets.QLabel(f'0 / {self.mines}')
|
||||||
|
self.statusBar().addWidget(self.mine_message)
|
||||||
|
|
||||||
|
self.dead_message = QtWidgets.QLabel('')
|
||||||
|
self.statusBar().addWidget(self.dead_message)
|
||||||
|
|
||||||
|
self.level_cb = QtWidgets.QComboBox()
|
||||||
|
self.level_cb.addItems(list(self.LEVELS.keys()))
|
||||||
|
self.level_cb.currentTextChanged.connect(self._init_map)
|
||||||
|
self.statusBar().addPermanentWidget(self.level_cb)
|
||||||
|
|
||||||
|
self._init_map('easy')
|
||||||
|
|
||||||
|
def _init_map(self, lvl: str = None):
|
||||||
|
if lvl is None:
|
||||||
|
lvl = self.level_cb.currentText()
|
||||||
|
|
||||||
|
self._clear_map()
|
||||||
|
|
||||||
|
self.gridsize, self.mines = QMines.LEVELS[lvl]
|
||||||
|
w, h = self.gridsize
|
||||||
|
self.map = [[None] * h for _ in range(w)]
|
||||||
|
|
||||||
|
for x in range(w):
|
||||||
|
for y in range(h):
|
||||||
|
pos = Field(x, y, parent=self)
|
||||||
|
pos.clicked.connect(self.start_game)
|
||||||
|
pos.clicked.connect(self.update_status)
|
||||||
|
pos.flag_change.connect(self.update_flag)
|
||||||
|
self.grid_layout.addWidget(pos, x+1, y+1)
|
||||||
|
self.map[x][y] = pos
|
||||||
|
|
||||||
|
self.set_mines()
|
||||||
|
|
||||||
|
def _clear_map(self):
|
||||||
|
self.status = 'waiting'
|
||||||
|
self.open_fields = 0
|
||||||
|
self.num_flags = 0
|
||||||
|
|
||||||
|
self._start = 0
|
||||||
|
|
||||||
|
self.map = []
|
||||||
|
|
||||||
|
while self.grid_layout.count():
|
||||||
|
child = self.grid_layout.takeAt(0)
|
||||||
|
w = child.widget()
|
||||||
|
if w:
|
||||||
|
self.grid_layout.removeWidget(w)
|
||||||
|
w.deleteLater()
|
||||||
|
else:
|
||||||
|
self.grid_layout.removeItem(child)
|
||||||
|
|
||||||
|
def set_mines(self):
|
||||||
|
count = 0
|
||||||
|
w, h = self.gridsize
|
||||||
|
while count < self.mines:
|
||||||
|
n = random.randint(0, w * h - 1)
|
||||||
|
row = n // h
|
||||||
|
col = n % h
|
||||||
|
pos = self.map[row][col] # type: Field
|
||||||
|
if pos.is_mine:
|
||||||
|
continue
|
||||||
|
pos.is_mine = True
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
self.status = 'waiting'
|
||||||
|
self.open_fields = 0
|
||||||
|
self.num_flags = 0
|
||||||
|
self._start = 0
|
||||||
|
|
||||||
|
self.timer_message.setText('0 s')
|
||||||
|
self.mine_message.setText(f'0 / {self.mines}')
|
||||||
|
self.dead_message.setText('')
|
||||||
|
|
||||||
|
def reveal_neighbors(self, pos: Field):
|
||||||
|
for x_i, y_i in pos.neighbors:
|
||||||
|
field_i = self.map[x_i][y_i] # type: Field
|
||||||
|
if field_i.isEnabled():
|
||||||
|
field_i.select()
|
||||||
|
|
||||||
|
def start_game(self):
|
||||||
|
if self.status == 'waiting':
|
||||||
|
self.status = 'running'
|
||||||
|
self._start = time.time()
|
||||||
|
self.timer.start(1000)
|
||||||
|
|
||||||
|
def update_time(self):
|
||||||
|
if self.status == 'running':
|
||||||
|
self.timer_message.setText(f'{time.time()-self._start:3.0f} s')
|
||||||
|
|
||||||
|
def update_status(self):
|
||||||
|
if self.status == 'finished':
|
||||||
|
return
|
||||||
|
|
||||||
|
pos = self.sender() # type: Field
|
||||||
|
if pos.is_known:
|
||||||
|
self.open_fields += 1
|
||||||
|
if self.open_fields == self.gridsize[0] * self.gridsize[1] - self.mines:
|
||||||
|
self.timer.stop()
|
||||||
|
|
||||||
|
_ = QtWidgets.QMessageBox.information(self, 'Game finished', 'Game finished!!!')
|
||||||
|
self.status = 'finished'
|
||||||
|
|
||||||
|
elif pos.has_died:
|
||||||
|
dead_cnt = self.dead_message.text()
|
||||||
|
if dead_cnt == '':
|
||||||
|
self.dead_message.setText('(Deaths: 1)')
|
||||||
|
else:
|
||||||
|
self.dead_message.setText(f'(Deaths: {int(dead_cnt[9:-1])+1})')
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(bool)
|
||||||
|
def update_flag(self, state: bool):
|
||||||
|
num_mines = int(self.mine_message.text().split()[0])
|
||||||
|
if state:
|
||||||
|
num_mines += 1
|
||||||
|
else:
|
||||||
|
num_mines -= 1
|
||||||
|
|
||||||
|
self.mine_message.setText(f'{num_mines} / {self.mines}')
|
||||||
|
|
||||||
|
@ -905,6 +905,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
@QtCore.pyqtSlot(name='on_actionSnake_triggered')
|
@QtCore.pyqtSlot(name='on_actionSnake_triggered')
|
||||||
@QtCore.pyqtSlot(name='on_actionTetris_triggered')
|
@QtCore.pyqtSlot(name='on_actionTetris_triggered')
|
||||||
@QtCore.pyqtSlot(name='on_actionLife_triggered')
|
@QtCore.pyqtSlot(name='on_actionLife_triggered')
|
||||||
|
@QtCore.pyqtSlot(name='on_actionMine_triggered')
|
||||||
def spannung_spiel_und_spass(self):
|
def spannung_spiel_und_spass(self):
|
||||||
|
|
||||||
if self.sender() == self.actionLife:
|
if self.sender() == self.actionLife:
|
||||||
@ -913,6 +914,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
game.setWindowModality(QtCore.Qt.NonModal)
|
game.setWindowModality(QtCore.Qt.NonModal)
|
||||||
game.show()
|
game.show()
|
||||||
|
|
||||||
|
elif self.sender() == self.actionMine:
|
||||||
|
from ..lib.stuff import QMines
|
||||||
|
game = QMines(parent=self)
|
||||||
|
game.setWindowModality(QtCore.Qt.NonModal)
|
||||||
|
game.show()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
from ..lib.stuff import Game
|
from ..lib.stuff import Game
|
||||||
if self.sender() == self.actionSnake:
|
if self.sender() == self.actionSnake:
|
||||||
|
@ -31,4 +31,5 @@ from .bds import *
|
|||||||
from .temperature import *
|
from .temperature import *
|
||||||
from .transitions import *
|
from .transitions import *
|
||||||
from .correlationfuncs import *
|
from .correlationfuncs import *
|
||||||
|
from .spectrum import *
|
||||||
from .wideline import *
|
from .wideline import *
|
||||||
|
92
nmreval/models/spectrum.py
Normal file
92
nmreval/models/spectrum.py
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
__all__ = ['Gaussian', 'Lorentzian', 'PseudoVoigt']
|
||||||
|
|
||||||
|
ArrayLike = Union[float, np.ndarray]
|
||||||
|
|
||||||
|
|
||||||
|
class Gaussian:
|
||||||
|
name = 'Gaussian'
|
||||||
|
equation = 'A*((4ln2/\pi)^{0.5}*(1/w) exp(-4ln2 [(x-\mu)/w]^{2})+A_{0}'
|
||||||
|
params = ['A', r'\mu', 'w', 'A_{0}']
|
||||||
|
type = 'Spectrum'
|
||||||
|
bounds = [(0, None), (None, None), (0, None), (None, None)]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def func(x: ArrayLike, a: float, mu: float, sigma: float, off: float) -> ArrayLike:
|
||||||
|
r"""
|
||||||
|
|
||||||
|
Calculates Gaussian lineshape
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
f(x) = \frac{A}{\sqrt{2\pi} \sigma} \exp\left[-\frac{(x-\mu)^2}{2\sigma^2} \right] + A_0
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (float): Frequncy axis
|
||||||
|
a (float): Amplitude
|
||||||
|
mu (float): Maximum position
|
||||||
|
sigma (float): FWHM
|
||||||
|
off (float): Baseline
|
||||||
|
|
||||||
|
"""
|
||||||
|
return a / (np.sqrt(4*np.log(2)/np.pi) * sigma) * np.exp(-4*np.log(2) * ((x-mu) / sigma)**2) + off
|
||||||
|
|
||||||
|
|
||||||
|
class Lorentzian:
|
||||||
|
type = 'Spectrum'
|
||||||
|
name = 'Lorentzian'
|
||||||
|
equation = 'A (2/\pi)w/[4*(x-\mu)^{2} + w^{2}] + A_{0}'
|
||||||
|
params = ['A', '\mu', 'w', 'A_{0}']
|
||||||
|
ext_params = None
|
||||||
|
bounds = [(0, None), (None, None), (0, None), (None, None)]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def func(x: ArrayLike, a: float, mu: float, sigma: float, off: float) -> ArrayLike:
|
||||||
|
r"""
|
||||||
|
Calculate Lorentzian lineshape
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
f(x) = \frac{A\sigma}{(x-\mu)^2 + \sigma^2} + A_0
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (float): Frequency axis
|
||||||
|
a (float): Amplitude
|
||||||
|
mu (float): Maximum position
|
||||||
|
sigma (float): FWHM
|
||||||
|
off (float): baseline
|
||||||
|
|
||||||
|
"""
|
||||||
|
return (a/np.pi) * 2*sigma / (4*(x-mu)**2 + sigma**2) + off
|
||||||
|
|
||||||
|
|
||||||
|
class PseudoVoigt:
|
||||||
|
type = 'Spectrum'
|
||||||
|
name = 'Pseudo Voigt'
|
||||||
|
equation = 'A [R*2/\pi*w/[4*(x-\mu)^{2} + w^{2}] + ' \
|
||||||
|
'(1-R)*sqrt(4*ln(2)/pi)/w*exp(-4*ln(2)[(x-\mu)/w]^{2})] + A_{0}'
|
||||||
|
params = ['A', 'R', '\mu', 'w', 'A_{0}']
|
||||||
|
ext_params = None
|
||||||
|
bounds = [(0, None), (0, 1), (None, None), (0, None)]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def func(x: ArrayLike, a: float, r_lor: float, mu: float, sigma: float, off: float) -> ArrayLike:
|
||||||
|
r"""
|
||||||
|
Calculate Pseudo-Voigt lineshape, superposition of Lorentzian and Gaussian with shared center and FWHM.
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
f(x) = A \left[ R \frac{2}{\pi} \frac{\sigma}{4(x-\mu)^2 + \sigma^2} +
|
||||||
|
(1-R)\sqrt{\frac{4\ln2}{\pi}} \frac{1}{\sigma} \exp\left(-4\ln2 \frac{(x-\mu)^2}{\sigma^2} \right) \right] + A_0
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (array-like): Frequency
|
||||||
|
a (float): Amplitude
|
||||||
|
r_lor (float): Relative Lorentzian contribution
|
||||||
|
mu (float): Maximum position
|
||||||
|
sigma (float): FWHM
|
||||||
|
off (float): Baseline
|
||||||
|
|
||||||
|
"""
|
||||||
|
return a * (r_lor * (2/np.pi) * (sigma/(4*(x-mu)**2 + sigma**2)) +
|
||||||
|
(1-r_lor) * np.sqrt(4*np.log(2)/np.pi)/sigma * np.exp(-4*np.log(2)*((x-mu)/sigma)**2)) + off
|
@ -9,7 +9,7 @@ from ..math.orientations import zcw_spherical as crystallites
|
|||||||
|
|
||||||
|
|
||||||
class Pake:
|
class Pake:
|
||||||
type = 'Wideline'
|
type = 'Spectrum'
|
||||||
name = 'Pake'
|
name = 'Pake'
|
||||||
equation = ''
|
equation = ''
|
||||||
params = ['A', r'\delta', r'\eta', r'\Sigma_{B}', r't_{pulse}']
|
params = ['A', r'\delta', r'\eta', r'\Sigma_{B}', r't_{pulse}']
|
||||||
@ -52,7 +52,7 @@ class Pake:
|
|||||||
|
|
||||||
|
|
||||||
class CSA:
|
class CSA:
|
||||||
type = 'Wideline'
|
type = 'Spectrum'
|
||||||
name = 'CSA'
|
name = 'CSA'
|
||||||
equation = ''
|
equation = ''
|
||||||
params = ['A', r'\delta', r'\eta', r'\omega_{iso}', r'\Sigma_{B}']
|
params = ['A', r'\delta', r'\eta', r'\omega_{iso}', r'\Sigma_{B}']
|
||||||
@ -85,8 +85,8 @@ class CSA:
|
|||||||
|
|
||||||
|
|
||||||
class SecCentralLine:
|
class SecCentralLine:
|
||||||
type = 'Wideline'
|
type = 'Spectrum'
|
||||||
name = 'Central Transition 2nd order'
|
name = 'Central Transition (2nd order)'
|
||||||
equation = ''
|
equation = ''
|
||||||
params = ['A', 'C_{Q}', r'\eta', r'\omega_{iso}', 'GB', r'\omega_{L}']
|
params = ['A', 'C_{Q}', r'\eta', r'\omega_{iso}', 'GB', r'\omega_{L}']
|
||||||
bounds = [(0, None), (0, None), (0, 1), (None, None), (0, None), (0, None)]
|
bounds = [(0, None), (0, None), (0, 1), (None, None), (0, None), (0, None)]
|
||||||
@ -129,4 +129,4 @@ class SecCentralLine:
|
|||||||
else:
|
else:
|
||||||
ret_val = s
|
ret_val = s
|
||||||
|
|
||||||
return c * ret_val / trapz(ret_val, x)
|
return c * ret_val / simpson(ret_val, x)
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
<addaction name="actionSnake"/>
|
<addaction name="actionSnake"/>
|
||||||
<addaction name="actionLife"/>
|
<addaction name="actionLife"/>
|
||||||
<addaction name="actionTetris"/>
|
<addaction name="actionTetris"/>
|
||||||
|
<addaction name="actionMine"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
<addaction name="menuWindow"/>
|
<addaction name="menuWindow"/>
|
||||||
@ -970,7 +971,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionSnake">
|
<action name="actionSnake">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Worms</string>
|
<string>Worm</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionFunction_editor">
|
<action name="actionFunction_editor">
|
||||||
@ -993,6 +994,11 @@
|
|||||||
<string>Look for updates</string>
|
<string>Look for updates</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionMine">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mine</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
Loading…
Reference in New Issue
Block a user