PennController for IBEX › Forums › Support › running penncontroller locally
- This topic has 13 replies, 6 voices, and was last updated 4 months, 1 week ago by dod.
-
AuthorPosts
-
March 19, 2019 at 11:35 am #2969camiloGuest
hi,
I am trying to run an instance of IBEX locally to use in a computer in the lab with no internet access. It works fine for regular ibex experiments, but since the penncontroller requires access to an online server to load images and audio (when calling “PennController.AddHost”) I am not sure how to get it to do this locally. How can i get it to check a local folder on the computer instead of an online server?
thanks a lot for the help (and for penncontroller in general, its awesome 🙂 )March 19, 2019 at 8:01 pm #2976JeremyKeymasterHi Camilo,
Are you running you IBEX instance on Mac OS? If so, you can place your image and audio files in
/Library/WebServer/Documents/
(or~/Sites/
) and then access it at, e.g.http://localhost/myImage.png
. So this should work:PennController.AddHost("http://localhost/"); PennController( newImage("my image", "myImage.png") .print() , newButton("continue", "Continue") .print() .wait() )
Alternatively you can edit the file
server.py
in your experiment’swww
folder and, below these two lines:if fname.endswith(".wav") or fname.endswith(".mp3") or fname.endswith("m4a"): continue
add
if fname.endswith(".png") or fname.endswith(".jpg") or fname.endswith(".bmp"): continue
And further down, replace this line:
start_response('200 OK', [('Content-Type', 'audio/mpeg'), ('Content-Length', stats.st_size)])
withif qs_hash['resource'][0].endswith(".wav") or qs_hash['resource'][0].endswith(".mp3") or qs_hash['resource'][0].endswith(".m4a"): start_response('200 OK', [('Content-Type', 'audio/mpeg'), ('Content-Length', stats.st_size)]) elif qs_hash['resource'][0].endswith(".png") or qs_hash['resource'][0].endswith(".jpg") or qs_hash['resource'][0].endswith(".bmp"): start_response('200 OK', [('Content-Type', 'image/*'), ('Content-Length', stats.st_size)])
Then you can place your image and audio files (though no OGG file) in chunk_includes and do this:
PennController( newImage("my image", "http://localhost:3000/server.py?resource=myImage.png") .print() , newButton("continue", "Continue") .print() .wait() )
March 26, 2019 at 3:50 pm #2983camiloGuestHi Jeremy,
wow, thanks so much for the detailed response! Unfortunately neither of these solutions worked for me. The first one (for mac) keeps spitting out this error in the terminal running the server.py:
127.0.0.1 - - [26/Mar/2019 16:35:10] "GET /picture.jpg HTTP/1.1" 404 -
I don’t know what it means, but it seems to not be able to connect to the local server (I saved all the pictures to /Library/WebServer/Documents/)
The experiment runs fine otherwise and goes through all items, it just doesnt show any of the pictures.
The second solution, working on a windows, seems to be even trickier, since the experiment doesn’t run at all, it gets stuck trying to load the images. the output of server.py shows a lot of stuff that I (again) have no idea what it means:
127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /experiment.html HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /jquery.min.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /jquery-ui.min.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /jsDump.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /PluginDetect.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /server.py?include=serverinfo_js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /shuffle.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /json.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /soundmanager2-jsmin.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /backcompatcruft.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /server.py?include=data HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /conf.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:02] "GET /server.py?include=js HTTP/1.1" 200 - ../css_includes127.0.0.1 - - [26/Mar/2019 15:32:03] "GET /server.py?include=main.js HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:03] "GET /server.py?include=css HTTP/1.1" 200 - 127.0.0.1 - - [26/Mar/2019 15:32:03] "GET /util.js HTTP/1.1" 200 - -------------------------------------------------------------------------------- Exception happened during processing of request fromException happened during processing of request from ( ----------------------------------------'1 27.0.0.(1'Exception happened during processing of request from', 127.0.0.1'50483(', 12----------------------------------------7.0.0.1' ), 50484Exception happened during processing of request from 50485T)raceback (most recent call last): ) File "C:\Python27\lib\SocketServer.py", line 599, in process_request_thread (Traceback (most recent call last): 'T1raceback (most recent call last): 2 7 File "C:\Python27\lib\SocketServer.py", line 599, in process_request_thread . 0 File "C:\Python27\lib\SocketServer.py", line 599, in process_request_thread . 0 self.finish_request(request, client_address) . 1 self.finish_request(request, client_address) ' , self.finish_request(request, client_address) 50486 ) File "C:\Python27\lib\SocketServer.py", line 334, in finish_request File "C:\Python27\lib\SocketServer.py", line 334, in finish_request File "C:\Python27\lib\SocketServer.py", line 334, in finish_request self.RequestHandlerClass(request, client_address, self) self.RequestHandlerClass(request, client_address, self) Traceback (most recent call last): File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1775, in __init__ - File "C:\Python27\lib\SocketServer.py", line 599, in process_request_thread --------------------------------------- File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1775, in __init__ E xception happened during processing of request from SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) ( self.finish_request(request, client_address) '1 2 File "C:\Python27\lib\SocketServer.py", line 334, in finish_request 7 . self.RequestHandlerClass(request, client_address, self) 0 . File "C:\Python27\lib\SocketServer.py", line 655, in __init__ 0 . SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) 1 ' self.handle() - ---------------------------------------, File "C:\Python27\lib\SocketServer.py", line 655, in __init__ 50487 File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1775, in __init__ E xception happened during processing of request from File "C:\Python27\lib\BaseHTTPServer.py", line 340, in handle () self.RequestHandlerClass(request, client_address, self) ' 1 self.handle() 2 SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) 7 . self.handle_one_request() 0 . File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1775, in __init__ 0 . File "C:\Python27\lib\BaseHTTPServer.py", line 340, in handle 1T'raceback (most recent call last): , 50488 self.handle_one_request() ) File "C:\Python27\lib\SocketServer.py", line 599, in process_request_thread Traceback (most recent call last): self.finish_request(request, client_address) File "C:\Python27\lib\SocketServer.py", line 334, in finish_request File "C:\Python27\lib\BaseHTTPServer.py", line 328, in handle_one_request self.RequestHandlerClass(request, client_address, self) File "C:\Python27\lib\SocketServer.py", line 599, in process_request_thread SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) self.finish_request(request, client_address) File "C:\Python27\lib\BaseHTTPServer.py", line 328, in handle_one_request method() File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1775, in __init__ File "C:\Python27\lib\SocketServer.py", line 655, in __init__ File "C:\Python27\lib\SocketServer.py", line 655, in __init__ File "C:\Python27\lib\SocketServer.py", line 334, in finish_request method() File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1829, in do_GET SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) File "C:\Python27\lib\SocketServer.py", line 655, in __init__ self.handle() self.RequestHandlerClass(request, client_address, self) File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1829, in do_GET self.do_either('GET') File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1813, in do_either self.handle() File "C:\Python27\lib\BaseHTTPServer.py", line 340, in handle File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1775, in __init__ self.do_either('GET') SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) assert response_type[0] File "C:\Python27\lib\BaseHTTPServer.py", line 340, in handle self.handle_one_request() File "D:\ADMIN_Experiments\Ibex\ibex-master\www\server.py", line 1813, in do_either self.handle() File "C:\Python27\lib\SocketServer.py", line 655, in __init__ AssertionError ---------------------------------------- self.handle_one_request() File "C:\Python27\lib\BaseHTTPServer.py", line 328, in handle_one_request assert response_type[0] method() self.handle() File "C:\Python27\lib\BaseHTTPServer.py", line 328, in handle_one_request File "C:\Python27\lib\BaseHTTPServer.py", line 340, in handle - method()
(This is just the first part of the output)
I really have no idea how to make this work, any help would be immensly appreciated!
March 26, 2019 at 5:29 pm #2984JeremyKeymasterHi Camilo,
1. Have you tried placing your images in
~/Sites/
as well?2. The errors could be due to hidden files in chunk_includes. On Mac, Finder automatically generates .DS_Store in some folders, which usually causes Ibex to crash. I usually solve the problem in the Terminal, I move to the chunk_includes folder and I type
rm .DS_Store
.This is an archive of the experiment I successfully ran on my Mac, if you want to try it yourself (and/or copy the
server.py
file in case you have doubts on the edits I describe in my previous message):
https://www.dropbox.com/s/x62tvt20e775i8m/ibex-local.zip?dl=0- This reply was modified 5 years, 6 months ago by PennController.
March 26, 2019 at 10:57 pm #2985Thao TranGuestBasically what is needed is are a webserver, that serves static files (jpg, mp3, etc), to be installed locally on your machine. There are many way to do that. Using Python httpserver is a portable and quick way, which is possible on any OS with python installed. For windows there is an instruction here: https://stackoverflow.com/a/5128451. See also other answers.
That approach may seem dirty (but it should work!). More elegantly, Ibex server seems to use SimpleHttpserver already, so it is possible to configure it to serves static files from a folder in ibex folder structure (e.g., using relative path). This however requires some programming skill.
July 29, 2020 at 5:09 pm #5877mat646ParticipantThank you all! Came across this thread when I tried to figure out how to run locally, and wanted to share what worked for me in case anyone else runs into any problems or has no prior knowledge about running anything via a local server.
Instructions for computer with Windows 10 and zero knowledge about local servers:
Before running experiment locally:
– download (zipped folder of everything) IBEX here: https://github.com/addrummond/ibex
– unpack somewhere accessible on your computer (e.g. desktop)
– download your zipped ibexfarm/pcibexfarm experiment file structure
– replace sample files from IBEX with your experiment files (most important = experiment script from data_includes and data/html pages from chunck_includes)To use locally stored images/sounds follow Jeremy’s instructions (repeated here):
edit the file server.py in your experiment’s www folder and, below these two lines:if fname.endswith(".wav") or fname.endswith(".mp3") or fname.endswith("m4a"): continue
add
if fname.endswith(".png") or fname.endswith(".jpg") or fname.endswith(".bmp"): continue
And further down, replace this line:
start_response('200 OK', [('Content-Type', 'audio/mpeg'), ('Content-Length', stats.st_size)])
withif qs_hash['resource'][0].endswith(".wav") or qs_hash['resource'][0].endswith(".mp3") or qs_hash['resource'][0].endswith(".m4a"): start_response('200 OK', [('Content-Type', 'audio/mpeg'), ('Content-Length', stats.st_size)]) elif qs_hash['resource'][0].endswith(".png") or qs_hash['resource'][0].endswith(".jpg") or qs_hash['resource'][0].endswith(".bmp"): start_response('200 OK', [('Content-Type', 'image/*'), ('Content-Length', stats.st_size)])
–> I first got an indentation error that was fixed by copy-pasting the indentation of a prior if line (don’t know why, but worked)
Then you can place your image and audio files (though no OGG file) in the chunk_includes folder
–> I did not need to change anything about the referencing in my script.js so after changing the lines above I could just refer to the stimuli as follows:
PennController( newImage("my image", "Image.png") .print() , newButton("continue", "Continue") .print() .wait() )
Now to run experiment locally:
-make sure python 2.7 is installed on your computer
-open windows command prompt (cmd)
-change directories to the ‘www’ folder of your local version of Ibex
e.g.cd C:\Users\maxim\desktop\ibex-master\www
– open server (SimpleHttpserver)
python server.py
Now open your browser and go to:
http://localhost:3000/experiment.htmlYour experiment should run.
December 2, 2020 at 9:38 pm #6430mat646ParticipantCorrection, I lied before (without realizing), following the steps above you SHOULD change something about the image referencing:
You should now refer to the stimuli as follows (like Jeremy pointed out also in this thread):
PennController( newImage("my image", "http://127.0.0.1:3000/server.py?resource=Image.png") .print() , newButton("continue", "Continue") .print() .wait() )
(127.0.0.1 refers to your local host and :3000 stands for port 3000)
May 21, 2022 at 1:55 pm #8199suleymanyamanParticipantHello,
Sorry for resurrecting an old thread. Is there anyone who is able to run their experiments with the current version of PciBex? I followed the instructions of mat646, and got the following python error in the terminal (Windows10). I only get the usual black loading screen when I go to http://localhost:3000/experiment.html after running server.py. Is there a solution for this?
—————————————-
Exception happened during processing of request from (‘127.0.0.1’, 62154)
Traceback (most recent call last):
File “C:\Python27\lib\SocketServer.py”, line 599, in process_request_thread
self.finish_request(request, client_address)
File “C:\Python27\lib\SocketServer.py”, line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File “server.py”, line 1770, in __init__
SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
File “C:\Python27\lib\SocketServer.py”, line 655, in __init__
self.handle()
File “C:\Python27\lib\BaseHTTPServer.py”, line 340, in handle
self.handle_one_request()
File “C:\Python27\lib\BaseHTTPServer.py”, line 328, in handle_one_request
method()
File “server.py”, line 1824, in do_GET
self.do_either(‘GET’)
File “server.py”, line 1807, in do_either
body = control(env, start_response)
File “server.py”, line 1599, in control
return [dict_to_json(jsondict)]
File “C:\Python27\lib\json\__init__.py”, line 244, in dumps
return _default_encoder.encode(obj)
File “C:\Python27\lib\json\encoder.py”, line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File “C:\Python27\lib\json\encoder.py”, line 270, in iterencode
return _iterencode(o, 0)
UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0x89 in position 0: invalid start byteHas an
May 21, 2022 at 2:15 pm #8200JeremyKeymasterHi,
Do you still have any non-HTML, non-CSV file in chunk_includes with an extension that you didn’t list in an
endsWith
command as illustrated above (note that this is case-sensitive, so make sure all your extensions are lower case)? That would produce the error you reportJeremy
May 21, 2022 at 5:50 pm #8202suleymanyamanParticipantUpon some tinkering, I was able to start up my experiment. Actually, I have a PNG file (i.e. my institution’s logo) that is printed in a seperate HTML file that I use for consent form at the beginning. Both this image file and HTMLs are located in chunck_includes. This time, when I start the experiment on localhost, the logo is not shown as in the screenshot I provide here here. I checked the file server.py for this problem as you wrote above, but the png extension is already listed here as far as I can understand:
try: for fname in os.listdir(os.path.join(PWD, CFG['CHUNK_INCLUDES_DIR'])): if fname.endswith(".wav") or fname.endswith(".mp3") or fname.endswith("m4a") or fname.endswith(".ogg"): continue if fname.endswith(".png") or fname.endswith(".jpg") or fname.endswith(".bmp"): continue if fname.endswith(".mp4") or fname.endswith(".webm") or fname.endswith(".ogv"): continue f = None try: try:
Is there also potential solution for this?
Thank you!
May 23, 2022 at 4:23 pm #8204JeremyKeymasterHi,
How do you reference the image in the HTML file? It should look like
<img src="http://localhost:3000/server.py?resource=logo.png">
NB: I cannot see the screenshot at the ImgBB link from your message
Jeremy
November 26, 2023 at 12:09 pm #10953postylemParticipantI’m just starting to use PCIbex, but I have been having trouble with the farm (preview results or downloading results or files takes over 5 minutes to load). I’d really like to run a local version of it in order to test things without waiting. Is there any way of running it without needing to install **python 2**? I have an M1 mac, and I’ve had a lot of issues trying to install python 2 on it in the past.
January 19, 2024 at 8:12 am #10989JeremyKeymasterHello,
I have come up with two little python3 scripts to handle this, they can be found here:
*
static.py
takes a full experiment folder’s structure (ie. a folder with the chunk_includes, css_includes, data_includes, js_includes, other_includes, www subfolders) and outputs a standalone, static experiment in another folder. The resulting experiment can be run entirely locally in a web browser, without even needing a local server. That being said, because of the absence of a server, it won’t support automatic update of the counter or sending of the results: by default the counter will be set to a random value between 0 and 1000, or to the value passed to thewithsquare
parameter in the URL, and the browser will open a prompt to download the results as a file on the device. You can still run the output on a server: to obtain the exact same behavior, make sure to passstatic=1
as a parameter in the URL, or don’t pass it if you want to handle the counter and the results file on the server. Usage example:python3 static.py -i ./ibex_exp -o ~/static_exp
*
server.py
will run a very simple server that handles counter updates, saving results and serving files. Note that it was not designed to be used as a public web server, although it could technically be implemented as such — it works well as a local server though. It will run atlocalhost:3000
by default, but you can update the port by settingPORT
at the top of the script to a different value. Also make sure to editPRIVATE_DIRECTORY
andPUBLIC_DIRECTORY
to point to the directories you want to use on your machine:PRIVATE_DIRECTORY
is where you will have the counter and results file, and it should not be publicly exposed (although if you’re running a local server, it doesn’t matter much);PUBLIC_DIRECTORY
is the directory serving files, and it should be set to point to the output folder ofstatic.py
above (in this example,~/static_exp/
) this way it can serve multimedia files, for example. Finally note the lineresponse.headers["Access-Control-Allow-Origin"] = "*"
: this will accept incoming requests from any domain (includinglocalhost
, crucially) so make sure to edit it if you need to make things more secure. Usage example:python3 server.py
Jeremy
May 24, 2024 at 4:57 am #11026dodParticipantHi Jeremy,
I tried to use the static.py script to run a simple experiment completely locally. It works very well for what I need.
However, the results file doesn’t have the usual format and it’s not read by the read.pcibex function. I can see all the headers and all the logged info, but cannot get the delimiters/logic to convert it into a csv or even the normal file to pass in the read.pcibex.I’m attaching the result file (.bak) of a simple demographic questionnaire to give you an idea. If it matters, I’m on an M1 mac.
Is there any extra script I missed?
Thank you in advance!
[false,0,[Controller name,Item number,Element number,Type,Group,PennElementType,PennElementName,Parameter,Value,EventTime,Comments,nameID,email,agerange,gender,raised,edu,cur_edu,glasses,lenses,vision],[[[0,PennController],[1,0],[2,0],[3,welcomeGO],[4,NULL],[5,PennController],[6,0],[7,_Trial_],[8,Start],[9,1716472079297],[10,NULL]],[[0,PennController],[1,0],[2,0],[3,welcomeGO],[4,NULL],[5,PennController],[6,0],[7,_Trial_],[8,End],[9,1716472080903],[10,NULL]],[[0,PennController],[1,2],[2,0],[3,ethicswarning],[4,NULL],[5,PennController],[6,2],[7,_Trial_],[8,Start],[9,1716472080904],[10,NULL]],[[0,PennController],[1,2],[2,0],[3,ethicswarning],[4,NULL],[5,PennController],[6,2],[7,_Trial_],[8,End],[9,1716472082127],[10,NULL]],[[0,PennController],[1,3],[2,0],[3,demo1-Ls],[4,NULL],[5,PennController],[6,3],[7,_Trial_],[8,Start],[9,1716472082129],[10,NULL]],[[0,PennController],[1,3],[2,0],[3,demo1-Ls],[4,NULL],[5,PennController],[6,3],[7,_Trial_],[8,End],[9,1716472094899],[10,NULL]],[[0,PennController],[1,8],[2,0],[3,demo-vision],[4,NULL],[5,PennController],[6,8],[7,_Trial_],[8,Start],[9,1716472094900],[10,NULL]],[[0,PennController],[1,8],[2,0],[3,demo-vision],[4,NULL],[5,PennController],[6,8],[7,_Trial_],[8,End],[9,1716472103425],[10,NULL]],[[0,PennController],[1,4],[2,0],[3,demo2-agegender],[4,NULL],[5,PennController],[6,4],[7,_Trial_],[8,Start],[9,1716472103427],[10,NULL]],[[0,PennController],[1,4],[2,0],[3,demo2-agegender],[4,NULL],[5,PennController],[6,4],[7,_Trial_],[8,End],[9,1716472108196],[10,NULL]],[[0,PennController],[1,6],[2,0],[3,demo4-edu],[4,NULL],[5,PennController],[6,6],[7,_Trial_],[8,Start],[9,1716472108197],[10,NULL]],[[0,PennController],[1,6],[2,0],[3,demo4-edu],[4,NULL],[5,PennController],[6,6],[7,_Trial_],[8,End],[9,1716472122493],[10,NULL]],[[0,PennController],[1,7],[2,0],[3,demo5-health],[4,NULL],[5,PennController],[6,7],[7,_Trial_],[8,Start],[9,1716472122494],[10,NULL]],[[0,PennController],[1,7],[2,0],[3,demo5-health],[4,NULL],[5,PennController],[6,7],[7,_Trial_],[8,End],[9,1716472131490],[10,NULL]],[[0,PennController],[1,9],[2,0],[3,valid],[4,NULL],[5,PennController],[6,9],[7,_Trial_],[8,Start],[9,1716472131492],[11,test],[12,test],[13,23 - 26],[14,test],[15,test],[16,Licence],[17,test],[18,Non],[19,Oui],[20,Non],[10,NULL]],[[0,PennController],[1,9],[2,0],[3,valid],[4,NULL],[5,PennController],[6,9],[7,_Trial_],[8,End],[9,1716472169232],[11,test],[12,test],[13,23 - 26],[14,test],[15,test],[16,Licence],[17,test],[18,Non],[19,Oui],[20,Non],[10,NULL]]],ktwl0BZ/sa+NNlDBjNaNng,true]
- This reply was modified 4 months, 1 week ago by dod.
-
AuthorPosts
- You must be logged in to reply to this topic.