Exemple #1
0
def nsmaskb(target=None, move=True, quiet=True):
    """
    Reads or modify the position of the nod and shuffle mask


    Parameters
    ----------
    target : string
        Desired position. Valid values are: "Open", "Test", "Mask"
    move : boolean
        Set to false to only modify the target without moving the N&S mask
    quiet : boolean
        Set to disable progress bar


    Examples
    --------
    Prints the position of the nod and shuffle mask

    >>> Blue.nsmasbk()

    Set the nod and shuffle mask to Mask

    >>> Blue.nsmaskb(target="Mask")

    """

    server = 'kbms'
    nasname = ktl.cache(server, 'NASNAME')   # current 
    nastargn = ktl.cache(server, 'NASTARGN') # target 
    nasmove = ktl.cache(server, 'NASMOVE')   # initiate the move
    nasstatus = ktl.cache(server, 'NASSTATUS') # values?

    monitoredKeywords = (nasname, nastargn,nasmove,nasstatus)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current slicer
    if target==None:
        nas = nasname.ascii
        lg.info("kcwiServer: Returning nod and shuffle value '%s'" % (nas))
        return nas

    # if the requested target is the same as the current, do not move
    if target==nasname.ascii and move==True:
        say("N&S: Target is the same as requested. No move needed.")
        return

    # check if move is possible
    checkIfMoveIsPossible(nasstatus)

    # initiate the move
    nastargn.write(target)

    # if move is True, then force a move
    if move==True:
        nasmove.write(1)
        if not quiet:
            p = AnimatedProgressBar(end=100, width=standardWidth)
            ktl.monitor(server,'NASPROG',ProgressCallback,p)
        # fmove expressions
        moving        = '$kbms.nasmove == 1'
        not_moving    = '$kbms.nasmove == 0'
        target_reached = '$kbms.nasname == $kbms.nastargn'

        moving = ktl.Expression(moving)
        not_moving = ktl.Expression(not_moving)
        target_reached = ktl.Expression(target_reached)

        # wait for moving
        result = moving.wait(timeout = timeOutMove)
        if result == False:
            raise RuntimeError("Mechanism %s did not start moving within %d seconds" % ("N&S Mask", timeOutMove))

        # wait for not moving
        not_moving.wait(timeout=240)

        # check for successful move
        time.sleep(5)

        checkSuccess(statusKeyword=nasstatus, mechanism="N&S Mask", targetReachedExpression=target_reached, successStatus="OK")
Exemple #2
0
def camangleb(angvalue=None, move=True, quiet=False):
    """
    Reads or set the blue channel articulation stage angle

    Parameters
    ----------
    angvalue : float
        Desired camera angle in degrees
    move : boolean
        Set to false to only modify the target without moving the camangle
    quiet : boolean
        Set to disable progress bar

    Examples
    --------
    Prints the name of the current camangle

    >>> Blue.camangleb()

    Go to 10 degrees

    >>> Blue.camangleb(angvalue=10)

    Modify the camangle target keyword but do not move

    >>> Blue.camangleb(angvalue=10, move=False)

    """
    timeOutComplete = 180.              # extra time for cam angle
    server = 'kbms'
    #gname = ktl.cache(server,'GNAME')   # current grating
    arttarg = ktl.cache(server,'ARTTARG') # target encoder
    arttargang = ktl.cache(server,'ARTTARGANG') # target angle
    artmove = ktl.cache(server,'ARTMOVE')   # initiate the move
    artstatus = ktl.cache(server,'ARTSTATUS') 
    artenc = ktl.cache(server,'ARTENC')
    artang = ktl.cache(server,'ARTANG')
    artposerr = ktl.cache(server,'ARTPOSERR')
    arttol = ktl.cache(server,'ARTTOL')

    monitoredKeywords = (arttarg,arttargang,artmove,artstatus,artenc,artang,artposerr,arttol)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current filter, otherwise set the filter
    if angvalue==None:
        result = artang.ascii
        lg.info("kcwiServer: Returning camera angle '%s'" % (result))
        return result

    # if the requested target is the same as the current, do not move
    if abs(float(angvalue)-artang) < 0.001 and move==True:
        say("Articulation stage: Target equals current, no move needed.")
        return artang.ascii

    # check if move is possible
    checkIfMoveIsPossible(artstatus)

    # check if we are in filling position
    if is_in_filling_position() != False:
        say("KCWI might be in filling position, moves are not allowed")
        return -1

    # set the target. This is done both for move=True and move=False
    arttargang.write(angvalue)

    # if move is True, then force a move
    if move==True:
        artmove.write(1)

        # move expressions
        moving        = '$kbms.artmove == 1'
        not_moving    = '$kbms.artmove == 0'
        target_reached = '$kbms.artang == $kbms.arttargang'

        moving = ktl.Expression(moving)
        not_moving = ktl.Expression(not_moving)
        target_reached = ktl.Expression(target_reached)

        # wait for moving
        result = moving.wait(timeout = timeOutMove)
        if not quiet:
            p = AnimatedProgressBar(end=100, width=standardWidth)
            ktl.monitor(server,'ARTPROG',ProgressCallback,p)

        if result == False:
            raise RuntimeError("Mechanism %s did not start moving within %d seconds" % ("Articulation stage", timeOutMove))

        # wait for not moving
        not_moving.wait(timeout=timeOutComplete)

        # check for successful move
        time.sleep(5)
        checkSuccess(statusKeyword=artstatus, mechanism="Articulation stage", targetReachedExpression=None, successStatus="OK")
        if abs(artposerr) > arttol:
            say("Warning: The required angle has NOT been reached")

        # return value
        result = artang.ascii
        lg.info("kcwiServer: Returning articulation stage angle '%s'" % (result))
        return result
