wiki:FAQ_LoaderUpDownload

Version 4 (modified by dkearney, 18 years ago) (diff)

--

Uploading with Rappture

Topics discussed:

  1. Uploading Basics
  2. Uploading Data Example Files
  3. How It Works

Uploading Basics

Rappture developers can allow application users to upload data into the application by using Rappture's Upload capabilities. This is usesful if you have an older application that requires a complicated input deck or if the input deck is actually the output of another application. You can allow the user to upload data into the Rappture GUI using the "Upload" capabilities of the loader. To learn more about how loaders work, check out the wiki page on loaders and pay particular attention to the "Upload / Download" section.

Uploading Data Example

This example demonstrates using the upload capabilities of Rappture. The following files are used in this example:

  1. sineIt.py - python script representing some science code
  2. inputDeck - cryptic input deck used by our science code
  3. wrapper.py - python script representing a wrapper script
  4. tool.xml - Rappture tool description file

Here is what each file should look like:
sineIt.py

#! /bin/sh
#
""":"
exec python $0 ${1+"$@"}
"""

# This script represents a bit of science code that takes in 3 numeric·
# values and outputs a file with values of a sine function.

import sys
from math import sin,pi

if __name__ == '__main__':
    inDeckName = sys.argv[1]

    # try to open our file
    try:
        fh = open(inDeckName)
    except IOError:
        # we'll pass on dealing with the exception for now
        # we'll just exit with a message
        print 'Error opening file %s' % inDeckName
        sys.exit(-1)

    # read the special cryptic inputDeck
    # inputDeck contains 3 numbers, each on a separate line
    # the first number is the start value.
    # the second number is the end value.
    # the third number is the step.
    # here we are splitting on whitespace (in this case, newlines '\n')
    [start,end,step] = fh.read().split()
    fh.close()

    x = float(eval(start))
    fstep = float(step)
    outData = ''

    while x < float(eval(end)):
        # perform our sin calculation
        y = sin(x)
        # save the values to a string
        outData += '%g %g\n' % (x,y)
        # increment our loop control variable
        x = x + fstep

    # write our saved calculation values to disk
    fh2 = open(inDeckName+'.out','w')
    fh2.write(outData)
    fh2.close()

    # exit successfully
    sys.exit(0)


inputDeck

0
4*pi
0.1


wrapper.py

#! /bin/sh
#
""":"
exec python $0 ${1+"$@"}
"""

# This script represents a bit of science code that takes in 3 numeric·
# values and outputs a file with values of a sine function.

import sys
import os
import re
import Rappture

def getCommandOutput(command):
    childin,childout,childerr = os.popen3(command)
    data = childout.read()
    err = childerr.read()
    errcode = childout.close()
    if err:
        print '%s\n%s' % (command, err)
        sys.exit(-1)

    return data

def getDriverId(driverFileName):
    idObj = re.search('\d+',driverFileName)
    if idObj != None:
        return idObj.group()
    return None


