Hacking the Human Mind


“The intelligent want self-control, children want candy.”
– Rumi

Last week I gave a talk about the progress I’ve made on my meditation platform. In it, I went into a little more depth about the whys behind meditation, stressing how distracted we’ve become as a technological society, and how we’re going to need better tools to build and manage our focus as the world becomes more and more distracting.

The slides from the talk are above, and a link to the video is at the end of this post.

But I’ll also got into a little bit of an overview for those of you not willing to make the 20 minute video commitment.

The World Has Become Dangerously Distracting


* 12% of all boys between 3-17 years now diagnosed with ADHD
* 20% of smartphone users check phone every 10 minutes
* Multitasking has been shown to lower IQ by 10 points
* The average american teen now sends an average of 3,417 text messages per month.

In the past 40 years, we’ve gone from Pong to Battlefield 3. If you’re a 12 year old boy, you’ve now got to decide between homework and playing in live battlefield with up to 64 other players, using tanks and helicopters and sniper rifles and C4 and more. The rush and excitement of video games, versus the slow dull grind of homework.

Psychologists are now designing games for addictiveness. And they’re incorporating very powerful psychological tools to keep kids reeled in. From skinner boxes to variable ratio reinforcement to social pressure, kids are facing a very real and strong draw to the game realities over our shared physical realities.

It’s not the kid’s fault their heads are stuck in phones and games. They’ve both been designed to be incredibly addictive to our brains.

What’s the cost of this distractedness?

Willpower and Focus

Willpower has been shown to be a finite resource which is depleted by decision making.

Nearly every piece of our technological realities drains focus and willpower.

With the Loss of Willpower We’re Losing the Ability to Control and Direct Ourselves.

The Solution: Using Technology to Manage Our Minds More Effectively in the Face of New Threats

Brand New Research on Meditation

* Increases Attention Span
* Sharpens Focus
* Improves Memory
* Dulls the Perception of Pain
* Slows Age Related Thinning of the Prefrontal Cortex
* Helps Build Willpower

So why aren’t we all meditating?

Chicken or the Egg Problem: Don’t have enough willpower to start building our willpower.

If we were to make meditation seductive to our distracted minds, what would it look like?

Building the Platform to Measure Mediation

First prototype measured Galvanic Skin Response, Skin Temperature, and Heart Rate. Read physiology using off the shelf components, and an Arduino. Tracked all inputs using Clojure, and graphed all data using the incanter library.

It provided audio feedback (via Overtone) when a deeper meditative state was reached, and recorded all data so meditation could be tracked over time.


Initial Prototype Drawbacks:

* Must be attached to computer
* Wires get tangled
* Setting up computer is too distracting
* Not easy enough

Meditation on the iPhone

Using new Bluetooth LE heart rate monitors, we can now track heart rate with medical quality data. Combined with an app I’ve written using algorithms developed with the data from my first prototype, I now have a low-friction environment to measure meditation.

Unfortunately, Bluetooth LE is only supported by the iPhone 4S and 5, the New iPad, the iPad mini, and the new iPod Touch.

But we now have a portable psychology lab capable of providing audio and visual feedback to direct changes in our physiology caused by meditation.

Look for the meditation app in the App Store by the end of December

Fill out my online form.

An Iterative Approach to Building an API – Part 4: Fabric Scripts for Code Deployment

Over the past three days, we’ve stubbed an API in YAML on Tornado, then upgraded to an ElasticSearch backend, and finally, built and deployed a server to Amazon Web Services using Chef scripts.

Today, we’ll write scripts in Fabric to make deploying code changes to the production server simple.

An Introduction to the Fabfile

Writing Fabric scripts begins with a fabfile.py in our source code directory. Fabfiles are a very straightforward and easy way to run commands on a remote server programmatically.

Here’s an example of what a fabfile.py file would look like. Save this file in your elasticAPI directory:

from fabric.api import *                                                                                                                                                                                    
from fabric.contrib import files                                                                                                                                                                            
 
# For virtualenv and Fabric                                                                                                                                                                                 
env.hosts = ['ec2-XX-XX-XX-XX.compute-1.amazonaws.com'] # Replace with your server name
env.user = 'ubuntu'  
 
def ls():
    run('ls -al')

Now we can install Fabric and then run the Fabfile to make sure we can connect to the remote server:

$ pip install Fabric
$ fab ls
[ec2-XX-XX-XXX-XXX.compute-1.amazonaws.com] Executing task 'ls'
[ec2-XX-XX-XXX-XXX.compute-1.amazonaws.com] run: ls -al

We’ve successfully confirmed that we can connect to, and run remote commands on the server. Now, let’s stub out the pieces necessary for building and deploying code remotely.

Preparing Code for Deployment

Each time we decide to deploy code to our server, we first need to commit it and save the changes. This is straightforward enough, thanks to the local() function provided by Fabric:

from fabric.api import *                                                                                                                                                                                    
from fabric.contrib import files                                                                                                                                                                            
 
# For virtualenv and Fabric                                                                                                                                                                                 
env.hosts = ['ec2-XX-XX-XX-XX.compute-1.amazonaws.com'] # Replace with your server name
env.user = 'ubuntu'  
 
def test():
    local("nosetests")
 
def commit():
    local("pip freeze > requirements.txt")
    local("git add -p && git commit")
 
def push():
    local("git push")
 
def prepare_deploy():
    test()
    commit()
    push()

Now, if our code has a remote repository, our nosetests will be run and then pushed to the repository. In my case, I used Github as my remote directory.

Adding the Code to Run the Server Deployment

We’re getting close now. We can pull our remote code from our server, and then stop and restart the server if necessary:

from __future__ import with_statement                                                                                                                                                                       
from fabric.api import *                                                                                                                                                                                    
from fabric.contrib import files                                                                                                                                                                            
 
from contextlib import contextmanager as _contextmanager                                                                                                                                                    
 
# For virtualenv and Fabric                                                                                                                                                                                 
env.hosts = ['ec2-XX-XX-XXX-XXX.compute-1.amazonaws.com']                                                                                                                                                   
env.user = 'ubuntu'                                                                                                                                                                                         
env.directory = '/home/ubuntu/elasticEnv'                                                                                                                                                                   
env.activate = 'source /home/ubuntu/elasticEnv/bin/activate'                                                                                                                                                
 
# For gunicorn process                                                                                                                                                                                      
env.remote_workdir = '/home/ubuntu/elasticAPI'                                                                                                                                                              
env.gunicorn_wsgi_app = 'webapp:app'                                                                                                                                                                        
 
@_contextmanager
def virtualenv():
    with cd(env.directory):
        with prefix(env.activate):
            yield
ef test():
    local("nosetests")
 
def commit():
    local("pip freeze > requirements.txt")
    local("git add -p && git commit")
 
def push():
    local("git push")
 
def prepare_deploy():
    test()
    commit()
    push()
 
def stop_gunicorn():
    with settings(warn_only=True):
        if files.exists("%s/gunicorn.pid" % env.remote_workdir):
            run("kill -9 `cat %s/gunicorn.pid`" % env.remote_workdir)
 
def restart_gunicorn():
    stop_gunicorn()
 
    with virtualenv():
        run("cd %s && gunicorn -k egg:gunicorn#tornado webapp:app --pid=%s/gunicorn.pid" % (env.remote_workdir, env.remote_workdir))
 
def deploy_server():
    with settings(warn_only=True):
       if run("nosetests %s" % env.remote_workdir).failed:
            run("git clone git://github.com/burningion/elasticAPI.git %s" % env.remote_workdir)
    with cd(env.remote_workdir):
        run("git pull")
    with virtualenv():
        run("pip install -U -r %s/requirements.txt" % env.remote_workdir)
    restart_gunicorn()

That’s it! Now we can do a fab deploy_server and see our server run on gunicorn!

$ fab deploy_server

You might get stuck at the end, because we’re just running gunicorn from the command line. It is safe to CTRL-C out of the Fabric process.

You can then ssh to the remote Amazon server and test that things are working:

$ ssh ubuntu@ec2-XX-XX-XXX-XXX.compute-1.amazonaws.com
$ curl http://localhost:8000/

But we’re still not accessible from port 80 remotely. Let’s fix that now, by adjusting our nginx settings.

Adding an Nginx Proxy to Gunicorn

Now we’ll open up the default nginx web server configuration file, and add forwarding to our gunicorn process running on port 8000.

Open up /etc/nginx/sites-available/default with sudo. (Ex: sudo emacs /etc/nginx/sites-available/default)

upstream app_server {
         server 127.0.0.1:8000 fail_timeout=0;
}

server {
        #listen   80; ## listen for ipv4; this line is default and implied
        #listen   [::]:80 default ipv6only=on; ## listen for ipv6

        root /usr/share/nginx/www;
        index index.html index.htm;

        # Make site accessible from http://localhost/
        server_name localhost;

        location / {
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;

             proxy_pass   http://app_server;
        }
}

Now we can restart our nginx server, and hopefully see our API server from the outside world. On the remote Amazon server:

$ sudo /etc/init.d/nginx restart

Verify the API Works

We can now verify the API works by running curl from our local computer.

$ curl http://c2-XX-XX-XXX-XXX.compute-1.amazonaws.com
Hello, world

Success! We now have a live base API we can iterate from. We add code, commit it, and then deploy it using our fabfile.

If you’ve got any questions, or got stuck anywhere, please let me know!

Part One – Building the API skeleton with YAML
Part Two – From YAML to ElasticSearch
Part Three – Writing Chef Scripts for Amazon Deployment
Part Four – Writing Fabric Scripts for Code Deployment

As before, the code for everything is already finished and available at github, and so are the Chef scripts.