def getDevice(self, device=None): """Starting with stdgraph, drill until a device is found in the graphcap or isn't""" if not device: device = iraf.envget("stdgraph", "") graphcap = getGraphcap() # protect against circular definitions devstr = device tried = {devstr: None} while devstr not in graphcap: pdevstr = devstr devstr = iraf.envget(pdevstr, "") if not devstr: raise IrafError("No entry found " f"for specified stdgraph device `{device}'") elif devstr in tried: # track back through circular definition s = [devstr] next = pdevstr while next and (next != devstr): s.append(next) next = tried[next] if next: s.append(next) s.reverse() raise IrafError( "Circular definition in graphcap for device\n" + ' -> '.join(s)) else: tried[devstr] = pdevstr return devstr
def set(self, arg=None): """Set wcs from metacode stream""" init_wcs_sizes() if arg is None: # commit immediately if arg=None self.wcs = _setWCSDefault() self.pending = None # print "Default WCS set for plotting window." return # Even in v2.14, arg[] elements are of type int64, but here we cast to # int16 and assume we lose no data wcsStruct = arg[1:].astype(numpy.int16) # Every time set() is called, reset the wcs sizes. We may be plotting # with old-compiled 32-bit tasks, then with new-compiled 32-bit tasks, # then with 64-bit tasks, all within the same PyRAF session. init_wcs_sizes(forceResetTo=int(arg[0] / (1. * WCS_SLOTS))) # Check that eveything is sized as expected if arg[0] != len(wcsStruct): raise IrafError( "Inconsistency in length of WCS graphics struct: " + str(arg[0])) if len(wcsStruct) != _WCS_RECORD_SIZE * WCS_SLOTS: raise IrafError("Unexpected length of WCS graphics struct: " + str(len(wcsStruct))) # Read through the input to populate self.pending SZ = 2 if _IRAF64BIT: SZ = 4 self.pending = [None] * WCS_SLOTS for i in range(WCS_SLOTS): record = wcsStruct[_WCS_RECORD_SIZE * i:_WCS_RECORD_SIZE * (i + 1)] # read 8 4-byte floats from beginning of record fvals = numpy.frombuffer(record[:8 * SZ].tobytes(), numpy.float32) if _IRAF64BIT: # seems to send an extra 0-valued int32 after each 4 bytes fvalsView = fvals.reshape(-1, 2).transpose() if fvalsView[1].sum() != 0: raise IrafError("Assumed WCS float padding is non-zero") fvals = fvalsView[0] # read 3 4-byte ints after that ivals = numpy.frombuffer(record[8 * SZ:11 * SZ].tobytes(), numpy.int32) if _IRAF64BIT: # seems to send an extra 0-valued int32 after each 4 bytes ivalsView = ivals.reshape(-1, 2).transpose() if ivalsView[1].sum() != 0: raise IrafError("Assumed WCS int padding is non-zero") ivals = ivalsView[0] self.pending[i] = tuple(fvals) + tuple(ivals) if len(self.pending[i]) != 11: raise IrafError("Unexpected WCS struct record length: " + str(len(self.pending[i]))) if self.wcs is None: self.commit()
def _getDevice(displayname=None): """Get device object for this display""" if displayname is None: displayname = iraf.envget("stdimage") try: return _devices[displayname] except KeyError: pass # look up display info in graphcap try: device = gwm.gki.getGraphcap()[displayname] dd = device['DD'].split(',') if len(dd) > 1 and dd[1] != '': imtdev = f'fifo:{dd[1]}i:{dd[1]}o' else: imtdev = None # multiple stdimage/graphcap entries can share the same device if imtdev not in _devices: _devices[imtdev] = irafdisplay.ImageDisplayProxy(imtdev) device = _devices[displayname] = _devices[imtdev] return device except (KeyError, OSError): pass # last gasp is to assume display is an imtdev string try: device = _devices[displayname] = irafdisplay.ImageDisplayProxy( displayname) return device except (ValueError, OSError): pass raise IrafError(f"Unable to open image display `{displayname}'\n")
def init_wcs_sizes(forceResetTo=None): """ Make sure global size var has been defined correctly """ global _WCS_RECORD_SIZE, _IRAF64BIT # _WCS_RECORD_SIZE is 24 in v2.15, but was 22 in prior versions. # It counts in 2 byte integers, ie. it was 11 shorts when it was size=22. # Either way however, there are still only 11 pieces of information - in # the case of size=24, it is padded by/in IRAF. # The 64-bit case uses a size of 48. # # This function HAS TO BE FAST. It is called multiple times during a # single plot. Do not check IRAF version unless absolutely necessary. # # See ticket #156 and http://iraf.net/phpBB2/viewtopic.php?p=1466296 if _WCS_RECORD_SIZE != 0 and forceResetTo == None: return # been here already # Given a value for _WCS_RECORD_SIZE ? if forceResetTo: if not forceResetTo in \ (WCSRCSZ_vOLD_32BIT, WCSRCSZ_v215_32BIT, WCSRCSZ_v215_64BIT): raise IrafError("Unexpected value for wcs record size: "+\ str(forceResetTo)) _WCS_RECORD_SIZE = forceResetTo _IRAF64BIT = _WCS_RECORD_SIZE == WCSRCSZ_v215_64BIT return # Define _WCS_RECORD_SIZE, based on IRAF ver - assume 32-bit for now vertup = irafinst.getIrafVerTup() _WCS_RECORD_SIZE = WCSRCSZ_vOLD_32BIT if vertup[0] > 2 or vertup[1] > 14: _WCS_RECORD_SIZE = WCSRCSZ_v215_32BIT
def control_getwcs(self, arg): if not self.wcs: self.errorMessage("Error: can't append to a nonexistent plot!") raise IrafError() if self.returnData: self.returnData = self.returnData + self.wcs.pack() else: self.returnData = self.wcs.pack()
def epar(theTask, parent=None, isChild=0): if wutil is None or not wutil.hasGraphics: raise IrafError("Cannot run epar without graphics windows") if not isChild: oldFoc = wutil.getFocalWindowID() wutil.forceFocusToNewWindow() PyrafEparDialog(theTask, parent, isChild) if not isChild: wutil.setFocusTo(oldFoc)
def transform1d(self, coord, dimension, wcsID): wx1, wx2, wy1, wy2, sx1, sx2, sy1, sy2, xt, yt, flag = \ self.wcs[wcsID-1] if dimension == 'x': w1, w2, s1, s2, type = wx1, wx2, sx1, sx2, xt elif dimension == 'y': w1, w2, s1, s2, type = wy1, wy2, sy1, sy2, yt if (s2 - s1) == 0.: raise IrafError("IRAF graphics WCS is singular!") fract = (coord - s1) / (s2 - s1) if type == LINEAR: val = (w2 - w1) * fract + w1 elif type == LOG: lw2, lw1 = math.log10(w2), math.log10(w1) lval = (lw2 - lw1) * fract + lw1 val = 10**lval elif type == ELOG: # Determine inverse mapping to determine corresponding values of s to w # This must be done to figure out which regime of the elog function the # specified point is in. (cs*ew + c0 = s) ew1, ew2 = elog(w1), elog(w2) cs = (s2 - s1) / (ew2 - ew1) c0 = s1 - cs * ew1 # linear part is between ew = 1 and -1, so just map those to s s10p = cs + c0 s10m = -cs + c0 if coord > s10p: # positive log area frac = (coord - s10p) / (s2 - s10p) val = 10. * (w2 / 10.)**frac elif coord >= s10m and coord <= s10p: # linear area frac = (coord - s10m) / (s10p - s10m) val = frac * 20 - 10. else: # negative log area frac = -(coord - s10m) / (s10m - s1) val = -10. * (-w1 / 10.)**frac else: raise IrafError("Unknown or unsupported axis plotting type") return val
def imcur(displayname=None): """Read image cursor and return string expected for IRAF's imcur parameter If key pressed is colon, also prompts for additional string input. Raises EOFError if ^D or ^Z is typed and IrafError on other errors. The optional display argument specifies the name of the display to use (default is the display specified in stdimage). """ try: # give kernel a chance to do anything it needs right before imcur gkrnl = gwm.getActiveGraphicsWindow() if gkrnl: gkrnl.pre_imcur() # get device device = _getDevice(displayname) # Read cursor position at keystroke result = device.readCursor() if Verbose > 1: sys.__stdout__.write(f"{result}\n") sys.__stdout__.flush() if result == 'EOF': raise EOFError() x, y, wcs, key = result.split() if key in [r'\004', r'\032']: # ctrl-D and ctrl-Z are treated as EOF # Should ctrl-C raise a KeyboardInterrupt? raise EOFError() elif key == ':': sys.stdout.write(": ") sys.stdout.flush() result = result + ' ' + irafutils.tkreadline()[:-1] return result except OSError as error: raise IrafError(str(error))
def control_getwcs(self, arg): raise IrafError("Attempt to access graphics when " "it isn't available")
def control_openws(self, arg): raise IrafError("Unable to plot graphics to screen")
# multiple stdimage/graphcap entries can share the same device if not imtdev in _devices: _devices[imtdev] = irafdisplay.ImageDisplayProxy(imtdev) device = _devices[displayname] = _devices[imtdev] return device except (KeyError, IOError, OSError), error: pass # last gasp is to assume display is an imtdev string try: device = _devices[displayname] = irafdisplay.ImageDisplayProxy( displayname) return device except (ValueError, IOError): pass raise IrafError("Unable to open image display `%s'\n" % displayname) def imcur(displayname=None): """Read image cursor and return string expected for IRAF's imcur parameter If key pressed is colon, also prompts for additional string input. Raises EOFError if ^D or ^Z is typed and IrafError on other errors. The optional display argument specifies the name of the display to use (default is the display specified in stdimage). """ try: # give kernel a chance to do anything it needs right before imcur gkrnl = gwm.getActiveGraphicsWindow() if gkrnl: