Пример #1
0
    def currentIndexChanged(self):

        self.commitData.emit(self.sender())
        #if a type from the components table was just set then fill in the component name unless it is already named
        if (self.name == 'component_type') & (self.parent.objectName()
                                              == 'components'):
            #get the table view object
            tv = self.parent
            #combo is the combo box that is sending these data
            combo = self.sender()
            #current row
            currentRow = tv.indexAt(combo.pos()).row()

            #check if there is already a component name
            currentName = tv.model().data(tv.model().index(currentRow, 4))
            if (currentName
                    == '') | (currentName is None) | (currentName == 'NA') | (
                        currentName[0:3] != self.sender().currentText()):
                #get the number of components of this type -
                handler = ProjectSQLiteHandler()
                i = handler.getTypeCount(self.sender().currentText())
                name = self.sender().currentText() + str(i)
                tv.model().setData(tv.model().index(currentRow, 4), name)
                tv.model().submitAll()
                tv.model().select()
                handler.closeDatabase()
            return
Пример #2
0
    def fillSetInfo(self, set='default'):

        databaseHandler = ProjectSQLiteHandler()
        # dictionary of set info
        setInfo = databaseHandler.getSetInfo(set)
        databaseHandler.closeDatabase()
        if type(setInfo['component_names']) == str:
            self.componentDefault = setInfo['component_names'].split(',')
        else:
            self.componentDefault = setInfo['component_names']
        start = datetime.datetime.strptime(setInfo['min_date'], '%Y-%m-%d')
        end = datetime.datetime.strptime(setInfo['max_date'], '%Y-%m-%d')

        #dates are strings here but they need to be datetimes
        self.startDate = setInfo.get('date_start')
        self.endDate = setInfo.get('date_end')
        self.getDefaultDates(start=self.startDate, end=self.endDate)
        #fillSetInfo the widget values

        self.setDateSelectorProperties(
            self.findChild(QtWidgets.QDateEdit, 'startDate'))
        self.setDateSelectorProperties(
            self.findChild(QtWidgets.QDateEdit, 'endDate'), False)
        self.findChild(QtWidgets.QDateEdit,
                       'startDate').setDateRange(start, end)
        self.findChild(QtWidgets.QDateEdit, 'endDate').setDateRange(start, end)
        self.findChild(QtWidgets.QLineEdit, 'componentNames').setText(','.join(
            self.componentDefault))
        self.updateComponentDelegate(self.componentDefault)

        return
Пример #3
0
    def getDefaultDates(self, **kwargs):
        #tuples
        start = kwargs.get('start')
        end = kwargs.get('end')

        handler = ProjectSQLiteHandler()
        if start == None:
            start = handler.cursor.execute(
                "select date_start from setup where set_name = 'default'"
            ).fetchone()
        if end == None:
            end = handler.cursor.execute(
                "select date_end from setup where set_name = 'default'"
            ).fetchone()
        handler.closeDatabase()

        #format the tuples from database output to datetime objects
        if type(start) == str:
            start = datetime.datetime.strptime(start, '%Y-%m-%d')
            end = datetime.datetime.strptime(end, '%Y-%m-%d')
        else:
            start = datetime.datetime.strptime(start[0], '%Y-%m-%d')
            end = datetime.datetime.strptime(end[0], '%Y-%m-%d')
        self.startDate = start
        self.endDate = end
        return
Пример #4
0
        def makeComponentList():
            import pandas as pd

            sqlhandler = ProjectSQLiteHandler('project_manager')
            components = pd.read_sql_query(
                "select component_name from components", sqlhandler.connection)

            components = list(components['component_name'])
            sqlhandler.closeDatabase()
            return components
Пример #5
0
    def updateValues(self):
        #find the data input grid
        myGrid = self.findChild(QtWidgets.QWidget, 'inputGrid')
        #get a soup of values that have changed
        newSoup, changes = update(myGrid)

        #TODO something with new soup and changes
        #should this be written to an xml file for optimizer input?
        #write changes to the database
        dbHandler = ProjectSQLiteHandler()
        for k in changes.keys():
            #if we return false upldate the existing parameter
            if not dbHandler.insertRecord('optimize_input',
                                          ['parameter', 'parameter_value'],
                                          [k, changes[k]]):
                dbHandler.updateRecord('optimize_input', ['parameter'], [k],
                                       ['parameter_value'], [changes[k]])
        return
Пример #6
0
def clearProjectDatabase(caller=None):
    handler = ProjectSQLiteHandler()
    # get the name of the last project worked on
    lastProjectPath = handler.getProjectPath()
    handler.makeDatabase()
    print(handler.dataCheck('components'))
    handler.closeDatabase()
    #the forms need to be cleared or data will get re-written to database
    if caller is not None:
        clearAppForms(caller)
    return lastProjectPath
Пример #7
0
    def createFileTab(self):
        self.dbhandler = ProjectSQLiteHandler()
        windowLayout = QtWidgets.QVBoxLayout()
        self.createTopBlock('Setup', self.assignFileBlock)
        l = self.FileBlock.findChild(QtWidgets.QWidget, 'inputFileDirvalue')
        l.clicked.connect(self.lineclicked)
        windowLayout.addWidget(self.FileBlock)

        self.createTableBlock('Components', 'components',
                              self.assignComponentBlock)

        windowLayout.addWidget(self.componentBlock)

        # the bottom block is disabled until a setup file is created or loaded
        self.createTableBlock('Environment Data', 'environment',
                              self.assignEnvironmentBlock)

        windowLayout.addWidget(self.environmentBlock)
        return windowLayout
Пример #8
0
def updateSetsSql(set, setupModel):
    uihandler = UIToHandler()
    xmlfile =  setupModel.getSetAttributeXML(set)
    soup = uihandler.getSetAttributeXML(xmlfile)
    setupTags = soup.findChild('setupTag')['value'].split(' ')
    setupValue = soup.findChild('setupValue')['value'].split(' ')
    if setupValue[setupTags.index("runTimeSteps")].split(',') != 'all':
        start = integerToTimeIndex(setupModel.data.fixed, setupValue[setupTags.index("runTimeSteps")].split(',')[0])
        end = integerToTimeIndex(setupModel.data.fixed, setupValue[setupTags.index("runTimeSteps")].split(',')[1])
    else:
        start = ''
        end = ''
    timestep = setupValue[setupTags.index("timeStep")]
    components = setupValue[setupTags.index("componentNames")]
    updateTuple = (start, end, timestep, components,  set)
    # check if the setup information exists in the database
    sqlHandler = ProjectSQLiteHandler()
    dataTuple = sqlHandler.cursor.execute("select date_start, date_end, timestep, component_names, _id from setup where set_name = '" + set + "'").fetchone()
    # update setup table database columns with xml attribute information if it exists otherwise create a record
    if dataTuple is not None:
        #update

        sqlHandler.cursor.execute("UPDATE setup set date_start = ?, date_end = ?, timestep = ?,component_names = ? where set_name = ?", updateTuple)
    else:
        #insert
        sqlHandler.cursor.execute(
            "INSERT INTO setup (date_start, date_end, timestep, component_names, set_name) Values(?,?,?,?,?) ", updateTuple)

    # update the set table also
    compNames = soup.findChild('compName')['value'].split(' ')
    compTags = soup.findChild('compTag')['value'].split(' ')
    compAttrs = soup.findChild('compAttr')['value'].split(' ')
    compValues = soup.findChild('compValue')['value'].split(' ')
    for i,c in enumerate(compNames):
        dataTuple = (set,c,compTags[i],compValues[i])
        #this will result in a new row if a value has changed directly in the xml but not in the project database
        if len(sqlHandler.cursor.execute("SELECT * from sets where set_name = ? AND component = ? AND change_tag = ? AND to_value = ?", dataTuple).fetchall()) < 1:
            sqlHandler.cursor.execute("INSERT INTO sets (set_name, component, change_tag, to_value) VALUES (?,?,?,?)", dataTuple)

    sqlHandler.connection.commit()
    sqlHandler.closeDatabase()

    return
