swifttools.ukssdc.data.SXPS moduleJupyter notebook version of this page
This module provides direct access to data in the LSXPS catalogue and some functionality for 2SXPS. Being part of the swifttools.ukssdc.data module it is designed for use where you already know which elements in the catalogue you want to get data for. If you don't know that, for example you want to select them based on their characteristics, you will need the SXPS query module.
I've split the page into sections, linked to from the contents page, so you don't have to read this straight thought but can jump to the point of interest. And (as with the rest of this documentation), this is designed to teach you how to use the API, not to explain details of the SXPS catalogues. For that, you should read (and cite!) the catalogue papers, and view the documentation on the relevant catalogue web pages; both can be accessed via the links above.
OK, first let's import the module, again using a short form to save our fingers and following the pattern adopted throughout:
import swifttools.ukssdc.data.SXPS as uds
There are a number of arguments which are common to many of the functions in this module and it's worth covering them here, so that after this you can dip into the sections you care about without having missed anything important.
Firstly is cat. This argument lets you specify which catalogue you want to access, the default being 'LSXPS'; at the time of writing the only other one available is '2SXPS' and not all functionality exists for that catalogue. The name cat is deliberately chosen to make this tool ambivalent about which side of the Atlantic your spelling originates from.
Secondly is how you identify the object for which you want data, and how those data are indexed when you get them. This is a bit more complicated than it was for GRBs, because for SXPS we can get data for sources, datasets or transients. The arguments by which the objects are identified are:
sourceName or sourceIDsourceName or sourceIDDatasetID or obsID.You can only supply one argument, so if, for example, requesting a dataset, you supply either the DatasetID or the obsID, but not both: this would generate an error. Whichever argument you supply you can either give a single value, or a list/tuple of values. This affects how your data are returned, and we'll return to that in just a moment (the fourth point, below).
Thirdly is the argument bands. This is not ubiquitous but appears sufficiently often that we should consider it here. It is used to define which of the SXPS energy bands you want data for. This can usually be either the string 'all' (the default) or a list/tuple of band names. These refer to the SXPS bands which are:
In some cases the hardness ratios 'HR1' and 'HR2' can be specified in the bands argument as well.
Fourthly we need to note how data are returned. Most functions in this module return a dict containing the data requested for the object; for example, getSourceDetails(sourceID=1) will return a dict of "sourceProperty": "value" pairs for source 1. But as I noted above, the argument specifying which object to get (sourceID, sourceName etc.) can be a list or tuple instead of a single value. In this case, the returned dict will contains keys for each requested object, and those entries will then contain the dict of results. So if we had run getSourceDetails(sourceID=(1,5)) then the returned dict would have had keys '1' and '5', and those would have in turn been dicts with the source details. If we had supplied the sourceName argument instead of sourceID, the keys of our dicts would have been the source names. If this is a bit unclear in the abstract don't worry, it will be obvious what we mean when we get into the examples.
For light curves and spectra, data can be saved to disk as well as / instead of being returned as a dict. You can control what happens using the arguments returnData and saveData:
returnData - (default False), whether or not the function should return a dict containing the data.saveData - (default: True), whether or not the function should download the data files from the UKSSDC website and write them to disk.You can set both to True to return and save. You can also set both to False and waste compute time, network bandwidth and carbon dioxide, but maybe don't do this. And you can returnData and then subsequently save what you got, or some subset thereof. If you've read the GRB page this will all look familiar; if not, don't worry, I'm not going to assume you have. If you are using saveData=True you may also need the clobber parameter. This specifies whether existing files should be overwritten, and is False by default.
And lastly, many of the functions have an argument skipErrors which is False by default. This -- and I know it's going to shock you -- tells the function to skip over certain errors and just continue. This is normally use for functions that can act on multiple objects, for example when saving light curves for several sources, and you don't want an error affecting one source or curve to cause the whole process to fail. I won't point this out when it occurs below, as it just adds too much information to an already-dense document, but you can always use help() to check whether a function supports this argument.
Right, that was a lot of preliminary, so let's just get to work. We'll start off with calculating an upper limit.
You can generate upper limits at any position covered by the SXPS catalogues using the cryptically-named getUpperLimits() function. There are quite a lot of parameters you can play with and we'll come to them, but let's jump straight in with a demonstation.
ul = uds.getUpperLimits(position='334.502058 -8.256481', cat='LSXPS')
getUpperLimits() always returns its result (there is no saveData option) so we captured it in the ul variable wich is a dict, let's explore it:
ul.keys()
dict_keys(['ResolvedRA', 'ResolvedDec', 'ResolvedInfo', 'ULData'])
The first few keys tell us how the position argument was parsed, and we'll come to that in a moment. The actual upper limit is contained in 'ULData', which we can examine:
ul['ULData']
| StartTime | StopTime | ObsID | SourceExposure | ImageExposure | Total_UpperLimit | Total_Counts | Total_BGCounts | Total_CorrectionFactor | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 2006-04-28 02:19:58 | 2019-10-18 21:06:16 | 10000018414 | 50071.75 | 55395.777344 | 0.000321 | 17.0 | 22.100154 | 1.326975 |
This is a pandas DataFrame object, and it gives you the upper limit (in the total band) along with some details about where the upper limit came from - see the online documentation for details.
You may be wondering why this is a DataFrame, when there's only a single entry. The answer is that there is only a single entry because we just accepted the default parameters, which returns an upper limit calculated from the dataset with the deepest exposure at the source location (and only in the total band). We can change this behaviour using the parameters whichData and bands. The latter was discussed in the General notes. whichData is a string and can be either:
So let's ask instead for upper limits in all bands and all datasets; this will take a few moments longer to calculate:
ul = uds.getUpperLimits(position='77.969042, -62.324167',
cat='LSXPS',
bands='all',
whichData='all')
And now let's see what the 'ULData' entry looks like:
ul['ULData']
| StartTime | StopTime | ObsID | SourceExposure | ImageExposure | Total_UpperLimit | Total_Counts | Total_BGCounts | Total_CorrectionFactor | Soft_UpperLimit | ... | Soft_BGCounts | Soft_CorrectionFactor | Medium_UpperLimit | Medium_Counts | Medium_BGCounts | Medium_CorrectionFactor | Hard_UpperLimit | Hard_Counts | Hard_BGCounts | Hard_CorrectionFactor | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2009-01-11 02:16:35 | 2021-03-13 23:46:13 | 10000020308 | 31007.108434 | 36730.542969 | 0.002796 | 575.0 | 579.319382 | 1.422133 | 0.001539 | ... | 175.639068 | 1.422133 | 0.001776 | 240.0 | 233.679986 | 1.422133 | 0.001384 | 166.0 | 141.947255 | 1.422133 |
| 1 | 2018-05-10 22:06:39 | 2018-05-10 23:58:24 | 00831816000 | 1032.104819 | 1033.007600 | 0.080617 | 508.0 | 513.051351 | 1.227909 | 0.043683 | ... | 150.637800 | 1.227909 | 0.051651 | 210.0 | 210.598484 | 1.227909 | 0.043812 | 151.0 | 151.527823 | 1.227909 |
| 2 | 2018-05-12 09:31:05 | 2018-05-12 12:47:20 | 00831816002 | 135.198780 | 190.554800 | 0.072142 | 1.0 | 0.054678 | 1.703401 | 0.052857 | ... | 0.094047 | 1.703401 | 0.072338 | 1.0 | 0.032169 | 1.703401 | 0.052857 | 0.0 | 0.022493 | 1.703401 |
| 3 | 2018-05-13 06:14:02 | 2018-05-13 11:13:57 | 00831816003 | 1302.687500 | 1313.825200 | 0.010449 | 3.0 | 0.533764 | 1.218156 | 0.007300 | ... | 0.305089 | 1.218156 | 0.009208 | 2.0 | 0.112232 | 1.218156 | 0.005490 | 0.0 | 0.101873 | 1.218156 |
| 4 | 2018-05-14 06:04:07 | 2018-05-14 11:10:09 | 00831816004 | 3420.219512 | 3913.895300 | 0.004883 | 13.0 | 13.770363 | 1.348728 | 0.005053 | ... | 0.518664 | 1.348728 | 0.005114 | 5.0 | 0.348361 | 1.348728 | 0.003901 | 3.0 | 0.459833 | 1.348728 |
| 5 | 2018-05-15 06:00:45 | 2018-05-15 08:02:17 | 00831816005 | 2981.200000 | 2993.716200 | 0.005406 | 11.0 | 11.769374 | 1.212614 | 0.005320 | ... | 0.393220 | 1.212614 | 0.005370 | 4.0 | 0.290672 | 1.212614 | 0.004587 | 3.0 | 0.459679 | 1.212614 |
| 6 | 2018-05-16 10:52:40 | 2018-05-16 23:46:36 | 00831816006 | 3458.195122 | 3565.380600 | 0.003669 | 6.0 | 7.200492 | 1.225049 | 0.002032 | ... | 0.509580 | 1.225049 | 0.003897 | 3.0 | 0.448037 | 1.225049 | 0.003861 | 3.0 | 0.554207 | 1.225049 |
| 7 | 2018-05-17 01:13:28 | 2018-05-17 22:01:36 | 00831816007 | 3627.719512 | 3903.866100 | 0.004593 | 13.0 | 13.794047 | 1.265324 | 0.003078 | ... | 0.559181 | 1.265324 | 0.004118 | 9.0 | 9.340048 | 1.265324 | 0.003109 | 2.0 | 0.452695 | 1.265324 |
| 8 | 2018-05-18 02:43:21 | 2018-05-18 09:18:37 | 00831816008 | 3012.913580 | 3151.676100 | 0.005775 | 5.0 | 0.830020 | 1.276016 | 0.004645 | ... | 0.315025 | 1.276016 | 0.003214 | 1.0 | 0.208594 | 1.276016 | 0.003167 | 1.0 | 0.365036 | 1.276016 |
| 9 | 2018-05-19 02:35:28 | 2018-05-19 07:23:19 | 00831816009 | 2671.634146 | 2720.420500 | 0.005043 | 3.0 | 0.748863 | 1.241829 | 0.003598 | ... | 0.280363 | 1.241829 | 0.003603 | 1.0 | 0.265807 | 1.241829 | 0.003587 | 1.0 | 0.315610 | 1.241829 |
| 10 | 2018-05-20 02:26:59 | 2018-05-20 07:29:29 | 00831816010 | 4908.426829 | 5282.881100 | 0.004115 | 7.0 | 1.604165 | 1.309514 | 0.003175 | ... | 0.640918 | 1.309514 | 0.002843 | 3.0 | 0.317096 | 1.309514 | 0.001466 | 0.0 | 0.598214 | 1.309514 |
| 11 | 2018-05-21 02:19:57 | 2018-05-21 13:56:37 | 00831816011 | 4487.000000 | 4620.953900 | 0.004481 | 7.0 | 1.505219 | 1.235999 | 0.002971 | ... | 0.686730 | 1.235999 | 0.002603 | 2.0 | 0.302586 | 1.235999 | 0.002530 | 2.0 | 0.599897 | 1.235999 |
12 rows × 21 columns
This time we have more rows (12 when I'm writing this, but LSXPS is living, so this could increase before you run it). We also have a lot more columns because of the bands='all' argument, you may need to scroll to the right (or give the command ul['ULData'].columns) to see them all, but basically you have upper limits and associated details in all of the bands now.
If you were paying close attention, you'll noticed that I gave a different position as well this time, which I did to show you something else. Let's have a look at our ul object returned by the above call:
ul.keys()
dict_keys(['ResolvedRA', 'ResolvedDec', 'ResolvedInfo', 'DetData', 'ULData'])
Note the new key 'DetData'. If this is present, it means that the input position is near to (within 30" of) a source in the catalogue you searched. If you already knew this, and wanted an upper limit close to the source then you don't need to worry about this. However, it may be telling you that your position corresponds to a known source, in which case, upper limits are probably not appropriate.
If this key is set, its value tells you about the source(s) in question:
ul['DetData']
| Distance | SourceName | |
|---|---|---|
| 0 | 2.4 | LSXPS J051152.3-621925 |
Here there is a single source 2.4" from the input position (the "Distance" field is always in arcsec), and you would often want to get the light curve for the source using the getLightCurves() function (described below), rather than getting upper limits. Of course, you may not want the light curve; maybe you really are placing limits on the flux of a source really near to the catalogued ones, for this reason the upper limits were still given.
There are a few other options that let you control your upper limits:
sigma (default: 3) - sets the confidence level (in Gaussian sigmas) of the desired upper limit.detThresh - only used if detectionsAsRates is True. This sets the confidence level needed to report a detection. By default it is the same as sigma but doesn't have to be. For example, you can set detThresh=2, sigma=3. This will cause a 3-sigma upper limit to be reported, unless the source is detected at the 2-sigma level, in which case the count-rate will be provided (if you think this is weird, I agree, but this feature was specifically requested, and I'm not here to judge. Much).detectionsAsRates (default: False) - tells the upper limit server to check if the count-rate value corresponds to a detection, and if so, to report the count-rate and 1-sigma error as well as the upper limit.skipDetections (default False) - causes datasets in which there is a catalogue detection within 30" of your input position to be skipped.Let's do a quick demonstration, because detectionsAsRates results in more columns in the output:
ul = uds.getUpperLimits(position='77.969042, -62.324167',
cat='LSXPS',
whichData='all',
detectionsAsRates=True)
(Note, I removed the bands argument so we just get the total band again).
Let's have a look at the results:
ul['ULData']
| StartTime | StopTime | ObsID | SourceExposure | ImageExposure | Total_UpperLimit | Total_Rate | Total_RatePos | Total_RateNeg | Total_Counts | Total_BGCounts | Total_CorrectionFactor | Total_IsDetected | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2009-01-11 02:16:35 | 2021-03-13 23:46:13 | 10000020308 | 31007.108434 | 36730.542969 | 0.002796 | NaN | NaN | NaN | 575.0 | 579.319382 | 1.422133 | False |
| 1 | 2018-05-10 22:06:39 | 2018-05-10 23:58:24 | 00831816000 | 1032.104819 | 1033.007600 | 0.080617 | NaN | NaN | NaN | 508.0 | 513.051351 | 1.227909 | False |
| 2 | 2018-05-12 09:31:05 | 2018-05-12 12:47:20 | 00831816002 | 135.198780 | 190.554800 | 0.072142 | NaN | NaN | NaN | 1.0 | 0.054678 | 1.703401 | False |
| 3 | 2018-05-13 06:14:02 | 2018-05-13 11:13:57 | 00831816003 | 1302.687500 | 1313.825200 | 0.010449 | NaN | NaN | NaN | 3.0 | 0.533764 | 1.218156 | False |
| 4 | 2018-05-14 06:04:07 | 2018-05-14 11:10:09 | 00831816004 | 3420.219512 | 3913.895300 | 0.004883 | NaN | NaN | NaN | 13.0 | 13.770363 | 1.348728 | False |
| 5 | 2018-05-15 06:00:45 | 2018-05-15 08:02:17 | 00831816005 | 2981.200000 | 2993.716200 | 0.005406 | NaN | NaN | NaN | 11.0 | 11.769374 | 1.212614 | False |
| 6 | 2018-05-16 10:52:40 | 2018-05-16 23:46:36 | 00831816006 | 3458.195122 | 3565.380600 | 0.003669 | NaN | NaN | NaN | 6.0 | 7.200492 | 1.225049 | False |
| 7 | 2018-05-17 01:13:28 | 2018-05-17 22:01:36 | 00831816007 | 3627.719512 | 3903.866100 | 0.004593 | NaN | NaN | NaN | 13.0 | 13.794047 | 1.265324 | False |
| 8 | 2018-05-18 02:43:21 | 2018-05-18 09:18:37 | 00831816008 | 3012.913580 | 3151.676100 | 0.005775 | 0.001688 | 0.001065 | -0.000786 | 5.0 | 0.830020 | 1.276016 | True |
| 9 | 2018-05-19 02:35:28 | 2018-05-19 07:23:19 | 00831816009 | 2671.634146 | 2720.420500 | 0.005043 | NaN | NaN | NaN | 3.0 | 0.748863 | 1.241829 | False |
| 10 | 2018-05-20 02:26:59 | 2018-05-20 07:29:29 | 00831816010 | 4908.426829 | 5282.881100 | 0.004115 | 0.001337 | 0.000750 | -0.000582 | 7.0 | 1.604165 | 1.309514 | True |
| 11 | 2018-05-21 02:19:57 | 2018-05-21 13:56:37 | 00831816011 | 4487.000000 | 4620.953900 | 0.004481 | 0.001470 | 0.000810 | -0.000628 | 7.0 | 1.505219 | 1.235999 | True |
Be sure to scroll to the right to see all the columns, or run the cell below:
ul['ULData'].columns.tolist()
['StartTime',
'StopTime',
'ObsID',
'SourceExposure',
'ImageExposure',
'Total_UpperLimit',
'Total_Rate',
'Total_RatePos',
'Total_RateNeg',
'Total_Counts',
'Total_BGCounts',
'Total_CorrectionFactor',
'Total_IsDetected']
This time, the DataFrame has extra columns. 'Total_Rate', 'Total_RatePos' and 'Total_RateNeg' columns are are NaN when the source is undetected, otherwise contains the rate and 1-sigma error. There is also a column 'Total_IsDetected' which is a boolean column indicating whether or not the source was detected in each dataset (a source is 'detected' if the lower-limit on its count rate is >0, at the confidence level set by the detThresh parameter, above).
We're nearly done, but there are two more things to mention.
First, let's come back to those 'Resolved' keys in the returned dict:
ul.keys()
dict_keys(['ResolvedRA', 'ResolvedDec', 'ResolvedInfo', 'DetData', 'ULData'])
Those keys starting "Resolved" tell you how the input position was parsed. Let's look at them:
print(f"ResolvedRA: {ul['ResolvedRA']}")
print(f"ResolvedDec: {ul['ResolvedDec']}")
print(f"ResolvedInfo: {ul['ResolvedInfo']}")
ResolvedRA: 77.96904
ResolvedDec: -62.32417
ResolvedInfo: Parsed '77.969042, -62.324167' as (77.96904, -62.32417)
As you may expect, 'ResolvedRA' and '-Dec' are just the RA and Dec (in decimal degrees), ResolvedInfo gives you some text.
You don't have to use the position argument to give the upper limit position, the input options are the same as for a cone search in the query module, that is:
position - as used above, a free-form coordinate string. It tries to support everything I can think of, but if you do something evil (and why would you?) like giving RA in sexagasimal and Dec in decimal then I can't promise it will work (and will be outrageously rude if you complain). But hey, that's why the Resolved* keys are returned, so you can check things.name - the name of a catalogued object, that the system will attempt to resolve using some standard services like SIMBAD, MARS and TNS.RA and Dec - You can explicitly provide the RA and Dec using these arguments, which can receive either a decimal number (assumed to be degrees) or an astropy.coordinates.Angle object.In the latter case the 'Resolved*' keys will not be present in the returned dict since no parsing/resolving was needed.
I should also mention the timeFormat argument. In all the examples above, the 'StartTime' and 'StopTime' appeared as calendar dates, but you can change this by setting timeFormat to one of 'MJD', 'TDB', 'MET' (or 'cal', the default). MJD and TBD are standard timesystems and MET is Swift's Mission Elapsed Time.
Of course, as with everything else, I have tried to provide useful docstrings, so help(uds.getUpperLimits) will give you more information.
Calculation of upper limits is not instantaneous, and only a finite number can be found at once. The API waits 5 minutes for a response from the upper limit server. If the limit has not been found in that time, the dict returned by getUpperLimits() will contain the key 'TIMEOUT'. Do not despair! This doesn't mean you can't get an upper limitm it just means you need to wait a moment. The value of the 'TIMEOUT' entry is an identifier that can be used to get your upper limit. So, wait a minute or so, then try:
ul = uds.getFailedUpperLimit(ul['TIMEOUT'])
If the limit has now been calculated then ul will now be the normal upper limit dict. If not, then it will still have the 'TIMEOUT' key, and you can wait a bit and try again. There are two things to note about this:
getFailedUpperLimit() can only return the result once.If the whichData='all' argument was passed, we may then want to combine upper limits from some subset of the results. For this we can use the mergeUpperLimits() function. This is actually one of the handful of 'common' functions in the top-level module, so we will need to import that module:
import swifttools.ukssdc as uk
I'm not going to go into details here of how this function works, and what all the options are for it, for that you should see the page describing the common functions. Let's just give a simple demo:
merged = uk.mergeUpperLimits(ul['ULData'],
verbose=True,
conf=0.95,
rows=ul['ULData']['ObsID']<"10000000000"
)
merged
Merge does not give a detection in band Total.
Skipping band `Soft` as data are missing
Skipping band `Medium` as data are missing
Skipping band `Hard` as data are missing
{'SourceExposure': 31037.299801963036,
'ImageExposure': 32690.1774,
'Total_UpperLimit': 0.0022251588163850447,
'Total_Counts': 577.0,
'Total_BGCounts': 564.8623355896407,
'Total_CorrectionFactor': 1.2676373917501889,
'Total_Rate': nan,
'Total_RatePos': nan,
'Total_RateNeg': nan,
'Total_IsDetected': False}
First, note the rows argument I supplied, which told the code to merge a subset of the data only. What you actually supply is a pandas Series but as demonstrated above, you can use pandas filter syntax to create this. In this case I wanted only the individual observations, so I filtered on ObsID because I know stacked images are the only things with obsIDs>1e10 (but as ObsID is a string column, to keep the leading zeroes, I did a string comparison).
Also, just for fun, I requested a 95% confidence (~2 sigma) rather than the normal 3-sigma upper limit (which is the default).
As you can see (because I turned on verbosity), only the total band was merged because we only have the total band data in our upper limit. And the returned data is a dict that looks very like a single row of the upper limits supplied.
If you want to simply download the full catalogue table, you can use the function getFullCat(). This requires, as a minimum, which table you want to get.
uds.getFullTable(table='sources',
saveData=True,
destDir='/tmp/APIDemo_SXPS_cat',
silent=False)
Making directory /tmp/APIDemo_SXPS_cat
In the above I also turned off silent output, and specified the directory in which to save things.
getFullTable() is one of the functions that takes the options saveData and returnData. In the above I explicitly gave saveData=True even though this is the default.
We could instead have given returnData=True which actually downloads the file, reads it into a DataFrame and then (unless saveData=True), deletes it. By default (unless you specify the destDir argument) this file will be briefly stored in a temporary directory. Let's explore this:
data = uds.getFullTable(table='sources',
returnData=True,
saveData=False,
silent=False,
verbose=True)
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['OK', 'URL', 'FILE', 'APIVersion'])
Checking returned data for required content.
Downloading file `/tmp/tmphxk3n848/LSXPS_Sources.csv`
Saving file `/tmp/tmphxk3n848/LSXPS_Sources.csv`
Removing downloaded file /tmp/tmphxk3n848/LSXPS_Sources.csv
This is just about the only function in which the return type is not a dict but is just the DataFrame:
data
| LSXPS_ID | IAUName | RA | Decl | Err90 | AstromType | l | b | MeanOffAxisAngle | NearestNeighbour | ... | MatchIn4XMM_DR10s | MatchInXMMSL2 | MatchInSwiftFT | MatchIn1SWXRT | MatchInXRTGRB | MatchInSDSS_QSO_DR14 | MatchIn2MASS | MatchInUSNOB1 | MatchIn2CSC | MatchIn2SXPS | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | LSXPS J163700.6+073914 | 249.25254 | 7.65391 | 7.1 | 0 | 23.87352 | 33.29467 | 2.18 | 265.31 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| 1 | 2 | LSXPS J163647.0+074206 | 249.19612 | 7.70193 | 7.3 | 0 | 23.89358 | 33.36643 | 3.57 | 265.31 | ... | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 |
| 2 | 3 | LSXPS J163710.1+074315 | 249.29248 | 7.72102 | 8.3 | 0 | 23.96660 | 33.29055 | 6.36 | 280.47 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| 3 | 4 | LSXPS J115006.7+641942 | 177.52833 | 64.32839 | 6.5 | 0 | 133.53886 | 51.51840 | 6.00 | 1749.80 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| 4 | 5 | LSXPS J155612.3-181111 | 239.05134 | -18.18660 | 5.4 | 0 | 352.81614 | 26.29516 | 7.83 | 571.15 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 278193 | 371055 | LSXPS J104250.9-592332 | 160.71247 | -59.39237 | 7.1 | 0 | 287.21236 | -0.50329 | NaN | 90.76 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 278194 | 371056 | LSXPS J104538.3-593935 | 161.40975 | -59.65987 | 9.9 | 0 | 287.65015 | -0.57371 | NaN | 53.72 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 278195 | 371057 | LSXPS J104354.6-593158 | 160.97773 | -59.53298 | 4.3 | 0 | 287.39755 | -0.56367 | NaN | 21.46 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 278196 | 371058 | LSXPS J104405.1-592706 | 161.02131 | -59.45190 | 6.5 | 0 | 287.37898 | -0.48171 | NaN | 60.31 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 278197 | 371059 | LSXPS J104202.9-593253 | 160.51211 | -59.54815 | 5.4 | 0 | 287.19677 | -0.68872 | NaN | 35.74 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
278198 rows × 234 columns
There are a few other options, which you can read about via the help() function:
format - defaults to 'csv' but can be changed to 'fits', provided that returnData=False.subset - some tables have subsets (e.g. the sources table has a 'clean' and 'ultra-clean' subset). You can request these. So:
data = uds.getFullTable(table='datasets',
destDir='/tmp/APIDemo_SXPS_cat',
saveData=True,
subset='ultra-clean',
format='fits',
silent=False,
verbose=True, )
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['OK', 'URL', 'FILE', 'APIVersion'])
Checking returned data for required content.
Downloading file `/tmp/APIDemo_SXPS_cat/LSXPS_Datasets_ultra-clean.fits`
Saving file `/tmp/APIDemo_SXPS_cat/LSXPS_Datasets_ultra-clean.fits`
I hope the result of this hasn't surprised you!
Since these catalogues are dynamic, the website allows you to access old versions of the catalogues too. This is not yet possible through the API, but will likely be added in the near future.
LSXPS is a dynamic catalogue and as such the tables are in constant flux. For this reason, snapshots of the tables are taken every hour (stored for a limited period of time) and day (stored indefinitely). You may wish to grab one of these old versions. We can do that simply by adding the epoch argument to the call above, where epoch is the timestamp of the table we want. But how do we find that out? We can use the listOldTables() function to see what is available.
oldTabs = uds.listOldTables()
oldTabs.keys()
dict_keys(['hourly', 'daily'])
As you can see, this has returned us something with keys 'hourly' and 'daily', and those themselves are dicts containing keys giving the epochs for which snapshots exist. These can have a lot of entries so I'll just show the first 5 here:
list(oldTabs['hourly'].keys())[0:5]
['2022-08-17 10:00:01 UTC',
'2022-08-17 11:00:02 UTC',
'2022-08-17 12:00:01 UTC',
'2022-08-17 13:00:01 UTC',
'2022-08-17 14:00:02 UTC']
list(oldTabs['daily'].keys())[0:5]
['2022-08-16', '2022-08-17', '2022-08-18', '2022-08-19', '2022-08-20']
If you want to you can look inside those entries too, they list all of the tables available in each snapshot and their filenames, but since every table should be available every time, we shouldn't need to bother.
Any of the keys we've just seen can be supplied as the epoch parameter to getFullTable, so '2022-08-16 21:00:02 UTC', for example, or '2022-08-16' are both valid; but they must be exact matches. So if we want to get a specific table we can do something like:
data = uds.getFullTable(table='sources',
destDir='/tmp/APIDemo_SXPS_cat',
saveData=True,
subset='ultra-clean',
epoch='2022-08-17',
format='fits',
silent=False,
verbose=True, )
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['OK', 'URL', 'FILE', 'APIVersion'])
Checking returned data for required content.
Downloading file `/tmp/APIDemo_SXPS_cat/LSXPS_Sources_ultra-clean_20220817T000001.fits.gz`
Saving file `/tmp/APIDemo_SXPS_cat/LSXPS_Sources_ultra-clean_20220817T000001.fits.gz`
gunzipping /tmp/APIDemo_SXPS_cat/LSXPS_Sources_ultra-clean_20220817T000001.fits.gz
Of course, the point of providing these old tables is for reproducibility: so you can come back to some old work and still get at the same catalogue table. This means that in reality, you will probably only run the listOldTables() function the first time you work on something that needs a static catalogue, and you will select the most recent version (it's probably best to take a 'daily' one, since they are kept forever). You can make a note of the epoch you obtained, and then when you come back to it later, you don't need to do a look up, you just use that epoch.
Before we get into the details of getting products for a given SXPS source, we need to address one thing affecting the LSXPS catalogue: it's dynamic. This means that source names and IDs can change. I'm not going into details now, you can read the paper / catalogue documentation, but we do need to discuss the consequences for this module.
There are basically two ways a source can change.
In the first case, the source name will be changed to match the new position, and its LSXPS_ID will also change. This should not cause a problem; these changes are tracked and so, if you request a source whose identifier has changed, the server can still work out which source you meant, and send its data as requested. And, importantly, if you supplied a list of source names or IDs, the results will be indexed under the name/ID you supplied so as to avoid confusion. I will demonstrate this in a moment, under source details.
The second case is a bit more complicated, but also much rarer, it generally only occurs in crowded fields with faint sources, or in fields with diffuse emission/extended sources where essentially the detections are all spurious. Obviously, in this case the server cannot work out which source you actually wanted, because there are multiple options. Instead, in this case, the returned dict will contain the key 'newerSources', this will list some details of all of the sources that are 'descended' from the one you requested. Let's explore that briefly now -- don't worry about the function being called, just what it returns.
data = uds.getSourceDetails(sourceID=37562,
cat='LSXPS',
silent=True,
verbose=False
)
data.keys()
dict_keys(['newerSources'])
data['newerSources']
[{'LSXPS_ID': 122876,
'IAUName': 'LSXPS J230213.6+585406',
'RA': 345.5570378024,
'Decl': 58.9018094346,
'Err90': 7.00000003739564},
{'LSXPS_ID': 142890,
'IAUName': 'LSXPS J230214.9+585332',
'RA': 345.5623495238,
'Decl': 58.8922237778,
'Err90': 6.32696388551127},
{'LSXPS_ID': 312964,
'IAUName': 'LSXPS J230212.3+585332',
'RA': 345.5512970474,
'Decl': 58.8924563009,
'Err90': 3.50000029414394},
{'LSXPS_ID': 129714,
'IAUName': 'LSXPS J230211.4+585313',
'RA': 345.5475086656,
'Decl': 58.8869740559,
'Err90': 5.96659999571639}]
As you can see, the function we called returned a dict with the 'newerSources' key, and that contains a list of dicts, each entry giving the source identifiers and positions.
For the getLightCurves() and getSpectra() functions (discussed below), if called with returnData=False then of course you won't get this dict; instead you simply won't get any products saved for the affected sources; if silent=False you will get a printed warning, however.
Note: This functionality only exists for LSXPS
The first and easiest thing we can retrieve for a specific SXPS source, or set of sources, is the full set of information about that source. We do that very simply, using the getSourceDetails() function. This only has the standard set of arguments, sourceID or sourceName to specify the source(s) to get, cat to specify the catalogue (which, as noted, for now at least must be LSXPS, which is the default) and the usual silent and verbose.
So, let's jump straight in with an example:
data = uds.getSourceDetails(sourceID=11375, cat='LSXPS')
(I said, truly, that cat is optional but I think it's helpful to make it explicit).
Let's see what that gave us:
data
{'IAUName': 'LSXPS J174527.1-290217',
'LSXPS_ID': 129723,
'RA': 266.3630014378,
'Decl': -29.0381036253,
'Err90': 6.69774772741747,
'AstromType': 0,
'l': 359.893861772376,
'b': -0.0217742847003364,
'MeanOffAxisAngle': 3.84108125,
'Exposure': 2995288.69138474,
'FirstObsDate': '2005-10-25 20:40:00',
'LastObsDate': '2022-08-13 07:07:28',
'FirstObsMET': 151962000,
'LastObsMET': 682063677.879243,
'FirstDetDate': '2005-10-25 20:40:00',
'LastDetDate': '2022-07-21 21:09:30',
'FirstDetMET': 151962000,
'LastDetMET': 680127000,
'FirstBlindDetDate': '2006-04-12 12:59:02',
'LastBlindDetDate': '2022-03-21 12:55:29',
'FirstBlindDetMET': 166535943.547143,
'LastBlindDetMET': 669560158.636463,
'NumObs': 3041,
'NumBlindDetObs': 8,
'NumDetObs': 29,
'DetFlag': 5,
'FieldFlag': 2,
'DetFlag_band0': 5,
'DetFlag_band1': -1,
'DetFlag_band2': -1,
'DetFlag_band3': -1,
'BestDetectionID': 918329,
'OpticalLoadingWarning': 3.4,
'StrayLightWarning': 0,
'NearBrightSourceWarning': 0,
'IsPotentialAlias': 0,
'Rate_band0': 0,
'Rate_band0_pos': 8.1040430324225e-05,
'Rate_band0_neg': 0,
'Rate_band1': 0,
'Rate_band1_pos': 2.22745588346762e-06,
'Rate_band1_neg': 0,
'Rate_band2': 0,
'Rate_band2_pos': 2.35332416405263e-06,
'Rate_band2_neg': 0,
'Rate_band3': 0,
'Rate_band3_pos': 7.68562691439001e-05,
'Rate_band3_neg': 0,
'Counts_band0': 12108,
'Counts_band1': 321,
'Counts_band2': 695,
'Counts_band3': 11097,
'BgCounts_band0': 12570.7137138397,
'BgCounts_band1': 431.447706588311,
'BgCounts_band2': 922.516402062029,
'BgCounts_band3': 11099.3017771393,
'RateCF_band0': 1.5454206547713,
'RateCF_band1': 1.54537083995678,
'RateCF_band2': 1.54537083995678,
'RateCF_band3': 1.54541536076132,
'NonBlindDet_band0': 0,
'NonBlindDet_band1': 0,
'NonBlindDet_band2': 0,
'NonBlindDet_band3': 0,
'UL_band0': 8.1040430324225e-05,
'UL_band1': 1.0737492870398e-05,
'UL_band2': 1.1585040349911e-05,
'UL_band3': 7.68562691439001e-05,
'PeakRate_band0': 0.0260927,
'PeakRate_band0_pos': 0.0173638,
'PeakRate_band0_neg': -0.0123563,
'PeakRate_band1': 0.00503188063105722,
'PeakRate_band1_pos': 0.00382373107360041,
'PeakRate_band1_neg': -0.0025746574516053,
'PeakRate_band2': 0.00459379427993472,
'PeakRate_band2_pos': 0.00353546044905044,
'PeakRate_band2_neg': -0.00238166260231657,
'PeakRate_band3': 0.0252778,
'PeakRate_band3_pos': 0.0140995,
'PeakRate_band3_neg': -0.0106964,
'PvarPchiSnapshot_band0': 3.567857120856388e-11,
'PvarPchiSnapshot_band1': 0.006695645340927814,
'PvarPchiSnapshot_band2': 0.1730414452869046,
'PvarPchiSnapshot_band3': 2.08360328990409e-10,
'PvarPchiSnapshot_HR1': 0,
'PvarPchiSnapshot_HR2': 0,
'PvarPchiObsID_band0': 0.06119498034136439,
'PvarPchiObsID_band1': 1,
'PvarPchiObsID_band2': 1,
'PvarPchiObsID_band3': 1,
'PvarPchiObsID_HR1': 0,
'PvarPchiObsID_HR2': 0,
'HR1': 0.436587,
'HR1_pos': 0.292967,
'HR1_neg': -0.348595,
'HR2': None,
'HR2_pos': None,
'HR2_neg': None,
'GalacticNH': 1.037617e+22,
'WhichPow': 0,
'WhichAPEC': 0,
'PowECFO': 6.04858e-11,
'PowECFU': 9.34817e-11,
'PowFlux': 0,
'PowFlux_pos': 4.90563704093089e-15,
'PowFlux_neg': 0,
'PowUnabsFlux': 0,
'PowUnabsFlux_pos': 7.58173472400446e-15,
'PowUnabsFlux_neg': 0,
'APECECFO': 2.38338e-11,
'APECECFU': 1.04282e-10,
'APECFlux': 0,
'APECFlux_pos': 1.93301522185602e-15,
'APECFlux_neg': 0,
'APECUnabsFlux': 0,
'APECUnabsFlux_pos': 8.4576816691249e-15,
'APECUnabsFlux_neg': 0,
'PowPeakFlux': 1.57823783366e-12,
'PowPeakFlux_pos': 1.0502633340399997e-12,
'PowPeakFlux_neg': -7.4738069054e-13,
'PowPeakUnabsFlux': 2.43918995359e-12,
'PowPeakUnabsFlux_pos': 1.6231975424599997e-12,
'PowPeakUnabsFlux_neg': -1.15508792971e-12,
'APECPeakFlux': 6.2188819326e-13,
'APECPeakFlux_pos': 4.1384533644e-13,
'APECPeakFlux_neg': -2.9449758294e-13,
'APECPeakUnabsFlux': 2.7209989414000003e-12,
'APECPeakUnabsFlux_pos': 1.8107317916e-12,
'APECPeakUnabsFlux_neg': -1.2885396766e-12,
'FixedPowECFO': 6.04858e-11,
'FixedPowECFU': 9.34817e-11,
'FixedPowFlux': 0,
'FixedPowFlux_pos': 4.90563704093089e-15,
'FixedPowFlux_neg': 0,
'FixedPowUnabsFlux': 0,
'FixedPowUnabsFlux_pos': 7.58173472400446e-15,
'FixedPowUnabsFlux_neg': 0,
'FixedAPECECFO': 2.38338e-11,
'FixedAPECECFU': 1.04282e-10,
'FixedAPECFlux': 0,
'FixedAPECFlux_pos': 1.93301522185602e-15,
'FixedAPECFlux_neg': 0,
'FixedAPECUnabsFlux': 0,
'FixedAPECUnabsFlux_pos': 8.4576816691249e-15,
'FixedAPECUnabsFlux_neg': 0,
'InterpPowECFO': None,
'InterpPowECFU': None,
'InterpPowNH': None,
'InterpPowNH_pos': None,
'InterpPowNH_neg': None,
'InterpPowGamma': None,
'InterpPowGamma_pos': None,
'InterpPowGamma_neg': None,
'InterpPowFlux': None,
'InterpPowFlux_pos': None,
'InterpPowFlux_neg': None,
'InterpPowUnabsFlux': None,
'InterpPowUnabsFlux_pos': None,
'InterpPowUnabsFlux_neg': None,
'InterpAPECECFO': None,
'InterpAPECECFU': None,
'InterpAPECNH': None,
'InterpAPECNH_pos': None,
'InterpAPECNH_neg': None,
'InterpAPECkT': None,
'InterpAPECkT_pos': None,
'InterpAPECkT_neg': None,
'InterpAPECFlux': None,
'InterpAPECFlux_pos': None,
'InterpAPECFlux_neg': None,
'InterpAPECUnabsFlux': None,
'InterpAPECUnabsFlux_pos': None,
'InterpAPECUnabsFlux_neg': None,
'P_pow': 0.999999,
'P_APEC': 0.999968,
'FittedPowECFO': None,
'FittedPowECFU': None,
'FittedPowNH': None,
'FittedPowNH_pos': None,
'FittedPowNH_neg': None,
'FittedPowGamma': None,
'FittedPowGamma_pos': None,
'FittedPowGamma_neg': None,
'FittedPowFlux': None,
'FittedPowFlux_pos': None,
'FittedPowFlux_neg': None,
'FittedPowUnabsFlux': None,
'FittedPowUnabsFlux_pos': None,
'FittedPowUnabsFlux_neg': None,
'FittedPowCstat': None,
'FittedPowDOF': None,
'FittedPowReducedChi2': None,
'FittedAPECECFO': None,
'FittedAPECECFU': None,
'FittedAPECNH': None,
'FittedAPECNH_pos': None,
'FittedAPECNH_neg': None,
'FittedAPECkT': None,
'FittedAPECkT_pos': None,
'FittedAPECkT_neg': None,
'FittedAPECFlux': None,
'FittedAPECFlux_pos': None,
'FittedAPECFlux_neg': None,
'FittedAPECUnabsFlux': None,
'FittedAPECUnabsFlux_pos': None,
'FittedAPECUnabsFlux_neg': None,
'FittedAPECCstat': None,
'FittedAPECDOF': None,
'FittedAPECReducedChi2': None,
'HasSpec': 0,
'NearestNeighbour': 26.214956,
'NearestOKNeighbour': 560.4195,
'NearestNeighbour_ID': 361353,
'NearestOKNeighbour_ID': 86151,
'NumExternalMatches': 13,
'NumExternalMatches_slim': 8,
'MatchInROSHRI': 0,
'MatchIn2RXS': 0,
'MatchIn4XMM_DR10': 1,
'MatchIn4XMM_DR10s': 0,
'MatchInXMMSL2': 0,
'MatchInSwiftFT': 0,
'MatchIn1SWXRT': 0,
'MatchInXRTGRB': 0,
'MatchInSDSS_QSO_DR14': 0,
'MatchIn2MASS': 1,
'MatchInUSNOB1': 1,
'MatchIn2CSC': 1,
'MatchIn2SXPS': 1,
'ra_rad': 4.648911380584,
'sindec': -0.4853911645911804,
'cosdec': 0.8742970990097231,
'HPPIX': 146043,
'ProcessedStatus': 7,
'WhenAdded': '2022-04-01 07:28:49',
'WhenModified': '2022-08-23 10:37:55',
'StillDetected': 1,
'HasExternalMatches': 13,
'lcRanges': {'TDB_lo': 2453791.4534803536,
'MJD_lo': 53790.95475808638,
'MET_lo': 162514492.134423,
'TDB_hi': 2459804.7594539933,
'MJD_hi': 59804.25518596347,
'MET_hi': 682063677.8792441,
'rate_lo': 0,
'rate_hi': 0.794781587249083},
'NearestNeighbour_name': 'LSXPS J174525.1-290213',
'NearestOKNeighbour_name': 'LSXPS J174444.4-290234',
'OK': 1,
'Detections': {'NumStacks': 0,
'NumObservations': 8,
'Observations': ObsSourceID DatasetID LSXPS_ID OSNum UsedCorrectedPosition \
0 20588 3681 129723 18 0
1 27526 5076 129723 4 0
2 95523 22539 129723 6 0
3 222435 69055 129723 13 0
4 259658 87005 129723 9 0
5 404884 163302 129723 15 0
6 429562 178529 129723 9 0
7 458370 195511 129723 9 0
NearestNeighbour NearestOKNeighbour Exposure HR1 HR1_pos ... \
0 65.570452 1.000000e+80 1527.104234 0.000243 0.520389 ...
1 111.849930 1.000000e+80 1244.026913 0.190570 0.809429 ...
2 203.195404 1.000000e+80 1257.150513 NaN NaN ...
3 125.186743 1.000000e+80 912.569375 NaN NaN ...
4 120.654107 1.000000e+80 860.139964 NaN NaN ...
5 84.879518 1.000000e+80 823.178839 NaN NaN ...
6 146.730525 1.000000e+80 787.462875 NaN NaN ...
7 182.487489 1.000000e+80 881.307697 NaN NaN ...
IsObsoleteStack BestDetFlag \
0 0 6
1 0 6
2 0 6
3 0 5
4 0 6
5 0 22
6 0 22
7 0 22
Total_Info HasBlindDetection_band0 \
0 {'sourceID': 129723, 'dsID': 3681, 'band': 0, ... 0
1 {'DetectionID': 52041, 'DatasetID': 5076, 'Ban... 1
2 {'sourceID': 129723, 'dsID': 22539, 'band': 0,... 0
3 {'DetectionID': 436402, 'DatasetID': 69055, 'B... 1
4 {'DetectionID': 511904, 'DatasetID': 87005, 'B... 1
5 {'sourceID': 129723, 'dsID': 163302, 'band': 0... 0
6 {'DetectionID': 860630, 'DatasetID': 178529, '... 1
7 {'DetectionID': 918329, 'DatasetID': 195511, '... 1
Soft_Info HasBlindDetection_band1 \
0 {'sourceID': 129723, 'dsID': 3681, 'band': 1, ... 0
1 {'sourceID': 129723, 'dsID': 5076, 'band': 1, ... 0
2 {'sourceID': 129723, 'dsID': 22539, 'band': 1,... 0
3 {'sourceID': 129723, 'dsID': 69055, 'band': 1,... 0
4 {'sourceID': 129723, 'dsID': 87005, 'band': 1,... 0
5 {'sourceID': 129723, 'dsID': 163302, 'band': 1... 0
6 {'sourceID': 129723, 'dsID': 178529, 'band': 1... 0
7 {'sourceID': 129723, 'dsID': 195511, 'band': 1... 0
Medium_Info HasBlindDetection_band2 \
0 {'sourceID': 129723, 'dsID': 3681, 'band': 2, ... 0
1 {'sourceID': 129723, 'dsID': 5076, 'band': 2, ... 0
2 {'sourceID': 129723, 'dsID': 22539, 'band': 2,... 0
3 {'sourceID': 129723, 'dsID': 69055, 'band': 2,... 0
4 {'sourceID': 129723, 'dsID': 87005, 'band': 2,... 0
5 {'sourceID': 129723, 'dsID': 163302, 'band': 2... 0
6 {'sourceID': 129723, 'dsID': 178529, 'band': 2... 0
7 {'sourceID': 129723, 'dsID': 195511, 'band': 2... 0
Hard_Info HasBlindDetection_band3
0 {'DetectionID': 39231, 'DatasetID': 3681, 'Ban... 1
1 {'sourceID': 129723, 'dsID': 5076, 'band': 3, ... 0
2 {'DetectionID': 180923, 'DatasetID': 22539, 'B... 1
3 {'DetectionID': 436414, 'DatasetID': 69055, 'B... 1
4 {'DetectionID': 511913, 'DatasetID': 87005, 'B... 1
5 {'DetectionID': 810646, 'DatasetID': 163302, '... 1
6 {'DetectionID': 860639, 'DatasetID': 178529, '... 1
7 {'sourceID': 129723, 'dsID': 195511, 'band': 3... 0
[8 rows x 71 columns]},
'NonDetections': {'NumStacks': 12,
'NumObservations': 3021,
'Stacks': ObsID DatasetID IsStackedImage \
0 10000024081 224562 1
1 10000024086 224720 1
2 10000024340 224800 1
3 10000024087 224852 1
4 10000024502 224854 1
5 10000024503 224887 1
6 10000024881 225061 1
7 10000024216 225219 1
8 10000024881 225481 1
9 10000024502 225492 1
10 10000024216 226661 1
11 10000024881 226665 1
Total_Info \
0 {'sourceID': 129723, 'dsID': 224562, 'band': 0...
1 {'sourceID': 129723, 'dsID': 224720, 'band': 0...
2 {'sourceID': 129723, 'dsID': 224800, 'band': 0...
3 {'sourceID': 129723, 'dsID': 224852, 'band': 0...
4 {'sourceID': 129723, 'dsID': 224854, 'band': 0...
5 {'sourceID': 129723, 'dsID': 224887, 'band': 0...
6 {'sourceID': 129723, 'dsID': 225061, 'band': 0...
7 {'sourceID': 129723, 'dsID': 225219, 'band': 0...
8 {'sourceID': 129723, 'dsID': 225481, 'band': 0...
9 {'sourceID': 129723, 'dsID': 225492, 'band': 0...
10 {'sourceID': 129723, 'dsID': 226661, 'band': 0...
11 {'sourceID': 129723, 'dsID': 226665, 'band': 0...
Soft_Info \
0 {'sourceID': 129723, 'dsID': 224562, 'band': 1...
1 {'sourceID': 129723, 'dsID': 224720, 'band': 1...
2 {'sourceID': 129723, 'dsID': 224800, 'band': 1...
3 {'sourceID': 129723, 'dsID': 224852, 'band': 1...
4 {'sourceID': 129723, 'dsID': 224854, 'band': 1...
5 {'sourceID': 129723, 'dsID': 224887, 'band': 1...
6 {'sourceID': 129723, 'dsID': 225061, 'band': 1...
7 {'sourceID': 129723, 'dsID': 225219, 'band': 1...
8 {'sourceID': 129723, 'dsID': 225481, 'band': 1...
9 {'sourceID': 129723, 'dsID': 225492, 'band': 1...
10 {'sourceID': 129723, 'dsID': 226661, 'band': 1...
11 {'sourceID': 129723, 'dsID': 226665, 'band': 1...
Medium_Info \
0 {'sourceID': 129723, 'dsID': 224562, 'band': 2...
1 {'sourceID': 129723, 'dsID': 224720, 'band': 2...
2 {'sourceID': 129723, 'dsID': 224800, 'band': 2...
3 {'sourceID': 129723, 'dsID': 224852, 'band': 2...
4 {'sourceID': 129723, 'dsID': 224854, 'band': 2...
5 {'sourceID': 129723, 'dsID': 224887, 'band': 2...
6 {'sourceID': 129723, 'dsID': 225061, 'band': 2...
7 {'sourceID': 129723, 'dsID': 225219, 'band': 2...
8 {'sourceID': 129723, 'dsID': 225481, 'band': 2...
9 {'sourceID': 129723, 'dsID': 225492, 'band': 2...
10 {'sourceID': 129723, 'dsID': 226661, 'band': 2...
11 {'sourceID': 129723, 'dsID': 226665, 'band': 2...
Hard_Info
0 {'sourceID': 129723, 'dsID': 224562, 'band': 3...
1 {'sourceID': 129723, 'dsID': 224720, 'band': 3...
2 {'sourceID': 129723, 'dsID': 224800, 'band': 3...
3 {'sourceID': 129723, 'dsID': 224852, 'band': 3...
4 {'sourceID': 129723, 'dsID': 224854, 'band': 3...
5 {'sourceID': 129723, 'dsID': 224887, 'band': 3...
6 {'sourceID': 129723, 'dsID': 225061, 'band': 3...
7 {'sourceID': 129723, 'dsID': 225219, 'band': 3...
8 {'sourceID': 129723, 'dsID': 225481, 'band': 3...
9 {'sourceID': 129723, 'dsID': 225492, 'band': 3...
10 {'sourceID': 129723, 'dsID': 226661, 'band': 3...
11 {'sourceID': 129723, 'dsID': 226665, 'band': 3... ,
'Observations': ObsID DatasetID IsStackedImage \
0 35063001 3259 0
1 35063002 3265 0
2 35063003 3273 0
3 35063004 3284 0
4 35063005 3292 0
... ... ... ...
3016 96726007 227364 0
3017 96721116 227713 0
3018 96721117 227825 0
3019 96721118 227881 0
3020 96721119 227998 0
Total_Info \
0 {'sourceID': 129723, 'dsID': 3259, 'band': 0, ...
1 {'sourceID': 129723, 'dsID': 3265, 'band': 0, ...
2 {'sourceID': 129723, 'dsID': 3273, 'band': 0, ...
3 {'sourceID': 129723, 'dsID': 3284, 'band': 0, ...
4 {'sourceID': 129723, 'dsID': 3292, 'band': 0, ...
... ...
3016 {'sourceID': 129723, 'dsID': 227364, 'band': 0...
3017 {'sourceID': 129723, 'dsID': 227713, 'band': 0...
3018 {'sourceID': 129723, 'dsID': 227825, 'band': 0...
3019 {'sourceID': 129723, 'dsID': 227881, 'band': 0...
3020 {'sourceID': 129723, 'dsID': 227998, 'band': 0...
Soft_Info \
0 {'sourceID': 129723, 'dsID': 3259, 'band': 1, ...
1 {'sourceID': 129723, 'dsID': 3265, 'band': 1, ...
2 {'sourceID': 129723, 'dsID': 3273, 'band': 1, ...
3 {'sourceID': 129723, 'dsID': 3284, 'band': 1, ...
4 {'sourceID': 129723, 'dsID': 3292, 'band': 1, ...
... ...
3016 {'sourceID': 129723, 'dsID': 227364, 'band': 1...
3017 {'sourceID': 129723, 'dsID': 227713, 'band': 1...
3018 {'sourceID': 129723, 'dsID': 227825, 'band': 1...
3019 {'sourceID': 129723, 'dsID': 227881, 'band': 1...
3020 {'sourceID': 129723, 'dsID': 227998, 'band': 1...
Medium_Info \
0 {'sourceID': 129723, 'dsID': 3259, 'band': 2, ...
1 {'sourceID': 129723, 'dsID': 3265, 'band': 2, ...
2 {'sourceID': 129723, 'dsID': 3273, 'band': 2, ...
3 {'sourceID': 129723, 'dsID': 3284, 'band': 2, ...
4 {'sourceID': 129723, 'dsID': 3292, 'band': 2, ...
... ...
3016 {'sourceID': 129723, 'dsID': 227364, 'band': 2...
3017 {'sourceID': 129723, 'dsID': 227713, 'band': 2...
3018 {'sourceID': 129723, 'dsID': 227825, 'band': 2...
3019 {'sourceID': 129723, 'dsID': 227881, 'band': 2...
3020 {'sourceID': 129723, 'dsID': 227998, 'band': 2...
Hard_Info
0 {'sourceID': 129723, 'dsID': 3259, 'band': 3, ...
1 {'sourceID': 129723, 'dsID': 3265, 'band': 3, ...
2 {'sourceID': 129723, 'dsID': 3273, 'band': 3, ...
3 {'sourceID': 129723, 'dsID': 3284, 'band': 3, ...
4 {'sourceID': 129723, 'dsID': 3292, 'band': 3, ...
... ...
3016 {'sourceID': 129723, 'dsID': 227364, 'band': 3...
3017 {'sourceID': 129723, 'dsID': 227713, 'band': 3...
3018 {'sourceID': 129723, 'dsID': 227825, 'band': 3...
3019 {'sourceID': 129723, 'dsID': 227881, 'band': 3...
3020 {'sourceID': 129723, 'dsID': 227998, 'band': 3...
[3021 rows x 7 columns]},
'CrossMatch': LSXPS_ID Distance ExtCat_ID Catalogue Ext_RA \
0 129723 2.310000 0609.286946 2MASS 266.362268
1 129723 3.408908 2CXO J174527.2-290214 2CSC 266.363700
2 129723 4.535610 4XMM J174526.7-290217 4XMM_DR10 266.361561
3 129723 6.070000 0609.0602516 USNOB1 266.361128
4 129723 6.386022 2CXO J174526.7-290220 2CSC 266.361300
5 129723 6.634397 2CXO J174526.6-290216 2CSC 266.360900
6 129723 7.300000 0609.286973 2MASS 266.363915
7 129723 7.400000 0609.286923 2MASS 266.361073
8 129723 8.473705 2CXO J174526.6-290223 2CSC 266.361100
9 129723 8.768994 2CXO J174527.3-290208 2CSC 266.363800
10 129723 9.590000 0609.286907 2MASS 266.360623
11 129723 9.763594 2CXO J174526.3-290216 2CSC 266.359900
12 129723 15.764050 2SXPS J174526.7-290202 2SXPS 266.361508
Ext_Decl Ext_Err90
0 -29.038139 NaN
1 -29.037380 0.681888
2 -29.038142 3.415725
3 -29.037700 NaN
4 -29.039070 0.614541
5 -29.037960 0.681888
6 -29.039967 NaN
7 -29.036928 NaN
8 -29.039770 0.622960
9 -29.035770 0.698725
10 -29.039768 NaN
11 -29.038050 0.648215
12 -29.033924 9.850933 }
Yowsers that's a lot of information! Not all of it will be of interest -- essentially this is everything needed to build the web page for the source.
I'll let you explore it at your leisure, with just a few notes. Firstly, those things which appear as tables on the web page are DataFrames in here. For example, let's look at the information about the datasets in which this source was detected.
data['Detections'].keys()
dict_keys(['NumStacks', 'NumObservations', 'Observations'])
This tells me how many stacks and normal observations the source was detected in, and then contains the DataFrames of the details. Given that there is an 'Observations' entry but no 'Stacks' entry, I can guess that 'NumStacks' will be 0, but let's prove it, then view the observations:
data['Detections']['NumStacks']
0
data['Detections']['Observations']
| ObsSourceID | DatasetID | LSXPS_ID | OSNum | UsedCorrectedPosition | NearestNeighbour | NearestOKNeighbour | Exposure | HR1 | HR1_pos | ... | IsObsoleteStack | BestDetFlag | Total_Info | HasBlindDetection_band0 | Soft_Info | HasBlindDetection_band1 | Medium_Info | HasBlindDetection_band2 | Hard_Info | HasBlindDetection_band3 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 20588 | 3681 | 129723 | 18 | 0 | 65.570452 | 1.000000e+80 | 1527.104234 | 0.000243 | 0.520389 | ... | 0 | 6 | {'sourceID': 129723, 'dsID': 3681, 'band': 0, ... | 0 | {'sourceID': 129723, 'dsID': 3681, 'band': 1, ... | 0 | {'sourceID': 129723, 'dsID': 3681, 'band': 2, ... | 0 | {'DetectionID': 39231, 'DatasetID': 3681, 'Ban... | 1 |
| 1 | 27526 | 5076 | 129723 | 4 | 0 | 111.849930 | 1.000000e+80 | 1244.026913 | 0.190570 | 0.809429 | ... | 0 | 6 | {'DetectionID': 52041, 'DatasetID': 5076, 'Ban... | 1 | {'sourceID': 129723, 'dsID': 5076, 'band': 1, ... | 0 | {'sourceID': 129723, 'dsID': 5076, 'band': 2, ... | 0 | {'sourceID': 129723, 'dsID': 5076, 'band': 3, ... | 0 |
| 2 | 95523 | 22539 | 129723 | 6 | 0 | 203.195404 | 1.000000e+80 | 1257.150513 | NaN | NaN | ... | 0 | 6 | {'sourceID': 129723, 'dsID': 22539, 'band': 0,... | 0 | {'sourceID': 129723, 'dsID': 22539, 'band': 1,... | 0 | {'sourceID': 129723, 'dsID': 22539, 'band': 2,... | 0 | {'DetectionID': 180923, 'DatasetID': 22539, 'B... | 1 |
| 3 | 222435 | 69055 | 129723 | 13 | 0 | 125.186743 | 1.000000e+80 | 912.569375 | NaN | NaN | ... | 0 | 5 | {'DetectionID': 436402, 'DatasetID': 69055, 'B... | 1 | {'sourceID': 129723, 'dsID': 69055, 'band': 1,... | 0 | {'sourceID': 129723, 'dsID': 69055, 'band': 2,... | 0 | {'DetectionID': 436414, 'DatasetID': 69055, 'B... | 1 |
| 4 | 259658 | 87005 | 129723 | 9 | 0 | 120.654107 | 1.000000e+80 | 860.139964 | NaN | NaN | ... | 0 | 6 | {'DetectionID': 511904, 'DatasetID': 87005, 'B... | 1 | {'sourceID': 129723, 'dsID': 87005, 'band': 1,... | 0 | {'sourceID': 129723, 'dsID': 87005, 'band': 2,... | 0 | {'DetectionID': 511913, 'DatasetID': 87005, 'B... | 1 |
| 5 | 404884 | 163302 | 129723 | 15 | 0 | 84.879518 | 1.000000e+80 | 823.178839 | NaN | NaN | ... | 0 | 22 | {'sourceID': 129723, 'dsID': 163302, 'band': 0... | 0 | {'sourceID': 129723, 'dsID': 163302, 'band': 1... | 0 | {'sourceID': 129723, 'dsID': 163302, 'band': 2... | 0 | {'DetectionID': 810646, 'DatasetID': 163302, '... | 1 |
| 6 | 429562 | 178529 | 129723 | 9 | 0 | 146.730525 | 1.000000e+80 | 787.462875 | NaN | NaN | ... | 0 | 22 | {'DetectionID': 860630, 'DatasetID': 178529, '... | 1 | {'sourceID': 129723, 'dsID': 178529, 'band': 1... | 0 | {'sourceID': 129723, 'dsID': 178529, 'band': 2... | 0 | {'DetectionID': 860639, 'DatasetID': 178529, '... | 1 |
| 7 | 458370 | 195511 | 129723 | 9 | 0 | 182.487489 | 1.000000e+80 | 881.307697 | NaN | NaN | ... | 0 | 22 | {'DetectionID': 918329, 'DatasetID': 195511, '... | 1 | {'sourceID': 129723, 'dsID': 195511, 'band': 1... | 0 | {'sourceID': 129723, 'dsID': 195511, 'band': 2... | 0 | {'sourceID': 129723, 'dsID': 195511, 'band': 3... | 0 |
8 rows × 71 columns
The other thing I want to point out about this relates to the notes above about when source identifiers change. You see, I somewhat sneakily chose a superseded source for this example. We asked for the details of source 11375, and we got source details but:
data['LSXPS_ID']
129723
This source is not source 11375 anymore! But that's OK, this is the source you were looking for, it's just got a new name/number.
Another useful aspect of the data this function returns is that it contains the details of any sources from other catalogues that were found as part of the automated lookup. Unfortunately, source 11375 wasn't very helpful in this regard (there are no external matches) so let's get a different source:
data = uds.getSourceDetails(sourceID=106107, cat='LSXPS')
data['CrossMatch']
| LSXPS_ID | Distance | ExtCat_ID | Catalogue | Ext_RA | Ext_Decl | Ext_Err90 | |
|---|---|---|---|---|---|---|---|
| 0 | 106107 | 2.258150 | 1SWXRT J221755.2-082058 | 1SWXRT | 334.480400 | -8.349700 | 7.399635 |
| 1 | 106107 | 2.629610 | 1SWXRT J221755.4-082103 a | 1SWXRT | 334.480867 | -8.350843 | 4.912901 |
| 2 | 106107 | 2.720092 | 1RXH J221755.5-082102 | ROSHRI | 334.481361 | -8.350697 | 10.123260 |
| 3 | 106107 | 2.875038 | 2SXPS J221755.3-082103 | 2SXPS | 334.480808 | -8.350908 | 3.500000 |
| 4 | 106107 | 3.364204 | 4XMM J221755.3-082103 | 4XMM_DR10 | 334.480772 | -8.351041 | 0.187498 |
| 5 | 106107 | 3.370000 | 0816.0702838 | USNOB1 | 334.480728 | -8.351036 | NaN |
| 6 | 106107 | 3.375030 | 1SWXRT J221755.4-082103 | 1SWXRT | 334.480917 | -8.351049 | 4.535022 |
| 7 | 106107 | 3.480000 | 0816.333109 | 2MASS | 334.480763 | -8.351073 | NaN |
| 8 | 106107 | 3.902853 | 1SWXRT J221755.3-082104 a | 1SWXRT | 334.480829 | -8.351196 | 4.788412 |
| 9 | 106107 | 4.076989 | 1SWXRT J221755.3-082104 b | 1SWXRT | 334.480671 | -8.351227 | 4.457084 |
| 10 | 106107 | 4.314952 | 1SWXRT J221755.3-082104 | 1SWXRT | 334.480717 | -8.351301 | 4.536789 |
| 11 | 106107 | 28.146582 | 2RXS J221753.8-082115 | 2RXS | 334.474188 | -8.354276 | 38.637817 |
Remember, this is not an exhaustive list of every catalogued source near the LSXPS soruce.
There's not really much more to say for getSourceDetails(), except a reminder that you could have supplied the sourceName instead of sourceID parameter, and it could have been a list. Actually, let's quickly demo both of these points:
data = uds.getSourceDetails(sourceName=('LSXPS J163700.6+073914', 'LSXPS J163647.0+074206'),
cat='LSXPS')
data.keys()
dict_keys(['LSXPS J163700.6+073914', 'LSXPS J163647.0+074206'])
This result should not be unexpected -- I warned you right at the top of this notebook and it's been seen for the GRB modules -- but if you've started with this notebook it's your first view, so I'll be explicit. We supplied multiple sourceNames, and so what we get back is a dict with one entry for each name we supplied, and the contents of each of those is the requested set of information. So:
data['LSXPS J163700.6+073914']
{'IAUName': 'LSXPS J163700.6+073914',
'LSXPS_ID': 1,
'RA': 249.2525355614,
'Decl': 7.6539136659,
'Err90': 7.11571681152209,
'AstromType': 0,
'l': 23.8735245731387,
'b': 33.2946669385987,
'MeanOffAxisAngle': 2.17696,
'Exposure': 2658.6742458,
'FirstObsDate': '2005-01-07 03:18:19',
'LastObsDate': '2005-01-07 15:00:13',
'FirstObsMET': 126760698.697603,
'LastObsMET': 126802813.183743,
'FirstDetDate': '2005-01-07 03:18:19',
'LastDetDate': '2005-01-07 15:00:13',
'FirstDetMET': 126760698.697603,
'LastDetMET': 126802813.183743,
'FirstBlindDetDate': '2005-01-07 03:18:19',
'LastBlindDetDate': '2005-01-07 15:00:13',
'FirstBlindDetMET': 126760698.697603,
'LastBlindDetMET': 126802813.183743,
'NumObs': 1,
'NumBlindDetObs': 1,
'NumDetObs': 1,
'DetFlag': 0,
'FieldFlag': 0,
'DetFlag_band0': 0,
'DetFlag_band1': -1,
'DetFlag_band2': -1,
'DetFlag_band3': -1,
'BestDetectionID': 4,
'OpticalLoadingWarning': 0,
'StrayLightWarning': 0,
'NearBrightSourceWarning': 0,
'IsPotentialAlias': 0,
'Rate_band0': 0.00301609430890933,
'Rate_band0_pos': 0.00150757706494268,
'Rate_band0_neg': -0.00118885637581542,
'Rate_band1': 0.000471026472290546,
'Rate_band1_pos': 0.000781283430086714,
'Rate_band1_neg': -0.000471026472290546,
'Rate_band2': 0.00130966043093958,
'Rate_band2_pos': 0.00101021545803631,
'Rate_band2_neg': -0.000679744789353423,
'Rate_band3': 0.00119354911491586,
'Rate_band3_pos': 0.00100786502653785,
'Rate_band3_neg': -0.000679274703053732,
'Counts_band0': 8,
'Counts_band1': 2,
'Counts_band2': 3,
'Counts_band3': 3,
'BgCounts_band0': 1.58444273471832,
'BgCounts_band1': 0.99823522567749,
'BgCounts_band2': 0.21358197927475,
'BgCounts_band3': 0.461401104927063,
'RateCF_band0': 1.262331366539,
'RateCF_band1': 1.26233134313997,
'RateCF_band2': 1.26233134313997,
'RateCF_band3': 1.26233134313997,
'NonBlindDet_band0': 1,
'NonBlindDet_band1': 0,
'NonBlindDet_band2': 1,
'NonBlindDet_band3': 0,
'UL_band0': 0.00850815007745481,
'UL_band1': 0.00423359721501862,
'UL_band2': 0.00539283003005703,
'UL_band3': 0.00526073577984381,
'PeakRate_band0': 0.0043817,
'PeakRate_band0_pos': 0.00247962,
'PeakRate_band0_neg': -0.00188112,
'PeakRate_band1': 0.000471026472290546,
'PeakRate_band1_pos': 0.000781283430086714,
'PeakRate_band1_neg': -0.000471026472290546,
'PeakRate_band2': 0.00250583,
'PeakRate_band2_pos': 0.00187762,
'PeakRate_band2_neg': -0.00126427,
'PeakRate_band3': 0.00119354911491586,
'PeakRate_band3_pos': 0.00100786502653785,
'PeakRate_band3_neg': -0.000679274703053732,
'PvarPchiSnapshot_band0': 0.266418084903665,
'PvarPchiSnapshot_band1': 0.8102458874137682,
'PvarPchiSnapshot_band2': 0.1130839850417589,
'PvarPchiSnapshot_band3': 0.6694086490392102,
'PvarPchiSnapshot_HR1': 0.0001555921832623319,
'PvarPchiSnapshot_HR2': 0.0983768578442934,
'PvarPchiObsID_band0': 0.3222290424614127,
'PvarPchiObsID_band1': 0.7174997282044917,
'PvarPchiObsID_band2': 0.7174997282044917,
'PvarPchiObsID_band3': 0.7174997282044917,
'PvarPchiObsID_HR1': None,
'PvarPchiObsID_HR2': None,
'HR1': 0.340902,
'HR1_pos': 0.659098,
'HR1_neg': -0.209542,
'HR2': 0.01114,
'HR2_pos': 0.519912,
'HR2_neg': -0.43819,
'GalacticNH': 7.422117e+20,
'WhichPow': 1,
'WhichAPEC': 1,
'PowECFO': 5.1283e-11,
'PowECFU': 6.08475e-11,
'PowFlux': 1.54674364443797e-13,
'PowFlux_pos': 7.73130746214555e-14,
'PowFlux_neg': -6.09681215209422e-14,
'PowUnabsFlux': 1.8352179846136e-13,
'PowUnabsFlux_pos': 9.17322954590997e-14,
'PowUnabsFlux_neg': -7.23389383274288e-14,
'APECECFO': 4.99246e-11,
'APECECFU': 5.58256e-11,
'APECFlux': 1.50577301934575e-13,
'APECFlux_pos': 7.52651819364373e-14,
'APECFlux_neg': -5.93531790200345e-14,
'APECUnabsFlux': 1.68375274451449e-13,
'APECUnabsFlux_pos': 8.41613941966641e-14,
'APECUnabsFlux_neg': -6.63686204937213e-14,
'PowPeakFlux': 2.2470672109999998e-13,
'PowPeakFlux_pos': 1.2716235246e-13,
'PowPeakFlux_neg': -9.646947696000001e-14,
'PowPeakUnabsFlux': 2.6661549075e-13,
'PowPeakUnabsFlux_pos': 1.5087867795e-13,
'PowPeakUnabsFlux_neg': -1.144614492e-13,
'APECPeakFlux': 2.1875461982e-13,
'APECPeakFlux_pos': 1.23794036652e-13,
'APECPeakFlux_neg': -9.3914163552e-14,
'APECPeakUnabsFlux': 2.4461103152e-13,
'APECPeakUnabsFlux_pos': 1.3842627427200002e-13,
'APECPeakUnabsFlux_neg': -1.05014652672e-13,
'FixedPowECFO': 4.51484e-11,
'FixedPowECFU': 5.03245e-11,
'FixedPowFlux': 1.36171832296362e-13,
'FixedPowFlux_pos': 6.80646923588581e-14,
'FixedPowFlux_neg': -5.36749631978649e-14,
'FixedPowUnabsFlux': 1.51783438048708e-13,
'FixedPowUnabsFlux_pos': 7.58680620047079e-14,
'FixedPowUnabsFlux_neg': -5.98286026847231e-14,
'FixedAPECECFO': 2.29751e-11,
'FixedAPECECFU': 2.79899e-11,
'FixedAPECFlux': 6.92950683566227e-14,
'FixedAPECFlux_pos': 3.46367338247646e-14,
'FixedAPECFlux_neg': -2.73140941199969e-14,
'FixedAPECUnabsFlux': 8.44201780969412e-14,
'FixedAPECUnabsFlux_pos': 4.21969312900391e-14,
'FixedAPECUnabsFlux_neg': -3.3275971073436e-14,
'InterpPowECFO': 5.1283e-11,
'InterpPowECFU': 6.08475e-11,
'InterpPowNH': 1.89339e+21,
'InterpPowNH_pos': -1,
'InterpPowNH_neg': 1,
'InterpPowGamma': 1.59334,
'InterpPowGamma_pos': -1,
'InterpPowGamma_neg': 1,
'InterpPowFlux': 1.54674364443797e-13,
'InterpPowFlux_pos': 7.73130746214555e-14,
'InterpPowFlux_neg': -6.09681215209422e-14,
'InterpPowUnabsFlux': 1.8352179846136e-13,
'InterpPowUnabsFlux_pos': 9.17322954590997e-14,
'InterpPowUnabsFlux_neg': -7.23389383274288e-14,
'InterpAPECECFO': 4.99246e-11,
'InterpAPECECFU': 5.58256e-11,
'InterpAPECNH': 1.32655e+21,
'InterpAPECNH_pos': -1,
'InterpAPECNH_neg': 1,
'InterpAPECkT': 9.5356,
'InterpAPECkT_pos': -1,
'InterpAPECkT_neg': 1,
'InterpAPECFlux': 1.50577301934575e-13,
'InterpAPECFlux_pos': 7.52651819364373e-14,
'InterpAPECFlux_neg': -5.93531790200345e-14,
'InterpAPECUnabsFlux': 1.68375274451449e-13,
'InterpAPECUnabsFlux_pos': 8.41613941966641e-14,
'InterpAPECUnabsFlux_neg': -6.63686204937213e-14,
'P_pow': 1,
'P_APEC': 1,
'FittedPowECFO': None,
'FittedPowECFU': None,
'FittedPowNH': None,
'FittedPowNH_pos': None,
'FittedPowNH_neg': None,
'FittedPowGamma': None,
'FittedPowGamma_pos': None,
'FittedPowGamma_neg': None,
'FittedPowFlux': None,
'FittedPowFlux_pos': None,
'FittedPowFlux_neg': None,
'FittedPowUnabsFlux': None,
'FittedPowUnabsFlux_pos': None,
'FittedPowUnabsFlux_neg': None,
'FittedPowCstat': None,
'FittedPowDOF': None,
'FittedPowReducedChi2': None,
'FittedAPECECFO': None,
'FittedAPECECFU': None,
'FittedAPECNH': None,
'FittedAPECNH_pos': None,
'FittedAPECNH_neg': None,
'FittedAPECkT': None,
'FittedAPECkT_pos': None,
'FittedAPECkT_neg': None,
'FittedAPECFlux': None,
'FittedAPECFlux_pos': None,
'FittedAPECFlux_neg': None,
'FittedAPECUnabsFlux': None,
'FittedAPECUnabsFlux_pos': None,
'FittedAPECUnabsFlux_neg': None,
'FittedAPECCstat': None,
'FittedAPECDOF': None,
'FittedAPECReducedChi2': None,
'HasSpec': 0,
'NearestNeighbour': 265.30963,
'NearestOKNeighbour': 265.30963,
'NearestNeighbour_ID': 2,
'NearestOKNeighbour_ID': 2,
'NumExternalMatches': 1,
'NumExternalMatches_slim': 1,
'MatchInROSHRI': 0,
'MatchIn2RXS': 0,
'MatchIn4XMM_DR10': 0,
'MatchIn4XMM_DR10s': 0,
'MatchInXMMSL2': 0,
'MatchInSwiftFT': 0,
'MatchIn1SWXRT': 0,
'MatchInXRTGRB': 0,
'MatchInSDSS_QSO_DR14': 0,
'MatchIn2MASS': 0,
'MatchInUSNOB1': 0,
'MatchIn2CSC': 0,
'MatchIn2SXPS': 1,
'ra_rad': 4.350277414490683,
'sindec': 0.13318903662789883,
'cosdec': 0.991090652020355,
'HPPIX': 85090,
'ProcessedStatus': 7,
'WhenAdded': '2022-03-31 12:09:40',
'WhenModified': '2022-04-22 07:36:37',
'StillDetected': 1,
'HasExternalMatches': 1,
'lcRanges': {'TDB_lo': 2453377.6347191166,
'MJD_lo': 53377.13772402102,
'MET_lo': 126760698.69760299,
'TDB_hi': 2453378.1221552985,
'MJD_hi': 53377.62516020319,
'MET_hi': 126802813.183743,
'rate_lo': 0,
'rate_hi': 0.00686132},
'NearestNeighbour_name': 'LSXPS J163647.0+074206',
'NearestOKNeighbour_name': 'LSXPS J163647.0+074206',
'OK': 1,
'Detections': {'NumStacks': 0,
'NumObservations': 1,
'Observations': ObsSourceID DatasetID LSXPS_ID OSNum UsedCorrectedPosition \
0 2 25 1 1 0
NearestNeighbour NearestOKNeighbour Exposure HR1 HR1_pos ... \
0 265.30963 265.30963 2658.674246 0.379183 0.620816 ...
IsObsoleteStack BestDetFlag \
0 0 0
Total_Info HasBlindDetection_band0 \
0 {'DetectionID': 4, 'DatasetID': 25, 'Band': 0,... 1
Soft_Info HasBlindDetection_band1 \
0 {'sourceID': 1, 'dsID': 25, 'band': 1, 'C': 2,... 0
Medium_Info HasBlindDetection_band2 \
0 {'sourceID': 1, 'dsID': 25, 'band': 2, 'C': 3,... 0
Hard_Info HasBlindDetection_band3
0 {'sourceID': 1, 'dsID': 25, 'band': 3, 'C': 3,... 0
[1 rows x 71 columns]},
'NonDetections': {'NumStacks': 0, 'NumObservations': 0},
'CrossMatch': LSXPS_ID Distance ExtCat_ID Catalogue Ext_RA Ext_Decl \
0 1 0.019439 2SXPS J163700.6+073914 2SXPS 249.252535 7.653919
Ext_Err90
0 5.405237 }
If we had supplied sourceID=(1,2) instead of sourceName=(...) then the returned dict would have keys 1 and 2, instead of the names.
From the lists of detections, non-detections etc in the data returned above, it is possible to derive the list of observations (and targetIDs) corresponding to catalogued dataset covering the source. It's a little bit involved though, as it involves iterating through some of the tables so, because I'm nice, I've given you a function to get this information out:
what = uds.getObsList(sourceName='LSXPS J073006.9-193710', useObs='allCat')
what
{'targList': ['03103545', '00015190', '00086462', '03102486'],
'obsList': ['03103545001',
'00015190001',
'00015190002',
'00015190003',
'00015190005',
'00015190006',
'00015190007',
'00015190010',
'00015190012',
'00086462001',
'03102486001',
'03102486002',
'03102486003',
'00015190008',
'00015190009',
'00015190011',
'00015190013',
'00015190014',
'00015190015']}
And you can see it has given a dict containing targList and obsList which are lists of the targetIDs or obsIDs covering the source.
This function can take the normal sourceID or sourceName arguments, or instead sourceDetails=data, where data is the value returned by a getSourceDetails() call.
The only other argument (beyond the usual cat, silent and verbose) is useObs, which tells you which observations of the source you want included in the list. This can be one of (case insensitive):
allCat - get all catalogued observations of the source position.blind - get only observations with a blind detection of the source.allDet - get observations with blind or retrospective detections.retro - get only observations with retrospective detections.nonDet - get only observations with no detection (blind or retrospective).Let me give you one important warning that may sound counter-intuitive at first: it is possible for useObs='blind' to return no observations.
This sounds impossible - how can a source be in the catalogue and yet have no blind detections? Well, of course, it can't. But a source can be in the catalogue and have no single observations in which it is blindly detected, if it is only detected in a stacked image. I did consider in this situation making getObs() return the list of observations making up the stack in which the source was detected, but I decided this would be incorrect: the source was not blindly detected in those. You can get that set of observations by setting useObs='allCat', and so of course you can always do a simple check, as in this example:
for sid in (209851, 209220):
print(f"Source {sid}:")
what = uds.getObsList(sourceID=sid, useObs='blind')
if len(what['obsList']) == 0:
print("No blind detections found, getting allCat")
what = uds.getObsList(sourceID=sid, useObs='allCat')
print(f" * Targets: {what['targList']}\n * Observations: {what['obsList']}\n\n")
Source 209851:
* Targets: ['00221755']
* Observations: ['00221755000', '00221755001', '00221755002', '00221755003', '00221755004', '00221755005', '00221755006', '00221755007', '00221755008', '00221755009', '00221755010', '00221755011', '00221755012', '00221755013', '00221755014', '00221755015', '00221755016', '00221755017', '00221755018', '00221755020', '00221755022', '00221755023', '00221755024', '00221755025', '00221755026', '00221755027', '00221755028', '00221755029', '00221755030', '00221755031', '00221755032', '00221755033', '00221755034', '00221755035', '00221755036', '00221755037', '00221755038', '00221755041', '00221755043', '00221755044']
Source 209220:
No blind detections found, getting allCat
* Targets: ['00031635']
* Observations: ['00031635001', '00031635002', '00031635003', '00031635004']
Having got the obs list you may want to download the actual data, we can do that using the functions introduced the parent swifttools.ukssdc.data module which let us get data either by supplying obsID(s) or targetID(s). So having just got the obslist above, we could do:
import swifttools.ukssdc.data as ud
ud.downloadObsData(what['obsList'],
instruments=('xrt',),
destDir='/tmp/APIDemo_SXPS_data',
silent=False
)
Making directory /tmp/APIDemo_SXPS_data
Downloading 4 datasets
Making directory /tmp/APIDemo_SXPS_data/00031635001
Making directory /tmp/APIDemo_SXPS_data/00031635001/xrt/
Making directory /tmp/APIDemo_SXPS_data/00031635001/xrt/event/
Making directory /tmp/APIDemo_SXPS_data/00031635001/xrt/hk/
Making directory /tmp/APIDemo_SXPS_data/00031635001/auxil/
Downloading 00031635001: 0%| | 0/30 [00:00<?, ?files/s]
Making directory /tmp/APIDemo_SXPS_data/00031635002
Making directory /tmp/APIDemo_SXPS_data/00031635002/xrt/
Making directory /tmp/APIDemo_SXPS_data/00031635002/xrt/event/
Making directory /tmp/APIDemo_SXPS_data/00031635002/xrt/hk/
Making directory /tmp/APIDemo_SXPS_data/00031635002/auxil/
Downloading 00031635002: 0%| | 0/30 [00:00<?, ?files/s]
Making directory /tmp/APIDemo_SXPS_data/00031635003
Making directory /tmp/APIDemo_SXPS_data/00031635003/xrt/
Making directory /tmp/APIDemo_SXPS_data/00031635003/xrt/event/
Making directory /tmp/APIDemo_SXPS_data/00031635003/xrt/hk/
Making directory /tmp/APIDemo_SXPS_data/00031635003/auxil/
Downloading 00031635003: 0%| | 0/30 [00:00<?, ?files/s]
Making directory /tmp/APIDemo_SXPS_data/00031635004
Making directory /tmp/APIDemo_SXPS_data/00031635004/xrt/
Making directory /tmp/APIDemo_SXPS_data/00031635004/xrt/event/
Making directory /tmp/APIDemo_SXPS_data/00031635004/xrt/hk/
Making directory /tmp/APIDemo_SXPS_data/00031635004/auxil/
Downloading 00031635004: 0%| | 0/30 [00:00<?, ?files/s]
Where I have taken advantage of the fact that what was set by the previous cell to something without too many observations.
I have not added a wrapper function in swifttools.ukssdc.data.SXPS to automatically call this function for a set of objects, you'd have to do that in a loop yourself (it's not hard!). If you think that such an addition would really help you, drop me a line and, if enough people ask, I'll consider it.
We will get light curves using a function called getLightCurves().
Sources in the SXPS catalogues have light curves created with two different binning methods (one bin per snapshot or one per obsid) and with three options for the units on the time axis (MJD, MET or TDB). This means that when we get light curves, using getLightCurves() we will have to specify which binning and time option we want. As well as specifying the object(s) we want to get light curves for of course, using the sourceName or sourceID argument, as ever.
As noted in the General notes, for light curves we have the option of saving them to disk, storing them in a variable, or both, controlled via the standard saveData and returnData arguments.
We'll start off by exploring how the latter option, getting data into a variable.
(If you have already read the GRB documentation and are wondering why I've swapped the order over, it will make sense in a bit.)
To get the light curve data into a variable we will need to set returnData=True, and we'll also set saveData=False so that we introduce one thing at a time.
All light curves returned by anything in the swifttools.ukssdc module have a common structure which I call a "light curve dict", and you can read about this here, but let's get ourselves a light curve dict shall we?
lcs = uds.getLightCurves(sourceName='LSXPS J062131.8-622213',
cat='LSXPS',
binning='obsid',
timeFormat='MJD',
saveData=False,
returnData=True
)
I'm not going to spend much time unpacking this, because you can read about the light curve dict elsewhere but we'll take a quick look.
list(lcs.keys())
['Total_rates',
'Total_UL',
'Soft_rates',
'Soft_UL',
'Medium_rates',
'Medium_UL',
'Hard_rates',
'Hard_UL',
'HR1',
'HR2',
'TimeFormat',
'T0',
'Binning',
'Datasets']
If you did read up on the light curve dict then this should be as expected. Let's look at some of the details of what we've downloaded.
print(f"TimeFormat: {lcs['TimeFormat']}")
print(f"Binning: {lcs['Binning']}")
print(f"T0: {lcs['T0']}")
TimeFormat: MJD
Binning: Observation
T0: 0
Well, that's a relief, the time format and binning method are what we requested. 'obsid' was a convenient abbreviation for 'Observation' which I provided because I'm nice. You can buy me a beer next time we meet.
The 'Datasets' key, as I'm sure you know, tells you what light curves we actually have, and the entries in this list will correspond to other keys in the dict:
lcs['Datasets']
['Total_rates',
'Total_UL',
'Soft_rates',
'Soft_UL',
'Medium_rates',
'Medium_UL',
'Hard_rates',
'Hard_UL',
'HR1',
'HR2']
Hopefully these names are fairly self-explanatory; there are the four SXPS bands and then either '_rates' or '_UL'. The former contain count-rate bins and 1-sigma errors, the latter contain 3-sigma upper limits.
Let's have a quick look at one each of these:
lcs['Total_rates']
| Time | TimePos | TimeNeg | Rate | RatePos | RateNeg | CtsInSrc | BGInSrc | CorrFact | Exposure | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 53945.873326 | 0.068862 | -0.068862 | 0.764142 | 0.015921 | -0.015921 | 2354.0 | 16.95460 | 1.586330 | 4851.6000 |
| 1 | 53946.917497 | 0.973284 | -0.973284 | 0.292977 | 0.002783 | -0.002783 | 11815.0 | 249.80200 | 1.232100 | 48636.6000 |
| 2 | 53948.487426 | 0.477115 | -0.477115 | 0.088098 | 0.002977 | -0.002977 | 915.0 | 13.24040 | 1.214730 | 12433.7000 |
| 3 | 53949.497626 | 0.479412 | -0.479412 | 0.050993 | 0.002131 | -0.002131 | 618.0 | 15.56590 | 1.394350 | 16473.0000 |
| 4 | 53951.004909 | 0.979716 | -0.979716 | 0.031649 | 0.001227 | -0.001227 | 732.0 | 23.31430 | 1.183030 | 26489.6000 |
| 5 | 53953.471155 | 1.446181 | -1.446181 | 0.017280 | 0.000818 | -0.000818 | 547.0 | 36.54720 | 1.362890 | 40259.7000 |
| 6 | 53955.587241 | 0.409244 | -0.409244 | 0.013712 | 0.001153 | -0.001153 | 178.0 | 13.44010 | 1.237220 | 14848.2000 |
| 7 | 53956.518565 | 0.477924 | -0.477924 | 0.012569 | 0.001006 | -0.001006 | 194.0 | 13.84700 | 1.210530 | 17350.5000 |
| 8 | 53957.523285 | 0.476671 | -0.476671 | 0.011100 | 0.000995 | -0.000995 | 146.0 | 7.65277 | 1.373980 | 17124.9000 |
| 9 | 53958.526869 | 0.473061 | -0.473061 | 0.008568 | 0.000964 | -0.000901 | 96.0 | 5.88043 | 1.269270 | 13351.4000 |
| 10 | 53960.529247 | 1.470660 | -1.470660 | 0.007378 | 0.000575 | -0.000575 | 239.0 | 29.01420 | 1.215610 | 34608.3000 |
| 11 | 53962.510137 | 0.430792 | -0.430792 | 0.005643 | 0.001244 | -0.001094 | 27.0 | 1.81502 | 1.641540 | 7326.3000 |
| 12 | 53963.483788 | 0.465422 | -0.465422 | 0.004356 | 0.000820 | -0.000735 | 38.0 | 3.35956 | 1.348240 | 10723.7000 |
| 13 | 53964.491166 | 0.476128 | -0.476128 | 0.005676 | 0.000974 | -0.000881 | 44.0 | 3.31592 | 1.695590 | 12152.9000 |
| 14 | 53965.487157 | 0.473143 | -0.473143 | 0.004569 | 0.000711 | -0.000649 | 53.0 | 3.96059 | 1.417040 | 15201.8000 |
| 15 | 53967.495869 | 1.471383 | -1.471383 | 0.003947 | 0.000506 | -0.000471 | 87.0 | 11.59110 | 1.289500 | 24639.2000 |
| 16 | 53969.503154 | 0.466175 | -0.466175 | 0.003994 | 0.000866 | -0.000765 | 29.0 | 2.51574 | 1.422350 | 9427.4000 |
| 17 | 53970.507336 | 0.468258 | -0.468258 | 0.003699 | 0.000783 | -0.000693 | 30.0 | 2.42715 | 1.418080 | 10573.3000 |
| 18 | 53971.508083 | 0.472396 | -0.472396 | 0.005005 | 0.000866 | -0.000781 | 42.0 | 2.51125 | 1.362980 | 10751.3000 |
| 19 | 53974.722583 | 1.277315 | -1.277315 | 0.002389 | 0.000404 | -0.000368 | 51.0 | 6.73629 | 1.564250 | 28986.9000 |
| 20 | 53984.518025 | 0.475666 | -0.475666 | 0.001479 | 0.000567 | -0.000471 | 13.0 | 2.63040 | 1.446080 | 10139.5000 |
| 21 | 53985.524246 | 0.475637 | -0.475637 | 0.002057 | 0.000480 | -0.000423 | 28.0 | 3.77880 | 1.396480 | 16442.9000 |
| 22 | 53986.526374 | 0.473524 | -0.473524 | 0.001064 | 0.000422 | -0.000353 | 14.0 | 3.64981 | 1.426250 | 13872.9000 |
| 23 | 53987.533304 | 0.478443 | -0.478443 | 0.002124 | 0.000506 | -0.000445 | 27.0 | 3.70659 | 1.479720 | 16224.7000 |
| 24 | 53988.539526 | 0.477025 | -0.477025 | 0.001092 | 0.000360 | -0.000308 | 18.0 | 4.03919 | 1.322680 | 16901.7000 |
| 25 | 53989.534317 | 0.465567 | -0.465567 | 0.000939 | 0.000395 | -0.000330 | 14.0 | 4.23648 | 1.576030 | 16387.7000 |
| 26 | 53990.510034 | 0.443663 | -0.443663 | 0.001437 | 0.000439 | -0.000376 | 19.0 | 3.53192 | 1.410500 | 15179.2000 |
| 27 | 53991.482346 | 0.478724 | -0.478724 | 0.000841 | 0.000419 | -0.000339 | 10.0 | 2.91185 | 1.464140 | 12345.9000 |
| 28 | 53992.481806 | 0.477445 | -0.477445 | 0.001341 | 0.000409 | -0.000352 | 20.0 | 4.16574 | 1.317290 | 15550.3000 |
| 29 | 53993.488863 | 0.475670 | -0.475670 | 0.001342 | 0.000426 | -0.000366 | 19.0 | 4.13623 | 1.272810 | 14098.5000 |
| 30 | 53995.493384 | 1.481591 | -1.481591 | 0.001223 | 0.000251 | -0.000227 | 44.0 | 9.97016 | 1.309060 | 36413.5000 |
| 31 | 53997.500696 | 0.477749 | -0.477749 | 0.001312 | 0.000383 | -0.000334 | 23.0 | 5.36184 | 1.335870 | 17959.8000 |
| 32 | 53998.509044 | 0.474263 | -0.474263 | 0.001412 | 0.000515 | -0.000433 | 15.0 | 3.37360 | 1.319820 | 10866.6000 |
| 33 | 54000.010655 | 0.980987 | -0.980987 | 0.001529 | 0.000315 | -0.000283 | 39.0 | 6.95204 | 1.296090 | 27159.1000 |
| 34 | 54001.515253 | 0.474994 | -0.474994 | 0.000924 | 0.000573 | -0.000477 | 13.0 | 6.68239 | 1.319230 | 9023.8000 |
| 35 | 54002.520797 | 0.477074 | -0.477074 | 0.001175 | 0.000392 | -0.000336 | 19.0 | 4.86250 | 1.397177 | 16816.4611 |
| 36 | 54003.523947 | 0.476023 | -0.476023 | 0.000902 | 0.000386 | -0.000324 | 15.0 | 5.08597 | 1.352240 | 14863.3000 |
| 37 | 54006.473985 | 0.470341 | -0.470341 | 0.000864 | 0.000433 | -0.000350 | 10.0 | 2.95052 | 1.297510 | 10583.3000 |
| 38 | 54009.485802 | 1.482193 | -1.482193 | 0.000379 | 0.000177 | -0.000152 | 20.0 | 9.66569 | 1.362140 | 37145.6000 |
| 39 | 54011.495094 | 0.476751 | -0.476751 | 0.001115 | 0.000681 | -0.000518 | 6.0 | 1.36028 | 1.395510 | 5804.4000 |
| 40 | 54012.424384 | 0.402432 | -0.402432 | 0.001179 | 0.000399 | -0.000341 | 18.0 | 4.39095 | 1.278874 | 14765.4897 |
| 41 | 54023.338587 | 1.334991 | -1.334991 | 0.000550 | 0.000275 | -0.000228 | 13.0 | 5.04527 | 1.350570 | 19519.3305 |
| 42 | 54056.494603 | 0.465791 | -0.465791 | 0.000814 | 0.000385 | -0.000314 | 11.0 | 3.20266 | 1.315218 | 12601.6898 |
| 43 | 54060.509081 | 0.473524 | -0.473524 | 0.000905 | 0.000485 | -0.000388 | 9.0 | 2.70163 | 1.442428 | 10034.2146 |
We have a pandas DataFrame with the light curve data in it. The upper limit entries are similar:
lcs['Total_UL']
| Time | TimePos | TimeNeg | UpperLimit | CtsInSrc | BGInSrc | CorrFact | Exposure | |
|---|---|---|---|---|---|---|---|---|
| 0 | 53972.115185 | 0.002146 | -0.002146 | 0.033719 | 1.0 | 0.117833 | 1.297271 | 308.3979 |
| 1 | 53983.583592 | 0.402257 | -0.402257 | 0.005793 | 1.0 | 0.783649 | 1.550901 | 2028.4057 |
| 2 | 54004.529811 | 0.470081 | -0.470081 | 0.002118 | 8.0 | 2.979070 | 1.281389 | 10049.2584 |
| 3 | 54005.505694 | 0.441811 | -0.441811 | 0.002482 | 7.0 | 3.148930 | 1.302565 | 7862.8928 |
| 4 | 54007.479178 | 0.471441 | -0.471441 | 0.001361 | 8.0 | 4.350830 | 1.310057 | 14710.3291 |
| 5 | 54013.899705 | 0.079428 | -0.079428 | 0.002864 | 3.0 | 1.258730 | 1.294858 | 4783.9284 |
| 6 | 54014.364350 | 0.333522 | -0.333522 | 0.002067 | 3.0 | 2.070700 | 1.288252 | 6193.0310 |
| 7 | 54016.220166 | 0.034669 | -0.034669 | 0.025967 | 0.0 | 0.178008 | 1.662100 | 378.6023 |
| 8 | 54019.519253 | 0.468909 | -0.468909 | 0.002533 | 6.0 | 2.209460 | 1.309719 | 7446.6810 |
| 9 | 54020.522711 | 0.468235 | -0.468235 | 0.003906 | 7.0 | 2.063620 | 1.297032 | 5328.0125 |
| 10 | 54021.531198 | 0.263198 | -0.263198 | 0.002760 | 6.0 | 1.853840 | 1.322800 | 7068.0787 |
| 11 | 54025.480183 | 0.476017 | -0.476017 | 0.001063 | 11.0 | 5.880080 | 1.269216 | 21532.6924 |
| 12 | 54026.511163 | 0.306173 | -0.306173 | 0.001524 | 3.0 | 2.384890 | 1.334519 | 8512.2835 |
| 13 | 54027.553192 | 0.342612 | -0.342612 | 0.023784 | 0.0 | 0.108319 | 1.401367 | 348.5147 |
| 14 | 54028.591359 | 0.373880 | -0.373880 | 0.001921 | 3.0 | 1.809190 | 1.355842 | 7150.8196 |
| 15 | 54036.007690 | 0.004092 | -0.004092 | 0.010649 | 0.0 | 0.283920 | 1.272987 | 707.0586 |
| 16 | 54038.484385 | 0.469053 | -0.469053 | 0.001710 | 3.0 | 2.268550 | 1.652575 | 9467.5648 |
| 17 | 54039.484920 | 0.474059 | -0.474059 | 0.001656 | 7.0 | 2.649130 | 1.265282 | 11819.4122 |
| 18 | 54040.490127 | 0.475101 | -0.475101 | 0.001222 | 5.0 | 3.185050 | 1.267645 | 12466.2956 |
| 19 | 54041.286575 | 0.271148 | -0.271148 | 0.005062 | 1.0 | 0.637675 | 2.120338 | 3204.3294 |
| 20 | 54042.763095 | 0.204929 | -0.204929 | 0.001569 | 0.0 | 1.426380 | 1.607898 | 6062.6514 |
| 21 | 54043.504793 | 0.464583 | -0.464583 | 0.001483 | 4.0 | 2.282300 | 1.274420 | 9695.7291 |
| 22 | 54044.501642 | 0.474025 | -0.474025 | 0.001276 | 4.0 | 2.811490 | 1.485202 | 12646.8212 |
| 23 | 54045.504761 | 0.474369 | -0.474369 | 0.001598 | 7.0 | 3.730210 | 1.576513 | 14246.4786 |
| 24 | 54046.508530 | 0.474711 | -0.474711 | 0.001537 | 6.0 | 3.075950 | 1.401871 | 12388.5693 |
| 25 | 54047.512386 | 0.474393 | -0.474393 | 0.000814 | 1.0 | 2.790930 | 1.506115 | 12869.9709 |
| 26 | 54048.515458 | 0.473396 | -0.473396 | 0.002447 | 6.0 | 2.212960 | 1.371360 | 8068.4914 |
| 27 | 54049.494503 | 0.490868 | -0.490868 | 0.002499 | 3.0 | 1.734400 | 1.303667 | 5315.4760 |
| 28 | 54050.497280 | 0.493658 | -0.493658 | 0.002820 | 1.0 | 1.225020 | 1.280589 | 3349.7528 |
| 29 | 54051.526132 | 0.468956 | -0.468956 | 0.011335 | 2.0 | 0.454937 | 1.398840 | 1183.4456 |
| 30 | 54052.535227 | 0.464723 | -0.464723 | 0.004418 | 3.0 | 0.853124 | 1.472001 | 3648.1215 |
| 31 | 54053.601508 | 0.341499 | -0.341499 | 0.002004 | 5.0 | 2.108230 | 1.364737 | 8833.2179 |
| 32 | 54054.474640 | 0.471170 | -0.471170 | 0.001553 | 2.0 | 1.980040 | 1.464412 | 8028.3746 |
| 33 | 54055.483015 | 0.473895 | -0.473895 | 0.001473 | 6.0 | 3.397540 | 1.365396 | 12320.8722 |
| 34 | 54058.628317 | 1.348039 | -1.348039 | 0.000694 | 12.0 | 8.451180 | 1.410559 | 34543.0721 |
| 35 | 54061.599343 | 0.308939 | -0.308939 | 0.001946 | 4.0 | 2.700270 | 1.451537 | 8168.7834 |
| 36 | 54063.101831 | 0.740505 | -0.740505 | 0.001041 | 1.0 | 3.000460 | 1.545185 | 10267.3935 |
| 37 | 54065.511660 | 1.343496 | -1.343496 | 0.000841 | 7.0 | 5.573930 | 1.304707 | 19973.1518 |
| 38 | 54067.559580 | 0.378577 | -0.378577 | 0.002432 | 3.0 | 1.457760 | 1.307466 | 5596.2936 |
| 39 | 54068.624855 | 0.238987 | -0.238987 | 0.002196 | 3.0 | 1.779640 | 1.285235 | 5942.3010 |
| 40 | 54069.461654 | 0.339701 | -0.339701 | 0.002186 | 4.0 | 2.792960 | 1.286905 | 6406.1515 |
| 41 | 54070.432043 | 0.233711 | -0.233711 | 0.001818 | 0.0 | 1.333560 | 1.274132 | 4144.5669 |
| 42 | 54072.014098 | 0.001103 | -0.001103 | 0.039673 | 0.0 | 0.058285 | 1.278075 | 190.5548 |
| 43 | 54077.300627 | 0.202120 | -0.202120 | 0.003752 | 0.0 | 0.670689 | 1.288309 | 2030.9130 |
| 44 | 54079.211638 | 1.173732 | -1.173732 | 0.001239 | 4.0 | 2.910770 | 1.299411 | 11322.9668 |
| 45 | 54081.052000 | 0.008575 | -0.008575 | 0.006685 | 1.0 | 0.517624 | 1.282892 | 1481.8143 |
| 46 | 54088.492384 | 0.469389 | -0.469389 | 0.002129 | 0.0 | 0.929418 | 1.407998 | 3911.3880 |
| 47 | 54089.495969 | 0.472737 | -0.472737 | 0.001945 | 2.0 | 1.216940 | 1.347583 | 6218.1040 |
| 48 | 54090.509868 | 0.474129 | -0.474129 | 0.001714 | 1.0 | 1.406950 | 1.275728 | 5440.8410 |
| 49 | 54092.012685 | 0.980340 | -0.980340 | 0.000738 | 8.0 | 6.143210 | 1.408027 | 26226.3580 |
| 50 | 54096.496788 | 0.495529 | -0.495529 | 0.001764 | 3.0 | 2.138070 | 1.336990 | 7494.3197 |
The basic difference here being that the 'UpperLimit' column has replaced the 'Rate' and errors.
In the above call we got all data in all bands, but we didn't have to, because of the bands argument (see the General notes). Let's use it:
lcs = uds.getLightCurves(sourceName='LSXPS J221755.4-082100',
cat='LSXPS',
binning='snapshot',
timeFormat='TDB',
bands=('total', 'hard', 'HR1'),
saveData=False,
returnData=True
)
lcs.keys()
dict_keys(['Total_rates', 'Hard_rates', 'HR1', 'TimeFormat', 'T0', 'Binning', 'Datasets'])
You'll note in this case there are no 'UL' datasets, and that's because for this object (FO Aqr, the subject of my first ever paper), there are no upper limits, only detections.
This leads us nicely onto the somewhat thorny question of when something is a rate, and when it's an upper limit and what we get. There are essentially 3 classes of bin in an SXPS light curve:
Just like on the web pages for a given source, this API gives you some control over how the different classes of bin are returned. The default (like on the website) is that blind and retrospective detections are all given as count-rate bins and grouped together in the same curve (e.g. 'Total_rates'), whereas non-detections come as upper limits. If you are happy with this then I strongly advise you to skip ahead a bit, because we're about to dive into a rabbit hole.
You read on? You brave soul.
Seriously though, the above behaviour is a good default, but there are plenty of cases where you will want to drill down into the details a bit more, or customise how you handle data, and I've done my best to make this a) possible and b) easy. It is definitely much easier to do than to explain, but I'll do my best.
As on the website, the API gives you some options about how the different class of bin should be given. Blind detections will always be returned as 'rates' in the light curve, i.e. a bin with a count-rate and 1-sigma confidence errors; for the other two categories, it's up to you - you can get rates or upper limits, or both! For the hardness ratio the situation is a little different as we don't run source detection in a hardness ratio (a meaningless concept), and we don't get upper limits for HRs. Instead you have a choice: do you want to get HRs only for datasets with a blind detection of the source, or those with blind or retrospective detections?
As well as choosing how each class of bin is returned, you can decide whether you want to group all rates and ULs together (the default) or not. i.e. in the example we showed above which used all the defaults, there was a single 'Total_rates' light curve and this contained both blind and retrospective detections, but you may well want to keep those separate.
You can control these factors through a set of boolean arguments to getLightCurves().
The easiest is getAllTypes. If this is True then you will get all possible light curves, and all kept separately. That is, blind detections will be rates in their own dataset. Retrospective detections will be returned as rates, separate to the blind detections, and returned a second time, as upper limits. The same will be true of the non-detections, which will also be kept separate from the retrospective ones (this will make more sense when I demonstrate in a moment). getAllTypes is False by default.
If you don't set getAllTypes you can instead control what you get with these arguments:
groupRates (default: True) - whether all of bins returned as count-rates and errors should be grouped into the same light curve.groupULs (default: True) - whether all upper limits (non-detection, and retrospective only) should be grouped into the same light curve.groupHRs (default: True) - whether all HRs (blind and retrospective dets) should be grouped into the same light curve.retroAsUL (default: False) - whether to return upper limits, instead of count-rate bins, for retrospective detectionsnondetAsUL (default: True) - whether to return upper limits, instead of count-rate bins, for non detectionsgetRetroHR (default: True) - whether to include HRs from retrospective detections.Note that the group* parameters only group bins within an energy band, the different bands' data will always be kept separate.
Before I move on to some examples, let me quickly outline three more arguments you can set:
False) - whether the obsID for each bin should also be returned as a column in the data.True) - whether bins with the "pupWarn" flag set should be rejected.True) - whether to include points from sources identified as aliases of the selected source.If you don't know what these mean, you'll have to read the SXPS documentation, or accept the defaults and trust me.
Right, assuming you are still conscious, enthusiastic and ready to go, let's try a few of these options. For ease, I'm always only going to get the total band data in these examples.
Let's start with getAllTypes, as it shows us everything!
lcs = uds.getLightCurves(sourceName='LSXPS J051152.3-621925',
cat='LSXPS',
bands=('total',),
binning='obsid',
timeFormat='MJD',
saveData=False,
returnData=True,
getAllTypes=True
)
lcs['Datasets']
['Total_blind_rates',
'Total_retro_rates',
'Total_nondet_rates',
'Total_retro_UL',
'Total_nondet_UL']
We have 5 datasets here for the total band which I hope is what you expected. The blind detections are given only as rates, and the retrospective and non-detections appear both as count-rates and as upper limits. Please be aware that this means we have duplicated time bins. That is, every dataset with a retrospective detection appears in both the 'Total_retro_rates' and 'Total_retro_UL' - because we set getAllTypes=True.
If we don't set this flag, we won't get duplicated data, so we can instead select whether retrospective/non detections appear as rates or limit, and whether all rates or limits are grouped into one dataset or not. I'm not going to explore every option here, but let's really explicitly probe the grouping thing:
lcs = uds.getLightCurves(sourceName='LSXPS J051152.3-621925',
cat='LSXPS',
bands=('total',),
binning='obsid',
timeFormat='MJD',
saveData=False,
returnData=True,
retroAsUL = True,
groupULs = False
)
Here we have asked for the retrospective detections to be given as upper limits. The non-detections will also be upper limits (the default), but we also said groupULs=False, so instead of having a Total_UL light curve containing the retrospective and non-detections, we expect these to have been kept separate. Let's confirm this:
lcs['Datasets']
['Total_rates', 'Total_retro_UL', 'Total_nondet_UL']
Great! Now, to hammer home this point about grouping: how many of each type of bin was there?
print(f"Retro: {len(lcs['Total_retro_UL'])}")
print(f"Nondet: {len(lcs['Total_nondet_UL'])}")
Retro: 2
Nondet: 4
So if we give the same command as above, but with the grouping of upper limits enabled, we should get a single 'Total_UL' light curve, containing the bins from those two light curves above. Let's prove this:
lcs = uds.getLightCurves(sourceName='LSXPS J051152.3-621925',
cat='LSXPS',
bands=('total',),
binning='obsid',
timeFormat='MJD',
saveData=False,
returnData=True,
retroAsUL = True,
groupULs = True, ## This is the default, but I'm being explicit
)
lcs['Datasets']
['Total_rates', 'Total_UL']
So we now just have a 'Total_UL' dataset with all of the upper limits in it. Let's really verify that, shall we?
len(lcs['Total_UL'])
6
And unless something has broken between me writing this, and you running it, the number above should be the sum of the number from a few cells ago. Obviously, the analogue is true for the rate and HR grouping too but you can explore that in your own time, or we'll never finish this notebook. And there's lots still to get through, starting with:
Since we have our light curve data in a variable, we can make use of the module-level plotLightCurve() function to give us a quick plot. I'm not going to repeat the plotLightCurve() documentation here, just show it in action:
from swifttools.ukssdc import plotLightCurve
fig, ax = plotLightCurve(lcs, whichCurves=('Total_rates',),
ylog=True,
verbose=True)
Creating new subplot object
Plotting Total_rates as upper rates

And I'll take this chance to show you something about that function; as well as returning fig, ax it can receive them if you want to add to the plot. So I may want to plot upper limits as well:
fig, ax = plotLightCurve(lcs, whichCurves=('Total_UL',),
ylog=True,
verbose=True,
fig=fig,
cols={"Total_UL": "blue"},
ax=ax)
fig
Plotting Total_UL as upper limits

For reasons I don't fully understand, Jupyter only plots this again if I put the fig line at the end of the cell, which is why I did it. I hope you noticed that this function automatically realised that the upper limits were, er, upper limits; I also used the 'cols' argument to specify the colour for my upper limits.
It may be that you didn't want to handle the data in a variable at all, but just grab the light curves into files on disk. We can do this by calling getLightCurves(saveData=True), like this:
uds.getLightCurves(sourceName='LSXPS J062131.8-622213',
cat='LSXPS',
saveData=True,
binning='obsid',
timeFormat='MJD',
destDir='/tmp/APIDemo_SXPS_LC',
verbose=True,
)
Getting data for sourceName = `LSXPS J062131.8-622213`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['TimeFormat', 'T0', 'Binning', 'Datasets', 'Total_ratesData', 'Total_ULData', 'Soft_ratesData', 'Soft_ULData', 'Medium_ratesData', 'Medium_ULData', 'Hard_ratesData', 'Hard_ULData', 'HR1Data', 'HR2Data', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_LC
Writing file: `/tmp/APIDemo_SXPS_LC/Total_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Total_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Soft_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Soft_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Medium_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Medium_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Hard_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/Hard_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/HR1_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC/HR2_MJD_Observation.dat`
I turned verbose on so you could see what was happening, and feel free to go and look at those files.
This function actually doesn't do very much itself, most of the work is done by another common function:
saveLightCurveFromDict(), and most of the arguments
you may pass to saveLightCurves() are just keyword arguments that will get passed straight through. The
uds.getLightCuvres function will override the default values for the timeFormatInFname and binningInFname
arguments for saveLightCurveFromDict(), setting them both to False unless you explicitly specify them.
As well as the arguments we pass to saveLightCurveFromDict(),
we can use all of those complicated controls over how data are grouped and formatted that we discussed earlier as well, for example:
uds.getLightCurves(sourceName='LSXPS J062131.8-622213',
cat='LSXPS',
saveData=True,
binning='obsid',
timeFormat='MJD',
destDir='/tmp/APIDemo_SXPS_LC2',
verbose=True,
getAllTypes=True
)
Getting data for sourceName = `LSXPS J062131.8-622213`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['TimeFormat', 'T0', 'Binning', 'Datasets', 'Total_blind_ratesData', 'Total_retro_ratesData', 'Total_nondet_ratesData', 'Total_retro_ULData', 'Total_nondet_ULData', 'Soft_blind_ratesData', 'Soft_retro_ratesData', 'Soft_nondet_ratesData', 'Soft_retro_ULData', 'Soft_nondet_ULData', 'Medium_blind_ratesData', 'Medium_retro_ratesData', 'Medium_nondet_ratesData', 'Medium_retro_ULData', 'Medium_nondet_ULData', 'Hard_blind_ratesData', 'Hard_retro_ratesData', 'Hard_nondet_ratesData', 'Hard_retro_ULData', 'Hard_nondet_ULData', 'HR1_blindData', 'HR1_retroData', 'HR2_blindData', 'HR2_retroData', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_LC2
Writing file: `/tmp/APIDemo_SXPS_LC2/Total_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Total_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Total_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Total_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Total_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Soft_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Soft_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Soft_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Soft_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Soft_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Medium_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Medium_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Medium_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Medium_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Medium_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Hard_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Hard_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Hard_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Hard_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/Hard_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/HR1_blind_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/HR1_retro_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/HR2_blind_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC2/HR2_retro_MJD_Observation.dat`
Let me also demonstrate the subDirs issue which only comes into play when we get mutliple light curves. It is True by default but I'll be explicit:
uds.getLightCurves(sourceName=('LSXPS J062131.8-622213','LSXPS J051152.3-621925'),
cat='LSXPS',
saveData=True,
binning='obsid',
timeFormat='MJD',
destDir='/tmp/APIDemo_SXPS_LC3',
verbose=True,
subDirs=True
)
Getting data for sourceName = `LSXPS J062131.8-622213`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['TimeFormat', 'T0', 'Binning', 'Datasets', 'Total_ratesData', 'Total_ULData', 'Soft_ratesData', 'Soft_ULData', 'Medium_ratesData', 'Medium_ULData', 'Hard_ratesData', 'Hard_ULData', 'HR1Data', 'HR2Data', 'OK', 'APIVersion'])
Getting data for sourceName = `LSXPS J051152.3-621925`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['TimeFormat', 'T0', 'Binning', 'Datasets', 'Total_ratesData', 'Total_ULData', 'Soft_ratesData', 'Soft_ULData', 'Medium_ratesData', 'Medium_ULData', 'Hard_ratesData', 'Hard_ULData', 'HR1Data', 'HR2Data', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_LC3
Making directory /tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Total_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Total_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Soft_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Soft_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Medium_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Medium_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Hard_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/Hard_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/HR1_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J062131.8-622213/HR2_MJD_Observation.dat`
Making directory /tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Total_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Total_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Soft_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Soft_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Medium_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Medium_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Hard_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/Hard_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/HR1_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC3/LSXPS J051152.3-621925/HR2_MJD_Observation.dat`
As you saw, I asked for light curves for two sources, and each was saved in its own subdirectory. Since I requested sources by name, the names are used to index the directories.
You have probably noticed that the file names are the same for the two sources, which means that if I had subDirs=False we'd have an issue, so in that case the source names are prepended to the file names, thus:
uds.getLightCurves(sourceName=('LSXPS J062131.8-622213','LSXPS J051152.3-621925'),
cat='LSXPS',
saveData=True,
binning='obsid',
timeFormat='MJD',
destDir='/tmp/APIDemo_SXPS_LC4',
verbose=True,
subDirs=False
)
Getting data for sourceName = `LSXPS J062131.8-622213`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['TimeFormat', 'T0', 'Binning', 'Datasets', 'Total_ratesData', 'Total_ULData', 'Soft_ratesData', 'Soft_ULData', 'Medium_ratesData', 'Medium_ULData', 'Hard_ratesData', 'Hard_ULData', 'HR1Data', 'HR2Data', 'OK', 'APIVersion'])
Getting data for sourceName = `LSXPS J051152.3-621925`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['TimeFormat', 'T0', 'Binning', 'Datasets', 'Total_ratesData', 'Total_ULData', 'Soft_ratesData', 'Soft_ULData', 'Medium_ratesData', 'Medium_ULData', 'Hard_ratesData', 'Hard_ULData', 'HR1Data', 'HR2Data', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_LC4
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Total_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Total_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Soft_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Soft_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Medium_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Medium_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Hard_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_Hard_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_HR1_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J062131.8-622213_HR2_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Total_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Total_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Soft_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Soft_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Medium_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Medium_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Hard_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_Hard_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_HR1_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC4/LSXPS J051152.3-621925_HR2_MJD_Observation.dat`
Notice now that everything is in /tmp/APIDemo_SXPS_LC3/ but with unique file names.
There is a third way ('yesss, yesss, we found it we did') to deal with light curves, which is that you can download them using the getLightCurves() function with returnData=True and then save them with a functionsaveLightCurves(). You may wonder why you would want to do this, instead of just letting getLightCurves() save the data for you -- the answer is that you may want to only save some of the data you downloaded.
There are two extra arguments we can add when saving this way:
whichSources allows you to specify which of the sources in your lc variable to save.whichCurves allows you to specify which of the curves (entries in the 'Datasets' array) to save.Obviously, the former argument only makes sense if we downloaded a few light curves, so, let's plunge in with one example, covering everything. First, I'm going to download all light curve stuff for three objects.
lcs = uds.getLightCurves(sourceName=('LSXPS J051152.3-621925','LSXPS J221755.4-082100', 'LSXPS J062131.8-622213'),
cat='LSXPS',
bands='all',
binning='obsid',
timeFormat='MJD',
saveData=False,
returnData=True,
getAllTypes=True
)
Let's remind ourself what this looks like:
lcs.keys()
dict_keys(['LSXPS J051152.3-621925', 'LSXPS J221755.4-082100', 'LSXPS J062131.8-622213'])
lcs['LSXPS J051152.3-621925']['Datasets']
['Total_blind_rates',
'Total_retro_rates',
'Total_nondet_rates',
'Total_retro_UL',
'Total_nondet_UL',
'Soft_blind_rates',
'Soft_retro_rates',
'Soft_nondet_rates',
'Soft_retro_UL',
'Soft_nondet_UL',
'Medium_blind_rates',
'Medium_retro_rates',
'Medium_nondet_rates',
'Medium_retro_UL',
'Medium_nondet_UL',
'Hard_blind_rates',
'Hard_retro_rates',
'Hard_nondet_rates',
'Hard_retro_UL',
'Hard_nondet_UL',
'HR1_blind',
'HR1_retro',
'HR2_blind',
'HR2_retro']
But now, for whatever reason, I only want to save the light curves of the first and third sources, and I only want to save the total-band blind rates, and the hard band non-detection upper limits.
uds.saveLightCurves(lcs,
whichSources=('LSXPS J051152.3-621925','LSXPS J062131.8-622213'),
whichCurves=('Total_blind_rates', 'Hard_nondet_UL'),
destDir='/tmp/APIDemo_SXPS_LC5',
subDirs=True,
verbose=True
)
Making directory /tmp/APIDemo_SXPS_LC5
Making directory /tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Total_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Total_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Total_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Total_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Total_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Soft_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Soft_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Soft_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Soft_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Soft_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Medium_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Medium_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Medium_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Medium_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Medium_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Hard_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Hard_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Hard_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Hard_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/Hard_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/HR1_blind_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/HR1_retro_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/HR2_blind_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J051152.3-621925/HR2_retro_MJD_Observation.dat`
Making directory /tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Total_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Total_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Total_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Total_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Total_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Soft_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Soft_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Soft_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Soft_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Soft_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Medium_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Medium_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Medium_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Medium_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Medium_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Hard_blind_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Hard_retro_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Hard_nondet_rates_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Hard_retro_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/Hard_nondet_UL_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/HR1_blind_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/HR1_retro_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/HR2_blind_MJD_Observation.dat`
Writing file: `/tmp/APIDemo_SXPS_LC5/LSXPS J062131.8-622213/HR2_retro_MJD_Observation.dat`
I turned on verbosity so you can see what its doing.
Just a few things to note:
saveLightCurves is the dict retured by getLightCurves().getLightCurves() call had specified sourceID instead of sourceName then in the above, whichCurves would have been a list of sourceIDs.whichCurves and whichSources can be 'all', instead of a list; indeed, this is their default value.For those of you who had read the GRB documentation and have been wondering for a while why I introduced getting things into a variable before saving to disk, I'm hoping you may have worked it out now… Essentially the reason is that for GRBs, saveData=True literally grabbed light curve files from the server and saved them to disk. You had no control over the format or anything of the files, you got what the server has. For SXPS, there are no such files (the light curves are compiled on the fly from some rather huge database tables), so saveData=True is completely identical to doing returnData=True and then calling saveLightCurves(). I'm sure you were desperate to know that.
Right, that took a while but you'll be glad to know that the worst is out of the way. SXPS source light curves are probably the second most complicated thing in the entire swifttools.ukssdc module (the most complicated being the GRB burst analyser data and we've got to the end of it. So take a breath, get a drink (I'll have a Hobgoblin Ruby please) and then we can move on...
What, we're still not done with sources? No, but nearly!
SXPS sources deemed bright enough have automatically-created and fitted spectra. You can access the data for these in a manner analogous to the light curves: save them directly to disk, return as a variable (or both), or return as a variable and then save to disk!
Spectra also differ a bit from light curves, in that the data we save and the data we get into a variable are not quite the same. When saving data to disk we save the spectral files (ready for use in xspec) but we don't return these raw data to a variable due to the specific nature of spectral data. Instead, the variable we return contains information about the spectrum, and its fit.
If you've already read GRB spectrum information you probably don't need to re-read all of this, you just need to know that for SXPS spectra there is only one rname, called 'interval0', and only one mode (PC) but there can be 2 models ('PowerLaw' and 'APEC'). If that didn't make sense to you, you need to read on.
We get spectra via a function called getSpectra() (bet you didn't see that coming), and as normal, the default behaviour is to save the spectral data to disk. Behind the scenes, this uses the saveSpectrum() common function.
For spectra we can choose to save a gif image of the spectrum and fit, and/or a .tar.gz archive containing the spectral files. There are various arguments you can provide to control how things are saved:
extract (default False) - whether to extract the spectral data from the tar file they are downloaded in.removeTar (default False) - whether to delete the tar file after extracting (this is ignored if extract is False)saveImages (default True) - whether to downoad the gif images of the automated spectral fits.prefix (default None) - an optional prefix to prepend to the names of the downloaded files. NOTE: this is not prepended to things extracted from the tar archive.The usual subDirs parameter is not listed here (you can supply it; you will be ignored). Because the contents of each tar file have the same name, if downloading spectra from multiple sources they will always be put in their own subdirectory, you cannot disable this.
Anyway, "A little less conversation a little more action" seems appropriate here, so let's get to work:
uds.getSpectra(sourceName='LSXPS J221755.4-082100',
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_spec',
verbose=True,
extract=True,
removeTar=True
)
Getting data for sourceName = `LSXPS J221755.4-082100`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['T0', 'DeltaFitStat', 'GalNH_unfitted', 'rnames', 'interval0', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_spec
Transient False
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_SXPS_spec/interval0.tar.gz`
Saving file `/tmp/APIDemo_SXPS_spec/interval0.tar.gz`
Extracting `/tmp/APIDemo_SXPS_spec/interval0.tar.gz`
README.txt
interval0pcsource.pi
interval0pcback.pi
interval0pc.pi
interval0pc.arf
interval0pc.rmf
interval0.areas
GRB_info.txt
models/interval0pc_apec.xcm
models/interval0pc_pow.xcm
interval0pc_apec_fit.fit
interval0pc_pow_fit.fit
Removing file /tmp/APIDemo_SXPS_spec/interval0.tar.gz
Downloading file `/tmp/APIDemo_SXPS_spec/interval0pc_pow_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec/interval0pc_pow_plot.gif`
Downloading file `/tmp/APIDemo_SXPS_spec/interval0pc_apec_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec/interval0pc_apec_plot.gif`
I turned on verbose mode so that you can see what's happening. Because we only requested one object the data were saved directly into the destDir, and then extracted as requested. If we had requested multiple spectra they would have been saved in multiple directories, named for the sourceID or name, depending on how we called the function, so:
uds.getSpectra(sourceName=('LSXPS J221755.4-082100', 'LSXPS J033112.0+435414'),
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_spec2',
verbose=True,
extract=True,
removeTar=True
)
Getting data for sourceName = `LSXPS J221755.4-082100`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['T0', 'DeltaFitStat', 'GalNH_unfitted', 'rnames', 'interval0', 'OK', 'APIVersion'])
Getting data for sourceName = `LSXPS J033112.0+435414`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['T0', 'DeltaFitStat', 'GalNH_unfitted', 'rnames', 'interval0', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_spec2
Making directory /tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100
Transient False
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0.tar.gz`
Saving file `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0.tar.gz`
Extracting `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0.tar.gz`
README.txt
interval0pcsource.pi
interval0pcback.pi
interval0pc.pi
interval0pc.arf
interval0pc.rmf
interval0.areas
GRB_info.txt
models/interval0pc_apec.xcm
models/interval0pc_pow.xcm
interval0pc_apec_fit.fit
interval0pc_pow_fit.fit
Removing file /tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0.tar.gz
Downloading file `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0pc_pow_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0pc_pow_plot.gif`
Downloading file `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0pc_apec_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec2/LSXPS J221755.4-082100/interval0pc_apec_plot.gif`
Making directory /tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414
Transient False
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0.tar.gz`
Saving file `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0.tar.gz`
Extracting `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0.tar.gz`
README.txt
interval0pcsource.pi
interval0pcback.pi
interval0pc.pi
interval0pc.arf
interval0pc.rmf
interval0.areas
GRB_info.txt
models/interval0pc_apec.xcm
models/interval0pc_pow.xcm
interval0pc_apec_fit.fit
interval0pc_pow_fit.fit
Removing file /tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0.tar.gz
Downloading file `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0pc_pow_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0pc_pow_plot.gif`
Downloading file `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0pc_apec_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec2/LSXPS J033112.0+435414/interval0pc_apec_plot.gif`
Hopefully you spotted the subdirectories above.
You can explore those files yourselves, I'm not giving an X-ray spectroscopy primer here!
One little note: if you want just the images and no tar file, you can set saveData=False, you will still get the images unless you also say saveImages=False.
As with light curves, we can grab the spectral information into a variable instead of (or as well as) saving to disk. In this case most of what we get is information about the spectral fit. As with pretty much everything in this API, when we do this we get a dict, and, in a shocking feat of imaginative naming, I call this a 'spectral dict', and it is documented with the other common data structures in this module.
So, let's get an spectrum:
specData = uds.getSpectra(sourceName='LSXPS J221755.4-082100',
cat='LSXPS',
saveData=False,
saveImages=False,
returnData=True,
)
Note that I have set both saveData and saveImages to False so all I have got is the spectral data. This follows the spectral dict and I'm not going to detail this much because of the dedicated documentation, but let's at least look at something. I want to know what the results of the APEC fit to this object was, and I know that, for all SXPS spectra, we only have one time interval (called interval0) and only one mode (PC), so I can jump straight to it:
specData['interval0']['PC']['APEC']
{'NH': 2.4225699999999997e+22,
'NHPos': 1.0006478800000008e+21,
'NHNeg': -7.268195799999999e+20,
'KT': 64,
'KTPos': 0,
'KTNeg': -1.1800726499999996,
'ObsFlux': 2.941710969752721e-11,
'ObsFluxPos': 4.866421422665964e-13,
'ObsFluxNeg': -5.005015402383723e-13,
'UnabsFlux': 4.1658151973796153e-11,
'UnabsFluxPos': 7.043380918691522e-13,
'UnabsFluxNeg': -7.226010160274717e-13,
'Cstat': 2619.411827,
'Dof': 876,
'FitChi': 2020.220249,
'Image': 'https://www.swift.ac.uk/LSXPS/sources/source106107/spectrum/interval0pc_apec_plot.gif'}
The only other thing to say here is a reminder that if you supplied a list/tuple of source IDs or names in the getSpectra() call then specData will have an extra level - the top level will have one entry for each source you requested.
As with light curves, you can separate the get and save phases, by calling getSpectra(returnData=True) and then calling saveSpectra(). The arguments for saveSpectra() are as discussed above when saving via the getSpectra() function, with one addition, whichSources. As for light curves, this lets you choose to save the spectra only of a subset of the sources you downloaded, thus:
specData = uds.getSpectra(sourceName=('LSXPS J051152.3-621925','LSXPS J221755.4-082100', 'LSXPS J062131.8-622213'),
cat='LSXPS',
saveData=False,
saveImages=False,
returnData=True,
)
uds.saveSpectra(specData,
whichSources=('LSXPS J051152.3-621925','LSXPS J221755.4-082100'),
destDir='/tmp/APIDemo_SXPS_spec3',
verbose=True,
extract=True,
removeTar=True
)
Making directory /tmp/APIDemo_SXPS_spec3
Making directory /tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925
Transient False
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0.tar.gz`
Saving file `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0.tar.gz`
Extracting `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0.tar.gz`
README.txt
interval0pcsource.pi
interval0pcback.pi
interval0pc.pi
interval0pc.arf
interval0pc.rmf
interval0.areas
GRB_info.txt
models/interval0pc_apec.xcm
models/interval0pc_pow.xcm
interval0pc_apec_fit.fit
interval0pc_pow_fit.fit
Removing file /tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0.tar.gz
Downloading file `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0pc_pow_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0pc_pow_plot.gif`
Downloading file `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0pc_apec_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec3/LSXPS J051152.3-621925/interval0pc_apec_plot.gif`
Making directory /tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100
Transient False
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0.tar.gz`
Saving file `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0.tar.gz`
Extracting `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0.tar.gz`
README.txt
interval0pcsource.pi
interval0pcback.pi
interval0pc.pi
interval0pc.arf
interval0pc.rmf
interval0.areas
GRB_info.txt
models/interval0pc_apec.xcm
models/interval0pc_pow.xcm
interval0pc_apec_fit.fit
interval0pc_pow_fit.fit
Removing file /tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0.tar.gz
Downloading file `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0pc_pow_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0pc_pow_plot.gif`
Downloading file `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0pc_apec_plot.gif`
Saving file `/tmp/APIDemo_SXPS_spec3/LSXPS J221755.4-082100/interval0pc_apec_plot.gif`
You can also download the png-format thumbnail images of the sources. These can only be saved to disk, not returned, and therefore the function is saveSourceImages(). Its arguments should be familiar by now, so let's just get on with it:
uds.saveSourceImages(sourceName='LSXPS J051152.3-621925',
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_image',
verbose=True)
Making directory /tmp/APIDemo_SXPS_image
Getting images for sourceName = `LSXPS J051152.3-621925`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Total', 'Soft', 'Medium', 'Hard', 'Expmap', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925
Downloading file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Total.png`
Saving file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Total.png`
Downloading file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Soft.png`
Saving file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Soft.png`
Downloading file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Medium.png`
Saving file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Medium.png`
Downloading file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Hard.png`
Saving file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Hard.png`
Downloading file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Expmap.png`
Saving file `/tmp/APIDemo_SXPS_image/LSXPS J051152.3-621925/Expmap.png`
As usual, cat is not mandatory but I think it's helpful, and I turned on verbosity so you can see what was happening.
One thing which I hope you noted above: as well as the usual bands (total, soft, etc) there is "Expmap" - which is the exposure map. So if you set the bands argument to something other than all then you can include 'expmap' (case insensitive), as well as the usual 'hard', 'total' etc.
As usual, this function includes a subDirs parameter (default: True) which is used if you supply a list of sourceNames or IDs. If True the images go into a separate directory for each source; if False, the source name or ID is prepended to the file name, as below:
uds.saveSourceImages(sourceName=('LSXPS J051152.3-621925','LSXPS J221755.4-082100'),
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_image2',
subDirs=False,
verbose=True)
Making directory /tmp/APIDemo_SXPS_image2
Getting images for sourceName = `LSXPS J051152.3-621925`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Total', 'Soft', 'Medium', 'Hard', 'Expmap', 'OK', 'APIVersion'])
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Total.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Total.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Soft.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Soft.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Medium.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Medium.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Hard.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Hard.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Expmap.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J051152.3-621925_Expmap.png`
Getting images for sourceName = `LSXPS J221755.4-082100`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Total', 'Soft', 'Medium', 'Hard', 'Expmap', 'OK', 'APIVersion'])
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Total.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Total.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Soft.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Soft.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Medium.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Medium.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Hard.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Hard.png`
Downloading file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Expmap.png`
Saving file `/tmp/APIDemo_SXPS_image2/LSXPS J221755.4-082100_Expmap.png`
Note the "Saving file" lines - all the files went into the same directory, but with the source name in the file. (Random aside: I hate spaces in directories and filenames, so I always supply 'sourceID' when I actually use this API myself).
You may want to build some custom products of a given SXPS source, using the XRTProductRequest object in the swifttools.ukssdc.xrt_prods module. To aid in this, there is a function makeProductRequest(), which will generate XRTProductRequests for you, supplying what information it can from the catalogue.
NOTE The function aims to return a submittable XRTProductRequest object for you, based on the catalogue information. This means that if you don't specify the T0 or observation list via the arguments below, the global parameters getT0 or getTargs will be set to True. Obviously, the XRTProductRequest can be manipulated before submission. If you don't know what I'm talking about, you should read the xrt_prods documentation before using this function.
In order to get this information, the function needs some information from you, so you must provide either the result of an earlier getSourceDetails() function call, or the name of the catalogue so that getSourceDetails() can be called internally. Or, if you are requesting multiple sources, you can always supply both and then getSourceDetails() will be called for any sources not in your sourceDetails dataset.
The information automatically applied to the product request is some subset of:
The first two of these are self-explanatory.
"Whether to centroid" is set to False, since the position determined from the catalogue should be the best position (the analysis tools will still check for snapshot-to-snapshot variability).
For T0, you have a few options, which are controlled by the T0 parameter to makeProductRequest(). This can be:
None (default): Let the user objects software set T0. This leaves the T0 global parameter in the XRTProductRequest object unset, but sets getT0 to True.T0 the start time of the first SXPS observation of the source location.T0 the start time of the first SXPS observation in which this source was blindly detected.T0 the start time of the first SXPS observation in which this source was detected, blindly or retrospectively.The targetID list and observation list are correlated, they determine which data should be used to build the product. This can be controlled by the useObs argument to makeProductRequest(). The behaviour of this is slightly more complex than T0. It sets the getTargs and targ global parameters in the XRTProductRequest, and it will also set the whichData and useObs arguments of any products you request (discussed in a minute). But please note those keys are only set for products you request in the makeProductRequest() call. If you then edit the returned XRTProductRequest object to add more products, those parameters will not be set, you will have to do this yourself (I will note how, below).
If not specified, the useObs argument is set to "all". This is the easiest case, and SXPS data are basically not used, because "all" means "use all data, including any not in SXPS". In this case the getTargs global parameter in the XRTProductRequest is set to True, and the targ value will be unset. All requested products will have whichData set to "all".
For all of the other useObs values, getTargs will be set to False, targ will be set to specific values, and for the requested products, whichData will be "user" and the product's useObs parameter will be set to the string giving the requested observations.
In full, the possible values for the useObs argument to makeProductRequest() are:
I have mentioned products several times; by default the XRTProductRequest will be returned with the global parameters set, but nothing else. However, the addProds argument to makeProductRequest() allows you to specify some products as well. If you do this, those products are added to the request, and their whichData and useObs parameters set as discussed above.
If you do not specify products, or don't specify all of them, then the "useObs" parameter is essentially pointless if it is not "all" (the default), since the restricted obs list is only applied to products. However, I have given an argument returnObsList. This is False by default, but if set to True then instead of returning an XRTProductRequest object, makeProductRequest() will return a dict with two keys: request will be the XRTProductRequest object, and useObs will be the string to pass to any products' useObs parameter if you add parameters.
Of course, the requests are not submitted, so you can view and play with them. And, like with all of these functions, you can supply a single sourceID (or name) and get back a single XRTProductRequest, or you can supply a list of IDs (or names) and get back a dict, indexed by ID or name.
Right, that is comprehensively far too much talk, so let's get to some demos:
First, a simple one:
myReq = uds.makeProductRequest('MY_EMAIL_ADDRESS',
cat='LSXPS',
sourceID=17092,
useObs='all',
silent=False
)
myReq.getGlobalPars()
Have to get sourceDetails for sourceID=17092
{'name': 'LSXPS J132527.7-430212',
'RA': 201.365762,
'Dec': -43.03672808,
'centroid': False,
'posErr': 1,
'useSXPS': True,
'getTargs': True,
'getT0': True}
Don't forget that you have to be registered to use the on-demand product tools, and to put the correct email address above.
In the above call, I did not provide any source information, instead I provided the catalogue, so the data lookup happened in the background. Let's see what it gave me:
print(myReq)
myReq.getGlobalPars()
XRTProductRequest object for user `MY_EMAIL_ADDRESS`, with the following products requested:
{'name': 'LSXPS J132527.7-430212',
'RA': 201.365762,
'Dec': -43.03672808,
'centroid': False,
'posErr': 1,
'useSXPS': True,
'getTargs': True,
'getT0': True}
OK, good, this made us a single request, and the default parameters have been set. Obviously, you can now edit this object, add products, submit it etc., but we're not doing that now (if you don't know how to, you need to read the xrt_prods documentation.
Let's explore a few more ways of using this function. First, we will specify that the product should only be built using observations in which our source was blindly detected, and we'll also say what products we want. Oh, and let's set silent to suppress all the output.
myReq = uds.makeProductRequest('MY_EMAIL_ADDRESS',
cat='LSXPS',
sourceID=17092,
T0='firstBlindDet',
useObs='blind',
addProds=['LightCurve', 'StandardPos'],
silent=True,
)
print(myReq)
print(f"Globals: {myReq.getGlobalPars()}\n")
for p in myReq.productList:
print(f"{p}:\t{myReq.getProductPars(p)}")
XRTProductRequest object for user `MY_EMAIL_ADDRESS`, with the following products requested:
* light curve
* standard position
Globals: {'name': 'LSXPS J132527.7-430212', 'targ': '00050950,00031312,00034314,00088977', 'T0': 129528000.0, 'RA': 201.365762, 'Dec': -43.03672808, 'centroid': False, 'posErr': 1, 'useSXPS': True, 'getTargs': False, 'getT0': False}
lc: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
psf: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
This all looks pretty good; notice how having supplied useObs='blind', the API has worked out for us which observations correspond to a blind detection. There is a problem, however: this information is only applied to products requested via uds.makeProductRequest(). The xrt_prods module does not copy information about observations between products (because it's easy to do yourself). So, for example, if we now decide to add a spectrum:
myReq.addSpectrum()
for p in myReq.productList:
print(f"{p}:\t{myReq.getProductPars(p)}")
lc: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
psf: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
spec: {'deltaFitStat': 2.706}
You can see that the spectrum parameters don't include the observation list. Of course, you can set it by yourself easily enough:
myReq.setSpectrumPars(whichData='user', useObs = myReq.getLightCurvePars()['useObs'])
for p in myReq.productList:
print(f"{p}:\t{myReq.getProductPars(p)}")
lc: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
psf: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
spec: {'deltaFitStat': 2.706, 'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
OK, two more things. First, I said above you don't have to supply the cat argument, you can instead get the source information yourself and then pass that directly to makeProductRequest(). We do that via the sourceDetails argument, as below:
info = uds.getSourceDetails(sourceID=17092,
cat='LSXPS',
silent=True,
verbose=False
)
myReq = uds.makeProductRequest('MY_EMAIL_ADDRESS',
sourceDetails=info,
sourceID=17092,
T0='firstBlindDet',
useObs='blind',
addProds=['LightCurve','Spectrum', 'StandardPos'],
silent=True,
)
print(myReq)
print(f"Globals: {myReq.getGlobalPars()}\n")
for p in myReq.productList:
print(f"{p}:\t{myReq.getProductPars(p)}")
XRTProductRequest object for user `MY_EMAIL_ADDRESS`, with the following products requested:
* light curve
* spectrum
* standard position
Globals: {'name': 'LSXPS J132527.7-430212', 'targ': '00050950,00031312,00034314,00088977', 'T0': 129528000.0, 'RA': 201.365762, 'Dec': -43.03672808, 'centroid': False, 'posErr': 1, 'useSXPS': True, 'getTargs': False, 'getT0': False}
lc: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
spec: {'deltaFitStat': 2.706, 'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
psf: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
Not surprisingly, this worked just as above. One note: if you do this - if you use the sourceDetails argument - and you gave a single value for sourceID (rather than a list) then it will be this source for which the request is built even if the sourceID parameter passed to makeProductRequest is different. i.e. sourceDetails trumps sourceID. If you're worried about making an error because of this, either don't use sourceDetails or always use a tuple. i.e. if you replace the sourceID argument (in both function calls) with sourceID=(17092,) then everything will be all right.
The last thing to show, related to what I've just said, is that we can of course pass in multiple sources as I said before. I'm actually going to combine one other thing in this demo: if you pass in sourceInfo, but it does not contain the info for the source you submitted, then a getSourceDetails() call will again be done in the background. I will turn verbosity on to make this clear:
data = uds.getSourceDetails(sourceID=(17092,),
cat='LSXPS',
silent=True,
verbose=False
)
rlist = uds.makeProductRequest('MY_EMAIL_ADDRESS',
sourceDetails=info,
sourceID=(17092,128791),
cat='LSXPS', # This is actually the default, but explicit is good
T0='firstBlindDet',
useObs='blind',
addProds=['LightCurve'],
silent=False,
verbose=False
)
Have to get sourceDetails for sourceID=17092
Also setting global getT0 = False
Also setting global getTargs = False
Successfully created a light curve
OK, setting whichData = user
OK, setting useObs = 00050950004,00050950006,00031312122,00034314001,00034314003,00088977001
Also setting lc whichData = user, because useObs = 00050950004,00050950006,00031312122,00034314001,00034314003,00088977001 (ANY)
Have to get sourceDetails for sourceID=128791
Also setting global getT0 = False
Also setting global getTargs = False
Successfully created a light curve
OK, setting whichData = user
OK, setting useObs = 00015016002
Also setting lc whichData = user, because useObs = 00015016002 (ANY)
As you see, we did a sourceInfo look up for 17006. You'll also notice that when I turned silent off, it was disabled for the XRTProductRequest objects as well, hence the extra blurb. We'll sort that in a second, first, let's look at what we got:
rlist
{17092: XRTProductRequest object, 128791: XRTProductRequest object}
Hopefully you were expecting that: we got a dict, and the keys were the supplied sourceIDs. If we have given sourceName not ID then the keys would be the names -- and the sourceInfo object would also need to be indexed by name or look ups would be done in the background.
I mentioned that we may want to make the actual XRTProductRequests be silent. Let's do that, and also just check them out:
for sourceID in rlist.keys():
print(f"\n{sourceID}\n======")
rlist[sourceID].silent=True
print(f"{rlist[sourceID]}")
print(f"Globals: {rlist[sourceID].getGlobalPars()}\n")
for p in rlist[sourceID].productList:
print(f"{p}:\t{rlist[sourceID].getProductPars(p)}")
17092
======
XRTProductRequest object for user `MY_EMAIL_ADDRESS`, with the following products requested:
* light curve
Globals: {'name': 'LSXPS J132527.7-430212', 'targ': '00050950,00031312,00034314,00088977', 'T0': 129528000.0, 'RA': 201.365762, 'Dec': -43.03672808, 'centroid': False, 'posErr': 1, 'useSXPS': True, 'getTargs': False, 'getT0': False}
lc: {'whichData': 'user', 'useObs': '00050950004,00050950006,00031312122,00034314001,00034314003,00088977001'}
128791
======
XRTProductRequest object for user `MY_EMAIL_ADDRESS`, with the following products requested:
* light curve
Globals: {'name': 'LSXPS J130059.3+275850', 'targ': '00015016', 'T0': 663928360.997203, 'RA': 195.2473611251, 'Dec': 27.9805846866, 'centroid': False, 'posErr': 1, 'useSXPS': True, 'getTargs': False, 'getT0': False}
lc: {'whichData': 'user', 'useObs': '00015016002'}
And you can see that we have two separate requests with their own parameters.
IMPORTANT REMINDER
This system allows you to easily create large numbers of XRTProductRequest objects, but please do not submit large numbers at once. The xrt_prods documentation gives advice on how to throttle your submissions. Users who overload the system will be given a stern talking to...
Datasets can be directly accessed through this module, either by their ObsID, or their DatasetID (LSXPS only). ObsIDs are the Swift standard 11-digit identifier of an observation, except for stacked images (which are built by combining observations); these have been given a 'fake' ObsID which begins with a 1 (normal Swift observations begin with 0), so if an obsID is >1e10, then it is a stacked image.
At present there are two things you can get for a dataset: the full set of information about it, and the images
Because LSXPS is dynamic, an observation may be analysed several times as new data are received on the quicklook site, thus each version of an observation is assigned a unique DatasetID for LSXPS. For normal observations, only a single DatasetID will enter the catalogue. Stacked images in LSXPS are more complex, because they can change as new data are added, as discussed in Sections 2.2 and 3.3 of the LSXPS paper. If you request products for a stacked image which has been superseded then you will get back details of the superseding stacks, rather than the products you asked for. We will return to this below.
Note: This functionality only exists for LSXPS
To get information about a dataset, we simply call the function getDatasetDetails(). As for sources, this does not have an option to save data to disk, simply always returning a dict. It has only the standard arguments (DatasetID or ObsID, cat, silent and verbose). So, let's go exploring:
dsInfo = uds.getDatasetDetails(ObsID='00282445000', cat='LSXPS')
dsInfo
{'DatasetID': 9725,
'OriginalExposure': 35894.5068000853,
'ExposureUsed': 34467.9,
'RA': 32.21544,
'Decl': 56.93269,
'l': 133.381153413184,
'b': -4.36002927363241,
'ImageSize': 1000,
'FieldBG_band0': 7.11205e-07,
'FieldBG_band1': 2.1145e-07,
'FieldBG_band2': 1.82208e-07,
'FieldBG_band3': 3.73284e-07,
'NumSrc_band0': 25,
'NumOK_band0': 20,
'MedianDist_band0': 91.7497659255654,
'NumSrc_band1': 8,
'NumOK_band1': 8,
'MedianDist_band1': 138.714538299276,
'NumSrc_band2': 13,
'NumOK_band2': 12,
'MedianDist_band2': 189.714643932916,
'NumSrc_band3': 8,
'NumOK_band3': 7,
'MedianDist_band3': 171.341923374331,
'StartTime_MET': 203705152.477843,
'StopTime_MET': 203803699.977843,
'MidTime_MET': 203754426.227843,
'MidTime_TDB': 2454268.765854076,
'MidTime_MJD': 54268.2687986174,
'AstromError': 2.78977,
'NumberOfSnapshots': 18,
'FieldFlag': 0,
'StartTime_UTC': '2007-06-16 16:45:50',
'StopTime_UTC': '2007-06-17 20:08:17',
'CRVAL1_corr': 32.2154431843056,
'CRVAL2_corr': 56.93269,
'CROTA2_corr': 0,
'ra_rad': 0.5622654979786821,
'sindec': 0.8380301577082725,
'cosdec': 0.5456239133060867,
'IsStackedImage': 0,
'DataVersion': 23,
'LiveDate': '2021-12-03 01:44:14',
'ObsID': '00282445000',
'IsObsoleteStack': 0,
'TargetID': 282445,
'FieldName': 'Observation 00282445000',
'inStack': [10000014634],
'TargetObjectName': 'GRB070616',
'TargetObjectRA': 32.152917,
'TargetObjectDec': 56.945528,
'SourcesThisField': 29,
'NumAllSources': 74,
'OK': 1,
'Sources': ObsSourceID DatasetID LSXPS_ID OSNum UsedCorrectedPosition \
0 46570 9725 209540 1 1
1 46571 9725 209541 2 1
2 46572 9725 209542 3 1
3 46573 9725 209543 4 1
4 46574 9725 209545 5 1
5 46575 9725 209546 6 1
6 46576 9725 209547 7 1
7 46577 9725 209549 8 1
8 46578 9725 209559 9 1
9 46579 9725 209548 10 1
10 46580 9725 209555 11 1
11 46581 9725 209554 12 1
12 46582 9725 209560 13 1
13 46583 9725 209563 14 1
14 46584 9725 209550 15 1
15 46585 9725 18290 16 1
16 46586 9725 209558 17 1
17 46587 9725 209597 18 1
18 46588 9725 209589 19 1
19 46589 9725 209557 20 1
20 46590 9725 18293 21 1
21 46591 9725 209592 22 1
22 46592 9725 209562 23 1
23 46593 9725 209565 24 1
24 46594 9725 18301 25 1
25 46595 9725 209551 26 1
26 46596 9725 209591 27 1
27 46597 9725 18299 28 1
28 46598 9725 209564 29 1
NearestNeighbour NearestOKNeighbour Exposure HR1 HR1_pos \
0 110.101900 110.101900 32102.128118 0.516215 0.042264
1 89.995404 201.328988 33061.088535 -0.597976 0.095367
2 222.880233 222.880233 28478.506739 0.405930 0.212163
3 150.160784 150.160784 26745.223986 -0.233273 0.158398
4 77.397100 77.397100 21595.810139 -0.231272 0.168748
5 72.059941 72.059941 21984.717057 -0.375948 0.184374
6 135.690083 201.029179 31446.808901 0.358638 0.235176
7 122.507402 122.507402 29171.375936 0.726274 0.273726
8 77.397100 77.397100 22326.967995 -0.313068 0.200934
9 159.421949 159.421949 26993.766380 0.447692 0.552305
10 63.232022 63.232022 31872.987296 0.675949 0.324051
11 60.132402 60.132402 31978.553625 0.811390 0.188610
12 60.143177 60.143177 30606.106041 0.499421 0.500579
13 60.143177 60.143177 29394.399412 0.331574 0.668426
14 150.160784 150.160784 28791.075780 0.523849 0.476151
15 89.995404 89.995404 32725.469768 0.385756 0.614244
16 166.674287 166.674287 32459.877461 0.641984 0.358016
17 110.101900 110.101900 29683.549978 -0.376178 0.191742
18 39.510825 39.510825 26408.051620 -0.894065 0.005309
19 127.275033 127.275033 29718.765098 0.046989 0.953007
20 39.510825 39.510825 25872.578658 -0.387948 0.165393
21 91.749766 91.749766 32507.058046 0.371633 0.628367
22 72.059941 72.059941 19784.732284 -0.525536 0.116494
23 236.886571 236.886571 27733.857594 0.349695 0.650305
24 127.275033 231.297224 31562.068196 0.232981 0.767019
25 60.132402 60.132402 31077.930362 0.706806 0.293194
26 104.380965 104.380965 26880.390981 -0.717652 0.046959
27 135.690083 135.690083 27212.816935 0.681760 0.318240
28 233.366200 233.366200 27573.874754 0.553807 0.446193
... Err90 Soft_DetectionDetails \
0 ... 2.840053 {'DetectionID': 87018, 'Rate': 0.00640934, 'Ra...
1 ... 3.262042 {'DetectionID': 87019, 'Rate': 0.00216024, 'Ra...
2 ... 3.604375 NaN
3 ... 4.074014 {'DetectionID': 87020, 'Rate': 0.000903818, 'R...
4 ... 4.726320 {'DetectionID': 87021, 'Rate': 0.000928608, 'R...
5 ... 3.728157 {'DetectionID': 87022, 'Rate': 0.0008459, 'Rat...
6 ... 4.049135 {'DetectionID': 87024, 'Rate': 0.000242089, 'R...
7 ... 4.511424 NaN
8 ... 5.102136 {'DetectionID': 87023, 'Rate': 0.000621925, 'R...
9 ... 4.740798 NaN
10 ... 4.919220 NaN
11 ... 5.828070 NaN
12 ... 6.870564 NaN
13 ... 5.034856 NaN
14 ... 5.274784 NaN
15 ... 6.437954 NaN
16 ... 5.835620 NaN
17 ... 5.408675 NaN
18 ... 7.209561 NaN
19 ... 5.525174 NaN
20 ... 7.030090 NaN
21 ... 6.270896 NaN
22 ... 5.268523 {'DetectionID': 87025, 'Rate': 0.000397444, 'R...
23 ... 4.984001 NaN
24 ... 6.398952 NaN
25 ... 6.288322 NaN
26 ... 5.595802 NaN
27 ... 7.311984 NaN
28 ... 5.606083 NaN
Medium_DetectionDetails \
0 {'DetectionID': 87026, 'Rate': 0.0200874, 'Rat...
1 {'DetectionID': 87027, 'Rate': 0.000512571, 'R...
2 {'DetectionID': 87028, 'Rate': 0.000627753, 'R...
3 {'DetectionID': 87029, 'Rate': 0.000580526, 'R...
4 {'DetectionID': 87031, 'Rate': 0.000562418, 'R...
5 {'DetectionID': 87033, 'Rate': 0.000343186, 'R...
6 {'DetectionID': 87030, 'Rate': 0.000542825, 'R...
7 {'DetectionID': 87034, 'Rate': 0.000241131, 'R...
8 NaN
9 {'DetectionID': 87032, 'Rate': 0.000300101, 'R...
10 NaN
11 NaN
12 NaN
13 {'DetectionID': 87036, 'Rate': 0.000143923, 'R...
14 NaN
15 NaN
16 {'DetectionID': 87038, 'Rate': 0.000207209, 'R...
17 NaN
18 NaN
19 NaN
20 NaN
21 NaN
22 NaN
23 NaN
24 NaN
25 {'DetectionID': 87035, 'Rate': 0.000227899, 'R...
26 NaN
27 {'DetectionID': 87037, 'Rate': 0.000224495, 'R...
28 NaN
Hard_DetectionDetails RA_sexagesimal \
0 {'DetectionID': 87039, 'Rate': 0.0146539, 'Rat... 02 08 36.30
1 NaN 02 08 35.79
2 {'DetectionID': 87040, 'Rate': 0.000877273, 'R... 02 08 09.10
3 NaN 02 08 17.73
4 NaN 02 07 42.71
5 NaN 02 09 55.63
6 NaN 02 09 29.04
7 {'DetectionID': 87043, 'Rate': 0.000457565, 'R... 02 09 40.73
8 NaN 02 07 35.48
9 NaN 02 09 41.96
10 {'DetectionID': 87041, 'Rate': 0.00047556, 'Ra... 02 09 09.59
11 {'DetectionID': 87042, 'Rate': 0.000443849, 'R... 02 09 02.45
12 NaN 02 08 24.55
13 NaN 02 08 27.63
14 NaN 02 08 10.33
15 NaN 02 08 42.02
16 NaN 02 08 50.37
17 {'DetectionID': 87044, 'Rate': 0.000351108, 'R... 02 08 49.74
18 NaN 02 09 05.77
19 NaN 02 08 21.16
20 NaN 02 09 06.00
21 NaN 02 09 01.11
22 NaN 02 09 57.08
23 NaN 02 07 44.10
24 {'DetectionID': 87045, 'Rate': 0.000258448, 'R... 02 08 05.82
25 NaN 02 09 05.44
26 NaN 02 08 40.15
27 NaN 02 09 41.22
28 {'DetectionID': 87046, 'Rate': 0.000218285, 'R... 02 08 15.85
Decl_sexagesimal Hard_NonDetectionDetails \
0 +56 56 44.6 NaN
1 +56 53 23.3 {'sourceID': 209541, 'dsID': 9725, 'band': 3, ...
2 +56 52 40.3 NaN
3 +57 05 19.8 {'sourceID': 209543, 'dsID': 9725, 'band': 3, ...
4 +56 49 48.5 {'sourceID': 209545, 'dsID': 9725, 'band': 3, ...
5 +57 00 10.9 {'sourceID': 209546, 'dsID': 9725, 'band': 3, ...
6 +56 57 27.8 {'sourceID': 209547, 'dsID': 9725, 'band': 3, ...
7 +57 00 24.7 NaN
8 +56 50 38.2 {'sourceID': 209559, 'dsID': 9725, 'band': 3, ...
9 +57 03 03.8 {'sourceID': 209548, 'dsID': 9725, 'band': 3, ...
10 +56 51 48.2 NaN
11 +56 51 24.4 NaN
12 +57 01 12.9 {'sourceID': 209560, 'dsID': 9725, 'band': 3, ...
13 +57 00 18.2 {'sourceID': 209563, 'dsID': 9725, 'band': 3, ...
14 +57 03 02.3 {'sourceID': 209550, 'dsID': 9725, 'band': 3, ...
15 +56 54 37.4 {'sourceID': 18290, 'dsID': 9725, 'band': 3, '...
16 +57 00 02.7 {'sourceID': 209558, 'dsID': 9725, 'band': 3, ...
17 +56 56 50.2 NaN
18 +57 01 52.0 {'sourceID': 209589, 'dsID': 9725, 'band': 3, ...
19 +56 57 29.3 {'sourceID': 209557, 'dsID': 9725, 'band': 3, ...
20 +57 02 31.4 {'sourceID': 18293, 'dsID': 9725, 'band': 3, '...
21 +56 52 55.5 {'sourceID': 209592, 'dsID': 9725, 'band': 3, ...
22 +56 58 59.8 {'sourceID': 209562, 'dsID': 9725, 'band': 3, ...
23 +56 55 14.2 {'sourceID': 209565, 'dsID': 9725, 'band': 3, ...
24 +56 57 50.9 NaN
25 +56 50 29.5 {'sourceID': 209551, 'dsID': 9725, 'band': 3, ...
26 +56 51 45.2 {'sourceID': 209591, 'dsID': 9725, 'band': 3, ...
27 +56 55 55.8 {'sourceID': 18299, 'dsID': 9725, 'band': 3, '...
28 +56 48 53.6 NaN
Soft_NonDetectionDetails \
0 NaN
1 NaN
2 {'sourceID': 209542, 'dsID': 9725, 'band': 1, ...
3 NaN
4 NaN
5 NaN
6 NaN
7 {'sourceID': 209549, 'dsID': 9725, 'band': 1, ...
8 NaN
9 {'sourceID': 209548, 'dsID': 9725, 'band': 1, ...
10 {'sourceID': 209555, 'dsID': 9725, 'band': 1, ...
11 {'sourceID': 209554, 'dsID': 9725, 'band': 1, ...
12 {'sourceID': 209560, 'dsID': 9725, 'band': 1, ...
13 {'sourceID': 209563, 'dsID': 9725, 'band': 1, ...
14 {'sourceID': 209550, 'dsID': 9725, 'band': 1, ...
15 {'sourceID': 18290, 'dsID': 9725, 'band': 1, '...
16 {'sourceID': 209558, 'dsID': 9725, 'band': 1, ...
17 {'sourceID': 209597, 'dsID': 9725, 'band': 1, ...
18 {'sourceID': 209589, 'dsID': 9725, 'band': 1, ...
19 {'sourceID': 209557, 'dsID': 9725, 'band': 1, ...
20 {'sourceID': 18293, 'dsID': 9725, 'band': 1, '...
21 {'sourceID': 209592, 'dsID': 9725, 'band': 1, ...
22 NaN
23 {'sourceID': 209565, 'dsID': 9725, 'band': 1, ...
24 {'sourceID': 18301, 'dsID': 9725, 'band': 1, '...
25 {'sourceID': 209551, 'dsID': 9725, 'band': 1, ...
26 {'sourceID': 209591, 'dsID': 9725, 'band': 1, ...
27 {'sourceID': 18299, 'dsID': 9725, 'band': 1, '...
28 {'sourceID': 209564, 'dsID': 9725, 'band': 1, ...
Medium_NonDetectionDetails \
0 NaN
1 NaN
2 NaN
3 NaN
4 NaN
5 NaN
6 NaN
7 NaN
8 {'sourceID': 209559, 'dsID': 9725, 'band': 2, ...
9 NaN
10 {'sourceID': 209555, 'dsID': 9725, 'band': 2, ...
11 {'sourceID': 209554, 'dsID': 9725, 'band': 2, ...
12 {'sourceID': 209560, 'dsID': 9725, 'band': 2, ...
13 NaN
14 {'sourceID': 209550, 'dsID': 9725, 'band': 2, ...
15 {'sourceID': 18290, 'dsID': 9725, 'band': 2, '...
16 NaN
17 {'sourceID': 209597, 'dsID': 9725, 'band': 2, ...
18 {'sourceID': 209589, 'dsID': 9725, 'band': 2, ...
19 {'sourceID': 209557, 'dsID': 9725, 'band': 2, ...
20 {'sourceID': 18293, 'dsID': 9725, 'band': 2, '...
21 {'sourceID': 209592, 'dsID': 9725, 'band': 2, ...
22 {'sourceID': 209562, 'dsID': 9725, 'band': 2, ...
23 {'sourceID': 209565, 'dsID': 9725, 'band': 2, ...
24 {'sourceID': 18301, 'dsID': 9725, 'band': 2, '...
25 NaN
26 {'sourceID': 209591, 'dsID': 9725, 'band': 2, ...
27 NaN
28 {'sourceID': 209564, 'dsID': 9725, 'band': 2, ...
Total_NonDetectionDetails
0 NaN
1 NaN
2 NaN
3 NaN
4 NaN
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
10 NaN
11 NaN
12 NaN
13 NaN
14 NaN
15 NaN
16 NaN
17 {'sourceID': 209597, 'dsID': 9725, 'band': 0, ...
18 NaN
19 NaN
20 NaN
21 NaN
22 NaN
23 NaN
24 NaN
25 {'sourceID': 209551, 'dsID': 9725, 'band': 0, ...
26 NaN
27 {'sourceID': 18299, 'dsID': 9725, 'band': 0, '...
28 {'sourceID': 209564, 'dsID': 9725, 'band': 0, ...
[29 rows x 34 columns]}
As you can see from the above, this is largely a dict containing the information that is provided in the dataset web pages (in fact, those web pages are built from this dict). Let's explore a few of the entries here.
If you scroll down in the above you'll see one thing that look like a tables -- 'Sources'. This is indeed a table (the list of sources in the dataset you can see on the webpage) and this has been converted into a DataFrame:
dsInfo['Sources']
| ObsSourceID | DatasetID | LSXPS_ID | OSNum | UsedCorrectedPosition | NearestNeighbour | NearestOKNeighbour | Exposure | HR1 | HR1_pos | ... | Err90 | Soft_DetectionDetails | Medium_DetectionDetails | Hard_DetectionDetails | RA_sexagesimal | Decl_sexagesimal | Hard_NonDetectionDetails | Soft_NonDetectionDetails | Medium_NonDetectionDetails | Total_NonDetectionDetails | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 46570 | 9725 | 209540 | 1 | 1 | 110.101900 | 110.101900 | 32102.128118 | 0.516215 | 0.042264 | ... | 2.840053 | {'DetectionID': 87018, 'Rate': 0.00640934, 'Ra... | {'DetectionID': 87026, 'Rate': 0.0200874, 'Rat... | {'DetectionID': 87039, 'Rate': 0.0146539, 'Rat... | 02 08 36.30 | +56 56 44.6 | NaN | NaN | NaN | NaN |
| 1 | 46571 | 9725 | 209541 | 2 | 1 | 89.995404 | 201.328988 | 33061.088535 | -0.597976 | 0.095367 | ... | 3.262042 | {'DetectionID': 87019, 'Rate': 0.00216024, 'Ra... | {'DetectionID': 87027, 'Rate': 0.000512571, 'R... | NaN | 02 08 35.79 | +56 53 23.3 | {'sourceID': 209541, 'dsID': 9725, 'band': 3, ... | NaN | NaN | NaN |
| 2 | 46572 | 9725 | 209542 | 3 | 1 | 222.880233 | 222.880233 | 28478.506739 | 0.405930 | 0.212163 | ... | 3.604375 | NaN | {'DetectionID': 87028, 'Rate': 0.000627753, 'R... | {'DetectionID': 87040, 'Rate': 0.000877273, 'R... | 02 08 09.10 | +56 52 40.3 | NaN | {'sourceID': 209542, 'dsID': 9725, 'band': 1, ... | NaN | NaN |
| 3 | 46573 | 9725 | 209543 | 4 | 1 | 150.160784 | 150.160784 | 26745.223986 | -0.233273 | 0.158398 | ... | 4.074014 | {'DetectionID': 87020, 'Rate': 0.000903818, 'R... | {'DetectionID': 87029, 'Rate': 0.000580526, 'R... | NaN | 02 08 17.73 | +57 05 19.8 | {'sourceID': 209543, 'dsID': 9725, 'band': 3, ... | NaN | NaN | NaN |
| 4 | 46574 | 9725 | 209545 | 5 | 1 | 77.397100 | 77.397100 | 21595.810139 | -0.231272 | 0.168748 | ... | 4.726320 | {'DetectionID': 87021, 'Rate': 0.000928608, 'R... | {'DetectionID': 87031, 'Rate': 0.000562418, 'R... | NaN | 02 07 42.71 | +56 49 48.5 | {'sourceID': 209545, 'dsID': 9725, 'band': 3, ... | NaN | NaN | NaN |
| 5 | 46575 | 9725 | 209546 | 6 | 1 | 72.059941 | 72.059941 | 21984.717057 | -0.375948 | 0.184374 | ... | 3.728157 | {'DetectionID': 87022, 'Rate': 0.0008459, 'Rat... | {'DetectionID': 87033, 'Rate': 0.000343186, 'R... | NaN | 02 09 55.63 | +57 00 10.9 | {'sourceID': 209546, 'dsID': 9725, 'band': 3, ... | NaN | NaN | NaN |
| 6 | 46576 | 9725 | 209547 | 7 | 1 | 135.690083 | 201.029179 | 31446.808901 | 0.358638 | 0.235176 | ... | 4.049135 | {'DetectionID': 87024, 'Rate': 0.000242089, 'R... | {'DetectionID': 87030, 'Rate': 0.000542825, 'R... | NaN | 02 09 29.04 | +56 57 27.8 | {'sourceID': 209547, 'dsID': 9725, 'band': 3, ... | NaN | NaN | NaN |
| 7 | 46577 | 9725 | 209549 | 8 | 1 | 122.507402 | 122.507402 | 29171.375936 | 0.726274 | 0.273726 | ... | 4.511424 | NaN | {'DetectionID': 87034, 'Rate': 0.000241131, 'R... | {'DetectionID': 87043, 'Rate': 0.000457565, 'R... | 02 09 40.73 | +57 00 24.7 | NaN | {'sourceID': 209549, 'dsID': 9725, 'band': 1, ... | NaN | NaN |
| 8 | 46578 | 9725 | 209559 | 9 | 1 | 77.397100 | 77.397100 | 22326.967995 | -0.313068 | 0.200934 | ... | 5.102136 | {'DetectionID': 87023, 'Rate': 0.000621925, 'R... | NaN | NaN | 02 07 35.48 | +56 50 38.2 | {'sourceID': 209559, 'dsID': 9725, 'band': 3, ... | NaN | {'sourceID': 209559, 'dsID': 9725, 'band': 2, ... | NaN |
| 9 | 46579 | 9725 | 209548 | 10 | 1 | 159.421949 | 159.421949 | 26993.766380 | 0.447692 | 0.552305 | ... | 4.740798 | NaN | {'DetectionID': 87032, 'Rate': 0.000300101, 'R... | NaN | 02 09 41.96 | +57 03 03.8 | {'sourceID': 209548, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209548, 'dsID': 9725, 'band': 1, ... | NaN | NaN |
| 10 | 46580 | 9725 | 209555 | 11 | 1 | 63.232022 | 63.232022 | 31872.987296 | 0.675949 | 0.324051 | ... | 4.919220 | NaN | NaN | {'DetectionID': 87041, 'Rate': 0.00047556, 'Ra... | 02 09 09.59 | +56 51 48.2 | NaN | {'sourceID': 209555, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209555, 'dsID': 9725, 'band': 2, ... | NaN |
| 11 | 46581 | 9725 | 209554 | 12 | 1 | 60.132402 | 60.132402 | 31978.553625 | 0.811390 | 0.188610 | ... | 5.828070 | NaN | NaN | {'DetectionID': 87042, 'Rate': 0.000443849, 'R... | 02 09 02.45 | +56 51 24.4 | NaN | {'sourceID': 209554, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209554, 'dsID': 9725, 'band': 2, ... | NaN |
| 12 | 46582 | 9725 | 209560 | 13 | 1 | 60.143177 | 60.143177 | 30606.106041 | 0.499421 | 0.500579 | ... | 6.870564 | NaN | NaN | NaN | 02 08 24.55 | +57 01 12.9 | {'sourceID': 209560, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209560, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209560, 'dsID': 9725, 'band': 2, ... | NaN |
| 13 | 46583 | 9725 | 209563 | 14 | 1 | 60.143177 | 60.143177 | 29394.399412 | 0.331574 | 0.668426 | ... | 5.034856 | NaN | {'DetectionID': 87036, 'Rate': 0.000143923, 'R... | NaN | 02 08 27.63 | +57 00 18.2 | {'sourceID': 209563, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209563, 'dsID': 9725, 'band': 1, ... | NaN | NaN |
| 14 | 46584 | 9725 | 209550 | 15 | 1 | 150.160784 | 150.160784 | 28791.075780 | 0.523849 | 0.476151 | ... | 5.274784 | NaN | NaN | NaN | 02 08 10.33 | +57 03 02.3 | {'sourceID': 209550, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209550, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209550, 'dsID': 9725, 'band': 2, ... | NaN |
| 15 | 46585 | 9725 | 18290 | 16 | 1 | 89.995404 | 89.995404 | 32725.469768 | 0.385756 | 0.614244 | ... | 6.437954 | NaN | NaN | NaN | 02 08 42.02 | +56 54 37.4 | {'sourceID': 18290, 'dsID': 9725, 'band': 3, '... | {'sourceID': 18290, 'dsID': 9725, 'band': 1, '... | {'sourceID': 18290, 'dsID': 9725, 'band': 2, '... | NaN |
| 16 | 46586 | 9725 | 209558 | 17 | 1 | 166.674287 | 166.674287 | 32459.877461 | 0.641984 | 0.358016 | ... | 5.835620 | NaN | {'DetectionID': 87038, 'Rate': 0.000207209, 'R... | NaN | 02 08 50.37 | +57 00 02.7 | {'sourceID': 209558, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209558, 'dsID': 9725, 'band': 1, ... | NaN | NaN |
| 17 | 46587 | 9725 | 209597 | 18 | 1 | 110.101900 | 110.101900 | 29683.549978 | -0.376178 | 0.191742 | ... | 5.408675 | NaN | NaN | {'DetectionID': 87044, 'Rate': 0.000351108, 'R... | 02 08 49.74 | +56 56 50.2 | NaN | {'sourceID': 209597, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209597, 'dsID': 9725, 'band': 2, ... | {'sourceID': 209597, 'dsID': 9725, 'band': 0, ... |
| 18 | 46588 | 9725 | 209589 | 19 | 1 | 39.510825 | 39.510825 | 26408.051620 | -0.894065 | 0.005309 | ... | 7.209561 | NaN | NaN | NaN | 02 09 05.77 | +57 01 52.0 | {'sourceID': 209589, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209589, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209589, 'dsID': 9725, 'band': 2, ... | NaN |
| 19 | 46589 | 9725 | 209557 | 20 | 1 | 127.275033 | 127.275033 | 29718.765098 | 0.046989 | 0.953007 | ... | 5.525174 | NaN | NaN | NaN | 02 08 21.16 | +56 57 29.3 | {'sourceID': 209557, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209557, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209557, 'dsID': 9725, 'band': 2, ... | NaN |
| 20 | 46590 | 9725 | 18293 | 21 | 1 | 39.510825 | 39.510825 | 25872.578658 | -0.387948 | 0.165393 | ... | 7.030090 | NaN | NaN | NaN | 02 09 06.00 | +57 02 31.4 | {'sourceID': 18293, 'dsID': 9725, 'band': 3, '... | {'sourceID': 18293, 'dsID': 9725, 'band': 1, '... | {'sourceID': 18293, 'dsID': 9725, 'band': 2, '... | NaN |
| 21 | 46591 | 9725 | 209592 | 22 | 1 | 91.749766 | 91.749766 | 32507.058046 | 0.371633 | 0.628367 | ... | 6.270896 | NaN | NaN | NaN | 02 09 01.11 | +56 52 55.5 | {'sourceID': 209592, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209592, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209592, 'dsID': 9725, 'band': 2, ... | NaN |
| 22 | 46592 | 9725 | 209562 | 23 | 1 | 72.059941 | 72.059941 | 19784.732284 | -0.525536 | 0.116494 | ... | 5.268523 | {'DetectionID': 87025, 'Rate': 0.000397444, 'R... | NaN | NaN | 02 09 57.08 | +56 58 59.8 | {'sourceID': 209562, 'dsID': 9725, 'band': 3, ... | NaN | {'sourceID': 209562, 'dsID': 9725, 'band': 2, ... | NaN |
| 23 | 46593 | 9725 | 209565 | 24 | 1 | 236.886571 | 236.886571 | 27733.857594 | 0.349695 | 0.650305 | ... | 4.984001 | NaN | NaN | NaN | 02 07 44.10 | +56 55 14.2 | {'sourceID': 209565, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209565, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209565, 'dsID': 9725, 'band': 2, ... | NaN |
| 24 | 46594 | 9725 | 18301 | 25 | 1 | 127.275033 | 231.297224 | 31562.068196 | 0.232981 | 0.767019 | ... | 6.398952 | NaN | NaN | {'DetectionID': 87045, 'Rate': 0.000258448, 'R... | 02 08 05.82 | +56 57 50.9 | NaN | {'sourceID': 18301, 'dsID': 9725, 'band': 1, '... | {'sourceID': 18301, 'dsID': 9725, 'band': 2, '... | NaN |
| 25 | 46595 | 9725 | 209551 | 26 | 1 | 60.132402 | 60.132402 | 31077.930362 | 0.706806 | 0.293194 | ... | 6.288322 | NaN | {'DetectionID': 87035, 'Rate': 0.000227899, 'R... | NaN | 02 09 05.44 | +56 50 29.5 | {'sourceID': 209551, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209551, 'dsID': 9725, 'band': 1, ... | NaN | {'sourceID': 209551, 'dsID': 9725, 'band': 0, ... |
| 26 | 46596 | 9725 | 209591 | 27 | 1 | 104.380965 | 104.380965 | 26880.390981 | -0.717652 | 0.046959 | ... | 5.595802 | NaN | NaN | NaN | 02 08 40.15 | +56 51 45.2 | {'sourceID': 209591, 'dsID': 9725, 'band': 3, ... | {'sourceID': 209591, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209591, 'dsID': 9725, 'band': 2, ... | NaN |
| 27 | 46597 | 9725 | 18299 | 28 | 1 | 135.690083 | 135.690083 | 27212.816935 | 0.681760 | 0.318240 | ... | 7.311984 | NaN | {'DetectionID': 87037, 'Rate': 0.000224495, 'R... | NaN | 02 09 41.22 | +56 55 55.8 | {'sourceID': 18299, 'dsID': 9725, 'band': 3, '... | {'sourceID': 18299, 'dsID': 9725, 'band': 1, '... | NaN | {'sourceID': 18299, 'dsID': 9725, 'band': 0, '... |
| 28 | 46598 | 9725 | 209564 | 29 | 1 | 233.366200 | 233.366200 | 27573.874754 | 0.553807 | 0.446193 | ... | 5.606083 | NaN | NaN | {'DetectionID': 87046, 'Rate': 0.000218285, 'R... | 02 08 15.85 | +56 48 53.6 | NaN | {'sourceID': 209564, 'dsID': 9725, 'band': 1, ... | {'sourceID': 209564, 'dsID': 9725, 'band': 2, ... | {'sourceID': 209564, 'dsID': 9725, 'band': 0, ... |
29 rows × 34 columns
And you may note that the columns 'Total_DetectionDetails', 'Soft_DetectionDetails' etc are dicts giving summary details of the detection of this source in this dataset in the named band. I have to admit, having a dict inside a DataFrame seems a little inelegant to me, but I didn't like the idea of expanding these properties out and making the DataFrame really wide. If any readers have suggestions as to how to handle this better: I'm listening! As it is, it's not so hard to access the details, e.g. to see the total-band details for the first source:
dsInfo['Sources']['Total_DetectionDetails'][0]
{'DetectionID': 86993,
'Rate': 0.0413669,
'Rate_pos': 0.00124418,
'Rate_neg': -0.00124418,
'DetFlag': 0,
'CtsInRate': 1209,
'BGCtsInRate': 35.8986,
'SNR': 31.0509,
'PileupFitted': 0,
'RA': 32.1512389564,
'Decl': 56.9457126989,
'Err90': 3.5402098243551,
'RA_corrected': 32.15124247,
'Decl_corrected': 56.94571277,
'Err90_corrected': 2.840053213}
And of course we can access a specific property:
dsInfo['Sources']['Total_DetectionDetails'][0]['SNR']
31.0509
As with all of the data access functions (see the General notes) we can get details of multiple objects by supplying a list/tuple to getDatasetDetails(). In this case, we get a dict of dicts back, the outer layer being indexed by the obsID or datasetID, whichever we supplied, as we see here:
dsInfo = uds.getDatasetDetails(ObsID=('00282445000','00015231001'),
cat='LSXPS')
dsInfo.keys()
dict_keys(['00282445000', '00015231001'])
You can also download the FITS images and source regions (ds9 format) for your datasets, using the saveDatasetImages() function. As with source images, this is called save not get because you can only save data to disk.
Let's start with a quick demo:
uds.saveDatasetImages(ObsID='00282445000',
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_Im',
verbose=True,
getRegions=True)
Making directory /tmp/APIDemo_SXPS_Im
Getting data for ObsID = `00282445000`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Total', 'Soft', 'Medium', 'Hard', 'Expmap', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_Im/00282445000
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_total.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_total.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_total_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_total_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_total_final_BGmap_w_source.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_total_final_BGmap_w_source.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/total.reg`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/total.reg`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band1.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band1.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band1_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band1_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band1_final_BGmap_w_source.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band1_final_BGmap_w_source.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/band1.reg`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/band1.reg`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band2.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band2.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band2_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band2_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band2_final_BGmap_w_source.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band2_final_BGmap_w_source.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/band2.reg`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/band2.reg`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band3.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band3.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band3_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band3_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band3_final_BGmap_w_source.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_band3_final_BGmap_w_source.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/band3.reg`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/band3.reg`
Downloading file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_ex.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im/00282445000/00282445000_ex.img.gz`
As ever, I've turned on verbosity so you can see what is going on.
The default settings (used above) get all of the images for the specified dataset(s), and I added getRegions=True (it defaults to False) to get the ds9 region files as well.
Apart from the normal arguments, (subDirs, destDir etc), note that like for source images, bands can include "Expmap" - which is the exposure map.
The other useful parameter is 'types', which specifies which images you want to get. The default is 'all', but can instead be a (case insensitive) list/tuple of:
Let's do one more quick demo, exploting these features and reminding you that you can get more than one dataset in a single request.
uds.saveDatasetImages(ObsID=('00282445000','00221755001'),
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_Im2',
types=('image','backgroundmap'),
bands=('total', 'soft'),
verbose=True,
getRegions=True)
Making directory /tmp/APIDemo_SXPS_Im2
Getting data for ObsID = `00282445000`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Total', 'Soft', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_Im2/00282445000
Downloading file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_total.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_total.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_total_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_total_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00282445000/total.reg`
Saving file `/tmp/APIDemo_SXPS_Im2/00282445000/total.reg`
Downloading file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_band1.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_band1.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_band1_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00282445000/00282445000_band1_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00282445000/band1.reg`
Saving file `/tmp/APIDemo_SXPS_Im2/00282445000/band1.reg`
Getting data for ObsID = `00221755001`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Total', 'Soft', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_Im2/00221755001
Downloading file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_total.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_total.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_total_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_total_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00221755001/total.reg`
Saving file `/tmp/APIDemo_SXPS_Im2/00221755001/total.reg`
Downloading file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_band1.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_band1.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_band1_final_BGmap.img.gz`
Saving file `/tmp/APIDemo_SXPS_Im2/00221755001/00221755001_band1_final_BGmap.img.gz`
Downloading file `/tmp/APIDemo_SXPS_Im2/00221755001/band1.reg`
Saving file `/tmp/APIDemo_SXPS_Im2/00221755001/band1.reg`
As mentioned above, in the dynamic LSXPS catalogue, stacked images can be superseded (see Sections 2.2 and 3.3 of the LSXPS paper). So, what happens if you try to get the products for a superseded dataset?
First, we have to remember that there are two types of superseded stacks:
What happens if you try to access one of these images depends on which function you called.
saveDatasetImages() has no return type, so if you try to get a non-existent dataset (including a superseded stack) you will just get an error. If you try to get an obsolete stacked image then you will get the data, but with a warning message.
For getDatasetDetails() things are slightly different. Again, if you request a non-existent data you will just get an error, but if you ask for a superseded or obsolete one, the returned dict will contain the key "SupersedingStacks", which tells us that the stack is superseded, and by what.
I will demonstrate these points but be aware due to the above-mentioned dynamic nature of the catalogue, the stacks I've used in the demos below may themselves change. If you're reading the web page, then the output for these examples is fixed so all is well. If you are using the Jupyter notebook, you may not get the same results that I did!
Let's start by getting images. I'm going to request an image which I know is a superseded stack.
uds.saveDatasetImages(ObsID='10000000668',
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_Im3',
verbose=True,
getRegions=True)
Making directory /tmp/APIDemo_SXPS_Im3
Getting data for ObsID = `10000000668`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['ERROR', 'ERRORTEXT'])
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-90-754083b5eba4> in <module>
----> 1 uds.saveDatasetImages(ObsID='10000000668',
2 cat='LSXPS',
3 destDir='/tmp/APIDemo_SXPS_Im3',
4 verbose=True,
5 getRegions=True)
/fast/pae9/soft/src/notebooks/testAPI/data/swifttools/ukssdc/data/SXPS.py in saveDatasetImages(DatasetID, ObsID, cat, bands, types, getRegions, destDir, subDirs, clobber, skipErrors, silent, verbose)
1770 # We can just accept this result, as the only key we have to have is "OK", and
1771 # if that wasn't set we will already have hit an error.
-> 1772 tmp = base.submitAPICall("getSXPSDatasetImages", sendData, verbose=verbose)
1773 if 'SupersededBy' in tmp:
1774 print("\n ** WARNING: This dataset is an obsolete stack ** \n")
/fast/pae9/soft/src/notebooks/testAPI/data/swifttools/ukssdc/main.py in submitAPICall(func, data, minKeys, skipErrors, verbose)
148 if "ERRORTEXT" in ret:
149 msg = msg + f" Message: `{ret['ERRORTEXT']}`"
--> 150 raise RuntimeError(msg)
151
152 if "OK" not in ret and not skipErrors:
RuntimeError: An error occurred processing your request. Code 1. Message: `Dataset with obsid: `10000000668` is not found in the LSXPS catalogue.`
As predicted, I got an error, and the error message tells me that the dataset cannot be found. What if I'd tried an obsolete stack?
uds.saveDatasetImages(ObsID='10000000189',
cat='LSXPS',
destDir='/tmp/APIDemo_SXPS_Im3',
verbose=True,
getRegions=True)
Getting data for ObsID = `10000000189`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['SupersededBy', 'Total', 'Soft', 'Medium', 'Hard', 'Missingexpmap', 'OK', 'APIVersion'])
** WARNING: This dataset is an obsolete stack **
Making directory /tmp/APIDemo_SXPS_Im3/10000000189
No Image image exists for the Total band for `10000000189`.
No BackgroundMap image exists for the Total band for `10000000189`.
No BackgroundMapWithSources image exists for the Total band for `10000000189`.
Downloading file `/tmp/APIDemo_SXPS_Im3/10000000189/total.reg`
Saving file `/tmp/APIDemo_SXPS_Im3/10000000189/total.reg`
No Image image exists for the Soft band for `10000000189`.
No BackgroundMap image exists for the Soft band for `10000000189`.
No BackgroundMapWithSources image exists for the Soft band for `10000000189`.
Downloading file `/tmp/APIDemo_SXPS_Im3/10000000189/band1.reg`
Saving file `/tmp/APIDemo_SXPS_Im3/10000000189/band1.reg`
No Image image exists for the Medium band for `10000000189`.
No BackgroundMap image exists for the Medium band for `10000000189`.
No BackgroundMapWithSources image exists for the Medium band for `10000000189`.
Downloading file `/tmp/APIDemo_SXPS_Im3/10000000189/band2.reg`
Saving file `/tmp/APIDemo_SXPS_Im3/10000000189/band2.reg`
No Image image exists for the Hard band for `10000000189`.
No BackgroundMap image exists for the Hard band for `10000000189`.
No BackgroundMapWithSources image exists for the Hard band for `10000000189`.
Downloading file `/tmp/APIDemo_SXPS_Im3/10000000189/band3.reg`
Saving file `/tmp/APIDemo_SXPS_Im3/10000000189/band3.reg`
Hopefully you can see the warning line above -- with verbose mode enabled, it can get lost, so be careful!
Now lets explore these same two datasets with getDatasetDetails():
dsInfo = uds.getDatasetDetails(ObsID='10000000668', cat='LSXPS')
dsInfo.keys()
dict_keys(['SupersedingStacks'])
This was a case of a stack that has been superseded and removed, and we know this because the returned dict has the key "SupersedingStacks". Let's see what's in there:
dsInfo['SupersedingStacks']
{'OtherStacks': [{'DatasetID': 229389,
'DataVersion': 8,
'ObsID': 10000025185,
'ExposureUsed': 48359.9}]}
We have the key "OtherStacks", which contains a list giving some details of which stacks have superseded the one we requested; in this case there was only one of them. The key "OtherStacks" tells us that the superseding images are actually different stacks, that is, stack 668 is dead, and has been replaced with 25185. Sometimes when a stack is superseded it can be split up into multiple stacks, hence "OtherStacks" is a list.
I don't want to get bogged down here in the details of stacked image management in LSXPS, but you should be aware that if you request a stack by its ObsID, as here, the only way you can get this "SupersedingStacks" key is because the stack itself has been replaced, because querying by ObsID will always get you the latest version of a stack. But if you query by DatasetID, which is tied to a specific version of a stack, you can find that your requested image has been superseded not by a new stack, just by a new version of it. Like in this case:
dsInfo = uds.getDatasetDetails(DatasetID=229018, cat='LSXPS')
dsInfo['SupersedingStacks']
{'LatestVersion': {'DatasetID': 229389,
'DataVersion': 8,
'ObsID': 10000025185,
'ExposureUsed': 48359.9}}
Here, instead of the "OtherStacks" key we have the "LatestVersion" entry. This tells us that the stack that dataset 229018 was in still exists, but there is a newer version.
If we asked for the dataset details for an obsolete stack we would get the full set of data - that stack is still in LSXPS - but the "IsObsoleteStack" value will be 1, rather than 0, which tells us that the stack is obsolete.
dsInfo = uds.getDatasetDetails(DatasetID=228895, cat='LSXPS')
dsInfo["IsObsoleteStack"]
1
The final SXPS product currently supported for direct access are transients, which are an LSXPS product only. To obtain transient data, we use the same functions as for sources, but pass the argument transient=True (except in one case). Since these functions were all discussed at length in the sources section I am not going to go into huge detail here, beyond identifying some transient-specific arguments, so I advise you to read the sources section if you want to understand what follows (yes, I know, it's long. Sorry).
The first of these is transAsSource, which defaults to False and needs a few words of explanation. XRT data are searched for transients as soon as they are received, and transients made public as soon as possible, so the transients can (and usually will) be made public before the dataset they were discovered in is marked as 'complete' and added to LSXPS. Thus, transients are given a Transient ID and a "Swift J" name, rather than an LSXPS ID and "LSXPS J" name. However, the transient source will of course appear in LSXPS when its dataset is complete, so at this point the transient record is updated to point to the relevant LSXPS entry -- and the transient light curve and spectra stop being updated (since these products are now curated for the source entry instead) unless the XRT team explicitly request otherwise.
The transAsSource argument lets you obtain information from the LSXPS source, accessed via its transient ID. That is, if I know I am interested in transient "Swift J123456.7+891011", but I actually want the spectra created once it entered LSXPS, I can say getSpectra(sourceName='Swift J123456.7+891011', transient=True, transAsSource=True). But beware if this transient is not yet in LSXPS, you will get an error (unless you also said skipErrors=True, in which case you'll just get an empty dict). Also beware if you supply a list of sourceID/sourceName values with transAsSource=True then the products saved/returned will be indexed by their LSXPS ID or name, not the transient ID you supplied. Generally, I will not demonstrate this argument, since it literally reproduces the behaviour already shown in the sources section.
Right, with that introduction out of the way, let's have a brief ramble through the transient products.
The one exception to the 'just use the sources function' is the function to get the dict of transient information. For that we have a dedicated transients function, but I think you can probably guess both its name, and its action.
data = uds.getTransientDetails(sourceID=576)
You'll note that I didn't bother giving cat='LSXPS' in this case, since transients are only in LSXPS. Let's have a look at what we got:
data
{'TransientID': 576,
'IAUName': 'Swift J073006.8-193709',
'LSXPS_ID': 366116,
'Classification': 'Confirmed transient',
'RA': 112.5284106332,
'Decl': -19.6192622721,
'Err90': 5.68740477879596,
'l': 234.708996950239,
'b': -0.705047035949943,
'DiscoveryDatasetID': 220793,
'ObsSourceID': 749043,
'PeakRateAtDetection': 0.0160416440644274,
'PeakRateAtDetection_pos': 0.0049906500083039,
'PeakRateAtDetection_neg': -0.00414192562953323,
'PeakSoftMedBandRateAtDetection': 0.0111489237921355,
'PeakSoftMedBandRateAtDetection_pos': 0.00423985536554523,
'PeakSoftMedBandRateAtDetection_neg': -0.0033873644584664,
'UpperLimitSource_Canned': 'LSXPS',
'UpperLimitSource_DiscoverySpectrum': 'LSXPS',
'UpperLimitSource_FullSpectrum': 'LSXPS',
'Significance': 3.02347,
'InitSpecNH': 1.72226e+21,
'InitSpecGamma': 1.59935,
'InitSpecCstat': 10.37244981,
'InitSpecTestStat': 5.568326163,
'InitSpecDof': 10,
'FullSpecNH': 1.75759e+21,
'FullSpecGamma': 1.15274,
'FullSpecCstat': 114.4372468,
'FullSpecTestStat': 118.2043202,
'FullSpecDof': 139,
'DiscoveryDate': '2022-05-30 11:18:21',
'DetectionMET': 675591242.228083,
'DetectionDate': '2022-05-30 09:13:32',
'LSXPS_UpperLimit': 0.003518672440790348,
'LSXPS_UpperLimit_ObsID': '10000020072',
'XMM_UpperLimit_native': 1.062817,
'XMM_UpperLimit_ObsMode': 'SLEW',
'XMM_UpperLimit_Instrument': 'pn_Medium',
'XMM_UpperLimit_asXRTTotal_DiscoverySpectrum': 0.08195381886999999,
'XMM_UpperLimit_asXRTTotal_FullSpectrum': 0.08524855157,
'XMM_UpperLimit_asXRTTotal_Canned': 0.0682222,
'RASS_UpperLimit_native': 0.03586536,
'RASS_UpperLimit_asXRTSoftMed_DiscoverySpectrum': 0.020106120816,
'RASS_UpperLimit_asXRTSoftMed_FullSpectrum': 0.020629755072,
'RASS_UpperLimit_asXRTSoftMed_Canned': 0.016505238672,
'RASS_UpperLimit_asXRTTotal_DiscoverySpectrum': 0.035280754632,
'RASS_UpperLimit_asXRTTotal_FullSpectrum': 0.0462663144,
'RASS_UpperLimit_asXRTTotal_Canned': 0.0237485849675838,
'LSXPSName': 'LSXPS J073006.8-193710',
'Notes': 'This appears to be a recurrent transient optically - see ATEL 15404.',
'ClassificationCode': 1,
'DiscoveryObs': '03103545001',
'DiscoveryDatasetProgress': 'live',
'DetFlag': 0,
'OpticalLoadingWarning': 0,
'StrayLightWarning': 0,
'NearBrightSourceWarning': 0,
'LSXPS_UpperLimit_ObsID_Live': 0,
'BestUpperLimitSource': 'LSXPS',
'BestUpperLimit': 0.003518672440790348,
'BestUpperLimitBand': '0.3 — 10 keV',
'HasLC': 1,
'HasLCCountBin': 1,
'HasLCObsBin': 1,
'HasLCSnapshotBin': 1,
'HasInitialSpectrum': 1,
'HasFullSpectrum': 1,
'AllNewObs': ['00015190001',
'00015190002',
'00015190003',
'00015190005',
'00015190006',
'00015190007',
'00015190008',
'00015190009',
'00015190010',
'00015190011',
'00015190012',
'00015190013',
'00015190014',
'00015190015',
'00044002095',
'01110865000',
'03103197001',
'03103545001'],
'AllNewTargs': [15190, 44002, 1110865, 3103197, 3103545]}
There are no tables/DataFrames in there to worry about, just information. You will also note that this has a valid 'LSXPS_ID' entry, i.e. it is now in LSXPS, so we could have used that transAsSource argument. Let's do that:
data = uds.getTransientDetails(sourceID=576, transAsSource=True)
data
{'IAUName': 'LSXPS J073006.8-193710',
'LSXPS_ID': 366116,
'RA': 112.5286087,
'Decl': -19.61960257,
'Err90': 2.880784335,
'AstromType': 1,
'l': 234.709385064657,
'b': -0.705046593110074,
'MeanOffAxisAngle': 2.435,
'Exposure': 61778.2777932775,
'FirstObsDate': None,
'LastObsDate': '2022-06-21 21:09:30',
'FirstObsMET': None,
'LastObsMET': 677535000,
'FirstDetDate': '2017-08-18 18:43:00',
'LastDetDate': '2022-06-21 21:09:30',
'FirstDetMET': 524771000,
'LastDetMET': 677535000,
'FirstBlindDetDate': '2017-08-18 18:43:00',
'LastBlindDetDate': '2022-06-21 21:09:30',
'FirstBlindDetMET': 524771000,
'LastBlindDetMET': 677535000,
'NumObs': 23,
'NumBlindDetObs': 11,
'NumDetObs': 12,
'DetFlag': 0,
'FieldFlag': 0,
'DetFlag_band0': 0,
'DetFlag_band1': 0,
'DetFlag_band2': 0,
'DetFlag_band3': 0,
'BestDetectionID': 1523307,
'OpticalLoadingWarning': 0,
'StrayLightWarning': 0,
'NearBrightSourceWarning': 0,
'IsPotentialAlias': 0,
'Rate_band0': 0.00502152629386046,
'Rate_band0_pos': 0.000379747158498282,
'Rate_band0_neg': -0.000379747158498282,
'Rate_band1': 0.000788295187445924,
'Rate_band1_pos': 0.000168154711960014,
'Rate_band1_neg': -0.000152242068867608,
'Rate_band2': 0.00209067800650082,
'Rate_band2_pos': 0.00023617653176094,
'Rate_band2_neg': -0.000220277749335092,
'Rate_band3': 0.00204179770941655,
'Rate_band3_pos': 0.000237165451345535,
'Rate_band3_neg': -0.000221329095749632,
'Counts_band0': 232,
'Counts_band1': 45,
'Counts_band2': 92,
'Counts_band3': 93,
'BgCounts_band0': 21.4732538461685,
'BgCounts_band1': 11.9082392118871,
'BgCounts_band2': 4.02694429457188,
'BgCounts_band3': 7.00313729047775,
'RateCF_band0': 1.4536698890085,
'RateCF_band1': 1.45178868236289,
'RateCF_band2': 1.44835567047346,
'RateCF_band3': 1.44699692404985,
'NonBlindDet_band0': 1,
'NonBlindDet_band1': 1,
'NonBlindDet_band2': 1,
'NonBlindDet_band3': 1,
'UL_band0': 0.00540127345235875,
'UL_band1': 0.00133604266539019,
'UL_band2': 0.00283941797527322,
'UL_band3': 0.00279346664766345,
'PeakRate_band0': 0.0200761,
'PeakRate_band0_pos': 0.00430174,
'PeakRate_band0_neg': -0.00377348,
'PeakRate_band1': 0.00540739,
'PeakRate_band1_pos': 0.00510469,
'PeakRate_band1_neg': -0.00312611,
'PeakRate_band2': 0.00774533,
'PeakRate_band2_pos': 0.00279031,
'PeakRate_band2_neg': -0.00225544,
'PeakRate_band3': 0.0109377,
'PeakRate_band3_pos': 0.0032368,
'PeakRate_band3_neg': -0.00270586,
'PvarPchiSnapshot_band0': 0,
'PvarPchiSnapshot_band1': 0.01639483636066086,
'PvarPchiSnapshot_band2': 4.259329555722502e-10,
'PvarPchiSnapshot_band3': 0,
'PvarPchiSnapshot_HR1': None,
'PvarPchiSnapshot_HR2': None,
'PvarPchiObsID_band0': 0,
'PvarPchiObsID_band1': 0.0003099477587816812,
'PvarPchiObsID_band2': 0,
'PvarPchiObsID_band3': 0,
'PvarPchiObsID_HR1': 4.207196921068856e-06,
'PvarPchiObsID_HR2': 0,
'HR1': 0.418532,
'HR1_pos': 0.0828,
'HR1_neg': -0.098073,
'HR2': -0.007257,
'HR2_pos': 0.076511,
'HR2_neg': -0.077046,
'GalacticNH': 8.681859e+21,
'WhichPow': 2,
'WhichAPEC': 2,
'PowECFO': 5.32064181809699e-11,
'PowECFU': 5.82457207207057e-11,
'PowFlux': 2.671774278978756e-13,
'PowFlux_pos': 2.020498611809465e-14,
'PowFlux_neg': -2.020498611809465e-14,
'PowUnabsFlux': 2.924824181038767e-13,
'PowUnabsFlux_pos': 2.2118646938372494e-14,
'PowUnabsFlux_neg': -2.2118646938372494e-14,
'APECECFO': 4.9120640774802e-11,
'APECECFU': 5.48357797634314e-11,
'APECFlux': 2.466605892219425e-13,
'APECFlux_pos': 1.8653423757845908e-14,
'APECFlux_neg': -1.8653423757845908e-14,
'APECUnabsFlux': 2.753593099264121e-13,
'APECUnabsFlux_pos': 2.0823731549200668e-14,
'APECUnabsFlux_neg': -2.0823731549200668e-14,
'PowPeakFlux': 1.0681773720429698e-12,
'PowPeakFlux_pos': 2.2888017734580544e-13,
'PowPeakFlux_neg': -2.007733548775263e-13,
'PowPeakUnabsFlux': 1.1693469137609596e-12,
'PowPeakUnabsFlux_pos': 2.5055794665308853e-13,
'PowPeakUnabsFlux_neg': -2.1978906222516854e-13,
'APECPeakFlux': 9.861508962590025e-13,
'APECPeakFlux_pos': 2.1130422524659677e-13,
'APECPeakFlux_neg': -1.8535575555089986e-13,
'APECPeakUnabsFlux': 1.100888598108625e-12,
'APECPeakUnabsFlux_pos': 2.358892672395434e-13,
'APECPeakUnabsFlux_neg': -2.0692171822171313e-13,
'FixedPowECFO': 5.80073e-11,
'FixedPowECFU': 8.71581e-11,
'FixedPowFlux': 2.91285182185852e-13,
'FixedPowFlux_pos': 2.20281073471574e-14,
'FixedPowFlux_neg': -2.20281073471574e-14,
'FixedPowUnabsFlux': 4.37666690872919e-13,
'FixedPowUnabsFlux_pos': 3.30980408151091e-14,
'FixedPowUnabsFlux_neg': -3.30980408151091e-14,
'FixedAPECECFO': 2.31507e-11,
'FixedAPECECFU': 8.66171e-11,
'FixedAPECFlux': 1.16251848771275e-13,
'FixedAPECFlux_pos': 8.79141254224618e-15,
'FixedAPECFlux_neg': -8.79141254224618e-15,
'FixedAPECUnabsFlux': 4.34950045147941e-13,
'FixedAPECUnabsFlux_pos': 3.28925976023615e-14,
'FixedAPECUnabsFlux_neg': -3.28925976023615e-14,
'InterpPowECFO': 5.04534e-11,
'InterpPowECFU': 6.02659e-11,
'InterpPowNH': 2.18329e+21,
'InterpPowNH_pos': 1.14271e+21,
'InterpPowNH_neg': -1.01433e+21,
'InterpPowGamma': 1.56392,
'InterpPowGamma_pos': 0.21484,
'InterpPowGamma_neg': -0.20576,
'InterpPowFlux': 2.53353074714659e-13,
'InterpPowFlux_pos': 1.91595352865772e-14,
'InterpPowFlux_neg': -1.91595352865772e-14,
'InterpPowUnabsFlux': 3.02626801473165e-13,
'InterpPowUnabsFlux_pos': 2.28858042793416e-14,
'InterpPowUnabsFlux_neg': -2.28858042793416e-14,
'InterpAPECECFO': 4.90399e-11,
'InterpAPECECFU': 5.55781e-11,
'InterpAPECNH': 1.64437e+21,
'InterpAPECNH_pos': 9.3774e+20,
'InterpAPECNH_neg': -8.56368e+20,
'InterpAPECkT': 10.4418,
'InterpAPECkT_pos': 18.8625,
'InterpAPECkT_neg': -4.06975,
'InterpAPECFlux': 2.46255147298288e-13,
'InterpAPECFlux_pos': 1.86227626780399e-14,
'InterpAPECFlux_neg': -1.86227626780399e-14,
'InterpAPECUnabsFlux': 2.79086890512806e-13,
'InterpAPECUnabsFlux_pos': 2.11056255497334e-14,
'InterpAPECUnabsFlux_neg': -2.11056255497334e-14,
'P_pow': 1,
'P_APEC': 1,
'FittedPowECFO': 5.32064181809699e-11,
'FittedPowECFU': 5.82457207207057e-11,
'FittedPowNH': 1.5254e+21,
'FittedPowNH_pos': 1.3059715343465046e+21,
'FittedPowNH_neg': -8.419145325835867e+20,
'FittedPowGamma': 1.28437,
'FittedPowGamma_pos': 0.19957148145896655,
'FittedPowGamma_neg': -0.17551513665653493,
'FittedPowFlux': 2.671774278978756e-13,
'FittedPowFlux_pos': 2.020498611809465e-14,
'FittedPowFlux_neg': -2.020498611809465e-14,
'FittedPowUnabsFlux': 2.924824181038767e-13,
'FittedPowUnabsFlux_pos': 2.2118646938372494e-14,
'FittedPowUnabsFlux_neg': -2.2118646938372494e-14,
'FittedPowCstat': 142.1016777,
'FittedPowDOF': 169,
'FittedPowReducedChi2': 0.844379887573964,
'FittedAPECECFO': 4.9120640774802e-11,
'FittedAPECECFU': 5.48357797634314e-11,
'FittedAPECNH': 1.76532e+21,
'FittedAPECNH_pos': 9.22735333130699e+20,
'FittedAPECNH_neg': -7.173157326443769e+20,
'FittedAPECkT': 21.2815,
'FittedAPECkT_pos': -12.937082066869301,
'FittedAPECkT_neg': -7.411332529483283,
'FittedAPECFlux': 2.466605892219425e-13,
'FittedAPECFlux_pos': 1.8653423757845908e-14,
'FittedAPECFlux_neg': -1.8653423757845908e-14,
'FittedAPECUnabsFlux': 2.753593099264121e-13,
'FittedAPECUnabsFlux_pos': 2.0823731549200668e-14,
'FittedAPECUnabsFlux_neg': -2.0823731549200668e-14,
'FittedAPECCstat': 140.8932297,
'FittedAPECDOF': 169,
'FittedAPECReducedChi2': 0.828203044378698,
'HasSpec': 1,
'NearestNeighbour': 30.028733,
'NearestOKNeighbour': 85.223651,
'NearestNeighbour_ID': 366142,
'NearestOKNeighbour_ID': 366118,
'NumExternalMatches': 0,
'NumExternalMatches_slim': 0,
'MatchInROSHRI': 0,
'MatchIn2RXS': 0,
'MatchIn4XMM_DR10': 0,
'MatchIn4XMM_DR10s': 0,
'MatchInXMMSL2': 0,
'MatchInSwiftFT': 0,
'MatchIn1SWXRT': 0,
'MatchInXRTGRB': 0,
'MatchInSDSS_QSO_DR14': 0,
'MatchIn2MASS': 0,
'MatchInUSNOB1': 0,
'MatchIn2CSC': 0,
'MatchIn2SXPS': 0,
'ra_rad': 1.9639947245033362,
'sindec': -0.3357738556513571,
'cosdec': 0.941942629814057,
'HPPIX': 131488,
'ProcessedStatus': 7,
'WhenAdded': '2022-08-14 04:36:37',
'WhenModified': '2022-08-14 05:03:53',
'StillDetected': 1,
'HasExternalMatches': 0,
'lcRanges': {'TDB_lo': 2457984.238930345,
'MJD_lo': 57983.74205611114,
'MET_lo': 524771333.195803,
'TDB_hi': 2459752.3361591264,
'MJD_hi': 59751.83923312228,
'MET_hi': 677534939.2707645,
'rate_lo': 0,
'rate_hi': 0.024377839999999998},
'NearestNeighbour_name': 'LSXPS J073007.8-193737',
'NearestOKNeighbour_name': 'LSXPS J073000.8-193720',
'OK': 1,
'Detections': {'NumStacks': 2,
'NumObservations': 9,
'Stacks': ObsSourceID DatasetID LSXPS_ID OSNum UsedCorrectedPosition \
0 792138 228142 366116 3 1
1 792027 228141 366116 3 1
NearestNeighbour NearestOKNeighbour Exposure HR1 HR1_pos \
0 85.500933 85.500933 54256.347768 0.383896 0.092297
1 30.154481 85.224263 51216.215002 0.408530 0.099186
... IsObsoleteStack BestDetFlag \
0 ... 0 0
1 ... 0 0
Total_Info HasBlindDetection_band0 \
0 {'DetectionID': 1523307, 'DatasetID': 228142, ... 1
1 {'DetectionID': 1523065, 'DatasetID': 228141, ... 1
Soft_Info HasBlindDetection_band1 \
0 {'DetectionID': 1523341, 'DatasetID': 228142, ... 1
1 {'DetectionID': 1523091, 'DatasetID': 228141, ... 1
Medium_Info HasBlindDetection_band2 \
0 {'DetectionID': 1523352, 'DatasetID': 228142, ... 1
1 {'DetectionID': 1523100, 'DatasetID': 228141, ... 1
Hard_Info HasBlindDetection_band3
0 {'DetectionID': 1523361, 'DatasetID': 228142, ... 1
1 {'DetectionID': 1523105, 'DatasetID': 228141, ... 1
[2 rows x 71 columns],
'Observations': ObsSourceID DatasetID LSXPS_ID OSNum UsedCorrectedPosition \
0 749043 220793 366116 1 0
1 749096 220833 366116 1 0
2 749258 220907 366116 1 0
3 749425 220995 366116 1 0
4 749465 221033 366116 2 0
5 749720 221279 366116 3 0
6 749690 221250 366116 3 0
7 750043 221515 366116 4 0
8 750955 221951 366116 1 0
NearestNeighbour NearestOKNeighbour Exposure HR1 HR1_pos ... \
0 1.000000e+80 1.000000e+80 814.007556 0.327592 0.360160 ...
1 3.823000e+02 3.823000e+02 3148.517415 0.337117 0.209317 ...
2 4.277373e+02 4.423895e+02 4838.287365 0.714705 0.285295 ...
3 3.395647e+02 3.395647e+02 3959.676065 0.458438 0.214943 ...
4 3.335399e+02 3.335399e+02 4017.034048 0.470151 0.328438 ...
5 3.455588e+02 3.455588e+02 4988.235127 0.205528 0.386526 ...
6 7.922934e+01 7.922934e+01 2750.272421 0.650255 0.349745 ...
7 3.414023e+02 3.414023e+02 3953.420273 0.113588 0.459811 ...
8 5.492380e+02 5.492380e+02 4298.483700 -0.224153 0.245883 ...
IsObsoleteStack BestDetFlag \
0 0 0
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 0 0
7 0 0
8 0 0
Total_Info HasBlindDetection_band0 \
0 {'DetectionID': 1447508, 'DatasetID': 220793, ... 1
1 {'DetectionID': 1447603, 'DatasetID': 220833, ... 1
2 {'DetectionID': 1447891, 'DatasetID': 220907, ... 1
3 {'DetectionID': 1448199, 'DatasetID': 220995, ... 1
4 {'DetectionID': 1448296, 'DatasetID': 221033, ... 1
5 {'DetectionID': 1448841, 'DatasetID': 221279, ... 1
6 {'DetectionID': 1448773, 'DatasetID': 221250, ... 1
7 {'DetectionID': 1449441, 'DatasetID': 221515, ... 1
8 {'DetectionID': 1451392, 'DatasetID': 221951, ... 1
Soft_Info HasBlindDetection_band1 \
0 {'sourceID': 366116, 'dsID': 220793, 'band': 1... 0
1 {'DetectionID': 1447607, 'DatasetID': 220833, ... 1
2 {'sourceID': 366116, 'dsID': 220907, 'band': 1... 0
3 {'DetectionID': 1448203, 'DatasetID': 220995, ... 1
4 {'sourceID': 366116, 'dsID': 221033, 'band': 1... 0
5 {'sourceID': 366116, 'dsID': 221279, 'band': 1... 0
6 {'sourceID': 366116, 'dsID': 221250, 'band': 1... 0
7 {'sourceID': 366116, 'dsID': 221515, 'band': 1... 0
8 {'sourceID': 366116, 'dsID': 221951, 'band': 1... 0
Medium_Info HasBlindDetection_band2 \
0 {'DetectionID': 1447509, 'DatasetID': 220793, ... 1
1 {'DetectionID': 1447608, 'DatasetID': 220833, ... 1
2 {'DetectionID': 1447899, 'DatasetID': 220907, ... 1
3 {'DetectionID': 1448204, 'DatasetID': 220995, ... 1
4 {'DetectionID': 1448302, 'DatasetID': 221033, ... 1
5 {'DetectionID': 1448845, 'DatasetID': 221279, ... 1
6 {'DetectionID': 1448777, 'DatasetID': 221250, ... 1
7 {'sourceID': 366116, 'dsID': 221515, 'band': 2... 0
8 {'sourceID': 366116, 'dsID': 221951, 'band': 2... 0
Hard_Info HasBlindDetection_band3
0 {'sourceID': 366116, 'dsID': 220793, 'band': 3... 0
1 {'DetectionID': 1447609, 'DatasetID': 220833, ... 1
2 {'DetectionID': 1447901, 'DatasetID': 220907, ... 1
3 {'sourceID': 366116, 'dsID': 220995, 'band': 3... 0
4 {'DetectionID': 1448304, 'DatasetID': 221033, ... 1
5 {'sourceID': 366116, 'dsID': 221279, 'band': 3... 0
6 {'sourceID': 366116, 'dsID': 221250, 'band': 3... 0
7 {'sourceID': 366116, 'dsID': 221515, 'band': 3... 0
8 {'sourceID': 366116, 'dsID': 221951, 'band': 3... 0
[9 rows x 71 columns]},
'NonDetections': {'NumStacks': 1,
'NumObservations': 10,
'Stacks': ObsID DatasetID IsStackedImage \
0 10000019357 212110 1
Total_Info \
0 {'sourceID': 366116, 'dsID': 212110, 'band': 0...
Soft_Info \
0 {'sourceID': 366116, 'dsID': 212110, 'band': 1...
Medium_Info \
0 {'sourceID': 366116, 'dsID': 212110, 'band': 2...
Hard_Info
0 {'sourceID': 366116, 'dsID': 212110, 'band': 3... ,
'Observations': ObsID DatasetID IsStackedImage \
0 86462001 114866 0
1 3102486001 127139 0
2 3102486002 144796 0
3 3102486003 144830 0
4 15190008 221320 0
5 15190009 221435 0
6 15190011 221593 0
7 15190013 222189 0
8 15190014 222465 0
9 15190015 222727 0
Total_Info \
0 {'sourceID': 366116, 'dsID': 114866, 'band': 0...
1 {'sourceID': 366116, 'dsID': 127139, 'band': 0...
2 {'sourceID': 366116, 'dsID': 144796, 'band': 0...
3 {'sourceID': 366116, 'dsID': 144830, 'band': 0...
4 {'sourceID': 366116, 'dsID': 221320, 'band': 0...
5 {'sourceID': 366116, 'dsID': 221435, 'band': 0...
6 {'sourceID': 366116, 'dsID': 221593, 'band': 0...
7 {'sourceID': 366116, 'dsID': 222189, 'band': 0...
8 {'sourceID': 366116, 'dsID': 222465, 'band': 0...
9 {'sourceID': 366116, 'dsID': 222727, 'band': 0...
Soft_Info \
0 {'sourceID': 366116, 'dsID': 114866, 'band': 1...
1 {'sourceID': 366116, 'dsID': 127139, 'band': 1...
2 {'sourceID': 366116, 'dsID': 144796, 'band': 1...
3 {'sourceID': 366116, 'dsID': 144830, 'band': 1...
4 {'sourceID': 366116, 'dsID': 221320, 'band': 1...
5 {'sourceID': 366116, 'dsID': 221435, 'band': 1...
6 {'sourceID': 366116, 'dsID': 221593, 'band': 1...
7 {'sourceID': 366116, 'dsID': 222189, 'band': 1...
8 {'sourceID': 366116, 'dsID': 222465, 'band': 1...
9 {'sourceID': 366116, 'dsID': 222727, 'band': 1...
Medium_Info \
0 {'sourceID': 366116, 'dsID': 114866, 'band': 2...
1 {'sourceID': 366116, 'dsID': 127139, 'band': 2...
2 {'sourceID': 366116, 'dsID': 144796, 'band': 2...
3 {'sourceID': 366116, 'dsID': 144830, 'band': 2...
4 {'sourceID': 366116, 'dsID': 221320, 'band': 2...
5 {'sourceID': 366116, 'dsID': 221435, 'band': 2...
6 {'sourceID': 366116, 'dsID': 221593, 'band': 2...
7 {'sourceID': 366116, 'dsID': 222189, 'band': 2...
8 {'sourceID': 366116, 'dsID': 222465, 'band': 2...
9 {'sourceID': 366116, 'dsID': 222727, 'band': 2...
Hard_Info
0 {'sourceID': 366116, 'dsID': 114866, 'band': 3...
1 {'sourceID': 366116, 'dsID': 127139, 'band': 3...
2 {'sourceID': 366116, 'dsID': 144796, 'band': 3...
3 {'sourceID': 366116, 'dsID': 144830, 'band': 3...
4 {'sourceID': 366116, 'dsID': 221320, 'band': 3...
5 {'sourceID': 366116, 'dsID': 221435, 'band': 3...
6 {'sourceID': 366116, 'dsID': 221593, 'band': 3...
7 {'sourceID': 366116, 'dsID': 222189, 'band': 3...
8 {'sourceID': 366116, 'dsID': 222465, 'band': 3...
9 {'sourceID': 366116, 'dsID': 222727, 'band': 3... },
'CrossMatch': Empty DataFrame
Columns: []
Index: []}
You can see that what we got here was the same as if we'd done getSourceDetails(sourceID=349111).
Transient light curves are obtained and saved as for source light curves; apart from the addition of the transient=True argument (essential to explain we are getting a transient), the only changes relate to the differences between transient light curves and source light curves. Transient light curves are built for rapid analysis, using the on-demand XRT analysis tools. This results in a few differences to how we call getLightCurves():
bands is ignored (only total-band curves are made for transients)timeFormat is ignored; only MJD is available for transients;binning supports an extra option, 'counts', which gives light curves binned to a minimum number of counts per bin.For the first two, you will not get an error if you supply an unsupported band or timeFormat, you'll just get the total-band, MJD data. If silent=False you will at least be warned that your input is being ignored. All the arguments about whether to get limits or bins and grouping them etc are silently ignored, as they are meaningless in the context of transients.
As usual, the files are either written to disk (default), returned as a variable, or both. We will just explore the return option, so that I can show you what the returned object looks like:
lcs = uds.getLightCurves(sourceName=('Swift J073006.8-193709', 'Swift J175737.4-070600'),
transient=True,
cat='LSXPS',
binning='counts',
saveData=False,
returnData=True,
)
lcs.keys()
dict_keys(['Swift J073006.8-193709', 'Swift J175737.4-070600'])
I got two transients, just to remind you that we can, so as you can see, the top-level of the returned dict has an entry per source. Those entries are each a standard light curve dict, so for example we can view the list of light curves:
lcs['Swift J073006.8-193709']['Datasets']
['PC_incbad',
'PCUL_incbad',
'PCHard_incbad',
'PCSoft_incbad',
'PCHR_incbad',
'PC_nosys_incbad',
'PCUL_nosys_incbad',
'PCHard_nosys_incbad',
'PCSoft_nosys_incbad',
'PCHR_nosys_incbad']
This automatically gave us all of the possible datasets from the transient light curves. The dataset name components '_nosys' and '_incbad' indicate that those datasets have had systematic errors removed, or times with poor/no centroid information included. For more details you will need to read up on the product generator.
The other thing to note -- sorry -- is that "hard", "soft" and "HR" here are again as used in the on-demand tool, not the catalogue. So "soft" is 0.3-1.5 keV, "hard" is 1.5-10 keV and the HR is just hard/soft.
If you find this annoying, there is a reason, but it's too boring to write here. Similarly let's check an actual light curve:
lcs['Swift J073006.8-193709']['PC_incbad']
| Time | TimePos | TimeNeg | Rate | RatePos | RateNeg | FracExp | BGrate | BGerr | CorrFact | CtsInSrc | BGInSrc | Exposure | Sigma | SNR | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 59729.403065 | 0.338300 | -0.060323 | 0.015596 | 0.004049 | -0.004049 | 0.050523 | 0.000047 | 0.000013 | 1.819264 | 15.0 | 0.082616 | 1740.06656 | 651.026624 | 3.851585 |
| 1 | 59729.751906 | 0.007480 | -0.010541 | 0.017725 | 0.003920 | -0.003920 | 1.000000 | 0.000505 | 0.000052 | 1.300949 | 22.0 | 0.786480 | 1557.03294 | 260.115585 | 4.522054 |
| 2 | 59729.815188 | 0.009194 | -0.009495 | 0.020317 | 0.004113 | -0.004113 | 1.000000 | 0.000502 | 0.000050 | 1.302390 | 26.0 | 0.810808 | 1614.70120 | 309.110494 | 4.939376 |
| 3 | 59730.684521 | 0.009008 | -0.011016 | 0.015637 | 0.003528 | -0.003528 | 1.000000 | 0.000698 | 0.000058 | 1.301092 | 22.0 | 1.208052 | 1730.03700 | 205.815223 | 4.431830 |
| 4 | 59730.750967 | 0.008581 | -0.011443 | 0.017166 | 0.003872 | -0.003872 | 1.000000 | 0.001955 | 0.000096 | 1.313061 | 26.0 | 3.382433 | 1730.03700 | 136.711412 | 4.433337 |
| 5 | 59730.813288 | 0.004828 | -0.007099 | 0.018343 | 0.004886 | -0.004886 | 1.000000 | 0.000444 | 0.000060 | 1.299888 | 15.0 | 0.457998 | 1030.50672 | 233.322726 | 3.754243 |
| 6 | 59730.820798 | 0.002860 | -0.002682 | 0.031557 | 0.010571 | -0.010571 | 1.000000 | 0.007155 | 0.000356 | 1.305766 | 15.0 | 3.426507 | 478.88788 | 67.889640 | 2.985372 |
| 7 | 59731.466261 | 0.352834 | -0.198170 | 0.008104 | 0.001662 | -0.001662 | 0.090534 | 0.000263 | 0.000018 | 1.404684 | 26.0 | 1.132701 | 4310.04870 | 327.106875 | 4.876337 |
| 8 | 59732.116372 | 0.226323 | -0.114388 | 0.006416 | 0.001580 | -0.001580 | 0.152717 | 0.000171 | 0.000011 | 1.673851 | 18.0 | 0.767120 | 4495.58890 | 336.965892 | 4.061534 |
| 9 | 59733.702422 | 0.501397 | -0.242141 | 0.004126 | 0.001048 | -0.001048 | 0.091992 | 0.000220 | 0.000012 | 1.459888 | 18.0 | 1.298394 | 5909.70610 | 227.937972 | 3.936019 |
| 10 | 59735.743050 | 1.184327 | -1.023557 | 0.002026 | 0.000830 | -0.000830 | 0.038918 | 0.000746 | 0.000018 | 1.589993 | 15.0 | 5.540165 | 7424.11530 | 71.409464 | 2.441091 |
| 11 | 59737.808680 | 0.640959 | -0.105611 | 0.002391 | 0.001095 | -0.000939 | 0.090957 | 0.001482 | 0.000053 | 1.360940 | 19.0 | 8.694409 | 5867.08200 | 3.094026 | 2.546578 |
As you can see, this light curve has a few extra columns compared to the source light curves, but the fundamentals are the same.
Again the spectra are very similar to source spectra, with just two differences:
getSpectra(): specType.The latter exists because two spectra are created for transients, one using only the dataset in which the transient was discovered, and one using also any subsequent observations covering the transient. specType is a string, and should be one of 'discovery' 'full' or 'both'. In the latter case, the returned dict will contain a new top-level per transient, with keys 'Discovery' and 'Full' and the contents being the spectrum dict.
Let's explore this:
specSet = uds.getSpectra(sourceID=(30, 576),
destDir='/tmp/APIDemo_transSpec2',
transient=True,
silent=False,
specType='both',
verbose=True,
returnData=True
)
Getting data for sourceID = `30`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Discovery', 'Full', 'OK', 'APIVersion'])
Getting data for sourceID = `576`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Discovery', 'Full', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_transSpec2
Making directory /tmp/APIDemo_transSpec2/30
Transient True
Source `30` has no `Full` spectrum.
Making directory /tmp/APIDemo_transSpec2/30/Discovery
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_transSpec2/30/Discovery/interval0.tar.gz`
Saving file `/tmp/APIDemo_transSpec2/30/Discovery/interval0.tar.gz`
Downloading file `/tmp/APIDemo_transSpec2/30/Discovery/interval0pc_plot.gif`
Saving file `/tmp/APIDemo_transSpec2/30/Discovery/interval0pc_plot.gif`
Making directory /tmp/APIDemo_transSpec2/576
Transient True
Making directory /tmp/APIDemo_transSpec2/576/Full
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_transSpec2/576/Full/interval0.tar.gz`
Saving file `/tmp/APIDemo_transSpec2/576/Full/interval0.tar.gz`
Downloading file `/tmp/APIDemo_transSpec2/576/Full/interval0pc_plot.gif`
Saving file `/tmp/APIDemo_transSpec2/576/Full/interval0pc_plot.gif`
Making directory /tmp/APIDemo_transSpec2/576/Discovery
Saving `interval0` spectrum
Downloading file `/tmp/APIDemo_transSpec2/576/Discovery/interval0.tar.gz`
Saving file `/tmp/APIDemo_transSpec2/576/Discovery/interval0.tar.gz`
Downloading file `/tmp/APIDemo_transSpec2/576/Discovery/interval0pc_plot.gif`
Saving file `/tmp/APIDemo_transSpec2/576/Discovery/interval0pc_plot.gif`
Note that I set returnData=True and did not set saveData to False, so we saved and returned. You can see from the above the structure of saved files; remember I got multiple transients which is where there is a separate directory for each. Let's just confirm what the returned data look like.
specSet.keys()
dict_keys([30, 576])
OK, that's expected, an entry per transient.
specSet[30].keys()
dict_keys(['Discovery', 'Full'])
As I warned you, specSet[30] is not a spectrum dict as it would have been for sources, but simply a dict indexing the two types of spectra we got. Those two entries, however, are spectrum dicts.
specSet[30]['Discovery'].keys()
dict_keys(['T0', 'DeltaFitStat', 'GalNH_unfitted', 'rnames', 'interval0'])
specSet[30]['Full'].keys()
dict_keys(['NoSpectrum'])
There was no full spectrum for source 30 (probably meaning that there were no observations apart from the discovery one), so we get the null spectral dict instead.
The only other thing to tell you about transient spectra is that, should you decide to separate the download and save steps you have to provide transient=True to saveSpectra as well.
Let's see if you can guess how we get the images of a transient. I will request only the soft band and exposure map, just for fun (look, it's 4pm on a Friday, anything feels like fun now).
uds.saveSourceImages(sourceName='Swift J073006.8-193709',
transient=True,
bands=('soft', 'expmap'),
destDir='/tmp/APIDemo_SXPS_image2',
verbose=True)
Making directory /tmp/APIDemo_SXPS_image2
Getting images for sourceName = `Swift J073006.8-193709`
Uploading data to https://www.swift.ac.uk/API/main.php
Returned keys: dict_keys(['Soft', 'Expmap', 'OK', 'APIVersion'])
Making directory /tmp/APIDemo_SXPS_image2/Swift J073006.8-193709
Downloading file `/tmp/APIDemo_SXPS_image2/Swift J073006.8-193709/Soft.png`
Saving file `/tmp/APIDemo_SXPS_image2/Swift J073006.8-193709/Soft.png`
Downloading file `/tmp/APIDemo_SXPS_image2/Swift J073006.8-193709/Expmap.png`
Saving file `/tmp/APIDemo_SXPS_image2/Swift J073006.8-193709/Expmap.png`
The final thing is to be able to make an XRTProductRequest. I think you can guess how we do this as well:
myReq = uds.makeProductRequest('MY_EMAIL_ADDRESS',
transient=True,
sourceID=576,
T0='Discovery',
useObs='new',
addProds=['LightCurve',]
)
print(myReq)
print(f"Globals: {myReq.getGlobalPars()}\n")
for p in myReq.productList:
print(f"{p}:\t{myReq.getProductPars(p)}")
XRTProductRequest object for user `MY_EMAIL_ADDRESS`, with the following products requested:
* light curve
Globals: {'name': 'Swift J073006.8-193709', 'targ': '15190,44002,1110865,3103197,3103545', 'T0': 675591242.228083, 'RA': 112.5284106332, 'Dec': -19.6192622721, 'centroid': False, 'posErr': 1, 'useSXPS': True, 'getTargs': False, 'getT0': False}
lc: {'whichData': 'user', 'useObs': '00015190001,00015190002,00015190003,00015190005,00015190006,00015190007,00015190008,00015190009,00015190010,00015190011,00015190012,00015190013,00015190014,00015190015,00044002095,01110865000,03103197001,03103545001'}
Where, above, we created an XRTProductRequest with a light curve.
The two (optional) parameters to set the T0 and observation list differ slightly for transients compared to for sources.
T0 can only be 'Discovery' or None (the default): 'Discovery' this will set it to the start time of the observation in which the transient was discovered, None will not set the T0 in the XRTProductRequest.
useObs can be (case insensitive):
Important note in this case 'all' and 'new' will get their observations from the full set of Swift observations, not only those in the LSXPS catalogue (as when calling this function for sources). This is because transients may not yet be in the catalogue, as already discussed above.
Well, you made it! Well done. Hopefully you didn't die of boredom during the above. If you spotted any mistakes, do let me know and I'll try not to curse you under my breath while I fix them.