示例#1
0
def test_card_no_default(exposure, value):
    card = models.Card("MYCARD", value=value)

    with pytest.raises(ValueError) as err:
        assert card.evaluate(exposure=exposure)

    assert "The context does not include all the Card value placeholders" in str(
        err)
示例#2
0
def test_evaluate_callable(exposure):

    card = models.Card("testcall", value=lambda x, y: x + y, fargs=(1, 2))

    name, value, comment = card.evaluate(exposure)

    assert name == "testcall"
    assert comment == ""
    assert value == 3
示例#3
0
def test_basic_header_model(exposure):

    basic_header_model = models.basic_header_model
    basic_header_model.append(MacroCardTest())
    basic_header_model.append(models.Card("TEST", "test"))

    header = basic_header_model.to_header(exposure)
    assert isinstance(header, astropy.io.fits.Header)
    assert "IMAGETYP" in header
    assert "TEST" in header
示例#4
0
def test_card_default_evaluate(exposure):

    models.DEFAULT_CARDS["TESTCARD"] = models.DefaultCard(
        "TESTCARD",
        value="2+2",
        comment="",
        evaluate=True,
    )

    card = models.Card("TESTCARD")
    assert card.evaluate(exposure)[1] == 4
示例#5
0
def test_autocast_boolean(value, expected, exposure):
    card = models.Card("MYCARD", value=value, autocast=True)
    assert card.evaluate(exposure).value == expected
示例#6
0
def test_placeholder_fails_no_default(exposure):
    card = models.Card("MYCARD", value="{__exposure__.blah}")
    with pytest.raises(AttributeError):
        card.evaluate(exposure=exposure)
示例#7
0
def test_placeholder_fails_with_default(exposure):
    card = models.Card("MYCARD",
                       value="{__exposure__.blah}",
                       default="a_default")
    result = card.evaluate(exposure=exposure)
    assert result.value == "a_default"
示例#8
0
def test_default_card_default_value(exposure):
    del exposure.camera
    card = models.Card("CAMUID")
    assert isinstance(card, DefaultCard)
    assert card.evaluate(exposure).value == "NA"
示例#9
0
def test_card_default(exposure):
    card = models.Card("MYCARD",
                       value="{some_value_not_passed}",
                       default="a_default")
    result = card.evaluate(exposure=exposure)
    assert result.value == "a_default"
示例#10
0
def test_card_name_trimming():

    with pytest.warns(CardWarning):
        card = models.Card("AVERYLARGENAME", "value")

    assert card.name == "AVERYLAR"
示例#11
0
def test_default_card_overridden():

    card = models.Card("VCAM", value="a value")
    assert card.value == "a value"