Пример #9
0
    def createInputFiles(self):
        import os
        self.addProgressBar()
        self.progress.setRange(0, 0)
        self.sendSetupData()
        # check all the required fields are filled
        dbhandler = ProjectSQLiteHandler()
        if not dbhandler.dataComplete():
            #if required fields are not filled in return to setup page.
            msg = QtWidgets.QMessageBox(
                QtWidgets.QMessageBox.Warning, "Missing Required Fields",
                "Please fill in all required fields before generating input files."
            )
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msg.exec()
            dbhandler.closeDatabase()
            return

        dbhandler.closeDatabase()
        # write all the xml files

        # start with the setupxml
        self.model.writeNewXML()

        # import datafiles
        handler = UIToHandler()
        cleaned_data, components = handler.loadFixData(
            os.path.join(model.setupFolder, model.project + 'Setup.xml'))
        self.updateModelPage(cleaned_data)
        # pickled data to be used later if needed
        handler.storeData(
            cleaned_data,
            os.path.join(model.setupFolder, model.project + 'Setup.xml'))
        handler.storeComponents(
            components,
            os.path.join(model.setupFolder, model.project + 'Setup.xml'))
        self.dataLoaded.setText('data loaded')
        self.progress.setRange(0, 1)
        # generate netcdf files
        msg = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning,
                                    "Time Series loaded",
                                    "Do you want to generate netcdf files?.")
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok
                               | QtWidgets.QMessageBox.Cancel)
        result = msg.exec()

        # if yes create netcdf files, Otherwise this can be done after the data is reviewed.
        if result == QtWidgets.QMessageBox.Ok:
            d = {}
            for c in components:
                d[c.column_name] = c.toDictionary()
            handler.createNetCDF(
                cleaned_data.fixed, d,
                os.path.join(model.setupFolder, model.project + 'Setup.xml'))

        return
Пример #10
0
def makeAttributeXML(currentSet, compmodel):
    from UserInterface.ProjectSQLiteHandler import ProjectSQLiteHandler
    from PyQt5 import QtWidgets
    soup = readTemplateAttributeXML()

    #fillSetInfo the soup to reflect the model
    #for each row in model
    compName = ''
    compTag = ''
    compAttr = ''
    compValue = ''
    for i in range(compmodel.rowCount()):
        compName = ' '.join([compName, compmodel.data(compmodel.index(i, 2))])
        compTag = ' '.join([
            compTag,
            '.'.join(compmodel.data(compmodel.index(i, 3)).split('.')[:-1])
        ])
        compAttr = ' '.join(
            [compAttr,
             compmodel.data(compmodel.index(i, 3)).split('.')[-1]])
        compValue = ' '.join(
            [compValue, compmodel.data(compmodel.index(i, 4))])

    tag = soup.find('compName')
    tag.attrs['value'] = compName.lstrip()
    tag = soup.find('compTag')
    tag.attrs['value'] = compTag.lstrip()
    tag = soup.find('compAttr')
    tag.attrs['value'] = compAttr.lstrip()
    tag = soup.find('compValue')
    tag.attrs['value'] = compValue.lstrip()

    #fillSetInfo the set information
    handler = ProjectSQLiteHandler()
    dataTuple = handler.cursor.execute(
        "SELECT set_name, date_start, date_end, timestep, component_names from setup where set_name = '"
        + currentSet.lower() + "'").fetchone()

    tag = soup.find('setupTag')
    tag.attrs['value'] = "componentNames runTimeSteps timeStep"
    tag = soup.find('setupAttr')
    tag.attrs['value'] = "value value value"
    tag = soup.find('setupValue')
    df = compmodel.parent().window().findChild(QtWidgets.QWidget,
                                               'setupDialog').model.data.fixed
    tag.attrs['value'] = " ".join([
        dataTuple[4],
        timeStepsToInteger(dataTuple[1], dataTuple[2], df),
        str(dataTuple[3])
    ])

    return soup
Пример #11
0
    def componentCellClicked(self):
        from UserInterface.DialogComponentList import ComponentSetListForm
        from UserInterface.ProjectSQLiteHandler import ProjectSQLiteHandler

        import pandas as pd
        handler = ProjectSQLiteHandler('project_manager')

        # get the cell, and open a listbox of possible components for this project
        checked = pd.read_sql_query("select component_name from components",
                                    handler.connection)

        checked = list(checked['component_name'])
        handler.closeDatabase()
        # checked is a comma seperated string but we need a list
        #checked = checked.split(',')
        listDialog = ComponentSetListForm(checked)
        components = listDialog.checkedItems()
        # format the list to be inserted into a text field in a datatable
        str1 = ','.join(components)
        widg = self.findChild(QtWidgets.QLineEdit, 'componentNames')
        widg.setText(str1)
        self.updateComponentDelegate(components)
Пример #12
0
    def makeListWidget(self):
        import pandas as pd
        from UserInterface.ProjectSQLiteHandler import ProjectSQLiteHandler
        sqlhandler = ProjectSQLiteHandler('project_manager')
        self.components = pd.read_sql_query(
            "select component_name from components", sqlhandler.connection)

        self.components = list(self.components['component_name'])
        checked = [x in self.checked for x in self.components]
        sqlhandler.closeDatabase()
        listWidget = QtWidgets.QListWidget()
        for i in range(len(self.components)):
            item = QtWidgets.QListWidgetItem(self.components[i])
            item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
            if checked[i]:
                item.setCheckState(QtCore.Qt.Checked)
            else:
                item.setCheckState(QtCore.Qt.unchecked)
            listWidget.addItem(item)

        listWidget.itemClicked.connect(self.on_listWidget_itemClicked)
        return listWidget
