예제 #1
0
    def _get_psychopy_pos(self, p):
        """Convert Tobii ADCS coordinates to PsychoPy coordinates.

        Args:
            p: Gaze position (x, y) in Tobii ADCS.

        Returns:
            Gaze position in PsychoPy coordinate systems.
        """

        if self.win.units == 'norm':
            return (2 * p[0] - 1, -2 * p[1] + 1)
        elif self.win.units == 'height':
            return ((p[0] - 0.5) * (self.win.size[0] / self.win.size[1]),
                    -p[1] + 0.5)
        elif self.win.units in ['pix', 'cm', 'deg', 'degFlat', 'degFlatPos']:
            p_pix = ((p[0] - 0.5) * self.win.size[0],
                     (-p[1] + 0.5) * self.win.size[1])
            if self.win.units == 'pix':
                return p_pix
            elif self.win.units == 'cm':
                return (pix2cm(p_pix[0], self.win.monitor),
                        pix2cm(p_pix[1], self.win.monitor))
            elif self.win.units == 'deg':
                return (pix2deg(p_pix[0], self.win.monitor),
                        pix2deg(p_pix[1], self.win.monitor))
            else:
                return (pix2deg(
                    np.array(p_pix), self.win.monitor, correctFlat=True))
        else:
            raise ValueError('unit ({}) is not supported.'.format(
                self.win.units))
예제 #2
0
    def get_psychopy_pos_from_trackbox(self, p, units=None):
        """
        Convert Tobii TBCS coordinates to PsychoPy coordinates.

        :param p: Position (x, y)
        """

        if units is None:
            units = self.win.units

        if units == 'norm':
            return (-2 * p[0] + 1, -2 * p[1] + 1)
        elif units == 'height':
            return ((-p[0] + 0.5) * (self.win.size[0] / self.win.size[1]),
                    -p[1] + 0.5)
        elif units in ['pix', 'cm', 'deg', 'degFlat', 'degFlatPos']:
            p_pix = ((-2 * p[0] + 1) * self.win.size[0] / 2,
                     (-2 * p[1] + 1) * self.win.size[1] / 2)
            if units == 'pix':
                return p_pix
            elif units == 'cm':
                return (pix2cm(p_pix[0], self.win.monitor),
                        pix2cm(p_pix[1], self.win.monitor))
            elif units == 'deg':
                return (pix2deg(p_pix[0], self.win.monitor),
                        pix2deg(p_pix[1], self.win.monitor))
            else:
                return (pix2deg(np.array(p_pix),
                                self.win.monitor,
                                correctFlat=True))
        else:
            raise ValueError('unit ({}) is not supported.'.format(
                self.win.units))
예제 #3
0
파일: __init__.py 프로젝트: savuzmir/psxeff
    def get_psychopy_pos(self, p):
        """
        Convert PsychoPy position to Tobii coordinate system.
        
        :param p: Position (x, y)
        """

        p = (p[0], 1 - p[1])  #flip vert
        if self.win.units == 'norm':
            return (2 * p[0] - 1, 2 * p[1] - 1)
        elif self.win.units == 'height':
            return ((p[0] - 0.5) * self.win.size[0] / self.win.size[1],
                    p[1] - 0.5)

        p_pix = ((p[0] - 0.5) * self.win.size[0],
                 (p[1] - 0.5) * self.win.size[1])
        if self.win.units == 'pix':
            return p_pix
        elif self.win.units == 'cm':
            return (pix2cm(p_pix[0],
                           self.win.monitor), pix2cm(p_pix[1],
                                                     self.win.monitor))
        elif self.win.units == 'deg':
            return (pix2deg(p_pix[0], self.win.monitor),
                    pix2deg(p_pix[1], self.win.monitor))
        elif self.win.units in ['degFlat', 'degFlatPos']:
            return (pix2deg(np.array(p_pix),
                            self.win.monitor,
                            correctFlat=True))
        else:
            raise ValueError('unit ({}) is not supported.'.format(
                self.win.units))
