예제 #1
0
def setColor(
        obj,
        color,
        colorSpace=None,
        operation='',
        rgbAttrib='rgb',  # or 'fillRGB' etc
        colorAttrib='color',  # or 'fillColor' etc
        colorSpaceAttrib=None,  # e.g. 'colorSpace' or 'fillColorSpace'
        log=True):
    """Provides the workings needed by setColor, and can perform this for
    any arbitrary color type (e.g. fillColor,lineColor etc).

    OBS: log argument is deprecated - has no effect now.
    Logging should be done when setColor() is called.
    """

    # how this works:
    # rather than using obj.rgb=rgb this function uses setattr(obj,'rgb',rgb)
    # color represents the color in the native space
    # colorAttrib is the name that color will be assigned using
    #   setattr(obj,colorAttrib,color)
    # rgb is calculated from converting color
    # rgbAttrib is the attribute name that rgb is stored under,
    #   e.g. lineRGB for obj.lineRGB
    # colorSpace and takes name from colorAttrib+space e.g.
    # obj.lineRGBSpace=colorSpace

    if colorSpaceAttrib is None:
        colorSpaceAttrib = colorAttrib + 'Space'

    # Handle strings and returns immediately as operations, colorspace etc.
    # does not apply here.
    if isinstance(color, basestring):
        if operation not in ('', None):
            raise TypeError('Cannot do operations on named or hex color')
        if color.lower() in colors.colors255:
            # set rgb, color and colorSpace
            setattr(obj, rgbAttrib,
                    np.array(colors.colors255[color.lower()], float))
            obj.__dict__[colorSpaceAttrib] = 'named'  # e.g. 3rSpace='named'
            obj.__dict__[colorAttrib] = color  # e.g. obj.color='red'
            setTexIfNoShaders(obj)
            return
        elif color[0] == '#' or color[0:2] == '0x':
            # e.g. obj.rgb=[0,0,0]
            setattr(obj, rgbAttrib, np.array(colors.hex2rgb255(color)))
            obj.__dict__[colorSpaceAttrib] = 'hex'  # eg obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = color  # eg Qr='#000000'
            setTexIfNoShaders(obj)
            return
        else:
            # we got a string, but it isn't in the list of named colors and
            # doesn't work as a hex
            raise AttributeError(
                "PsychoPy can't interpret the color string '%s'" % color)

    else:
        # If it wasn't a string, do check and conversion of scalars,
        # sequences and other stuff.
        color = val2array(color, length=3)  # enforces length 1 or 3

        if color is None:
            setattr(obj, rgbAttrib, None)  # e.g. obj.rgb=[0,0,0]
            obj.__dict__[colorSpaceAttrib] = None  # e.g. obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = None  # e.g. obj.color='#000000'
            setTexIfNoShaders(obj)

    # at this point we have a numpy array of 3 vals
    # check if colorSpace is given and use obj.colorSpace if not
    if colorSpace is None:
        colorSpace = getattr(obj, colorSpaceAttrib)
        # using previous color space - if we got this far in the
        # _stColor function then we haven't been given a color name -
        # we don't know what color space to use.
        if colorSpace in ('named', 'hex'):
            logging.error("If you setColor with a numeric color value then"
                          " you need to specify a color space, e.g. "
                          "setColor([1,1,-1],'rgb'), unless you used a "
                          "numeric value previously in which case PsychoPy "
                          "will reuse that color space.)")
            return
    # check whether combining sensible colorSpaces (e.g. can't add things to
    # hex or named colors)
    if operation != '' and getattr(obj, colorSpaceAttrib) in ['named', 'hex']:
        msg = ("setColor() cannot combine ('%s') colors "
               "within 'named' or 'hex' color spaces")
        raise AttributeError(msg % operation)
    elif operation != '' and colorSpace != getattr(obj, colorSpaceAttrib):
        msg = ("setColor cannot combine ('%s') colors"
               " from different colorSpaces (%s,%s)")
        raise AttributeError(msg % (operation, obj.colorSpace, colorSpace))
    else:  # OK to update current color
        if colorSpace == 'named':
            # operations don't make sense for named
            obj.__dict__[colorAttrib] = color
        else:
            setAttribute(obj,
                         colorAttrib,
                         color,
                         log=False,
                         operation=operation,
                         stealth=True)
    # get window (for color conversions)
    if colorSpace in ['dkl', 'lms']:  # only needed for these spaces
        if hasattr(obj, 'dkl_rgb'):
            win = obj  # obj is probably a Window
        elif hasattr(obj, 'win'):
            win = obj.win  # obj is probably a Stimulus
        else:
            win = None
            logging.error("_setColor() is being applied to something"
                          " that has no known Window object")
    # convert new obj.color to rgb space
    newColor = getattr(obj, colorAttrib)
    if colorSpace in ['rgb', 'rgb255']:
        setattr(obj, rgbAttrib, newColor)
    elif colorSpace == 'dkl':
        if (win.dkl_rgb is None or np.all(win.dkl_rgb == np.ones([3, 3]))):
            dkl_rgb = None
        else:
            dkl_rgb = win.dkl_rgb
        setattr(obj, rgbAttrib,
                colors.dkl2rgb(np.asarray(newColor).transpose(), dkl_rgb))
    elif colorSpace == 'lms':
        if (win.lms_rgb is None or np.all(win.lms_rgb == np.ones([3, 3]))):
            lms_rgb = None
        elif win.monitor.getPsychopyVersion() < '1.76.00':
            logging.error("The LMS calibration for this monitor was carried"
                          " out before version 1.76.00."
                          " We would STRONGLY recommend that you repeat the "
                          "color calibration before using this color space "
                          "(contact Jon for further info).")
            lms_rgb = win.lms_rgb
        else:
            lms_rgb = win.lms_rgb
        setattr(obj, rgbAttrib, colors.lms2rgb(newColor, lms_rgb))
    elif colorSpace == 'hsv':
        setattr(obj, rgbAttrib, colors.hsv2rgb(np.asarray(newColor)))
    else:
        logging.error('Unknown colorSpace: %s' % colorSpace)
    # store name of colorSpace for future ref and for drawing
    obj.__dict__[colorSpaceAttrib] = colorSpace
    # if needed, set the texture too
    setTexIfNoShaders(obj)
