running penncontroller locally

PennController for IBEX Forums Support running penncontroller locally

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #2969
    camilo
    Guest

    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 🙂 )

    #2976
    Jeremy
    Keymaster

    Hi 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’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)])
    with

    if 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()
    )
    #2983
    camilo
    Guest

    Hi 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!

    #2984
    Jeremy
    Keymaster

    Hi 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

    #2985
    Thao Tran
    Guest

    Basically 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.

    #5877
    mat646
    Participant

    Thank 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)])
    with

    if 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.html

    Your experiment should run.

    #6430
    mat646
    Participant

    Correction, 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)

    #8199
    suleymanyaman
    Participant

    Hello,

    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 byte

    Has an

    #8200
    Jeremy
    Keymaster

    Hi,

    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 report

    Jeremy

    #8202
    suleymanyaman
    Participant

    Upon 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!

    #8204
    Jeremy
    Keymaster

    Hi,

    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

    #10953
    postylem
    Participant

    I’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.

    #10989
    Jeremy
    Keymaster

    Hello,

    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 the withsquare 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 pass static=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 at localhost:3000 by default, but you can update the port by setting PORT at the top of the script to a different value. Also make sure to edit PRIVATE_DIRECTORY and PUBLIC_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 of static.py above (in this example, ~/static_exp/) this way it can serve multimedia files, for example. Finally note the line response.headers["Access-Control-Allow-Origin"] = "*": this will accept incoming requests from any domain (including localhost, crucially) so make sure to edit it if you need to make things more secure. Usage example: python3 server.py

    Jeremy

    #11026
    dod
    Participant

    Hi 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.
Viewing 14 posts - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.