Exemple #3
0
def grangleb(angvalue=None, move=True, quiet=False):
    """
    Reads or set the blue channel grating angle

    Parameters
    ----------
    angvalue : float
        Desired grating angle in degrees
    move : boolean
        Set to false to only modify the target without moving the grangle
    quiet : boolean
        Set to disable progress bar

    Examples
    --------
    Prints the name of the current camangle

    >>> Blue.grangleb()

    Go to 10 degrees

    >>> Blue.grangleb(angvalue=10)

    """
    timeOutComplete = 180.                  # extra time for grating angle
    server = 'kbes'
    grtargp = ktl.cache(server,'GRTARGP')   # target position (0,1 or 2)
    grangle = ktl.cache(server,'GRANGLE')   # current angle
    grtrgang = ktl.cache(server,'GRTRGANG') # target angle
    grstatus = ktl.cache(server,'GRSTATUS') 
    gstatus = ktl.cache(server,'GSTATUS')
    grmove = ktl.cache(server,'GRMOVE')
    monitoredKeywords = (grtargp, grangle, grtrgang, grstatus,gstatus, grmove)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current filter, otherwise set the filter
    if angvalue==None:
        result = grangle.ascii
        lg.info("kcwiServer: Returning grating angle '%s'" % (result))
        return result

    # if the requested target is the same as the current, do not move
    if abs(float(angvalue)-grangle) < 0.01:
        say("Grating angle: Target equals current, no move needed.")
        return grangle.ascii

    # check if move is possible
    checkIfMoveIsPossible(gstatus)
    checkIfMoveIsPossible(grstatus)

    # set the target. This is done both for move=True and move=False
    grtrgang.write(angvalue)

    # stop here if we are not asking for a move

    if move == False:
        return

    # check that we are in angle mode

    # if we are not in angle mode, changing the angle mode initiates a move
    # if we are in angle mode, we need to issue a move command

    if grtargp != 2:
        sys.stdout.write("Setting grating rotator to angle mode\n")
        grtargp.write(2)

    grmove.write(1)

    # move expressions
    moving        = '$kbes.grstatus == "Moving"'
    not_moving    = '$kbes.grstatus == "Move complete"'
    target_reached = '$kbes.grposerr < $kbes.grtolopt'

    moving = ktl.Expression(moving)
    not_moving = ktl.Expression(not_moving)
    target_reached = ktl.Expression(target_reached)

    # wait for moving
    result = moving.wait(timeout = timeOutMove)
    if not quiet:
        p = AnimatedProgressBar(end=100, width=standardWidth)
        ktl.monitor(server,'GRPROG',ProgressCallback,p)

    if result == False:
        raise RuntimeError("Mechanism %s did not start moving within %d seconds"
                % ("Grating rotator", timeOutMove))

    # wait for not moving
    not_moving.wait(timeout=timeOutComplete)

    # check for successful move
    time.sleep(2)
    checkSuccess(statusKeyword=grstatus, mechanism="Grating rotator",
            targetReachedExpression=target_reached, successStatus="Move")
    #if abs(artposerr) > arttol:
    #    say("Warning: The required encoder position has NOT been reached")

    # return value
    result = grangle.ascii
    return result
