Skip to content

A web service implementation of the online exposure age calculator

September 26, 2014

What is this?

This posting is to point out the existence of a new interface to the online exposure age calculator. This is a “web service” implementation, which means that when one submits an HTTP request, the server returns only a compact representation of the calculator results in a structured data format, rather than as a complete web page. It’s not really compliant with formal web service protocols (except possibly by accident); basically it just responds to a HTTP GET request with an XML object rather than a web page. The idea here is that other software can simply query the online exposure age calculator to obtain an exposure age, rather than doing the calculations itself. The purpose of building this is to enable a database project for Antarctic exposure age data that I am working on and that will, presumably, be described here in a subsequent post.

Specifically, it works like this:

1. Submit a HTTP “GET” request to the calculator Octave server at the following address:

The GET request should have the following fields:



The ‘text_block’ field is simply the text string that you would paste into the input window of the online calculator, with appropriate HTML escape strings (these are the %20 character strings to denote spaces) inserted. Multiple-line input should be supported.

So a complete URL would look like:

The response to this will be an XML object that looks like:


Basically this is an XML representation of the exposure ages (the t10St, t10Lm, t26St, t26Lm elements), the internal uncertainties (the delt_int… elements), and the external uncertainties (the delt_ext… elements). The code attempts to gracefully pass errors in the “diagnostics” element, so if you make an input format error you should get exposure ages of zero with some information in the diagnostics element about what happened.

Some important features:

1. Only reports exposure ages via the “St” and “Lm” scaling schemes. This speeds things up a lot. For discussion of why, see here.

2. You can also submit optional fields P10_St, delP10_St, P10_Lm, delP10_Lm, P26_St, delP26_St, P26_Lm, delP26_Lm to force use of non-default production rates. Theoretically it should manage the situation where only some of these are supplied as inputs and use default production rates for the others. Note that this deviates from the general policy of not allowing users to randomly enter arbitrary production rates, but the thinking is that if you have gotten far enough into this that you are coding your own interface to the server, you understand the concept that a reference production rate is a scaling-scheme-specific representation of a calibration data set and not an independent parameter that you get to futz with as you like. For tabulations of reference production rates associated with specific calibration data sets, see here.

Other comments:

The code is basically the same as in the rest of the online exposure age calcuator. It should give the same results.

Note that although this has been reasonably well tested, I am not sure this will actually work in all circumstances. Consider it developmental.

Although I’ve attempted to catch formatting errors that are reasonably likely to happen, it is likely that there are some formatting errors that will crash it, in which case there will be no response.

If you want to develop something to use this, especially if it is high volume, you might want to talk to me about it. I have no idea how fast it will run.

In general, if you make use of this to do anything useful, I would appreciate your letting me know.

Please avoid embedding URLs for this service in web pages, which would create unnecessary search engine traffic on the web server.

What can you do with this?

You can write dynamic web pages that calculate exposure ages online using data generated from a database. That’s what I’m trying to do.

You can access the exposure age calculator  directly from within MATLAB or other software without cutting and pasting into the web page or running the code locally. This seems potentially useful. Of course, you need a live internet connection.

You can write iPhone apps that calculate exposure ages. This is not high on my priority list.

Note that you could have done this already using the existing interface with POST requests, but you would have to do much more work to parse the resulting web pages. All this new interface does is simplify things a bit and make it work with XML parsers.

Here are some examples.

Here is an example of how one might use this in MATLAB, using the ‘urlread’ function.


% Utilizes online exposure age calculator interface

% Enter data
sample_name = 'PH-1'
lat = 41.3567;
long = -70.7348;
elv = 91;
atm = 'std';
thick = 4.5;
rho = 2.7;
shielding = 1;
erate = 8e-5;
N10 = 123500;
delN10 = 3700;
std10 = 'KNSTD';
N26 = 712400;
delN26 = 31200;
std26 = 'KNSTD';

% Assemble fields for GET request 

mlmfile = 'al_be_age_many_v22_ws';

text_block = [sample_name ' ' sprintf('%0.4f',lat) ' ' sprintf('%0.4f',long) ' ' sprintf('%0.0f',elv) ];
text_block = [text_block ' ' atm ' ' sprintf('%0.1f',thick) ' ' sprintf('%0.2f',rho) ' ' sprintf('%0.4f',shielding)];
text_block = [text_block ' ' sprintf('%0.2e',erate) ' ' sprintf('%0.0f',N10) ' ' sprintf('%0.0f',delN10) ' ' std10];
text_block = [text_block ' ' sprintf('%0.0f',N26) ' ' sprintf('%0.0f',delN26) ' ' std26];

% Specify URL
ws_url = '';

% Use urlread to query exposure age server and get XML data
xmldata = urlread(ws_url,'get',{'mlmfile',mlmfile,'text_block',text_block});