예제 #2
0
def setColor(obj, color, colorSpace=None, operation='',
                rgbAttrib='rgb', #or 'fillRGB' etc
                colorAttrib='color', #or 'fillColor' etc
                colorSpaceAttrib=None, #e.g. 'colorSpace' or 'fillColorSpace'
                log=True):
    """Provides the workings needed by setColor, and can perform this for
    any arbitrary color type (e.g. fillColor,lineColor etc)
    """

    #how this works:
    #rather than using obj.rgb=rgb this function uses setattr(obj,'rgb',rgb)
    #color represents the color in the native space
    #colorAttrib is the name that color will be assigned using setattr(obj,colorAttrib,color)
    #rgb is calculated from converting color
    #rgbAttrib is the attribute name that rgb is stored under, e.g. lineRGB for obj.lineRGB
    #colorSpace and takes name from colorAttrib+space e.g. obj.lineRGBSpace=colorSpace

    if colorSpaceAttrib==None:
        colorSpaceAttrib = colorAttrib+'Space'

    # Handle strings and returns immediately as operations, colorspace etc. does not apply here.
    if type(color) in [str, unicode, numpy.string_]:
        if color.lower() in colors.colors255.keys():
            #set rgb, color and colorSpace
            setattr(obj,rgbAttrib,numpy.array(colors.colors255[color.lower()], float))
            obj.__dict__[colorSpaceAttrib] = 'named'  #e.g. 3rSpace='named'
            obj.__dict__[colorAttrib] = color  #e.g. obj.color='red'
            setTexIfNoShaders(obj)
            return
        elif color[0]=='#' or color[0:2]=='0x':
            setattr(obj,rgbAttrib,numpy.array(colors.hex2rgb255(color)))#e.g. obj.rgb=[0,0,0]
            obj.__dict__[colorSpaceAttrib] = 'hex'  #e.g. obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = color  #e.g. Qr='#000000'
            setTexIfNoShaders(obj)
            return
        #we got a string, but it isn't in the list of named colors and doesn't work as a hex
        else:
            raise AttributeError("PsychoPy can't interpret the color string '%s'" %color)

    # If it wasn't a strin, do check and conversion of scalars, sequences and other stuff.
    else:
        color = val2array(color, length=3)

        if color==None:
            setattr(obj,rgbAttrib,None)#e.g. obj.rgb=[0,0,0]
            obj.__dict__[colorSpaceAttrib] = None  #e.g. obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = None  #e.g. obj.color='#000000'
            setTexIfNoShaders(obj)

    #at this point we have a numpy array of 3 vals (actually we haven't checked that there are 3)
    #check if colorSpace is given and use obj.colorSpace if not
    if colorSpace==None:
        colorSpace=getattr(obj,colorSpaceAttrib)
        #using previous color space - if we got this far in the _stColor function
        #then we haven't been given a color name - we don't know what color space to use.
        if colorSpace == 'named':
            logging.error("If you setColor with a numeric color value then you need to specify a color space, e.g. setColor([1,1,-1],'rgb'), unless you used a numeric value previously in which case PsychoPy will reuse that color space.)")
            return
    #check whether combining sensible colorSpaces (e.g. can't add things to hex or named colors)
    if operation!='' and getattr(obj,colorSpaceAttrib) in ['named','hex']:
            raise AttributeError("setColor() cannot combine ('%s') colors within 'named' or 'hex' color spaces"\
                %(operation))
    elif operation!='' and colorSpace!=getattr(obj,colorSpaceAttrib) :
            raise AttributeError("setColor cannot combine ('%s') colors from different colorSpaces (%s,%s)"\
                %(operation, obj.colorSpace, colorSpace))
    else:#OK to update current color
        setWithOperation(obj, colorAttrib, color, operation, True)
    #get window (for color conversions)
    if colorSpace in ['dkl','lms']: #only needed for these spaces
        if hasattr(obj,'dkl_rgb'):
            win=obj #obj is probably a Window
        elif hasattr(obj, 'win'):
            win=obj.win #obj is probably a Stimulus
        else:
            win=None
            logging.error("_setColor() is being applied to something that has no known Window object")
    #convert new obj.color to rgb space
    newColor=getattr(obj, colorAttrib)
    if colorSpace in ['rgb','rgb255']:
        setattr(obj,rgbAttrib, newColor)
    elif colorSpace=='dkl':
        if numpy.all(win.dkl_rgb==numpy.ones([3,3])):
            dkl_rgb=None
        else:
            dkl_rgb=win.dkl_rgb
        setattr(obj,rgbAttrib, colors.dkl2rgb(numpy.asarray(newColor).transpose(), dkl_rgb) )
    elif colorSpace=='lms':
        if numpy.all(win.lms_rgb==numpy.ones([3,3])):
            lms_rgb=None
        elif win.monitor.getPsychopyVersion()<'1.76.00':
            logging.error("The LMS calibration for this monitor was carried out before version 1.76.00." +\
                      " We would STRONGLY recommend that you repeat the color calibration before using this color space (contact Jon for further info)")
            lms_rgb=win.lms_rgb
        else:
            lms_rgb=win.lms_rgb
        setattr(obj,rgbAttrib, colors.lms2rgb(newColor, lms_rgb) )
    elif colorSpace=='hsv':
        setattr(obj,rgbAttrib, colors.hsv2rgb(numpy.asarray(newColor)) )
    else:
        logging.error('Unknown colorSpace: %s' %colorSpace)
    obj.__dict__[colorSpaceAttrib] = colorSpace  #store name of colorSpace for future ref and for drawing
    #if needed, set the texture too
    setTexIfNoShaders(obj)

    if hasattr(obj, 'autoLog'):
        autoLog = obj.autoLog
    else:
        autoLog = False
    if autoLog and log:
        if hasattr(obj,'win'):
            obj.win.logOnFlip("Set %s.%s=%s (%s)" %(obj.name,colorAttrib,newColor,colorSpace),
                level=logging.EXP,obj=obj)
        else:
            obj.logOnFlip("Set Window %s=%s (%s)" %(colorAttrib,newColor,colorSpace),
                level=logging.EXP,obj=obj)
