def command(self, cmd): """ Run gphoto2 command """ # Test to see if there is a running command already if self._proc and self._proc.poll(): raise error.InvalidCommand("Command already running") else: # Build the command. run_cmd = [self._gphoto2, '--port', self.port] run_cmd.extend(listify(cmd)) self.logger.debug("gphoto2 command: {}".format(run_cmd)) try: self._proc = subprocess.Popen(run_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=False) except OSError as e: raise error.InvalidCommand( "Can't send command to gphoto2. {} \t {}".format( e, run_cmd)) except ValueError as e: raise error.InvalidCommand( "Bad parameters to gphoto2. {} \t {}".format(e, run_cmd)) except Exception as e: raise error.PanError(e)
def cr2_to_pgm(cr2_fname, pgm_fname=None, overwrite=True, *args, **kwargs): # pragma: no cover """ Convert CR2 file to PGM Converts a raw Canon CR2 file to a netpbm PGM file via `dcraw`. Assumes `dcraw` is installed on the system Note: This is a blocking call Arguments: cr2_fname {str} -- Name of CR2 file to convert **kwargs {dict} -- Additional keywords to pass to script Keyword Arguments: pgm_fname {str} -- Name of PGM file to output, if None (default) then use same name as CR2 (default: {None}) dcraw {str} -- Path to installed `dcraw` (default: {'dcraw'}) overwrite {bool} -- A bool indicating if existing PGM should be overwritten (default: {True}) Returns: str -- Filename of PGM that was created """ verbose = kwargs.get('verbose', False) dcraw = shutil.which('dcraw') if dcraw is None: raise error.InvalidCommand('dcraw not found') if pgm_fname is None: pgm_fname = cr2_fname.replace('.cr2', '.pgm') if os.path.exists(pgm_fname) and not overwrite: if verbose: print("PGM file exists, returning existing file: {}".format( pgm_fname)) else: try: # Build the command for this file command = '{} -t 0 -D -4 {}'.format(dcraw, cr2_fname) cmd_list = command.split() if verbose: print("PGM Conversion command: \n {}".format(cmd_list)) # Run the command if subprocess.check_call(cmd_list) == 0: if verbose: print("PGM Conversion command successful") except subprocess.CalledProcessError as err: raise error.InvalidSystemCommand( msg="File: {} \n err: {}".format(cr2_fname, err)) return pgm_fname
def _make_pretty_from_cr2(fname, title=None, **kwargs): script_name = shutil.which('cr2-to-jpg') cmd = [script_name, fname] if title: cmd.append(title) logger.debug(f'Pretty cr2 command: {cmd!r}') try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) logger.debug(f'Pretty CR2 output={output!r}') except subprocess.CalledProcessError as e: raise error.InvalidCommand( f"Error executing {script_name}: {e.output!r}\nCommand: {cmd}") return fname.replace('cr2', 'jpg')
def _make_pretty_from_cr2(fname, title=None, timeout=15, **kwargs): verbose = kwargs.get('verbose', False) script_name = shutil.which('cr2-to-jpg') cmd = [script_name, fname] if title: cmd.append(title) if verbose: print(cmd) try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) if verbose: print(output) except Exception as e: raise error.InvalidCommand("Error executing gphoto2: {!r}\nCommand: {}".format(e, cmd)) return fname.replace('cr2', 'jpg')
def get_wcsinfo(fits_fname, **kwargs): """Returns the WCS information for a FITS file. Uses the `wcsinfo` astrometry.net utility script to get the WCS information from a plate-solved file. Args: fits_fname ({str}): Name of a FITS file that contains a WCS. **kwargs: Args that can be passed to wcsinfo. Returns: dict: Output as returned from `wcsinfo`. Raises: error.InvalidCommand: Raised if `wcsinfo` is not found (part of astrometry.net) """ assert os.path.exists(fits_fname), warn(f"No file exists at: {fits_fname}") wcsinfo = shutil.which('wcsinfo') if wcsinfo is None: raise error.InvalidCommand('wcsinfo not found') run_cmd = [wcsinfo, fits_fname] if fits_fname.endswith('.fz'): run_cmd.append('-e') run_cmd.append('1') proc = subprocess.Popen(run_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) try: output, errs = proc.communicate(timeout=5) except subprocess.TimeoutExpired: # pragma: no cover proc.kill() output, errs = proc.communicate() unit_lookup = { 'crpix0': u.pixel, 'crpix1': u.pixel, 'crval0': u.degree, 'crval1': u.degree, 'cd11': (u.deg / u.pixel), 'cd12': (u.deg / u.pixel), 'cd21': (u.deg / u.pixel), 'cd22': (u.deg / u.pixel), 'imagew': u.pixel, 'imageh': u.pixel, 'pixscale': (u.arcsec / u.pixel), 'orientation': u.degree, 'ra_center': u.degree, 'dec_center': u.degree, 'orientation_center': u.degree, 'ra_center_h': u.hourangle, 'ra_center_m': u.minute, 'ra_center_s': u.second, 'dec_center_d': u.degree, 'dec_center_m': u.minute, 'dec_center_s': u.second, 'fieldarea': (u.degree * u.degree), 'fieldw': u.degree, 'fieldh': u.degree, 'decmin': u.degree, 'decmax': u.degree, 'ramin': u.degree, 'ramax': u.degree, 'ra_min_merc': u.degree, 'ra_max_merc': u.degree, 'dec_min_merc': u.degree, 'dec_max_merc': u.degree, 'merc_diff': u.degree, } wcs_info = {} for line in output.split('\n'): try: k, v = line.split(' ') try: v = float(v) except Exception: pass wcs_info[k] = float(v) * unit_lookup.get(k, 1) except ValueError: pass # print("Error on line: {}".format(line)) wcs_info['wcs_file'] = fits_fname return wcs_info
def solve_field(fname, timeout=15, solve_opts=None, **kwargs): """ Plate solves an image. Args: fname(str, required): Filename to solve in .fits extension. timeout(int, optional): Timeout for the solve-field command, defaults to 60 seconds. solve_opts(list, optional): List of options for solve-field. verbose(bool, optional): Show output, defaults to False. """ verbose = kwargs.get('verbose', False) if verbose: print("Entering solve_field") solve_field_script = shutil.which('panoptes-solve-field') if solve_field_script is None: # pragma: no cover raise error.InvalidSystemCommand( "Can't find panoptes-solve-field: {}".format(solve_field_script)) # Add the options for solving the field if solve_opts is not None: options = solve_opts else: options = [ '--guess-scale', '--cpulimit', str(timeout), '--no-verify', '--no-plots', '--crpix-center', '--match', 'none', '--corr', 'none', '--wcs', 'none', '--downsample', '4', ] if kwargs.get('overwrite', False): options.append('--overwrite') if kwargs.get('skip_solved', False): options.append('--skip-solved') if 'ra' in kwargs: options.append('--ra') options.append(str(kwargs.get('ra'))) if 'dec' in kwargs: options.append('--dec') options.append(str(kwargs.get('dec'))) if 'radius' in kwargs: options.append('--radius') options.append(str(kwargs.get('radius'))) if fname.endswith('.fz'): options.append('--extension=1') cmd = [solve_field_script] + options + [fname] if verbose: print("Cmd:", cmd) try: proc = subprocess.Popen(cmd, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError as e: raise error.InvalidCommand( "Can't send command to panoptes-solve-field: {} \t {}".format( e, cmd)) except ValueError as e: raise error.InvalidCommand( "Bad parameters to solve_field: {} \t {}".format(e, cmd)) except Exception as e: raise error.PanError("Timeout on plate solving: {}".format(e)) if verbose: print("Returning proc from solve_field") return proc