bio-plates 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e44d7a6b3cfc76994ef177d1c2c2797a34b86963
4
+ data.tar.gz: da64276088d9fb070d52137efde8e397da455bae
5
+ SHA512:
6
+ metadata.gz: b5a2b385d0776efee6e348dbede43caba9e781c3c7cc3a38bfd8fd2e457af634b924786796861d1c4f42416515d1d0af83271501dec954a2e13ff9638b8ff1e0
7
+ data.tar.gz: 4e88d259a43da26fc48346a8de5a8df88811fca00d3f5ad1fa09bb134c7985545a5cc884bd30213762e32055a87b996b5912dd529a314d12afbba743840c67b6
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.2.0
5
+
6
+ # - rbx-19mode
7
+ # - 1.8.7
8
+ # - jruby-18mode # JRuby in 1.8 mode
9
+ # - rbx-18mode
10
+
11
+ # uncomment this line if your project needs to run something other than `rake`:
12
+ # script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ gem "bio", "~> 1.4"
5
+ gem "thor"
6
+ # gem "activesupport", ">= 2.3.5"
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development, :test do
10
+ gem "rspec", "~> 3.3"
11
+ gem "jeweler", "~> 2.0"
12
+ gem "bundler"
13
+ gem "rdoc", "~> 3.12"
14
+ gem "fakefs", "~> 0.6"
15
+ gem "simplecov", "~> 0.10"
16
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 stveep
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.
@@ -0,0 +1,146 @@
1
+ # bio-plates
2
+
3
+ [![Build Status](https://secure.travis-ci.org/stveep/bioruby-plates.png)](http://travis-ci.org/stveep/bioruby-plates)
4
+
5
+ Full description goes here
6
+
7
+ Note: this software is under active development!
8
+
9
+ ## Installation
10
+
11
+ ```sh
12
+ gem install bio-plates
13
+ ```
14
+
15
+ ## Usage
16
+ Command line (currently only rearrangement of 96-well plates into a 384-well plate in quadrants):
17
+
18
+ ```sh
19
+ gem install bio-plates
20
+
21
+ bioplates example
22
+ bioplates quadrants [--output=output.csv --newname='My Plate'] PLATE1.csv PLATE2.csv ... # convert 4x96-well plate annotations to a 384-well plate
23
+ ```
24
+ Example input [input.csv]:
25
+
26
+ ```csv
27
+ Plate,Well,siRNA,Drug,Concentration
28
+ Plate1,A1,PLK1,olaparib,0
29
+ Plate1,A2,siCON,olaparib,1
30
+ Plate1,A3,Allstar,olaparib,5
31
+ Plate1,A4,Mock,olaparib,10
32
+ Plate1,A5,BRCA1,olaparib,20
33
+ Plate1,A6,TP53,olaparib,50
34
+ Plate2,A1,PLK1,olaparib,0
35
+ Plate2,A2,siCON,olaparib,1
36
+ Plate2,A3,Allstar,olaparib,5
37
+ Plate2,A4,Mock,olaparib,10
38
+ Plate2,A5,ATR,olaparib,20
39
+ Plate2,A6,ATM,olaparib,50
40
+ Plate3,A1,PLK1,olaparib,0
41
+ Plate3,A2,siCON,olaparib,1
42
+ Plate3,A3,Allstar,olaparib,5
43
+ Plate3,A4,Mock,olaparib,10
44
+ Plate3,A5,PARP1,olaparib,20
45
+ Plate3,A6,ARID1A,olaparib,50
46
+ Plate4,A1,PLK1,olaparib,0
47
+ Plate4,A2,siCON,olaparib,1
48
+ Plate4,A3,Allstar,olaparib,5
49
+ Plate4,A4,Mock,olaparib,10
50
+ Plate4,A5,BRCA2,olaparib,20
51
+ Plate4,A6,PALB2,olaparib,50
52
+ ```
53
+
54
+ ```sh
55
+ bioplates quadrants --output=384.csv --newname="Screen Plate" input.csv
56
+ ```
57
+
58
+ ```csv
59
+ Plate,Row,Column,sirna,drug,concentration,original_well,original_plate
60
+ Screen Plate,A,01,PLK1,olaparib,0,A1,Plate1
61
+ Screen Plate,A,02,PLK1,olaparib,0,A1,Plate2
62
+ Screen Plate,A,03,siCON,olaparib,1,A2,Plate1
63
+ Screen Plate,A,04,siCON,olaparib,1,A2,Plate2
64
+ Screen Plate,A,05,Allstar,olaparib,5,A3,Plate1
65
+ Screen Plate,A,06,Allstar,olaparib,5,A3,Plate2
66
+ Screen Plate,A,07,Mock,olaparib,10,A4,Plate1
67
+ Screen Plate,A,08,Mock,olaparib,10,A4,Plate2
68
+ Screen Plate,A,09,BRCA1,olaparib,20,A5,Plate1
69
+ Screen Plate,A,10,ATR,olaparib,20,A5,Plate2
70
+ Screen Plate,A,11,TP53,olaparib,50,A6,Plate1
71
+ Screen Plate,A,12,ATM,olaparib,50,A6,Plate2
72
+ Screen Plate,B,01,PLK1,olaparib,0,A1,Plate3
73
+ Screen Plate,B,02,PLK1,olaparib,0,A1,Plate4
74
+ Screen Plate,B,03,siCON,olaparib,1,A2,Plate3
75
+ Screen Plate,B,04,siCON,olaparib,1,A2,Plate4
76
+ Screen Plate,B,05,Allstar,olaparib,5,A3,Plate3
77
+ Screen Plate,B,06,Allstar,olaparib,5,A3,Plate4
78
+ Screen Plate,B,07,Mock,olaparib,10,A4,Plate3
79
+ Screen Plate,B,08,Mock,olaparib,10,A4,Plate4
80
+ Screen Plate,B,09,PARP1,olaparib,20,A5,Plate3
81
+ Screen Plate,B,10,BRCA2,olaparib,20,A5,Plate4
82
+ Screen Plate,B,11,ARID1A,olaparib,50,A6,Plate3
83
+ Screen Plate,B,12,PALB2,olaparib,50,A6,Plate4
84
+ ```
85
+
86
+ In a script:
87
+ ```ruby
88
+ require 'bio-plates'
89
+ BioPlates.read("plate.csv")
90
+ #=> => {"Plate1"=>#<BioPlates::Plate:0x007fbc3b0cb260 @name="Plate1", @wells=[#<BioPlates::Plate::Well:0x007fbc3b0cb1e8 @row="A", @column="01", @annotation={:plate=>"Plate1", :drug=>"si1", :conc=>"5"}>, #<BioPlates::Plate::Well:0x007fbc3b0cabf8 @row="A", @column="02", @annotation={:plate=>"Plate1", :drug=>"si2", :conc=>"5"}>, #<BioPlates::Plate::Well:0x007fbc3b0ca540 @row="A", @column="03", @annotation={:plate=>"Plate1", :drug=>"si3", :conc=>"5"}>, #<BioPlates::Plate::Well:0x007fbc3b0c9c30 @row="A", @column="04", @annotation={:plate=>"Plate1", :drug=>"si4", :conc=>"5"}>...
91
+ ## See specs for examples
92
+ ```
93
+
94
+ Example CSV format. Must have a column headed Plate containing plate name, and either a well column Well (e.g. A01 or B4) or two further columns with Row and Column (A,3)
95
+ Any number of further columns can be specified for annotations
96
+ Multiple plates can be specified in the same file, these are read into a Hash keyed by plate name
97
+ ```csv
98
+ Plate,Well,Row,Column,siRNA,Conc
99
+ Plate1,,A,1,si1,5
100
+ Plate1,,A,2,si2,5
101
+ Plate1,,A,3,si3,5
102
+ Plate1,,A,4,si4,5
103
+ Plate1,,A,5,si5,5
104
+ Plate1,,A,6,si6,5
105
+ Plate1,,A,7,si7,5
106
+ Plate1,,A,8,si8,5
107
+ Plate1,,A,9,si9,5
108
+ Plate1,,A,10,si10,5
109
+ Plate1,,A,11,si11,5
110
+ Plate1,,A,12,si12,5
111
+ Plate1,,B,1,si1,5
112
+ Plate1,,B,1,si1,5
113
+ Plate1,,B,1,si1,5
114
+ Plate1,,B,1,si1,5
115
+ ...
116
+ Plate2,A01,,,si1,15
117
+ Plate2,A02,,,si1,15
118
+ Plate2,A03,,,si1,15
119
+ ```
120
+
121
+ The API doc is online. For more code examples see the test files in
122
+ the source tree.
123
+
124
+ ## Project home page
125
+
126
+ Information on the source tree, documentation, examples, issues and
127
+ how to contribute, see
128
+
129
+ http://github.com/stveep/bioruby-plates
130
+
131
+ The BioRuby community is on IRC server: irc.freenode.org, channel: #bioruby.
132
+
133
+ ## Cite
134
+
135
+ If you use this software, please cite one of
136
+
137
+ * [BioRuby: bioinformatics software for the Ruby programming language](http://dx.doi.org/10.1093/bioinformatics/btq475)
138
+ * [Biogem: an effective tool-based approach for scaling up open source software development in bioinformatics](http://dx.doi.org/10.1093/bioinformatics/bts080)
139
+
140
+ ## Biogems.info
141
+
142
+ This Biogem is published at (http://biogems.info/index.html#bio-plates)
143
+
144
+ ## Copyright
145
+
146
+ Copyright (c) 2015 stveep. See LICENSE.txt for further details.
@@ -0,0 +1,48 @@
1
+ = bio-plates
2
+
3
+ {<img
4
+ src="https://secure.travis-ci.org/stveep/bioruby-plates.png"
5
+ />}[http://travis-ci.org/#!/stveep/bioruby-plates]
6
+
7
+ Full description goes here
8
+
9
+ Note: this software is under active development!
10
+
11
+ == Installation
12
+
13
+ gem install bio-plates
14
+
15
+ == Usage
16
+
17
+ == Developers
18
+
19
+ To use the library
20
+
21
+ require 'bio-plates'
22
+
23
+ The API doc is online. For more code examples see also the test files in
24
+ the source tree.
25
+
26
+ == Project home page
27
+
28
+ Information on the source tree, documentation, issues and how to contribute, see
29
+
30
+ http://github.com/stveep/bioruby-plates
31
+
32
+ The BioRuby community is on IRC server: irc.freenode.org, channel: #bioruby.
33
+
34
+ == Cite
35
+
36
+ If you use this software, please cite one of
37
+
38
+ * [BioRuby: bioinformatics software for the Ruby programming language](http://dx.doi.org/10.1093/bioinformatics/btq475)
39
+ * [Biogem: an effective tool-based approach for scaling up open source software development in bioinformatics](http://dx.doi.org/10.1093/bioinformatics/bts080)
40
+
41
+ == Biogems.info
42
+
43
+ This Biogem is published at http://biogems.info/index.html#bio-plates
44
+
45
+ == Copyright
46
+
47
+ Copyright (c) 2015 stveep. See LICENSE.txt for further details.
48
+
@@ -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://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "bio-plates"
18
+ gem.homepage = "http://github.com/stveep/bioruby-plates"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Methods for handling multiwell plate annotations}
21
+ gem.description = %Q{Methods for handling multiwell plate annotations, includes ranges and quadrants}
22
+ gem.email = "spettitt@gmail.com"
23
+ gem.authors = ["Steve Pettitt"]
24
+ gem.version = "0.2.0"
25
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
26
+ gem.required_ruby_version = '>= 2.1.0'
27
+ # dependencies defined in Gemfile
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rspec/core'
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ desc "Code coverage detail"
38
+ task :simplecov do
39
+ ENV['COVERAGE'] = "true"
40
+ Rake::Task['spec'].execute
41
+ end
42
+
43
+ task :default => :spec
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 = "bio-plates #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bio-plates'
3
+ require 'thor'
4
+
5
+ class BioPlatesCLI < Thor
6
+ desc "quadrants [--output=output.csv --newname='QuadrantPlate'] PLATE1.csv PLATE2.csv ...", "convert 4x96-well plate annotations to a 384-well plate"
7
+ option :output
8
+ option :newname
9
+ def quadrants(*plates)
10
+ # read files and merge
11
+ plate_array = []
12
+ plates.each do |plate|
13
+ # TODO: check/warn if any plate names are the same
14
+ BioPlates.read(plate).each{|k,v| plate_array << v}
15
+ end
16
+ output = options[:output] || "output.csv"
17
+ newname = options[:newname] || "QuadrantPlate"
18
+ BioPlates.quadrants(plate_array, newname).dump(output)
19
+ end
20
+
21
+ desc "example", "Show example plate config"
22
+ def example
23
+ puts "Input as comma-separated values, must have a column headed Plate containing plate name, and either a well column Well (e.g. A01 or B4) or two further columns with Row and Column (A,3)"
24
+ puts "Any number of further columns can be specified for annotations"
25
+ print "
26
+ Plate,Well,Row,Column,siRNA,Conc
27
+ Plate1,,A,1,si1,5
28
+ Plate1,,A,2,si2,5
29
+ Plate1,,A,3,si3,5
30
+ Plate1,,A,4,si4,5
31
+ Plate1,,A,5,si5,5
32
+ Plate1,,A,6,si6,5
33
+ Plate1,,A,7,si7,5
34
+ Plate1,,A,8,si8,5
35
+ Plate1,,A,9,si9,5
36
+ Plate1,,A,10,si10,5
37
+ Plate1,,A,11,si11,5
38
+ Plate1,,A,12,si12,5
39
+ Plate1,,B,1,si1,5
40
+ Plate1,,B,1,si1,5
41
+ Plate1,,B,1,si1,5
42
+ Plate1,,B,1,si1,5
43
+ ...
44
+ Plate2,A01,,,si1,15
45
+ Plate2,A02,,,si1,15
46
+ Plate2,A03,,,si1,15"
47
+
48
+
49
+ end
50
+
51
+
52
+ end
53
+
54
+ BioPlatesCLI.start(ARGV)
@@ -0,0 +1,12 @@
1
+ # Please require your code below, respecting the naming conventions in the
2
+ # bioruby directory tree.
3
+ #
4
+ # For example, say you have a plugin named bio-plugin, the only uncommented
5
+ # line in this file would be
6
+ #
7
+ # require 'bio/bio-plugin/plugin'
8
+ #
9
+ # In this file only require other files. Avoid other source code.
10
+
11
+ require 'bio-plates/plates.rb'
12
+
@@ -0,0 +1,159 @@
1
+ class BioPlates
2
+ require 'csv'
3
+ def self.read(file)
4
+ plates = Hash.new{|h,k| h[k] = BioPlates::Plate.new(k)}
5
+ csv = CSV.read(File.open(file), headers: true, header_converters: :symbol)
6
+ unless csv.headers.include? :well || ((csv.headers.include? :row) && (csv.headers.include? :column))
7
+ raise "Column headers must include either Well, or Row and Column"
8
+ end
9
+ csv.each do |row|
10
+ plates[row[:plate]].wells << BioPlates::Plate::Well.new(row)
11
+ end
12
+ plates.map{|k,v| v.add_leading_zeroes!}
13
+ # Return a hash of Plate Objects for all the plates in the CSV
14
+ #plates.each.map!{|k,v| v.name = k}
15
+ plates
16
+ end
17
+
18
+ # form quadrants from four plate Objects
19
+ def self.quadrants(plates,newname="QuadrantPlate")
20
+ if plates.is_a? Hash
21
+ plates = plates.sort.to_h.values
22
+ end
23
+ unless plates.length == 4
24
+ warn "Number of plates supplied should be four; truncating/reusing"
25
+ if plates.length > 4
26
+ plates = plates[0..3]
27
+ elsif plates.length < 4
28
+ i = 0
29
+ until plates.length == 4 do
30
+ duplicate = plates[i].dup
31
+ duplicate.wells = duplicate.wells.map(&:dup)
32
+ plates << duplicate
33
+ # Keep incrementing as long as there are still supplied plates, else reset
34
+ i < plates.length ? i += 1 : i = 0
35
+ end
36
+ end
37
+ end
38
+ newplate = BioPlates::Plate.new(newname)
39
+ plates.each.with_index do |plateobj, plateno|
40
+ plateno = plateno + 1
41
+ modplate = plateobj.dup
42
+ modplate.wells.map!{|x| x.quadrantize!(plateno)}
43
+ modplate.add_leading_zeroes!
44
+ modplate.wells.map(&:index!)
45
+ newplate.wells = newplate.wells + modplate.wells
46
+ end
47
+ newplate.wells = newplate.wells.sort_by{|w| w.well}
48
+ newplate
49
+ end
50
+
51
+ end
52
+
53
+
54
+
55
+
56
+ class BioPlates::Plate
57
+ attr_accessor :wells, :name, :rows, :columns
58
+
59
+ def initialize(name="")
60
+ @name = name
61
+ @wells = []
62
+ end
63
+
64
+ def each
65
+ @wells.each
66
+ end
67
+
68
+ def rows
69
+ @rows = Hash.new{|h,k| h[k] = []}
70
+ @wells.each{|well| @rows[well.row] << well}
71
+ @rows
72
+ end
73
+
74
+ def columns
75
+ @columns = Hash.new{|h,k| h[k] = []}
76
+ @wells.each{|well| @columns[well.column] << well}
77
+ @columns
78
+ end
79
+
80
+ # Add leading zeroes to column strings
81
+ def add_leading_zeroes!
82
+ max = self.wells.dup.sort_by!{|x| x.column.to_s.length}.pop.column.to_s.length
83
+ self.wells.map!{|x| y = ""; (max - x.column.to_s.length).times{y << "0"} ; x.column = y + x.column.to_s; x }
84
+ self
85
+ end
86
+
87
+ def dump(file="output.csv",head=true,format="csv")
88
+ #Column titles required:
89
+ columns = Hash.new{|h,k| h[k] = 1}
90
+ self.wells.each do |well|
91
+ well.annotation.each{|k,v| columns[k] += 1}
92
+ end
93
+ columns.delete(:plate) # Remove original plate annotation
94
+ CSV.open(file,"wb") do |csv|
95
+ if head
96
+ csv << ["Plate","Row","Column"] + columns.keys
97
+ head = false
98
+ end
99
+ self.wells.each do |well|
100
+ line = [self.name,well.row,well.column]
101
+ columns.keys.each do |col_title|
102
+ if well.annotation.keys.include?(col_title)
103
+ line << well.annotation[col_title]
104
+ else
105
+ # Any wells without value for an annotation get a zero
106
+ line << 0
107
+ end
108
+ end
109
+ csv << line
110
+ end
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ class BioPlates::Plate::Well
118
+ attr_accessor :row, :column, :annotation, :well
119
+ @@regexp = /(?<row>[A-Za-z]+)(?<column>\d+)/
120
+ # Better not to hard code these...
121
+ @@nrow = 8
122
+ @@ncol = 12
123
+ def initialize(hash)
124
+
125
+ if hash[:row] && hash[:column]
126
+ @row = hash[:row]
127
+ @column = hash[:column].to_s
128
+ else
129
+ # Split the well annotation if row & col not given separately
130
+ m = hash[:well].match(@@regexp)
131
+ @well = hash[:well]
132
+ @row = m[:row]
133
+ @column = m[:column]
134
+ end
135
+ # NB annotation includes the original well annotation
136
+ @annotation = hash.delete_if{|k,f| [:row, :column, :well].include? k}.to_h
137
+ end
138
+
139
+ def index!
140
+ @well = @row.upcase.to_s + @column
141
+ end
142
+
143
+ def quadrantize!(plate)
144
+ self.index! unless @well
145
+ @annotation[:original_well] = @well
146
+ @annotation[:original_plate] = @annotation[:plate]
147
+ @annotation.delete(:plate) # Remove so no conflict with new plate
148
+ (plate == 2 || plate == 4) ? inc = 1 : inc = 0
149
+ (plate == 3 || plate == 4) ? rowinc = 1 : rowinc = 0
150
+ @column = (@column.to_i + [*0..@@ncol][@column.to_i-1]+inc).to_s
151
+ @row = (@row.ord + [*0..@@nrow][@row.upcase.ord-65]+rowinc).chr # 65 = ASCII "A"
152
+ self
153
+ end
154
+
155
+ def quadrantize(plate)
156
+ dup = self.dup
157
+ dup.quadrantize!(plate)
158
+ end
159
+ end