How do we acquire?Ā¶
Aligning the telescope slit to the correct position and rotation can be tricky. How can we be sure we have the right star? If we want multiple stars in the slit, how do we figure out the exact coordinates and rotation so they'll fit?
Use Simbad for basic data + finders.Ā¶
To search for a star and find its basic properties and a finder chart from previous imaging, try to the Simbad Identifier Query. Enter a star's name (from many different catalogs), and it will pull up its basic data along with some archival imaging of the field. It's a handy way to answer many basic questions you might have on the fly.
Use Gaia for up-to-date star finder charts.Ā¶
For some observations, we might want to align two stars along the same slit, such as a target star and a comparison star. Thanks to Gaia, we generally have the data we need to figure this out. The interactive finder chart below is designed particularly to help line up two stars on a KOSMOS spectrograh slit.
from kosmoscraftroom.finder import *
Status messages could not be retrieved
We can create Finder
object that will search for and download Gaia stars near a target. Nearby stars might have proper motions large enough that they will have moved from where Gaia measured them in 2016; this finder tries to propagate those motions to the time of your observation.
f = Finder("GJ1214")
/Users/zach/Dropbox/zach/code/thefriendlystars/thefriendlystars/gaia.py:373: SyntaxWarning: invalid escape sequence '\l' save_address = save_address + "\lightcurve_data"
--------------------------------------------------------------------------- gaierror Traceback (most recent call last) Cell In[2], line 1 ----> 1 f = Finder("GJ1214") File ~/Dropbox/zach/code/kosmos-craftroom/kosmoscraftroom/finder.py:35, in Finder.__init__(self, name, epoch, **kwargs) 34 def __init__(self, name, epoch="now", **kwargs): ---> 35 self.stars_at_gaia_epoch = get_gaia(name, **kwargs) 36 self.stars = propagate_proper_motions(self.stars_at_gaia_epoch, epoch=epoch) File ~/Dropbox/zach/code/thefriendlystars/thefriendlystars/gaia.py:129, in get_gaia(center, radius) 126 raise ValueError('Sorry! `center` must be a string or SkyCoord.') 128 # get the data from the archive --> 129 job = Gaia.cone_search_async( 130 center_skycoord, 131 radius=radius, 132 columns=[ 133 "source_id", 134 "ra", 135 "dec", 136 "phot_g_mean_mag", 137 "phot_rp_mean_mag", 138 "phot_bp_mean_mag", 139 "parallax", "parallax_error", 140 "pmra", "pmra_error", 141 "pmdec", "pmdec_error" 142 ], 143 ) 144 results = job.get_results() 146 # tidy up the table and convert to quantities File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/gaia/core.py:790, in GaiaClass.cone_search_async(self, coordinate, radius, table_name, ra_column_name, dec_column_name, background, output_file, output_format, verbose, dump_to_file, columns) 748 def cone_search_async(self, coordinate, *, radius=None, 749 table_name=None, 750 ra_column_name=MAIN_GAIA_TABLE_RA, (...) 753 output_file=None, output_format="votable_gzip", 754 verbose=False, dump_to_file=False, columns=()): 755 """Cone search sorted by distance (async) 756 TAP & TAP+ 757 (...) 788 A Job object 789 """ --> 790 return self.__cone_search(coordinate, 791 radius=radius, 792 table_name=table_name, 793 ra_column_name=ra_column_name, 794 dec_column_name=dec_column_name, 795 async_job=True, 796 background=background, 797 output_file=output_file, 798 output_format=output_format, 799 verbose=verbose, 800 dump_to_file=dump_to_file, columns=columns) File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/gaia/core.py:684, in GaiaClass.__cone_search(self, coordinate, radius, table_name, ra_column_name, dec_column_name, async_job, background, output_file, output_format, verbose, dump_to_file, columns) 660 query = """ 661 SELECT 662 {row_limit} (...) 680 'radius': radiusDeg, 681 'table_name': table_name or self.MAIN_GAIA_TABLE or conf.MAIN_GAIA_TABLE}) 683 if async_job: --> 684 return self.launch_job_async(query=query, 685 output_file=output_file, 686 output_format=output_format, 687 verbose=verbose, 688 dump_to_file=dump_to_file, 689 background=background) 690 else: 691 return self.launch_job(query=query, 692 output_file=output_file, 693 output_format=output_format, 694 verbose=verbose, 695 dump_to_file=dump_to_file) File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/gaia/core.py:1021, in GaiaClass.launch_job_async(self, query, name, output_file, output_format, verbose, dump_to_file, background, upload_resource, upload_table_name, autorun) 980 def launch_job_async(self, query, *, name=None, output_file=None, 981 output_format="votable_gzip", verbose=False, 982 dump_to_file=False, background=False, 983 upload_resource=None, upload_table_name=None, 984 autorun=True): 985 """Launches an asynchronous job 986 987 Parameters (...) 1019 A Job object 1020 """ -> 1021 return TapPlus.launch_job_async(self, query=query, 1022 name=name, 1023 output_file=output_file, 1024 output_format=output_format, 1025 verbose=verbose, 1026 dump_to_file=dump_to_file, 1027 background=background, 1028 upload_resource=upload_resource, 1029 upload_table_name=upload_table_name, 1030 autorun=autorun, 1031 format_with_results_compressed=('votable_gzip', 'fits', 'ecsv')) File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/utils/tap/core.py:429, in Tap.launch_job_async(self, query, name, output_file, output_format, verbose, dump_to_file, background, upload_resource, upload_table_name, autorun, maxrec, format_with_results_compressed) 419 response = self.__launchJobMultipart(query, 420 upload_resource, 421 upload_table_name, (...) 426 autorun=autorun, 427 maxrec=maxrec) 428 else: --> 429 response = self.__launchJob(query, 430 output_format, 431 "async", 432 verbose, 433 name=name, 434 autorun=autorun, 435 maxrec=maxrec) 436 isError = self.__connHandler.check_launch_response_status(response, 437 verbose, 438 303, 439 raise_exception=False) 440 job = Job(async_job=True, query=query, connhandler=self.__connHandler) File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/utils/tap/core.py:649, in Tap.__launchJob(self, query, outputFormat, context, verbose, name, autorun, maxrec) 647 if name is not None: 648 args['jobname'] = name --> 649 response = self.__connHandler.execute_tappost(subcontext=context, 650 data=urlencode(args), 651 verbose=verbose) 652 if verbose: 653 print(response.status, response.reason) File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/utils/tap/conn/tapconn.py:269, in TapConn.execute_tappost(self, subcontext, data, content_type, verbose) 248 """Executes a POST request 249 The connection is done through HTTP or HTTPS depending on the login 250 status (logged in -> HTTPS) (...) 266 An HTTP(s) response object 267 """ 268 context = self.__get_tap_context(subcontext) --> 269 return self.__execute_post(context, data, content_type, verbose=verbose) File ~/opt/anaconda3/envs/2024/lib/python3.12/site-packages/astroquery/utils/tap/conn/tapconn.py:422, in TapConn.__execute_post(self, context, data, content_type, verbose) 420 print(f"Content-type = {content_type}") 421 self.__postHeaders["Content-type"] = content_type --> 422 conn.request("POST", context, data, self.__postHeaders) 423 response = conn.getresponse() 424 self.__currentReason = response.reason File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1336, in HTTPConnection.request(self, method, url, body, headers, encode_chunked) 1333 def request(self, method, url, body=None, headers={}, *, 1334 encode_chunked=False): 1335 """Send a complete request to the server.""" -> 1336 self._send_request(method, url, body, headers, encode_chunked) File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1382, in HTTPConnection._send_request(self, method, url, body, headers, encode_chunked) 1378 if isinstance(body, str): 1379 # RFC 2616 Section 3.7.1 says that text default has a 1380 # default charset of iso-8859-1. 1381 body = _encode(body, 'body') -> 1382 self.endheaders(body, encode_chunked=encode_chunked) File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1331, in HTTPConnection.endheaders(self, message_body, encode_chunked) 1329 else: 1330 raise CannotSendHeader() -> 1331 self._send_output(message_body, encode_chunked=encode_chunked) File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1091, in HTTPConnection._send_output(self, message_body, encode_chunked) 1089 msg = b"\r\n".join(self._buffer) 1090 del self._buffer[:] -> 1091 self.send(msg) 1093 if message_body is not None: 1094 1095 # create a consistent interface to message_body 1096 if hasattr(message_body, 'read'): 1097 # Let file-like take precedence over byte-like. This 1098 # is needed to allow the current position of mmap'ed 1099 # files to be taken into account. File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1035, in HTTPConnection.send(self, data) 1033 if self.sock is None: 1034 if self.auto_open: -> 1035 self.connect() 1036 else: 1037 raise NotConnected() File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1470, in HTTPSConnection.connect(self) 1467 def connect(self): 1468 "Connect to a host on a given (SSL) port." -> 1470 super().connect() 1472 if self._tunnel_host: 1473 server_hostname = self._tunnel_host File ~/opt/anaconda3/envs/2024/lib/python3.12/http/client.py:1001, in HTTPConnection.connect(self) 999 """Connect to the host and port specified in __init__.""" 1000 sys.audit("http.client.connect", self, self.host, self.port) -> 1001 self.sock = self._create_connection( 1002 (self.host,self.port), self.timeout, self.source_address) 1003 # Might fail in OSs that don't implement TCP_NODELAY 1004 try: File ~/opt/anaconda3/envs/2024/lib/python3.12/socket.py:828, in create_connection(address, timeout, source_address, all_errors) 826 host, port = address 827 exceptions = [] --> 828 for res in getaddrinfo(host, port, 0, SOCK_STREAM): 829 af, socktype, proto, canonname, sa = res 830 sock = None File ~/opt/anaconda3/envs/2024/lib/python3.12/socket.py:963, in getaddrinfo(host, port, family, type, proto, flags) 960 # We override this function since we want to translate the numeric family 961 # and socket type values to enum constants. 962 addrlist = [] --> 963 for res in _socket.getaddrinfo(host, port, family, type, proto, flags): 964 af, socktype, proto, canonname, sa = res 965 addrlist.append((_intenum_converter(af, AddressFamily), 966 _intenum_converter(socktype, SocketKind), 967 proto, canonname, sa)) gaierror: [Errno 8] nodename nor servname provided, or not known
To interactively explore the stars in this field, run .interact
. It will bring up a plot of all the stars in the field. If you click to select two stars, it will give tell you the center and rotation needed in order to align those stars in the KOSMOS slit. (Sometimes the interactivity is a little flaky; we'll work on it!)
%matplotlib widget
f.interact()
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[3], line 2 1 get_ipython().run_line_magic('matplotlib', 'widget') ----> 2 f.interact() NameError: name 'f' is not defined
(Some work to-do):
- Draw the slit (width + length).
- Identify which stars are in the slit, print their info.
- Try to show TESS light curves of stars in the slit.
- Calculate the total flux (= photon noise) of comparison stars along the slit.
- Explore interaction on different platforms. Seems best in
jupyter notebook
, only halfway works in VSCode.