def doOpen(self): """Open the ds9 window (if necessary). Raise OSError or RuntimeError on failure, even if doRaise is False. """ if self.isOpen(): return # We want to fork ds9. This is possible with os.fork, but # it doesn't work on Windows. At present Sherpa does not # run on Windows, so it is not a serious problem, but it is # not clear if it is an acceptable, or sensible, option. # p = _Popen( args=('ds9', '-title', self.template, '-port', "0"), cwd=None, close_fds=True, stdin=None, stdout=None, stderr=None ) startTime = time.time() while True: time.sleep(_OpenCheckInterval) if self.isOpen(): # Trick to stop a ResourceWarning warning to be created when # running sherpa/tests/test_image.py # # Adapted from https://hg.python.org/cpython/rev/72946937536e p.returncode = 0 return if time.time() - startTime > _MaxOpenTime: raise RuntimeErr('nowin', self.template)
def xpaset(cmd, data=None, dataFunc=None, template=_DefTemplate, doRaise=True): """Executes a simple xpaset command: xpaset -p <template> <cmd> or else feeds data to: xpaset <template> <cmd> The command must not return any output for normal completion. Inputs: - cmd command to execute - data data to write to xpaset's stdin; ignored if dataFunc specified. If data[-1] is not \n then a final \n is appended. - dataFunc a function that takes one argument, a file-like object, and writes data to that file. If specified, data is ignored. Warning: if a final \n is needed, dataFunc must supply it. - template xpa template; can be the ds9 window title (as specified in the -title command-line option) host:port, etc. - doRaise if True, raise RuntimeError if there is a communications error, else issue a UserWarning warning Raises RuntimeError or issues a warning (depending on doRaise) if anything is written to stdout or stderr. """ # Would be better to make a sequence rather than have to quote arguments if data or dataFunc: fullCmd = 'xpaset %s "%s"' % (template, cmd) else: fullCmd = 'xpaset -p %s "%s"' % (template, cmd) with _Popen(args=fullCmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as p: try: try: data = bytearray(data, "UTF-8") except: pass if data: p.stdin.write(data) if data[-1] != b'\n': p.stdin.write(b'\n') p.stdin.close() reply = p.stdout.read() if reply: fullErrMsg = "%r failed: %s" % (fullCmd, reply.strip()) if doRaise: raise RuntimeErr('cmdfail', fullCmd, reply.strip()) else: warnings.warn(fullErrMsg) finally: p.stdin.close() # redundant p.stdout.close()
def xpaget(cmd, template=_DefTemplate, doRaise=True): """Executes a simple xpaget command: xpaset -p <template> <cmd> returning the reply. Inputs: - cmd command to execute; may be a string or a list - template xpa template; can be the ds9 window title (as specified in the -title command-line option) host:port, etc. - doRaise if True, raise RuntimeError if there is a communications error, else issue a UserWarning warning Raises RuntimeError or issues a warning (depending on doRaise) if anything is written to stderr. """ # Would be better to make a sequence rather than have to quote arguments fullCmd = 'xpaget %s "%s"' % ( template, cmd, ) with _Popen(args=fullCmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p: try: p.stdin.close() errMsg = p.stderr.read() if errMsg: fullErrMsg = "%r failed: %s" % (fullCmd, errMsg) if doRaise: raise RuntimeErr('cmdfail', fullCmd, errMsg) else: warnings.warn(fullErrMsg) return_value = p.stdout.read() if six.PY2: return return_value else: return return_value.decode() finally: p.stdout.close() p.stderr.close()
def showFITSFile(self, fname, **kargs): """Display a fits file in ds9. Inputs: - fname name of file (including path information, if necessary) kargs: see Extra Keyword Arguments in the module doc string for information. Keywords that specify array info (see doc for showBinFile for the list) must NOT be included. """ filepath = _expandPath(fname) self.xpaset(cmd='file "%s"' % filepath) # remove array info keywords from kargs; we compute all that arrKeys = _splitDict(kargs, _ArrayKeys) if arrKeys: raise RuntimeErr('badarr', arrKeys.keys()) for keyValue in six.iteritems(kargs): self.xpaset(cmd=' '.join(keyValue))
def _findUnixApp(appName): """Search PATH to find first directory that has the application. Return the path if found. Raise RuntimeError if not found. """ try: appPath = '' for path in os.environ['PATH'].split(':'): if os.access(path + '/' + appName, os.X_OK): appPath = path break if appPath == '' or not appPath.startswith("/"): raise RuntimeErr('notonpath', appName) except: raise return appPath
def doOpen(self): """Open the ds9 window (if necessary). Raise OSError or RuntimeError on failure, even if doRaise is False. """ if self.isOpen(): return _Popen( args=('ds9', '-title', self.template, '-port', "0"), cwd=None, ) startTime = time.time() while True: time.sleep(_OpenCheckInterval) if self.isOpen(): return if time.time() - startTime > _MaxOpenTime: raise RuntimeErr('nowin', self.template)
def setup(doRaise=True, debug=False): """Search for xpa and ds9 and set globals accordingly. Return None if all is well, else return an error string. The return value is also saved in global variable _SetupError. Sets globals: - _SetupError same value as returned - _Popen subprocess.Popen, if ds9 and xpa found, else a variant that searches for ds9 and xpa first and then runs subprocess.Popen if found else raises an exception This permits the user to install ds9 and xpa and use this module without reloading it """ global _SetupError, _Popen, _ex _SetupError = None try: ds9Dir, xpaDir = _findDS9AndXPA() if debug: print("ds9Dir=%r\npaDir=%r" % (ds9Dir, xpaDir)) except (SystemExit, KeyboardInterrupt): raise except Exception as e: _ex = e _SetupError = "DS9Win unusable: %s" % (e, ) ds9Dir = xpaDir = None if _SetupError: class _Popen(subprocess.Popen): def __init__(self, *args, **kargs): setup(doRaise=True) subprocess.Popen.__init__(self, *args, **kargs) if doRaise: raise RuntimeErr('badwin', _ex) else: _Popen = subprocess.Popen return _SetupError
def showArray(self, arr, **kargs): """Display a 2-d or 3-d grayscale integer numarray arrays. 3-d images are displayed as data cubes, meaning one can view a single z at a time or play through them as a movie, that sort of thing. Inputs: - arr: a numarray array; must be 2-d or 3-d: 2-d arrays have index order (y, x) 3-d arrays are loaded as a data cube index order (z, y, x) kargs: see Extra Keyword Arguments in the module doc string for information. Keywords that specify array info (see doc for showBinFile for the list) are ignored, because array info is determined from the array itself. Data types: - UInt8, Int16, Int32 and floating point types sent unmodified. - All other integer types are converted before transmission. - Complex types are rejected. Raises ValueError if arr's elements are not some kind of integer. Raises RuntimeError if ds9 is not running or returns an error message. """ if not hasattr(arr, "dtype") or not hasattr(arr, "astype"): arr = np.array(arr) if np.iscomplexobj(arr): raise TypeErr('nocomplex') ndim = arr.ndim if ndim not in (2, 3): raise RuntimeErr('only2d3d') dimNames = ["z", "y", "x"][3 - ndim:] # if necessary, convert array type cnvType = _CnvDict.get(arr.dtype.type) if cnvType: # print "converting array from %s to %s" % (arr.type(), cnvType) arr = arr.astype(cnvType) # determine byte order of array # First check if array endianness is not native--if # not, use the nonnative endianness # If the byteorder is native, then use the system # endianness if arr.dtype.byteorder == '>': isBigendian = True elif arr.dtype.byteorder == '<': isBigendian = False else: if sys.byteorder == 'big': isBigendian = True else: isBigendian = False # compute bits/pix; ds9 uses negative values for floating values bitsPerPix = arr.itemsize * 8 # if np.issubclass_(arr.dtype.type, float): if arr.dtype.type in _FloatTypes: # array is float; use negative value bitsPerPix = -bitsPerPix # remove array info keywords from kargs; we compute all that _splitDict(kargs, _ArrayKeys) # generate array info keywords; note that numarray # 2-d images are in order [y, x] # 3-d images are in order [z, y, x] arryDict = {} for axis, size in zip(dimNames, arr.shape): arryDict["%sdim" % axis] = size arryDict["bitpix"] = bitsPerPix if isBigendian: arryDict["arch"] = 'bigendian' else: arryDict["arch"] = 'littleendian' self.xpaset( cmd='array [%s]' % (_formatOptions(arryDict), ), data=arr.tobytes(), ) for keyValue in six.iteritems(kargs): self.xpaset(cmd=' '.join(keyValue))
def setup(doRaise=True, debug=False): """Search for xpa and ds9 and set globals accordingly. Return None if all is well, else return an error string. The return value is also saved in global variable _SetupError. Sets globals: - _SetupError same value as returned - _Popen subprocess.Popen, if ds9 and xpa found, else a variant that searches for ds9 and xpa first and then runs subprocess.Popen if found else raises an exception This permits the user to install ds9 and xpa and use this module without reloading it """ global _SetupError, _Popen, _ex _SetupError = None try: ds9Dir, xpaDir = _findDS9AndXPA() if debug: print("ds9Dir=%r\npaDir=%r" % (ds9Dir, xpaDir)) except (SystemExit, KeyboardInterrupt): raise except Exception as e: _ex = e _SetupError = "DS9Win unusable: %s" % (e, ) ds9Dir = xpaDir = None if _SetupError: class _Popen(subprocess.Popen): def __init__(self, *args, **kargs): setup(doRaise=True) subprocess.Popen.__init__(self, *args, **kargs) if doRaise: raise RuntimeErr('badwin', _ex) elif sys.version_info < (3, 2): class _Popen(subprocess.Popen): # Add in the necessary methods so it can be used as a # context manager (for Python 3.1 and earlier). # # See https://stackoverflow.com/a/30421047 # def __enter__(self): return self def __exit__(self, type, value, traceback): if self.stdout: self.stdout.close() if self.stderr: self.stderr.close() if self.stdin: self.stdin.close() # Wait for the process to terminate, to avoid zombies. self.wait() else: _Popen = subprocess.Popen return _SetupError
print "ds9Dir=%r\npaDir=%r" % (ds9Dir, xpaDir) except (SystemExit, KeyboardInterrupt): raise except Exception, e: _ex = e _SetupError = "DS9Win unusable: %s" % (e,) ds9Dir = xpaDir = None if _SetupError: class _Popen(subprocess.Popen): def __init__(self, *args, **kargs): setup(doRaise=True) subprocess.Popen.__init__(self, *args, **kargs) if doRaise: raise RuntimeErr('badwin', _ex) else: _Popen = subprocess.Popen return _SetupError errStr = setup(doRaise=True, debug=False) if errStr: warnings.warn(errStr) _ArrayKeys = ("dim", "dims", "xdim", "ydim", "zdim", "bitpix", "skip", "arch") _DefTemplate = "sherpa" _OpenCheckInterval = 0.2 # seconds _MaxOpenTime = 60.0 # seconds