Skip to content

Commit

Permalink
Added basic GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
gyanz committed Aug 19, 2019
1 parent f1db307 commit 7c56c06
Show file tree
Hide file tree
Showing 12 changed files with 772 additions and 2 deletions.
92 changes: 92 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#########################################
# Editor temporary/working/backup files #
.#*
*\#*\#
[#]*#
*~
*$
*.bak
*.log
*.swp
*.pdb
.project
.pydevproject
.settings
.idea
.ipynb_checkpoints
.tags
.cache/
.vscode/

# Compiled source #
###################
*.a
*.com
*.class
*.dll
*.exe
*.px[i]
*.o
*.obj
*.lib
*.manifest
*.exp
*.py[oc]
.build_cache_dir
MANIFEST

# Python files #
################
# setup.py working directory
build
# sphinx build directory
doc/_build
# setup.py dist directory
dist
# Egg metadata
*.egg-info
.eggs
.pypirc

# wheel files
*.whl
**/wheelhouse/*
# coverage
.coverage
coverage.xml
coverage_html_report
.mypy_cache
*.pytest_cache
# hypothesis test database
.hypothesis/
__pycache__

# OS generated files #
######################
.directory
.gdb_history
.DS_Store
ehthumbs.db
Icon?
Thumbs.db

# Data files #
##############
*.dta
*.xpt
*.h5


# Generated Sources #
#####################
*.c
*.cpp

# Unit / Performance Testing #
##############################
test

# Documentation generated files #
#################################
API.MD
*.html
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# dssvue
Python based Graphical User Interface (GUI) for HEC-DSS
About dssvue
===
Graphical User Interface for [HEC-DSS](http://www.hec.usace.army.mil/software/hec-dssvue/) database file.

Usage
===
```
from dssvue.main import show
show(dss_file_path)
```

Dependencies
===

- [pydsstools](https://github.com/gyanz/pydsstools)
- [pyqt5](https://pypi.org/project/PyQt5/)
- [pyqtgraph](https://github.com/pyqtgraph/pyqtgraph)
- [NumPy](https://www.numpy.org)
- [pandas](https://pandas.pydata.org/)

Installation
===
```
python setup.py install
or
pip install https://github.com/gyanz/dssvue/zipball/master
```

Contributing
===
All contributions, bug reports, bug fixes, documentation improvements, enhancements and ideas are welcome.
Feel free to ask questions on my [email](mailto:gyanBasyalz@gmail.com).

License
===
This program is a free software: you can modify and/or redistribute it under [MIT](LICENSE) license.
Empty file added dssvue/__init__.py
Empty file.
200 changes: 200 additions & 0 deletions dssvue/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import logging
import sys
import os
from datetime import datetime
import numpy as np
import pandas as pd
from .mplqt import *
from .models import CustomTableView,PathDataModel,create_toc_data,PairedDataWindow,MplPlotWindow
from pydsstools.heclib.dss.HecDss import Open
from pydsstools.core import DssPathName

ui_dir = os.path.join(os.path.dirname(__file__),'ui')

class DSSVue(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi(os.path.join(os.path.dirname(__file__),'ui','main.ui'),self)
self.setWindowTitle('dssvue')
self.add_gui_elements()
self.init_toc()
self.set_variables()
self.add_actions()

def add_gui_elements(self):
pass

def set_variables(self):
self.dss_fid = None

def add_actions(self):
self.reset_row_action = self.createAction('Reset Rows',self.reset_rows,None,
'','',None)
self.excel_action = self.createAction('Open in Excel',self.show_excel,None,
'excel.ico','',None)
self.table_action = self.createAction('Show table',self.show_table,None,
'table.ico','',None)
self.plot_action = self.createAction('Show Plot',self.show_plot,None,
'plot.ico','',None)
self.toolbar = self.addToolBar('Ribbon')
self.toolbar.addAction(self.reset_row_action)
self.toolbar.addAction(self.excel_action)
self.toolbar.addAction(self.table_action)
self.toolbar.addAction(self.plot_action)

def createAction(self, text, slot=None, shortcut=None, icon=None,
tip=None, checkable=None, signal="triggered"):
action = QAction(text, self)
if icon is not None:
pass
action.setIcon(QIcon(QtGui.QPixmap(os.path.join(ui_dir,icon))))
if shortcut is not None:
action.setShortcut(shortcut)
if tip is not None:
action.setToolTip(tip)
action.setStatusTip(tip)
if slot is not None:
getattr(action,signal).connect(slot)
if checkable is not None:
action.setCheckable(True)
return action

def show_excel(self):
try:
file_prefix = os.path.join(tempfile.gettempdir(),'dssvue')
file_suffix = str(uuid1()) + '.xlsx'
filename = file_prefix + file_suffix
df = self.toc_tv.model().getData()
writer = pd.ExcelWriter(filename, engine='xlsxwriter')
df.to_excel(writer,sheet_name='Sheet1')
writer.save()
open_file(filename)
except:
logging.warn('Error opening data in excel.')

def selected(self):
index = self.toc_tv.currentIndex()
pathname = self.toc_tv.model().get_pathname(index)
typ = self.toc_tv.model().get_type(index)
print(pathname)
print(typ)
return typ,pathname

def show_table(self):
typ, pathname = self.selected()
if typ == 'TS':
ts = self.dss_fid.read_ts(pathname)
if not ts.empty:
times = np.array(ts.pytimes)
times = times[~ts.nodata]
times = times.tolist()
values = ts.values[~ts.nodata].tolist()
data = [xy for xy in zip(times,values)]
data = np.array(data,dtype=[('Date',object),('Value',float)])
win = QtGui.QMainWindow(self)
win.setWindowTitle('Time Series')
t = pg.TableWidget()
win.setCentralWidget(t)
t.setData(data)
win.resize(500,500)
win.show()

elif typ == 'PD':
df = self.dss_fid.read_pd(pathname)
idx = df.index.tolist()
df.insert(0,df.index.name,idx)
df.index = range(1,df.shape[0] + 1)
win = PairedDataWindow(df,parent=self)
win.show()

elif typ == 'GRID':
pass

else:
pass

def show_plot(self):
typ, pathname = self.selected()
if typ == 'TS':
ts = self.dss_fid.read_ts(pathname)
if not ts.empty:
times = np.array(ts.pytimes)
times = times[~ts.nodata].tolist()
values = ts.values[~ts.nodata].tolist()
win = MplPlotWindow(times,values,pathname,self)
win.show()

elif typ == 'PD':
pass

elif typ == 'GRID':
dataset = self.dss_fid.read_grid(pathname)
data = dataset.read(masked=True)
pg.image(data,title=pathname)

else:
pass

def reset_rows(self):
self.toc_tv.model().reset_rows()

def init_toc(self):
df = create_toc_data(None)
self.toc_tv = CustomTableView()
self.toc_tv.setSortingEnabled(True)
model = PathDataModel(df)
self.toc_tv.setModel(model)
self.setCentralWidget(self.toc_tv)

def open_dss(self,dss_file):
if not self.dss_fid is None:
self.dss_fid.close()
self.dss_fid = Open(dss_file)
self._load_pathnames()

def _load_pathnames(self,condense=True):
if isinstance(self.dss_fid,Open):
path_list = []
path_dict = self.dss_fid.getPathnameDict()
print(path_dict)
for typ,paths in path_dict.items():
for path in paths:
pathobj = DssPathName(path)
parts = [typ] + pathobj.getParts()
path_list.append(parts)
df = create_toc_data(path_list)
if condense:
df = self._condense_pathnames(df)
self.toc_tv.model().set_data(df)

def _condense_pathnames(self,df):
ts_df = df[df.Type == 'TS']
ts_parts = []
for _,ts in ts_df.groupby(by=["A","B","C","E","F"]):
d_parts = [datetime.strptime(x,'%d%b%Y') for x in ts.D.tolist()]
_min = min(d_parts).strftime('%d%b%Y')
_max = max(d_parts).strftime('%d%b%Y')
d_part = '%s - %s'%(_min,_max)
parts = ['TS',
ts.A.iloc[0],
ts.B.iloc[0],
ts.C.iloc[0],
d_part,
ts.E.iloc[0],
ts.F.iloc[0]]
ts_parts.append(parts)

ts_df = create_toc_data(ts_parts)
rest_df = df[df.Type != 'TS']
df = pd.concat([ts_df,rest_df],ignore_index=True)
return df

def show(dss_file):
APP = mkQApp()
window = DSSVue()
window.open_dss(dss_file)
window.show()
APP.exec_()

if __name__ == "__main__":
pass
Loading

0 comments on commit 7c56c06

Please sign in to comment.