예제 #3
0
def setColor(obj, color, colorSpace=None, operation='',
             rgbAttrib='rgb',  # or 'fillRGB' etc
             colorAttrib='color',  # or 'fillColor' etc
             colorSpaceAttrib=None,  # e.g. 'colorSpace' or 'fillColorSpace'
             log=True):
    """Provides the workings needed by setColor, and can perform this for
    any arbitrary color type (e.g. fillColor,lineColor etc).

    OBS: log argument is deprecated - has no effect now.
    Logging should be done when setColor() is called.
    """

    # how this works:
    # rather than using obj.rgb=rgb this function uses setattr(obj,'rgb',rgb)
    # color represents the color in the native space
    # colorAttrib is the name that color will be assigned using
    #   setattr(obj,colorAttrib,color)
    # rgb is calculated from converting color
    # rgbAttrib is the attribute name that rgb is stored under,
    #   e.g. lineRGB for obj.lineRGB
    # colorSpace and takes name from colorAttrib+space e.g.
    # obj.lineRGBSpace=colorSpace

    if colorSpaceAttrib is None:
        colorSpaceAttrib = colorAttrib + 'Space'

    # Handle strings and returns immediately as operations, colorspace etc.
    # does not apply here.
    if isinstance(color, basestring):
        if operation not in ('', None):
            raise TypeError('Cannot do operations on named or hex color')
        if color.lower() in colors.colors255:
            # set rgb, color and colorSpace
            setattr(obj, rgbAttrib,
                    np.array(colors.colors255[color.lower()], float))
            obj.__dict__[colorSpaceAttrib] = 'named'  # e.g. 3rSpace='named'
            obj.__dict__[colorAttrib] = color  # e.g. obj.color='red'
            setTexIfNoShaders(obj)
            return
        elif color[0] == '#' or color[0:2] == '0x':
            # e.g. obj.rgb=[0,0,0]
            setattr(obj, rgbAttrib, np.array(colors.hex2rgb255(color)))
            obj.__dict__[colorSpaceAttrib] = 'hex'  # eg obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = color  # eg Qr='#000000'
            setTexIfNoShaders(obj)
            return
        else:
            # we got a string, but it isn't in the list of named colors and
            # doesn't work as a hex
            raise AttributeError(
                "PsychoPy can't interpret the color string '%s'" % color)

    else:
        # If it wasn't a string, do check and conversion of scalars,
        # sequences and other stuff.
        color = val2array(color, length=3)  # enforces length 1 or 3

        if color is None:
            setattr(obj, rgbAttrib, None)  # e.g. obj.rgb=[0,0,0]
            obj.__dict__[colorSpaceAttrib] = None  # e.g. obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = None  # e.g. obj.color='#000000'
            setTexIfNoShaders(obj)

    # at this point we have a numpy array of 3 vals
    # check if colorSpace is given and use obj.colorSpace if not
    if colorSpace is None:
        colorSpace = getattr(obj, colorSpaceAttrib)
        # using previous color space - if we got this far in the
        # _stColor function then we haven't been given a color name -
        # we don't know what color space to use.
        if colorSpace in ('named', 'hex'):
            logging.error("If you setColor with a numeric color value then"
                          " you need to specify a color space, e.g. "
                          "setColor([1,1,-1],'rgb'), unless you used a "
                          "numeric value previously in which case PsychoPy "
                          "will reuse that color space.)")
            return
    # check whether combining sensible colorSpaces (e.g. can't add things to
    # hex or named colors)
    if operation != '' and getattr(obj, colorSpaceAttrib) in ['named', 'hex']:
        msg = ("setColor() cannot combine ('%s') colors "
               "within 'named' or 'hex' color spaces")
        raise AttributeError(msg % operation)
    elif operation != '' and colorSpace != getattr(obj, colorSpaceAttrib):
        msg = ("setColor cannot combine ('%s') colors"
               " from different colorSpaces (%s,%s)")
        raise AttributeError(msg % (operation, obj.colorSpace, colorSpace))
    else:  # OK to update current color
        if colorSpace == 'named':
            # operations don't make sense for named
            obj.__dict__[colorAttrib] = color
        else:
            setAttribute(obj, colorAttrib, color, log=False,
                         operation=operation, stealth=True)
    # get window (for color conversions)
    if colorSpace in ['dkl', 'lms']:  # only needed for these spaces
        if hasattr(obj, 'dkl_rgb'):
            win = obj  # obj is probably a Window
        elif hasattr(obj, 'win'):
            win = obj.win  # obj is probably a Stimulus
        else:
            win = None
            logging.error("_setColor() is being applied to something"
                          " that has no known Window object")
    # convert new obj.color to rgb space
    newColor = getattr(obj, colorAttrib)
    if colorSpace in ['rgb', 'rgb255']:
        setattr(obj, rgbAttrib, newColor)
    elif colorSpace == 'dkl':
        if (win.dkl_rgb is None or
                np.all(win.dkl_rgb == np.ones([3, 3]))):
            dkl_rgb = None
        else:
            dkl_rgb = win.dkl_rgb
        setattr(obj, rgbAttrib, colors.dkl2rgb(
            np.asarray(newColor).transpose(), dkl_rgb))
    elif colorSpace == 'lms':
        if (win.lms_rgb is None or
                np.all(win.lms_rgb == np.ones([3, 3]))):
            lms_rgb = None
        elif win.monitor.getPsychopyVersion() < '1.76.00':
            logging.error("The LMS calibration for this monitor was carried"
                          " out before version 1.76.00."
                          " We would STRONGLY recommend that you repeat the "
                          "color calibration before using this color space "
                          "(contact Jon for further info).")
            lms_rgb = win.lms_rgb
        else:
            lms_rgb = win.lms_rgb
        setattr(obj, rgbAttrib, colors.lms2rgb(newColor, lms_rgb))
    elif colorSpace == 'hsv':
        setattr(obj, rgbAttrib, colors.hsv2rgb(np.asarray(newColor)))
    elif colorSpace is None:
        pass  # probably using named colors?
    else:
        logging.error('Unknown colorSpace: %s' % colorSpace)
    # store name of colorSpace for future ref and for drawing
    obj.__dict__[colorSpaceAttrib] = colorSpace
    # if needed, set the texture too
    setTexIfNoShaders(obj)
