Skip to content

Commit

Permalink
Frist pass at sizing help.
Browse files Browse the repository at this point in the history
refs #66
  • Loading branch information
davidmiller committed Jun 6, 2013
1 parent 76512c0 commit 723ac30
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 14 deletions.
5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Cython==0.19.1
Django==1.5.1
Jinja2==2.7
MarkupSafe==0.18
Expand Down Expand Up @@ -38,8 +39,10 @@ lxml==3.1.1
mailtools==2.1
meld3==0.6.10
mock==1.0.1
numpy==1.7.1
oauth2==1.5.211
oauthlib==0.4.0
pandas==0.11.0
psutil==0.7.0
psycopg2==2.4.6
py==1.4.13
Expand All @@ -51,6 +54,8 @@ pyzmq==13.0.2
regex==2013-03-11
requests==1.2.0
requests-oauthlib==0.3.0
scipy==0.12.0
six==1.3.0
supervisor==3.0b1
wsgiref==0.1.2
patsy
4 changes: 4 additions & 0 deletions rm/static/css/rm.css
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ ul.parsley-error-list {
color: #e54f25;
}

ul.parsley-error-list li {
list-style-type: none;
}

.controls ul li {
list-style-type: none;
}
Expand Down
12 changes: 7 additions & 5 deletions rm/static/js/rm.carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@
return this.$items.index(this.$active)
}

