Last active
December 12, 2015 00:49
-
-
Save JogoShugh/4686674 to your computer and use it in GitHub Desktop.
OpenEpi Module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define ['../modules/outputBuilder'], (outputBuilder) -> | |
name:'ConfidenceInterval', | |
group:'Continuous Variables', | |
title: 'Confidence Interval', | |
titleShort: 'Median / %ile CI', | |
summary: 'Confidence Interval of median or other percentile for a sample size', | |
description: "This module calculates confidence interval around a selected percentile for | |
a sample size given. Entering sample size and desired percentile will calculate | |
95% confidence interval as a default confidence limit. The user can change the | |
confidence interval by typing in new value. Please note that the selected percentile | |
should be within 1-100%", | |
authors: | |
Statistics: 'Minn M. Soe and Kevin M. Sullivan (Emory University)' | |
Interface: "Andrew G. Dean (<a href='http://www.EpiInformatics.com' target='_blank'>EpiInformatics.com</a>), Roger A. Mir, and Joshua Gough (<a href='http://www.agilefromthegroundup.com/site/Home.aspx' target='_blank'>AgileFromTheGroundUp.com</a>)" | |
inputFields: | |
sampleSize: | |
label: 'Sample Size' | |
labelSm: 's' | |
jqmType: 'textinput' | |
dataType: 'number' | |
editorAttrs: | |
value: '100' | |
median: | |
label: 'Desired Percentile' | |
labelSm: 'm' | |
jqmType: 'textinput' | |
dataType: 'number' | |
editorAttrs: | |
value: '50' | |
confidenceLevel: | |
label: 'Confidence Level (%)' | |
labelSm: 'cl' | |
jqmType: 'textinput' | |
dataType: 'number' | |
editorAttrs: | |
value: '95' | |
calculate: (model, callback, error) -> | |
n = parseFloat model.sampleSize | |
if n <= 0 | |
error "Sample size must be > 0" | |
return | |
median = parseFloat model.median | |
if median <= 0 or median > 100 | |
error "Percentile value must be within the limits of 1-100%" | |
return | |
cscrit = 0 | |
pt = 0 | |
z = 0 | |
pt = parseFloat model.confidenceLevel | |
cscrit = 15.137 if pt is 99.99 | |
cscrit = 13.831 if pt is 99.98 | |
cscrit = 12.116 if pt is 99.95 | |
cscrit = 10.828 if pt is 99.9 | |
cscrit = 9.550 if pt is 99.8 | |
cscrit = 7.879 if pt is 99.5 | |
cscrit = 6.635 if pt is 99 | |
cscrit = 5.412 if pt is 98 | |
cscrit = 3.841 if pt is 95 | |
cscrit = 2.706 if pt is 90 | |
cscrit = 2.072 if pt is 85 | |
cscrit = 1.642 if pt is 80 | |
cscrit = 1.323 if pt is 75 | |
cscrit = 1.074 if pt is 70 | |
cscrit = 0.873 if pt is 65 | |
cscrit = 0.708 if pt is 60 | |
cscrit = 0.571 if pt is 55 | |
cscrit = 0.455 if pt is 50 | |
cscrit = 0.357 if pt is 45 | |
cscrit = 0.275 if pt is 40 | |
cscrit = 0.206 if pt is 35 | |
cscrit = 0.148 if pt is 30 | |
cscrit = 0.102 if pt is 25 | |
cscrit = 0.064 if pt is 20 | |
if cscrit is 0 | |
error "The selected confidence interval is not available, choose other ranges" | |
return false | |
z = Math.sqrt cscrit | |
#rank calculation: | |
np = 0 | |
p = 0 | |
p = median / 100 | |
if p is 0.5 | |
np = (n + 1) / 2 | |
else | |
np = Math.round(n * p) | |
#confidence limits and checking errors; | |
ll = Math.round(n * p - z * (Math.sqrt(n * p * (1 - p)))) | |
ll = 0 if ll <= 0 | |
ul = Math.round(1 + n * p + z * (Math.sqrt(n * p * (1 - p)))) | |
ul = 0 if ul <= 0 | |
ul = n if ul >= n | |
resultModel = | |
model: model | |
fields: @.inputFields | |
n: n | |
median: median | |
pt: pt | |
confidenceIntervalCategory: pt | |
sampleSize: n | |
output: | |
lowerLimit: ll | |
rank: np | |
upperLimit: ul | |
callback resultModel | |
render: (result, callback, error) -> | |
builder = outputBuilder.create() | |
builder | |
.heading("Confidence Interval for #{result.model.median}th percentile of sample size #{result.model.sampleSize}") | |
.columns(['Method', 'Lower Limit', 'Rank', 'Uppert Limit']) | |
.row(['Normal Approximation', result.output.lowerLimit, result.output.rank, result.output.upperLimit]) | |
.render(result) | |
callback(builder.el) | |
renderHistoryLabel: (result, callback, error) -> | |
sampleSize = @.inputFields.sampleSize.labelSm | |
median = @.inputFields.median.labelSm | |
conf = @.inputFields.confidenceLevel.labelSm | |
label = "#{sampleSize}:#{result.model.sampleSize} #{median}:#{result.model.median} #{conf}:#{result.model.confidenceLevel}" | |
callback label | |
renderHistoryResult: (result, callback, error) -> | |
ll = result.output.lowerLimit | |
np = result.output.rank | |
ul = result.output.upperLimit | |
label = "ll:#{ll} np:#{np} ul:#{ul}" | |
callback label |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define [ | |
'modules', | |
'templates', | |
'backbone', | |
'backbone-forms', | |
'underscore', | |
'toastr', | |
'jquery', | |
'jquery.mobile', | |
'jquery.jade', | |
'dateFormat' | |
], | |
( | |
modules, | |
templates, | |
Backbone, | |
bbforms, | |
_, | |
toastr, | |
$, | |
jqm, | |
jade, | |
dateFormat | |
) -> | |
log = (message) -> | |
console.log message | |
info = (message, options) -> | |
toastr.info message, options | |
success = (message, options) -> | |
toastr.success message, options | |
error = (message) -> | |
toastr.error message | |
console.log 'OpenEpi Error:' + message | |
class OpenEpiShell | |
constructor: -> | |
@moduleModels = {} | |
@templateModules = @getTemplatesModules() | |
@templatesListRendered = false | |
@historyList = @getHistoryList() | |
@historyListRendered = false | |
toastr.options = positionClass : 'toast-bottom-right' | |
$ => | |
h = $(window).height() | |
$("#splash").css("height", h) | |
$.mobile.loading('show') | |
$('#bodyDiv').css('visibility','visible').hide().fadeIn('slow'); | |
$.mobile.loading('hide') | |
$("#more").on | |
popupbeforeposition: -> | |
h = $(window).height() | |
$("#more").css("height", h) | |
$("#moreModule").on | |
popupbeforeposition: -> | |
h = $(window).height() | |
$("#moreModule").css("height", h) | |
@renderModuleLinks() | |
window.setTimeout -> | |
$.mobile.changePage "#home" | |
, 1750 | |
renderModuleLinks: -> | |
info "Loaded all modules successfully..." | |
moduleSelector = $("#moduleSelector") | |
tmpl = templates['display-moduleList'] | |
mods = modules : modules | |
html = $.jade(tmpl, mods) | |
moduleSelector.append(html) | |
that = @ | |
$('.moduleItem a').each -> | |
item = $(@) | |
moduleName = item.attr('data-moduleName') | |
item.bind 'click', => | |
that.moduleLoad moduleName | |
@templateModulesListRender() | |
@historyListRender() | |
exec: (moduleName, args, addToHistory) -> | |
module = @getModule moduleName | |
callback = (result) => | |
console.log result | |
if addToHistory | |
@historyAdd module, result.model, result | |
error = (err) -> | |
console.log 'Error:' | |
console.log err | |
if not module? | |
error "Could not find module named: #{moduleName}" | |
return | |
module.calculate args, callback, error | |
moduleLoad: (moduleName, formValue) -> | |
modulePage = $("#module") | |
module = @getModule moduleName | |
if not module? | |
return | |
moduleModel = @getModuleModel module | |
if not moduleModel? | |
return | |
$("#resultsMissing").show() | |
$("#resultsPane").hide() | |
modulePage.find('.fields').each (i, el) => | |
fieldContainer = $(el) | |
fieldContainer.empty() | |
$("#moduleTitle").text(module.title) | |
model = new moduleModel | |
args = model: model | |
formModel = new Backbone.Form(args) | |
if formValue? | |
formModel.model.attributes = formValue | |
form = formModel.render() | |
fieldContainer.html(form.el) | |
# Finallly, rebind the click handler for the "Calculate" button and | |
# attach it to the calculate method of the current module | |
modulePage.find('.calculate').each (i, el) => | |
command = $(el) | |
command.unbind('click').bind 'click', => | |
formValue = form.getValue() | |
$.mobile.loading('show') | |
module.calculate formValue, (result) => | |
@showResult result, module.render | |
@historyAdd module, formValue, result | |
$.mobile.loading('hide') | |
, @error | |
modulePage.find('.templateSave').each (i, el) => | |
command = $(el) | |
command.unbind('click').bind 'click', => | |
formValue = form.getValue() | |
@templatesAdd module, formValue | |
stp = $('#saveTemplatePopup') | |
stp.popup 'close' | |
$("#moduleSummary").html(module.summary) | |
$("#moduleDescription").html(module.description) | |
authors = $("<div style='padding-left:5px'></div>") | |
for authorType, authorCredit of module.authors | |
authors.append("<div style='color:#333333'><b style='color:#555555'>#{authorType}:</b> #{authorCredit}</div>") | |
$("#moduleAuthors").append(authors) | |
$("#moduleInfo").collapsible() | |
$.mobile.changePage("#module") | |
modulePage.trigger('create') # enhance the controls, JQM style | |
$('#history').trigger('create') | |
getModule: (moduleName) -> | |
module = modules[moduleName] | |
if not module? | |
error "Could not find module #{moduleName}" | |
return null | |
return module | |
getModuleModel: (module) -> | |
moduleModel = @moduleModels[module.name] | |
if not moduleModel? | |
moduleModel = Backbone.Model.extend(schema: module.inputFields) | |
@moduleModels[module.name] = moduleModel | |
return moduleModel | |
showResult: (result, renderFn) -> | |
resultPage = $('#results') | |
resultData = $('#resultData') | |
processing = $('#processing') | |
resultData.hide() | |
processing.show() | |
$("#resultsMissing").hide() | |
$("#resultsPane").show() | |
$.mobile.changePage('#results') | |
window.setTimeout -> | |
processing.fadeOut().promise().done -> | |
completeRender = (html) -> | |
resultData.empty() | |
resultData.append(html) | |
resultData.fadeIn(200) | |
renderFn(result, completeRender, error) | |
, 200 | |
getTemplatesModules: () -> | |
if window.localStorage.getItem('templateModules') == null | |
window.localStorage.setItem('templateModules', JSON.stringify []) | |
templateModules = JSON.parse window.localStorage.getItem('templateModules') | |
return templateModules | |
templatesAdd: (module, formValue) -> | |
templateName = $('#templateName').val() | |
templateModule = {templateName: templateName, moduleName: module.name, formValue: formValue, dateTime: new Date().format()} | |
@templateModules.unshift templateModule | |
window.localStorage.setItem('templateModules', JSON.stringify @templateModules) | |
success "Template #{templateName} added" | |
@templateModulesListRender() | |
templateModulesListRender: -> | |
templateModuleSelector = $("#templateModules") | |
if (@templatesListRendered == false) | |
tmpl = templates['display-templatesList'] | |
html = $.jade(tmpl, {}) | |
templateModuleSelector.append(html) | |
$('#templateModulesList').empty() | |
modObjs = {} | |
$.extend true, modObjs, @templateModules | |
mods = templateModules : modObjs | |
log mods | |
_.each mods.templateModules, (item) => | |
item.module = @getModule item.moduleName | |
tmplItems = templates['display-templatesListItem'] | |
items = $.jade(tmplItems, mods) | |
$('#templateModulesList').append(items) | |
$('.templateModule').children('a').each (i, el) => | |
item = $(el) | |
index = Number(item.attr('data-index')) | |
templateModule = @templateModules[index] | |
moduleName = templateModule.moduleName | |
formValue = templateModule.formValue | |
item.bind 'click', => | |
@moduleLoad moduleName, formValue | |
if @templatesListRendered | |
try | |
$('#templateModulesList').listview('refresh') | |
catch ex | |
console.log "Error:" | |
console.log ex | |
else | |
@templatesListRendered = true | |
return | |
getHistoryList: -> | |
if window.localStorage.getItem('historyList') == null | |
window.localStorage.setItem('historyList', JSON.stringify []) | |
histList = JSON.parse window.localStorage.getItem('historyList') | |
return histList | |
historyAdd: (module, formValue, result) -> | |
historyItem = | |
moduleName: module.name | |
result: | |
model: formValue # TODO TEMP HACK | |
output: result.output | |
dateTime: new Date().format() | |
@historyList.unshift historyItem | |
window.localStorage.setItem('historyList', JSON.stringify @historyList) | |
@historyListRender() | |
historyListRender: -> | |
historyItemsSelector = $("#historyListContainer") | |
if @historyListRendered == false | |
tmpl = templates['display-historyList'] | |
html = $.jade(tmpl, {}) | |
historyItemsSelector.append(html) | |
$('#historyList').empty() | |
modObjs = {} | |
$.extend true, modObjs, @historyList | |
mods = historyList : modObjs | |
log mods | |
_.each mods.historyList, (item) => | |
module = @getModule item.moduleName | |
item.module = module | |
module.renderHistoryLabel item.result, (result) -> | |
item.label = result | |
module.renderHistoryResult item.result, (result) -> | |
item.result = result | |
tmplItems = templates['display-historyListItem'] | |
items = $.jade(tmplItems, mods) | |
$('#historyList').append(items) | |
$('.historyItem').children('a').each (i, el) => | |
item = $(el) | |
index = Number(item.attr('data-index')) | |
historyItem = @historyList[index] | |
moduleName = historyItem.moduleName | |
formValue = historyItem.result.model | |
item.bind 'click', => | |
@moduleLoad moduleName, formValue | |
try | |
if @historyListRendered == true | |
$('#historyList').listview('refresh') | |
else | |
#$('#historyList').listview() | |
$('#historyList').listview('refresh') | |
catch ex | |
console.log "Error listviewifying the list:" | |
console.log ex | |
@historyListRendered = true | |
return OpenEpiShell |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment