{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from pyscope.observatory import Observatory\n", "from astropy import coordinates as coord\n", "import logging\n", "import time\n", "import numpy as np\n", "import pathlib\n", "from IPython.display import display, clear_output\n", "\n", "# Set up logging\n", "logging.basicConfig(level=logging.DEBUG)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:pyscope.observatory.observatory:Using config file to initialize observatory: ./rlmt.cfg\n", "INFO:pyscope.observatory.observatory:Using MaxIm DL as the camera driver\n", "INFO:pyscope.observatory.observatory:Using MaxIm DL as the filter wheel driver\n", "INFO:pyscope.observatory.observatory:Using MaxIm DL as the WCS driver\n", "INFO:pyscope.observatory.observatory:CCD Temp Set to -65.63\n", "INFO:pyscope.observatory.observatory:Checking passed kwargs and overriding config file values\n", "INFO:pyscope.observatory.observatory:CCD Temp Set to -65.63\n", "INFO:pyscope.observatory.observatory:Camera connected\n", "INFO:pyscope.observatory.observatory:CCD Temp Set to -65.63\n", "INFO:pyscope.observatory.observatory:Filter wheel connected\n", "INFO:pyscope.observatory.observatory:Focuser connected\n", "INFO:pyscope.observatory.observatory:Telescope connected\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Turning cooler on\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rlmt = Observatory(config_path=\"./rlmt.cfg\")\n", "rlmt.connect_all()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Center on object (run both cells below)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RA: hms_tuple(h=12.0, m=56.0, s=43.696008000012796),\n", "Dec: dms_tuple(d=21.0, m=40.0, s=57.569879999999785)\n", "\n", "Elevation: 47.35, Azimuth: 91.87\n", "Elevation dms: dms_tuple(d=47.0, m=20.0, s=57.97982308112353), \n", "Azimuth dms: dms_tuple(d=91.0, m=52.0, s=4.038177513159553)\n", "\n", "RA: hms_tuple(h=12.0, m=57.0, s=56.47754517831942),\n", "Dec: dms_tuple(d=21.0, m=33.0, s=0.24173380448331727)\n" ] } ], "source": [ "src = coord.SkyCoord.from_name(\"M64\")\n", "print(f\"RA: {src.ra.hms},\\nDec: {src.dec.dms}\")\n", "print(src)\n", "# Print alt az of source\n", "src_altaz = rlmt.get_object_altaz(src)\n", "print(f\"Elevation: {src_altaz.alt.deg:.2f}, Azimuth: {src_altaz.az.deg:.2f}\")\n", "print(f\"Elevation dms: {src_altaz.alt.dms}, \\nAzimuth dms: {src_altaz.az.dms}\")\n", "if src_altaz.alt.deg < 30:\n", " raise Exception(\"Source is too low to observe.\")\n", " \n", "# tete_coords = src.transform_to(coord.TETE(obstime = rlmt.observatory_time, location=rlmt.observatory_location))\n", "# print(tete_coords)\n", "# print(f\"RA: {tete_coords.ra.hms},\\nDec: {tete_coords.dec.dms}\")" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:pyscope.observatory.observatory:Attempt 1 of 5\n", "INFO:pyscope.observatory.observatory:Slewing to RA hms_tuple(h=12.0, m=56.0, s=43.69600800001919) and Dec dms_tuple(d=21.0, m=40.0, s=57.569879999999785)\n", "INFO:pyscope.observatory.observatory:Turning on sidereal tracking...\n", "INFO:pyscope.observatory.observatory:Sidereal tracking is on.\n", "INFO:pyscope.observatory.observatory:Attempting to slew to coordinates...\n", "INFO:pyscope.observatory.observatory:Slewing to RA 12.96569 and Dec 21.55007\n", "INFO:pyscope.observatory.observatory:Settling for 0.00 seconds...\n", "INFO:pyscope.observatory.observatory:Settling for 0.00 seconds\n", "INFO:pyscope.observatory.observatory:Taking 3.00 second exposure\n", "INFO:pyscope.observatory.observatory:Exposure complete\n", "INFO:pyscope.observatory.observatory:Using Maxim to save image\n", "INFO:pyscope.observatory.observatory:Overwrite allowed for header keys ['AIRMASS', 'OBJECT', 'TELESCOP', 'INSTRUME', 'OBSERVER']\n", "INFO:pyscope.observatory.observatory:Getting header from MaxIm image\n", "INFO:pyscope.observatory.observatory:Searching for a WCS solution...\n", "INFO:pyscope.observatory.observatory:Saving the centering image to ./recenter_images/\n", "INFO:pyscope.observatory.observatory:Using Maxim to save image\n", "INFO:pyscope.observatory.observatory:Overwrite allowed for header keys ['AIRMASS', 'OBJECT', 'TELESCOP', 'INSTRUME', 'OBSERVER']\n", "INFO:pyscope.observatory.observatory:Getting header from MaxIm image\n", "INFO:pyscope.observatory.observatory:Using Maxim to save image\n", "INFO:pyscope.observatory.observatory:Overwrite allowed for header keys ['AIRMASS', 'OBJECT', 'TELESCOP', 'INSTRUME', 'OBSERVER']\n", "INFO:pyscope.observatory.observatory:Getting header from MaxIm image\n", "INFO:pyscope.observatory.observatory:WCS solution found, solving for the pixel location of the target\n", "INFO:pyscope.observatory.observatory:Error in RA is 147.74 arcseconds\n", "INFO:pyscope.observatory.observatory:Error in Dec is -141.10 arcseconds\n", "INFO:pyscope.observatory.observatory:Error in x pixels is -158.31\n", "INFO:pyscope.observatory.observatory:Error in y pixels is 184.56\n", "INFO:pyscope.observatory.observatory:Offsetting next slew coordinates\n", "INFO:pyscope.observatory.observatory:\n", "INFO:pyscope.observatory.observatory:Attempt 2 of 5\n", "INFO:pyscope.observatory.observatory:Slewing to RA hms_tuple(h=12.0, m=56.0, s=53.54504877961986) and Dec dms_tuple(d=21.0, m=38.0, s=36.47371021132358)\n", "INFO:pyscope.observatory.observatory:Turning on sidereal tracking...\n", "INFO:pyscope.observatory.observatory:Sidereal tracking is on.\n", "INFO:pyscope.observatory.observatory:Attempting to slew to coordinates...\n", "INFO:pyscope.observatory.observatory:Slewing to RA 12.96842 and Dec 21.51089\n", "INFO:pyscope.observatory.observatory:Settling for 0.00 seconds...\n", "INFO:pyscope.observatory.observatory:Settling for 0.00 seconds\n", "INFO:pyscope.observatory.observatory:Taking 3.00 second exposure\n", "INFO:pyscope.observatory.observatory:Exposure complete\n", "INFO:pyscope.observatory.observatory:Using Maxim to save image\n", "INFO:pyscope.observatory.observatory:Overwrite allowed for header keys ['AIRMASS', 'OBJECT', 'TELESCOP', 'INSTRUME', 'OBSERVER']\n", "INFO:pyscope.observatory.observatory:Getting header from MaxIm image\n", "INFO:pyscope.observatory.observatory:Searching for a WCS solution...\n", "INFO:pyscope.observatory.observatory:Saving the centering image to ./recenter_images/\n", "INFO:pyscope.observatory.observatory:Using Maxim to save image\n", "INFO:pyscope.observatory.observatory:Overwrite allowed for header keys ['AIRMASS', 'OBJECT', 'TELESCOP', 'INSTRUME', 'OBSERVER']\n", "INFO:pyscope.observatory.observatory:Getting header from MaxIm image\n", "INFO:pyscope.observatory.observatory:Using Maxim to save image\n", "INFO:pyscope.observatory.observatory:Overwrite allowed for header keys ['AIRMASS', 'OBJECT', 'TELESCOP', 'INSTRUME', 'OBSERVER']\n", "INFO:pyscope.observatory.observatory:Getting header from MaxIm image\n", "INFO:pyscope.observatory.observatory:WCS solution found, solving for the pixel location of the target\n", "INFO:pyscope.observatory.observatory:Error in RA is -0.90 arcseconds\n", "INFO:pyscope.observatory.observatory:Error in Dec is -0.16 arcseconds\n", "INFO:pyscope.observatory.observatory:Error in x pixels is 1.02\n", "INFO:pyscope.observatory.observatory:Error in y pixels is 0.14\n", "INFO:pyscope.observatory.observatory:Target is now in position after 2 attempts\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Set to g filter\n", "rlmt.filter_wheel.Position = 2\n", "\n", "# Run recentering algorithm\n", "if src_altaz.alt.deg < 30:\n", " raise Exception(\"Source is too low to observe.\")\n", "rlmt.recenter(src, \n", " target_x_pixel=1024, # TODO: make default center of sensor in each axis\n", " target_y_pixel=1024,\n", " exposure=3, \n", " save_images=True,\n", " save_path=\"./recenter_images/\",\n", " readout=2,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Setup for Focus position movement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Change values in cell below" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Focus positions are [3000 3250 3500 3750 4000 4250 4500 4750 5000 5250 5500 5750], there are 12 positions\n", "Filter wheel is at (or moving to) position 0\n" ] } ], "source": [ "# Image save directory\n", "save_dir = \"focus_images\"\n", "# Make the save directory if it doesn't exist\n", "pathlib.Path(save_dir).mkdir(parents=True, exist_ok=True)\n", "\n", "# Set up focuser position list\n", "# Start at min, end at max, step by focus_step\n", "min_focus = 500\n", "max_focus = 3000\n", "focus_step = 250\n", "\n", "# Filter positions DO NOT CHANGE\n", "filter_positions = {\n", " \"LowRes\": 0,\n", " \"HighRes\": 4,\n", " \"g\": 2,\n", "}\n", "\n", "# Camera and filter wheel settings (use filter names from above)\n", "num_images = 4 # Images at each focus position\n", "exp_time = 5\n", "filter_name = \"LowRes\" # This is the filter that will be used\n", "\n", "# Move filter wheel to position\n", "rlmt.filter_wheel.Position = filter_positions[filter_name]\n", "\n", "# Print for verification\n", "focus_positions = np.arange(min_focus, max_focus, focus_step)\n", "print(f\"Focus positions are {focus_positions}, there are {len(focus_positions)} positions\")\n", "print(f\"Filter wheel is at (or moving to) position {rlmt.filter_wheel.Position}\")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def capture_focus_image(focus_position, filter_name, exp_time=5, filename_prefix=\"focus\", binning=1):\n", " # # Set binning\n", " rlmt.camera.BinX = binning\n", " rlmt.camera.BinY = binning\n", "\n", " # # Start exposure\n", " print(f\"Starting {int(exp_time)}s exposure...\")\n", " rlmt.camera.StartExposure(int(exp_time), True)\n", " \n", " # Set up image base filename\n", " exp_time_str = str(exp_time).replace(\".\", \"p\")\n", " filename_base = f\"{filename_prefix}_{focus_position}_{exp_time_str}s_{filter_name}\"\n", " # Check if file exists in save_dir\n", " i = 0\n", " filename = pathlib.Path(save_dir) / f\"{filename_base}_{i}.fts\"\n", " # print(f\"Checking if {filename} exists...\")\n", " # print(f\"filename.exists() is {filename.exists()}\")\n", " while filename.exists():\n", " # If file exists, add a number to the end of the filename\n", " i += 1\n", " # print(f\"{filename} does exist\")\n", " filename = pathlib.Path(save_dir) / f\"{filename_base}_{i}.fts\"\n", " # print(f\"Checking if {filename} exists...\")\n", "\n", " # Save latest image\n", " while not rlmt.camera.ImageReady:\n", " time.sleep(0.1)\n", " time.sleep(0.1)\n", " rlmt.save_last_image(filename, \"Light\", overwrite=True)\n", "\n", " return filename" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Focus at each position\n", "focus_move_time = 15\n", "img_download_time = 6\n", "focus_image_time = exp_time + img_download_time\n", "\n", "# Estimate total time required\n", "total_time = (\n", " focus_move_time * len(focus_positions)\n", ") + focus_image_time * num_images * len(focus_positions)\n", "print(f\"Estimated total time required is {total_time/60} minutes\")\n", "\n", "time_per_cycle = []\n", "\n", "for focus_position in focus_positions:\n", " if time_per_cycle:\n", " print(f\"Average time per cycle is {np.mean(time_per_cycle):.2f} seconds\")\n", " est_time_remaining = np.mean(time_per_cycle) * (\n", " len(focus_positions) - np.where(focus_positions == focus_position)[0][0]\n", " )\n", " # Print time remaining in minutes and seconds\n", " print(\n", " f\"Estimated time remaining is {est_time_remaining//60:.0f} min {est_time_remaining%60:.0f} sec\"\n", " )\n", " start_time = time.time()\n", " print(f\"Moving to focus position {focus_position}\")\n", "\n", " print(\n", " f\"This is position {np.where(focus_positions == focus_position)[0][0]+1} of {len(focus_positions)}\"\n", " )\n", " rlmt.focuser.Move(focus_position)\n", " while rlmt.focuser.IsMoving:\n", " #print(f\"Focuser is moving to {focus_positions[0]}\")\n", " time.sleep(0.1)\n", " #current_focus = int(rlmt.focuser.Position)\n", " current_focus = focus_position\n", " print(f\"Focus position is {current_focus}\")\n", " print(\"========================================\")\n", "\n", " current_exp_time = exp_time\n", " print(f\"current_exp_time={current_exp_time}\")\n", "\n", " for i in range(num_images):\n", " img_file = capture_focus_image(current_focus, filter_name, exp_time=current_exp_time, filename_prefix=\"focus\", binning=1)\n", " print(f\"Saved image {i} at focus position {current_focus}\")\n", "\n", " end_time = time.time()\n", " time_per_cycle.append(end_time - start_time)\n", "\n", " # Clear cell output for next loop\n", " clear_output()" ] } ], "metadata": { "kernelspec": { "display_name": "pyscope-dev", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.2" } }, "nbformat": 4, "nbformat_minor": 2 }