Ejemplo n.º 1
0
    def generateSamples(data,
                        selectedInputs,
                        selectedOutputs,
                        numSamples=None,
                        sampleMethod=-1):
        psuadeDataFile = os.getcwd() + os.path.sep + 'psuadeData'
        if os.path.exists(psuadeDataFile):
            os.remove(psuadeDataFile)

        # Create new SampleData object with only selected inputs and outputs
        newModel = Model()
        inputNames = numpy.array(data.getInputNames())
        newModel.setInputNames(inputNames[selectedInputs])
        outputNames = numpy.array(data.getOutputNames())
        newModel.setOutputNames(outputNames[selectedOutputs])
        newModel.setInputMins(data.getInputMins()[selectedInputs])
        newModel.setInputMaxs(data.getInputMaxs()[selectedInputs])
        newModel.setDriverName(data.getDriverName())
        if data.getInputDefaults() is not None:
            newModel.setInputDefaults(data.getInputDefaults()[selectedInputs])
        returnData = SampleData(newModel)

        if numSamples:
            returnData.setNumSamples(numSamples)
        else:
            returnData.setNumSamples(data.getNumSamples())

        if sampleMethod >= 0:
            returnData.setSampleMethod(sampleMethod)
        else:
            returnData.setSampleMethod(data.getSampleMethod())
        if returnData.getSampleMethod(
        ) == SamplingMethods.METIS and os.path.exists('psuadeMetisInfo'):
            os.remove('psuadeMetisInfo')

        distributions = data.getInputDistributions()
        pdfconvert = False
        for dist in distributions:
            distType = dist.getDistributionType()
            if returnData.getSampleMethod(
            ) != SamplingMethods.MC and distType not in [
                    Distribution.SAMPLE, Distribution.UNIFORM
            ]:
                pdfconvert = True
        returnData.setInputDistributions(distributions)

        curDir = os.getcwd()
        if platform.system() == 'Windows':
            import win32api
            curDir = win32api.GetShortPathName(curDir)
        psuadeInFile = curDir + os.sep + 'psuade.in'

        if pdfconvert:
            # omit non-uniform and non-sample PDF info from input file
            ExperimentalDesign.createPsuadeInFile(returnData,
                                                  psuadeInFile,
                                                  includePDF=False)
        else:
            ExperimentalDesign.createPsuadeInFile(returnData,
                                                  psuadeInFile,
                                                  includePDF=True)

        out, error = Common.invokePsuade(psuadeInFile)

        if os.path.exists(psuadeDataFile):
            showerr = True
            data = LocalExecutionModule.readSampleFromPsuadeFile(
                psuadeDataFile)
            if pdfconvert:
                os.remove(psuadeDataFile)
                tmpfile = os.getcwd() + os.path.sep + 'tmp'
                y = 1
                # add back in the full PDF info
                RSAnalyzer.writeRSdata(tmpfile,
                                       y,
                                       data,
                                       inputPDF=distributions)
                # write script to PDF conversion
                f = tempfile.SpooledTemporaryFile()
                if platform.system() == 'Windows':
                    import win32api
                    tmpfile = win32api.GetShortPathName(tmpfile)
                f.write(('load %s\n' % tmpfile).encode())
                f.write(b'pdfconvert\n')
                f.write(('write %s\n' % psuadeDataFile).encode())
                nOutputs = returnData.getNumOutputs()
                if nOutputs > 1:
                    f.write(b'n\n')  # write all outputs
                f.write(b'quit\n')
                f.seek(0)
                out, error = Common.invokePsuade(f)
                f.close()
                if os.path.exists(psuadeDataFile):
                    data = LocalExecutionModule.readSampleFromPsuadeFile(
                        psuadeDataFile)
                    showerr = False
            else:
                showerr = False

            if showerr:
                error = 'ExperimentalDesign: %s does not exist.' % psuadeDataFile
                Common.showError(error, out)
                return None
            else:
                return data
Ejemplo n.º 2
0
    def __init__(self,
                 model,
                 session,
                 viewOnly=False,
                 returnDataSignal=None,
                 parent=None):
        super(SimSetup, self).__init__(parent)

        self.setupUi(self)
        self.viewOnly = viewOnly
        self.returnDataSignal = returnDataSignal
        self.sampleFileSet = (
            set()
        )  # Contains which inputs are of the distribution "Sample from File"

        self.fsDataBrowser = dataBrowserFrame(session, self)
        self.dataViewWidget.setLayout(QStackedLayout(self.dataViewWidget))
        self.dataViewWidget.layout().addWidget(self.fsDataBrowser)
        self.fsDataBrowser.refreshContents()

        self.fileLoaded = False
        self.samplesGenerated = False

        self.currentArchiveData = None

        self.model = model
        self.session = session

        if isinstance(model, Model):
            data = SampleData(model)
            dists = []
            for i in range(model.getNumInputs()):
                dists = dists + ["U"]
            data.setInputDistributions(dists)
        else:
            data = model
            self.currentArchiveData = data

        self.ignoreDistributionCheck = False

        if model.getRunType() == Model.EMULATOR:
            self.flowsheetDataRadio.setHidden(True)

        if viewOnly:
            self.loadSamplesRadio.setEnabled(False)
            self.flowsheetDataRadio.setEnabled(False)
        self.loadSamplesRadio.clicked.connect(self.setPage)
        self.flowsheetDataRadio.clicked.connect(self.setPage)
        self.chooseSchemeRadio.clicked.connect(self.setPage)
        self.setPage()

        self.browseButton.clicked.connect(self.loadSampleFile)

        # self.cancelButton.clicked.connect(self.reject)
        self.cancelButton.clicked.connect(self.cancel)
        self.previewButton.clicked.connect(self.preview)
        self.previewButton.setEnabled(False)
        # self.doneButton.clicked.connect(self.accept)
        self.doneButton.clicked.connect(self.doneClicked)
        self.doneButton.setEnabled(False)
        if viewOnly:
            self.cancelButton.setText("OK")
            self.doneButton.setHidden(True)
            self.samplingTabs.setTabEnabled(1, False)

        # Make sure appropriate option is visible
        # self.chooseSchemeRadio.setChecked(True)
        # self.showChooseSchemePage()
        if not isinstance(model, Model):
            if model.getInputData() is not None:
                self.previewButton.setEnabled(True)
                if not viewOnly:
                    self.doneButton.setEnabled(True)
                self.runData = model

        # Make sure distribution tab is showing
        self.samplingTabs.setCurrentIndex(0)
        self.samplingTabs.currentChanged[int].connect(self.checkDists)

        # Set up distributions table
        self.distTable.init(model, InputPriorTable.SIMSETUP, viewOnly=viewOnly)

        self.allFixedButton.clicked.connect(self.makeAllFixed)
        self.allVariableButton.clicked.connect(self.makeAllVariable)
        if viewOnly or model.getRunType() == Model.EMULATOR:
            self.allFixedButton.setHidden(True)
            self.allVariableButton.setHidden(True)

        # Set up sampling schemes tab
        self.generateSamplesButton.setEnabled(False)
        self.generateStatusText.setText("")
        self.allSchemesRadio.setChecked(True)

        foundLibs = LocalExecutionModule.getPsuadeInstalledModules()
        foundMETIS = foundLibs["METIS"]

        self.schemesList.clear()
        self.schemesList.addItems(SamplingMethods.fullNames[:-2]
                                  )  # Leave out GMETIS and FULL Factorial
        if not foundMETIS:
            item = self.schemesList.item(SamplingMethods.METIS)
            text = item.text()
            item.setText(text + " (Not installed)")
            flags = item.flags()
            item.setFlags(flags & ~Qt.ItemIsEnabled)

        if isinstance(model, SampleData):
            self.schemesList.setCurrentRow(model.getSampleMethod())
            self.generateSamplesButton.setEnabled(True)

        # Change lists of schemes displayed
        self.allSchemesRadio.toggled.connect(self.showAllSchemes)
        self.paramScreenRadio.toggled.connect(self.showParamScreenSchemes)
        self.adaptiveRefineRadio.toggled.connect(
            self.showAdaptiveRefineSchemes)
        self.otherRadio.toggled.connect(self.showOtherSchemes)

        self.schemesList.currentItemChanged.connect(
            self.handleGenerateSamplesButton)
        self.generateSamplesButton.clicked.connect(self.generateSamples)