예제 #4
0
def plot_category_exemplars_2(x, y, xpos, ypos, contrast=None):
    '''plot sine-wave gratings at x CPD and at y degrees orientation in
    stimulus space --- cat, x, and y should be lists of the same length.'''

    # NOTE: Screen coordinate system has origin in the middle of the screen with
    # positive numbers going right and negative number going left
    screen_size = 600

    x_max = np.max(xpos)
    y_max = np.max(ypos)

    x_min = np.min(xpos)
    y_min = np.min(ypos)

    # NOTE: convert stimulus coordinates into screen coordinates
    xp = ((xpos - np.min(xpos)) /
          np.max(xpos - np.min(xpos))) * (screen_size) - screen_size / 2.0
    yp = ((ypos - np.min(ypos)) /
          np.max(ypos - np.min(ypos))) * (screen_size) - screen_size / 2.0

    win = visual.Window(size=(screen_size + 150, screen_size + 150),
                        fullscr=False,
                        screen=0,
                        allowGUI=False,
                        allowStencil=False,
                        monitor='testMonitor',
                        color=[0, 0, 0],
                        colorSpace='rgb',
                        blendMode='avg',
                        useFBO=False)

    mon = Monitor('testMonitor')
    mon.setWidth(29.0)
    mon.setSizePix((1440, 900))
    cm_per_pix = pix2cm(1, mon)

    n = x.shape[0]

    if contrast is None:
        cont = [1] * n
    else:
        cont = contrast

    stim = []
    for i in range(n):
        grating = visual.GratingStim(win,
                                     units='pix',
                                     mask='circle',
                                     sf=x[i] * cm_per_pix,
                                     ori=y[i],
                                     pos=(xp[i], yp[i]),
                                     contrast=cont[i],
                                     size=(2 / cm_per_pix, 2 / cm_per_pix))

        stim.append(grating)

    [i.draw() for i in stim]
    win.flip()

    event.waitKeys(keyList=['escape'])
예제 #5
0
 def _pix2windowUnits(self, win_handle, pos):
     win = self._iohub_server._psychopy_windows.get(win_handle)
     win_units = win['units']
     monitor = win['monitor']
     pos = np.asarray(pos)
     if win_units == 'pix':
         return pos
     elif win_units == 'norm':
         return pos * 2.0 / win['size']
     elif win_units == 'cm':
         if monitor:
             return pix2cm(pos, monitor['monitor'])
         else:
             # should raise exception?
             print2err(
                 "iohub Mouse error: Window is using units %s but has no Monitor definition."
                 % win_units)
     elif win_units == 'deg':
         if monitor:
             return pix2deg(pos, monitor['monitor'])
         else:
             # should raise exception?
             print2err(
                 "iohub Mouse error: Window is using units %s but has no Monitor definition."
                 % win_units)
     elif win_units == 'height':
         return pos / float(win['size'][1])
예제 #6
0
    def _pixToWindowUnits(self, pos):
        """Conversion from 'pix' units to window units.

        The mouse class stores mouse positions in 'pix' units. This function is
        used by getter and setter methods to convert position values to the
        units specified by the window.

        Parameters
        ----------
        pos : ArrayLike
            Position `(x, y)` in 'pix' coordinates to convert.

        Returns
        -------
        ndarray
            Position `(x, y)` in window units.

        """
        pos = np.asarray(pos, dtype=np.float32)

        if self.win is None:
            return pos

        if self.win.units == 'pix':
            if self.win.useRetina:
                pos /= 2.0
            return pos
        elif self.win.units == 'norm':
            return pos * 2.0 / self.win.size
        elif self.win.units == 'cm':
            return pix2cm(pos, self.win.monitor)
        elif self.win.units == 'deg':
            return pix2deg(pos, self.win.monitor)
        elif self.win.units == 'height':
            return pos / float(self.win.size[1])