Пример #13
0
    def runSet(self):
        # currentSet
        currentSet = self.set
        #set info needs to be updated in the database
        setInfo = (currentSet, self.findChild(QtWidgets.QDateEdit,
                                              'startDate').text(),
                   self.findChild(QtWidgets.QDateEdit, 'endDate').text(),
                   self.findChild(QtWidgets.QLineEdit, 'timestep').text(),
                   self.findChild(QtWidgets.QLineEdit,
                                  'componentNames').text())
        sqlhandler = ProjectSQLiteHandler()
        try:
            sqlhandler.cursor.execute(
                "INSERT INTO setup(set_name, date_start, date_end, timestep, component_names) VALUES(?,?,?,?,?)",
                setInfo)
        except:
            sqlhandler.cursor.execute(
                "UPDATE setup set date_start = ?, date_end=?, timestep=?, component_names=? WHERE set_name = '"
                + setInfo[0] + "'", setInfo[1:])
        sqlhandler.connection.commit()
        sqlhandler.closeDatabase()
        uihandler = UIToHandler()

        # component table is the table associated with the button
        componentTable = self.findChild(SetTableView).model()
        if componentTable.rowCount() > 0:

            uihandler.runModels(
                currentSet, componentTable,
                self.window().findChild(QtWidgets.QWidget,
                                        'setupDialog').model)
        else:
            msg = QtWidgets.QMessageBox(
                QtWidgets.QMessageBox.Warning, "Add components",
                "You need to select component attributes to alter before running sets."
            )
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msg.exec()
Пример #14
0
def replaceDefaultDatabase(projectdb):
    from UserInterface.ProjectSQLiteHandler import ProjectSQLiteHandler
    import pandas as pd
    tables = ['environment', 'components', 'sets', 'runs']
    for t in tables:
        h = ProjectSQLiteHandler(projectdb)
        # project data becomes a dataframe
        try:
            projectTable = pd.read_sql_query("select * from " + t,
                                             h.connection)
            h.closeDatabase()
            # the _id field is always the index for all tables
            projectTable.set_index(projectTable['_id'])
            projectTable = projectTable.drop('_id', 1)
            projectTable.index.names = ['_id']
            # connect to the active database and overwrite the table
            h = ProjectSQLiteHandler('project_manager')
            #data gets appended into empty tables created in default database
            projectTable.to_sql(t, h.connection, if_exists='append')
            h.closeDatabase()
        except:
            #TODO print some message to the console
            h.closeDatabase()
