#!/bin/bash
#
# ulSXRT    [-r RADIUS] [-s NSIGMA]  {-m} {-d} {-h} ra(deg) dec(deg)
# provids upper limit at sky position (ra,dec) based on Swift XRT data
# returns json structure
# e.g.
# ulSXRT -s5 -r10 90.0 -1.0 
# returns 5-sigma limit at ra=90deg, dec=-1deg and  radius=10"

#-----------------------------------------------------------------------
RADIUS=20; SIGMA=3; TYPE="all"; MANUAL=; HELP=;
#-----------------------------------------------------------------------

while getopts r:s:tmh OPTVAL
do
    case $OPTVAL in
	r) RADIUS=$OPTARG;;
	s) SIGMA=$OPTARG;;
	t) TYPE=;;
	m) MANUAL=1;;
	h) HELP=1;;
	*) echo "ulSXRT -h for help"; exit -1
    esac
done
shift $((OPTIND-1))

if [ $HELP ]; then
    printf "\tulSXRT  [-r RADIUS] [-s NSIGMA]  {-d} {-m} {-h} ra(deg) dec(deg)\n"
    printf "\tupper limit at sky position (ra,dec) based on Swift XRT data\n"
    printf "\t-r.. radius in arcseconds [20]\n"
    printf "\t-s.. confidence level in sigma [3]\n"
    printf "\t-d.. use deepest exposure; default all exposures\n"
    printf "\t-m.. print manual which explains output\n"
    exit;
fi

! [ $TYPE ] && TYPE="deepest"

#-----------------------------------------------------------------------
# the heavy lift!
#-----------------------------------------------------------------------
if [ $# -eq 2 ]; then
    curl -s "https://www.swift.ac.uk/2SXPS/processUL_JSON.php?RA="$RA"&DEC="$DEC"&"$TYPE"=1&soft=1&medium=1&hard=1&total=1&sigma="$SIGMA"&forceUL=1&notESA=1"  | tee a.json
    exit
fi

if [ $MANUAL ]; then

cat << EOF
------------------------------------------------------------------------
upper limit service from Swift XRT
manual for "ulSXRT"
------------------------------------------------------------------------
These nmtes provided by P. Eavns, Leicester University, UK explain
the structure of the JSON output object.

If an error occurs the JSON object will have the keys: ERRORCODE
and ERRORTEXT describing the problem and giving a code that should
make it easier for me to debug.  If the position selected is not
covered by 2SXPS, then the object will have the key NOFIELD.
Otherwise, the JSON should have the following entries

* RA  - gives the RA queried (mainly in case you gave a name, this
tells you how it was resolved). Decimal degrees, J2000 
* Dec - give the Dec queried. . Decimal degrees, J2000

If the input position matches a 2SXPS source:
	* SOURCEMATCH = the name of the source.
	*  SOURCEDIST = the distance from your input position to the 2SXPS source.

* RESULTS - a list, comprising one entry per dataset returned (i.e.
only one entry if "deepest" was set). Each entry in the list will
have the following keys:


* "Obs" = the observation ID in 2SXPS (normally a Swift obsid, but
for stacked image will be, e.g. "Stacked Image 10000009398")
* "start" = the start time of the dataset, in UT
* "stop" = the stop time of the dataset, in UT
* "exp" = exposure time *at the requested position*
* "ImageExp" = the nominal, on-axis exposure time of the dataset
* "TOTALFROMCAT". If the position corresponded to a detected source
in this dataset/band in 2SXPS, then the value returned is the
count-rate of that detection (cf. fn1 above). In that case, this
value is "yes", otherwise "no".

[Optional: if the n-sigma lower-limit on the count-rate is non zero:]
* TOTALRATE = 0.3-10 keV band count rate in XRT ct/sec
* TOTALRATEPOS = 1-sigma positive error on the above
* TOTALRATENEG = 1-sigma negative error on the above

[Optional: if the n-sigma lower-limit is zero, or 'forceUL' was set]:
*TOTALUL = n-sigma upper limit in the 0.3-10 keV band, XRT ct/sec

* TOTALC = Total counts in a 12 pixel circle centred on the source
* TOTALB = Total counts in the background map in the same 12 pixel circle.
* TOTALCF = A correction factor for bad columns and vignetting etc.

IMPORTANT NOTE: the "exp" keyword is the exposure at the source
position, i.e. this includes vignetting. However, the "CF" value
corrects for vignetting. Therefore, if you want to use the C/B/CF
values to calculate rates or arbitrary confidence intervals yourself,
you must use the "ImageExp" value for the exposure (i.e. rate =
(C-B) * CF /ImageExp).

Then, you also get SOFTFROMCAT, SOFTRATE etc. etc. and MEDIUMFROMCAT,
HARDFROMCAT etc. Obviously, you only get the TOTAL/SOFT/MEDIUM/HARD
keywords for the bands you requested.
EOF

fi

#-----------------------------------------------------------------------
# Notes on the call (from P. Evans, Leicester University)
#-----------------------------------------------------------------------

#* RA: Mandatory. RA in decimal degrees (J2000)
#* DEC: Mandatory. RA in decimal degrees (J2000)
#  [* NAME: You can supply a text name instead of RA/Dec in which
#    case it will try to resolve these via SIMBAD]
#
#* all or deepest: One of these must be supplied and given a value.   
#  This tells the code whether to return an upper limit calculated
#  from every 2SXPS dataset overlapping the input position, or just
#  that with the deepest exposure at that position.
#
#* The arguments "soft", "medium", "hard", "total" identify which
#  of the 2SXPS energy bands you want the upper limits for. You have
#  to supply at least one band.
#
#* sigma: Optional. The confidence level for the upper limits, which
#  defaults to 3 sigma if not specified. This can be up to 5 sigma.
#  NB, where I refer to "n-sigma" below I'm referring to whatever value
#  was supplied here.
#
#* forceUL: Always return an upper limit (fn1). Without this, if the
#  lower-limit on the inferred count rate at the requested sigma level
#  is non-zero then it counts as a detection, and so the count rate
#  (and 1-sigma errors) are reported instead of an upper limit.
#  'forceUL=1' ensures that the upper limit is reported as well.
#
#* "notESA" is really important. This is partly related to the above:
#  the ESA service this interface was built to support always reports
#  a count-rate for a source if the lower-limit is non-zero at the
#  2-sigma level, regardless of the "sigma" parameter entered (this
#  seems odd to me, but it's what they asked me to do). So the "notESA"
#  argument ensures that the decision whether the write a count-rate
#  or not is based on the "sigma" significance, rather than being
#  hard-coded at 2-sigma.
#
#(fn1: If the position actually matches a catalogue detection, an
#  upper limit cannot be reliably calculated: in this case even with
#  forceUL set, you will get the count-rate, more on this in the output
#  section below).  ote that when checking if these are set, for most
#  (except the coordinates) the values don't matter, just the presence
#  of the argument. So "soft=1", "soft=0", "soft=yes" and "soft=no"
#  will all result in soft band data being returned.
