Initial Commit

This commit is contained in:
Santiago Soler
2018-01-31 12:35:47 -03:00
commit 567a37e08c
5 changed files with 353 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.pyc

0
__init__.py Normal file
View File

95
figure_canvas.py Normal file
View File

@@ -0,0 +1,95 @@
from __future__ import print_function
from future.builtins import super
import os
import sys
import numpy
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QSizePolicy, QMainWindow, QApplication, QAction
from PyQt5.QtWidgets import QMenu, QWidget, QVBoxLayout, QMessageBox
from PyQt5.QtWidgets import QSlider, QHBoxLayout, QLabel, QDialog
from PyQt5.QtWidgets import QDialogButtonBox
class GravityModelCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
self.fig = Figure(figsize=(width, height), dpi=dpi)
super().__init__(self.fig)
self.setParent(parent)
self._x, self._z = None, None
self._min_depth, self._max_depth = 0., 35000.
self.predicted = None
self.data = None
self.polygons = None
self._plotted = False
FigureCanvasQTAgg.setSizePolicy(self,
QSizePolicy.Expanding,
QSizePolicy.Expanding)
FigureCanvasQTAgg.updateGeometry(self)
@property
def x(self):
return self._x
@x.setter
def x(self, new_value):
self._x = new_value
@property
def z(self):
return self._z
@z.setter
def z(self, new_value):
self._z = new_value
@property
def min_depth(self):
return self._min_depth
@min_depth.setter
def min_depth(self, new_value):
self._min_depth = new_value
@property
def max_depth(self):
return self._max_depth
@max_depth.setter
def max_depth(self, new_value):
self._max_depth = new_value
def update_plot(self):
if self._plotted:
pass
else:
self._figure_setup()
def _figure_setup(self, **kwargs):
self.dataax, self.modelax = self.fig.subplots(2, 1, sharex=True)
if self.data is not None:
self.data_line, = self.dataax.plot(self.x, self.data, '.k')
self.dataax.set_ylabel('Gravity anomaly [mGal]')
self.dataax.set_xlim(self.x.min(), self.x.max())
self.dataax.set_ylim((-200, 200))
self.dataax.grid(True)
self.modelax.set_xlabel('x [m]')
self.modelax.set_xlim(self.x.min(), self.x.max())
self.modelax.set_ylim(self.min_depth, self.max_depth)
self.modelax.grid(True)
self.modelax.invert_yaxis()
self.modelax.set_ylabel('z [m]')
self.fig.subplots_adjust(top=0.95, left=0.1, right=0.95, bottom=0.1,
hspace=0.1)
self.figure = self.fig
self.canvas = self.fig.canvas
self.fig.canvas.draw()

110
moulder.py Normal file
View File

