예제 #1
0
    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)
예제 #2
0
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()
예제 #3
0
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()
예제 #4
0
    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))
예제 #5
0
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
예제 #6
0
    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)
예제 #7
0
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
예제 #8
0
    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))
예제 #9
0
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
예제 #10
0
            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