youandme 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +13 -0
- data/README.md +23 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/youandme +76 -0
- data/lib/.DS_Store +0 -0
- data/lib/youandme.rb +2 -0
- data/lib/youandme/data_processor.rb +116 -0
- data/lib/youandme/raw_data_file_loader.rb +48 -0
- data/lib/youandme/report.css +235 -0
- data/lib/youandme/report.md.erb +37 -0
- data/lib/youandme/xhtml-toc.xslt +134 -0
- data/test/helper.rb +18 -0
- data/test/test_youandme.rb +7 -0
- metadata +146 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem 'getopt', "~> 1.4.1"
|
4
|
+
gem 'rpeg-multimarkdown', '~> 0.1.1', :require => 'multimarkdown'
|
5
|
+
gem 'libxslt-ruby', '~> 1.0.8 '
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "shoulda", ">= 0"
|
9
|
+
gem "bundler", "~> 1.0.0"
|
10
|
+
gem "jeweler", "~> 1.6.4"
|
11
|
+
gem "rcov", ">= 0"
|
12
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
getopt (1.4.1)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.4)
|
7
|
+
bundler (~> 1.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
libxml-ruby (2.2.2)
|
11
|
+
libxslt-ruby (1.0.8)
|
12
|
+
libxml-ruby (>= 2.2.2)
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rcov (0.9.11)
|
15
|
+
rpeg-multimarkdown (0.1.1)
|
16
|
+
shoulda (2.11.3)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
bundler (~> 1.0.0)
|
23
|
+
getopt (~> 1.4.1)
|
24
|
+
jeweler (~> 1.6.4)
|
25
|
+
libxslt-ruby (~> 1.0.8)
|
26
|
+
rcov
|
27
|
+
rpeg-multimarkdown (~> 0.1.1)
|
28
|
+
shoulda
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2011 Preston Lee
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# youandme
|
2
|
+
|
3
|
+
An unofficial Ruby library and command-line application ("youandme") for quickly parsing 23andme raw data files into a plain Ruby structures for quick processing and analysis.
|
4
|
+
|
5
|
+
## Installation ##
|
6
|
+
|
7
|
+
gem install youandme
|
8
|
+
|
9
|
+
## Command-Line Usage
|
10
|
+
|
11
|
+
The primary command-line script is "youandme", which generates a simple side-by-side comparison report for two given 23andme raw data files. To generate the reports, grab a few raw 23andme data files (from 23andme.com, SNPedia etc.), and compare them like so:
|
12
|
+
|
13
|
+
bin/youandme --directory <output_directory> --left <23andme_data_file.txt> --right <23andme_data_file.txt>
|
14
|
+
|
15
|
+
For "full" files, this will take a LONG time to run. (As in, probably more than 24 hours.) I recommend breaking down the data files into chromosome-size chunks, and running each comparison through this script individually.
|
16
|
+
|
17
|
+
## Authors ##
|
18
|
+
|
19
|
+
Preston Lee
|
20
|
+
|
21
|
+
## Copyright
|
22
|
+
|
23
|
+
Copyright (c) 2011 Preston Lee. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "youandme"
|
18
|
+
gem.homepage = "http://github.com/preston/youandme"
|
19
|
+
gem.license = "Apache 2.0"
|
20
|
+
gem.summary = %Q{Data comparison and analysis tools for 23andme raw data files.}
|
21
|
+
gem.description = %Q{An unofficial ruby library for quickly parsing 23andme raw data files into a plain Ruby structures for quick processing and analysis.}
|
22
|
+
gem.email = "conmotto@gmail.com"
|
23
|
+
gem.authors = ["Preston Lee"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
test.rcov_opts << '--exclude "gems/*"'
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rdoc/task'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "youandme #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/bin/youandme
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# An script to compare two 23andme SNP data files.
|
4
|
+
#
|
5
|
+
# Author: Preston Lee
|
6
|
+
# License: Apache 2
|
7
|
+
|
8
|
+
# Runtime libraries:
|
9
|
+
require 'erb'
|
10
|
+
|
11
|
+
# 3rd-party libraries:
|
12
|
+
require 'getopt/long'
|
13
|
+
require 'multimarkdown'
|
14
|
+
|
15
|
+
# Our libraries:
|
16
|
+
current_dir = File.dirname(File.expand_path(__FILE__))
|
17
|
+
gem_dir = File.join(current_dir, '..')
|
18
|
+
lib_path = File.join(gem_dir, 'lib')
|
19
|
+
$LOAD_PATH.unshift lib_path
|
20
|
+
require 'youandme'
|
21
|
+
|
22
|
+
|
23
|
+
def print_help_and_exit
|
24
|
+
puts "Usage:"
|
25
|
+
puts "\t#{$0} --directory <output_directory> --left <23andme_data_file.txt> --right <23andme_data_file.txt>"
|
26
|
+
puts "\t#{$0} -d <output_directory> -l <23andme_data_file.txt> -r <23andme_data_file.txt>"
|
27
|
+
exit(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
begin
|
32
|
+
opt = Getopt::Long.getopts(
|
33
|
+
["--left", "-l", Getopt::REQUIRED],
|
34
|
+
["--right", "-r", Getopt::REQUIRED],
|
35
|
+
["--directory", "-d", Getopt::REQUIRED],
|
36
|
+
["--help", "-h", Getopt::BOOLEAN]
|
37
|
+
)
|
38
|
+
rescue
|
39
|
+
print_help_and_exit
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
if(opt['help'])
|
45
|
+
print_help_and_exit
|
46
|
+
end
|
47
|
+
|
48
|
+
puts "Checking data file existyness..."
|
49
|
+
loader = YouAndMe::RawDataFileLoader.new
|
50
|
+
left_file = opt['left']
|
51
|
+
right_file = opt['right']
|
52
|
+
unless(loader.check_file(left_file) and loader.check_file(right_file))
|
53
|
+
puts "Please specify valid data files!"
|
54
|
+
print_help_and_exit
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "Parsing data files... (may take a while)"
|
58
|
+
max_rows = 1000
|
59
|
+
left = loader.load_file(left_file, max_rows).sort{|a,b| a[:rsid] <=> b[:rsid]}
|
60
|
+
puts "\tLoaded #{left.length} SNPs from #{left_file}"
|
61
|
+
# y left[0..4]
|
62
|
+
right = loader.load_file(right_file, max_rows).sort{|a,b| a[:rsid] <=> b[:rsid]}
|
63
|
+
puts "\tLoaded #{right.length} SNPs from #{right_file}"
|
64
|
+
processor = YouAndMe::DataProcessor.new(left, right)
|
65
|
+
processor.process(true)
|
66
|
+
|
67
|
+
|
68
|
+
puts "Writing reports..."
|
69
|
+
processor.to_multimarkdown(left_file, right_file)
|
70
|
+
path = File.expand_path("#{opt['directory']}")
|
71
|
+
processor.write_multimarkdown(path)
|
72
|
+
processor.write_latex(path)
|
73
|
+
processor.write_html(path)
|
74
|
+
|
75
|
+
|
76
|
+
puts "Done!"
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/youandme.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'xml'
|
2
|
+
require 'libxslt'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
|
6
|
+
module YouAndMe
|
7
|
+
|
8
|
+
class DataProcessor
|
9
|
+
|
10
|
+
attr_accessor :left
|
11
|
+
attr_accessor :right
|
12
|
+
attr_accessor :rsid_same
|
13
|
+
attr_accessor :rsid_diff
|
14
|
+
attr_accessor :both_rsid
|
15
|
+
|
16
|
+
attr_accessor :multimarkdown_text
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(left, right)
|
20
|
+
@left = left
|
21
|
+
@right = right
|
22
|
+
# @rsid_same = nil
|
23
|
+
# @rsid_diff = nil
|
24
|
+
# @both_rsid = nil
|
25
|
+
# process
|
26
|
+
end
|
27
|
+
|
28
|
+
def write_multimarkdown(path)
|
29
|
+
file_path = File.join(path, "report.md")
|
30
|
+
puts "\tMultiMarkdown #{file_path}..."
|
31
|
+
report = File.open(file_path, 'w')
|
32
|
+
report.write @multimarkdown_text
|
33
|
+
report.close
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_latex(path)
|
37
|
+
file_path = File.join(path, "report.ltx")
|
38
|
+
puts "\tLaTeX #{file_path}..."
|
39
|
+
report = File.open(file_path, 'w')
|
40
|
+
mmd = MultiMarkdown.new(@multimarkdown_text)
|
41
|
+
report.write mmd.to_latex
|
42
|
+
report.close
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_html(path)
|
46
|
+
# Write the default file first.
|
47
|
+
file_path = File.join(path, "report.html")
|
48
|
+
puts "\tHTML #{file_path}..."
|
49
|
+
report = File.open(file_path, 'w')
|
50
|
+
mmd = MultiMarkdown.new(@multimarkdown_text, :smart, :filter_html)
|
51
|
+
report.write mmd.to_html
|
52
|
+
report.close
|
53
|
+
|
54
|
+
# Load the XSL Transform.
|
55
|
+
stylesheet_doc = XML::Document.file(File.join(File.dirname(__FILE__), 'xhtml-toc.xslt'))
|
56
|
+
stylesheet = LibXSLT::XSLT::Stylesheet.new(stylesheet_doc)
|
57
|
+
|
58
|
+
# Apply it and re-write the document.
|
59
|
+
old_html = XML::Document.file(file_path)
|
60
|
+
new_html = stylesheet.apply(old_html)
|
61
|
+
report = File.open(file_path, 'w')
|
62
|
+
report.write new_html
|
63
|
+
report.close
|
64
|
+
|
65
|
+
# Copy the CSS file into place.
|
66
|
+
css_src = File.join(File.dirname(__FILE__), 'report.css')
|
67
|
+
css_dest = File.join(path, 'report.css')
|
68
|
+
FileUtils.copy(css_src, css_dest)
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_multimarkdown(left_file, right_file)
|
72
|
+
@left_file = left_file
|
73
|
+
@right_file = right_file
|
74
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
75
|
+
template_file = File.join(dir, 'report.md.erb')
|
76
|
+
template = ERB.new(File.read(template_file))
|
77
|
+
@multimarkdown_text = template.result(binding)
|
78
|
+
end
|
79
|
+
|
80
|
+
def process(status = false)
|
81
|
+
puts "Creating indexes..." if status
|
82
|
+
puts "\tIndexing left data..." if status
|
83
|
+
@left_rsid = @left.collect do |n| n[:rsid] end
|
84
|
+
@left_chromosome = @left.collect do |n| n[:chromosome] end
|
85
|
+
@left_position = @left.collect do |n| n[:position] end
|
86
|
+
@left_genotype = @left.collect do |n| n[:genotype] end
|
87
|
+
|
88
|
+
puts "\tIndexing right data..." if status
|
89
|
+
@right_rsid = @right.collect do |n| n[:rsid] end
|
90
|
+
@right_chromosome = @right.collect do |n| n[:chromosome] end
|
91
|
+
@right_position = @right.collect do |n| n[:position] end
|
92
|
+
@right_genotype = @right.collect do |n| n[:genotype] end
|
93
|
+
|
94
|
+
puts "Computing stuff..." if status
|
95
|
+
puts "\tDetecting basic commonalities..." if status
|
96
|
+
@both_rsid = @left_rsid & @right_rsid
|
97
|
+
both_position = @left_position & @right_position
|
98
|
+
|
99
|
+
puts "\tFinding dissimilar genotypes..." if status
|
100
|
+
@rsid_same = []
|
101
|
+
@rsid_diff = []
|
102
|
+
@both_rsid.each do |rsid|
|
103
|
+
l = left[@left_rsid.index(rsid)]
|
104
|
+
r = right[@right_rsid.index(rsid)]
|
105
|
+
if l[:genotype] == r[:genotype]
|
106
|
+
@rsid_same << [l, r]
|
107
|
+
else
|
108
|
+
@rsid_diff << [l, r]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Author: Preston Lee
|
2
|
+
|
3
|
+
module YouAndMe
|
4
|
+
|
5
|
+
# Tool for loading raw data files from 23andme into native Ruby structures
|
6
|
+
class RawDataFileLoader
|
7
|
+
|
8
|
+
# Returns Markdown-formatted URLs for the given SNP hash.
|
9
|
+
def markdown_links(snp)
|
10
|
+
"[dbSNP](http://www.ncbi.nlm.nih.gov/SNP/snp_ref.cgi?rs=#{snp[:rsid]}) [SNPedia](http://www.snpedia.com/index.php/#{snp[:rsid]})"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns true if and only if the given file exists and is readable.
|
14
|
+
def check_file(file_name)
|
15
|
+
valid = false
|
16
|
+
if(file_name != nil && File.file?(file_name) && File.readable?(file_name))
|
17
|
+
valid = true
|
18
|
+
end
|
19
|
+
valid
|
20
|
+
end
|
21
|
+
|
22
|
+
# Reads the given raw 23andme data file, parses the data, and shoves it into a native Ruby data structure.
|
23
|
+
# The returned data is an +Array+ full of +Hash+es, where each hash has key/value pairs for the columns in the data file.
|
24
|
+
def load_file(file_name, max = 0)
|
25
|
+
snps = []
|
26
|
+
# Manually spliting seems to be faster than the built-in CSV parser for
|
27
|
+
rows = File.read(file_name).split("\n")
|
28
|
+
rows.each do |n|
|
29
|
+
row = n.chomp.split("\t")
|
30
|
+
# CSV.foreach(file_name, :col_sep => "\t") do |row|
|
31
|
+
# Skip if the the line is a comment
|
32
|
+
next if row[0][0] == '#'
|
33
|
+
break if max > 0 && snps.length >= max
|
34
|
+
snp = {
|
35
|
+
:rsid => row[0],
|
36
|
+
:chromosome => row[1],
|
37
|
+
:position => row[2],
|
38
|
+
:genotype => row[3]
|
39
|
+
}
|
40
|
+
# y snp
|
41
|
+
snps << snp
|
42
|
+
end
|
43
|
+
snps
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
body blockquote {
|
4
|
+
margin-top: .75em;
|
5
|
+
line-height: 1.5;
|
6
|
+
margin-bottom: .75em;
|
7
|
+
}
|
8
|
+
html {
|
9
|
+
background: #f8f8f8;
|
10
|
+
}
|
11
|
+
html body {
|
12
|
+
background: #fff;
|
13
|
+
margin: 1em auto 1em auto;
|
14
|
+
padding: 40px 100px;
|
15
|
+
line-height: 1.8;
|
16
|
+
width: 1000px;
|
17
|
+
text-align: justify;
|
18
|
+
font: 1.2em/2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
|
19
|
+
font-size: 18px;
|
20
|
+
color: #444;
|
21
|
+
}
|
22
|
+
|
23
|
+
.legalnotice {
|
24
|
+
font-size: small;
|
25
|
+
font-variant: small-caps;
|
26
|
+
}
|
27
|
+
|
28
|
+
body div {
|
29
|
+
margin: 0;
|
30
|
+
}
|
31
|
+
|
32
|
+
dl {
|
33
|
+
margin: .8em 0;
|
34
|
+
line-height: 1.2;
|
35
|
+
}
|
36
|
+
|
37
|
+
body form {
|
38
|
+
margin: .6em 0;
|
39
|
+
}
|
40
|
+
|
41
|
+
h1, h2, h4, h5, h6,
|
42
|
+
div.example p b,
|
43
|
+
.question,
|
44
|
+
div.table p b,
|
45
|
+
div.procedure p b {
|
46
|
+
color: #005599;
|
47
|
+
font: bold 1.2em/2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
|
48
|
+
margin: 20px 0;
|
49
|
+
}
|
50
|
+
|
51
|
+
h1 {
|
52
|
+
border-bottom: 1px solid black;
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
body hr {
|
59
|
+
margin: .6em;
|
60
|
+
border-width: 0 0 1px 0;
|
61
|
+
border-style: solid;
|
62
|
+
border-color: #cecece;
|
63
|
+
}
|
64
|
+
|
65
|
+
body img.navheader {
|
66
|
+
margin: 0 0 0 -4%;
|
67
|
+
}
|
68
|
+
|
69
|
+
ol {
|
70
|
+
margin: 0 0 0 5%;
|
71
|
+
line-height: 1.2;
|
72
|
+
}
|
73
|
+
|
74
|
+
body pre {
|
75
|
+
margin: .75em 0;
|
76
|
+
line-height: 1.0;
|
77
|
+
font-family: monospace;
|
78
|
+
}
|
79
|
+
|
80
|
+
body td, body th {
|
81
|
+
line-height: 1.2;
|
82
|
+
}
|
83
|
+
|
84
|
+
ul, body dir, body menu {
|
85
|
+
margin: 0 0 0 5%;
|
86
|
+
line-height: 1.2;
|
87
|
+
}
|
88
|
+
|
89
|
+
html {
|
90
|
+
margin: 0;
|
91
|
+
padding: 0;
|
92
|
+
}
|
93
|
+
|
94
|
+
body p b.application {
|
95
|
+
color: #000000;
|
96
|
+
}
|
97
|
+
|
98
|
+
.FILENAME {
|
99
|
+
color: #007a00;
|
100
|
+
}
|
101
|
+
|
102
|
+
.GUIMENU, .GUIMENUITEM, .GUISUBMENU,
|
103
|
+
.GUILABEL, .INTERFACE,
|
104
|
+
.SHORTCUT, .SHORTCUT .KEYCAP {
|
105
|
+
font-weight: bold;
|
106
|
+
}
|
107
|
+
|
108
|
+
.GUIBUTTON {
|
109
|
+
background-color: #CFCFCF;
|
110
|
+
padding: 2px;
|
111
|
+
}
|
112
|
+
|
113
|
+
.ACCEL {
|
114
|
+
background-color: #F0F0F0;
|
115
|
+
text-decoration: underline;
|
116
|
+
}
|
117
|
+
|
118
|
+
.SCREEN {
|
119
|
+
padding: 1ex;
|
120
|
+
}
|
121
|
+
|
122
|
+
.PROGRAMLISTING {
|
123
|
+
padding: 1ex;
|
124
|
+
background-color: #eee;
|
125
|
+
border: 1px solid #ccc;
|
126
|
+
}
|
127
|
+
|
128
|
+
@media screen {/* hide from IE3 */
|
129
|
+
a[href]:hover {
|
130
|
+
background: #ffa
|
131
|
+
}
|
132
|
+
|
133
|
+
}
|
134
|
+
|
135
|
+
BLOCKQUOTE.NOTE {
|
136
|
+
color: #222;
|
137
|
+
background: #eee;
|
138
|
+
border: 1px solid #ccc;
|
139
|
+
padding: 0.4em 0.4em;
|
140
|
+
width: 85%;
|
141
|
+
}
|
142
|
+
|
143
|
+
BLOCKQUOTE.TIP {
|
144
|
+
color: #004F00;
|
145
|
+
background: #d8ecd6;
|
146
|
+
border: 1px solid green;
|
147
|
+
padding: 0.2em 2em;
|
148
|
+
width: 85%;
|
149
|
+
}
|
150
|
+
|
151
|
+
BLOCKQUOTE.IMPORTANT {
|
152
|
+
font-style: italic;
|
153
|
+
border: 1px solid #a00;
|
154
|
+
border-left: 12px solid #c00;
|
155
|
+
padding: 0.1em 1em;
|
156
|
+
}
|
157
|
+
|
158
|
+
BLOCKQUOTE.WARNING {
|
159
|
+
color: #9F1313;
|
160
|
+
background: #f8e8e8;
|
161
|
+
border: 1px solid #e59595;
|
162
|
+
padding: 0.2em 2em;
|
163
|
+
width: 85%;
|
164
|
+
}
|
165
|
+
|
166
|
+
.EXAMPLE {
|
167
|
+
background: #fefde6;
|
168
|
+
border: 1px solid #f1bb16;
|
169
|
+
margin: 1em 0;
|
170
|
+
padding: 0.2em 2em;
|
171
|
+
width: 90%;
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
table {
|
176
|
+
width: 90%;
|
177
|
+
border-top: 1px solid #e5eff8;
|
178
|
+
border-right: 1px solid #e5eff8;
|
179
|
+
margin: 1em auto;
|
180
|
+
border-collapse: collapse;
|
181
|
+
}
|
182
|
+
caption {
|
183
|
+
color: #9ba9b4;
|
184
|
+
font-size: .94em;
|
185
|
+
letter-spacing: .1em;
|
186
|
+
margin: 1em 0 0 0;
|
187
|
+
padding: 0;
|
188
|
+
caption-side: top;
|
189
|
+
text-align: center;
|
190
|
+
}
|
191
|
+
tr.odd td {
|
192
|
+
background: #f7fbff
|
193
|
+
}
|
194
|
+
tr.odd .column1 {
|
195
|
+
background: #f4f9fe;
|
196
|
+
}
|
197
|
+
.column1 {
|
198
|
+
background: #f9fcfe;
|
199
|
+
}
|
200
|
+
td {
|
201
|
+
color: #678197;
|
202
|
+
border-bottom: 1px solid #e5eff8;
|
203
|
+
border-left: 1px solid #e5eff8;
|
204
|
+
padding: .3em 1em;
|
205
|
+
text-align: center;
|
206
|
+
}
|
207
|
+
th {
|
208
|
+
font-weight: normal;
|
209
|
+
color: #678197;
|
210
|
+
text-align: left;
|
211
|
+
border-bottom: 1px solid #e5eff8;
|
212
|
+
border-left: 1px solid #e5eff8;
|
213
|
+
padding: .3em 1em;
|
214
|
+
}
|
215
|
+
thead th {
|
216
|
+
background: #f4f9fe;
|
217
|
+
text-align: center;
|
218
|
+
font: bold 1.2em/2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
|
219
|
+
color: #66a3d3
|
220
|
+
}
|
221
|
+
tfoot th {
|
222
|
+
text-align: center;
|
223
|
+
background: #f4f9fe;
|
224
|
+
}
|
225
|
+
tfoot th strong {
|
226
|
+
font: bold 1.2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
|
227
|
+
margin: .5em .5em .5em 0;
|
228
|
+
color: #66a3d3;
|
229
|
+
}
|
230
|
+
tfoot th em {
|
231
|
+
color: #f03b58;
|
232
|
+
font-weight: bold;
|
233
|
+
font-size: 1.1em;
|
234
|
+
font-style: normal;
|
235
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
Title: SNV Comparison Report
|
2
|
+
Subtitle: A side-by-side comparison
|
3
|
+
Format: complete
|
4
|
+
CSS: report.css
|
5
|
+
|
6
|
+
# SNV Comparison Report
|
7
|
+
|
8
|
+
<% loader = YouAndMe::RawDataFileLoader.new %>
|
9
|
+
|
10
|
+
- Left file: <%= @left_file %>
|
11
|
+
- Right file: <%= @right_file %>
|
12
|
+
- SNPs sequenced in both profiles: <%= @both_rsid.length %> (<%= 100.0 * @both_rsid.length / @left.length %>% of left and <%= 100.0 * @both_rsid.length / @right.length %>% of right.)
|
13
|
+
- Same genotype when SNV in both profiles: <%= @rsid_same.length %> (<%= "%.3f" % (100.0 * @rsid_same.length / @left.length) %>% of left and <%= "%.3f" % (100.0 * @rsid_same.length / @right.length) %>% of right.))
|
14
|
+
- Differing genotypes when SNV in both profiles: <%= @rsid_diff.length %> (<%= "%.3f" % (100.0 * @rsid_diff.length / @left.length) %>% of left and <%= "%.3f" % (100.0 * @rsid_diff.length / @right.length) %>% of right.))
|
15
|
+
- Generated <%= Time.now.strftime("%m/%d/%Y at %I:%M%p") %>.
|
16
|
+
|
17
|
+
## Same Genotype
|
18
|
+
|
19
|
+
The following <%= @rsid_same.length %> SNVs are the *same* in both profiles. Click the links in the last column for access to scientific literature.
|
20
|
+
|
21
|
+
[Same Genotype]
|
22
|
+
| rsID | Genotype | Reference Position | Links ||
|
23
|
+
-------- |
|
24
|
+
<% @rsid_same.each do |n| %><%= n[0][:rsid] %> | <%= n[0][:genotype] %> | <%= n[0][:position] %> |<%= loader.markdown_links(n[0]) %>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
|
28
|
+
## Different Genotype
|
29
|
+
|
30
|
+
The follow <%= @rsid_diff.length %> SNVs *differ* between the profiles. Click the links in the last column for access to scientific literature.
|
31
|
+
|
32
|
+
[Same Genotype]
|
33
|
+
| rsID | Left Genotype | Right Genotype | Reference Position | Links ||
|
34
|
+
-------- |
|
35
|
+
<% @rsid_diff.each do |n| %><%= n[0][:rsid] %> | <%= n[0][:genotype] %> | <%= n[1][:genotype] %> | <%= n[0][:position] %> | <%= loader.markdown_links(n[0]) %>
|
36
|
+
<% end %>
|
37
|
+
|
@@ -0,0 +1,134 @@
|
|
1
|
+
<?xml version='1.0' encoding='utf-8'?>
|
2
|
+
|
3
|
+
<!-- XHTML-to-XHTML converter by Fletcher Penney
|
4
|
+
specifically designed for use with MultiMarkdown created XHTML
|
5
|
+
|
6
|
+
Adds a Table of Contents to the top of the XHTML document,
|
7
|
+
and adds linkbacks from h1 and h2's.
|
8
|
+
|
9
|
+
Also, an example of the sorts of things that can be done to customize
|
10
|
+
the XHTML output of MultiMarkdown.
|
11
|
+
|
12
|
+
MultiMarkdown Version 2.0.b6
|
13
|
+
|
14
|
+
$Id: xhtml-toc.xslt 499 2008-03-23 13:03:19Z fletcher $
|
15
|
+
|
16
|
+
TODO: If a section has no children, a "<ol></ol>" is generated, which is invalid
|
17
|
+
-->
|
18
|
+
|
19
|
+
<!--
|
20
|
+
# Copyright (C) 2007-2008 Fletcher T. Penney <fletcher@fletcherpenney.net>
|
21
|
+
#
|
22
|
+
# This program is free software; you can redistribute it and/or modify
|
23
|
+
# it under the terms of the GNU General Public License as published by
|
24
|
+
# the Free Software Foundation; either version 2 of the License, or
|
25
|
+
# (at your option) any later version.
|
26
|
+
#
|
27
|
+
# This program is distributed in the hope that it will be useful,
|
28
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
29
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
30
|
+
# GNU General Public License for more details.
|
31
|
+
#
|
32
|
+
# You should have received a copy of the GNU General Public License
|
33
|
+
# along with this program; if not, write to the
|
34
|
+
# Free Software Foundation, Inc.
|
35
|
+
# 59 Temple Place, Suite 330
|
36
|
+
# Boston, MA 02111-1307 USA
|
37
|
+
-->
|
38
|
+
|
39
|
+
|
40
|
+
<xsl:stylesheet
|
41
|
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
42
|
+
xmlns:xhtml="http://www.w3.org/1999/xhtml"
|
43
|
+
xmlns="http://www.w3.org/1999/xhtml"
|
44
|
+
exclude-result-prefixes="xhtml xsl"
|
45
|
+
version="1.0">
|
46
|
+
|
47
|
+
<xsl:variable name="newline">
|
48
|
+
<xsl:text>
|
49
|
+
</xsl:text>
|
50
|
+
</xsl:variable>
|
51
|
+
|
52
|
+
<xsl:output method='xml' version="1.0" encoding='utf-8' doctype-public="-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" doctype-system="http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" indent="no"/>
|
53
|
+
|
54
|
+
<!-- the identity template, based on http://www.xmlplease.com/xhtmlxhtml -->
|
55
|
+
<xsl:template match="@*|node()">
|
56
|
+
<xsl:copy>
|
57
|
+
<xsl:apply-templates select="@*|node()"/>
|
58
|
+
</xsl:copy>
|
59
|
+
</xsl:template>
|
60
|
+
|
61
|
+
<!-- adjust the body to add a ToC -->
|
62
|
+
<!-- TODO: Will need to move this to just before first <h1> to allow for introductory comments -->
|
63
|
+
<xsl:template match="xhtml:body">
|
64
|
+
<xsl:copy>
|
65
|
+
<xsl:value-of select="$newline"/>
|
66
|
+
<h1>Table of Contents</h1>
|
67
|
+
<xsl:value-of select="$newline"/>
|
68
|
+
<ol>
|
69
|
+
<xsl:apply-templates select="xhtml:h1" mode="ToC"/>
|
70
|
+
<xsl:value-of select="$newline"/>
|
71
|
+
</ol>
|
72
|
+
<xsl:apply-templates select="@*|node()"/>
|
73
|
+
</xsl:copy>
|
74
|
+
</xsl:template>
|
75
|
+
|
76
|
+
|
77
|
+
<!-- create ToC entry -->
|
78
|
+
<xsl:template match="xhtml:h1" mode="ToC">
|
79
|
+
<xsl:value-of select="$newline"/>
|
80
|
+
<xsl:variable name="link">
|
81
|
+
<xsl:value-of select="@id"/>
|
82
|
+
</xsl:variable>
|
83
|
+
<xsl:variable name="myId">
|
84
|
+
<xsl:value-of select="generate-id(.)"/>
|
85
|
+
</xsl:variable>
|
86
|
+
<li>
|
87
|
+
<a id="ToC-{$link}" href="#{$link}">
|
88
|
+
<xsl:apply-templates select="node()"/>
|
89
|
+
</a>
|
90
|
+
<xsl:if test="following::xhtml:h2[1][preceding::xhtml:h1[1]]">
|
91
|
+
<xsl:value-of select="$newline"/>
|
92
|
+
<ol>
|
93
|
+
<xsl:apply-templates select="following::xhtml:h2[preceding::xhtml:h1[1][generate-id() = $myId]]" mode="ToC"/>
|
94
|
+
<xsl:value-of select="$newline"/>
|
95
|
+
</ol>
|
96
|
+
<xsl:value-of select="$newline"/>
|
97
|
+
</xsl:if>
|
98
|
+
</li>
|
99
|
+
</xsl:template>
|
100
|
+
|
101
|
+
<xsl:template match="xhtml:h2" mode="ToC">
|
102
|
+
<xsl:value-of select="$newline"/>
|
103
|
+
<xsl:variable name="link">
|
104
|
+
<xsl:value-of select="@id"/>
|
105
|
+
</xsl:variable>
|
106
|
+
<li>
|
107
|
+
<a id="ToC-{$link}" href="#{$link}">
|
108
|
+
<xsl:apply-templates select="node()"/>
|
109
|
+
</a>
|
110
|
+
</li>
|
111
|
+
</xsl:template>
|
112
|
+
|
113
|
+
<!-- h1 and h2's should point back to the ToC for easy navigation -->
|
114
|
+
<xsl:template match="xhtml:h1">
|
115
|
+
<xsl:variable name="link">
|
116
|
+
<xsl:value-of select="@id"/>
|
117
|
+
</xsl:variable>
|
118
|
+
<xsl:copy>
|
119
|
+
<xsl:apply-templates select="@*|node()"/>
|
120
|
+
<a href="#ToC-{$link}"> ↩</a>
|
121
|
+
</xsl:copy>
|
122
|
+
</xsl:template>
|
123
|
+
|
124
|
+
<xsl:template match="xhtml:h2">
|
125
|
+
<xsl:variable name="link">
|
126
|
+
<xsl:value-of select="@id"/>
|
127
|
+
</xsl:variable>
|
128
|
+
<xsl:copy>
|
129
|
+
<xsl:apply-templates select="@*|node()"/>
|
130
|
+
<a href="#ToC-{$link}"> ↩</a>
|
131
|
+
</xsl:copy>
|
132
|
+
</xsl:template>
|
133
|
+
|
134
|
+
</xsl:stylesheet>
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'youandme'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: youandme
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Preston Lee
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: getopt
|
16
|
+
requirement: &70244552095660 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.4.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70244552095660
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rpeg-multimarkdown
|
27
|
+
requirement: &70244552094940 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.1
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70244552094940
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: libxslt-ruby
|
38
|
+
requirement: &70244552094060 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.8
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70244552094060
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: shoulda
|
49
|
+
requirement: &70244552093220 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70244552093220
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: bundler
|
60
|
+
requirement: &70244552091740 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.0.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70244552091740
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: jeweler
|
71
|
+
requirement: &70244552090860 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.6.4
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70244552090860
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rcov
|
82
|
+
requirement: &70244552090000 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70244552090000
|
91
|
+
description: An unofficial ruby library for quickly parsing 23andme raw data files
|
92
|
+
into a plain Ruby structures for quick processing and analysis.
|
93
|
+
email: conmotto@gmail.com
|
94
|
+
executables:
|
95
|
+
- youandme
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files:
|
98
|
+
- LICENSE.txt
|
99
|
+
- README.md
|
100
|
+
files:
|
101
|
+
- .document
|
102
|
+
- Gemfile
|
103
|
+
- Gemfile.lock
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- VERSION
|
108
|
+
- bin/youandme
|
109
|
+
- lib/.DS_Store
|
110
|
+
- lib/youandme.rb
|
111
|
+
- lib/youandme/data_processor.rb
|
112
|
+
- lib/youandme/raw_data_file_loader.rb
|
113
|
+
- lib/youandme/report.css
|
114
|
+
- lib/youandme/report.md.erb
|
115
|
+
- lib/youandme/xhtml-toc.xslt
|
116
|
+
- test/helper.rb
|
117
|
+
- test/test_youandme.rb
|
118
|
+
homepage: http://github.com/preston/youandme
|
119
|
+
licenses:
|
120
|
+
- Apache 2.0
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ! '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
hash: -3067078396370175135
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.8.11
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: Data comparison and analysis tools for 23andme raw data files.
|
146
|
+
test_files: []
|