├── Dark Testing Notebooks └── graphing_functions.py └── Linearity Notebooks ├── generate-linearity-observing-plan.ipynb └── Writeup.ipynb /Dark Testing Notebooks/graphing_functions.py: -------------------------------------------------------------------------------- 1 | from matplotlib import pyplot as plt 2 | import numpy as np 3 | 4 | __all__ = ['plot_linearity', 'plot_dark_current'] 5 | 6 | def plot_linearity(all_darks, bad_locs, exposures, pix_max=0, pix_min=0, legend=True, plot_fraction=1.0): 7 | max_exposure = np.max(exposures) 8 | plt.figure(figsize=(10, 10)) 9 | badnesses = [] 10 | longest_exp = all_darks[:, :, -1] 11 | #print('outside loop', bad_locs.shape, flush=True) 12 | for i, j in zip(bad_locs[:, 0], bad_locs[:, 1]): 13 | #print('inside loop') 14 | actual_values = all_darks[i, j, :]/longest_exp[i, j] 15 | badness = np.sqrt(((actual_values - exposures/max_exposure)**2).mean()) 16 | badnesses.append(badness) 17 | wid = 4 if badness > 0.07 else 1 18 | if np.random.rand() < plot_fraction: 19 | plt.plot(exposures, actual_values, label='{}, {}; {:.3f}'.format(i,j, badness), linewidth=wid) 20 | plt.plot([0, max_exposure], [0,1], color='black', linewidth=4, linestyle='dashed', label='Linear') 21 | if legend: 22 | plt.legend(bbox_to_anchor=(1.5, 0.6), ncol=3) 23 | plt.ylim(-0.1, 1.1) 24 | plt.xlabel('Exposure time (sec)', size=20) 25 | plt.ylabel('pixel value as fraction of value in 120sec frame', size=20) 26 | plt.title('Linearity of master darks ({} pixels ' 27 | 'between {}$\sigma$ and {}$\sigma$)'.format(bad_locs.shape[0], pix_min, pix_max), 28 | size=15) 29 | return badnesses 30 | 31 | 32 | def plot_dark_current(all_darks, bad_locs, badnesses, exposures, gain=1.5, legend=False, plot_fraction=1.0): 33 | plt.figure(figsize=(10, 10)) 34 | linestyles = ['dashed', 'solid', 'dotted'] 35 | for i, j, badness in zip(bad_locs[:, 0], bad_locs[:, 1], badnesses): 36 | actual_values = gain * all_darks[i, j, :] / exposures 37 | width = 4 if badness > 0.07 else 1 38 | wid = 4 if badness > 0.07 else 1 39 | if np.random.rand() < plot_fraction: 40 | plt.plot(exposures, actual_values, label='{}, {}; {:.3f}'.format(i,j, badness), linewidth=wid) 41 | #plt.plot(exposures, actual_values, label='{}, {}'.format(i,j), 42 | #linestyle=np.random.choice(linestyles), linewidth=width) 43 | 44 | 45 | plt.xlabel('Exposure time (sec)', size=20) 46 | plt.ylabel('Dark current (e$^-$/sec/pixel', size=20) 47 | if legend: 48 | plt.legend() 49 | -------------------------------------------------------------------------------- /Linearity Notebooks/generate-linearity-observing-plan.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 228, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "\n", 11 | "repeat = 5\n", 12 | "max_exposure = 75\n", 13 | "min_exposure = 1\n", 14 | "time_between = 1\n", 15 | "points_between = 160\n", 16 | "step = .5\n", 17 | "\n", 18 | "exposures = list(np.arange(min_exposure, max_exposure, step))" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 229, 24 | "metadata": {}, 25 | "outputs": [ 26 | { 27 | "name": "stdout", 28 | "output_type": "stream", 29 | "text": [ 30 | "Time for plan (minutes) 773.9166666666666\n" 31 | ] 32 | } 33 | ], 34 | "source": [ 35 | "print('Time for plan (minutes)', repeat * ((sum(exposures) + 25 * len(exposures))/60))" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 218, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "repeat = '#repeat ' + str(repeat)" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 219, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "interval = '#interval {}'.format(','.join([str(i) for i in exposures]))" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 220, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "binning = '#binning {}'.format(','.join(['1'] * len(exposures)))\n", 63 | "count = '#count {}'.format(','.join(['1'] * len(exposures)))" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 221, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "fil = '#filter {}'.format(','.join(['r'] * len(exposures)))" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 222, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "manual_dome = '#manual dome'" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "## The output of the cell below is what you want\n", 89 | "\n", 90 | "I copied/pasted into an email to myself to get it on the telescope machine.\n", 91 | "\n", 92 | "Notebook now writes plan to text document." 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 227, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "read_out = '\\n'.join([repeat, count, binning, fil, interval, manual_dome])" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 225, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "text_file = open('Linearity Plan.txt', 'w')\n", 111 | "text_file.write(str(read_out))\n", 112 | "text_file.close()" 113 | ] 114 | } 115 | ], 116 | "metadata": { 117 | "kernelspec": { 118 | "display_name": "Python 3", 119 | "language": "python", 120 | "name": "python3" 121 | }, 122 | "language_info": { 123 | "codemirror_mode": { 124 | "name": "ipython", 125 | "version": 3 126 | }, 127 | "file_extension": ".py", 128 | "mimetype": "text/x-python", 129 | "name": "python", 130 | "nbconvert_exporter": "python", 131 | "pygments_lexer": "ipython3", 132 | "version": "3.6.5" 133 | } 134 | }, 135 | "nbformat": 4, 136 | "nbformat_minor": 2 137 | } 138 | -------------------------------------------------------------------------------- /Linearity Notebooks/Writeup.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Methods\n", 8 | "To test linearity, two datasets of photos were taken by starting with a low exposure time and taking photos, increasing the exposure each time. The idea is to start with exposures that yield a low number of ADU and stop taking photos when the ccd saturates or reaches its maximum ADU. Each dataset of linearity photos were taken with the telescope pointing at the top of the closed dome and the room light on. Dataset 1 was taken on Monday, May 21st. Dataset 2 was taken on Thursday, May 24th. Because the ccd chip was not equally saturated everywhere, a selection of pixel values in the center of the ccd were used opposed to the whole chip. " 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# Results\n", 16 | "## Data\n", 17 | "The graphs below show the average CCD Data in counts on the y-axis, and the corresponding image's exposure time on the x-axis. The data was fit to a line. Ideally, the linear fit show what the ADU should be at a given exposure but the camera can only count up so high. At the far right, the data starts to dip. This is the where the CCD starts to saturate. " 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "Figure_1 | Figure_2\n", 25 | "- | -\n", 26 | "![Image name](Linear Fit for Dataset 1.png 'Figure 1') | ![Another Image](Linear Fit Dataset 2.png 'Figure 2')" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "Dataset 1 seemed not as useful as desired so a second dataset with more datapoints was created. Additionally, we can look at the difference from the fit and what the data shows. This is useful to see where the data becomes unusable. On the x-axis is the measured counts and on the y-axis is the difference in ADU from the fit and the data as a percentage. an ideal window of error to allow is less than 2% from 0. " 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "figure_3 | figure_4\n", 41 | "- | -\n", 42 | "![Image](Residuals Counts for Dataset 1.png 'Figure 3') | ![Image](Residuals Counts for Dataset 2.png 'Figure 4')" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "Again, Dataset 2 is more useful as it shows the same features but with more datapoints.\n", 50 | "## Subset of Data\n", 51 | "One issue with ploting the data from the whole CCD is that there are some areas of the chip that aren't equally saturated. For example, when the camera is near complete saturation, if the object is in the center of the frame then the center will be more saturated than the edges. To combat this only a subset of the data on the CCD was used to calculate the ADU. The subset is a 1000 by 1000 square in the middle of the CCD. " 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "figure_5 | figure_6\n", 59 | "- | -\n", 60 | "![Image](Linear Fit for Dataset 1 modified.png 'Figure 5') | ![Image](Linear Fit Dataset 2 modified.png 'Figure 6')" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "When the Dataset is limited to a block in the center where saturation is more uniform, there is a more clear point of saturation. It also helps to look at the residuals since there is a more clear saturation." 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "figure_7 | figure_8\n", 75 | "- | -\n", 76 | "![Image](Residuals Counts for Dataset 1 modified.png 'Figure 7') |![Image](Residuals counts for Dataset 2 modified.png 'Figure 8')" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [] 85 | } 86 | ], 87 | "metadata": { 88 | "kernelspec": { 89 | "display_name": "Python 3", 90 | "language": "python", 91 | "name": "python3" 92 | }, 93 | "language_info": { 94 | "codemirror_mode": { 95 | "name": "ipython", 96 | "version": 3 97 | }, 98 | "file_extension": ".py", 99 | "mimetype": "text/x-python", 100 | "name": "python", 101 | "nbconvert_exporter": "python", 102 | "pygments_lexer": "ipython3", 103 | "version": "3.6.5" 104 | } 105 | }, 106 | "nbformat": 4, 107 | "nbformat_minor": 2 108 | } 109 | --------------------------------------------------------------------------------