Exemple #4
0
def focusb(target=None, move=True, quiet=False):
    """
    Reads or set the blue camera focus

    Parameters
    ----------
    target : float
        Desired focus value in mm.
    move : boolean
        Set to False to just set target
    quiet : boolean
        Set to disable progress bar

    Examples
    --------
    Print the current focus value
    >>> Blue.focusb

    Set the current focus value to 1.5mm
    >>> Blue.focusb(target=1.5)

    """
    server = 'kbms'
    foctargmm = ktl.cache(server,'FOCTARGMM') # target encoder
    focmove = ktl.cache(server,'FOCMOVE')   # initiate the move
    focstatus = ktl.cache(server,'FOCSTATUS') 
    focmm = ktl.cache(server,'FOCMM')
    focposerr = ktl.cache(server,'FOCPOSERR')
    focmmerr = ktl.cache(server,'FOCMMERR')
    foctol = ktl.cache(server,'FOCTOL')
    focenc = ktl.cache(server,'FOCENC')
    foctarg = ktl.cache(server,'FOCTARG')

    monitoredKeywords = (foctargmm,focmove,focstatus,focmm,focposerr,focmmerr,foctol,focenc,foctarg)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current value
    if target==None:
        result = focmm.ascii
        lg.info("kcwiServer: Returning focus value '%s'" % (result))
        return result

    # set the target. This is done both for move=True and move=False
    foctargmm.write(target,wait=True)
    time.sleep(2)

    # if the requested target is the same as the current, do not move
    #print(float(focenc.ascii))
    #print(abs(float(focenc.ascii)-float(foctarg.ascii)))
    #print(float(foctarg.ascii))
    
    #time.sleep(2)

    if abs(float(focenc.ascii)-float(foctarg.ascii)) < float(foctol.ascii) and move==True:
        say("Focus: Target equals current, no move needed.")
        return focmm.ascii

    # check if move is possible
    checkIfMoveIsPossible(focstatus)

    # if move is True, then force a move
    if move==True:
        focmove.write(1)

        # move expressions
        moving        = '$kbms.focmove == 1'
        not_moving    = '$kbms.focmove == 0'

        moving = ktl.Expression(moving)
        not_moving = ktl.Expression(not_moving)

        # wait for moving
        result = moving.wait(timeout = timeOutMove)
        if not quiet:
            p = AnimatedProgressBar(end=100, width=standardWidth)
            ktl.monitor(server,'FOCPROG',ProgressCallback,p)

        if result == False:
            raise RuntimeError("Mechanism %s did not start moving within %d seconds" % ("Blue camera focus", timeOutMove))

        # wait for not moving
        not_moving.wait(timeout=timeOutComplete)

        # check for successful move
        time.sleep(4)
        checkSuccess(statusKeyword=focstatus, mechanism="Blue Camera focus", targetReachedExpression=None, successStatus="OK")
        if abs(focposerr) > foctol:
            say("Warning: The required focus has NOT been reached")

        # return value
        result = focmm.ascii
        lg.info("kcwiServer: Returning blue camera focus '%s'" % (result))
        return result