示例#12
0
async def singleFrame(exptim,
                      name,
                      verb=False,
                      ip_add=None,
                      config="cameras.yaml",
                      targ=None,
                      kmirr=0.0,
                      flen=None):
    """ Expose once and write the image to a FITS file.
    :param exptim: The exposure time in seconds. Non-negative.
    :type exptim: float
    :param verb: Verbosity on or off
    :type verb: boolean
    :param ip_add: list of explicit IP's (like 192.168.70.51 or lvmt.irws2.mpia.de)
    :type ip_add: list of strings
    :param config: Name of the YAML file with the cameras configuration
    :type config: string of the file name
    :param targ: alpha/delta ra/dec of the sidereal target
    :type targ: astropy.coordinates.SkyCoord
    :param kmirr: Kmirr angle in degrees (0 if up, positive with right hand rule along North on bench)
    :type kmirr: float
    :param flen: focal length of telescope/siderostat in mm
                 If not provided it will be taken from the configuration file
    :type flen: float
    """

    cs = BlackflyCameraSystem(BlackflyCamera,
                              camera_config=config,
                              verbose=verb,
                              ip_list=ip_add)
    cam = await cs.add_camera(name=name)
    # print("cameras", cs.cameras)
    # print("config" ,config)

    exp = await cam.expose(exptim, "LAB TEST")

    if targ is not None and kmirr is not None:
        # if there is already a (partial) header information, keep it,
        # otherwise create one ab ovo.
        if exp.wcs is None:
            wcshdr = astropy.io.fits.Header()
        else:
            wcshdr = exp.wcs.to_header()

        key = astropy.io.fits.Card("CUNIT1", "deg", "WCS units along axis 1")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CUNIT2", "deg", "WCS units along axis 2")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CTYPE1", "RA---TAN", "WCS type axis 1")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CTYPE2", "DEC--TAN", "WCS type axis 2")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CRVAL1", targ.ra.deg,
                                   "[deg] RA at reference pixel")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CRVAL2", targ.dec.deg,
                                   "[deg] DEC at reference pixel")
        wcshdr.append(key)

        # field angle: degrees, then radians
        # direction of NCP on the detectors (where we have already flipped pixels
        # on all detectors so fieldrot=kmirr=0 implies North is up and East is left)
        # With right-handed-rule: zero if N=up (y-axis), 90 deg if N=right (x-axis)
        # so the direction is the vector ( sin(f), cos(f)) before the K-mirror.
        # Action of K-mirror is ( cos(2*m), sin(2*m); sin(2*m), -cos(2*m))
        # and action of prism is (-1 0 ; 0 1), i.e. to flip the horizontal coordinate.
        # todo: get starting  value from a siderostat field rotation tracking model
        fieldrot = 0.0

        if name[-1] == 'c':
            # without prism, assuming center camera placed horizontally
            if name[:4] == 'spec':
                # without K-mirror
                pass
            else:
                # with K-mirror
                # in the configuration the y-axis of the image has been flipped,
                # the combined action of (1, 0; 0, -1) and the K-mirror is (cos(2m), sin(2m); -sin(2m), cos(2m))
                # and applied to the input vector this is (sin(2m+f), cos(2m+f))
                fieldrot += 2. * kmirr
        else:
            # with prism
            if name[:4] == 'spec':
                # without K-mirror
                # Applied to input beam this gives (-sin(f), cos(f)) but prism effect
                # had been undone by vertical flip in the FLIR image.
                pass
            else:
                # with K-mirror
                # Combined action of K-mirror and prism is (-cos(2*m), -sin(2*m);sin(2*m), -cos(2*m)).
                # Applied to input beam this gives (-sin(2*m+f), -cos(2*m+f)) = (sin(2*m+f+pi), cos(2*m+f+pi)).
                fieldrot += 2. * kmirr + 180.0

            if name[-1] == 'w':
                # Camera is vertically,
                # so up in the lab is right in the image
                fieldrot += 90
            else:
                # Camera is vertically,
                # so up in the lab is left in the image
                fieldrot -= 90

        fieldrot = math.radians(fieldrot)

        # the section/dictionary of the yaml file for this camera
        yamlconfig = cs._config[name]

        if flen is None:
            flen = yamlconfig["flen"]

        # pixel scale per arcseconds is focal length *pi/180 /3600
        # = flen * mm *pi/180 /3600
        # = flen * um *pi/180 /3.6, so in microns per arcsec...
        pixscal = math.radians(flen) / 3.6

        # degrees per pixel is arcseconds per pixel/3600 = (mu/pix)/(mu/arcsec)/3600
        degperpix = yamlconfig["pixsize"] / pixscal / 3600.0

        # for the right handed coordinates
        # (pixx,pixy) = (cos f', -sin f'; sin f', cos f')*(DEC,RA) where f' =90deg -fieldrot
        # (pixx,pixy) = (sin f, -cos f; cos f , sin f)*(DEC,RA)
        # (sin f, cos f; -cos f, sin f)*(pixx,pixy) = (DEC,RA)
        # (-cos f, sin f; sin f, cos f)*(pixx,pixy) = (RA,DEC)
        # Note that the det of the WCS matrix is negativ (because RA/DEC is left-handed...)
        cosperpix = degperpix * math.cos(fieldrot)
        sinperpix = degperpix * math.sin(fieldrot)
        key = astropy.io.fits.Card("CD1_1", -cosperpix,
                                   "[deg/px] WCS matrix diagonal")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CD2_2", cosperpix,
                                   "[deg/px] WCS matrix diagonal")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CD1_2", sinperpix,
                                   "[deg/px] WCS matrix outer diagonal")
        wcshdr.append(key)
        key = astropy.io.fits.Card("CD2_1", sinperpix,
                                   "[deg/px] WCS matrix outer diagonal")
        wcshdr.append(key)

        exp.wcs = astropy.wcs.WCS(wcshdr)
        # print(exp.wcs.to_header_string())
        for headr in wcshdr.cards:
            exp.fits_model[0].header_model.append(models.Card(headr))

    await exp.write()
    if verb:
        print("wrote ", exp.filename)