Пример #15
0
class FileBlock(QtWidgets.QGroupBox):
    def __init__(self, parent, input):
        super().__init__(parent)
        #integer -> FileBlock
        self.init(input)

    # creates a single form for entering individual file type information
    def init(self, input):
        self.input = input
        windowLayout = self.createFileTab()
        self.setLayout(windowLayout)
        self.model = self.window().findChild(QtWidgets.QWidget,
                                             'setupDialog').model
        self.setFocusPolicy(QtCore.Qt.StrongFocus)

    # -> QVBoxLayout
    def createFileTab(self):
        self.dbhandler = ProjectSQLiteHandler()
        windowLayout = QtWidgets.QVBoxLayout()
        self.createTopBlock('Setup', self.assignFileBlock)
        l = self.FileBlock.findChild(QtWidgets.QWidget, 'inputFileDirvalue')
        l.clicked.connect(self.lineclicked)
        windowLayout.addWidget(self.FileBlock)

        self.createTableBlock('Components', 'components',
                              self.assignComponentBlock)

        windowLayout.addWidget(self.componentBlock)

        # the bottom block is disabled until a setup file is created or loaded
        self.createTableBlock('Environment Data', 'environment',
                              self.assignEnvironmentBlock)

        windowLayout.addWidget(self.environmentBlock)
        return windowLayout

        # creates a horizontal layout containing gridlayouts for data input
    @QtCore.pyqtSlot()
    def lineclicked(self):
        '''opens a folder dialog and returns the string value of the pathway selected'''
        #if the directory has already been set then open the dialog to there otherwise default to current working directory
        curdir = self.findChild(QtWidgets.QWidget, 'inputFileDirvalue').text()
        if curdir == '':
            curdir = os.getcwd()
        folderDialog = QtWidgets.QFileDialog.getExistingDirectory(
            None, 'Select a directory.', curdir)
        if (folderDialog != ''):
            #once selected folderDialog gets set to the input box
            self.findChild(QtWidgets.QWidget,
                           'inputFileDirvalue').setText(folderDialog)
            #save the input to the setup data model and into the database
            self.saveInput()
            #update the filedir path
            if self.dbhandler.getInputPath(str(self.input)) is None:
                self.dbhandler.insertRecord('input_files',
                                            ['inputfiledirvalue'],
                                            [folderDialog])
            else:
                self.dbhandler.updateRecord('input_files', ['_id'],
                                            [str(self.input)],
                                            ['inputfiledirvalue'],
                                            [folderDialog])

            #filter the component and environemnt input tables to the current input directory
            self.filterTables()
            self.saveInput()
            self.model.writeNewXML()
        return folderDialog

    def createTopBlock(self, title, fn):
        '''The top block is where file information is set (format, date and time channels and file type)
        :param title: [String]
        :param fn: [method] used to assign the layout to a property'''

        # create a horizontal grouping to contain the top portion of the form
        gb = QtWidgets.QGroupBox(title)
        hlayout = QtWidgets.QHBoxLayout()
        hlayout.setObjectName("setup")

        # add the setup grids
        g1 = {
            'headers': [1, 2, 3, 4],
            'rowNames': [1, 2, 3, 4],
            'columnWidths': [1, 1, 1, 3],
            1: {
                1: {
                    'widget': 'lbl',
                    'name': 'File Type:',
                    'default': 'File Type'
                },
                2: {
                    'widget': 'combo',
                    'name': 'inputFileTypevalue',
                    'items': ['csv', 'MET']
                },
                3: {
                    'widget': 'lbl',
                    'name': 'File Directory',
                    'default': 'Directory'
                },
                4: {
                    'widget': 'lncl',
                    'name': 'inputFileDirvalue'
                }
            },
            2: {
                1: {
                    'widget': 'lbl',
                    'name': 'Date Channel',
                    'default': 'Date Channel'
                },
                2: {
                    'widget': 'txt',
                    'name': 'dateChannelvalue'
                },
                3: {
                    'widget': 'lbl',
                    'name': 'Date Format',
                    'default': 'Date Format'
                },
                4: {
                    'widget':
                    'combo',
                    'items': [
                        'mm/dd/yy', 'mon-dd YYYY', 'mm/dd/YYYY', 'mm-dd-YYYY',
                        'dd/mm/YYYY'
                    ],
                    'name':
                    'dateChannelformat'
                }
            },
            3: {
                1: {
                    'widget': 'lbl',
                    'name': 'Time Channel',
                    'default': 'Time Channel'
                },
                2: {
                    'widget': 'txt',
                    'name': 'timeChannelvalue'
                },
                3: {
                    'widget': 'lbl',
                    'name': 'Time Format',
                    'default': 'Time Format'
                },
                4: {
                    'widget': 'combo',
                    'items': ['HH:MM:SS'],
                    'name': 'timeChannelformat'
                }
            },
            4: {
                1: {
                    'widget': 'lbl',
                    'name': 'Time Zone',
                    'default': 'Time Zone'
                },
                2: {
                    'widget': 'combo',
                    'items': pytz.all_timezones,
                    'name': 'timeZonevalue',
                    'default': 'America/Anchorage'
                },
                3: {
                    'widget': 'lbl',
                    'name': 'Use DST',
                    'default': 'Use DST'
                },
                4: {
                    'widget': 'chk',
                    'name': 'useDSTvalue',
                    'default': False
                }
            }
        }

        grid = setupGrid(g1)
        hlayout.addLayout(grid)
        hlayout.addStretch(1)
        gb.setLayout(hlayout)
        fn(gb)

    # layout for tables
    def createTableBlock(self, title, table, fn):

        gb = QtWidgets.QGroupBox(title)

        tableGroup = QtWidgets.QVBoxLayout()
        tableGroup.addWidget(self.dataButtons(table))
        if table == 'components':

            tv = T.ComponentTableView(self)
            tv.setObjectName('components')
            m = T.ComponentTableModel(self)

            tv.hideColumn(1)
            tv.setModel(m)
            tv.hideColumn(0)

            tableGroup.addWidget(tv, 1)
        else:
            tv = E.EnvironmentTableView(self)
            tv.setObjectName('environment')
            m = E.EnvironmentTableModel(self)

            tv.setModel(m)
            tv.hideColumn(0)
            tableGroup.addWidget(tv, 1)
        self.filterTables()
        gb.setLayout(tableGroup)
        gb.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                         QtWidgets.QSizePolicy.Expanding)
        fn(gb)
        return

    # Load an existing descriptor file and populate the component table
    # -> None
    def functionForLoadDescriptor(self):

        msg = QtWidgets.QMessageBox(
            QtWidgets.QMessageBox.Warning, 'Load Descriptor',
            'If the component descriptor file you are loading has the same name as an existing component it will not load'
        )
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msg.exec()

        tableView = self.findChild((QtWidgets.QTableView), 'components')
        model = tableView.model()
        # identify the xml
        descriptorFile = QtWidgets.QFileDialog.getOpenFileName(
            self, "Select a descriptor file", None, "*xml")
        if (descriptorFile == ('', '')) | (descriptorFile is None):
            return

        fieldName, ok = QtWidgets.QInputDialog.getText(
            self, 'Field Name',
            'Enter the name of the channel that contains data for this component.'
        )
        # if a field was entered add it to the table model and database
        if ok:
            record = model.record()
            record.setValue('original_field_name', fieldName)

            handler = UIToHandler()
            record = handler.copyDescriptor(descriptorFile[0],
                                            self.model.componentFolder, record)

            # add a row into the database
            model.insertRowIntoTable(record)
            # refresh the table
            model.select()
        return

    # Add an empty record to the specified datatable
    # String -> None
    def functionForNewRecord(self, table):
        # add an empty record to the table
        handler = TableHandler(self)
        filedir = self.FileBlock.findChild(QtWidgets.QWidget,
                                           'inputFileDirvalue').text()
        handler.functionForNewRecord(table, fields=[1], values=[filedir])

    # delete the selected record from the specified datatable
    # String -> None
    def functionForDeleteRecord(self, table):

        # get selected rows
        tableView = self.findChild((QtWidgets.QTableView), table)
        model = tableView.model()
        # selected is the indices of the selected rows
        selected = tableView.selectionModel().selection().indexes()
        if len(selected) == 0:
            msg = QtWidgets.QMessageBox(
                QtWidgets.QMessageBox.Warning, 'Select Rows',
                'Select rows before attempting to delete')
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msg.exec()
        else:
            msg = QtWidgets.QMessageBox(
                QtWidgets.QMessageBox.Warning, 'Confirm Delete',
                'Are you sure you want to delete the selected records?')
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok
                                   | QtWidgets.QMessageBox.Cancel)

            result = msg.exec()

            if result == QtWidgets.QMessageBox.Ok:
                handler = UIToHandler()
                removedRows = []
                for r in selected:
                    if r.row() not in removedRows:
                        if table == 'components':
                            # remove the xml files too
                            handler.removeDescriptor(
                                model.data(model.index(r.row(), 3)),
                                self.model.componentFolder)
                        removedRows.append(r.row())
                        model.removeRows(r.row(), 1)

                # Delete the record from the database and refresh the tableview
                model.submitAll()
                model.select()

    # string -> QGroupbox
    def dataButtons(self, table):
        buttonBox = QtWidgets.QGroupBox()
        buttonRow = QtWidgets.QHBoxLayout()

        if table == 'components':
            buttonRow.addWidget(
                makeButtonBlock(
                    self, self.functionForLoadDescriptor, None,
                    'SP_DialogOpenButton',
                    'Load a previously created component xml file.'))

        buttonRow.addWidget(
            makeButtonBlock(self, lambda: self.functionForNewRecord(table),
                            '+', None, 'Add a component'))
        buttonRow.addWidget(
            makeButtonBlock(self, lambda: self.functionForDeleteRecord(table),
                            None, 'SP_TrashIcon', 'Delete a component'))
        buttonRow.addStretch(3)
        buttonBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                QtWidgets.QSizePolicy.Expanding)
        buttonBox.setLayout(buttonRow)
        return buttonBox

    # TODO this needs to change if its populating from a table
    # inserts data from the data model into corresponding boxes on the screen
    # SetupInfo -> None
    def fillData(self, model, i):

        # dictionary of attributes of the class SetupTag belonging to a SetupInformation Model
        d = model.getSetupTags()
        # for every key in d find the corresponding textbox or combo box
        for k in d.keys():
            #values in d are setup tags and can contain list values
            #each key in the setuptag has its own display slot on the form
            #this fills the topblock
            tag_keys = d[k].keys()
            for t in tag_keys:
                if t != 'name':
                    edit_field = self.findChild(
                        (QtWidgets.QLineEdit, QtWidgets.QComboBox), k + t)

                    if type(edit_field) is QtWidgets.QLineEdit:
                        if len(d[k][t]) > 0:
                            edit_field.setText(d[k][t][self.input - 1])
                    elif type(edit_field) is ClickableLineEdit:
                        if len(d[k][t]) > 0:
                            edit_field.setText(d[k][t][self.input - 1])
                    elif type(edit_field) is QtWidgets.QComboBox:
                        if len(d[k][t]) > 0:
                            edit_field.setCurrentIndex(
                                edit_field.findText(d[k][t][self.input - 1]))

        def getDefault(l, i):
            try:
                l[i]
                return l[i]
            except IndexError:
                return 'NA'

        # refresh the tables
        self.filterTables()

        return

    # Setters
    #(String, number, list or Object) ->
    def assignEnvironmentBlock(self, value):
        self.environmentBlock = value

    def assignComponentBlock(self, value):
        self.componentBlock = value

    def assignFileBlock(self, value):
        self.FileBlock = value
        self.FileBlock.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                     QtWidgets.QSizePolicy.Expanding)
        self.FileBlock.sizePolicy().retainSizeWhenHidden()
        self.FileBlock.setObjectName('fileInput')

    # if the fileblock looses focus update database information
    def focusOutEvent(self, event):

        if 'projectFolder' in self.model.__dict__.keys():
            #input to model
            self.saveInput()
            #input to database
            setupFields, setupValues = self.getSetupInfo()

            # update database table
            if not self.dbhandler.insertRecord('input_files', setupFields,
                                               setupValues):
                self.dbhandler.updateRecord('input_files', ['_id'],
                                            [str(setupValues[0])],
                                            setupFields[1:], setupValues[1:])
            # on leave save the xml files
            self.model.writeNewXML()
        return

    #reads data from an file input top block and returns a list of fields and values
    def getSetupInfo(self):
        fieldNames = ['_id']
        #values = [re.findall(r'\d+',self.input)[0]]
        values = [self.input]
        for child in self.FileBlock.findChildren(
            (QtWidgets.QLineEdit, QtWidgets.QComboBox)):

            if type(child) is QtWidgets.QLineEdit:
                fieldNames.append(child.objectName())
                values.append(child.text())
            elif type(child) is ClickableLineEdit:
                fieldNames.append(child.objectName())
                values.append(child.text())
            else:
                fieldNames.append(child.objectName())
                values.append(child.itemText(child.currentIndex()))

        return fieldNames, values

    #save the form input to the form setup data model
    def saveInput(self):

        #update model info from fileblock
        self.model.assignTimeChannel(SetupTag.assignValue,
                                     self.FileBlock.findChild(
                                         QtWidgets.QWidget,
                                         'timeChannelvalue').text(),
                                     position=int(self.input) - 1)
        self.model.assignTimeChannel(SetupTag.assignFormat,
                                     self.FileBlock.findChild(
                                         QtWidgets.QWidget,
                                         'timeChannelformat').currentText(),
                                     position=int(self.input) - 1)
        self.model.assignDateChannel(SetupTag.assignValue,
                                     self.FileBlock.findChild(
                                         QtWidgets.QWidget,
                                         'dateChannelvalue').text(),
                                     position=int(self.input) - 1)
        self.model.assignDateChannel(SetupTag.assignFormat,
                                     self.FileBlock.findChild(
                                         QtWidgets.QWidget,
                                         'dateChannelformat').currentText(),
                                     position=int(self.input) - 1)
        self.model.assignInputFileDir(SetupTag.assignValue,
                                      self.FileBlock.findChild(
                                          QtWidgets.QWidget,
                                          'inputFileDirvalue').text(),
                                      position=int(self.input) - 1)
        self.model.assignInputFileType(SetupTag.assignValue,
                                       self.FileBlock.findChild(
                                           QtWidgets.QWidget,
                                           'inputFileTypevalue').currentText(),
                                       position=int(self.input) - 1)
        self.model.assignTimeZone(SetupTag.assignValue,
                                  self.FileBlock.findChild(
                                      QtWidgets.QWidget,
                                      'timeZonevalue').currentText(),
                                  position=int(self.input) - 1)
        self.model.assignUseDST(SetupTag.assignValue,
                                str(
                                    self.FileBlock.findChild(
                                        QtWidgets.QWidget,
                                        'useDSTvalue').isChecked()),
                                position=int(self.input) - 1)

        self.saveTables()
        return

    # calls the specified function connected to a button onClick event
    @QtCore.pyqtSlot()
    def onClick(self, buttonFunction):
        buttonFunction()

    def filterTables(self):
        tables = self.findChildren(QtWidgets.QTableView)
        filedir = self.FileBlock.findChild(QtWidgets.QWidget,
                                           'inputFileDirvalue').text()
        self.filter = filedir
        for t in tables:
            m = t.model()
            m.setFilter("inputfiledir = '" + filedir + "'")

    def saveTables(self):
        '''get data from component and environment tables and update the setupInformation model
        components within a single directory are seperated with commas
        component info comes from the database not the tableview
        component names, units, scale, offset, attribute, fieldname get saved'''

        names = self.dbhandler.getComponentNames()
        names = list(set(names))
        self.model.assignComponentNames(SetupTag.assignValue, ' '.join(names))
        #df is a pandas dataframe  of component information
        df = self.dbhandler.getComponentsTable(self.filter)
        self.model.assignComponentName(
            SetupTag.assignValue, [','.join(df['component_name'].tolist())],
            position=int(self.input) - 1)
        self.model.assignHeaderName(
            SetupTag.assignValue,
            [','.join(df['original_field_name'].tolist())],
            position=int(self.input) - 1)
        self.model.assignComponentAttribute(SetupTag.assignValue, [
            ','.join([
                x if x is not None else 'NA' for x in df['attribute'].tolist()
            ])
        ],
                                            position=int(self.input) - 1)
        self.model.assignComponentAttribute(SetupTag.assignUnits, [
            ','.join(
                [x if x is not None else 'NA' for x in df['units'].tolist()])
        ],
                                            position=int(self.input) - 1)

        loC = [
            self.model.makeNewComponent(df['component_name'],
                                        x['original_field_name'], x['units'],
                                        x['attribute'], x['component_type'])
            for i, x in df.iterrows()
        ]
        return loC

    def close(self):
        if 'projectFolder' in self.model.__dict__.keys():
            #input to model
            self.saveInput()
            #input to database
            setupFields, setupValues = self.getSetupInfo()

            # update database table
            if not self.dbhandler.insertRecord('input_files', setupFields,
                                               setupValues):
                self.dbhandler.updateRecord('input_files', ['_id'],
                                            [setupFields[0]], setupFields[1:],
                                            setupValues[1:])
            self.saveTables()
            # on leave save the xml files
            self.model.writeNewXML()

        self.dbhandler.closeDatabase()
