Add stvid notebook draft
parent
5afce3ed7e
commit
665feef2dc
|
@ -6,8 +6,9 @@ and `acquire.py` for didadic purposes.
|
|||
The following Jupyter notebooks are available:
|
||||
|
||||
* acquire.ipynb --- Acquires 10 seconds of FITS. Works.
|
||||
* hacquire.ipynb --- Hakcy version going to have new features.
|
||||
* hacquire.ipynb --- Hakcy version, may show live view someday.
|
||||
* process_new.ipynb --- Processes one FITS file, as shown below.
|
||||
* stvid.ipynb --- Acquire, display image, and process one FITS.
|
||||
|
||||
|
||||
# Install
|
||||
|
|
|
@ -0,0 +1,890 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"import os\n",
|
||||
"import numpy as np\n",
|
||||
"import cv2\n",
|
||||
"import time\n",
|
||||
"import ctypes\n",
|
||||
"import multiprocessing\n",
|
||||
"from astropy.coordinates import EarthLocation\n",
|
||||
"from astropy.time import Time\n",
|
||||
"from astropy.io import fits\n",
|
||||
"import astropy.units as u\n",
|
||||
"from stvid.utils import get_sunset_and_sunrise\n",
|
||||
"import logging\n",
|
||||
"import configparser\n",
|
||||
"import argparse\n",
|
||||
"import zwoasi as asi\n",
|
||||
"# XXX Requires non-libre libbcm_host.so ?\n",
|
||||
"#from picamerax.array import PiRGBArray\n",
|
||||
"#from picamerax import PiCamera"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Capture images from pi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"jupyter": {
|
||||
"source_hidden": true
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def capture_pi(image_queue, z1, t1, z2, t2, nx, ny, nz, tend, device_id, live, cfg):\n",
|
||||
" # Intialization\n",
|
||||
" first = True\n",
|
||||
" slow_CPU = False\n",
|
||||
"\n",
|
||||
" # Initialize cv2 device\n",
|
||||
" camera = PiCamera(sensor_mode=2)\n",
|
||||
" camera.resolution = (nx, ny) \n",
|
||||
" # Turn off any thing automatic.\n",
|
||||
" camera.exposure_mode = 'off' \n",
|
||||
" camera.awb_mode = 'off'\n",
|
||||
" # ISO needs to be 0 otherwise analog and digital gain won't work.\n",
|
||||
" camera.iso = 0\n",
|
||||
" # set the camea settings\n",
|
||||
" camera.framerate = cfg.getfloat(camera_type, 'framerate')\n",
|
||||
" camera.awb_gains = (cfg.getfloat(camera_type, 'awb_gain_red'), cfg.getfloat(camera_type, 'awb_gain_blue')) \n",
|
||||
" camera.analog_gain = cfg.getfloat(camera_type, 'analog_gain')\n",
|
||||
" camera.digital_gain = cfg.getfloat(camera_type, 'digital_gain')\n",
|
||||
" camera.shutter_speed = cfg.getint(camera_type, 'exposure')\n",
|
||||
" rawCapture = PiRGBArray(camera, size=(nx, ny))\n",
|
||||
" # allow the camera to warmup\n",
|
||||
" time.sleep(0.1)\n",
|
||||
" try:\n",
|
||||
" # Loop until reaching end time\n",
|
||||
" while float(time.time()) < tend:\n",
|
||||
" # Wait for available capture buffer to become available\n",
|
||||
" if (image_queue.qsize() > 1):\n",
|
||||
" logger.warning(\"Acquiring data faster than your CPU can process\")\n",
|
||||
" slow_CPU = True\n",
|
||||
" while (image_queue.qsize() > 1):\n",
|
||||
" time.sleep(0.1)\n",
|
||||
" if slow_CPU:\n",
|
||||
" lost_video = time.time() - t\n",
|
||||
" logger.info(\"Waited %.3fs for available capture buffer\" % lost_video)\n",
|
||||
" slow_CPU = False\n",
|
||||
"\n",
|
||||
" # Get frames\n",
|
||||
" i = 0\n",
|
||||
" for frameA in camera.capture_continuous(rawCapture, format=\"bgr\", use_video_port=True):\n",
|
||||
" \n",
|
||||
" # Store start time\n",
|
||||
" t0 = float(time.time()) \n",
|
||||
" # grab the raw NumPy array representing the image, then initialize the timestamp \n",
|
||||
" frame = frameA.array\n",
|
||||
" \n",
|
||||
" # Compute mid time\n",
|
||||
" t = (float(time.time())+t0)/2.0\n",
|
||||
" \n",
|
||||
" # Skip lost frames\n",
|
||||
" if frame is not None:\n",
|
||||
" # Convert image to grayscale\n",
|
||||
" z = np.asarray(cv2.cvtColor(\n",
|
||||
" frame, cv2.COLOR_BGR2GRAY)).astype(np.uint8)\n",
|
||||
" # optionally rotate the frame by 2 * 90 degrees. \n",
|
||||
" # z = np.rot90(z, 2)\n",
|
||||
" \n",
|
||||
" # Display Frame\n",
|
||||
" if live is True: \n",
|
||||
" cv2.imshow(\"Capture\", z) \n",
|
||||
" cv2.waitKey(1)\n",
|
||||
" \n",
|
||||
" # Store results\n",
|
||||
" if first:\n",
|
||||
" z1[i] = z\n",
|
||||
" t1[i] = t\n",
|
||||
" else:\n",
|
||||
" z2[i] = z\n",
|
||||
" t2[i] = t\n",
|
||||
" \n",
|
||||
" # clear the stream in preparation for the next frame\n",
|
||||
" rawCapture.truncate(0)\n",
|
||||
" # count up to nz frames, then break out of the for loop.\n",
|
||||
" i += 1\n",
|
||||
" if i >= nz:\n",
|
||||
" break\n",
|
||||
" \n",
|
||||
" if first: \n",
|
||||
" buf = 1\n",
|
||||
" else:\n",
|
||||
" buf = 2\n",
|
||||
" image_queue.put(buf)\n",
|
||||
" logger.debug(\"Captured z%d\" % buf)\n",
|
||||
"\n",
|
||||
" # Swap flag\n",
|
||||
" first = not first\n",
|
||||
" reason = \"Session complete\"\n",
|
||||
" except KeyboardInterrupt:\n",
|
||||
" print()\n",
|
||||
" reason = \"Keyboard interrupt\"\n",
|
||||
" except ValueError as e:\n",
|
||||
" logger.error(\"%s\" % e)\n",
|
||||
" reason = \"Wrong image dimensions? Fix nx, ny in config.\"\n",
|
||||
" finally:\n",
|
||||
" # End capture\n",
|
||||
" logger.info(\"Capture: %s - Exiting\" % reason)\n",
|
||||
" camera.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"source": [
|
||||
"Capture images from cv2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def capture_cv2(image_queue, z1, t1, z2, t2, nx, ny, nz, tend, device_id, live, cfg):\n",
|
||||
" # Intialization\n",
|
||||
" first = True\n",
|
||||
" slow_CPU = False\n",
|
||||
"\n",
|
||||
" # Initialize cv2 device\n",
|
||||
" device = cv2.VideoCapture(device_id)\n",
|
||||
"\n",
|
||||
" # Test for software binning\n",
|
||||
" try:\n",
|
||||
" software_bin = cfg.getint(camera_type, 'software_bin')\n",
|
||||
" except configparser.Error:\n",
|
||||
" software_bin = 1\n",
|
||||
"\n",
|
||||
" # Set properties\n",
|
||||
" device.set(3, nx * software_bin)\n",
|
||||
" device.set(4, ny * software_bin)\n",
|
||||
" try:\n",
|
||||
" # Loop until reaching end time\n",
|
||||
" while float(time.time()) < tend:\n",
|
||||
" # Wait for available capture buffer to become available\n",
|
||||
" if (image_queue.qsize() > 1):\n",
|
||||
" logger.warning(\"Acquiring data faster than your CPU can process\")\n",
|
||||
" slow_CPU = True\n",
|
||||
" while (image_queue.qsize() > 1):\n",
|
||||
" time.sleep(0.1)\n",
|
||||
" if slow_CPU:\n",
|
||||
" lost_video = time.time() - t\n",
|
||||
" logger.info(\"Waited %.3fs for available capture buffer\" % lost_video)\n",
|
||||
" slow_CPU = False\n",
|
||||
"\n",
|
||||
" # Get frames\n",
|
||||
" for i in range(nz):\n",
|
||||
" # Store start time\n",
|
||||
" t0 = float(time.time())\n",
|
||||
" # Get frame\n",
|
||||
" res, frame = device.read()\n",
|
||||
" # Compute mid time\n",
|
||||
" t = (float(time.time())+t0)/2.0\n",
|
||||
" # Skip lost frames\n",
|
||||
" if res is True:\n",
|
||||
" # Convert image to grayscale\n",
|
||||
" z = np.asarray(cv2.cvtColor(\n",
|
||||
" frame, cv2.COLOR_BGR2GRAY)).astype(np.uint8)\n",
|
||||
" # Apply software binning\n",
|
||||
" if software_bin > 1:\n",
|
||||
" my, mx = z.shape\n",
|
||||
" z = cv2.resize(z, (mx // software_bin, my // software_bin))\n",
|
||||
" # Display Frame\n",
|
||||
" if live is True:\n",
|
||||
" cv2.imshow(\"Capture\", z)\n",
|
||||
" cv2.waitKey(1)\n",
|
||||
" # Store results\n",
|
||||
" if first:\n",
|
||||
" z1[i] = z\n",
|
||||
" t1[i] = t\n",
|
||||
" else:\n",
|
||||
" z2[i] = z\n",
|
||||
" t2[i] = t\n",
|
||||
" if first: \n",
|
||||
" buf = 1\n",
|
||||
" else:\n",
|
||||
" buf = 2\n",
|
||||
" image_queue.put(buf)\n",
|
||||
" logger.debug(\"Captured z%d\" % buf)\n",
|
||||
"\n",
|
||||
" # Swap flag\n",
|
||||
" first = not first\n",
|
||||
" reason = \"Session complete\"\n",
|
||||
" except ValueError as e:\n",
|
||||
" logger.error(\"%s\" % e)\n",
|
||||
" reason = \"Wrong image dimensions? Fix nx, ny in config.\"\n",
|
||||
" finally:\n",
|
||||
" # End capture\n",
|
||||
" logger.info(\"Capture: %s - Exiting\" % reason)\n",
|
||||
" device.release()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Capture images"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"jupyter": {
|
||||
"source_hidden": true
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def capture_asi(image_queue, z1, t1, z2, t2, nx, ny, nz, tend, device_id, live, cfg):\n",
|
||||
" first = True # Array flag\n",
|
||||
" slow_CPU = False # Performance issue flag\n",
|
||||
" \n",
|
||||
" camera_type = \"ASI\"\n",
|
||||
" gain = cfg.getint(camera_type, 'gain')\n",
|
||||
" maxgain = cfg.getint(camera_type, 'maxgain')\n",
|
||||
" autogain = cfg.getboolean(camera_type, 'autogain')\n",
|
||||
" exposure = cfg.getint(camera_type, 'exposure')\n",
|
||||
" binning = cfg.getint(camera_type, 'bin')\n",
|
||||
" brightness = cfg.getint(camera_type, 'brightness')\n",
|
||||
" bandwidth = cfg.getint(camera_type, 'bandwidth')\n",
|
||||
" high_speed = cfg.getint(camera_type, 'high_speed')\n",
|
||||
" hardware_bin = cfg.getint(camera_type, 'hardware_bin')\n",
|
||||
" sdk = cfg.get(camera_type, 'sdk')\n",
|
||||
" try:\n",
|
||||
" software_bin = cfg.getint(camera_type, 'software_bin')\n",
|
||||
" except configparser.Error:\n",
|
||||
" software_bin = 0\n",
|
||||
"\n",
|
||||
" # Initialize device\n",
|
||||
" asi.init(sdk)\n",
|
||||
" num_cameras = asi.get_num_cameras()\n",
|
||||
" if num_cameras == 0:\n",
|
||||
" logger.error(\"No ZWOASI cameras found\")\n",
|
||||
" raise ValueError\n",
|
||||
" sys.exit()\n",
|
||||
" cameras_found = asi.list_cameras() # Models names of the connected cameras\n",
|
||||
" if num_cameras == 1:\n",
|
||||
" device_id = 0\n",
|
||||
" logger.info(\"Found one camera: %s\" % cameras_found[0])\n",
|
||||
" else:\n",
|
||||
" logger.info(\"Found %d ZWOASI cameras\" % num_cameras)\n",
|
||||
" for n in range(num_cameras):\n",
|
||||
" logger.info(\" %d: %s\" % (n, cameras_found[n]))\n",
|
||||
" logger.info(\"Using #%d: %s\" % (device_id, cameras_found[device_id]))\n",
|
||||
" camera = asi.Camera(device_id)\n",
|
||||
" camera_info = camera.get_camera_property()\n",
|
||||
" logger.debug(\"ASI Camera info:\")\n",
|
||||
" for (key, value) in camera_info.items():\n",
|
||||
" logger.debug(\" %s : %s\" % (key,value))\n",
|
||||
" camera.set_control_value(asi.ASI_BANDWIDTHOVERLOAD, bandwidth)\n",
|
||||
" camera.disable_dark_subtract()\n",
|
||||
" camera.set_control_value(asi.ASI_GAIN, gain, auto=autogain)\n",
|
||||
" camera.set_control_value(asi.ASI_EXPOSURE, exposure, auto=False)\n",
|
||||
" camera.set_control_value(asi.ASI_AUTO_MAX_GAIN, maxgain)\n",
|
||||
" camera.set_control_value(asi.ASI_AUTO_MAX_BRIGHTNESS, 20)\n",
|
||||
" camera.set_control_value(asi.ASI_WB_B, 99)\n",
|
||||
" camera.set_control_value(asi.ASI_WB_R, 75)\n",
|
||||
" camera.set_control_value(asi.ASI_GAMMA, 50)\n",
|
||||
" camera.set_control_value(asi.ASI_BRIGHTNESS, brightness)\n",
|
||||
" camera.set_control_value(asi.ASI_FLIP, 0)\n",
|
||||
" try:\n",
|
||||
" camera.set_control_value(asi.ASI_HIGH_SPEED_MODE, high_speed)\n",
|
||||
" except:\n",
|
||||
" pass\n",
|
||||
" try:\n",
|
||||
" camera.set_control_value(asi.ASI_HARDWARE_BIN, hardware_bin)\n",
|
||||
" except:\n",
|
||||
" pass\n",
|
||||
" camera.set_roi(bins=binning)\n",
|
||||
" camera.start_video_capture()\n",
|
||||
" camera.set_image_type(asi.ASI_IMG_RAW8)\n",
|
||||
" try:\n",
|
||||
" # Fix autogain\n",
|
||||
" if autogain:\n",
|
||||
" while True:\n",
|
||||
" # Get frame\n",
|
||||
" z = camera.capture_video_frame()\n",
|
||||
" # Break on no change in gain\n",
|
||||
" settings = camera.get_control_values()\n",
|
||||
" if gain == settings[\"Gain\"]:\n",
|
||||
" break\n",
|
||||
" gain = settings[\"Gain\"]\n",
|
||||
" camera.set_control_value(asi.ASI_GAIN, gain, auto=autogain)\n",
|
||||
"\n",
|
||||
" # Loop until reaching end time\n",
|
||||
" while float(time.time()) < tend:\n",
|
||||
" # Wait for available capture buffer to become available\n",
|
||||
" if (image_queue.qsize() > 1):\n",
|
||||
" logger.warning(\"Acquiring data faster than your CPU can process\")\n",
|
||||
" slow_CPU = True\n",
|
||||
" while (image_queue.qsize() > 1):\n",
|
||||
" time.sleep(0.1)\n",
|
||||
" if slow_CPU:\n",
|
||||
" lost_video = time.time() - t\n",
|
||||
" logger.info(\"Waited %.3fs for available capture buffer\" % lost_video)\n",
|
||||
" slow_CPU = False\n",
|
||||
"\n",
|
||||
" # Get settings\n",
|
||||
" settings = camera.get_control_values()\n",
|
||||
" gain = settings[\"Gain\"]\n",
|
||||
" temp = settings[\"Temperature\"]/10.0\n",
|
||||
" logger.info(\"Capturing frame with gain %d, temperature %.1f\" % (gain, temp))\n",
|
||||
"\n",
|
||||
" # Set gain\n",
|
||||
" if autogain:\n",
|
||||
" camera.set_control_value(asi.ASI_GAIN, gain, auto=autogain)\n",
|
||||
"\n",
|
||||
" # Get frames\n",
|
||||
" for i in range(nz):\n",
|
||||
" # Store start time\n",
|
||||
" t0 = float(time.time())\n",
|
||||
" # Get frame\n",
|
||||
" z = camera.capture_video_frame()\n",
|
||||
" # Apply software binning\n",
|
||||
" if software_bin > 1:\n",
|
||||
" my, mx = z.shape\n",
|
||||
" z = cv2.resize(z, (mx // software_bin, my // software_bin))\n",
|
||||
" \n",
|
||||
" # Compute mid time\n",
|
||||
" t = (float(time.time())+t0)/2.0\n",
|
||||
" # Display Frame\n",
|
||||
" if live is True:\n",
|
||||
" cv2.imshow(\"Capture\", z)\n",
|
||||
" cv2.waitKey(1)\n",
|
||||
" # Store results\n",
|
||||
" if first:\n",
|
||||
" z1[i] = z\n",
|
||||
" t1[i] = t\n",
|
||||
" else:\n",
|
||||
" z2[i] = z\n",
|
||||
" t2[i] = t\n",
|
||||
" if first: \n",
|
||||
" buf = 1\n",
|
||||
" else:\n",
|
||||
" buf = 2\n",
|
||||
" image_queue.put(buf)\n",
|
||||
" logger.debug(\"Captured buffer %d (%dx%dx%d)\" % (buf, nx, ny, nz))\n",
|
||||
"\n",
|
||||
" # Swap flag\n",
|
||||
" first = not first\n",
|
||||
" reason = \"Session complete\"\n",
|
||||
" except KeyboardInterrupt:\n",
|
||||
" print()\n",
|
||||
" reason = \"Keyboard interrupt\"\n",
|
||||
" except ValueError as e:\n",
|
||||
" logger.error(\"%s\" % e)\n",
|
||||
" reason = \"Wrong image dimensions? Fix nx, ny in config.\"\n",
|
||||
" except MemoryError as e:\n",
|
||||
" logger.error(\"Capture: Memory error %s\" % e)\n",
|
||||
" finally:\n",
|
||||
" # End capture\n",
|
||||
" logger.info(\"Capture: %s - Exiting\" % reason)\n",
|
||||
" camera.stop_video_capture()\n",
|
||||
" camera.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def compress(image_queue, z1, t1, z2, t2, nx, ny, nz, tend, path, device_id, cfg):\n",
|
||||
" \"\"\" compress: Aggregate nframes of observations into a single FITS file, with statistics.\n",
|
||||
" ImageHDU[0]: mean pixel value nframes (zmax)\n",
|
||||
" ImageHDU[1]: standard deviation of nframes (zstd)\n",
|
||||
" ImageHDU[2]: maximum pixel value of nframes (zmax)\n",
|
||||
" ImageHDU[3]: maximum pixel value frame number (znum)\n",
|
||||
" Also updates a [observations_path]/control/state.txt for interfacing with satttools/runsched and sattools/slewto\n",
|
||||
" \"\"\"\n",
|
||||
" # Force a restart\n",
|
||||
" controlpath = os.path.join(path, \"control\")\n",
|
||||
" if not os.path.exists(controlpath):\n",
|
||||
" try:\n",
|
||||
" os.makedirs(controlpath)\n",
|
||||
" except PermissionError:\n",
|
||||
" logger.error(\"Can not create control path directory: %s\" % controlpath)\n",
|
||||
" raise\n",
|
||||
" if not os.path.exists(os.path.join(controlpath, \"position.txt\")):\n",
|
||||
" with open(os.path.join(controlpath, \"position.txt\"), \"w\") as fp:\n",
|
||||
" fp.write(\"\\n\")\n",
|
||||
" \n",
|
||||
" with open(os.path.join(controlpath, \"state.txt\"), \"w\") as fp:\n",
|
||||
" fp.write(\"restart\\n\")\n",
|
||||
" try:\n",
|
||||
" # Start processing\n",
|
||||
" while True:\n",
|
||||
" # Check mount state\n",
|
||||
" restart = False\n",
|
||||
" with open(os.path.join(controlpath, \"state.txt\"), \"r\") as fp:\n",
|
||||
" line = fp.readline().rstrip()\n",
|
||||
" if line == \"restart\":\n",
|
||||
" restart = True\n",
|
||||
"\n",
|
||||
" # Restart\n",
|
||||
" if restart:\n",
|
||||
" # Log state\n",
|
||||
" with open(os.path.join(controlpath, \"state.txt\"), \"w\") as fp:\n",
|
||||
" fp.write(\"observing\\n\")\n",
|
||||
" # Get obsid\n",
|
||||
" trestart = time.gmtime()\n",
|
||||
" obsid = \"%s_%d/%s\" % (time.strftime(\"%Y%m%d\", trestart), device_id, time.strftime(\"%H%M%S\", trestart))\n",
|
||||
" filepath = os.path.join(path, obsid)\n",
|
||||
" logger.info(\"Storing files in %s\" % filepath)\n",
|
||||
" # Create output directory\n",
|
||||
" if not os.path.exists(filepath):\n",
|
||||
" try:\n",
|
||||
" os.makedirs(filepath)\n",
|
||||
" except PermissionError:\n",
|
||||
" logger.error(\"Can not create output directory: %s\" % filepath)\n",
|
||||
" raise\n",
|
||||
" # Get mount position\n",
|
||||
" with open(os.path.join(controlpath, \"position.txt\"), \"r\") as fp:\n",
|
||||
" line = fp.readline()\n",
|
||||
" with open(os.path.join(filepath, \"position.txt\"), \"w\") as fp:\n",
|
||||
" fp.write(line)\n",
|
||||
"\n",
|
||||
" # Wait for completed capture buffer to become available\n",
|
||||
" while (image_queue.qsize == 0):\n",
|
||||
" time.sleep(0.1)\n",
|
||||
" \n",
|
||||
" # Get next buffer # from the work queue\n",
|
||||
" proc_buffer = image_queue.get()\n",
|
||||
" logger.debug(\"Processing buffer %d\" % proc_buffer)\n",
|
||||
"\n",
|
||||
" # Log start time\n",
|
||||
" tstart = time.time()\n",
|
||||
"\n",
|
||||
" # Process first buffer\n",
|
||||
" if proc_buffer == 1:\n",
|
||||
" t = t1 \n",
|
||||
" z = z1\n",
|
||||
" elif proc_buffer == 2:\n",
|
||||
" t = t2\n",
|
||||
" z = z2\n",
|
||||
"\n",
|
||||
" # Format time\n",
|
||||
" nfd = \"%s.%03d\" % (time.strftime(\"%Y-%m-%dT%T\",\n",
|
||||
" time.gmtime(t[0])), int((t[0] - np.floor(t[0])) * 1000))\n",
|
||||
" t0 = Time(nfd, format='isot')\n",
|
||||
" dt = t - t[0]\n",
|
||||
"\n",
|
||||
" # Cast to 32 bit float\n",
|
||||
" z = z.astype(\"float32\")\n",
|
||||
" \n",
|
||||
" # Compute statistics\n",
|
||||
" zmax = np.max(z, axis=0)\n",
|
||||
" znum = np.argmax(z, axis=0)\n",
|
||||
" zs1 = np.sum(z, axis=0) - zmax\n",
|
||||
" zs2 = np.sum(z * z, axis=0) - zmax * zmax \n",
|
||||
" zavg = zs1 / float(nz - 1)\n",
|
||||
" zstd = np.sqrt((zs2 - zs1 * zavg) / float(nz - 2))\n",
|
||||
"\n",
|
||||
" # Convert to float and flip\n",
|
||||
" zmax = np.flipud(zmax.astype(\"float32\"))\n",
|
||||
" znum = np.flipud(znum.astype(\"float32\"))\n",
|
||||
" zavg = np.flipud(zavg.astype(\"float32\"))\n",
|
||||
" zstd = np.flipud(zstd.astype(\"float32\"))\n",
|
||||
"\n",
|
||||
" # Generate fits\n",
|
||||
" fname = \"%s.fits\" % nfd\n",
|
||||
"\n",
|
||||
" # Format header\n",
|
||||
" hdr = fits.Header()\n",
|
||||
" hdr['DATE-OBS'] = \"%s\" % nfd\n",
|
||||
" hdr['MJD-OBS'] = t0.mjd\n",
|
||||
" hdr['EXPTIME'] = dt[-1]-dt[0]\n",
|
||||
" hdr['NFRAMES'] = nz\n",
|
||||
" hdr['CRPIX1'] = float(nx)/2.0\n",
|
||||
" hdr['CRPIX2'] = float(ny)/2.0\n",
|
||||
" hdr['CRVAL1'] = 0.0\n",
|
||||
" hdr['CRVAL2'] = 0.0\n",
|
||||
" hdr['CD1_1'] = 1.0/3600.0\n",
|
||||
" hdr['CD1_2'] = 0.0\n",
|
||||
" hdr['CD2_1'] = 0.0\n",
|
||||
" hdr['CD2_2'] = 1.0/3600.0\n",
|
||||
" hdr['CTYPE1'] = \"RA---TAN\"\n",
|
||||
" hdr['CTYPE2'] = \"DEC--TAN\"\n",
|
||||
" hdr['CUNIT1'] = \"deg\"\n",
|
||||
" hdr['CUNIT2'] = \"deg\"\n",
|
||||
" hdr['CRRES1'] = 0.0\n",
|
||||
" hdr['CRRES2'] = 0.0\n",
|
||||
" hdr['EQUINOX'] = 2000.0\n",
|
||||
" hdr['RADECSYS'] = \"ICRS\"\n",
|
||||
" hdr['COSPAR'] = cfg.getint('Common', 'observer_cospar')\n",
|
||||
" hdr['OBSERVER'] = cfg.get('Common', 'observer_name')\n",
|
||||
" hdr['SITELONG'] = cfg.getfloat('Common', 'observer_lon')\n",
|
||||
" hdr['SITELAT'] = cfg.getfloat('Common', 'observer_lat')\n",
|
||||
" hdr['ELEVATIO'] = cfg.getfloat('Common', 'observer_height')\n",
|
||||
" if cfg.getboolean('Astrometry', 'tracking_mount'):\n",
|
||||
" hdr['TRACKED'] = 1\n",
|
||||
" else:\n",
|
||||
" hdr['TRACKED'] = 0\n",
|
||||
" for i in range(nz):\n",
|
||||
" hdr['DT%04d' % i] = dt[i]\n",
|
||||
" for i in range(10):\n",
|
||||
" hdr['DUMY%03d' % i] = 0.0\n",
|
||||
"\n",
|
||||
" # Write fits file\n",
|
||||
" hdu = fits.PrimaryHDU(data=np.array([zavg, zstd, zmax, znum]),\n",
|
||||
" header=hdr)\n",
|
||||
" hdu.writeto(os.path.join(filepath, fname))\n",
|
||||
" logger.info(\"Compressed %s in %.2f sec\" % (fname, time.time() - tstart))\n",
|
||||
"\n",
|
||||
" # Exit on end of capture\n",
|
||||
" if t[-1] > tend:\n",
|
||||
" break\n",
|
||||
" logger.debug(\"Processed buffer %d\" % proc_buffer)\n",
|
||||
" \n",
|
||||
" except KeyboardInterrupt:\n",
|
||||
" pass\n",
|
||||
" except MemoryError as e:\n",
|
||||
" logger.error(\"Compress: Memory error %s\" % e)\n",
|
||||
" finally:\n",
|
||||
" # Exiting\n",
|
||||
" logger.info(\"Exiting compress\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Main function"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if __name__ == '__main__':\n",
|
||||
" test_duration = 10\n",
|
||||
" testing = True\n",
|
||||
" live = False"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Process commandline options and parse configuration\n",
|
||||
" cfg = configparser.ConfigParser(inline_comment_prefixes=('#', ';'))\n",
|
||||
" conf_file = \"configuration.ini\"\n",
|
||||
" result = cfg.read([conf_file])\n",
|
||||
" if not result:\n",
|
||||
" print(\"Could not read config file: %s\\nExiting...\" % conf_file)\n",
|
||||
" sys.exit()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Setup logging\n",
|
||||
" logFormatter = logging.Formatter(\"%(asctime)s [%(threadName)-12.12s] \" +\n",
|
||||
" \"[%(levelname)-5.5s] %(message)s\")\n",
|
||||
" logger = logging.getLogger()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Generate directory\n",
|
||||
" path = os.path.abspath(cfg.get('Common', 'observations_path'))\n",
|
||||
" if not os.path.exists(path):\n",
|
||||
" try:\n",
|
||||
" os.makedirs(path)\n",
|
||||
" except PermissionError:\n",
|
||||
" logger.error(\"Can not create observations_path: %s\" % path)\n",
|
||||
" sys.exit()\n",
|
||||
" fileHandler = logging.FileHandler(os.path.join(path, \"acquire.log\"))\n",
|
||||
" fileHandler.setFormatter(logFormatter)\n",
|
||||
" logger.addHandler(fileHandler)\n",
|
||||
" consoleHandler = logging.StreamHandler(sys.stdout)\n",
|
||||
" consoleHandler.setFormatter(logFormatter)\n",
|
||||
" logger.addHandler(consoleHandler)\n",
|
||||
" logger.setLevel(logging.DEBUG)\n",
|
||||
" logger.info(\"Using config: %s\" % conf_file)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Testing mode\n",
|
||||
" logger.info(\"Test mode: %s\" % testing)\n",
|
||||
" if (testing):\n",
|
||||
" logger.info(\"Test duration: %ds\" % test_duration)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Live mode\n",
|
||||
" #live = True if args.live else False\n",
|
||||
" logger.info(\"Live mode: %s\" % live)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Get camera type\n",
|
||||
" camera_type = cfg.get('Camera', 'camera_type')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Get device id\n",
|
||||
" device_id = cfg.getint(camera_type, 'device_id')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Current time\n",
|
||||
" tnow = Time.now()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Set location\n",
|
||||
" loc = EarthLocation(lat=cfg.getfloat('Common', 'observer_lat')*u.deg,\n",
|
||||
" lon=cfg.getfloat('Common', 'observer_lon')*u.deg,\n",
|
||||
" height=cfg.getfloat('Common', 'observer_height')*u.m)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" if not testing:\n",
|
||||
" # Reference altitudes\n",
|
||||
" refalt_set = cfg.getfloat('Control', 'alt_sunset')*u.deg\n",
|
||||
" refalt_rise = cfg.getfloat('Control', 'alt_sunrise')*u.deg\n",
|
||||
"\n",
|
||||
" # FIXME: The following will fail without internet access\n",
|
||||
" # due to failure to download finals2000A.all\n",
|
||||
" # Get sunrise and sunset times\n",
|
||||
" state, tset, trise = get_sunset_and_sunrise(tnow, loc, refalt_set, refalt_rise)\n",
|
||||
"\n",
|
||||
" # Start/end logic\n",
|
||||
" if state == \"sun never rises\":\n",
|
||||
" logger.info(\"The sun never rises. Exiting program.\")\n",
|
||||
" sys.exit()\n",
|
||||
" elif state == \"sun never sets\":\n",
|
||||
" logger.info(\"The sun never sets.\")\n",
|
||||
" tend = tnow+24*u.h\n",
|
||||
" elif (trise < tset):\n",
|
||||
" logger.info(\"The sun is below the horizon.\")\n",
|
||||
" tend = trise\n",
|
||||
" elif (trise >= tset):\n",
|
||||
" dt = np.floor((tset-tnow).to(u.s).value)\n",
|
||||
" logger.info(\"The sun is above the horizon. Sunset at %s.\"\n",
|
||||
" % tset.isot)\n",
|
||||
" logger.info(\"Waiting %.0f seconds.\" % dt)\n",
|
||||
" tend = trise\n",
|
||||
" try:\n",
|
||||
" time.sleep(dt)\n",
|
||||
" except KeyboardInterrupt:\n",
|
||||
" sys.exit()\n",
|
||||
" else:\n",
|
||||
" tend = tnow + test_duration*u.s\n",
|
||||
" logger.info(\"Starting data acquisition\")\n",
|
||||
" logger.info(\"Acquisition will end after \"+tend.isot)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Get settings\n",
|
||||
" nx = cfg.getint(camera_type, 'nx')\n",
|
||||
" ny = cfg.getint(camera_type, 'ny')\n",
|
||||
" nz = cfg.getint(camera_type, 'nframes')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Initialize arrays\n",
|
||||
" z1base = multiprocessing.Array(ctypes.c_uint8, nx*ny*nz)\n",
|
||||
" z1 = np.ctypeslib.as_array(z1base.get_obj()).reshape(nz, ny, nx)\n",
|
||||
" t1base = multiprocessing.Array(ctypes.c_double, nz)\n",
|
||||
" t1 = np.ctypeslib.as_array(t1base.get_obj())\n",
|
||||
" z2base = multiprocessing.Array(ctypes.c_uint8, nx*ny*nz)\n",
|
||||
" z2 = np.ctypeslib.as_array(z2base.get_obj()).reshape(nz, ny, nx)\n",
|
||||
" t2base = multiprocessing.Array(ctypes.c_double, nz)\n",
|
||||
" t2 = np.ctypeslib.as_array(t2base.get_obj())\n",
|
||||
" image_queue = multiprocessing.Queue()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Set processes\n",
|
||||
" pcompress = multiprocessing.Process(target=compress,\n",
|
||||
" args=(image_queue, z1, t1, z2, t2, nx, ny,\n",
|
||||
" nz, tend.unix, path, device_id, cfg))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" if camera_type == \"PI\":\n",
|
||||
" pcapture = multiprocessing.Process(target=capture_pi,\n",
|
||||
" args=(image_queue, z1, t1, z2, t2,\n",
|
||||
" nx, ny, nz, tend.unix, device_id, live, cfg))\n",
|
||||
"\n",
|
||||
" elif camera_type == \"CV2\":\n",
|
||||
" pcapture = multiprocessing.Process(target=capture_cv2,\n",
|
||||
" args=(image_queue, z1, t1, z2, t2,\n",
|
||||
" nx, ny, nz, tend.unix, device_id, live, cfg))\n",
|
||||
"\n",
|
||||
" elif camera_type == \"ASI\":\n",
|
||||
" pcapture = multiprocessing.Process(target=capture_asi,\n",
|
||||
" args=(image_queue, z1, t1, z2, t2,\n",
|
||||
" nx, ny, nz, tend.unix, device_id, live, cfg))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Start\n",
|
||||
" pcapture.start()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" pcompress.start()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # End\n",
|
||||
" try:\n",
|
||||
" pcapture.join()\n",
|
||||
" pcompress.join()\n",
|
||||
" except (KeyboardInterrupt, ValueError):\n",
|
||||
" time.sleep(0.1) # Allow a little time for a graceful exit\n",
|
||||
" except MemoryError as e:\n",
|
||||
" logger.error(\"Memory error %s\" % e)\n",
|
||||
" finally:\n",
|
||||
" pcapture.terminate()\n",
|
||||
" pcompress.terminate()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # Release device\n",
|
||||
"# if live is True:\n",
|
||||
"# cv2.destroyAllWindows()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"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.10.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
Loading…
Reference in New Issue