def cal_object(position=None, move=True, quiet=False):
    """
    Reads or set the calibration object

    Parameters
    ----------
    position : string
        Desired position. Valid values are:
        Pin300, Pin500
        FinBars, MedBarsA, MedBarsB, LrgBarsA, LrgBarsB
        DiagLin, HorLin
        FlatA, FlatB
        Dark, Tpat, MIRA

    move : boolean
        Set to False to only set the target without moving
    quiet : boolean
        Set to disable progress bar

    Examples
    --------

    Set the current calibration object stage to Pin300

    >>> Calibration.cal_object(position="Pin300")

    """
    server = 'kcas'
    calxname = ktl.cache(server, 'CALXNAME')  # current
    calxtargn = ktl.cache(server, 'CALXTARGN')  # target
    calxmove = ktl.cache(server, 'CALXMOVE')  # initiate the move
    calxstatus = ktl.cache(server, 'CALXSTATUS')  # values?
    calyname = ktl.cache(server, 'CALYNAME')  # current
    calytargn = ktl.cache(server, 'CALYTARGN')  # target
    calymove = ktl.cache(server, 'CALYMOVE')  # initiate the move
    calystatus = ktl.cache(server, 'CALYSTATUS')  # values?

    calxtargenc = ktl.cache(server, 'CALXTARGENC')  # target encoder
    calxenc = ktl.cache(server, 'CALXENC')  # current encoder
    calxtol = ktl.cache(server, 'CALXTOL')  # encoder tolerance
    calytargenc = ktl.cache(server, 'CALYTARGENC')  # target
    calyenc = ktl.cache(server, 'CALYENC')  # initiate the move
    calytol = ktl.cache(server, 'CALYTOL')  # encoder tolerance

    monitoredKeywords = (calxname, calxtargn, calxmove, calxstatus, calyname,
                         calytargn, calymove, calystatus, calxtargenc, calxenc,
                         calxtol, calytargenc, calyenc, calytol)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current slicer
    if position == None:
        resultx = calxname.ascii
        resulty = calyname.ascii
        if resultx == resulty:
            lg.info("kcwiServer: Returning CAL Object position '%s'" %
                    (resultx))
            return resultx
        else:
            return "Inconsistent values"

    # if the requested target is the same as the current, do not move
    if position == calxname.ascii and position == calyname.ascii and move == True:
        say("Cal XY: Target is the same as requested. No move needed.")
        return

    # check if move is possible
    checkIfMoveIsPossible(calxstatus)
    checkIfMoveIsPossible(calystatus)

    # initiate the move
    calxtargn.write(position)
    calytargn.write(position)

    # if move is True, then force a move
    if move == True:
        # fmove expressions
        movingx = '$kcas.calxmove == 1'
        not_movingx = '$kcas.calxmove == 0'
        target_reachedx = '$kcas.calxname == $kcas.calxtargn'
        movingy = '$kcas.calymove == 1'
        not_movingy = '$kcas.calymove == 0'
        target_reachedy = '$kcas.calyname == $kcas.calytargn'

        movingx = ktl.Expression(movingx)
        not_movingx = ktl.Expression(not_movingx)
        target_reachedx = ktl.Expression(target_reachedx)
        movingy = ktl.Expression(movingy)
        not_movingy = ktl.Expression(not_movingy)
        target_reachedy = ktl.Expression(target_reachedy)

        # wait for moving
        say("Moving X stage...")
        #       if calxname != position:
        if abs(int(calxtargenc.read()) - int(calxenc.read())) > calxtol:
            calxmove.write(1)
            time.sleep(2)

            #print calxenc
            #print calxtargenc
            #print movingx
            #           result = movingx.wait(timeout = timeOutMove)
            #  The above line has been causing problems. removed 160903 (temporarily?)
            result = True
            if not quiet:
                p = AnimatedProgressBar(end=100, width=standardWidth)
                ktl.monitor(server, 'CALXPROG', ProgressCallback, p)
            if result == False:
                raise RuntimeError(
                    "Mechanism %s did not start moving within %d seconds" %
                    ("CAL X", timeOutMove))
            # wait for not moving
            not_movingx.wait(timeout=timeOutComplete)
            time.sleep(5)
        else:
            say("X stage move is not needed")

        # wait for moving
        say("Moving Y stage...")
        #       if calyname != position:
        if abs(int(calytargenc.read()) - int(calyenc.read())) > calytol:
            calymove.write(1)

            result = movingy.wait(timeout=timeOutMove)
            if not quiet:
                p = AnimatedProgressBar(end=100, width=standardWidth)
                ktl.monitor(server, 'CALYPROG', ProgressCallback, p)
            if result == False:
                raise RuntimeError(
                    "Mechanism %s did not start moving within %d seconds" %
                    ("CAL Y", timeOutMove))
            # wait for not moving
            not_movingy.wait(timeout=timeOutComplete)

            time.sleep(5)
        else:
            say("Y stage move is not needed")

        #checkSuccess(statusKeyword=calxstatus, mechanism="CAL X", targetReachedExpression=target_reachedx, successStatus="OK")
        #say("%s successfully set to %s" % ("CAL X", position))
        #checkSuccess(statusKeyword=calystatus, mechanism="CAL Y", targetReachedExpression=target_reachedy, successStatus="OK")
        #say("%s successfully set to %s" % ("CAL Y", position))
        return calxname.ascii