Пример #16
0
class FormSetup(QtWidgets.QWidget):
    global model
    model = ModelSetupInformation()

    def __init__(self, parent):
        super().__init__(parent)
        self.lastProjectPath = parent.lastProjectPath
        self.initUI()

    #initialize the form
    def initUI(self):
        self.dbHandler = ProjectSQLiteHandler()
        self.setObjectName("setupDialog")

        self.model = model

        #the main layout is oriented vertically
        windowLayout = QtWidgets.QVBoxLayout()

        # the top block is buttons to load setup xml and data files
        self.createButtonBlock()
        windowLayout.addWidget(self.ButtonBlock)
        self.tabs = Pages(self, '1', FileBlock)
        self.tabs.setDisabled(True)
        #each file type gets its own page to specify formats and headers to include
        # button to create a new set tab
        newTabButton = QtWidgets.QPushButton()
        newTabButton.setText(' + Input')
        newTabButton.setFixedWidth(100)
        newTabButton.clicked.connect(self.newTab)
        windowLayout.addWidget(newTabButton)

        windowLayout.addWidget(self.tabs, 3)

        #list of dictionaries containing information for wizard
        #this is the information that is not input file specific.

        dlist = [{
            'title': 'Dates to model',
            'prompt':
            'Enter the timespan you would like to include in the model.',
            'sqltable': None,
            'sqlfield': None,
            'reftable': None,
            'name': 'runTimesteps',
            'folder': False,
            'dates': True
        }, {
            'title': 'Timestep',
            'prompt': 'Enter desired timestep',
            'sqltable': None,
            'sqlfield': None,
            'reftable': 'ref_time_units',
            'name': 'timestep',
            'folder': False
        }, {
            'title': 'Project',
            'prompt': 'Enter the name of your project',
            'sqltable': None,
            'sqlfield': None,
            'reftable': None,
            'name': 'project',
            'folder': False
        }]

        self.WizardTree = self.buildWizardTree(dlist)
        self.createBottomButtonBlock()
        windowLayout.addWidget(self.BottomButtons)
        #set the main layout as the layout for the window

        self.setLayout(windowLayout)
        #title is setup
        self.setWindowTitle('Setup')
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)
        #show the form
        self.showMaximized()

    #FormSetup -> QWidgets.QHBoxLayout
    #creates a horizontal button layout to insert in FormSetup
    def createButtonBlock(self):
        self.ButtonBlock = QtWidgets.QGroupBox()
        hlayout = QtWidgets.QHBoxLayout()
        #layout object name
        hlayout.setObjectName('buttonLayout')
        #add the button to load a setup xml

        hlayout.addWidget(
            makeButtonBlock(self, self.functionForLoadButton,
                            'Load Existing Project', None,
                            'Load a previously created project files.'))

        #add button to launch the setup wizard for setting up the setup xml file
        hlayout.addWidget(
            makeButtonBlock(
                self, self.functionForCreateButton, 'Create setup XML', None,
                'Start the setup wizard to create a new setup file'))
        #force the buttons to the left side of the layout
        hlayout.addStretch(1)

        self.ButtonBlock.setLayout(hlayout)

        self.ButtonBlock.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                       QtWidgets.QSizePolicy.Expanding)
        projectTitlewdg = QtWidgets.QLabel()
        projectTitlewdg.setObjectName('projectTitle')
        hlayout.addWidget(projectTitlewdg)
        hlayout.addStretch(1)
        return hlayout

        # FormSetup -> QWidgets.QHBoxLayout
        # creates a horizontal button layout to insert in FormSetup
    def createBottomButtonBlock(self):
        self.BottomButtons = QtWidgets.QGroupBox()
        hlayout = QtWidgets.QHBoxLayout()
        # layout object name
        hlayout.setObjectName('buttonLayout')
        # add the button to load a setup xml
        button = QtWidgets.QPushButton('Create input files')
        button.setToolTip('Create input files to run models')
        button.clicked.connect(lambda: self.onClick(self.createInputFiles))
        button.setFixedWidth(200)
        # windowLayout.addWidget(makeButtonBlock(self,self.createInputFiles,'Create input files',None,'Create input files to run models'),3)
        hlayout.addWidget(button)
        dataLoaded = QtWidgets.QLineEdit()
        dataLoaded.setFrame(False)
        dataLoaded.setObjectName('dataloaded')
        dataLoaded.setText('No data loaded')
        dataLoaded.setFixedWidth(200)
        self.dataLoaded = dataLoaded
        hlayout.addWidget(self.dataLoaded)
        # generate netcd button
        netCDFButton = self.createSubmitButton()
        hlayout.addWidget(netCDFButton)
        button.setFixedWidth(200)
        self.netCDFsLoaded = QtWidgets.QLineEdit()
        self.netCDFsLoaded.setFrame(False)
        self.netCDFsLoaded.setText("none")
        hlayout.addWidget(self.netCDFsLoaded)
        #hlayout.addStretch(1)
        self.BottomButtons.setLayout(hlayout)

        return hlayout

    #method -> None
    #calls the specified function connected to a button onClick event
    @QtCore.pyqtSlot()
    def onClick(self, buttonFunction):
        buttonFunction()

    #FormSetup -> None
    #method to modify FormSetup content
    def functionForCreateButton(self):
        #if a project is already started save it before starting a new one
        if (self.model.project != '') & (self.model.project is not None):
            self.model = switchProject(self)
            global model
            model = self.model

        s = self.WizardTree
        s.exec_()
        handler = UIToHandler()
        handler.makeSetup(model)
        #display collected data
        #returns true if setup info has been entered
        hasSetup = model.feedSetupInfo()
        self.projectDatabase = False
        if hasSetup:
            #self.topBlock.setEnabled(True)
            #self.environmentBlock.setEnabled(True)
            #self.componentBlock.setEnabled(True)
            #enable the model and optimize pages too
            pages = self.window().findChild(QtWidgets.QTabWidget, 'pages')
            pages.enableTabs()
            self.tabs.setEnabled(True)
            self.findChild(QtWidgets.QLabel,
                           'projectTitle').setText(self.model.project)

    #searches for and loads existing project data - database, setupxml,descriptors, DataClass pickle, Component pickle netcdf,previously run model results, previous optimization results
    def functionForLoadButton(self):
        '''The load function reads the designated setup xml, looks for descriptor xmls,
        looks for an existing project database and a pickled data object.'''

        #if we were already working on a project its state gets saved and  new project is loaded
        if (self.model.project != '') & (self.model.project is not None):
            self.model = switchProject(self)
            global model
            model = self.model

        #launch file navigator to identify setup file
        setupFile = QtWidgets.QFileDialog.getOpenFileName(
            self, "Select your setup file", self.lastProjectPath, "*xml")
        if (setupFile == ('', '')) | (setupFile is None):
            return
        model.assignSetupFolder(setupFile[0])

        # assign setup information to data model
        model.feedSetupInfo()

        # now that setup data is set display it in the form
        self.displayModelData()

        #Look for an existing project database and replace the default one with it
        if os.path.exists(
                os.path.join(self.model.projectFolder, 'project_manager')):
            print('An existing project database was found for %s.' %
                  self.model.project)

            replaceDefaultDatabase(
                os.path.join(self.model.projectFolder, 'project_manager'))
            self.projectDatabase = True
        else:
            self.projectDatabase = False
            print('An existing project database was not found for %s.' %
                  self.model.project)

        # record the current project
        self.dbHandler.insertRecord('project', ['project_path'],
                                    [setupFile[0]])

        # look for an existing data pickle
        handler = UIToHandler()
        self.model.data = handler.loadInputData(
            os.path.join(self.model.setupFolder,
                         self.model.project + 'Setup.xml'))

        if self.model.data is not None:
            self.updateModelPage(self.model.data)
            self.dataLoaded.setText('data loaded')
            #refresh the plot
            resultDisplay = self.parent().findChild(ResultsSetup)
            resultDisplay.defaultPlot()

        #look for an existing component pickle or create one from information in setup xml
        self.model.components = handler.loadComponents(
            os.path.join(self.model.setupFolder,
                         self.model.project + 'Setup.xml'))
        if self.model.components is None:
            self.getComponentsFromSetup()

        #list netcdf files previously generated
        self.netCDFsLoaded.setText(', '.join(self.listNetCDFs()))
        #TODO this part of the code always sets setsRun to false, need to implement check for models run
        #boolean indicator of whether or not model sets have already been run
        setsRun = False
        #make the data blocks editable if there are no sets already created
        #if sets have been created then input data is not editable from the interface
        if setsRun:
            msg = QtWidgets.QMessageBox(
                QtWidgets.QMessageBox.Warning, "Analysis in Progress",
                "Analysis results were detected. You cannot edit input data after analysis has begun."
            )
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msg.exec()
        else:
            self.tabs.setEnabled(True)

            print('Loaded %s:' % model.project)

        #set the project name on the form
        self.findChild(QtWidgets.QLabel,
                       'projectTitle').setText(self.model.project)

        return

    #looks in the processed folder and lists nc files found
    #->ListOfStrings
    def listNetCDFs(self):
        lof = [
            f for f in os.listdir(
                getFilePath(self.model.setupFolder, 'Processed'))
            if f[-2] == 'nc'
        ]
        return lof

    def displayModelData(self):
        """creates a tab for each input directory specified the SetupModelInformation model inputFileDir attribute.
        Each tab contains a FileBlock object to interact with the data input
        Each FileBlock is filled with data specific to the input directory"""
        self.tabs.removeTab(0)
        #the number of directories listed in inputFileDir indicates how many tabs are required
        tab_count = len(self.model.inputFileDir.value)
        #if directories have been entered then replace the first tab and create a tab for each directory #TODO should remove all previous tabs
        if tab_count > 0:
            self.tabs.removeTab(0)
            for i in range(tab_count):
                self.newTab(i + 1)
        else:
            self.newTab(1)
        return

    #List -> WizardTree
    def buildWizardTree(self, dlist):
        """builds a QWizard based on list of inputs"""
        wiztree = QtWidgets.QWizard()
        wiztree.setWizardStyle(QtWidgets.QWizard.ModernStyle)
        wiztree.setWindowTitle("Setup")
        wiztree.addPage(WizardPage(dlist[2]))
        wiztree.addPage(TextWithDropDown(dlist[1]))
        wiztree.addPage(TwoDatesDialog(dlist[0]))
        btn = wiztree.button(QtWidgets.QWizard.FinishButton)
        btn.clicked.connect(self.saveInput)
        return wiztree

    #save the input in the wizard tree to the setup data model
    def saveInput(self):
        """save the input in the wizard tree to the ModelSetupInformation data model"""
        model = self.model
        model.assignProject(self.WizardTree.field('project'))
        model.assignTimeStep(SetupTag.assignValue,
                             self.WizardTree.field('timestep'))
        model.assignRunTimesteps(
            SetupTag.assignValue,
            self.WizardTree.field('sdate') + ' ' +
            self.WizardTree.field('edate'))
        return

    def sendSetupData(self):
        """ send input data to the ModelSetupInformation data model
        reads through all the file tabs to collect input
        """

        #needs to come from each page
        tabWidget = self.findChild(QtWidgets.QTabWidget)
        for t in range(tabWidget.count()):
            page = tabWidget.widget(t)
            # cycle through the input children in the topblock
            for child in page.FileBlock.findChildren(
                (QtWidgets.QLineEdit, QtWidgets.QComboBox)):

                if type(child) is QtWidgets.QLineEdit:
                    value = child.text()
                elif type(child) is ClickableLineEdit:
                    value = child.text()
                elif type(child) is QtWidgets.QComboBox:
                    value = child.itemText(child.currentIndex())
                #append to appropriate list
                attr = child.objectName()
                model.assign(attr, value, position=int(page.input) - 1)

            model.setComponents(page.saveTables())

            return

    #TODO this should be done on a seperate thread
    # Create a dataframe of input data based on importing files within each SetupModelInformation.inputFileDir
    # None->None
    def createInputFiles(self):
        import os
        self.addProgressBar()
        self.progress.setRange(0, 0)
        self.sendSetupData()
        # check all the required fields are filled
        dbhandler = ProjectSQLiteHandler()
        if not dbhandler.dataComplete():
            #if required fields are not filled in return to setup page.
            msg = QtWidgets.QMessageBox(
                QtWidgets.QMessageBox.Warning, "Missing Required Fields",
                "Please fill in all required fields before generating input files."
            )
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msg.exec()
            dbhandler.closeDatabase()
            return

        dbhandler.closeDatabase()
        # write all the xml files

        # start with the setupxml
        self.model.writeNewXML()

        # import datafiles
        handler = UIToHandler()
        cleaned_data, components = handler.loadFixData(
            os.path.join(model.setupFolder, model.project + 'Setup.xml'))
        self.updateModelPage(cleaned_data)
        # pickled data to be used later if needed
        handler.storeData(
            cleaned_data,
            os.path.join(model.setupFolder, model.project + 'Setup.xml'))
        handler.storeComponents(
            components,
            os.path.join(model.setupFolder, model.project + 'Setup.xml'))
        self.dataLoaded.setText('data loaded')
        self.progress.setRange(0, 1)
        # generate netcdf files
        msg = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning,
                                    "Time Series loaded",
                                    "Do you want to generate netcdf files?.")
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok
                               | QtWidgets.QMessageBox.Cancel)
        result = msg.exec()

        # if yes create netcdf files, Otherwise this can be done after the data is reviewed.
        if result == QtWidgets.QMessageBox.Ok:
            d = {}
            for c in components:
                d[c.column_name] = c.toDictionary()
            handler.createNetCDF(
                cleaned_data.fixed, d,
                os.path.join(model.setupFolder, model.project + 'Setup.xml'))

        return

    # DataClass with data frame called 'fixed' and field 'datetime'
    # updates default component list, time range and time step values in the setup table and passes these values to the modelDialog
    # DataClass -> None
    def updateModelPage(self, data):
        # start and end dates get set written to database as default date ranges
        import pandas as pd

        def getDefaults(listDf,
                        defaultStart=pd.to_datetime("1/1/1900").date(),
                        defaultEnd=pd.datetime.today().date()):
            if len(listDf) > 0:
                s = listDf[0].index[0].date()
                e = listDf[0].index[len(listDf[0]) - 1].date()

                if (s < defaultStart) & (e > defaultEnd):
                    return getDefaults(listDf[1:], s, e)
                elif s < defaultStart:
                    return getDefaults(listDf[1:], s, defaultEnd)
                elif e > defaultStart:
                    return getDefaults(listDf[1:], defaultStart, e)
            return str(defaultStart), str(defaultEnd)

        #default start is the first date there is record for
        defaultStart, defaultEnd = getDefaults(data.fixed)
        defaultComponents = ','.join(self.model.componentNames.value)

        #TODO this should be moved to the handler
        #TODO this should be moved to the handler
        self.dbHandler.cursor.execute(
            "UPDATE setup set date_start = ?, date_end = ?, component_names = ? where set_name = 'default'",
            [defaultStart, defaultEnd, defaultComponents])
        self.dbHandler.connection.commit()

        # Deliver appropriate info to the ModelForm
        modelForm = self.window().findChild(SetsTableBlock)
        # start and end are tuples at this point
        modelForm.makeSetInfo(start=defaultStart,
                              end=defaultEnd,
                              components=defaultComponents)

        #deliver the data to the ResultsSetup form so it can be plotted
        resultsForm = self.window().findChild(ResultsSetup)
        resultsForm.setPlotData(data)

    # close event is triggered when the form is closed
    def closeEvent(self, event):
        #save xmls
        if 'projectFolder' in self.model.__dict__.keys():
            self.sendSetupData()
            # on close save the xml files
            self.model.writeNewXML()
            self.dbHandler.closeDatabase
        #close the fileblocks
        for i in range(self.tabs.count()):
            page = self.tabs.widget(i)
            page.close()

    #TODO add progress bar for uploading raw data and generating fixed data pickle
    def addProgressBar(self):
        self.progress = QtWidgets.QProgressBar(self)
        self.progress.setObjectName('uploadBar')
        self.progress.setGeometry(100, 100, 100, 50)
        return self.progress

    # add a new file input tab
    def newTab(self, i=0):
        # get the set count
        tab_count = self.tabs.count() + 1
        widg = FileBlock(self, tab_count)
        #widg.fillSetInfo()
        self.tabs.addTab(widg, 'Input' + str(tab_count))
        #if its not the default empty tab fill data into form slots
        if i > 0:
            widg.fillData(self.model, i)

    # calls the specified function connected to a button onClick event
    @QtCore.pyqtSlot()
    def onClick(self, buttonFunction):
        buttonFunction()

