Repository: psychopy/psychopy

Issue:
Builder: rating scale is broken
Hi

The rating scale element in Builder has some shortcomings (when using as visual analog scale at least):
1. It produces incorrect code if the slider is `glow` and therefor doesn't run.
The resulting code inserts twice the `markerExpansion` keyword.
`
valence_rating = visual.RatingScale(win=win, name='valence_rating', marker=u'glow', markerExpansion=5, size=1.0, pos=[0.0, -0.4], low=0, high=1, precision=100, showValue=False, markerExpansion=0, scale=u'Wie f\xfchlen Sie sich gerade?')
`
2. It ignore the 'low' and 'high' values, eg. defined as 0, 10 (integers) and produces `low=0, high=1` arguments.
3. It ignores the labels. Eg. 'negativ', 'positiv' also results in `low=0, high=1` arguments.



Discussion:
Hi, sorry for the delayed response but I've found a fix for all of your issues. The marker expansion issue was definitely a bug and will be fixed as soon as I submit a PR for it.

However I think your other issues are worth discussing, as they seemed to be hardcoded very intentionally.  If its a visual analog scale, change low and high to 0 and 1 respectively. Also it purposely ignores any labels you pass if you're using the rating scale as a visual analog scale. Unfortunately I wasn't around when this was initially coded so I'm hesitant to make large feature changes.

@hoechenberger do you know the reason behind hardcoding these values to the VAS from the builder?
https://github.com/psychopy/psychopy/blob/f5c1b5a40dc988721b28935755c74b343ce9cb83/psychopy/app/builder/components/ratingScale/__init__.py#L226-L230


The markerExpansion duplication is definitely a bug, should be fixed.

The visual analog scale lack of features were intentional. This idea is to be a visual analog (spatial), not symbolic and or quantitative representations (verbal or numerical). Its intended to avoid being a "1 to 10" scale. Using 0-1 as endpoints means that no intermediate tick marks will be drawn on the screen. Similarly, labels are suppressed to avoid having words on-screen. (That was the idea, maybe labels should be allowed?)

Another consideration is that the options in the builder are intentional simplifications. Rating scale is complex, and takes a LOT of options. Part of the intent of the Builder interface is to reduce that flexibility. The customize-everything option is still available for people who want more control -- in fact, anything doable can be done through that option.

Resolving patch:
diff --git a/psychopy/experiment/components/ratingScale/__init__.py b/psychopy/experiment/components/ratingScale/__init__.py
--- a/psychopy/experiment/components/ratingScale/__init__.py
+++ b/psychopy/experiment/components/ratingScale/__init__.py
@@ -230,7 +230,7 @@ def writeInitCode(self, buff):
             choices = str(self.params['categoryChoices'].val)
             if self.params['visualAnalogScale'].val:
                 init_str += (", low=0, high=1, precision=100, "
-                             "showValue=False, markerExpansion=0")
+                             "showValue=False")
                 if not self.params['marker'].val:
                     init_str += ", marker='glow'"
             elif len(choices):
diff --git a/psychopy/visual/ratingscale.py b/psychopy/visual/ratingscale.py
--- a/psychopy/visual/ratingscale.py
+++ b/psychopy/visual/ratingscale.py
@@ -12,7 +12,6 @@
 from builtins import str
 from builtins import range
 from past.builtins import basestring
-import copy
 import sys
 import numpy
 
@@ -813,7 +812,7 @@ def _initMarker(self, marker, markerColor, expansion):
             if markerColor is None or not isValidColor(markerColor):
                 markerColor = 'White'
             self.marker = PatchStim(win=self.win, units='norm',
-                                    tex='sin', mask='gauss',
+                                    tex=None, mask='gauss',
                                     color=markerColor, opacity=0.85,
                                     autoLog=False,
                                     name=self.name + '.markerGlow')
@@ -858,7 +857,6 @@ def _initMarker(self, marker, markerColor, expansion):
         self.markerColor = markerColor
         self.markerYpos = self.offsetVert + self.markerOffsetVert
         # save initial state, restore on reset
-        self.markerOrig = copy.copy(self.marker)
 
     def _initTextElements(self, win, scale, textColor,
                           textFont, textSize, showValue, tickMarks):
@@ -1304,7 +1302,10 @@ def reset(self, log=True):
         # ratingScale instance is used by a subject
         self.noResponse = True
         # restore in case it turned gray, etc
-        self.marker = copy.copy(self.markerOrig)
+        self.resetMarker = str(self.marker)
+        self.resetMarker = self.resetMarker.replace('Window(...)', 'self.win')
+        self.resetMarker = self.resetMarker.replace('white', 'red')
+
         # placed by subject or markerStart: show on screen
         self.markerPlaced = False
         # placed by subject is actionable: show value, singleClick


Test patch: