コード例 #1
0
    def __report_incomplete(self, participant_ids):

        log_path = os.path.join(P.local_dir,
                                "uninitialized_users_{0}".format(now(True)))
        log = io.open(log_path, "w+", encoding='utf-8')
        p_cols = [
            'user_id', 'session_structure', 'session_count',
            'sessions_completed', 'figure_set', 'handedness', 'created'
        ]
        header = p_cols + ["session_rows", "trial_rows"]
        log.write("\t".join(header))
        for p in participant_ids:
            data = self.db_select('participants', p_cols, where={'id':
                                                                 p[0]})[0]
            num_sessions = len(
                self.db_select('sessions', ['id'],
                               where={'participant_id': p[0]}))
            num_trials = len(
                self.db_select('trials', ['id'],
                               where={'participant_id': p[0]}))
            data += [num_sessions, num_trials]
            log.write("\n")
            log.write("\t".join([utf8(i) for i in data]))
        log.close()
        self.exp.quit()
コード例 #2
0
    def clean_up(self):

        if self.session_number == self.session_count and P.enable_learned_figures_querying:
            self.fig_dir = os.path.join(self.p_dir, "learned")
            if not os.path.exists(self.fig_dir):
                os.makedirs(self.fig_dir)

            learned_fig_num = 1
            if query(user_queries.experimental[3]) == "y":
                self.origin_pos = (P.screen_c[0], int(P.screen_y * 0.8))
                self.origin_boundary = [self.origin_pos, P.origin_size // 2]
                while True:
                    self.setup_response_collector()
                    self.rc.draw_listener.add_boundaries([
                        ('start', self.origin_boundary, CIRCLE_BOUNDARY),
                        ('stop', self.origin_boundary, CIRCLE_BOUNDARY)
                    ])
                    self.start_trial_button()
                    self.capture_learned_figure(learned_fig_num)
                    if query(user_queries.experimental[4]) == "y":
                        learned_fig_num += 1
                    else:
                        break

        # if the entire experiment is successfully completed, update the sessions_completed column
        q_str = "UPDATE `participants` SET `sessions_completed` = ? WHERE `id` = ?"
        self.db.query(q_str,
                      QUERY_UPD,
                      q_vars=[self.session_number, P.participant_id])

        # log session data to database
        session_data = {
            'participant_id': P.participant_id,
            'user_id': self.user_id,
            'session_number': self.session_number,
            'completed': now(True)
        }
        self.db.insert(session_data, "sessions")

        # show 'experiment complete' message before exiting experiment
        msg = message(P.experiment_complete_message,
                      "instructions",
                      blit_txt=False)
        flush()
        fill()
        blit(msg, registration=5, location=P.screen_c)
        flip()
        any_key()
コード例 #3
0
	def start(self, trial_number):
		"""Starts recording simulated eye events from the mouse cursor.
		
		Called automatically at the start of each trial unless ``P.manual_eyelink_recording`` is
		True, in which case it must be called manually in order to start recording eye events and
		gaze position from the eye tracker. To stop recording after this method is called, use the
		:meth:`stop` method.

		Args:
			trial_number (int): The current trial number. Used to mark the start of the trial in
				the data files of eye trackers that support data markup.

		"""
		self.local_start_time = now()
		self.__recording = True
		self.tracker_start_time = self.now()
		return 0
コード例 #4
0
 def file_name(self):
     file_name_data = [
         P.participant_id, P.block_number, P.trial_number,
         now(True, "%Y-%m-%d"), self.session_number
     ]
     return "p{0}_s{4}_b{1}_t{2}_{3}".format(*file_name_data)
コード例 #5
0
def collect_demographics(anonymous=False):
    '''Collects participant demographics and writes them to the 'participants' table in the
	experiment's database, based on the queries in the "demographic" section of the project's
	user_queries.json file.
	
	If P.manual_demographics_collection = True, this function should be called at some point during
	the setup() section of your experiment class. Otherwise, this function will be run
	automatically when the experiment is launched.

	Args:
		anonymous (bool, optional): If True, this function will log all of the anonymous values for
			the experiment's demographic queries to the database immediately without prompting the
			user for input.

	'''
    from klibs.KLEnvironment import exp, db

    # ie. demographic questions aren't being asked for this experiment
    if not P.collect_demographics and not anonymous: return

    # first insert required, automatically-populated fields
    demographics = EntryTemplate('participants')
    demographics.log('created', now(True))
    try:
        # columns moved to session_info in newer templates
        demographics.log("random_seed", P.random_seed)
        demographics.log("klibs_commit", P.klibs_commit)
    except ValueError:
        pass

    # collect a response and handle errors for each question
    for q in user_queries.demographic:
        if q.active:
            # if querying unique identifier, make sure it doesn't already exist in db
            if q.database_field == P.unique_identifier:
                # TODO: fix this to work with multi-user mode
                existing = db.query("SELECT `{0}` FROM `participants`".format(
                    q.database_field))
                while True:
                    value = query(q, anonymous=anonymous)
                    if utf8(value) in [utf8(val[0]) for val in existing]:
                        err = ("A participant with that ID already exists!\n"
                               "Please try a different identifier.")
                        fill()
                        blit(
                            message(err,
                                    "alert",
                                    align='center',
                                    blit_txt=False), 5, P.screen_c)
                        flip()
                        any_key()
                    else:
                        break
            else:
                value = query(q, anonymous=anonymous)
            demographics.log(q.database_field, value)

    # typical use; P.collect_demographics is True and called automatically by klibs
    if not P.demographics_collected:
        P.participant_id = db.insert(demographics)
        P.p_id = P.participant_id
        P.demographics_collected = True
        # Log info about current runtime environment to database
        if 'session_info' in db.table_schemas.keys():
            runtime_info = EntryTemplate('session_info')
            for col, value in runtime_info_init().items():
                runtime_info.log(col, value)
            db.insert(runtime_info)
        # Save copy of experiment.py and config files as they were for participant
        if not P.development_mode:
            pid = P.random_seed if P.multi_user else P.participant_id  # pid set at end for multiuser
            P.version_dir = join(P.versions_dir,
                                 "p{0}_{1}".format(pid, now(True)))
            os.mkdir(P.version_dir)
            copyfile("experiment.py", join(P.version_dir, "experiment.py"))
            copytree(P.config_dir, join(P.version_dir, "Config"))
    else:
        #  The context for this is: collect_demographics is set to false but then explicitly called later
        db.update(demographics.table, demographics.defined)

    if P.multi_session_project and not P.manual_demographics_collection:
        try:
            exp.init_session()
        except:
            pass