Ejemplo n.º 3
0
    def generateSamples(self):
        # self.setModal(False)

        # Gather all info into SampleData object
        if isinstance(self.model, Model):
            model = copy.deepcopy(self.model)
        #            runData = SampleData(self.model)
        else:
            model = copy.deepcopy(self.model.model)
        #            runData = copy.deepcopy(self.model)

        # Gather distributions from distribution table
        types = []
        modelTypes = self.model.getInputTypes()
        defaults = []
        modelDefaults = self.model.getInputDefaults()
        mins = []
        modelMins = self.model.getInputMins()
        maxs = []
        modelMaxs = self.model.getInputMaxs()
        dists = []
        selectedInputs = []
        # Set sampling scheme to selected or monte carlo if adaptive
        if self.chooseSchemeRadio.isChecked():
            scheme = self.schemesList.currentItem().text()
        else:
            scheme = "Monte Carlo"

        # First get parameters for the model
        row = 0
        for inputNum in range(self.model.getNumInputs()):
            if modelTypes[inputNum] == Model.VARIABLE:
                # Type
                combobox = self.distTable.cellWidget(row, 1)
                if combobox is None:
                    text = self.distTable.item(row, 1).text()
                else:
                    text = combobox.currentText()

                if text == "Fixed":
                    value = Model.FIXED
                else:
                    value = Model.VARIABLE

                types.append(value)
                if value == Model.VARIABLE:
                    selectedInputs.append(inputNum)

                # Defaults
                item = self.distTable.item(row, 2)
                if item is None or len(item.text()) == 0:
                    defaults.append(None)
                else:
                    defaults.append(float(item.text()))

                # Mins
                item = self.distTable.item(row, 3)
                mins.append(float(item.text()))

                # Maxs
                item = self.distTable.item(row, 4)
                maxs.append(float(item.text()))

                row += 1
            else:  # Fixed
                types.append(Model.FIXED)
                defaults.append(modelDefaults[inputNum])
                mins.append(modelMins[inputNum])
                maxs.append(modelMaxs[inputNum])

        # Update model
        model.setInputTypes(types)
        model.setInputDefaults(defaults)
        model.setInputMins(mins)
        model.setInputMaxs(maxs)

        # Create SampleData object
        runData = SampleData(model, self.session)
        runData.setModelName(
            self.session.flowsheet.results.incrimentSetName("UQ_Ensemble"))
        runData.setFromFile(False)

        # Now get distributions for the SampleData object
        numSampleFromFile = 0
        row = 0
        for inputNum in range(self.model.getNumInputs()):
            if modelTypes[inputNum] == Model.VARIABLE:
                # Only collect those that are not fixed to generate inputs
                combobox = self.distTable.cellWidget(row, 5)
                dist = combobox.currentIndex()
                # Check non-uniform distribution and non-Monte Carlo scheme
                if (
                        False
                ):  # dist != Distribution.UNIFORM and SamplingMethods.getEnumValue(scheme) != SamplingMethods.MC:
                    msgbox = QMessageBox()
                    msgbox.setWindowTitle("UQ/Opt GUI Warning")
                    msgbox.setText(
                        "Non-Uniform distributions are not compatible with any "
                        +
                        "sampling scheme other than Monte Carlo!  Please change "
                        +
                        "all distributions back to uniform or select Monte Carlo "
                        + "sampling scheme.")
                    msgbox.setIcon(QMessageBox.Warning)
                    msgbox.exec_()
                    return

                if dist == Distribution.SAMPLE:
                    numSampleFromFile += 1

                dists += [self.distTable.getDistribution(row)]

                row += 1
            else:  # Fixed
                dist = Distribution(Distribution.UNIFORM)
                dists = dists + [dist]

        runData.setInputDistributions(dists)

        numSamples = int(self.numSamplesBox.value())
        runData.setNumSamples(numSamples)
        runData.setSampleMethod(scheme)

        # Check number of samples
        scheme = runData.getSampleMethod()
        newNumSamples = SamplingMethods.validateSampleSize(
            scheme, len(selectedInputs), numSamples)
        if scheme == SamplingMethods.LSA:
            if newNumSamples != numSamples:
                msgbox = QMessageBox()
                msgbox.setWindowTitle("UQ/Opt GUI Warning")
                msgbox.setText(
                    "%s scheme with %d variable inputs requires %d samples! Do you want to proceed?"
                    % (
                        SamplingMethods.getPsuadeName(scheme),
                        len(selectedInputs),
                        newNumSamples,
                    ))
                msgbox.setIcon(QMessageBox.Question)
                msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                msgbox.setDefaultButton(QMessageBox.Yes)
                response = msgbox.exec_()
                if response == QMessageBox.Yes:
                    runData.setNumSamples(newNumSamples)
                else:
                    return
        elif scheme == SamplingMethods.MOAT or scheme == SamplingMethods.GMOAT:
            if type(newNumSamples) is tuple:
                msgbox = QMessageBox()
                msgbox.setWindowTitle("UQ/Opt GUI Warning")
                msgbox.setText(
                    "%s scheme with %d variable inputs cannot have %d samples! How do you want to proceed?"
                    % (
                        SamplingMethods.getFullName(scheme),
                        len(selectedInputs),
                        numSamples,
                    ))
                msgbox.setIcon(QMessageBox.Question)
                firstValButton = msgbox.addButton(
                    "Change to %d samples" % newNumSamples[0],
                    QMessageBox.AcceptRole)
                secondValButton = msgbox.addButton(
                    "Change to %d samples" % newNumSamples[1],
                    QMessageBox.AcceptRole)
                cancelButton = msgbox.addButton(QMessageBox.Cancel)

                msgbox.exec_()
                if msgbox.clickedButton() == firstValButton:
                    runData.setNumSamples(int(newNumSamples[0]))
                elif msgbox.clickedButton() == secondValButton:
                    runData.setNumSamples(int(newNumSamples[1]))
                else:
                    return

        # Visual indications of processing
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.generateStatusText.setText("Generating...")
        self.generateStatusText.repaint()

        # Generate samples for the variable inputs
        selectedRunData = ExperimentalDesign.generateSamples(
            runData, selectedInputs, self.model.getSelectedOutputs())
        if selectedRunData is None:
            QApplication.restoreOverrideCursor()
            self.generateStatusText.setText("")
            return
        selectedInputData = selectedRunData.getInputData()

        # Add fixed inputs back in
        ##        print runData.getNumSamples()
        fullInputData = [0] * runData.getNumSamples()
        for row in range(runData.getNumSamples()):
            rowData = []
            selectedIndex = 0
            for col in range(runData.getNumInputs()):
                if col in selectedInputs:
                    rowData.append(selectedInputData[row][selectedIndex])
                    selectedIndex = selectedIndex + 1
                else:
                    rowData.append(defaults[col])
            fullInputData[row] = rowData
        runData.setInputData(fullInputData)
        runData.setRunState([0] * runData.getNumSamples())
        self.runData = runData

        # Handle archive of METIS file
        if self.runData.getSampleMethod() == SamplingMethods.METIS:
            if self.currentArchiveData is not None:
                # Common.removeArchive(self.currentArchive)
                self.currentArchiveData.removeArchiveFolder()
                pass
            # Common.archiveFile('psuadeMetisInfo', self.runData.getID())
            self.runData.archiveFile("psuadeMetisInfo")
            self.currentArchiveData = self.runData

        # Restore cursor
        QApplication.restoreOverrideCursor()
        self.generateStatusText.setText("Done!")

        self.samplesGenerated = True
        self.previewButton.setEnabled(True)
        self.doneButton.setEnabled(True)
