diff --git a/operations/bin/fiber_search.ipynb b/operations/bin/fiber_search.ipynb index d49534b2..1be97938 100644 --- a/operations/bin/fiber_search.ipynb +++ b/operations/bin/fiber_search.ipynb @@ -20,6 +20,12 @@ "import numpy as np\n", "from ipywidgets import Button\n", "from IPython.display import display, clear_output\n", + "import time\n", + "from matplotlib.colors import LogNorm\n", + "import matplotlib.patches as mpatches\n", + "\n", + "from ipywidgets import interact, interactive, fixed, interact_manual\n", + "import ipywidgets as widgets\n", "\n", "# Constants\n", "meter = 1\n", @@ -56,7 +62,139 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Connect to mount" + "## Connect to camera" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Connect to ASCOM camera\n", + "fiber_camera = Dispatch('ASCOM.ASICamera2.Camera')\n", + "\n", + "# Open setup dialog\n", + "fiber_camera.SetupDialog()\n", + "\n", + "if fiber_camera.Connected:\n", + " print('Camera is already connected')\n", + "else:\n", + " fiber_camera.Connected = True\n", + " if fiber_camera.Connected:\n", + " print('Camera is connected')\n", + " else:\n", + " print('Camera is not connected, try again')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Camera setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Function to take and download image\n", + "def take_image(exposure_time):\n", + " fiber_camera.StartExposure(exposure_time, True)\n", + " while fiber_camera.ImageReady == False:\n", + " time.sleep(0.1)\n", + " img = fiber_camera.ImageArray\n", + " img = np.array(img)\n", + " img = np.rot90(img, 1)\n", + " return img" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "img = take_image(0.1)\n", + "\n", + "\n", + "# Plot image\n", + "plt.imshow(img, cmap='viridis')\n", + "plt.show()\n", + "\n", + "value = 16\n", + "print('Number of pixels at value ', value, ': ', np.count_nonzero(img == value))\n", + "\n", + "# Plot histogram of image with log scale on y-axis\n", + "plt.hist(img.ravel(), bins=256, range=(0.0, 65536.0), fc='k', ec='k')\n", + "plt.yscale('log')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create widget to draw circle on image and reposition it, as well as save\n", + "# the x, y, and r values\n", + "def draw_circle(x, y, r):\n", + " plt.imshow(img, cmap='viridis')\n", + " circle = plt.Circle((x, y), r, color='r', fill=False)\n", + " plt.gcf().gca().add_artist(circle)\n", + " # Make figure larger\n", + " plt.gcf().set_size_inches(10, 10)\n", + " plt.show()\n", + " return [x, y, r]\n", + "\n", + "# Get max x and y dimensions from camera\n", + "max_x = fiber_camera.CameraXSize\n", + "max_y = fiber_camera.CameraYSize\n", + "\n", + "circle_selector = interactive(draw_circle, x=widgets.IntSlider(min=0, max=max_x, step=1, value=max_x/2),\n", + " y=widgets.IntSlider(min=0, max=max_y, step=1, value=max_y/2), \n", + " r=widgets.IntSlider(min=0, max=1024, step=1, value=256),\n", + " continuous_update=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "display(circle_selector)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Print average, median, and standard deviation of pixels in box around fiber (circle is too hard)\n", + "\n", + "[fiber_x, fiber_y, fiber_r] = circle_selector.result\n", + "\n", + "# Get box around fiber\n", + "fiber_box = img[fiber_y-fiber_r:fiber_y+fiber_r, fiber_x-fiber_r:fiber_x+fiber_r]\n", + "\n", + "# Print average, median, and standard deviation of pixels in box around fiber\n", + "print('Average: %.2f' % np.average(fiber_box))\n", + "print('Median: %2d' % np.median(fiber_box))\n", + "print('Standard deviation: %2d' % np.std(fiber_box))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Connect to mount" ] }, { @@ -163,6 +301,7 @@ " for j in range(len(y)):\n", " xrot[i,j], yrot[i,j] = np.dot([[np.cos(theta), np.sin(theta)], [-np.sin(theta), np.cos(theta)]], np.array([x[i,j], y[i,j]]))\n", "delta_ras = xrot.flatten(); delta_decs = yrot.flatten()\n", + "delta_coords = np.array([delta_ras, delta_decs]).T\n", "\n", "# Plot grid\n", "fig,ax = plt.subplots(figsize=(6,6))\n", @@ -181,6 +320,74 @@ "plt.show()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Make numpy array to store average, median, and standard deviation of pixels in box around fiber\n", + "# for multiple images. We will append to this array each time we take an image.\n", + "# We will use this array to plot the average, median, and standard deviation of pixels in box around fiber\n", + "# as a function of exposure time.\n", + "fiber_stats = np.empty((0, 3), float)\n", + "\n", + "# On function call, take image, show image, and print average, median, and standard deviation of pixels in box around fiber\n", + "def take_image_and_print_stats(exposure_time, fiber_x, fiber_y, fiber_r, fiber_stats):\n", + " '''Take image, plot image, and print average, median, and standard deviation of pixels in box around fiber\n", + "\n", + " Parameters:\n", + " exposure_time (float): Exposure time in seconds\n", + " '''\n", + " # This is supposed to wait to clear the current output until new output is available, but it doesn't seem to work\n", + " clear_output(wait=True) \n", + "\n", + " # Take image, plot image\n", + " img = take_image(exposure_time)\n", + "\n", + " # Set parameters for log stretch based on image statistics\n", + " # Set minimum value to 1\n", + " min_value = np.percentile(img, 5)\n", + " # Set maximum value to 99th percentile\n", + " max_value = np.percentile(img, 99)\n", + "\n", + " # Plot image, set log stretch\n", + " plt.imshow(img, cmap='inferno', norm=LogNorm(vmin=min_value, vmax=max_value))\n", + " \n", + " # Use linear stretch\n", + " #plt.imshow(img, cmap='inferno', vmin=min_value, vmax=max_value)\n", + " \n", + " # Show box around fiber\n", + " plt.plot([fiber_x-fiber_r, fiber_x+fiber_r, fiber_x+fiber_r, fiber_x-fiber_r, fiber_x-fiber_r],\n", + " [fiber_y-fiber_r, fiber_y-fiber_r, fiber_y+fiber_r, fiber_y+fiber_r, fiber_y-fiber_r], 'r', linewidth=1)\n", + " # Make figure larger\n", + " plt.gcf().set_size_inches(15, 10)\n", + " plt.colorbar()\n", + " plt.gcf()\n", + "\n", + " # Statistics\n", + " [fiber_x, fiber_y, fiber_r] = circle_selector.result\n", + " fiber_box = img[fiber_y-fiber_r:fiber_y+fiber_r, fiber_x-fiber_r:fiber_x+fiber_r]\n", + " print('Average: %.2f' % np.average(fiber_box))\n", + " print('Median: %2d' % np.median(fiber_box))\n", + " print('Standard deviation: %2d' % np.std(fiber_box))\n", + "\n", + " # Append average, median, and standard deviation of pixels in box around fiber to fiber_stats\n", + " fiber_stats = np.append(fiber_stats, [[np.average(fiber_box), np.median(fiber_box), np.std(fiber_box)]], axis=0)\n", + " return fiber_stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(1, 10):\n", + " fiber_stats = take_image_and_print_stats(0.001, fiber_x, fiber_y, fiber_r, fiber_stats)\n", + " time.sleep(5)" + ] + }, { "attachments": {}, "cell_type": "markdown",