# ->QPushButton

    def createSubmitButton(self):
        button = QtWidgets.QPushButton()
        button.setText("Generate netCDF inputs")
        button.clicked.connect(self.generateNetcdf)
        return button

    #uses the current data object to generate input netcdfs
    def generateNetcdf(self):

        handler = UIToHandler()
        #df gets read in from TimeSeries processed data folder
        #component dictionary comes from setupXML's
        MainWindow = self.window()
        setupForm = MainWindow.findChild(QtWidgets.QWidget, 'setupDialog')
        setupModel = setupForm.model
        if 'setupFolder' in setupModel.__dict__.keys():
            setupFile = os.path.join(setupModel.setupFolder,
                                     setupModel.project + 'Setup.xml')
            componentModel = setupForm.findChild(QtWidgets.QWidget,
                                                 'components').model()
            #From the setup file read the location of the input pickle
            #by replacing the current pickle with the loaded one the user can manually edit the input and
            #  then return to working with the interface
            data = handler.loadInputData(setupFile)
            if data:
                df = data.fixed
                componentDict = {}
                if 'components' not in setupModel.__dict__.keys():
                    #generate components
                    setupForm.makeComponentList(componentModel)
                for c in setupModel.components:
                    componentDict[c.column_name] = c.toDictionary()
                #filesCreated is a list of netcdf files that were generated
                filesCreated = handler.createNetCDF(df, componentDict,
                                                    setupModel.setupFolder)
                self.netCDFsLoaded.setText(', '.join(filesCreated))
            else:
                print("no data found")

    #generate a list of Component objects based on attributes specified ModelSetupInformation
    #
    def getComponentsFromSetup(self):
        for i, c in enumerate(self.model.componentName.value):
            self.model.makeNewComponent(c, self.model.headerName.value[i],
                                        self.model.componentAttribute.unit[i],
                                        self.model.componentAttribute.value[i],
                                        None)
