def polar_rotation(pocs, exptime=30, base_dir=None, **kwargs): assert base_dir is not None, print_warning("base_dir cannot be empty") mount = pocs.observatory.mount print_info('Performing polar rotation test') pocs.say('Performing polar rotation test') mount.slew_to_home(blocking=True) print_info('At home position, taking {} sec exposure'.format(exptime)) pocs.say('At home position, taking {} sec exposure'.format(exptime)) cam = pocs.observatory.primary_camera analyze_fn = f'{base_dir}/pole_{cam.name.lower()}.cr2' cam_event = cam.take_exposure(seconds=exptime, filename=analyze_fn) while cam_event.is_set() is False: time.sleep(2) try: img_utils.make_pretty_image(analyze_fn, title='Alignment Test - Celestial Pole', link_path=os.path.expandvars('$PANDIR/images/latest.jpg'), primary=True) except AssertionError: print_warning(f"Can't make image for {analyze_fn}") pocs.say(f"Can't make image for {analyze_fn}") return analyze_fn
def test_make_pretty_image(solved_fits_file, tiny_fits_file, save_environ): # Make a dir and put test image files in it. with tempfile.TemporaryDirectory() as tmpdir: # TODO Add a small CR2 file to our sample image files. # Can't operate on a non-existent files. with pytest.warns(UserWarning, match="File doesn't exist"): assert not img_utils.make_pretty_image('Foobar') # Can handle the fits file, and creating the images dir for linking # the latest image. imgdir = os.path.join(tmpdir, 'images') assert not os.path.isdir(imgdir) os.makedirs(imgdir, exist_ok=True) link_path = os.path.join(tmpdir, 'latest.jpg') pretty = img_utils.make_pretty_image(solved_fits_file, link_path=link_path) assert pretty assert os.path.isfile(pretty) assert os.path.isdir(imgdir) assert link_path == pretty os.remove(link_path) os.rmdir(imgdir) # Try again, but without link_path. pretty = img_utils.make_pretty_image(tiny_fits_file, title='some text') assert pretty assert os.path.isfile(pretty) assert not os.path.isdir(imgdir)
def test_make_pretty_image_cr2_fail(): with tempfile.TemporaryDirectory() as tmpdir: tmpfile = os.path.join(tmpdir, 'bad.cr2') with open(tmpfile, 'w') as f: f.write('not an image file') with pytest.raises(error.InvalidCommand): img_utils.make_pretty_image(tmpfile, title='some text') with pytest.raises(error.InvalidCommand): img_utils.make_pretty_image(tmpfile)
def test_make_pretty_image_cr2(cr2_file, tmpdir): link_path = str(tmpdir.mkdir('images').join('latest.jpg')) pretty_path = img_utils.make_pretty_image(cr2_file, title='CR2 Test', image_type='cr2', link_path=link_path) assert os.path.exists(pretty_path) assert pretty_path == link_path
def test_make_pretty_image_cr2(cr2_file): link_path = os.path.expandvars('$PANDIR/images/latest.jpg') pretty_path = img_utils.make_pretty_image(cr2_file, title='CR2 Test', image_type='cr2', link_path=link_path) assert os.path.exists(pretty_path) assert pretty_path == link_path
def test_make_pretty_image(solved_fits_file, tiny_fits_file, save_environ): # Not a valid file type (can't automatically handle .fits.fz files). with pytest.warns(UserWarning, match='File must be'): assert not img_utils.make_pretty_image(solved_fits_file) # Make a dir and put test image files in it. with tempfile.TemporaryDirectory() as tmpdir: fz_file = os.path.join(tmpdir, os.path.basename(solved_fits_file)) fits_file = os.path.join(tmpdir, os.path.basename(tiny_fits_file)) # TODO Add a small CR2 file to our sample image files. # Can't operate on a non-existent files. with pytest.warns(UserWarning, match="File doesn't exist"): assert not img_utils.make_pretty_image(fits_file) # Copy the files. shutil.copy(solved_fits_file, tmpdir) shutil.copy(tiny_fits_file, tmpdir) # Not a valid file type (can't automatically handle fits.fz files). with pytest.warns(UserWarning): assert not img_utils.make_pretty_image(fz_file) # Can handle the fits file, and creating the images dir for linking # the latest image. imgdir = os.path.join(tmpdir, 'images') assert not os.path.isdir(imgdir) os.environ['PANDIR'] = tmpdir pretty = img_utils.make_pretty_image(fits_file, link_latest=True) assert pretty assert os.path.isfile(pretty) assert os.path.isdir(imgdir) latest = os.path.join(imgdir, 'latest.jpg') assert os.path.isfile(latest) os.remove(latest) os.rmdir(imgdir) # Try again, but without link_latest. pretty = img_utils.make_pretty_image(fits_file, title='some text') assert pretty assert os.path.isfile(pretty) assert not os.path.isdir(imgdir)
def mount_rotation(pocs, base_dir=None, include_west=False, **kwargs): mount = pocs.observatory.mount print_info("Doing rotation test") pocs.say("Doing rotation test") mount.slew_to_home(blocking=True) exptime = 25 mount.move_direction(direction='west', seconds=11) # Start exposing on cameras for direction in ['east', 'west']: if include_west is False and direction == 'west': continue print_info(f"Rotating to {direction}") pocs.say(f"Rotating to {direction}") cam = pocs.observatory.primary_camera rotate_fn = f'{base_dir}/rotation_{direction}_{cam.name.lower()}.cr2' cam_event = cam.take_exposure(seconds=exptime, filename=rotate_fn) # Move mount mount.move_direction(direction=direction, seconds=21) while cam_event.is_set() is False: time.sleep(2) # Get exposures try: img_utils.make_pretty_image(rotate_fn, title=f'Alignment Test - Rotate {direction}', link_path=os.path.expandvars('$PANDIR/images/latest.jpg'), primary=True) except AssertionError: print_warning(f"Can't make image for {rotate_fn}") pocs.say(f"Can't make image for {rotate_fn}") return rotate_fn
def process_exposure(self, metadata, observation_event, compress_fits=None, record_observations=None, make_pretty_images=None): """ Processes the exposure. Performs the following steps: 1. First checks to make sure that the file exists on the file system. 2. Calls `_process_fits` with the filename and info, which is specific to each camera. 3. Makes pretty images if requested. 4. Records observation metadata if requested. 5. Compresses FITS files if requested. 6. Sets the observation_event. If the camera is a primary camera, extract the jpeg image and save metadata to database `current` collection. Saves metadata to `observations` collection for all images. Args: metadata (dict): Header metadata saved for the image observation_event (threading.Event): An event that is set signifying that the camera is done with this exposure compress_fits (bool or None): If FITS files should be fpacked into .fits.fz. If None (default), checks the `observations.compress_fits` config-server key. record_observations (bool or None): If observation metadata should be saved. If None (default), checks the `observations.record_observations` config-server key. make_pretty_images (bool or None): If should make a jpg from raw image. If None (default), checks the `observations.make_pretty_images` config-server key. Raises: FileNotFoundError: If the FITS file isn't at the specified location. """ # Wait for exposure to complete. Timeout handled by exposure thread. while self.is_exposing: time.sleep(1) self.logger.debug( f'Starting exposure processing for {observation_event}') if compress_fits is None: compress_fits = self.get_config('observations.compress_fits', default=False) if make_pretty_images is None: make_pretty_images = self.get_config( 'observations.make_pretty_images', default=False) image_id = metadata['image_id'] seq_id = metadata['sequence_id'] file_path = metadata['file_path'] exptime = metadata['exptime'] field_name = metadata['field_name'] # Make sure image exists. if not os.path.exists(file_path): observation_event.set() raise FileNotFoundError( f"Expected image at file_path={file_path!r} does not exist or " + "cannot be accessed, cannot process.") self.logger.debug(f'Starting FITS processing for {file_path}') file_path = self._process_fits(file_path, metadata) self.logger.debug(f'Finished FITS processing for {file_path}') # TODO make this async and take it out of camera. if make_pretty_images: try: image_title = f'{field_name} [{exptime}s] {seq_id}' self.logger.debug( f"Making pretty image for file_path={file_path!r}") link_path = None if metadata['is_primary']: # This should be in the config somewhere. link_path = os.path.expandvars('$PANDIR/images/latest.jpg') img_utils.make_pretty_image(file_path, title=image_title, link_path=link_path) except Exception as e: # pragma: no cover self.logger.warning( f'Problem with extracting pretty image: {e!r}') metadata['exptime'] = get_quantity_value(metadata['exptime'], unit='seconds') if record_observations: self.logger.debug(f"Adding current observation to db: {image_id}") self.db.insert_current('observations', metadata) if compress_fits: self.logger.debug(f'Compressing file_path={file_path!r}') compressed_file_path = fits_utils.fpack(file_path) self.logger.debug(f'Compressed {compressed_file_path}') # Mark the event as done observation_event.set()