예제 #7
0
    def size(self, value):
        """
        :ref:`x,y-pair <attrib-xy>`, :ref:`scalar <attrib-scalar>` or None (resets to default). Supports :ref:`operations <attrib-operations>`.
            Units are inherited from the stimulus.
            Sizes can be negative and can extend beyond the window.

            Example::

                stim.size = 0.8  # Set size to (xsize, ysize) = (0.8, 0.8), quadratic.
                print stim.size  # Outputs array([0.8, 0.8])
                stim.size += (0,5, -0.5)  # make wider and flatter. Is now (1.3, 0.3)

            Tip: if you can see the actual pixel range this corresponds to by
            looking at stim._sizeRendered
        """
        value = val2array(value)  # Check correct user input
        self._requestedSize = value  #to track whether we're just using a default
        # None --> set to default
        if value == None:
            """Set the size to default (e.g. to the size of the loaded image etc)"""
            #calculate new size
            if self._origSize is None:  #not an image from a file
                value = numpy.array([0.5, 0.5])  #this was PsychoPy's original default
            else:
                #we have an image - calculate the size in `units` that matches original pixel size
                if self.units == 'pix': value = numpy.array(self._origSize)
                elif self.units == 'deg': value = pix2deg(numpy.array(self._origSize, float), self.win.monitor)
                elif self.units == 'cm': value = pix2cm(numpy.array(self._origSize, float), self.win.monitor)
                elif self.units == 'norm': value = 2 * numpy.array(self._origSize, float) / self.win.size
                elif self.units == 'height': value = numpy.array(self._origSize, float) / self.win.size[1]
        self.__dict__['size'] = value
        self._calcSizeRendered()
        if hasattr(self, '_calcCyclesPerStim'):
            self._calcCyclesPerStim()
        self._needUpdate = True
예제 #8
0
    def _get_psychopy_pos(self, p, units=None):
        """Convert Tobii ADCS coordinates to PsychoPy coordinates.

        Args:
            p: Gaze position (x, y) in Tobii ADCS.
            units: The PsychoPy coordinate system to use.

        Returns:
            Gaze position in PsychoPy coordinate systems. For example: (0,0).
        """
        if units is None:
            units = self.win.units

        if units == "norm":
            return (2 * p[0] - 1, -2 * p[1] + 1)
        elif units == "height":
            return ((p[0] - 0.5) * (self.win.size[0] / self.win.size[1]),
                    -p[1] + 0.5)
        elif units in ["pix", "cm", "deg", "degFlat", "degFlatPos"]:
            p_pix = self._tobii2pix(p)
            if units == "pix":
                return p_pix
            elif units == "cm":
                return tuple(pix2cm(pos, self.win.monitor) for pos in p_pix)
            elif units == "deg":
                tuple(pix2deg(pos, self.win.monitor) for pos in p_pix)
            else:
                return tuple(
                    pix2deg(np.array(p_pix),
                            self.win.monitor,
                            correctFlat=True))
        else:
            raise ValueError("unit ({}) is not supported.".format(units))
예제 #9
0
파일: event.py 프로젝트: arokem/psychopy
 def _pix2windowUnits(self, pos):
     if self.win.units == "pix":
         return pos
     elif self.win.units == "norm":
         return pos * 2.0 / self.win.size
     elif self.win.units == "cm":
         return pix2cm(pos, self.win.monitor)
     elif self.win.units == "deg":
         return pix2deg(pos, self.win.monitor)
     elif self.win.units == "height":
         return pos / float(self.win.size[1])
예제 #10
0
 def _pix2windowUnits(self, pos):
     if self.win.units == 'pix':
         return pos
     elif self.win.units == 'norm':
         return pos * 2.0 / self.win.size
     elif self.win.units == 'cm':
         return pix2cm(pos, self.win.monitor)
     elif self.win.units == 'deg':
         return pix2deg(pos, self.win.monitor)
     elif self.win.units == 'height':
         return pos / float(self.win.size[1])
