{ "cells": [ { "metadata": {}, "cell_type": "markdown", "source": "# Measure the Milky Way with Stars \n## RR Lyrae Stars as Standard Candles" }, { "metadata": {}, "cell_type": "markdown", "source": "How can we measure astronomical distances? One technique is to use \"standard candles\", which are astronomical objects that have well-known brightnesses. By measuring how bright an object appears to us and knowing the actual brightness from some analysis, we can work out how far the object is from us. We employ the \"inverse square law\" for light to make this happen and do a bit of math.\n\n Look for the variable stars. They seem to blink.

\n\n## Need more on how we use variable stars to measure distance?\nIf you are new to the idea of variable stars as tools for measuring distances, start with these:\n* [OpenStax Astronomy: Variable Stars - One Key to Cosmic Distances](https://cnx.org/contents/LnN76Opl@21.8:vdWWIntw@8/19-3-Variable-Stars-One-Key-to-Cosmic-Distances). \n* [Measuring the the Milky Way with RR Lyrae Stars, a presentation by J Newland](https://docs.google.com/presentation/d/18IaOORqe0qh4A5u7A5SULAgiyDVl1sOz0sP0g7rmOns/edit?usp=sharing) " }, { "metadata": {}, "cell_type": "markdown", "source": "## Inverse Square Law\nWhen light leaves the surface of an astronomical object, like a star's photosphere, the resulting light spreads out radially in all directions at the speed of light. All the energy emitted at that same instant can be thought of as being spread out over surface of a sphere. As this imaginary sphere gets bigger, the light gets more spread out. This is why distance matters when looking at a light source. Note the equation for the surface area of a sphere:\n\\begin{equation*}\nA=4\\pi{R^2}\n\\end{equation*}\nThe closer you are, the more concentrated the light is because the sphere over which it is spread is smaller (smaller radius, R). The farther you get from the source, the bigger the sphere must be when it reaches you (larger radius, R) and consequently, the light is spread out more and so the source seems dimmer.\n Illustration of inverse square law.

\n\nThe physical properties of electromagnetic radiation eminating from a star or other astronomical object is best described using flux which is related to power which is related to energy. Another common way to describe light leaving an astronomical object is through the concept of luminosity. The Stefan-Boltzman relation connections the energy density of a star (how much energy leaves 1 square meter of the star's surfce) and the star's temperature.\n\n\\begin{equation*}\nL=\\sigma{T^4}\\>[\\mathbf{W/m^2}]\n\\end{equation*}\n\nWe can find the power emitted by the star if we include the entire spherical surface of the star\n\n\\begin{equation*}\nL=\\sigma{T^4}(4\\pi{R^2})\\>[\\mathbf{W}]\n\\end{equation*}\n\nDon't forget that astronomers can determine the surface temperature of a star using Wien's law. Once the peak wavelength of the light from the star is found, we can get the temperature using the relation:\n\n\\begin{equation*}\n\\lambda_{peak}\\cdot{T}=constant\\>[\\mathbf{m\\cdot{K}}]\n\\end{equation*}\n\n## Magnitude vs Luminosity\nFor historical and convenience reasons, astronomers use a system called magnitude dating back to Hipparcos which uses the star Vega as a reference star. There are many peculiarlities with magnitude. For example a negative magnitude represents a brighter object than does a positive magnitude. Another useful point is that just using light from an image, astronomers can quickly measure the magnitude as seen from earth, the apparent magnitude. That leaves some work to do to get turn the physical brightness or luminosity of the object into the absolute magnitude. The magnitude scale is clunky but still in use - for now." }, { "metadata": {}, "cell_type": "markdown", "source": "## Globular Clusters\nA globular cluster is a very old grouping of stars usually found in the halo or the central region of a galaxy. NGC 3201 is one such globular cluster found in the Milky Way Galaxy. The images used for this activity were taken using the [Skynet Robitic Telescope Network](https://skynet.unc.edu/) run by the University of North Carolina. Yes... they called a robotic telescope system Skynet. The globular cluster was imaged 5 times in a single night by the system. This way, any star that has a periodic change of a day or so will show up in the series of images.\n\n

\n \nGlobular Cluster NGC 3201

\n\nFor this activity, we are going to study images taken of a variable star in a globular cluster over a single night. This star is known as an RR Lyrae variable star which varies over a period of less than one day. All stars that fall into this class have approximately the same absolute luminosity. That means if all RR Lyrae stars were the same distance from the observer, they would all appear the same brightness.\n\nBut stars are, of course, spread out across a galaxy and ours is no exception. So RR Lyrae stars appear to be different brightnesses due to their distances. " }, { "metadata": {}, "cell_type": "markdown", "source": "## Choosing a target\nWe will study [one such star](http://simbad.u-strasbg.fr/simbad/sim-id?Ident=Cl*+NGC+3201+++++LS+++++358&NbIdent=1) in a globular cluster visible from Earth's southern hemisphere.\n\nIn order to determine the magnitude of the star, we will need a [known calibration star](http://simbad.u-strasbg.fr/simbad/sim-id?Ident=Cl*+NGC+3201+++CWFD++3-106&NbIdent=1) that is in the field and near the target star. Note that here we have zoomed in a lot on our target star. At this level in this image the only things visible are stars (no galaxies or such) and almost every star visible is a part of the globular cluster.\n" }, { "metadata": {}, "cell_type": "markdown", "source": "Using the [Aladin Sky Atlas](https://aladin.u-strasbg.fr/), we can overlay data from previous surveys onto the image we took. Note the cirlcles and labels. Some objects have known proper motion values and some are known to be variable stars.\n\n

\n \nImage loaded into Aladin Sky Atlas with with Simbad source data overlaid.

\n\nNote the types of objects seen:\n* inCl* - source is a star and part of the cluster.\n* BlueStraggler - source is likely result of smaller, redder [stars merging](http://astronomy.swin.edu.au/cosmos/b/blue+stragglers)\n* RGB* - source is a star that has left the main sequence and moved to the [red giant branch](http://astronomy.swin.edu.au/cosmos/H/Horizontal+Branch+stars) of the HR diagram\n* RRLyr - source is a variable star similar to [RR Lyrae](http://astronomy.swin.edu.au/cosmos/R/RR+Lyrae) with a period less than one day and a known absolute magnitude\n* Star - source is a star and not necessarily a member of the cluster\n* X - source is an X-ray emitter such as a pulsar (neutron star), or black hole.\n\n\n

\n \nList of targets visible in the field above.

" }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# If you are using Microsoft Azure Notebook, uncomment the line below by removing the #\n# We need this line to include the non-standard SEP aperture photometry package.\n!pip install --no-deps sep", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# Let's import the packages and libraries to help us do our analysis.\n# The NumPy package is extremely useful and very common in scientific Python coding.\nimport numpy as np\n# The SEP package is rather specific to our task of performing aperture photometry\nimport sep\n# We import the math package to make our calculations easier to code.\nimport math", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# additional setup for reading the test image and displaying plots\nfrom astropy.utils.data import download_file\nfrom astropy.io import fits\n\n# The MatplotLib package is extremely useful and very common for making plots and displaying images.\nimport matplotlib.pyplot as plt\nfrom matplotlib import rcParams\n\n# Let's make Jupyter and Matplotlib work together\n%matplotlib inline\n\n# This determines the size of the images we display. \nrcParams['figure.figsize'] = [8., 8.]", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# The known apparent magnitude of calibration star Cl* NGC 3201 CWFD 3-106 \n# in the visual or green band according to the Simbad database.\n# http://simbad.u-strasbg.fr/simbad/sim-id?Ident=Cl*+NGC+3201+CWFD+3-106\nm_calibration = 14.81\n\n# The known absolute magnitude of target star Cl* NGC 3201 LS 358\n# https://iopscience.iop.org/article/10.1086/344948\nM_target = 0.58", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# Convenience function for mirroring a image about X and Y\n# One of the FITS images was flipped horizontally and vertically and this function helps us fix that.\ndef mirror_data(data):\n dataout = np.array(data)\n rows = len(data)\n cols = len(data)\n for r in range(rows):\n for c in range(cols):\n dataout[rows-1-r][cols-1-c] = data[r][c]\n return dataout", "execution_count": null, "outputs": [] }, { "metadata": {}, "cell_type": "markdown", "source": "## Distance Modulus\nIf the apparent magnitude and the absolute magnitude of a source are known, once can determine the distance to the source in parsecs using the [distance modulus](https://astro.unl.edu/naap/distance/distance_modulus.html) relation. Small m is the apparent magnitude of the source. Big M is the absolute magnitude of the source. The distance is then d. Note the base of the logarithm is 10 in this case. The distance modulus is logarithmic in nature but it is also based on historical uses of magnitudes. Hence a distance modulus of 5 corresponds to a distance of 100 pc. The absolute magnitude scale is based on objects all being located 100 pc away from the viewer. Another example: a magnitude 1 star is exactly 100 times brighter than a magnitude 6 star.\n\\begin{equation*}\nm - M = -5 + 5\\cdot log_{10}(d)\n\\end{equation*}" }, { "metadata": {}, "cell_type": "markdown", "source": "# Coding and Questions\n### If you need to install Python and Jupyter notebook, the best bet is to [install Anaconda](https://www.anaconda.com/distribution/).\n* Follow the directions and answer the questions listed in the comments of a given block of code.\n* Don't be afraid to experiment! This is an interactive lesson using coding. There is always the undo button!\n* The code used here is Python 3 which is common for scientific computing. This isn't the only language used in science by any means. It just works well for our purposes here.\n* Answer questions directly in the code block using comments. That will be part of your finished product!\n* The # means just that line is a comment\n* The \"\"\" ... \"\"\" means everthing between the triple quotes is a comment and can span multiple lines.\n* Include your name, the date, and class or period information. Be sure not to leave out any group members!" }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# Example of a single line comment\n\"\"\" \n Example of multi-line comment\n\"\"\"", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\" \n Function to find the distance of an astronomical object in parsecs \n if given the apparent, m, and absolute, M, magnitudes of the object.\n\n Use some algebra and re-arrange the distance modulus equation to return \n the distance in parsecs of the object\n Don't forget how exponents work: x^2 (x squared) would be written as x**2\n\"\"\"\ndef distance_modulus(m,M):\n return ...", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n Testing the distance modulus: should be approximately 1.0 for the Sun\n m = -26.76 and M =4.81\n There are 648000 arcseconds in 180 degrees of arc. Why do we need that conversion here?\n Is your result close enough to be useful? How can you tell?\n Compare your result with another student.\n\"\"\"\nprint(distance_modulus(-26.76,4.81)*648000/math.pi)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\" \n Function to find the apparent magnitude of an object if given the\n flux (or counts) found via aperture photometry.\n http://classic.sdss.org/dr7/algorithms/fluxcal.html\n This function depends on the filters used and the mininum about of \n flux the filter allows. Likely you shouldn't change anything here.\n\"\"\"\ndef app_mag(flux):\n return -2.5*math.log10(flux/(25.11*10**8))", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\" \n Testing the apparent magnitude function: \n should be 14.81 for our calibration star according to literature.\n https://iopscience.iop.org/article/10.1086/344948\n\"\"\"\nprint(app_mag(2967.8))", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n This functions consumes as input the filename as a string and a \"flag\"\n for whether or not this image should be mirrored. To mirror an image \n is to flip the image in both the horizontal and vertical direction.\n \n The data is returned as a 2-D NumPy array. This array represents the\n light received by each pixel in the camera.\n\n\"\"\"\ndef get_image_data(filename, mirror=False):\n # process filename as FITS file\n file = filename\n image_file = download_file(file, cache=True )\n\n data = fits.getdata(image_file)\n \n if mirror==True:\n data = mirror_data(data)\n \n # We need this line to allow the SEP package to work with our \n # AstroPy formatted FITS file\n # See: https://sep.readthedocs.io/en/v1.0.x/tutorial.html#Finally-a-brief-word-on-byte-order\n data = data.byteswap().newbyteorder()\n \n return data", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n This functions consumes as input a 2D NumPy array from a FITS image.\n The data returned is the data with the background subtracted and also\n background data to use in other functions.\n \n Removing the background improves the signal to noise ratio so our sources\n can be extracted more easily.\n\"\"\"\ndef subtract_background(data):\n # measure a spatially varying background on the image\n bkg = sep.Background(data)\n \n # evaluate background as 2-d array, same size as original image\n bkg_image = bkg.back()\n # bkg_image = np.array(bkg) # equivalent to above\n \n # evaluate the background noise as 2-d array, same size as original image\n bkg_rms = bkg.rms()\n data_sub = data - bkg\n \n return data_sub, bkg", "execution_count": null, "outputs": [] }, { "metadata": {}, "cell_type": "markdown", "source": "## Why subtract the background?\nIf we have an astronomical image, the things we care about, like stars, might be hidden in the excess light and noise of our image. By using the SEP package to find and remove the background, we improve the signal to noice ratio. We want more signal and less noise. Finding ways to improve the S/N is a very common practice is scientific analysis. The 1st image has the background, the 2nd shows the background and the 3rd image is missing the background." }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "data = get_image_data('http://jimmynewland.com/astronomy/ngc-3201/ngc3201_1.fits')\ndata_sub, bkg = subtract_background(data)\nbkg_image = bkg.back()", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "m1, s1 = np.mean(data), np.std(data)\nplt.imshow(data, interpolation='nearest', cmap='gray',vmin=m1-s1, vmax=m1+s1, origin='lower')", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# show the background\nplt.imshow(bkg_image, interpolation='nearest', cmap='gray', origin='lower')", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "m2, s2 = np.mean(data_sub), np.std(data_sub)\nplt.imshow(data_sub, interpolation='nearest', cmap='gray',vmin=m2-s2, vmax=m2+s2, origin='lower')", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n This function consumes the subtracted data, the background, and \n the x and y coordinates for the subsection of the image containing the target star.\n There are 2 XY pairs for the \"bounding box\" we want within the original image.\n We then plot ellipses around each detected source and finally return the list\n of sources extracted.\n\"\"\"\ndef extract_sources(data_sub, bkg, x1, y1, x2, y2):\n # perform the extraction\n objects = sep.extract(data_sub, 1.5, err=bkg.globalrms)\n \n # display the image\n from matplotlib.patches import Ellipse\n\n # plot background-subtracted image\n fig, ax = plt.subplots()\n m, s = np.mean(data_sub), np.std(data_sub)\n im = ax.imshow(data_sub, interpolation='nearest', cmap='gray',\n vmin=m-s, vmax=m+s, origin='lower')\n plt.xlim(x1,x2)\n plt.ylim(y1,y2)\n\n # plot an ellipse for each object\n for i in range(len(objects)):\n e = Ellipse(xy=(objects['x'][i], objects['y'][i]),\n width=6*objects['a'][i],\n height=6*objects['b'][i],\n angle=objects['theta'][i] * 180. / np.pi)\n e.set_facecolor('none')\n e.set_edgecolor('red')\n ax.add_artist(e)\n plt.show()\n \n return objects", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n This function helps us chose the center of the given region\n so we can find the target closest to the center.\n \n We consume the 2 XY pairs and return the ordered pair for the \n center of the image as a tuple.\n\"\"\"\ndef select_target(x1, y1, x2, y2):\n # select our target star by x and y position in the image\n cen_x = x1 + (x2-x1)/2\n cen_y = y1 + (y2-y1)/2\n \n return cen_x, cen_y", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n This function consumes our list of extracted targets along with \n the data after subtraction, the background, and the center x and\n center y values.\n \n We then go through the list and find the flux for the target closest\n to the center (within 5).\n \n The flux for the target star is then returned.\n\"\"\"\ndef get_target_flux(objects, data_sub, bkg, cen_x, cen_y):\n target_flux = 0\n \n for i in range(len(objects)):\n curr_x = objects[i]['x']\n curr_y = objects[i]['y']\n \n # Get the flux for target star (center)\n if curr_x > cen_x-5 and curr_x < cen_x+5 and curr_y > cen_y-5 and curr_y < cen_y+5:\n # find the flux of object nearest the center\n flux, fluxerr, flag = sep.sum_circle(data_sub, objects[i]['x'], objects[i]['y'],\n 3.0, err=bkg.globalrms, gain=1.0)\n target_flux = round(int(flux))\n return target_flux", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\" \n This function consumes our list of extracted targets along with \n the data after subtraction, the background, and the center x and\n center y values.\n \n We then go through the list and find the flux for the calibration star.\n Note: this will work ONLY for these images. Changing the calibration star\n would require a tedious by-hand analysis to locate the new position.\n \n The flux for the calibration star is returned.\n\"\"\"\ndef get_calib_flux(objects, data_sub, bkg, cen_x, cen_y):\n for i in range(len(objects)):\n curr_x = objects[i]['x']\n curr_y = objects[i]['y']\n \n # Get flux of calibration star (below)\n if curr_x > cen_x-5 and curr_x < cen_x+5 and curr_y > cen_y-81-15 and curr_y < cen_y-81+15:\n # find the flux of object nearest the center\n flux, fluxerr, flag = sep.sum_circle(data_sub, objects[i]['x'], objects[i]['y'],\n 3.0, err=bkg.globalrms, gain=1.0)\n calibration_flux = round(int(flux))\n return calibration_flux", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n This functions consumes:\n a filename which can be local or a URL for a FITS file, \n the starting and ending points marking the bounding box for the image, \n and whether or not the image needs to be flipped (both vertical and horizontal)\n This function returns:\n the apparent magnitude of the target star\n The process image function is where we bring the steps together.\n 1) Get the image data using the filename and mirror flag.\n 2) Get the subtracted data and background using the data from step 1\n 3) Extract a list of sources using the subtracted data, the background\n and the given x and y pairs (2 x values and 2 y values).\n 4) Set the target as the center of the image.\n 5) Get the flux for our target star.\n 6) Get the flux for out calibration star.\n 7) Determine the apparent magnitude of the calibration star.\n 8) Calibrate the apparent magnitude of the target star.\n 9) Print and return our target star magnitude.\n\"\"\"\ndef process_image(filename, x1=0, y1=0, x2=2048, y2=2048, mirror=False):\n # Get image data\n data = ...\n \n # Measure and subtract background\n data_sub, bkg = ...\n \n # Extract sources\n objects = ...\n \n # Select target (center)\n cen_x, cen_y = ...\n \n # Find target star flux\n target_flux = ...\n \n # Find the calibration star flux\n calibration_flux = ...\n \n # Convert the flux into an apparent magnitude\n m_cal_ap = ...\n \n # Calibrate the magnitudes for the target and calibration star\n f_cal = m_cal_ap/m_calibration # Calibration factor\n m_cal = m_cal_ap/f_cal\n \n # Convert the flux into an apparent magnitude\n m_tar_ap = ...\n \n # Calibrate the magnitude of the target\n m_tar = m_tar_ap/f_cal\n \n print(\"App. mag of target star m = : \"+str(m_tar))\n print(\"App. mag of calib. star m = : \"+str(m_cal))\n \n # Return the magnitude for the distance calculation\n return m_tar", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# Empty list meant to hold calculated magnitudes for target star returned from process_image function\ntarget_mags = []", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n Run process_image using the following parameters:\n filename='http://jimmynewland.com/astronomy/ngc-3201/ngc3201_1.fits'\n x1=860\n x2=1060\n y1=668\n y2=868\n\"\"\"\nm_out = process_image(..., ..., ..., ..., ...)\ntarget_mags.append(m_out)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n Run process_image using the following parameters:\n filename='http://jimmynewland.com/astronomy/ngc-3201/ngc3201_2.fits'\n x1=869\n x2=1069\n y1=673\n y2=873\n\"\"\"\nm_out = process_image(..., ..., ..., ..., ...)\ntarget_mags.append(m_out)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n Run process_image using the following parameters:\n filename='http://jimmynewland.com/astronomy/ngc-3201/ngc3201_3.fits'\n x1=205\n x2=435\n y1=190\n y2=420\n\"\"\"\nm_out = process_image(..., ..., ..., ..., ...)\ntarget_mags.append(m_out)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\n Run process_image using the following parameters:\n filename='http://jimmynewland.com/astronomy/ngc-3201/ngc3201_4.fits'\n x1=262\n x2=462\n y1=195\n y2=395\n\"\"\"\nm_out = process_image(..., ..., ..., ..., ...)\ntarget_mags.append(m_out)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "\"\"\"\nNOTE: This image was taken by a different telescope in the network \nand subsequently was slightly different than the other 4 images.\nBe sure to set mirror to True for this star.\n Run process_image using the following parameters:\n filename='http://jimmynewland.com/astronomy/ngc-3201/ngc3201_5.fits'\n x1=641\n x2=841\n y1=709\n y2=909\n mirror=True\n\"\"\"\nm_out = process_image(..., ..., ..., ..., ..., ...)\ntarget_mags.append(m_out)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# Print out the list of determined magnitudes for target star from the 5 images.\n# Note the more negative a magnitude is, the brighter.\n# Did the star vary in brightness over the 5 images as we expect for an RR Lyrae?\n# Do the magnitudes make sense? Are any way brighter or dimmer than the others?\nprint(target_mags)\n# Students see\n# print(...)", "execution_count": null, "outputs": [] }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# You should select the brightest magnitude to use in the distance modulus calculation\n\n# The command np.min(list) will return the smallest value in list.\n# Why would we want the smallest magnitude if we want the brightest one from the list?\nbrightest = np.min(target_mags)\n# Students see\n# brightest = ...\n\n# Subtract off the reddening factor from our brightest value: 0.25\n# The 0.25 is to correct for dust scattering some of the light.\n# This is known as stellar reddening. The value was taken from literature.\nm_target = brightest-0.25\n# Students see\n# m_target = ...\n\n# Print our new apparent magnitude for our target star.\n# Students see\n# print(...)\nprint(m_target)", "execution_count": null, "outputs": [] }, { "metadata": {}, "cell_type": "markdown", "source": "## How far away is NGC 3201?\nAccording to [other researchers](http://spider.seds.org/spider/MWGC/n3201.html), the distance to NGC 3201 is 16 kly or 4.9 kpc. How does our analysis compare?" }, { "metadata": { "scrolled": false, "trusted": true }, "cell_type": "code", "source": "# Finally we find the distance to the globular cluster based on our analysis.\n# Convert the given distance from pc to kpc.\ndistance = distance_modulus(m_target,M_target)/1000\n\n# Print the distance in kpc .\nprint('Distance to NGC 3201: '+str(...)+' kpc')\n", "execution_count": null, "outputs": [] }, { "metadata": {}, "cell_type": "markdown", "source": "## Wrap up\nBe sure to submit your final work! From within Jupyter notebook, you can select \n* File->Download as-> html (.html) \nand you'll get a single HTML file you can submit as your finished product. Be sure to keep a copy of the final output just in case you need to submit it again. If you want the Jupyter notebook in an editable form, select\n* File->Download as-> Notebook (.ipynb)\nand you'll get a single Jupyter notebook file.\n\nYou will need Python and Jupyter notebook on whatever computer you want to use to edit the notebook file. You can also use [Microsoft Azure Notebooks](https://notebooks.azure.com/) on the web. " }, { "metadata": {}, "cell_type": "markdown", "source": "# References" }, { "metadata": {}, "cell_type": "markdown", "source": "* Much of the photometry code comes from [Python library for Source Extraction and Photometry](https://sep.readthedocs.io/en/v1.0.x/tutorial.html#Aperture-photometry)\n* The FITS file handling comes from [python4Astronomers](https://python4astronomers.github.io/astropy/fits.html)\n* Be sure to check out my original[observational project](http://www.jimmynewland.com/wp/astro/measuring-rr-lyrae-stars-in-ngc-3201/)\nFor more information, contact [Jimmy Newland](https://jimmynewland.com/)\n\n This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License." } ], "metadata": { "kernelspec": { "name": "python3", "display_name": "Python 3", "language": "python" }, "language_info": { "mimetype": "text/x-python", "nbconvert_exporter": "python", "name": "python", "pygments_lexer": "ipython3", "version": "3.5.4", "file_extension": ".py", "codemirror_mode": { "version": 3, "name": "ipython" } } }, "nbformat": 4, "nbformat_minor": 2 }