if __name__ == '__main__':

    inDeckName = sys.argv[1]

    lib = Rappture.library(inDeckName)

    if lib == None:
        # we'll pass on dealing with the exception for now
        # we'll just exit with a message
        print 'Error opening file %s' % inDeckName
        sys.exit(-1)

    # check to see if the user uploaded their own data
    # or if they inputted the values
    inputType = lib.get('input.loader.current')
    if inputType == 'Uploaded data':
        # they uploaded their datafile
        # we need to write this data to a file so our science code can read it
        # find the location of where rappture stored the data from their file
        # and store the data int the writeData variable
        writeDataLocation = lib.get('input.loader.upload.to')
        writeData = lib.get(writeDataLocation+'.current')
    else:
        # they manually entered their data into the GUI
        # grab each value and create a string we can write to a file.
        start = lib.get('input.string(start).current')
        end = lib.get('input.string(end).current')
        step = lib.get('input.number(step).current')
        writeData = '%s\n%s\n%s' % (start,end,step)

    # prepare our semi-unique file name
    outFileName = 'inputDeck.' + getDriverId(inDeckName)
    fh = open(outFileName, 'w')
    if fh != None:
        # write our input deck to the file
        fh.write(writeData)
        fh.close()

    # run the science code
    dirpath = os.path.dirname(sys.argv[0])
    getCommandOutput('%s/sineIt.py %s' % (dirpath,outFileName))

    # our science code outputted the answer to a file
    # grab that file and add the answer to the Rappture library object
    dataFileName = outFileName + '.out'
    data = ''

    # try to open our data file
    try:
        dFH = open(dataFileName)

        # read the data from the data file
        data = dFH.read()
        dFH.close()
    except IOError:
        # we'll pass on dealing with the exception for now
        # send a message to the user letting them know there was an error
        errMsg = 'Error opening file %s' % dataFileName
        lib.put('output.string(errorLog).current',errMsg,1)


    # store the data inside of the rappture library
    lib.put('output.curve(sin_data).about.label','sin curve')
    lib.put('output.curve(sin_data).about.label','sample output of the sin function')
    lib.put('output.curve(sin_data).component.xy',data)

    # remove any temporary files
    try:
        os.remove(outFileName)
        os.remove(dataFileName)
    except OSError:
        # we were unable to remove the files,
        # send a note to the user
        errMsg = 'Error while removing tmp files'
        lib.put('output.string(errorLog).current',errMsg,1)

    # signal to the Rappture GUI that processing has completed
    Rappture.result(lib)

    # exit gracefully
    sys.exit(0)


tool.xml

<?xml version="1.0"?>
<run>
<tool>
  <title>upload example</title>
  <about>Example of Uploading with Rappture GUI.</about>
  <command>@tool/wrapper.py @driver</command>
</tool>
<input>
  <loader>
    <about>
      <label>Example</label>
      <description>Use this to load examples.</description>
    </about>
    <upload>
      <to>input.string(uploadedFile)</to>
      <prompt>Upload Input Deck.</prompt>
    </upload>
  </loader>
  <string id="uploadedFile">
    <about>
      <label>Uploaded File</label>
    </about>
    <size>5x5</size>
    <default></default>
  </string>
  <string id="start">
    <about>
      <label>start</label>
    </about>
    <default>-1</default>
  </string>
  <string id="end">
    <about>
      <label>end</label>
    </about>
    <default>-1</default>
  </string>
  <number id="step">
    <about>
      <label>step</label>
    </about>
    <default>-1</default>
  </number>
</input>
</run>

How it works

As always, first the user starts simulation and the graphical user interface comes up.

By clicking on the loader (drop down menu) and choosing the "Upload" option the user can pick a file from their local computer and have it uploaded to the rappture graphical user interface.

After the user uploads their data, it is stored in the xml file at the location described in the loader:

<input>
  <loader>
    <upload>
      <to>input.string(uploadedFile)</to>
      <prompt>Upload Input Deck.</prompt>
    </upload>
  </loader>
...

In this case the contents of the uploaded file was saved to input.string(uploadedFile).current as described by the path input.loader.upload.to.

Next the user clicks the simulate button. Rappture writes the inputs to the driver.xml file and executes the tool command (wrapper.py). wrapper.py reads the xml file, checks to see if the user uploaded data to the graphical user interface or manually filled in the values. You can check to see if the user uploaded data by comparing the value of input.loader.current to the string 'Uploaded data'. If they match, then you know the user uploaded data into the graphical user interface. As the wrapper.py script shows, to get the data that was uploaded by the user, simply issue a get command with the "upload to" location specified.

In the wrapper.py python script above we issue these commands:

        writeDataLocation = lib.get('input.loader.upload.to')
        writeData = lib.get(writeDataLocation+'.current')

now writeData holds the information that was uploaded and we can write it to a file, which is what the science code expects.

    # prepare our semi-unique file name
    outFileName = 'inputDeck.' + getDriverId(inDeckName)
    fh = open(outFileName, 'w')
    if fh != None:
        # write our input deck to the file
        fh.write(writeData)
        fh.close()

After writing the data to a file, we call the science code with the name of the input deck. The science code reads the input deck, calculates its science and writes the answer back to a file. The wrapper.py script then reads and parses the result file from the science code and places the results back into the rappture library.

Back to Frequently Asked Questions

Attachments (4)

Download all attachments as: .zip