예제 #11
0
파일: event.py 프로젝트: mmagnuski/psychopy
 def _pix2windowUnits(self, pos):
     if self.win.units == 'pix':
         return pos
     elif self.win.units == 'norm':
         return pos * 2.0 / self.win.size
     elif self.win.units == 'cm':
         return pix2cm(pos, self.win.monitor)
     elif self.win.units == 'deg':
         return pix2deg(pos, self.win.monitor)
     elif self.win.units == 'height':
         return pos / float(self.win.size[1])
예제 #12
0
    def size(self, value):
        """The size (w,h) of the stimulus in the stimulus :ref:`units <units>`

        Value should be :ref:`x,y-pair <attrib-xy>`, :ref:`scalar <attrib-scalar>` (applies to both dimensions)
        or None (resets to default). :ref:`Operations <attrib-operations>` are supported.

        Sizes can be negative (causes a flip) and can extend beyond the window.

        Example::

            stim.size = 0.8  # Set size to (xsize, ysize) = (0.8, 0.8), quadratic.
            print stim.size  # Outputs array([0.8, 0.8])
            stim.size += (0,5, -0.5)  # make wider and flatter. Is now (1.3, 0.3)

        Tip: if you can see the actual pixel range this corresponds to by
        looking at `stim._sizeRendered`
        """
        value = val2array(value)  # Check correct user input
        self._requestedSize = value  #to track whether we're just using a default
        # None --> set to default
        if value == None:
            """Set the size to default (e.g. to the size of the loaded image etc)"""
            #calculate new size
            if self._origSize is None:  #not an image from a file
                value = numpy.array([0.5, 0.5
                                     ])  #this was PsychoPy's original default
            else:
                #we have an image - calculate the size in `units` that matches original pixel size
                if self.units == 'pix':
                    value = numpy.array(self._origSize)
                elif self.units in ['deg', 'degFlatPos', 'degFlat']:
                    #NB when no size has been set (assume to use orig size in pix) this should not
                    #be corrected for flat anyway, so degFlat==degFlatPos
                    value = pix2deg(numpy.array(self._origSize, float),
                                    self.win.monitor)
                elif self.units == 'norm':
                    value = 2 * numpy.array(self._origSize,
                                            float) / self.win.size
                elif self.units == 'height':
                    value = numpy.array(self._origSize,
                                        float) / self.win.size[1]
                elif self.units == 'cm':
                    value = pix2cm(numpy.array(self._origSize, float),
                                   self.win.monitor)
                else:
                    raise AttributeError, "Failed to create default size for ImageStim. Unsupported unit, %s" % (
                        repr(self.units))
        self.__dict__['size'] = value
        self._needVertexUpdate = True
        self._needUpdate = True
        if hasattr(self, '_calcCyclesPerStim'):
            self._calcCyclesPerStim()
예제 #13
0
    def size(self, value):
        """The size (w,h) of the stimulus in the stimulus :ref:`units <units>`

        Value should be :ref:`x,y-pair <attrib-xy>`, :ref:`scalar <attrib-scalar>` (applies to both dimensions)
        or None (resets to default). :ref:`Operations <attrib-operations>` are supported.

        Sizes can be negative (causing a mirror-image reversal) and can extend beyond the window.

        Example::

            stim.size = 0.8  # Set size to (xsize, ysize) = (0.8, 0.8), quadratic.
            print stim.size  # Outputs array([0.8, 0.8])
            stim.size += (0.5, -0.5)  # make wider and flatter. Is now (1.3, 0.3)

        Tip: if you can see the actual pixel range this corresponds to by
        looking at `stim._sizeRendered`
        """
        value = val2array(value)  # Check correct user input
        self._requestedSize = value  #to track whether we're just using a default
        # None --> set to default
        if value == None:
            """Set the size to default (e.g. to the size of the loaded image etc)"""
            #calculate new size
            if self._origSize is None:  #not an image from a file
                value = numpy.array([0.5, 0.5])  #this was PsychoPy's original default
            else:
                #we have an image - calculate the size in `units` that matches original pixel size
                if self.units == 'pix':
                    value = numpy.array(self._origSize)
                elif self.units in ['deg', 'degFlatPos', 'degFlat']:
                    #NB when no size has been set (assume to use orig size in pix) this should not
                    #be corrected for flat anyway, so degFlat==degFlatPos
                    value = pix2deg(numpy.array(self._origSize, float), self.win.monitor)
                elif self.units == 'norm':
                    value = 2 * numpy.array(self._origSize, float) / self.win.size
                elif self.units == 'height':
                    value = numpy.array(self._origSize, float) / self.win.size[1]
                elif self.units == 'cm':
                    value = pix2cm(numpy.array(self._origSize, float), self.win.monitor)
                else:
                    raise AttributeError, "Failed to create default size for ImageStim. Unsupported unit, %s" %(repr(self.units))
        self.__dict__['size'] = value
        self._needVertexUpdate=True
        self._needUpdate = True
        if hasattr(self, '_calcCyclesPerStim'):
            self._calcCyclesPerStim()
