Add stvid notebook draft

jupyter
Jeff Moe 2022-09-10 10:27:31 -06:00
parent 5afce3ed7e
commit 665feef2dc
2 changed files with 892 additions and 1 deletions

View File

@ -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

890
stvid.ipynb 100644
View File

@ -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
}