Ejemplo n.º 4
0
class SimSetup(_SimSetup, _SimSetupUI):

    SCHEME_PAGE_INDEX = 0
    LOAD_PAGE_INDEX = 1
    FLOWSHEET_PAGE_INDEX = 2

    def __init__(self,
                 model,
                 session,
                 viewOnly=False,
                 returnDataSignal=None,
                 parent=None):
        super(SimSetup, self).__init__(parent)

        self.setupUi(self)
        self.viewOnly = viewOnly
        self.returnDataSignal = returnDataSignal
        self.sampleFileSet = (
            set()
        )  # Contains which inputs are of the distribution "Sample from File"

        self.fsDataBrowser = dataBrowserFrame(session, self)
        self.dataViewWidget.setLayout(QStackedLayout(self.dataViewWidget))
        self.dataViewWidget.layout().addWidget(self.fsDataBrowser)
        self.fsDataBrowser.refreshContents()

        self.fileLoaded = False
        self.samplesGenerated = False

        self.currentArchiveData = None

        self.model = model
        self.session = session

        if isinstance(model, Model):
            data = SampleData(model)
            dists = []
            for i in range(model.getNumInputs()):
                dists = dists + ["U"]
            data.setInputDistributions(dists)
        else:
            data = model
            self.currentArchiveData = data

        self.ignoreDistributionCheck = False

        if model.getRunType() == Model.EMULATOR:
            self.flowsheetDataRadio.setHidden(True)

        if viewOnly:
            self.loadSamplesRadio.setEnabled(False)
            self.flowsheetDataRadio.setEnabled(False)
        self.loadSamplesRadio.clicked.connect(self.setPage)
        self.flowsheetDataRadio.clicked.connect(self.setPage)
        self.chooseSchemeRadio.clicked.connect(self.setPage)
        self.setPage()

        self.browseButton.clicked.connect(self.loadSampleFile)

        # self.cancelButton.clicked.connect(self.reject)
        self.cancelButton.clicked.connect(self.cancel)
        self.previewButton.clicked.connect(self.preview)
        self.previewButton.setEnabled(False)
        # self.doneButton.clicked.connect(self.accept)
        self.doneButton.clicked.connect(self.doneClicked)
        self.doneButton.setEnabled(False)
        if viewOnly:
            self.cancelButton.setText("OK")
            self.doneButton.setHidden(True)
            self.samplingTabs.setTabEnabled(1, False)

        # Make sure appropriate option is visible
        # self.chooseSchemeRadio.setChecked(True)
        # self.showChooseSchemePage()
        if not isinstance(model, Model):
            if model.getInputData() is not None:
                self.previewButton.setEnabled(True)
                if not viewOnly:
                    self.doneButton.setEnabled(True)
                self.runData = model

        # Make sure distribution tab is showing
        self.samplingTabs.setCurrentIndex(0)
        self.samplingTabs.currentChanged[int].connect(self.checkDists)

        # Set up distributions table
        self.distTable.init(model, InputPriorTable.SIMSETUP, viewOnly=viewOnly)

        self.allFixedButton.clicked.connect(self.makeAllFixed)
        self.allVariableButton.clicked.connect(self.makeAllVariable)
        if viewOnly or model.getRunType() == Model.EMULATOR:
            self.allFixedButton.setHidden(True)
            self.allVariableButton.setHidden(True)

        # Set up sampling schemes tab
        self.generateSamplesButton.setEnabled(False)
        self.generateStatusText.setText("")
        self.allSchemesRadio.setChecked(True)

        foundLibs = LocalExecutionModule.getPsuadeInstalledModules()
        foundMETIS = foundLibs["METIS"]

        self.schemesList.clear()
        self.schemesList.addItems(SamplingMethods.fullNames[:-2]
                                  )  # Leave out GMETIS and FULL Factorial
        if not foundMETIS:
            item = self.schemesList.item(SamplingMethods.METIS)
            text = item.text()
            item.setText(text + " (Not installed)")
            flags = item.flags()
            item.setFlags(flags & ~Qt.ItemIsEnabled)

        if isinstance(model, SampleData):
            self.schemesList.setCurrentRow(model.getSampleMethod())
            self.generateSamplesButton.setEnabled(True)

        # Change lists of schemes displayed
        self.allSchemesRadio.toggled.connect(self.showAllSchemes)
        self.paramScreenRadio.toggled.connect(self.showParamScreenSchemes)
        self.adaptiveRefineRadio.toggled.connect(
            self.showAdaptiveRefineSchemes)
        self.otherRadio.toggled.connect(self.showOtherSchemes)

        self.schemesList.currentItemChanged.connect(
            self.handleGenerateSamplesButton)
        self.generateSamplesButton.clicked.connect(self.generateSamples)

    def cancel(self):
        self.reject()

    def doneClicked(self):
        if self.returnDataSignal:
            self.returnDataSignal.emit(self.getData())
        self.accept()

    def setPage(self):
        """
        Change the page view
        """
        if self.chooseSchemeRadio.isChecked():
            self.samplePages.setCurrentIndex(self.SCHEME_PAGE_INDEX)
            self.previewButton.setEnabled(self.samplesGenerated)
            self.doneButton.setEnabled(self.samplesGenerated)
        elif self.flowsheetDataRadio.isChecked():
            self.samplePages.setCurrentIndex(self.FLOWSHEET_PAGE_INDEX)
            self.previewButton.setEnabled(False)
            self.doneButton.setEnabled(True)
        elif self.loadSamplesRadio.isChecked():
            self.samplePages.setCurrentIndex(self.LOAD_PAGE_INDEX)
            self.previewButton.setEnabled(self.fileLoaded)
            self.doneButton.setEnabled(self.fileLoaded)
        else:
            # I think this is impossible
            raise Exception("No generate samples radio button checked")

    #### Load samples methods
    def loadSampleFile(self):
        if platform.system() == "Windows":
            allFiles = "*.*"
        else:
            allFiles = "*"
        sampleFile, _ = QFileDialog.getOpenFileName(
            self,
            "Load Sample file",
            "",
            "Psuade Files (*.dat *.psuade *.filtered);;Psuade Simple File (*.smp);;CSV (Comma delimited) (*.csv);;All files (%s)"
            % allFiles,
        )
        if not sampleFile:  # Cancelled
            return
        fromSimpleFile = False
        try:
            if sampleFile.endswith(".csv"):
                data = LocalExecutionModule.readSampleFromCsvFile(
                    sampleFile, False)
                inputNames = data.getInputNames()
                if len(inputNames[0]) == 0:
                    fromSimpleFile = True
            else:
                data = LocalExecutionModule.readSampleFromPsuadeFile(
                    sampleFile)
            inputData = data.getInputData()
            numSamples = data.getNumSamples()
            numInputs = data.getNumInputs()
            numLoadVariableInputs = data.getInputTypes().count(Model.VARIABLE)
        except:
            import traceback

            traceback.print_exc()
            try:
                (
                    inputData,
                    _,
                    numInputs,
                    _,
                ) = LocalExecutionModule.readDataFromSimpleFile(sampleFile)
                numSamples = inputData.shape[0]
                numLoadVariableInputs = numInputs
                fromSimpleFile = True
            except:
                QMessageBox.critical(
                    self,
                    "Incorrect format",
                    "File does not have the correct format! Please consult the users manual about the format.",
                )
                return

        # Check compatibility with model.
        # For now, we just check number of inputs ok.
        modelInputTypes = self.model.getInputTypes()
        numModelVariableInputs = modelInputTypes.count(Model.VARIABLE)
        compatible = True
        if fromSimpleFile and numLoadVariableInputs != numModelVariableInputs:
            prompt = (
                "This file does not have the same number of variable inputs (%d) as the setup model (%d)!"
                % (numLoadVariableInputs, numModelVariableInputs))
            compatible = False
        elif not fromSimpleFile:  # Check if input names match
            if numLoadVariableInputs < numModelVariableInputs:
                prompt = (
                    "This file does not have as many variable inputs (%d) as the setup model (%d)!"
                    % (numLoadVariableInputs, numModelVariableInputs))
                compatible = False
            else:
                loadInputNames = data.getInputNames()
                loadInputTypes = data.getInputTypes()
                loadVariableNames = set([
                    loadInputNames[modelIndex]
                    for modelIndex in range(len(loadInputNames))
                    if loadInputTypes[modelIndex] == Model.VARIABLE
                ])
                modelInputNames = self.model.getInputNames()
                modelVariableNames = set([
                    modelInputNames[modelIndex]
                    for modelIndex in range(len(modelInputNames))
                    if modelInputTypes[modelIndex] == Model.VARIABLE
                ])
                if not loadVariableNames <= modelVariableNames:
                    compatible = False
                    prompt = "This file does not have the same variable names as the setup model!"

        if not compatible:
            QMessageBox.warning(self, self.tr("UQ GUI"), self.tr(prompt),
                                QMessageBox.Ok, QMessageBox.Ok)
            return

        # UI indications of success
        self.sampleFileNameEdit.setText(sampleFile)
        self.fileLoaded = True
        self.previewButton.setEnabled(True)
        self.doneButton.setEnabled(True)

        # Create loadData object
        self.loadData = SampleData(self.model)
        self.loadData.setFromFile(False)
        if fromSimpleFile:
            self.loadData.setSampleMethod(SamplingMethods.MC)
        else:
            self.loadData.setSampleMethod(data.getSampleMethod())
        self.loadData.setNumSamples(numSamples)
        resultData = numpy.zeros([numSamples, self.model.getNumInputs()])
        modelDefaults = self.model.getInputDefaults()
        loadIndex = 0
        if fromSimpleFile:
            for modelIndex, modelInType in enumerate(modelInputTypes):
                if modelInType == Model.FIXED:
                    resultData[:, modelIndex] = [modelDefaults[modelIndex]
                                                 ] * numSamples
                else:
                    inDataCol = inputData[:, loadIndex]
                    resultData[:, modelIndex] = inDataCol
                    loadIndex += 1
        else:  # full file
            # Create mapping between model names and load names
            loadDefaults = self.loadData.getInputDefaults()
            for modelIndex, (modelInName, modelInType) in enumerate(
                    zip(modelInputNames, modelInputTypes)):
                if modelInName in loadInputNames:
                    loadIndex = loadInputNames.index(modelInName)
                if modelInType == Model.FIXED:
                    if modelInName in loadInputNames:
                        value = loadDefaults[loadIndex]
                    else:
                        value = modelDefaults[modelIndex]
                    resultData[:, modelIndex] = [value] * numSamples
                else:  # Variable
                    if modelInName not in loadInputNames:
                        resultData[:,
                                   modelIndex] = [modelDefaults[modelIndex]
                                                  ] * numSamples
                    elif loadInputTypes[loadIndex] == Model.FIXED:
                        resultData[:, modelIndex] = [loadDefaults[loadIndex]
                                                     ] * numSamples
                    else:
                        inDataCol = inputData[:, loadIndex]
                        resultData[:, modelIndex] = inDataCol

            self.loadData.setInputDistributions(data.getInputDistributions())

        dists = []
        for modelIndex in range(self.model.getNumInputs()):
            d = Distribution(Distribution.SAMPLE)
            d.setParameterValues(sampleFile, modelIndex + 1)
            dists.append(d)
            self.loadData.setInputDistributions(dists)

        self.loadData.setInputData(resultData)
        self.loadData.setRunState([False] * numSamples)

    def makeAllFixed(self):
        #        self.setAllTypeButtons(Model.FIXED)
        self.distTable.makeAllFixed()

    def makeAllVariable(self):
        #        self.setAllTypeButtons(Model.VARIABLE)
        self.distTable.makeAllVariable()

    def checkDists(self, tabIndex):
        if tabIndex == 0 or self.ignoreDistributionCheck:
            self.ignoreDistributionCheck = False
            return

        showMessage = False
        if self.distTable.getNumVariables() == 0:
            showMessage = True
            message = "All inputs are fixed! One needs to be variable."
        else:
            valid, error = self.distTable.checkValidInputs()
            if not valid:
                showMessage = True
                message = (
                    "Distribution settings not correct or entirely filled out! %s"
                    % error)
            else:
                rowsToWarnAboutMass = []
                for row in range(self.distTable.rowCount()):
                    for col in [3, 4]:
                        item = self.distTable.item(row, col)
                        if col == 3:
                            minVal = float(item.text())
                        else:
                            maxVal = float(item.text())

                    #### Get distribution parameters
                    for col in [6, 7]:
                        cellTable = self.distTable.cellWidget(row, col)
                        if isinstance(cellTable, QComboBox):
                            continue
                        item = None
                        if cellTable is not None:
                            item = cellTable.item(0, 1)
                        if item is not None and item.text():
                            if col == 6:
                                distParam1 = float(item.text())
                            else:
                                distParam2 = float(item.text())
                        else:
                            if col == 6:
                                distParam1 = None
                            else:
                                distParam2 = None

                    #### Check mass and warn if below 50%
                    # Only collect those that are not fixed to generate inputs
                    combobox = self.distTable.cellWidget(row, 5)
                    dist = combobox.currentIndex()
                    # Create file for psuade input
                    if dist not in [Distribution.UNIFORM, Distribution.SAMPLE]:
                        f = tempfile.SpooledTemporaryFile()
                        for i in range(2):
                            f.write(b"cdf_lookup\n")
                            distNum = dist
                            if dist == Distribution.BETA:
                                distNum = 4
                            elif dist == Distribution.WEIBULL:
                                distNum = 5
                            elif dist == Distribution.GAMMA:
                                distNum = 6
                            elif dist == Distribution.EXPONENTIAL:
                                distNum = 7
                            f.write(b"%d\n" %
                                    distNum)  # Number of distribution
                            f.write(b"%f\n" % distParam1)  # Parameter 1
                            if distParam2 is not None:
                                f.write(b"%f\n" % distParam2)  # Parameter 2
                            if i == 0:
                                val = minVal
                            else:
                                val = maxVal
                            f.write(b"%f\n" % val)  # Min or max value
                        f.write(b"quit\n")
                        f.seek(0)

                        # invoke psuade
                        psuadePath = LocalExecutionModule.getPsuadePath()
                        if psuadePath is None:
                            return
                        p = subprocess.Popen(
                            psuadePath,
                            stdin=f,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            shell=True,
                        )
                        f.close()

                        # process error
                        out, error = p.communicate()
                        if error:
                            Common.showError(error, out)
                            return None

                        # parse output
                        lines = out.splitlines()
                        vals = []
                        for line in lines:
                            if "Cumulative probability = " in line.decode(
                                    "utf-8"):
                                words = line.split()
                                vals.append(float(words[-1]))

                        mass = vals[1] - vals[0]
                        if mass < 0.5:
                            rowsToWarnAboutMass.append(row)

                if len(rowsToWarnAboutMass) > 0:
                    self.samplingTabs.setCurrentIndex(0)
                    for row in rowsToWarnAboutMass:
                        msgbox = QMessageBox()
                        msgbox.setWindowTitle("UQ/Opt GUI Warning")
                        msgbox.setText(
                            "Regarding input " +
                            self.model.getInputNames()[row] +
                            ": Min/max range is narrow for its distribution. "
                            +
                            "This could cause sample generation to take more time.  Continue?"
                        )
                        msgbox.setIcon(QMessageBox.Warning)
                        msgbox.setStandardButtons(QMessageBox.Yes
                                                  | QMessageBox.No)
                        msgbox.setDefaultButton(QMessageBox.Yes)
                        ret = msgbox.exec_()
                        if ret != QMessageBox.Yes:
                            self.distTable.selectRow(row)
                            return
                    self.ignoreDistributionCheck = True
                    self.samplingTabs.setCurrentIndex(1)

        if showMessage:
            self.samplingTabs.setCurrentIndex(0)
            msgbox = QMessageBox()
            msgbox.setWindowTitle("UQ/Opt GUI Warning")
            msgbox.setText(message)
            msgbox.setIcon(QMessageBox.Warning)
            msgbox.exec_()
            return

    ### Sampling schemes methods
    def showAllSchemes(self):
        if self.chooseSchemeRadio.isChecked():
            foundLibs = LocalExecutionModule.getPsuadeInstalledModules()
            foundMETIS = foundLibs["METIS"]

            self.schemesList.clear()
            self.schemesList.addItems(
                SamplingMethods.fullNames[:-2])  # Remove GMETIS
            if not foundMETIS:
                item = self.schemesList.item(SamplingMethods.METIS)
                text = item.text()
                item.setText(text + " (Not installed)")
                flags = item.flags()
                item.setFlags(flags & ~Qt.ItemIsEnabled)

    def showParamScreenSchemes(self):
        if self.paramScreenRadio.isChecked():
            self.schemesList.clear()
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.MOAT))
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.GMOAT))
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.LSA))

    def showAdaptiveRefineSchemes(self):
        if self.adaptiveRefineRadio.isChecked():
            foundLibs = LocalExecutionModule.getPsuadeInstalledModules()
            foundMETIS = foundLibs["METIS"]
            self.schemesList.clear()
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.METIS))
            if not foundMETIS:
                item = self.schemesList.item(0)
                text = item.text()
                item.setText(text + " (Not installed)")
                flags = item.flags()
                item.setFlags(flags & ~Qt.ItemIsEnabled)

    def showOtherSchemes(self):
        if self.otherRadio.isChecked():
            self.schemesList.clear()
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.MC))
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.LPTAU))
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.LH))
            self.schemesList.addItem(
                SamplingMethods.getFullName(SamplingMethods.OA))

    def handleGenerateSamplesButton(self):
        self.generateSamplesButton.setEnabled(
            self.schemesList.currentRow() != -1)

    def generateSamples(self):
        # self.setModal(False)

        # Gather all info into SampleData object
        if isinstance(self.model, Model):
            model = copy.deepcopy(self.model)
        #            runData = SampleData(self.model)
        else:
            model = copy.deepcopy(self.model.model)
        #            runData = copy.deepcopy(self.model)

        # Gather distributions from distribution table
        types = []
        modelTypes = self.model.getInputTypes()
        defaults = []
        modelDefaults = self.model.getInputDefaults()
        mins = []
        modelMins = self.model.getInputMins()
        maxs = []
        modelMaxs = self.model.getInputMaxs()
        dists = []
        selectedInputs = []
        # Set sampling scheme to selected or monte carlo if adaptive
        if self.chooseSchemeRadio.isChecked():
            scheme = self.schemesList.currentItem().text()
        else:
            scheme = "Monte Carlo"

        # First get parameters for the model
        row = 0
        for inputNum in range(self.model.getNumInputs()):
            if modelTypes[inputNum] == Model.VARIABLE:
                # Type
                combobox = self.distTable.cellWidget(row, 1)
                if combobox is None:
                    text = self.distTable.item(row, 1).text()
                else:
                    text = combobox.currentText()

                if text == "Fixed":
                    value = Model.FIXED
                else:
                    value = Model.VARIABLE

                types.append(value)
                if value == Model.VARIABLE:
                    selectedInputs.append(inputNum)

                # Defaults
                item = self.distTable.item(row, 2)
                if item is None or len(item.text()) == 0:
                    defaults.append(None)
                else:
                    defaults.append(float(item.text()))

                # Mins
                item = self.distTable.item(row, 3)
                mins.append(float(item.text()))

                # Maxs
                item = self.distTable.item(row, 4)
                maxs.append(float(item.text()))

                row += 1
            else:  # Fixed
                types.append(Model.FIXED)
                defaults.append(modelDefaults[inputNum])
                mins.append(modelMins[inputNum])
                maxs.append(modelMaxs[inputNum])

        # Update model
        model.setInputTypes(types)
        model.setInputDefaults(defaults)
        model.setInputMins(mins)
        model.setInputMaxs(maxs)

        # Create SampleData object
        runData = SampleData(model, self.session)
        runData.setModelName(
            self.session.flowsheet.results.incrimentSetName("UQ_Ensemble"))
        runData.setFromFile(False)

        # Now get distributions for the SampleData object
        numSampleFromFile = 0
        row = 0
        for inputNum in range(self.model.getNumInputs()):
            if modelTypes[inputNum] == Model.VARIABLE:
                # Only collect those that are not fixed to generate inputs
                combobox = self.distTable.cellWidget(row, 5)
                dist = combobox.currentIndex()
                # Check non-uniform distribution and non-Monte Carlo scheme
                if (
                        False
                ):  # dist != Distribution.UNIFORM and SamplingMethods.getEnumValue(scheme) != SamplingMethods.MC:
                    msgbox = QMessageBox()
                    msgbox.setWindowTitle("UQ/Opt GUI Warning")
                    msgbox.setText(
                        "Non-Uniform distributions are not compatible with any "
                        +
                        "sampling scheme other than Monte Carlo!  Please change "
                        +
                        "all distributions back to uniform or select Monte Carlo "
                        + "sampling scheme.")
                    msgbox.setIcon(QMessageBox.Warning)
                    msgbox.exec_()
                    return

                if dist == Distribution.SAMPLE:
                    numSampleFromFile += 1

                dists += [self.distTable.getDistribution(row)]

                row += 1
            else:  # Fixed
                dist = Distribution(Distribution.UNIFORM)
                dists = dists + [dist]

        runData.setInputDistributions(dists)

        numSamples = int(self.numSamplesBox.value())
        runData.setNumSamples(numSamples)
        runData.setSampleMethod(scheme)

        # Check number of samples
        scheme = runData.getSampleMethod()
        newNumSamples = SamplingMethods.validateSampleSize(
            scheme, len(selectedInputs), numSamples)
        if scheme == SamplingMethods.LSA:
            if newNumSamples != numSamples:
                msgbox = QMessageBox()
                msgbox.setWindowTitle("UQ/Opt GUI Warning")
                msgbox.setText(
                    "%s scheme with %d variable inputs requires %d samples! Do you want to proceed?"
                    % (
                        SamplingMethods.getPsuadeName(scheme),
                        len(selectedInputs),
                        newNumSamples,
                    ))
                msgbox.setIcon(QMessageBox.Question)
                msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                msgbox.setDefaultButton(QMessageBox.Yes)
                response = msgbox.exec_()
                if response == QMessageBox.Yes:
                    runData.setNumSamples(newNumSamples)
                else:
                    return
        elif scheme == SamplingMethods.MOAT or scheme == SamplingMethods.GMOAT:
            if type(newNumSamples) is tuple:
                msgbox = QMessageBox()
                msgbox.setWindowTitle("UQ/Opt GUI Warning")
                msgbox.setText(
                    "%s scheme with %d variable inputs cannot have %d samples! How do you want to proceed?"
                    % (
                        SamplingMethods.getFullName(scheme),
                        len(selectedInputs),
                        numSamples,
                    ))
                msgbox.setIcon(QMessageBox.Question)
                firstValButton = msgbox.addButton(
                    "Change to %d samples" % newNumSamples[0],
                    QMessageBox.AcceptRole)
                secondValButton = msgbox.addButton(
                    "Change to %d samples" % newNumSamples[1],
                    QMessageBox.AcceptRole)
                cancelButton = msgbox.addButton(QMessageBox.Cancel)

                msgbox.exec_()
                if msgbox.clickedButton() == firstValButton:
                    runData.setNumSamples(int(newNumSamples[0]))
                elif msgbox.clickedButton() == secondValButton:
                    runData.setNumSamples(int(newNumSamples[1]))
                else:
                    return

        # Visual indications of processing
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.generateStatusText.setText("Generating...")
        self.generateStatusText.repaint()

        # Generate samples for the variable inputs
        selectedRunData = ExperimentalDesign.generateSamples(
            runData, selectedInputs, self.model.getSelectedOutputs())
        if selectedRunData is None:
            QApplication.restoreOverrideCursor()
            self.generateStatusText.setText("")
            return
        selectedInputData = selectedRunData.getInputData()

        # Add fixed inputs back in
        ##        print runData.getNumSamples()
        fullInputData = [0] * runData.getNumSamples()
        for row in range(runData.getNumSamples()):
            rowData = []
            selectedIndex = 0
            for col in range(runData.getNumInputs()):
                if col in selectedInputs:
                    rowData.append(selectedInputData[row][selectedIndex])
                    selectedIndex = selectedIndex + 1
                else:
                    rowData.append(defaults[col])
            fullInputData[row] = rowData
        runData.setInputData(fullInputData)
        runData.setRunState([0] * runData.getNumSamples())
        self.runData = runData

        # Handle archive of METIS file
        if self.runData.getSampleMethod() == SamplingMethods.METIS:
            if self.currentArchiveData is not None:
                # Common.removeArchive(self.currentArchive)
                self.currentArchiveData.removeArchiveFolder()
                pass
            # Common.archiveFile('psuadeMetisInfo', self.runData.getID())
            self.runData.archiveFile("psuadeMetisInfo")
            self.currentArchiveData = self.runData

        # Restore cursor
        QApplication.restoreOverrideCursor()
        self.generateStatusText.setText("Done!")

        self.samplesGenerated = True
        self.previewButton.setEnabled(True)
        self.doneButton.setEnabled(True)

    ### Preview button
    def preview(self):
        if self.loadSamplesRadio.isChecked():
            previewData = self.loadData
        else:
            previewData = self.runData

        # self.setModal(False)
        dialog = Preview(previewData, self)
        # dialog.exec_()
        dialog.show()
        # self.setModal(True)

    ### Return data
    def getData(self):
        if self.loadSamplesRadio.isChecked():
            returnData = self.loadData
        elif self.flowsheetDataRadio.isChecked():
            self.session.flowsheet.results.exportPSUADE("temp/psuadeData2.tmp")
            returnData = LocalExecutionModule.readSampleFromPsuadeFile(
                "temp/psuadeData2.tmp")
        else:
            returnData = self.runData
        return returnData