예제 #14
0
def save_stim(x, y, contrast, name):
    screen_size = 100

    win = visual.Window(size=(screen_size, screen_size),
                        fullscr=False,
                        screen=0,
                        allowGUI=False,
                        allowStencil=False,
                        monitor='testMonitor',
                        color=[0, 0, 0],
                        colorSpace='rgb',
                        blendMode='avg',
                        useFBO=False)

    mon = Monitor('testMonitor')
    mon.setWidth(29.0)
    mon.setSizePix((1440, 900))
    cm_per_pix = pix2cm(1, mon)

    cont = contrast

    grating = visual.GratingStim(win,
                                 units='pix',
                                 mask='circle',
                                 sf=x * cm_per_pix,
                                 ori=y,
                                 pos=(0, 0),
                                 contrast=cont,
                                 size=(2 / cm_per_pix, 2 / cm_per_pix),
                                 interpolate=True,
                                 texRes=2048)

    grating.draw()
    win.flip()
    win.getMovieFrame()
    win.saveMovieFrames(name)
예제 #15
0
    def __init__(self, params=None, reportobj=None, subroutines=[]):
        logging.LogFile(params['cwd'] + os.sep + params['logfile'],
                        level=logging.INFO,
                        filemode='w')
        logging.LogFile(level=logging.ERROR)

        logging.info('Using Python ' + sys.version)

        self.args = sys.argv
        self.params = self.update_params(self.args, params)
        self.win = None
        self.model = None
        self.routines = subroutines
        self.thisExp = None
        self.name = params['name']
        self.cwd = params['cwd']
        self.reportobj = reportobj

        if params['monitor'] not in monitors.getAllMonitors():
            logging.error('monitor not found: ' + params.monitor)
            logging.info('available monitors: ' +
                         ' '.join(monitors.getAllMonitors()))
            logging.info('Define monitor in monitor center.')
            logging.info('To launch monitor center, type:\n'
                         'python -m psychopy.monitors.MonitorCenter')
            core.quit()
        else:
            self.monitor = monitors.Monitor(
                '',
                width=None,
                distance=self.params['viewing_distance'],
                gamma=None,
                notes=None,
                useBits=None,
                verbose=True,
                currentCalib=None,
                autoLog=True)
            self.monitor.setSizePix((1920, 1280))
            self.monitor.setWidth(54.15)

            logging.exp('using monitor: ' + self.params['monitor'] +
                        ' with viewing_distance=' +
                        str(self.params['viewing_distance']) + ' cm\n' +
                        ' resolution (pixel/deg): ' +
                        str(deg2pix(1, self.monitor)))
            # TODO: change screen_pixel_size back to calculation from monitor
            # TODO: change the monitor definition width so that screen_pixel_size=0.282
            if 'screen_pixel_size' not in self.params['model']:
                self.params['model']['screen_pixel_size'] = pix2cm(
                    1, self.monitor) * 10.0

            #self.params['model']['screen_pixel_size'] = 0.282
            self.params['model'][
                'viewing_distance'] = self.params['viewing_distance'] / 2.54

        self.expInfo = params['exp_info']
        self.expInfo['date'] = data.getDateStr()

        # Ensure that relative paths start from the same directory as this script
        _thisDir = os.path.dirname(os.path.abspath(__file__))
        os.chdir(_thisDir)
        # Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
        runsubject = self.params['runsubject']
        if runsubject:
            self.filename = self.cwd + os.sep + u'data' + os.sep + '%s_%s_%s' % (
                self.expInfo['participant'], params['name'],
                self.expInfo['date'])
        else:
            self.filename = self.cwd + os.sep + u'data' + os.sep + 'model-' + params[
                'expName']
예제 #16
0
def TransformStim(xin, yin):

    #initialize variable, transfer labels
    trans_y = np.zeros(np.shape(xin)[0])

    # Convert x values; as long as input's x-values are in 0-100 space, this
    # line linearly transforms those values to -1:2 space; to choose
    # a different range, simply change the linear scaling, but be sure to
    # change the scaling for the y transformation as well so the ratio of the
    # axes remains the same.
    trans_x = (xin / 100) * 3 - 0.5
    # trans_x = (xin / 100) * 3 - 1

    # Nonlinear conversion of x values: trans_x exponentiated, resulting in a
    # range of .5-4 for CPD. DO NOT CHANGE.
    trans_x = 2**trans_x

    # Y values should also be in 0-100; negative values in particular cause
    # problems.
    if np.any(xin < 0) or np.any(yin < 0):
        print('Negative value for input!')

    # Linear conversion of y values to pi/11:(3*pi/8+pi/11) space. Again,
    # different ranges and bounds can be chosen at this step.
    # y = (yin / 100) * ((3 * np.pi / 8) + (np.pi / 11))
    y = (yin / 100) * ((3 * np.pi / 8) + (np.pi / 9))

    # The remainder of the code performs the nonlinear transformation on the y
    # values, which remain in the same space, but warped. DO NOT CHANGE.
    ind = np.argsort(y)
    sort_y = y[ind]
    z = 4.7 * np.sin(sort_y)**2

    trans_y[0] = np.sqrt(sort_y[0]**2 + z[0]**2)

    for i in range(1, np.shape(sort_y)[0]):
        trans_y[i] = trans_y[i - 1] + np.sqrt(
            np.power(sort_y[i] - sort_y[i - 1], 2) +
            np.power(z[i] - z[i - 1], 2))

    range_trans_y = np.amax(trans_y) - np.amin(trans_y)
    range_sort_y = np.amax(sort_y) - np.amin(sort_y)

    trans_y = trans_y / range_trans_y * range_sort_y
    trans_y = trans_y - np.min(trans_y) + np.min(sort_y)

    # NOTE: Convert radians to degrees
    trans_y = trans_y * 180 / np.pi

    xout = trans_x
    yout = np.zeros(np.shape(xin)[0])
    for i in range(0, len(ind)):
        yout[ind[i]] = trans_y[i]

    # NOTE: Convert Cycles per degree to cycles per cm
    mon = Monitor('testMonitor')
    mon.distance = 20.0  # viewing distance in cm
    xout = xout * (pix2deg(1, mon) / pix2cm(1, mon))

    # xout = (xin / 100) * 5 + 1
    # yout = (yin / 100) * 90

    return ([xout, yout])
예제 #17
0
 def pix2cmcoord(self, x, y, display_index=None):
     # print2err('Display {0} bounds: {1}'.format(display_index,self.getBounds()))
     if display_index == self.getIndex():
         ppx, ppy = display2psychopyPix(x, y)
         return pix2cm(ppx, self._psychopy_monitor), pix2cm(ppy, self._psychopy_monitor)
     return x, y