bio-plates 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.
@@ -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