Ejemplo n.º 5
0
    def loadSampleFile(self):
        if platform.system() == "Windows":
            allFiles = "*.*"
        else:
            allFiles = "*"
        sampleFile, _ = QFileDialog.getOpenFileName(
            self,
            "Load Sample file",
            "",
            "Psuade Files (*.dat *.psuade *.filtered);;Psuade Simple File (*.smp);;CSV (Comma delimited) (*.csv);;All files (%s)"
            % allFiles,
        )
        if not sampleFile:  # Cancelled
            return
        fromSimpleFile = False
        try:
            if sampleFile.endswith(".csv"):
                data = LocalExecutionModule.readSampleFromCsvFile(
                    sampleFile, False)
                inputNames = data.getInputNames()
                if len(inputNames[0]) == 0:
                    fromSimpleFile = True
            else:
                data = LocalExecutionModule.readSampleFromPsuadeFile(
                    sampleFile)
            inputData = data.getInputData()
            numSamples = data.getNumSamples()
            numInputs = data.getNumInputs()
            numLoadVariableInputs = data.getInputTypes().count(Model.VARIABLE)
        except:
            import traceback

            traceback.print_exc()
            try:
                (
                    inputData,
                    _,
                    numInputs,
                    _,
                ) = LocalExecutionModule.readDataFromSimpleFile(sampleFile)
                numSamples = inputData.shape[0]
                numLoadVariableInputs = numInputs
                fromSimpleFile = True
            except:
                QMessageBox.critical(
                    self,
                    "Incorrect format",
                    "File does not have the correct format! Please consult the users manual about the format.",
                )
                return

        # Check compatibility with model.
        # For now, we just check number of inputs ok.
        modelInputTypes = self.model.getInputTypes()
        numModelVariableInputs = modelInputTypes.count(Model.VARIABLE)
        compatible = True
        if fromSimpleFile and numLoadVariableInputs != numModelVariableInputs:
            prompt = (
                "This file does not have the same number of variable inputs (%d) as the setup model (%d)!"
                % (numLoadVariableInputs, numModelVariableInputs))
            compatible = False
        elif not fromSimpleFile:  # Check if input names match
            if numLoadVariableInputs < numModelVariableInputs:
                prompt = (
                    "This file does not have as many variable inputs (%d) as the setup model (%d)!"
                    % (numLoadVariableInputs, numModelVariableInputs))
                compatible = False
            else:
                loadInputNames = data.getInputNames()
                loadInputTypes = data.getInputTypes()
                loadVariableNames = set([
                    loadInputNames[modelIndex]
                    for modelIndex in range(len(loadInputNames))
                    if loadInputTypes[modelIndex] == Model.VARIABLE
                ])
                modelInputNames = self.model.getInputNames()
                modelVariableNames = set([
                    modelInputNames[modelIndex]
                    for modelIndex in range(len(modelInputNames))
                    if modelInputTypes[modelIndex] == Model.VARIABLE
                ])
                if not loadVariableNames <= modelVariableNames:
                    compatible = False
                    prompt = "This file does not have the same variable names as the setup model!"

        if not compatible:
            QMessageBox.warning(self, self.tr("UQ GUI"), self.tr(prompt),
                                QMessageBox.Ok, QMessageBox.Ok)
            return

        # UI indications of success
        self.sampleFileNameEdit.setText(sampleFile)
        self.fileLoaded = True
        self.previewButton.setEnabled(True)
        self.doneButton.setEnabled(True)

        # Create loadData object
        self.loadData = SampleData(self.model)
        self.loadData.setFromFile(False)
        if fromSimpleFile:
            self.loadData.setSampleMethod(SamplingMethods.MC)
        else:
            self.loadData.setSampleMethod(data.getSampleMethod())
        self.loadData.setNumSamples(numSamples)
        resultData = numpy.zeros([numSamples, self.model.getNumInputs()])
        modelDefaults = self.model.getInputDefaults()
        loadIndex = 0
        if fromSimpleFile:
            for modelIndex, modelInType in enumerate(modelInputTypes):
                if modelInType == Model.FIXED:
                    resultData[:, modelIndex] = [modelDefaults[modelIndex]
                                                 ] * numSamples
                else:
                    inDataCol = inputData[:, loadIndex]
                    resultData[:, modelIndex] = inDataCol
                    loadIndex += 1
        else:  # full file
            # Create mapping between model names and load names
            loadDefaults = self.loadData.getInputDefaults()
            for modelIndex, (modelInName, modelInType) in enumerate(
                    zip(modelInputNames, modelInputTypes)):
                if modelInName in loadInputNames:
                    loadIndex = loadInputNames.index(modelInName)
                if modelInType == Model.FIXED:
                    if modelInName in loadInputNames:
                        value = loadDefaults[loadIndex]
                    else:
                        value = modelDefaults[modelIndex]
                    resultData[:, modelIndex] = [value] * numSamples
                else:  # Variable
                    if modelInName not in loadInputNames:
                        resultData[:,
                                   modelIndex] = [modelDefaults[modelIndex]
                                                  ] * numSamples
                    elif loadInputTypes[loadIndex] == Model.FIXED:
                        resultData[:, modelIndex] = [loadDefaults[loadIndex]
                                                     ] * numSamples
                    else:
                        inDataCol = inputData[:, loadIndex]
                        resultData[:, modelIndex] = inDataCol

            self.loadData.setInputDistributions(data.getInputDistributions())

        dists = []
        for modelIndex in range(self.model.getNumInputs()):
            d = Distribution(Distribution.SAMPLE)
            d.setParameterValues(sampleFile, modelIndex + 1)
            dists.append(d)
            self.loadData.setInputDistributions(dists)

        self.loadData.setInputData(resultData)
        self.loadData.setRunState([False] * numSamples)
