class TestMirrorDispatcherWrapper(TestCase):
    """Test basics of MirrorDispatcherWrapper
    """
    def setUp(self):
        self.dw = TCCLCODispatcherWrapper()
        return self.dw.readyDeferred

    def tearDown(self):
        return self.dw.close()

    def testSetUpTearDown(self):
        self.assertFalse(self.dw.didFail)
        self.assertFalse(self.dw.isDone)
        self.assertTrue(self.dw.isReady)
 def setUp(self):
     self.dw = TCCLCODispatcherWrapper()
     return self.dw.readyDeferred
Example #3
0
 def setUp(self):
     """!Set up a test
     """
     self.dw = TCCLCODispatcherWrapper()
     # reset the global threadring position
     return self.dw.readyDeferred
Example #4
0
class TestLCOCommands(TestCase):

    def setUp(self):
        """!Set up a test
        """
        self.dw = TCCLCODispatcherWrapper()
        # reset the global threadring position
        return self.dw.readyDeferred

    def tearDown(self):
        """!Tear down a test
        """
        delayedCalls = reactor.getDelayedCalls()
        for call in delayedCalls:
            call.cancel()
        return self.dw.close()

    @property
    def dispatcher(self):
        """!Return the actor dispatcher that talks to the mirror controller
        """
        return self.dw.dispatcher

    @property
    def actor(self):
        """!Return the tcc actor
        """
        return self.dw.actorWrapper.actor

    @property
    def model(self):
        """!Return the tcc model
        """
        return self.dw.dispatcher.model

    @property
    def cmdQueue(self):
        """!return the cmdQueue on the dispatcher wrapper
        """
        return self.dw.cmdQueue

    def queueCmd(self, cmdStr, callFunc):
        d1, cmd1 = self.dw.queueCmd(
            cmdStr,
            callFunc = callFunc,
            callCodes = ":>",
        )
        return d1

    def queueOffsetCmd(self, cmdStr, raVal, decVal):
        """TCS device sets track commands done instantly (eg before state=Tracking)
        return a deferred here that will only fire when state==Tracking
        """
        d = Deferred()
        def fireWhenTracking(keyVar):
            if keyVar.valueList[0] == "Tracking" and keyVar.valueList[1] == "Tracking":
                # telescope is tracking
                self.checkOffsetDone(raVal, decVal)
                d.callback(None)
        def removeCB(foo=None):
            self.model.axisCmdState.removeCallback(fireWhenTracking)
        d.addCallback(removeCB)
        self.model.axisCmdState.addCallback(fireWhenTracking)
        self.dw.queueCmd(cmdStr)
        return d

    def checkFocus(self, cmdVar, focusVal):
        """Check the actor, and the model, verify that the correct focus
        is present

        @param[in] cmdVar, passed automatically by callback framework
        @param[in] focusVal, the expected focus value
        """
        if cmdVar.isDone:
            self.assertFalse(cmdVar.didFail)
            self.assertAlmostEqual(float(focusVal), float(self.actor.secDev.status.secFocus))
            # tcs isn't used for focus
            # self.assertAlmostEqual(float(focusVal), float(self.actor.tcsDev.status.statusFieldDict["focus"].value))
            # model doesn't update very fast
            # self.assertAlmostEqual(float(focusVal), float(self.model.secFocus.valueList[0]))

    def checkScale(self, cmdVar, scaleVal):
        """Check the actor, and the model, verify that the correct scale
        is present

        @param[in] cmdVar, passed automatically by callback framework
        @param[in] scaleVal, the expected scale value
        """
        if cmdVar.isDone:
            print("threadpos", self.actor.scaleDev.status.position)
            print("measScale pos", self.actor.scaleDev.encPos)
            print("measScale encs", self.actor.measScaleDev.encPos)
            # self.assertAlmostEqual(float(scaleVal), float(self.actor.scaleDev.currentScaleFactor), msg="actor-current: %.6f, %.6f"%(float(scaleVal), float(self.actor.scaleDev.currentScaleFactor)))
            # self.assertAlmostEqual(float(scaleVal), float(self.actor.scaleDev.targetScaleFactor), msg="actor-target: %.6f, %.6f"%(float(scaleVal), float(self.actor.scaleDev.targetScaleFactor)))
            self.assertAlmostEqual(float(scaleVal), float(self.model.scaleFac.valueList[0]), msg="model: %.6f, %.6f"%(float(scaleVal), float(self.model.scaleFac.valueList[0])))

    def checkAxesState(self, axisStateList):
        assert len(axisStateList) == 3
        for axisState in axisStateList:
            assert axisState in ["Tracking", "Slewing", "Halted"]
        # model isn't always 100% reliable check the state on status instead
        #for desState, lastState in itertools.izip(axisStateList, self.model.axisCmdState.valueList):
        for desState, lastState in itertools.izip(axisStateList, self.actor.tcsDev.status.axisCmdStateList()):
            self.assertEqual(desState, lastState)

    def checkAxesPosition(self, raVal, decVal):
        raActorPos = self.actor.tcsDev.status.statusFieldDict["ra"].value
        decActorPos = self.actor.tcsDev.status.statusFieldDict["dec"].value
        # raModelPos, decModelPos, rotModelPos = self.model.axePos.valueList
        # if raModelPos is None or decModelPos is None:
        #     self.assertTrue(False, "No value on model!")
        self.assertAlmostEqual(float(raVal), float(raActorPos))
        self.assertAlmostEqual(float(decVal), float(decActorPos))
        # self.assertAlmostEqual(float(raVal), float(raModelPos))
        # self.assertAlmostEqual(float(decVal), float(decModelPos))

    def checkIsSlewing(self):
        self.checkAxesState(["Slewing"]*2 + ["Halted"])

    def checkOffsetDone(self, raVal, decVal):
        # how to verify position is correct?
        self.checkAxesState(["Tracking"]*2 + ["Halted"])
        self.checkAxesPosition(raVal, decVal) # Undo negative offsets!

    def testFocus(self):
        focusVal = 70
        return self.queueCmd(
            cmdStr = "set focus=%i"%focusVal,
            callFunc = functools.partial(self.checkFocus, focusVal=focusVal)
            )


    def testFocusList(self):
        focusCmdList = ["set focus=70", "set focus=100/incr", "set focus=-50/incr", "set focus=30.4", "set focus"]
        focusValList = [70, 170, 120, 30.4, 30.4]
        callFuncList = [functools.partial(self.checkFocus, focusVal=focusVal) for focusVal in focusValList]
        deferredList = [self.queueCmd(cmdStr, callFunc) for cmdStr, callFunc in itertools.izip(focusCmdList, callFuncList)]
        return gatherResults(deferredList)

   # LCO HACK: small focus moves are allowed, uncomment and rewrite tests when min threshold is implemented.

    # def testFocusSmall1(self):
    #     focusVal = self.actor.secDev.status.secFocus + 20
    #     # focus delta's less than 50 will return successfully
    #     # immediately
    #     return self.queueCmd(
    #         cmdStr = "set focus=%i"%focusVal,
    #         callFunc = functools.partial(self.checkFocus, focusVal=focusVal-20)
    #         )

    # def testFocusSmall2(self):
    #     focusValInc = 20
    #     # focus delta's less than 50 will return successfully
    #     # immediately
    #     focusVal = self.actor.secDev.status.secFocus
    #     return self.queueCmd(
    #         cmdStr = "set focus=%i/incr"%focusValInc,
    #         callFunc = functools.partial(self.checkFocus, focusVal=focusVal)
    #         )

    def testOffset(self):
        # self.checkAxesState("Idle")
        raVal, decVal = 5,5
        offsetCmd = "offset arc %i,%i"%(raVal, decVal)
        d = self.queueOffsetCmd(offsetCmd, raVal, decVal)
        reactor.callLater(0.1, self.checkIsSlewing)
        return d

    def testOffset2(self):
        # self.checkAxesState("Idle")
        raVal, decVal = 10.8,-5.2
        offsetCmd = "offset arc %.2f,%.2f"%(raVal, decVal)
        d = self.queueOffsetCmd(offsetCmd, raVal, decVal)
        reactor.callLater(0.1, self.checkIsSlewing)
        return d

    def _doubleOffset(self, raOff1, decOff1, raOff2, decOff2):
        returnD = Deferred()
        offsetCmd = "offset arc %.2f,%.2f"%(raOff1, decOff1)
        offsetCmd2 = "offset arc %.2f,%.2f"%(raOff2, decOff2)
        d1 = self.queueOffsetCmd(offsetCmd, raOff1, decOff1)
        reactor.callLater(0.1, self.checkIsSlewing)
        def sendNextOffset(*args):
            # only send offset once track is finished
            d2 = self.queueOffsetCmd(offsetCmd2, raOff1+raOff2, decOff1+decOff2)
            def setDone(callback):
                returnD.callback(None)
            d2.addCallback(setDone)
        d1.addCallback(sendNextOffset)
        return returnD

    def testDoubleOffset(self):
        return self._doubleOffset(5,6,7,8)

    def testDoubleOffset2(self):
        return self._doubleOffset(5.4, -3.6, 7.02, -8.2)

    def testScale1(self):
        scaleVal = 1
        def checkScaleAndMotorPos(cmdVar):
            self.checkScale(cmdVar, scaleVal=scaleVal)
            pos = self.actor.scaleDev.encPos
            zeropoint = self.actor.measScaleDev.zeroPoint
            self.assertAlmostEqual(float(pos), float(zeropoint), msg="pos: %.4f, zeropoint: %.4f"%(pos, zeropoint))
        return self.queueCmd(
            cmdStr = "set scale=%.6f"%scaleVal,
            callFunc = checkScaleAndMotorPos
            )

    def testScale(self):
        scaleVal = 1.00006
        return self.queueCmd(
            cmdStr = "set scale=%.6f"%scaleVal,
            callFunc = functools.partial(self.checkScale, scaleVal=scaleVal)
            )

    def testScale2(self):
        scaleVal = 0.9999
        return self.queueCmd(
            cmdStr = "set scale=%.6f"%scaleVal,
            callFunc = functools.partial(self.checkScale, scaleVal=scaleVal)
            )

    def testShowScale(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        self.queueCmd("show scale", cb)

    def testScaleList(self):
        scaleVal1 = 1.00006
        scaleMult = 1.0004
        scaleCmdList = ["set scale=%.6f"%scaleVal1, "set scale=%.6f/mult"%scaleMult]
        scaleValList = [scaleVal1, scaleVal1*scaleMult]
        callFuncList = [functools.partial(self.checkScale, scaleVal=scaleVal) for scaleVal in scaleValList]
        deferredList = [self.queueCmd(cmdStr, callFunc) for cmdStr, callFunc in itertools.izip(scaleCmdList, callFuncList)]
        return gatherResults(deferredList)

    def testScaleCompRoundTrip(self):
        # test that there is no numerical issues with very small scale changes?
        scaleMults = numpy.linspace(0.999999, 1.000001, 10)
        # hand force very small offsets
        for pos in numpy.linspace(19.9999, 20.0001, 30):
            # set various zero poisitions
            self.actor.scaleDev.status._scaleZero = pos
            currScale = self.actor.currentScaleFactor
            for mult in scaleMults:
                mm1 = self.actor.scaleMult2mm(mult)
                mm2 = self.actor.scaleMult2mmStable(mult)
                self.assertAlmostEqual(mm1, mm2)
                s1 = self.actor.mm2scale(mm1)
                s2 = self.actor.mm2scale(mm2)
                self.assertAlmostEqual(s1, currScale * mult)
                self.assertAlmostEqual(s2, currScale * mult)

    def testThreadRingStatus(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("threadring status", cb)

    def testThreadRingStop(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("threadring stop", cb)

    def testThreadRingMove(self):
        position = self.actor.scaleDev.encPos + 5
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            self.assertEqual(self.actor.scaleDev.encPos, position)
        return self.queueCmd("threadring move %.4f"%position, cb)

    def testThreadRingHome(self):
        def cb(cmdVar):
            self.assertTrue(not cmdVar.didFail)
        return self.queueCmd("threadring home", cb)

    def testThreadRingMoveInc(self):
        posStart = self.actor.scaleDev.encPos
        incr = 5
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            self.assertEqual(self.actor.scaleDev.encPos, posStart+incr)
        return self.queueCmd("threadring move %.2f/incr"%incr, cb)

    def testThreadRingMoveStop(self):
        d = Deferred()
        def moveCB(cmdVar):
            self.assertTrue(cmdVar.didFail)
        def stopCB(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            d.callback(None)
        position = self.actor.scaleDev.encPos + 5
        self.queueCmd("threadring move %.4f"%position, moveCB)
        cmd = self.actor.scaleDev.stop()
        cmd.addCallback(stopCB)
        return d

    def testThreadRingMoveStopWithDelay(self):
        d = Deferred()
        def moveCB(cmdVar):
            print(cmdVar)
            self.assertTrue(cmdVar.didFail)
        def stopCB(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            d.callback(None)
        position = self.actor.scaleDev.encPos + 5
        self.queueCmd("threadring move %.4f"%position, moveCB)
        def callLater():
            cmd = self.actor.scaleDev.stop()
            cmd.addCallback(stopCB)
        reactor.callLater(0.5, callLater)
        return d

    def testThreadRingSpeed(self):
        speed = 0.1
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            self.assertEqual(self.actor.scaleDev.status.speed, speed)
        return self.queueCmd("threadring speed %.4f"%speed, cb)

    def testThreadRingSpeedMult(self):
        speedMult = 0.1
        prevSpeed = self.actor.scaleDev.status.speed
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            self.assertAlmostEqual(self.actor.scaleDev.status.speed, prevSpeed*speedMult)
        return self.queueCmd("threadring speed %.4f/mult"%speedMult, cb)

    # again command fails as expected but unit test sees
    # runtime error and fails?
    # def testThreadRingOverSpeed(self):
    #     speed = 1
    #     def cb(cmdVar):
    #         self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
    #         self.assertEqual(self.actor.scaleDev.status.speed, speed)
    #     return self.queueCmd("threadring speed %.4f"%speed, cb)

    def testSecStatus(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("sec status", cb)

    def testSecStop(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("sec stop", cb)

    def testSecMove(self):
        position = self.actor.secDev.status.secFocus + 5
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            self.assertEqual(self.actor.secDev.status.secFocus, position)
        return self.queueCmd("sec move %.4f"%position, cb)

    def testSecMove2(self):
        position = self.actor.secDev.status.secFocus + 5
        tipx = 2
        newOrient = self.actor.secDev.status.orientation[:]
        newOrient[0] = position
        newOrient[1] = tipx
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            for x1, x2 in itertools.izip(self.actor.secDev.status.orientation, newOrient):
                self.assertEqual(x1, x2)
        return self.queueCmd("sec move %.4f, %.2f"%(position,tipx), cb)

    def testTarget(self):
        ra = 5
        dec = 6
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
            self.assertTrue(self.actor.tcsDev.status.statusFieldDict["inpra"], ra)
            self.assertTrue(self.actor.tcsDev.status.statusFieldDict["inpdc"], dec)
            self.assertTrue(self.actor.tcsDev.status.statusFieldDict["ra"], ra)
            self.assertTrue(self.actor.tcsDev.status.statusFieldDict["dec"], dec)
        return self.queueCmd("target %.4f, %.2f icrs"%(ra, dec), cb)

    def testOffsetGuideMin(self):
        offset = 0.001 # below min threshold
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("offset guide 0, 0, %.5f"%(offset), cb)

    def testOffsetGuideOverMax(self):
        offset = 0.5 # above max thresh
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("offset guide 0, 0, %.5f"%(offset), cb)

    def testOffsetGuide(self):
        offset = 0.01
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("offset guide 0, 0, %.5f"%(offset), cb)

    def testShowFocus(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("show focus", cb)

    def testShowScale(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("show scaleFactor", cb)

    def testShowStatus(self):
        def cb(cmdVar):
            self.assertTrue(cmdVar.isDone and not cmdVar.didFail)
        return self.queueCmd("show status", cb)