예제 #4
0
def setColor(
        obj,
        color,
        colorSpace=None,
        operation='',
        rgbAttrib='rgb',  #or 'fillRGB' etc
        colorAttrib='color',  #or 'fillColor' etc
        colorSpaceAttrib=None,  #e.g. 'colorSpace' or 'fillColorSpace'
        log=True):
    """Provides the workings needed by setColor, and can perform this for
    any arbitrary color type (e.g. fillColor,lineColor etc)
    """

    #how this works:
    #rather than using obj.rgb=rgb this function uses setattr(obj,'rgb',rgb)
    #color represents the color in the native space
    #colorAttrib is the name that color will be assigned using setattr(obj,colorAttrib,color)
    #rgb is calculated from converting color
    #rgbAttrib is the attribute name that rgb is stored under, e.g. lineRGB for obj.lineRGB
    #colorSpace and takes name from colorAttrib+space e.g. obj.lineRGBSpace=colorSpace

    if colorSpaceAttrib == None:
        colorSpaceAttrib = colorAttrib + 'Space'

    # Handle strings and returns immediately as operations, colorspace etc. does not apply here.
    if type(color) in [str, unicode, numpy.string_]:
        if color.lower() in colors.colors255.keys():
            #set rgb, color and colorSpace
            setattr(obj, rgbAttrib,
                    numpy.array(colors.colors255[color.lower()], float))
            obj.__dict__[colorSpaceAttrib] = 'named'  #e.g. 3rSpace='named'
            obj.__dict__[colorAttrib] = color  #e.g. obj.color='red'
            setTexIfNoShaders(obj)
            return
        elif color[0] == '#' or color[0:2] == '0x':
            setattr(obj, rgbAttrib, numpy.array(
                colors.hex2rgb255(color)))  #e.g. obj.rgb=[0,0,0]
            obj.__dict__[colorSpaceAttrib] = 'hex'  #e.g. obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = color  #e.g. Qr='#000000'
            setTexIfNoShaders(obj)
            return
        #we got a string, but it isn't in the list of named colors and doesn't work as a hex
        else:
            raise AttributeError(
                "PsychoPy can't interpret the color string '%s'" % color)

    # If it wasn't a strin, do check and conversion of scalars, sequences and other stuff.
    else:
        color = val2array(color, length=3)

        if color == None:
            setattr(obj, rgbAttrib, None)  #e.g. obj.rgb=[0,0,0]
            obj.__dict__[colorSpaceAttrib] = None  #e.g. obj.colorSpace='hex'
            obj.__dict__[colorAttrib] = None  #e.g. obj.color='#000000'
            setTexIfNoShaders(obj)

    #at this point we have a numpy array of 3 vals (actually we haven't checked that there are 3)
    #check if colorSpace is given and use obj.colorSpace if not
    if colorSpace == None:
        colorSpace = getattr(obj, colorSpaceAttrib)
        #using previous color space - if we got this far in the _stColor function
        #then we haven't been given a color name - we don't know what color space to use.
        if colorSpace == 'named':
            logging.error(
                "If you setColor with a numeric color value then you need to specify a color space, e.g. setColor([1,1,-1],'rgb'), unless you used a numeric value previously in which case PsychoPy will reuse that color space.)"
            )
            return
    #check whether combining sensible colorSpaces (e.g. can't add things to hex or named colors)
    if operation != '' and getattr(obj, colorSpaceAttrib) in ['named', 'hex']:
        raise AttributeError("setColor() cannot combine ('%s') colors within 'named' or 'hex' color spaces"\
            %(operation))
    elif operation != '' and colorSpace != getattr(obj, colorSpaceAttrib):
        raise AttributeError("setColor cannot combine ('%s') colors from different colorSpaces (%s,%s)"\
            %(operation, obj.colorSpace, colorSpace))
    else:  #OK to update current color
        setWithOperation(obj, colorAttrib, color, operation, True)
    #get window (for color conversions)
    if colorSpace in ['dkl', 'lms']:  #only needed for these spaces
        if hasattr(obj, 'dkl_rgb'):
            win = obj  #obj is probably a Window
        elif hasattr(obj, 'win'):
            win = obj.win  #obj is probably a Stimulus
        else:
            win = None
            logging.error(
                "_setColor() is being applied to something that has no known Window object"
            )
    #convert new obj.color to rgb space
    newColor = getattr(obj, colorAttrib)
    if colorSpace in ['rgb', 'rgb255']:
        setattr(obj, rgbAttrib, newColor)
    elif colorSpace == 'dkl':
        if numpy.all(win.dkl_rgb == numpy.ones([3, 3])):
            dkl_rgb = None
        else:
            dkl_rgb = win.dkl_rgb
        setattr(obj, rgbAttrib,
                colors.dkl2rgb(numpy.asarray(newColor).transpose(), dkl_rgb))
    elif colorSpace == 'lms':
        if numpy.all(win.lms_rgb == numpy.ones([3, 3])):
            lms_rgb = None
        elif win.monitor.getPsychopyVersion() < '1.76.00':
            logging.error("The LMS calibration for this monitor was carried out before version 1.76.00." +\
                      " We would STRONGLY recommend that you repeat the color calibration before using this color space (contact Jon for further info)")
            lms_rgb = win.lms_rgb
        else:
            lms_rgb = win.lms_rgb
        setattr(obj, rgbAttrib, colors.lms2rgb(newColor, lms_rgb))
    elif colorSpace == 'hsv':
        setattr(obj, rgbAttrib, colors.hsv2rgb(numpy.asarray(newColor)))
    else:
        logging.error('Unknown colorSpace: %s' % colorSpace)
    obj.__dict__[
        colorSpaceAttrib] = colorSpace  #store name of colorSpace for future ref and for drawing
    #if needed, set the texture too
    setTexIfNoShaders(obj)

    if hasattr(obj, 'autoLog'):
        autoLog = obj.autoLog
    else:
        autoLog = False
    if autoLog and log:
        if hasattr(obj, 'win'):
            obj.win.logOnFlip("Set %s.%s=%s (%s)" %
                              (obj.name, colorAttrib, newColor, colorSpace),
                              level=logging.EXP,
                              obj=obj)
        else:
            obj.logOnFlip("Set Window %s=%s (%s)" %
                          (colorAttrib, newColor, colorSpace),
                          level=logging.EXP,
                          obj=obj)