def polangle(angle=None, move=True, quiet=True):
    """
    Reads or modify the angle of the polarizer

    Parameters
    ----------
    angle : float
        Desired angle. 
    move : boolean
        Set to false to only modify the target without moving the polarizer angle
    quiet : boolean
        Set to disable progress bar

    Examples
    --------
    Prints the current polarizer angle

    >>> Calibration.polangle()

    Set the angle to 90 degrees

    >>> Calibration.polangle(target=90)

    Set the target angle for the polarizer to 180 but do not move

    >>> Calibration.polangle(target=180, move=False)

    """
    server = 'kcas'
    callangle = ktl.cache(server, 'CALLANGLE')  # current
    calltarga = ktl.cache(server, 'CALLTARGA')  # target
    callmove = ktl.cache(server, 'CALLMOVE')  # initiate the move
    callstatus = ktl.cache(server, 'CALLSTATUS')  # values?
    calltol = ktl.cache(server, 'CALLTOL')  # tolerance in counts for angle
    callenc = ktl.cache(server, 'CALLENC')  # encoder value
    calltargenc = ktl.cache(server, 'CALLTARGENC')  # requested encoder value
    callprog = ktl.cache(server, 'CALLPROG')  # progress
    monitoredKeywords = (callangle, calltarga, callmove, callstatus, calltol,
                         callenc, calltargenc)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current angle
    if angle == None:
        result = callangle.ascii
        lg.info("kcwiServer: Returning linear polarizer angle value '%s'" %
                (result))
        return result

    # if the requested target is the same as the current, do not move
    if abs(float(angle) - calltarga) < 0.11 and move == True:
        say("Cal Angle: Target is the same as requested. Curangle '%s'." %
            (angle))
        return

    # check if move is possible
    checkIfMoveIsPossible(callstatus)

    # initiate the move
    calltarga.write(angle)

    # if move is True, then force a move
    if move == True:
        callmove.write(1)

        # fmove expressions
        moving = '$kcas.callmove == 1'
        not_moving = '$kcas.callmove == 0'
        #target_reached = 'abs($kcas.callangle - $kcas.calltarga) < 1'

        moving = ktl.Expression(moving)
        not_moving = ktl.Expression(not_moving)
        #target_reached = ktl.Expression(target_reached)

        # wait for moving
        result = moving.wait(timeout=timeOutMove)
        if not quiet:
            p = AnimatedProgressBar(end=100, width=standardWidth)
            ktl.monitor(server, 'CALLPROG', ProgressCallback, p)

        if result == False:
            raise RuntimeError(
                "Mechanism %s did not start moving within %d seconds" %
                ("Linear Polarizer", timeOutMove))

        # wait for not moving
        not_moving.wait(timeout=timeOutComplete)

        # check for successful move
        time.sleep(2)
        checkSuccess(statusKeyword=callstatus,
                     mechanism="Linear Polarizer",
                     targetReachedExpression=None,
                     successStatus="OK")
        if abs(callenc - calltargenc) > calltol:
            say("Warning: The required encoder precision has NOT been reached")
