clinical 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ tmp
7
+ features_rcov
8
+ coverage.data
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Dan Pickett
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = clinical
2
+
3
+ Description goes here.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Dan Pickett. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,87 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin require "metric_fu" rescue LoadError; end
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "clinical"
10
+ gem.summary = %Q{a library for accessing data from ClinicalTrials.gov}
11
+ gem.email = "dpickett@enlightsolutions.com"
12
+ gem.homepage = "http://github.com/dpickett/clinical"
13
+ gem.authors = ["Dan Pickett"]
14
+ gem.add_dependency("jnunemaker-httparty", ">= 0.4.3")
15
+ gem.add_dependency("jnunemaker-happymapper", ">= 0.2.5")
16
+ gem.add_dependency("mislav-will_paginate", ">= 2.3.11")
17
+ gem.add_dependency("nokogiri", ">= 1.3.3")
18
+
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
24
+ end
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/*_test.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ namespace :rcov do
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new(:tests) do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/*_test.rb'
38
+ test.rcov_opts = %w{--aggregate coverage.data --exclude osx\/objc,gems\/,spec\/}
39
+ test.verbose = true
40
+ end
41
+
42
+ require 'cucumber/rake/task'
43
+ Cucumber::Rake::Task.new(:cucumber) do |t|
44
+ t.rcov = true
45
+ t.rcov_opts = %w{--aggregate coverage.data --exclude osx\/objc,gems\/,features\/,spec\/ -o "features_rcov"}
46
+ end
47
+ end
48
+ begin
49
+ desc "Run both specs and features to generate aggregated coverage"
50
+ task :rcov do |t|
51
+ rm "coverage.data" if File.exist?("coverage.data")
52
+ Rake::Task["rcov:cucumber"].invoke
53
+ Rake::Task["rcov:tests"].invoke
54
+ end
55
+ rescue LoadError
56
+ task :rcov do
57
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
58
+ end
59
+ end
60
+
61
+ begin
62
+ require 'cucumber/rake/task'
63
+ Cucumber::Rake::Task.new(:features)
64
+
65
+ rescue LoadError
66
+ task :features do
67
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
68
+ end
69
+ end
70
+
71
+ task :default => :test
72
+
73
+ require 'rake/rdoctask'
74
+ Rake::RDocTask.new do |rdoc|
75
+ if File.exist?('VERSION.yml')
76
+ config = YAML.load(File.read('VERSION.yml'))
77
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
78
+ else
79
+ version = ""
80
+ end
81
+
82
+ rdoc.rdoc_dir = 'rdoc'
83
+ rdoc.title = "clinical #{version}"
84
+ rdoc.rdoc_files.include('README*')
85
+ rdoc.rdoc_files.include('lib/**/*.rb')
86
+ end
87
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.2
data/clinical.gemspec ADDED
@@ -0,0 +1,81 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{clinical}
5
+ s.version = "0.2.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Dan Pickett"]
9
+ s.date = %q{2009-07-28}
10
+ s.email = %q{dpickett@enlightsolutions.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "clinical.gemspec",
23
+ "features/finding_clinical_trials.feature",
24
+ "features/getting_keywords_and_categories.feature",
25
+ "features/step_definitions/clinical_steps.rb",
26
+ "features/support/env.rb",
27
+ "lib/clinical.rb",
28
+ "lib/clinical/address.rb",
29
+ "lib/clinical/agency.rb",
30
+ "lib/clinical/collaborator.rb",
31
+ "lib/clinical/collection.rb",
32
+ "lib/clinical/condition.rb",
33
+ "lib/clinical/contact.rb",
34
+ "lib/clinical/extensions.rb",
35
+ "lib/clinical/intervention.rb",
36
+ "lib/clinical/lead_sponsor.rb",
37
+ "lib/clinical/location.rb",
38
+ "lib/clinical/outcome.rb",
39
+ "lib/clinical/primary_outcome.rb",
40
+ "lib/clinical/secondary_outcome.rb",
41
+ "lib/clinical/sponsor.rb",
42
+ "lib/clinical/status.rb",
43
+ "lib/clinical/trial.rb",
44
+ "test/clinical/trial_test.rb",
45
+ "test/fixtures/lupus_single.xml",
46
+ "test/fixtures/open_set.xml",
47
+ "test/test_helper.rb"
48
+ ]
49
+ s.has_rdoc = true
50
+ s.homepage = %q{http://github.com/dpickett/clinical}
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = %q{1.3.2}
54
+ s.summary = %q{a library for accessing data from ClinicalTrials.gov}
55
+ s.test_files = [
56
+ "test/clinical/trial_test.rb",
57
+ "test/test_helper.rb"
58
+ ]
59
+
60
+ if s.respond_to? :specification_version then
61
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
65
+ s.add_runtime_dependency(%q<jnunemaker-httparty>, [">= 0.4.3"])
66
+ s.add_runtime_dependency(%q<jnunemaker-happymapper>, [">= 0.2.5"])
67
+ s.add_runtime_dependency(%q<mislav-will_paginate>, [">= 2.3.11"])
68
+ s.add_runtime_dependency(%q<nokogiri>, [">= 1.3.3"])
69
+ else
70
+ s.add_dependency(%q<jnunemaker-httparty>, [">= 0.4.3"])
71
+ s.add_dependency(%q<jnunemaker-happymapper>, [">= 0.2.5"])
72
+ s.add_dependency(%q<mislav-will_paginate>, [">= 2.3.11"])
73
+ s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
74
+ end
75
+ else
76
+ s.add_dependency(%q<jnunemaker-httparty>, [">= 0.4.3"])
77
+ s.add_dependency(%q<jnunemaker-happymapper>, [">= 0.2.5"])
78
+ s.add_dependency(%q<mislav-will_paginate>, [">= 2.3.11"])
79
+ s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
80
+ end
81
+ end
@@ -0,0 +1,52 @@
1
+ Feature: As a potential participant for a clinical study
2
+ I want to search for clinical trials
3
+ So that I can find out more information about them
4
+
5
+ Scenario: Find open studies
6
+ Given I am searching for trials where "recruiting" is "true"
7
+ When I perform the search
8
+ Then I should get trials that are "open"
9
+
10
+ Scenario: Find closed studies
11
+ Given I am searching for trials where "recruiting" is "false"
12
+ When I perform the search
13
+ Then I should get trials that are not "open"
14
+
15
+ Scenario: Find a specific condition
16
+ Given I am searching for trials where "condition" is "hemophelia"
17
+ When I perform the extended search
18
+ Then I should get trials where the "conditions" contains "hemophelia"
19
+
20
+ Scenario: Find a specific intervention
21
+ Given I am searching for trials where "intervention" is "drug"
22
+ When I perform the extended search
23
+ Then I should get trials where the "interventions" contains "drug"
24
+
25
+ Scenario: Find a specific outcome
26
+ Given I am searching for trials where "outcome" is "toxic"
27
+ When I perform the extended search
28
+ Then I should get trials where the "outcomes" contains "toxic"
29
+
30
+ Scenario: Find a specific sponsor
31
+ Given I am searching for trials where "sponsor" is "Eli Lilly"
32
+ When I perform the extended search
33
+ Then I should get trials where the "sponsors" contains "Eli Lilly"
34
+
35
+ Scenario: Find a specific trial
36
+ When I attempt to retrieve trial "NCT00001372"
37
+ Then I should get a trial
38
+ And the trial should have an "id" of "NCT00001372"
39
+
40
+ Scenario: Find a specific trial with extended attributes
41
+ When I attempt to retrieve trial "NCT00454363"
42
+ Then I should get a trial
43
+ And the trial should have a "phase" of "2"
44
+ And the trial should have "conditions" like "Lung Cancer"
45
+ And the trial should have a "minimum_age" of "21 Years"
46
+ And the trial should have "sponsors" like "M.D. Anderson"
47
+
48
+ Scenario: Find a non-existant trial
49
+ When I attempt to retrieve trial "4325785"
50
+ Then I should not get a trial
51
+
52
+
@@ -0,0 +1,9 @@
1
+ Feature: As a user of the clinical library
2
+ I want to retrieve keywords, categories, and terms from ClinicalTrials.gov
3
+ So that I can associate related trials
4
+
5
+ Scenario: Get keywords, categories, and terms
6
+ When I attempt to retrieve keywords for trial "NCT00001372"
7
+ Then the trial should have "keywords" like "Autoimmunity"
8
+ And the trial should have "categories" like "Urologic Diseases"
9
+ And the trial should have "terms" like "Connective Tissue Diseases"
@@ -0,0 +1,74 @@
1
+ Given /^I am searching for trials where "([^\"]*)" is "([^\"]*)"$/ do |field, value|
2
+ @params ||= {}
3
+
4
+ if value == "true"
5
+ value = true
6
+ elsif value == "false"
7
+ value = false
8
+ end
9
+
10
+ @params[field.to_sym] = value
11
+ end
12
+
13
+ When /^I perform the search$/ do
14
+ @trials = Clinical::Trial.find(:conditions => @params)
15
+ end
16
+
17
+ When /^I perform the extended search$/ do
18
+ @trials = Clinical::Trial.find(:conditions => @params, :extended => true)
19
+ end
20
+
21
+ When /^I attempt to retrieve trial "([^\"]*)"$/ do |id|
22
+ @trial = Clinical::Trial.find_by_id(id)
23
+ end
24
+
25
+ When /^I attempt to retrieve keywords for trial "([^\"]*)"$/ do |id|
26
+ @trial = Clinical::Trial.find_by_id(id)
27
+ @trial.get_metadata
28
+ end
29
+
30
+ Then /^I should get trials that are (not )?"([^\"]*)"$/ do |not_included, field|
31
+ if not_included
32
+ result = false
33
+ else
34
+ result = true
35
+ end
36
+
37
+ @trials.each do |trial|
38
+ trial.send(field + "?").should(eql(result))
39
+ end
40
+ end
41
+
42
+ Then /^I should get trials where the "([^\"]*)" contains "([^\"]*)"$/ do |field, value|
43
+ @trials.each do |trial|
44
+ item_values = []
45
+ result = trial.send(field)
46
+ if result.is_a?(Array)
47
+ found = false
48
+ result.each do |i|
49
+ found = true if i.to_s =~ /#{value}/i
50
+ end
51
+ found.should be_true
52
+ else
53
+ result.to_s.should =~ /#{value}/i
54
+ end
55
+ end
56
+ end
57
+
58
+ Then /^I should get a trial$/ do
59
+ @trial.should_not be_nil
60
+ end
61
+
62
+ Then /^the trial should have an? "([^\"]*)" of "([^\"]*)"$/ do |field, value|
63
+ @trial.send(field).to_s.should eql(value)
64
+ end
65
+
66
+ Then /^the trial should have "([^\"]*)" like "([^\"]*)"$/ do |field, value|
67
+ @trial.send(field).to_s.should =~ /#{Regexp.escape(value)}/
68
+ end
69
+
70
+
71
+ Then /^I should not get a trial$/ do
72
+ @trial.should be_nil
73
+ end
74
+
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'clinical'
3
+
4
+ require 'test/unit/assertions'
5
+
6
+ World(Test::Unit::Assertions)
@@ -0,0 +1,10 @@
1
+ module Clinical
2
+ class Address
3
+ include HappyMapper
4
+
5
+ element :city, String
6
+ element :state, String
7
+ element :zip, String
8
+ element :country, String
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module Clinical
2
+ class Agency
3
+ include Clinical::Sponsor
4
+ tag "sponsors/agency"
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Clinical
2
+ class Collaborator
3
+ include Clinical::Sponsor
4
+ tag "sponsors/collaborator"
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ module Clinical
2
+ class Collection < WillPaginate::Collection
3
+ include HappyMapper
4
+ attr_accessor :count
5
+ class << self
6
+ def create_from_results(page, per_page, body)
7
+ results = SearchResult.parse(body)
8
+ col = create(page, per_page, results.count || 0) do |pager|
9
+ pager.replace(results.trials)
10
+ end
11
+ col.count = results.count
12
+ col
13
+ end
14
+ end
15
+
16
+ class SearchResult
17
+ include HappyMapper
18
+ tag "search_results"
19
+ attribute "count", Integer
20
+
21
+ has_many :trials, Clinical::Trial
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Clinical
2
+ class Condition
3
+ attr_accessor :name
4
+ include HappyMapper
5
+
6
+ def to_s
7
+ self.name || ""
8
+ end
9
+
10
+ class << self
11
+ def parse(xml, options)
12
+ xml.find("condition").collect do |n|
13
+ item = new
14
+ item.name = n.content.chomp.strip
15
+ item
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module Clinical
2
+ class Contact
3
+ include HappyMapper
4
+
5
+ element :first_name, String
6
+ element :middle_name, String
7
+ element :last_name, String
8
+ element :degrees, String
9
+ element :phone, String
10
+ element :phone_ext, String
11
+ element :email, String
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ #thanks Rails Core!
2
+ module Clinical
3
+ module Extensions
4
+ module Array
5
+ def extract_options!
6
+ last.is_a?(::Hash) ? pop : {}
7
+ end
8
+
9
+ end
10
+
11
+ module String
12
+ def underscore(camel_cased_word)
13
+ camel_cased_word.to_s.gsub(/::/, '/').
14
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
15
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
16
+ tr("-", "_").
17
+ downcase
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ unless String.instance_methods.include?("underscore")
24
+ String.send(:include, Clinical::Extensions::String)
25
+ end
26
+ unless Array.instance_methods.include?("extract_options!")
27
+ Array.send(:include, Clinical::Extensions::Array)
28
+ end
@@ -0,0 +1,13 @@
1
+ module Clinical
2
+ class Intervention
3
+ include HappyMapper
4
+
5
+ element :type, String, :tag => "intervention_type"
6
+ element :description, String
7
+ element :name, String, :tag => "intervention_name"
8
+
9
+ def to_s
10
+ "#{self.name} (#{self.type}): #{self.description}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module Clinical
2
+ class LeadSponsor
3
+ include Clinical::Sponsor
4
+ tag "sponsors/lead_sponsor"
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module Clinical
2
+ class Location
3
+ include HappyMapper
4
+
5
+ element :facility, String
6
+ has_one :status, Clinical::Status, :parser => :parse
7
+ has_one :contact, Clinical::Contact
8
+ has_one :address, Clinical::Address
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ module Clinical
2
+ module Outcome
3
+
4
+ def self.included(base)
5
+ base.send(:include, InstanceMethods)
6
+ base.class_eval do
7
+ include InstanceMethods
8
+ include HappyMapper
9
+ element :measure, String
10
+ element :time_frame, String
11
+ element :safety_issue, String
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ def primary?
17
+ self.class.tag_name == "primary_outcome"
18
+ end
19
+
20
+ def to_s
21
+ val = "#{measure}"
22
+ val << ", TIME FRAME: #{time_frame}" if time_frame
23
+ val << ",SAFETY ISSUE: #{safety_issue}" if safety_issue
24
+ val
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ module Clinical
2
+ class PrimaryOutcome
3
+ include Outcome
4
+ tag :primary_outcome
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Clinical
2
+ class SecondaryOutcome
3
+ include Outcome
4
+ tag :secondary_outcome
5
+ end
6
+ end
@@ -0,0 +1,27 @@
1
+ module Clinical
2
+ module Sponsor
3
+ def self.included(base)
4
+ base.class_eval do
5
+ attr_accessor :name
6
+ include HappyMapper
7
+ end
8
+ base.extend(ClassMethods)
9
+ base.send(:include, InstanceMethods)
10
+ end
11
+
12
+ module InstanceMethods
13
+ def to_s
14
+ name
15
+ end
16
+ end
17
+ module ClassMethods
18
+ def parse(xml, options = {})
19
+ xml.find(tag_name).collect do |n|
20
+ item = new
21
+ item.name = n.content.chomp.strip
22
+ item
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ module Clinical
2
+ class Status
3
+ STATUSES = [
4
+ :not_yet_recruiting,
5
+ :recruiting,
6
+ :enrolling_by_invitation,
7
+ :active,
8
+ :not_recruiting,
9
+ :completed,
10
+ :suspended,
11
+ :terminated,
12
+ :withdrawn,
13
+ :available,
14
+ :no_longer_available
15
+ ]
16
+
17
+ OPEN_STATUSES = [
18
+ :not_yet_recruiting,
19
+ :recruiting
20
+ ]
21
+
22
+ attr_reader :name
23
+
24
+ def initialize(sym)
25
+ @name = sym
26
+ end
27
+
28
+ def open?
29
+ OPEN_STATUSES.include?(name)
30
+ end
31
+
32
+ def to_s
33
+ @name.to_s
34
+ end
35
+
36
+ class << self
37
+ def parse(s)
38
+ s.nil? ? nil : Status.new(s.downcase.gsub(" ", "_").to_sym)
39
+ end
40
+ end
41
+ end
42
+ end