Introduction

This document describes snippets of JEScript for performing common tasks.

Working with tables.

JEScript integrates the STIL library for reading and writing astronomical tables in many common formats.

Construct a table from contents of a String

the following example constructs a star table from data held in a string votableString. If possible, the opotional second parameter should be used to tell the library what format table to expect

table = astrogrid.tableHelper.builder.makeStarTableFromString(votableString, 'votable' )
                

Construct a table from contents of a URI

The following example constructs a star table from data held at a remote location, pointed to by a string uri. The following example will work for references to myspace, http, file and ftp - ie for uri's starting with ivo://,file:/,http://,ftp://

ev = astrogrid.ioHelper.getExternalValue(uri)
table = astrogrid.tableHelper.builder.makeStarTable(ev)
                

There are also variants of makeStarTable() that accept a URL or String directly - but these will only work for conventional http:// and ftp:// references.

Write out a table

Contents of a table object can be written out to a uri location (for uri's starting with ivo://,file:/,http://,ftp://) as follows

ev = astrogrid.ioHelper.getExternalValue(uri);
astrogrid.tableHelper.writeTable(ev,table,'votable')
// and you can check it's there be doing something like..
table1 = astrogrid.tableHelper.builder.makeStarTable(ev)
assert table.rowCount == table1.rowCount
assert table.columnCount == table1.columnCount
                

Processing the rows of a table

As well as the row and cell access methods defined by the classes of the STIL library, JEScript also provides iterators over the rows and cells of a table. This allows Groovy's list-processing features to be used to filter and process table data

The following sums all the cells in column 3 of the table

colSum = table.columnIterator(3).inject(0) {acc, item | acc + item}
                

The following example sums each row of a table, returning a list of sums

sumList = table.iterator().collect{ it.inject(0) {acc, item | acc + item}}
                

The following returns all values of column 5 in rows where column 3 is less than column 4

vals = table.iterator().findAll{ it[3] < it[4]}.collect{it[5]}
        

Extract a column by UCD

The following example parses the metadata of a votable, to identify which column has the UCD VOX:Image_AccessReference It then extracts the contents of that column of the table into a list. Most of the methods used in this example are part of the STIL table library

The script assumes that a table object already exists.

Results is a list of strings - which in this example happen to be urls

col = ( 0 ... table.columnCount ).find{ table.getColumnInfo( it ).getUCD() == 'VOX:Image_AccessReference' }
urls = table.columnIterator(col).collect{it}
                

This example uses the internal-iterator style of Groovy programming to acheive very concise code. The equivalent using external looping would be

col = 0
for (x in 0 ... table.columnCount) {
  if (table.getColumnInfo(x).getUCD() == 'VOX:Image_AccessReference') {
    col = x
  }
}
urls = []
for (x in table.columnIterator(col)) {
  urls.add(x);
}
                

Extract a column by name

Variation of the previous example - look for a column based on it's name

col = ( 0 ... table.columnCount ).find{ table.getColumnInfo( it ).name == 'dec' }
decs= table.columnIterator(col).collect{it}
                

Removing a column from a table

To define a new table that is the same as an existing table t, but with column 3 remove, say:

newTable = t.removeColumn(3)
                        

Adding a constant column to a table

To define a new table, based on an existing table, but with a new column of a constant value '5'

meta = astrogrid.tableHelper.newColumnInfo("column-name")
newTable = table.addColumn(meta,5);
        

Adding a computed column to a table

To define a new table, based on an existing table, but with a new column whose values are computed from other cells in the row:

meta = astrogrid.tableHelper.newColumnInfo("column-name")
newTable = table.addColumn(info,{ it[1] * 3 + it[4]})
  

To define a compute column, the value passed in is a groovy closure. This will be passed a list containing the values of the other cells in the row - the value it returns is used as the value for the computed cell

Building a table from scratch

If you need to build up a table bit by bit, it's best to create a mutable table, as follows

cols = [
   astrogrid.tableHelper.newColumnInfo("ra"),
   astrogrid.tableHelper.newColumnInfo("dec"),
   astrogrid.tableHelper.newColumnInfo("radius")
                ]
mutableTable = astrogrid.tableHelper.newMutableTable(cols);
                

The mutable table provides methods for adding rows, and setting cell values

It's also possible to create a mutable table that has the same structure as an existing table (although it will not contain the table's data)

mutableTable = astrogrid.tableHelper.newMutableTableFromTemplate(table)
        

Fine-grain table modification

If you need to do table manipulation that can't be expressed as new columns, then it is possible to create a mutable copy of the table, as follows. The copy have the same structure and contain the same data as the original

mutableCopy = table.asMutableTable()
        

Working with VOSpace

Using VOSpaceClient

The following example creates a new date-stamped folder in vospace, and then loads the contents of a URL into a vospace file in this new directory.

vospace = astrogrid.createVoSpaceClient(user)
newDirIvorn = astrogrid.objectBuilder.newIvorn(homeIvorn,"example-" + astrogrid.ioHelper.dateStamp())
vospace.newFolder(newDirIvorn)
target = astrogrid.objectBuilder.newIvorn(newDirIvorn,'slashdot.html')
vospace.putUrl('http://www.slashdot.org',target,false)
                

The first line creates a new vospace client, which will act under the permissions of the current user - user is a predefined JEScript object that represents the owner of the current workfow.

An ivorn pointing to a new directory is then created. This is relative to the homeIvorn, which is another predefined JEScript object that is the Ivorn of the homespace of the owner of the current workflow

The new folder is created, and then a file ivorn is computed relative to this. Finally, the vospace client is told to fetch the contents of a url and save it to this target ivorn.

System Information

Check server version

try {
 jes.info("Scripting version :" + astrogrid.version)
} catch (Exception e) {
  jes.warn(e)
}
try {
jes.info("JES version: " + jes.version)
} catch (Exception e) {
jes.warn(e)
}

This script will send two messages, with version info for the scripting library, and then the jes server. The version information is at present a space-separated list of bugzilla numbers that this component implements. The version can be checked programmatically by searching for a particular substring with these version reports.

Groovy Programming

This section gives examples of how to do common things in groovy

Manipulating Dates

import java.util.Calendar
interval = ['start':'2002-03-14 01:38:00'  , 'end': '2002-03-14 01:45:00' ]
cal = Calendar.getInstance()
df = new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss')
cal.setTime(df.parse(interval.start))
cal.set(Calendar.MINUTE,0)
refstarttime = df.format(cal.time)

cal.setTime(df.parse(interval.end))
cal.set(Calendar.MINUTE,0)
cal.add(Calendar.HOUR,1)
refendtime = df.format(cal.time)

This script shows how to parse a string into a date object, alter values (in this case round up and down to the hour), and then write out to another string. Time calculations should be done with care, using the appropriate classes, rather than straight string manipulation - otherwise periods that cross midnight will fail.

Date patterns are documented at: http://java.sun.com/j2se/1.4.2/docs/api/java/text/DateFormat.html

Templates

import groovy.text.SimpleTemplateEngine
// set up the query template - although this could also be read from a file
queryTemplate = 'query with ${var1} < ${var2} \nwhere ${foo}'
// set up values to substitute
binding = ['var1':'23','var2':'RA','foo':'x = 3']
// create template engine
engine = new SimpleTemplateEngine()
template = engine.createTemplate(queryTemplate)
query = template.make(binding)

The above example illustrates how to construct templates, and then how to apply a template to a set of bindings.