def image_slicer(target=None, move=True, quiet=False):
    """
    Reads or set the image slicer

    Parameters
    ----------
    target : string
        Desired slicer. Values are: "Small", "Medium", "Large", "FPCam", "Aux"
    move : boolean
        Set to false to only modify the target without moving the slicer
    quiet : boolean
        Set to disable progress bar

    Examples
    --------
    Prints the name of the current slicer

    >>> Calibration.image_slicer()

    Insert the small image slicer

    >>> Calibration.image_slicer(target="Small")

    Modify the slicer target keyword but do not move

    >>> Calibration.image_slicer(target="Medium", move=False)

    """
    server = 'kcas'
    ifuname = ktl.cache(server, 'IFUNAME')  # current slicer
    ifutargn = ktl.cache(server, 'IFUTARGN')  # target slicer
    ifumove = ktl.cache(server, 'IFUMOVE')  # initiate the move
    ifustatus = ktl.cache(server, 'IFUSTATUS')  # values?

    monitoredKeywords = (ifuname, ifutargn, ifustatus, ifumove)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current slicer
    if target == None:
        slicer = ifuname.ascii
        lg.info("kcwiServer: Returning slicer value '%s'" % slicer)
        return slicer

    # if the requested target is the same as the current, do not move
    if target.upper() == ifuname.ascii.upper() and move == True:
        say("IFU: Target is the same as requested. No move needed.")
        slicer = ifuname.ascii
        return slicer

    # check if move is possible
    checkIfMoveIsPossible(ifustatus)

    # initiate the move
    ifutargn.write(target)
    say("Setting target to %s" % (target))

    # if move is True, then force a move
    if move == True:
        ifumove.write(1)

        # fmove expressions
        moving = '$kcas.ifumove == 1'
        not_moving = '$kcas.ifumove == 0'
        target_reached = '$kcas.ifuname == $kcas.ifutargn'

        moving = ktl.Expression(moving)
        not_moving = ktl.Expression(not_moving)
        target_reached = ktl.Expression(target_reached)

        # wait for moving
        result = moving.wait(timeout=timeOutMove)
        if not quiet:
            p = AnimatedProgressBar(end=100, width=standardWidth)
            ktl.monitor(server, 'IFUPROG', ProgressCallback, p)

        if result == False:
            raise RuntimeError(
                "Mechanism %s did not start moving within %d seconds" %
                ("Slicer", timeOutMove))

        # wait for not moving
        not_moving.wait(timeout=timeOutComplete + 300)

        # check for successful move
        time.sleep(4)
        checkSuccess(statusKeyword=ifustatus,
                     mechanism="Slicer",
                     targetReachedExpression=target_reached,
                     successStatus="OK")
        slicer = ifuname.ascii
        return slicer
def polarizer(target=None, move=True, quiet=False):
    """
    Reads or modify the position of the polarizer


    Parameters
    ----------
    target : string
        Desired position. Valid values are: "Sky", "Polar", "Lens"
        "Lens" refers to the hexagonal pupil

    move : boolean
        Set to false to only modify the target without moving the polarizer
    quiet : boolean
        Set to disable progress bar


    Examples
    --------
    Prints the position of the polarizer

    >>> Calibration.polarizer()

    Set the polarizer to Polar

    >>> Calibration.polarizer(target="Polar")

    Set the target for the polarizer to Sky but do not move

    >>> Calibration.polarizer(target="Sky", move=False)

    """

    server = 'kcas'
    calpname = ktl.cache(server, 'CALPNAME')  # current
    calptargn = ktl.cache(server, 'CALPTARGN')  # target
    calpmove = ktl.cache(server, 'CALPMOVE')  # initiate the move
    calpstatus = ktl.cache(server, 'CALPSTATUS')  # values?

    monitoredKeywords = (calpname, calptargn, calpmove, calpstatus)

    # set wait = False if you can accept undefined keywords (for simulation, for example)
    setupMonitoring(monitoredKeywords, wait=True)

    # if called with an empty string, return the current slicer
    if target == None:
        pupil = calpname.ascii
        lg.info("kcwiServer: Returning pupil lens value '%s'" % (pupil))
        return pupil

    # if the requested target is the same as the current, do not move
    if target.upper() == calpname.ascii.upper() and move == True:
        say("Pupil: Target is the same as requested. No move needed.")
        return

    # check if move is possible
    checkIfMoveIsPossible(calpstatus)

    # initiate the move
    calptargn.write(target)

    # if move is True, then force a move
    if move == True:
        calpmove.write(1)
        if not quiet:
            p = AnimatedProgressBar(end=100, width=standardWidth)
            ktl.monitor(server, 'CALPPROG', ProgressCallback, p)
        # fmove expressions
        moving = '$kcas.calpmove == 1'
        not_moving = '$kcas.calpmove == 0'
        target_reached = '$kcas.calpname == $kcas.calptargn'

        moving = ktl.Expression(moving)
        not_moving = ktl.Expression(not_moving)
        target_reached = ktl.Expression(target_reached)

        # wait for moving
        result = moving.wait(timeout=timeOutMove)
        if result == False:
            raise RuntimeError(
                "Mechanism %s did not start moving within %d seconds" %
                ("Cal Pupil", timeOutMove))

        # wait for not moving
        not_moving.wait(timeout=timeOutComplete)

        # check for successful move
        time.sleep(2)
        checkSuccess(statusKeyword=calpstatus,
                     mechanism="Cal Pupil",
                     targetReachedExpression=target_reached,
                     successStatus="OK")