12
12
13
13
"""
14
14
import re
15
+ from getpass import getpass
15
16
from ...utils .tap .core import TapPlus
16
17
from ...query import BaseQuery
17
18
import shutil
21
22
import os
22
23
23
24
from astropy .io import fits
24
- from . import conf
25
+ from . import conf , config
25
26
from astroquery import log
26
27
from astropy .coordinates import SkyCoord
27
28
from ...exceptions import LoginError
@@ -41,14 +42,13 @@ def __init__(self, tap_handler=None):
41
42
super (XMMNewtonClass , self ).__init__ ()
42
43
43
44
if tap_handler is None :
44
- self ._tap = TapPlus (url = "https://nxsa.esac.esa.int"
45
- "/tap-server/tap" )
45
+ self ._tap = TapPlus (url = "https://nxsa.esac.esa.int/tap-server/tap" )
46
46
else :
47
47
self ._tap = tap_handler
48
48
self ._rmf_ftp = str ("http://sasdev-xmm.esac.esa.int/pub/ccf/constituents/extras/responses/" )
49
49
50
50
def download_data (self , observation_id , * , filename = None , verbose = False ,
51
- cache = True , ** kwargs ):
51
+ cache = True , prop = False , username = None , password = None , ** kwargs ):
52
52
"""
53
53
Download data from XMM-Newton
54
54
@@ -100,42 +100,38 @@ def download_data(self, observation_id, *, filename=None, verbose=False,
100
100
None if not verbose. It downloads the observation indicated
101
101
If verbose returns the filename
102
102
"""
103
- if filename is not None :
104
- filename = os .path .splitext (filename )[0 ]
103
+ """
104
+ Here we change the log level so that it is above 20, this is to stop a log.debug in query.py. this debug
105
+ reveals the url being sent which in turn reveals the users username and password
106
+ """
107
+ previouslevel = log .getEffectiveLevel ()
108
+ log .setLevel (50 )
105
109
106
- link = self .data_aio_url + "obsno=" + observation_id
110
+ # create url to access the aio
111
+ link = self ._create_link (observation_id , ** kwargs )
107
112
108
- link = link + "" .join ("&{0}={1}" .format (key , val )
109
- for key , val in kwargs .items ())
113
+ # If the user wants to access proprietary data, ask them for there credentials
114
+ if prop :
115
+ username , password = self ._get_username_and_password (credentials_file )
116
+ link = f"{ link } &AIOUSER={ username } &AIOPWD={ password } "
110
117
111
118
if verbose :
112
119
log .info (link )
113
120
114
- # we can cache this HEAD request - the _download_file one will check
115
- # the file size and will never cache
116
- response = self ._request ('HEAD' , link , save = False , cache = cache )
117
-
118
- # Get original extension
119
- if 'Content-Type' in response .headers and 'text' not in response .headers ['Content-Type' ]:
120
- _ , params = cgi .parse_header (response .headers ['Content-Disposition' ])
121
- else :
122
- if response .status_code == 401 :
123
- error = "Data protected by proprietary rights. Please check your credentials"
124
- raise LoginError (error )
125
- response .raise_for_status ()
126
-
121
+ # get response of created url
122
+ params = self ._request_link (link , cache )
127
123
r_filename = params ["filename" ]
128
124
suffixes = Path (r_filename ).suffixes
125
+ print (suffixes )
129
126
130
- if filename is None :
131
- filename = observation_id
132
-
133
- filename += "" .join (suffixes )
127
+ # get desired filename
128
+ filename = self ._create_filename (filename , observation_id , suffixes )
134
129
135
130
self ._download_file (link , filename , head_safe = True , cache = cache )
136
131
137
132
if verbose :
138
- log .info ("Wrote {0} to {1}" .format (link , filename ))
133
+ log .info (f"Wrote { link } to { filename } " )
134
+ log .setLevel (previouslevel )
139
135
140
136
def get_postcard (self , observation_id , * , image_type = "OBS_EPIC" ,
141
137
filename = None , verbose = False ):
@@ -186,12 +182,12 @@ def get_postcard(self, observation_id, *, image_type="OBS_EPIC",
186
182
else :
187
183
filename = observation_id + ".png"
188
184
189
- log .info ("Copying file to {0 }..." . format ( filename ) )
185
+ log .info (f "Copying file to { filename } ..." )
190
186
191
187
shutil .move (local_filepath , filename )
192
188
193
189
if verbose :
194
- log .info ("Wrote {0 } to {1}" . format ( link , filename ) )
190
+ log .info (f "Wrote { link } to { filename } " )
195
191
196
192
return filename
197
193
@@ -273,14 +269,53 @@ def get_columns(self, table_name, *, only_names=True, verbose=False):
273
269
break
274
270
275
271
if columns is None :
276
- raise ValueError ("table name specified is not found in "
277
- "XSA TAP service" )
272
+ raise ValueError ("table name specified is not found in XSA TAP service" )
278
273
279
274
if only_names :
280
275
return [c .name for c in columns ]
281
276
else :
282
277
return columns
283
278
279
+ def _create_link (self , observation_id , ** kwargs ):
280
+ link = f"{ self .data_aio_url } obsno={ observation_id } "
281
+ link = link + "" .join ("&{0}={1}" .format (key , val )
282
+ for key , val in kwargs .items ())
283
+ return link
284
+
285
+ def _request_link (self , link , cache ):
286
+ # we can cache this HEAD request - the _download_file one will check
287
+ # the file size and will never cache
288
+ response = self ._request ('HEAD' , link , save = False , cache = cache )
289
+ # Get original extension
290
+ if 'Content-Type' in response .headers and 'text' not in response .headers ['Content-Type' ]:
291
+ _ , params = cgi .parse_header (response .headers ['Content-Disposition' ])
292
+ elif response .status_code == 401 :
293
+ error = "Data protected by proprietary rights. Please check your credentials"
294
+ raise LoginError (error )
295
+ elif 'Content-Type' not in response .headers :
296
+ error = "Incorrect credentials"
297
+ raise LoginError (error )
298
+ response .raise_for_status ()
299
+ return params
300
+
301
+ def _get_username_and_password (self , credentials_file ):
302
+ if credentials_file != None :
303
+ self .configuration .read (credentials_file )
304
+ username = self .configuration .get ('user' , 'username' )
305
+ password = self .configuration .get ('user' , 'password' )
306
+ else :
307
+ username = input ("Username: " )
308
+ password = getpass ("Password: " )
309
+ return username , password
310
+
311
+ def _create_filename (self , filename , observation_id , suffixes ):
312
+ if filename is not None :
313
+ filename = os .path .splitext (filename )[0 ]
314
+ else :
315
+ filename = observation_id
316
+ filename += "" .join (suffixes )
317
+ return filename
318
+
284
319
def _parse_filename (self , filename ):
285
320
"""Parses the file's name of a product
286
321
@@ -572,9 +607,9 @@ def get_epic_metadata(self, *, target_name=None,
572
607
Tables containing the metadata of the target
573
608
"""
574
609
if not target_name and not coordinates :
575
- raise Exception ("Input parameters needed, "
576
- "please provide the name "
577
- "or the coordinates of the target" )
610
+ raise Exception ("Input parameters needed, "
611
+ "please provide the name "
612
+ "or the coordinates of the target" )
578
613
579
614
epic_source = {"table" : "xsa.v_epic_source" ,
580
615
"column" : "epic_source_equatorial_spoint" }
@@ -600,29 +635,29 @@ def get_epic_metadata(self, *, target_name=None,
600
635
query_fmt = ("select {} from {} "
601
636
"where 1=contains({}, circle('ICRS', {}, {}, {}));" )
602
637
epic_source_table = self .query_xsa_tap (query_fmt .format (cols ,
603
- epic_source ["table" ],
604
- epic_source ["column" ],
605
- c .ra .degree ,
606
- c .dec .degree ,
607
- radius ))
638
+ epic_source ["table" ],
639
+ epic_source ["column" ],
640
+ c .ra .degree ,
641
+ c .dec .degree ,
642
+ radius ))
608
643
cat_4xmm_table = self .query_xsa_tap (query_fmt .format (cols ,
609
- cat_4xmm ["table" ],
610
- cat_4xmm ["column" ],
611
- c .ra .degree ,
612
- c .dec .degree ,
613
- radius ))
644
+ cat_4xmm ["table" ],
645
+ cat_4xmm ["column" ],
646
+ c .ra .degree ,
647
+ c .dec .degree ,
648
+ radius ))
614
649
stack_4xmm_table = self .query_xsa_tap (query_fmt .format (cols ,
615
- stack_4xmm ["table" ],
616
- stack_4xmm ["column" ],
617
- c .ra .degree ,
618
- c .dec .degree ,
619
- radius ))
650
+ stack_4xmm ["table" ],
651
+ stack_4xmm ["column" ],
652
+ c .ra .degree ,
653
+ c .dec .degree ,
654
+ radius ))
620
655
slew_source_table = self .query_xsa_tap (query_fmt .format (cols ,
621
- slew_source ["table" ],
622
- slew_source ["column" ],
623
- c .ra .degree ,
624
- c .dec .degree ,
625
- radius ))
656
+ slew_source ["table" ],
657
+ slew_source ["column" ],
658
+ c .ra .degree ,
659
+ c .dec .degree ,
660
+ radius ))
626
661
return epic_source_table , cat_4xmm_table , stack_4xmm_table , slew_source_table
627
662
628
663
def get_epic_lightcurve (self , filename , source_number , * ,
0 commit comments