@@ -0,0 +1,110 @@
from __future__ import print_function
from future.builtins import super
import os
import sys
import numpy as np
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QSizePolicy, QMainWindow, QApplication, QAction
from PyQt5.QtWidgets import QMenu, QWidget, QVBoxLayout, QMessageBox
from PyQt5.QtWidgets import QSlider, QHBoxLayout, QLabel, QDialog
from PyQt5.QtWidgets import QDialogButtonBox
from figure_canvas import GravityModelCanvas
from new_dialog import NewModelDialog
class Moulder(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Moulder")
self.setWindowIcon(QIcon.fromTheme('python-logo'))
self.setGeometry(200, 200, 1024, 800)
self.init_ui()
self.set_callbacks()
self.canvas = GravityModelCanvas(self,
width=5, height=4, dpi=100)
self.canvas.setFocus()
self.setCentralWidget(self.canvas)
def closeEvent(self, event):
event.ignore()
self._quit_callback()
def init_ui(self):
self._define_actions()
self._configure_menubar()
self._configure_toolbar()
def set_callbacks(self):
self.new_action.triggered.connect(self._new_model_callback)
self.about_action.triggered.connect(self._about_callback)
# self.file_menu.triggered.connect(self._file_menu_callback)
self.quit_action.triggered.connect(self._quit_callback)
def _define_actions(self):
self.new_action = QAction(QIcon.fromTheme('document-new'),
'&New model', self)
self.new_action.setShortcut('Ctrl+N')
self.open_action = QAction(QIcon.fromTheme('document-open'),
'&Open model', self)
self.open_action.setShortcut('Ctrl+O')
self.save_action = QAction(QIcon.fromTheme('document-save'),
'&Save model', self)
self.save_action.setShortcut('Ctrl+S')
self.save_as_action = QAction(QIcon.fromTheme('document-save-as'),
'&Save model as...', self)
self.save_as_action.setShortcut('Ctrl+Shift+S')
self.quit_action = QAction(QIcon.fromTheme('application-exit'),
'&Quit', self)
self.quit_action.setShortcut('Ctrl+Q')
self.about_action = QAction("&About", self)
def _configure_menubar(self):
self.menubar = self.menuBar()
self.file_menu = self.menubar.addMenu('File')
self.file_menu.addAction(self.open_action)
self.file_menu.addAction(self.save_action)
self.file_menu.addAction(self.quit_action)
self.about_menu = self.menubar.addMenu('About')
self.about_menu.addAction(self.about_action)
def _configure_toolbar(self):
self.toolbar = self.addToolBar("adasd")
self.toolbar.addAction(self.new_action)
self.toolbar.addAction(self.open_action)
self.toolbar.addAction(self.save_action)
self.toolbar.addAction(self.save_as_action)
def _about_callback(self):
QMessageBox.about(self, "About Moulder",
"About Moulder\nVersion 0.1")
def _new_model_callback(self):
new_model_dialog = NewModelDialog(parent=self)
new_model_dialog.exec_()
if new_model_dialog.is_completed():
self.canvas.x = new_model_dialog.x
self.canvas.z = new_model_dialog.z
self.canvas.update_plot()
def _quit_callback(self):
answer = QMessageBox.question(self, "Quit",
"Are you sure you want to quit?",
QMessageBox.Yes, QMessageBox.No)
if answer == QMessageBox.Yes:
sys.exit()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setApplicationName("Moulder")
moulder = Moulder()
moulder.show()
sys.exit(app.exec_())

147
new_dialog.py Normal file
View File

@@ -0,0 +1,147 @@
from __future__ import print_function
from future.builtins import super
import os
import sys
import numpy
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QSizePolicy, QMainWindow, QApplication, QAction
from PyQt5.QtWidgets import QMenu, QWidget, QVBoxLayout, QMessageBox
from PyQt5.QtWidgets import QSlider, QHBoxLayout, QLabel, QDialog, QPushButton
from PyQt5.QtWidgets import QDialogButtonBox, QGridLayout, QRadioButton, QLineEdit
class NewModelDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setModal(False)
self.setWindowTitle("Create New Model")
self._completed = False
self._init_ui()
self.regular_grid_btn.toggled.connect(self._radio_button_callback)
self.custom_grid_btn.toggled.connect(self._radio_button_callback)
self.cancel_btn.clicked.connect(self._button_pushed_callback)
self.ok_btn.clicked.connect(self._button_pushed_callback)
@property
def x(self):
if self.regular_grid_btn.isChecked():
entries = self._read_regular_grid_entries()
if entries:
x1, x2, step, z = entries[:]
return numpy.arange(x1, x2, step, dtype=numpy.float64)
else:
return None
elif self.custom_grid_btn.isChecked():
# Need to be completed
pass
@property
def z(self):
if self.regular_grid_btn.isChecked():
entries = self._read_regular_grid_entries()
if entries:
x1, x2, step, z = entries[:]
return z*numpy.ones_like(self.x)
else:
return None
elif self.custom_grid_btn.isChecked():
# Need to be completed
pass
def is_completed(self):
return self._completed
def _init_ui(self):
self.regular_grid_btn = QRadioButton("Regular grid (in meters)")
self.regular_grid_btn.setChecked(True)
self.custom_grid_btn = QRadioButton("Custom grid")
self.from_input = QLineEdit()
self.to_input = QLineEdit()
self.step_input = QLineEdit()
self.height_input = QLineEdit()
self.ok_btn = QPushButton("Ok")
self.cancel_btn = QPushButton("Cancel")
self.ok_btn.setDefault(True)
bold_font = QFont()
bold_font.setBold(True)
layout = QVBoxLayout()
layout.addWidget(QLabel("Create Meassurement Points", font=bold_font))
layout.addWidget(self.regular_grid_btn)
grid = QGridLayout()
grid.setContentsMargins(25, 0, 0, 0)
grid.addWidget(QLabel("From:"), 0, 0)
grid.addWidget(self.from_input, 0, 1)
grid.addWidget(QLabel("To:"), 0, 2)
grid.addWidget(self.to_input, 0, 3)
grid.addWidget(QLabel("Step:"), 0, 4)
grid.addWidget(self.step_input, 0, 5)
grid.addWidget(QLabel("Height:"), 1, 0)
grid.addWidget(self.height_input, 1, 1, 1, 5)
layout.addLayout(grid)
layout.addWidget(self.custom_grid_btn)
hbox = QHBoxLayout()
hbox.setAlignment(Qt.AlignRight)
hbox.addWidget(self.cancel_btn)
hbox.addWidget(self.ok_btn)
layout.addLayout(hbox)
self.setLayout(layout)
def _button_pushed_callback(self):
sender_text = self.sender().text()
if sender_text == "Cancel":
self.close()
elif sender_text == "Ok":
filled_entries = self._check_filled_entries()
if filled_entries:
self._completed = True
self.close()
else:
QMessageBox.warning(self, "Warning",
"Some entries are not properly " +
"completed or are incomplete.")
def _radio_button_callback(self):
regular_grid_lines = [self.from_input, self.to_input,
self.step_input, self.height_input]
if self.sender().text() == "Custom grid":
for line_edit in regular_grid_lines:
line_edit.setDisabled(True)
else:
for line_edit in regular_grid_lines:
line_edit.setEnabled(True)
def _check_filled_entries(self):
if self.regular_grid_btn.isChecked():
entries = self._read_regular_grid_entries()
if entries:
return True
else:
# Show messagebox with warning for not completed entries
pass
elif self.custom_grid_btn.isChecked():
# Needed to be completed
return False
def _read_regular_grid_entries(self):
x1, x2 = self.from_input.text(), self.to_input.text()
step = self.step_input.text()
z = self.height_input.text()
try:
x1, x2, step = float(x1), float(x2), float(step)
z = float(z)
except ValueError:
return False
return x1, x2, step, z