示例#13
0
    async def _expose_internal(self, exposure):
        """ Read a single unbinned full frame and store in a FITS file.
        :param exposure:  On entry exposure.exptim is the intended exposure time in [sec]
                  On exit, exposure.data contains the 16bit data of a single frame
        :return: There is no return value
        """

        # fill exposure.data with the frame's 16bit data
        # reg becomes a x=, y=, width= height= dictionary
        # these are in standard X11 coordinates where upper left =(0,0)
        reg = await self._expose_grabFrame(exposure)
        # print('region',reg)

        binxy = {}
        try:
            # becomes a dictionary with dx=... dy=... for the 2 horiz/vert binn fact
            binxy = self.device.get_binning()
        except Exception as ex:
            binxy = None

        # append FITS header cards
        # For the x/y coordinates transform from X11 to FITS coordinates
        # Todo: reports the camera y-flipped reg.y if ReversY=true above??
        addHeaders = [
            ("BinX", binxy.dx, "[ct] Horizontal Bin Factor 1, 2 or 4"),
            ("BinY", binxy.dy, "[ct] Vertical Bin Factor 1, 2 or 4"),
            ("Width", reg.width, "[ct] Pixel Columns"),
            ("Height", reg.height, "[ct] Pixel Rows"),
            ("RegX", 1 + reg.x, "[ct] Pixel Region Horiz start"),
            # The lower left FITS corner is the upper left X11 corner...
            ("RegY", self.regionBounds[1] - (reg.y + reg.height - 1),
             "[ct] Pixel Region Vert start")
        ]

        dev = self.device.get_device()
        # print(dir(dev))
        # print(dir(self))
        # print(self.camera_system.get_camera(self.name))
        # print(self.camera_system._config[self.name])

        try:
            gain = dev.get_float_feature_value("Gain")
            addHeaders.append(("Gain", gain, "Gain"))
        except Exception as ex:
            # print("failed to read gain" + str(ex))
            pass

        imgrev = [False, False]
        try:
            imgrev[0] = self.device.get_boolean("ReverseX")
            addHeaders.append(
                ("ReverseX", imgrev[0] != 0, " Flipped left-right"))
            imgrev[1] = self.device.get_boolean("ReverseY")
            addHeaders.append(("ReverseY", imgrev[1] != 0, " Flipped up-down"))
            # print("reversed" +  str(imgrev[0]) + str(imgrev[1]) )
        except Exception as ex:
            # print("failed to read ReversXY" + str(ex))
            pass

        # This is an enumeration in the GenICam. See features list of
        #  `arv-tool-0.8 --address=192.168.70.50 features`

        binMod = [-1, -1]
        try:
            binMod[0] = dev.get_integer_feature_value("BinningHorizontalMode")
            if binMod[0] == 0:
                addHeaders.append(
                    ("BinModeX", "Averag", "Horiz Bin Mode Sum or Averag"))
            else:
                addHeaders.append(
                    ("BinModeX", "Sum", "Horiz Bin Mode Sum or Averag"))
            binMod[1] = dev.get_integer_feature_value("BinningVerticalMode")
            if binMod[1] == 0:
                addHeaders.append(
                    ("BinModeY", "Averag", "Vert Bin Mode Sum or Averag"))
            else:
                addHeaders.append(
                    ("BinModeY", "Sum", "Vert Bin Mode Sum or Averag"))
        except Exception as ex:
            # print("failed to read binmode" + str(ex))
            pass

        tmp = False
        try:
            tmp = self.device.get_boolean("BlackLevelClampingEnable")
            addHeaders.append(
                ("CAMBLCLM", tmp != 0, "Black Level Clamping en/disabled"))
            # print("BlackLevelClampingEnable" +  str(imgrev[0]) + str(imgrev[1]) )
        except Exception as ex:
            # print("failed to read BlackLevelClampingEnable" + str(ex))
            pass

        try:
            camtyp = self.device.get_model_name()
            addHeaders.append(("CAMTYP", camtyp, "Camera model"))
        except:
            pass

        # call _expose_wcs() to gather WCS header keywords
        addHeaders.extend(self._expose_wcs(exposure, reg))

        for headr in addHeaders:
            exposure.fits_model[0].header_model.append(models.Card(headr))

        # print(repr(exposure.to_hdu()[0].header))

        # unref() is currently usupported in this GObject library.
        # Hope that this does not lead to any memory leak....
        # buf.unref()
        return