Пример #17
0
    def initUI(self):
        self.dbHandler = ProjectSQLiteHandler()
        self.setObjectName("setupDialog")

        self.model = model

        #the main layout is oriented vertically
        windowLayout = QtWidgets.QVBoxLayout()

        # the top block is buttons to load setup xml and data files
        self.createButtonBlock()
        windowLayout.addWidget(self.ButtonBlock)
        self.tabs = Pages(self, '1', FileBlock)
        self.tabs.setDisabled(True)
        #each file type gets its own page to specify formats and headers to include
        # button to create a new set tab
        newTabButton = QtWidgets.QPushButton()
        newTabButton.setText(' + Input')
        newTabButton.setFixedWidth(100)
        newTabButton.clicked.connect(self.newTab)
        windowLayout.addWidget(newTabButton)

        windowLayout.addWidget(self.tabs, 3)

        #list of dictionaries containing information for wizard
        #this is the information that is not input file specific.

        dlist = [{
            'title': 'Dates to model',
            'prompt':
            'Enter the timespan you would like to include in the model.',
            'sqltable': None,
            'sqlfield': None,
            'reftable': None,
            'name': 'runTimesteps',
            'folder': False,
            'dates': True
        }, {
            'title': 'Timestep',
            'prompt': 'Enter desired timestep',
            'sqltable': None,
            'sqlfield': None,
            'reftable': 'ref_time_units',
            'name': 'timestep',
            'folder': False
        }, {
            'title': 'Project',
            'prompt': 'Enter the name of your project',
            'sqltable': None,
            'sqlfield': None,
            'reftable': None,
            'name': 'project',
            'folder': False
        }]

        self.WizardTree = self.buildWizardTree(dlist)
        self.createBottomButtonBlock()
        windowLayout.addWidget(self.BottomButtons)
        #set the main layout as the layout for the window

        self.setLayout(windowLayout)
        #title is setup
        self.setWindowTitle('Setup')
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)
        #show the form
        self.showMaximized()
Пример #18
0
 def getItems(self):
     dbHandler = ProjectSQLiteHandler()
     items = dbHandler.getCodes(self.d['reftable'])
     dbHandler.closeDatabase()
     return items