Ejemplo n.º 6
0
    def writeOUUdata(outfile, outputs, constraints, derivatives, data, xtable,
                     **kwargs):

        # Charles TODO: Handle y is now a list of inputs
        # Charles TODO: Handle derivatives

        # defaults
        rseed = None
        driver = data.getDriverName()
        if driver is None:
            driver = 'NONE'
        optdriver = data.getOptDriverName()
        if optdriver is None:
            optdriver = 'NONE'
        ensoptdriver = data.getEnsembleOptDriverName()
        if ensoptdriver is None:
            ensoptdriver = 'NONE'
        auxdriver = data.getAuxDriverName()
        if auxdriver is None:
            auxdriver = 'NONE'
        inputLB = None
        inputUB = None
        inputDefaults = None
        distributions = None
        init_input = None

        # process keyworded arguments
        for key in kwargs:
            k = key.lower()
            if k == 'randseed':
                rseed = kwargs[key]
            elif k == 'driver':
                driver = kwargs[key]
            elif k == 'optdriver':
                optdriver = kwargs[key]
            elif k == 'ensoptdriver':
                ensoptdriver = kwargs[key]
            elif k == 'auxdriver':
                auxdriver = kwargs[key]
            elif k == 'inputlowerbounds':
                inputLB = kwargs[key]
            elif k == 'inputupperbounds':
                inputUB = kwargs[key]
            elif k == 'inputpdf':
                distributions = kwargs[key]
            elif k == 'init_input':
                init_input = kwargs[key]

        inputTypes = data.getInputTypes()
        nInputs = data.getNumInputs()
        inputNames = data.getInputNames()
        variableInputIndices = []
        for e in xtable:
            if e['type'] != u'Fixed':
                variableInputIndices.append(inputNames.index(e['name']))
        nVariableInputs = len(variableInputIndices)
        nOutputs = len(outputs)
        nSamples = num_fmin = 1  # number of random restarts
        nConstraints = constraints.count(True)
        nDerivatives = derivatives.count(True)
        totalOutputs = nOutputs + nConstraints + nDerivatives

        f = open(outfile, 'w')
        if init_input:
            f.write('PSUADE_IO\n')
            f.write('%d %d %d\n' % (nVariableInputs, totalOutputs, nSamples))
            f.write("1 0\n")  # assume initial point has not been run
            for x in init_input:
                f.write(' % .16e\n' % x)
            for i in xrange(totalOutputs):
                f.write(' 9.9999999999999997e+34\n')
            f.write("PSUADE_IO\n")

        # TO DO: merge with RSAnalyzer.writeRSdata()
        f.write('PSUADE\n')

        # ... input ...
        numFixed = nInputs - nVariableInputs
        f.write('INPUT\n')
        if numFixed > 0:
            f.write('   num_fixed %d\n' % numFixed)
        f.write('   dimension = %d\n' % nVariableInputs)
        if inputLB is None:
            inputLB = data.getInputMins()
        if inputUB is None:
            inputUB = data.getInputMaxs()
        if inputDefaults is None:
            inputDefaults = data.getInputDefaults()
        indices = range(nInputs)
        variableIndex = 1
        fixedIndex = 1
        for i, name, inType, lb, ub, default in zip(indices, inputNames, \
                             inputTypes, inputLB, inputUB, inputDefaults):
            if i in variableInputIndices:  #inType == Model.VARIABLE:
                f.write('   variable %d %s  =  % .16e  % .16e\n' % \
                        (variableIndex, name, lb, ub))
                variableIndex = variableIndex + 1
            else:
                f.write('   fixed %d %s = % .16e\n' %
                        (fixedIndex, name, default))
                fixedIndex = fixedIndex + 1

        # inject discrete variables in psuade
        opttypes = []
        cnt = 0
        for e in xtable:
            cnt = cnt + 1
            t = e['type']
            if t == u'Opt: Primary Discrete (Z1d)':
                opttypes.append(cnt)

        nn = len(opttypes)
        for ii in range(nn):
            jj = opttypes[ii]
            f.write('   discrete %d\n' % (jj))

        if distributions is None:
            distributions = SampleData.getInputDistributions(data)
        for i, inType, dist in zip(indices, inputTypes, distributions):
            if i in variableInputIndices:  #inType == Model.VARIABLE:
                distType = dist.getDistributionType()
                distParams = dist.getParameterValues()
                if distType != Distribution.UNIFORM:
                    f.write('   PDF %d %c' % (i+1, \
                            Distribution.getPsuadeName(distType)))
                    if distType == Distribution.SAMPLE:
                        error = 'OUU: In function writeOUUdata(), '
                        error = error + 'SAMPLE distribution is not supported.'
                        Common.showError(error)
                        return None
                    else:
                        if distParams[0] is not None:
                            f.write(' % .16e' % distParams[0])
                        if distParams[1] is not None:
                            f.write(' % .16e' % distParams[1])
                    f.write('\n')
        f.write('END\n')

        # ... output ...
        outActive = nOutputs
        nConstrs = 0
        nDerivs = 0
        for ii in range(len(constraints)):
            if constraints[ii]:
                outActive = outActive + 1
                nConstrs = nConstrs + 1
        for ii in range(len(derivatives)):
            if derivatives[ii]:
                outActive = outActive + 1
                nDerivs = nDerivs + 1
        if (nOutputs != 1):
            error = 'OUU: In function writeOUUdata(), '
            error = error + 'multi-objective optimization not supported.'
            Common.showError(error)
            return None
        else:
            if ((nConstrs > 0) and (nDerivs > 0)):
                error = 'OUU: In function writeOUUdata(), '
                error = error + 'LBFGS does not support inequality constraints.'
                Common.showError(error)
                return None
            elif ((nDerivs > 0) and (nDerivs != nVariableInputs)):
                error = 'OUU: In function writeOUUdata(), '
                error = error + 'Number of derivatives not correct'
                Common.showError(error)
                return None

        f.write('OUTPUT\n')
        f.write('   dimension = %d\n' % (outActive))
        outputNames = SampleData.getOutputNames(data)
        for ii in range(nOutputs):
            ind = outputs[ii]
            f.write('   variable %d %s\n' % (ii + 1, outputNames[ind - 1]))
            print('   variable %d %s\n' % (ii + 1, outputNames[ind - 1]))
        outActive = nOutputs + 1
        for ii in range(len(constraints)):
            if constraints[ii]:
                f.write('   variable %d %s\n' % (outActive, outputNames[ii]))
                print('   variable %d %s\n' % (outActive, outputNames[ii]))
                outActive = outActive + 1
        for ii in range(len(derivatives)):
            if derivatives[ii]:
                f.write('   variable %d %s\n' % (outActive, outputNames[ii]))
                print('   variable %d %s\n' % (outActive, outputNames[ii]))
                outActive = outActive + 1
        f.write('END\n')

        # ... method ...
        f.write('METHOD\n')
        f.write('   sampling = MC\n')  # OUU uses this to create
        f.write('   num_samples = 1\n')  # initial guess
        if rseed is not None:
            f.write('random_seed = %d\n' % rseed)  # random seed
        f.write('END\n')

        # ... application ...
        f.write('APPLICATION\n')
        if platform.system() == 'Windows':
            import win32api
            if driver != 'NONE' and driver != 'PSUADE_LOCAL':
                driver = win32api.GetShortPathName(driver)
            if optdriver != 'NONE' and optdriver != 'PSUADE_LOCAL':
                optdriver = win32api.GetShortPathName(optdriver)
            if ensoptdriver != 'NONE' and ensoptdriver != 'PSUADE_LOCAL':
                ensoptdriver = win32api.GetShortPathName(ensoptdriver)
            if auxdriver != 'NONE' and auxdriver != 'PSUADE_LOCAL':
                auxdriver = win32api.GetShortPathName(auxdriver)
        f.write('   driver = %s\n' % driver)
        f.write('   opt_driver = %s\n' % optdriver)
        f.write('   ensemble_opt_driver = %s\n' % ensoptdriver)
        f.write('   aux_opt_driver = %s\n' % auxdriver)
        f.write('   launch_interval = 0\n')
        f.write('END\n')

        # ... analysis ...
        f.write('ANALYSIS\n')
        if (nDerivs > 0):
            f.write('   optimization method = ouu_lbfgs\n')
        else:
            f.write('   optimization method = ouu\n')
        f.write('   optimization num_local_minima = 1\n')
        f.write('   optimization max_feval = 1000000\n')
        f.write('   optimization fmin = 0.0\n')
        f.write('   optimization tolerance = 1.000000e-06\n')
        f.write('   optimization num_fmin = %d\n' % num_fmin)
        f.write('   optimization print_level = 3\n')
        #f.write('   analyzer output_id = %d\n' % y)
        f.write('   analyzer output_id = 1\n')
        f.write('   opt_expert\n')
        f.write('   printlevel 0\n')
        f.write('END\n')

        f.write('END\n')
        f.close()

        return outfile