/
custom.py
152 lines (123 loc) · 5.13 KB
/
custom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# this file imports custom routes into the experiment server
from flask import Blueprint, render_template, request, jsonify, Response, abort, current_app #, session
from jinja2 import TemplateNotFound
from functools import wraps
from sqlalchemy import or_
from psiturk.psiturk_config import PsiturkConfig
from psiturk.experiment_errors import ExperimentError
from psiturk.user_utils import PsiTurkAuthorization, nocache
# # Database setup
from psiturk.db import db_session, init_db
from psiturk.models import Participant
from json import dumps, loads
# for basic experiment setup
from numpy import linspace, fromstring
from numpy import array as npa
from numpy.random import RandomState
# load the configuration options
config = PsiturkConfig()
config.load_config()
myauth = PsiTurkAuthorization(config) # if you want to add a password protect route use this
# explore the Blueprint
custom_code = Blueprint('custom_code', __name__, template_folder='templates', static_folder='static')
import bayesOptExperiment as boe
from jbutils import make_domain_grid, jsonToNpa, unpack_rngstate, pack_rngstate
from time import time
# with open('secretkey', 'r') as f: SECRETKEY = f.read().splitlines()[0]
## EXPERIMENT FREE VARS
COSTTODRILL = 50
COSTTOSAMPLE = 0
INITSCORE = 0
# gp params
SIGVAR = 1.
NOISEVAR2 = 1e-7
NPASSIVEPOOL = [0, 1, 2, 3, 4] # how many obs you start with
NACTIVEPOOL = [2, 3, 4, 5, 6] # how many more samples subj takes before interrogation
NTRIALTYPE = len(NACTIVEPOOL) * len(NPASSIVEPOOL)
NPERTRIALTYPE = 5
NTRIAL = NTRIALTYPE * NPERTRIALTYPE
assert NTRIAL % NTRIALTYPE == 0 # assert equal amount of every trial type
LENSCALEPOWSOF2 = [2., 4., 6.]
LENSCALEPOOL = [1./2.**n for n in LENSCALEPOWSOF2]
DOMAINBOUNDS = [[0., 1.]]
DOMAINRES = 1024
DOMAIN = make_domain_grid(DOMAINBOUNDS, DOMAINRES).flatten()
EDGEBUF = 0.05 # samples for 2sams wont be closer than EDGEBUF from screen edge
# how close to domain edges passive observations can occur
XSAM_BOUNDS = [dim[:] for dim in DOMAINBOUNDS] # deep copy of DOMAINBOUNDS
XSAM_BOUNDS[0][0] = EDGEBUF
XSAM_BOUNDS[0][1] -= EDGEBUF
# made with numpy.random.randint(4294967295, size=20) # (number is max allowed on amazon linux)
RNGSEEDPOOL =\
npa([1903799985, 1543581047, 1218602148, 764353219, 1906699770,
951675775, 2101131205, 1792109879, 781776608, 2388543424,
2154736893, 2773127409, 3304953852, 678883645, 3097437001,
3696226994, 242457524, 991216532, 2747458246, 2432174005])
## LOAD GP STUFF INTO WORKSPACE
@custom_code.route('/init_experiment', methods=['GET'])
def init_experiment():
if not request.args.has_key('condition'):
raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this
condition = int(request.args['condition'])
counterbalance = int(request.args['counterbalance'])
## END FREE VARS
lenscale = LENSCALEPOOL[condition]
rngseed = RNGSEEDPOOL[counterbalance]
rng = RandomState(rngseed)
experParams = {
'nTrial': NTRIAL,
'nPassivePool': NPASSIVEPOOL,
'nActivePool': NACTIVEPOOL,
'rng': rng
}
subParams = boe.make_experiment(**experParams)
# bundle response to send
resp = {}
for f in subParams:
try:
resp[f] = subParams[f].tolist()
except:
resp[f] = subParams[f]
for f in experParams:
if f is not 'rng': # don't pass the random number generator
try: # convet numpy array to list if possible
resp[f] = experParams[f].tolist()
except:
resp[f] = experParams[f]
resp['itrial'] = -1
resp['isam3'] = -1
resp['nTrial'] = NTRIAL
resp['costToDrill'] = COSTTODRILL
resp['costToSample'] = COSTTOSAMPLE
resp['initscore'] = INITSCORE
resp['lenscale'] = lenscale
resp['sigvar'] = SIGVAR
resp['domainbounds'] = DOMAINBOUNDS
resp['domainres'] = DOMAINRES
resp['edgebuf'] = EDGEBUF
resp['rngstate'] = pack_rngstate(rng.get_state())
return jsonify(**resp)
@custom_code.route('/make_trial', methods=['POST'])
def make_trial():
try:
# t0 = time()
# args:
# lenscale
# nPassiveObs
# rngstate
params = request.json # works when ajax request contentType specified as "applications/json"
# unpack random number generator
rng = RandomState()
rngstate = unpack_rngstate(params['rngstate'])
rng.set_state(rngstate)
lenscale = float(params['lenscale'])
nPassiveObs = int(params['nPassiveObs'])
thisTri = boe.make_trial(nPassiveObs, DOMAIN, lenscale, SIGVAR, NOISEVAR2, XSAM_BOUNDS, rng)
resp = {'sample': thisTri['sample'].tolist(),
'xObs': thisTri['xObs'].flatten().tolist(),
'yObs': thisTri['yObs'].tolist(),
'iObs': thisTri['iObs'].tolist(),
'rngstate': pack_rngstate(rng.get_state())}
except:
raise ExperimentError('improper_inputs') # i don't like returning HTML to JSON requests... maybe should change this
return jsonify(**resp)