Version 4 (modified by dkearney, 18 years ago) (diff) |
---|
Uploading with Rappture
Topics discussed:
- Uploading Basics
- Uploading Data Example Files
- 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:
- sineIt.py - python script representing some science code
- inputDeck - cryptic input deck used by our science code
- wrapper.py - python script representing a wrapper script
- 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.
Attachments (4)
-
inputDeck
(11 bytes) -
added by dkearney 18 years ago.
example input deck for science code
-
sineIt.py
(1.3 KB) -
added by dkearney 18 years ago.
sample science code
-
tool.xml
(926 bytes) -
added by dkearney 18 years ago.
example tool.xml
- wrapper.py (3.1 KB) - added by dkearney 16 years ago.
Download all attachments as: .zip