, to: function (pos) {
, to: function (pos, force) {

if(!this.validp()){
return this.pause().cycle()
if(!force){
if(!this.validp()){
return this.pause().cycle()
}
}
var activeIndex = this.getActiveIndex()
, that = this
Expand Down Expand Up @@ -221,14 +223,14 @@

var old = $.fn.carousel

$.fn.carousel = function (option) {
$.fn.carousel = function (option, force) {
return this.each(function () {
var $this = $(this)
, data = $this.data('carousel')
, options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
, action = typeof option == 'string' ? option : options.slide
if (!data) $this.data('carousel', (data = new Carousel(this, options)))
if (typeof option == 'number') data.to(option)
if (typeof option == 'number') data.to(option, force)
else if (action) data[action]()
else if (options.interval) data.pause().cycle()
})
Expand Down
35 changes: 35 additions & 0 deletions rm/static/js/rm.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,41 @@ var RM = {
})
},

// Bind the power calculation form to an ajax call
init_power: function(){

$('form#power-form').ajaxForm({

beforeSubmit: function(){
if(!$('form#power-form').parsley().validate()){
return false
}
$('#power-btn').attr('disabled', true).text(
'calculating required participants...')
},

success: function(data){
var msg = 'You need ' + data + ' participant';
if(parseInt(data) > 1){
msg += 's'
}
$('#power-btn').attr('disabled', false).text(
'run the numbers');
$('#power-answer').text(msg);
$('#id_min_participants').attr('value', data);
$('#power-done').text('done')
},

error: function(data){
console.log(data);
console.log('Power calculation - something went wrong :()')
$('#power-btn').attr('disabled', false).text(
'run the numbers');
},

})
},

},

graphs: {
Expand Down
Empty file added rm/stats/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions rm/stats/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
16 changes: 16 additions & 0 deletions rm/stats/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""

from django.test import TestCase


class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)
8 changes: 8 additions & 0 deletions rm/stats/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.conf.urls import patterns, include, url

from rm.stats.views import PowerCalcView

urlpatterns = patterns(
'',
url(r'power-calc$', PowerCalcView.as_view(), name='power-calc'),
)
25 changes: 25 additions & 0 deletions rm/stats/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Utility functions for statistical calculations on Randomise Me
"""
from statsmodels.stats.power import tt_ind_solve_power

def nobs(estimated=None, impressive=None):
"""
Given the estimated and impressive figures,
conduct a power calculation and return the
number of required observations.
Arguments:
- `estimated`: int
- `impressive`: int
Return: int
Exceptions: None
"""
estimated, impressive = float(estimated), float(impressive)
if abs(estimated/impressive) > 1:
effect_size = abs(estimated/impressive)
else:
effect_size = abs(impressive/estimated)
num = tt_ind_solve_power(effect_size=effect_size, alpha=0.05, power=0.8, nobs1=None)
return int(num) * 2
24 changes: 24 additions & 0 deletions rm/stats/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Views to do server-side stats help
"""
from django.http import HttpResponse
from django.views.generic import View

from rm.stats.utils import nobs

class PowerCalcView(View):
"""
Run a power calculation
"""
def post(self, *args, **kwargs):
"""
Calculate the required number of participants
for the variables given
Return: str(int)
Exceptions: None
"""
estimated, impressive = [int(self.request.POST.get(k))
for k in ['impressive', 'estimated']]
num = nobs(estimated=estimated, impressive=impressive)
return HttpResponse(str(num))
48 changes: 48 additions & 0 deletions rm/templates/trials/_trial_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,60 @@ <h2>

</form>

<!-- Modal power -->
<div id="power" class="modal hide fade" tabindex="-1"
role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<h3 id="myModalLabel">How many people do you need?</h3>
</div>
<div class="modal-body">
<form method="POST" action="{% url 'power-calc' %}"
id="power-form"
data-validate="parsley">
{% csrf_token %}
<p class="muted">
Roughly what score/proportion/count do you expect in group A?
</p>
<input type="text" name="estimated" value=""
placeholder="estimated number"
data-required="true" data-type="digits"
/>
<p class="muted">
What score in treatment group B would be meaningfully different enough
for you to be impressed?
</p>
<input type="text" name="impressive" value=""
placeholder="impressive number"
data-required="true" data-type="digits"
/>
<p>
<button class="btn btn-danger" type="submit" id="power-btn">
run the numbers
</button>
</p>
<h3 id="power-answer">How many participants do you need?</h3>
</form>

</div>
<div class="modal-footer">
<button id="power-done" class="btn" data-dismiss="modal" aria-hidden="true">
cancel
</button>
</div>
</div>


<script type="text/javascript">

$(document).ready( function(){
RM.forms.init_instruction_toggles();
RM.forms.init_enter_sliding();
RM.forms.init_focus();
RM.forms.init_power();
if(window.location.search.search(/step=(\d+)/) != -1){
var step = (parseInt(window.location.search.match(/step=(\d+)/)[1]) -1);
$('.carousel').carousel(step, true).carousel('pause');
}
});

</script>
28 changes: 19 additions & 9 deletions rm/templates/trials/steps/step_sizing.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<div class="item">
<h2>3. <span class="red bold">SIZE</span> <span class="light">OF YOUR TRIAL</span></h2>
{% if n1trial %}

<h3>Would you like help to decide how many observations you'll need?</h3>
<p class="muted">
IMPLEMENT THIS PLEASE.
Expand All @@ -11,15 +12,24 @@ <h3>No, you think you've got it?</h3>
{{ form.ending_reports|bootstrap }}

{% else %}

<h3>Minimum number of participants</h3>
{{ form.min_participants|bootstrap }}
<p class="muted">
This is the minimum number of people you need in your trial
in order to obtain statistically significant results
</p>


<h3>Would you like help to decide how many people you will need in your trial? </h3>
<p class="muted">
Roughly what score/proportion/count do you expect in group A?
What score in treatment group B would be meaningfully different enough
for you to be impressed? <br>
> simple power calculation
</p>
<p>IMPLEMENT THIS</p>
<h3>No, you think you've got it?</h3>
{{ form.min_participants|bootstrap }}

<a href="#power" class="btn btn-warning" data-toggle="modal" role="button">
help me decide
</a>


{% endif %}



</div>
1 change: 1 addition & 0 deletions rm/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
url(r'^trials/', include('rm.trials.urls')),
url(r'search$', TrialSearchView.as_view(), name='search'),

url(r'^stats/', include('rm.stats.urls')),
)

urlpatterns += staticfiles_urlpatterns()

0 comments on commit 723ac30

Please sign in to comment.