% Use lame regexp calls to parse XML because the MATLAB XML parser appears
% to operate only on files. 
s.t10St = regexp(xmldata,'<t10St>([\d]*)</t10St>','tokens');
s.int10St = regexp(xmldata,'<delt10_int_St>([\d]*)</delt10_int_St>','tokens');
s.ext10St = regexp(xmldata,'<delt10_ext_St>([\d]*)</delt10_ext_St>','tokens');
s.t10Lm = regexp(xmldata,'<t10Lm>([\d]*)</t10Lm>','tokens');
s.int10Lm = regexp(xmldata,'<delt10_int_Lm>([\d]*)</delt10_int_Lm>','tokens');
s.ext10Lm = regexp(xmldata,'<delt10_ext_Lm>([\d]*)</delt10_ext_Lm>','tokens');
s.t26St = regexp(xmldata,'<t26St>([\d]*)</t26St>','tokens');
s.int26St = regexp(xmldata,'<delt26_int_St>([\d]*)</delt26_int_St>','tokens');
s.ext26St = regexp(xmldata,'<delt26_ext_St>([\d]*)</delt26_ext_St>','tokens');
s.t26Lm = regexp(xmldata,'<t26Lm>([\d]*)</t26Lm>','tokens');
s.int26Lm = regexp(xmldata,'<delt26_int_Lm>([\d]*)</delt26_int_Lm>','tokens');
s.ext26Lm = regexp(xmldata,'<delt26_ext_Lm>([\d]*)</delt26_ext_Lm>','tokens');
% Convert to numbers; for loop accommodates multiple samples
for a = 1:length(s.t10St);
    n.t10St(a) = str2num(char(s.t10St{a}(1)));
    n.t10Lm(a) = str2num(char(s.t10Lm{a}(1)));
    n.t26St(a) = str2num(char(s.t26St{a}(1)));
    n.t26Lm(a) = str2num(char(s.t26Lm{a}(1)));
    n.int10St(a) = str2num(char(s.int10St{a}(1)));
    n.int10Lm(a) = str2num(char(s.int10Lm{a}(1)));
    n.int26St(a) = str2num(char(s.int26St{a}(1)));
    n.int26Lm(a) = str2num(char(s.int26Lm{a}(1)));
    n.ext10St(a) = str2num(char(s.ext10St{a}(1)));
    n.ext10Lm(a) = str2num(char(s.ext10Lm{a}(1)));
    n.ext26St(a) = str2num(char(s.ext26St{a}(1)));
    n.ext26Lm(a) = str2num(char(s.ext26Lm{a}(1)));
    str = ['Sample ' int2str(a) '-- t10St: ' int2str(n.t10St(a)) ' +/- ' int2str(n.int10St(a)) '(' int2str(n.ext10St) ')'];
    str = [str ' t10Lm: ' int2str(n.t10Lm(a)) ' +/- ' int2str(n.int10Lm(a)) '(' int2str(n.ext10Lm(a)) ')'];
    str = [' t26St: ' int2str(n.t26St(a)) ' +/- ' int2str(n.int26St(a)) '(' int2str(n.ext26St) ')'];
    str = [str ' t26Lm: ' int2str(n.t26Lm(a)) ' +/- ' int2str(n.int26Lm(a)) '(' int2str(n.ext26Lm) ')'];

Here is an example of how one might use this in a Python script, using Python modules for getting URLs and parsing XML. This is pretty lame because I am not great at Python. This uses the option to pass nonstandard production rates.


import urllib2
import urllib
import xml.etree.ElementTree as xmlET

# Make up a text block
text_block = "PH-1 41.3567 -70.7348 91 std 4.5 2.70 1.0000 8.00e-05 123500 3700 KNSTD 712400 31200 KNSTD"

# Form URL
this_url_string =     ("" \
    + "text_block=" + urllib.quote(text_block) \
    +  "&P10_St=3.93089&delP10_St=0.18857" \
    + "&P10_Lm=3.87397&delP10_Lm=0.18737")

# Read response
response = urllib2.urlopen(this_url_string)

# Parse XML
tree = xmlET.fromstring(

# Print results
print "t10St (yr) = " + tree.findall("./exposureAgeResult/t10St")[0].text  + \
    " +/- " + tree.findall("./exposureAgeResult/delt10_int_St")[0].text + \
    " (" + tree.findall("./exposureAgeResult/delt10_ext_St")[0].text + ")\n"
print "t26St (yr) = " + tree.findall("./exposureAgeResult/t26St")[0].text  + \
    " +/- " + tree.findall("./exposureAgeResult/delt26_int_St")[0].text + \
    " (" + tree.findall("./exposureAgeResult/delt26_ext_St")[0].text + ")\n"
print "t10Lm (yr) = " + tree.findall("./exposureAgeResult/t10Lm")[0].text  + \
    " +/- " + tree.findall("./exposureAgeResult/delt10_int_Lm")[0].text + \
    " (" + tree.findall("./exposureAgeResult/delt10_ext_Lm")[0].text + ")\n"
print "t26Lm (yr) = " + tree.findall("./exposureAgeResult/t26Lm")[0].text  + \
    " +/- " + tree.findall("./exposureAgeResult/delt26_int_Lm")[0].text + \
    " (" + tree.findall("./exposureAgeResult/delt26_ext_Lm")[0].text + ")\n"
print format(tree[1].tag) + ": " + format(tree[1].text) + "\n"






Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: