ruby-igv 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +63 -12
- data/lib/igv/version.rb +1 -1
- data/lib/igv.rb +242 -53
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ca8294136b5eab8a344a40bf1d5ebb6d8ebf08f2794a1c6e1f582f593432049
|
4
|
+
data.tar.gz: c36d4c09a163ade8bfd860519a50519a28ae3f93121a14c482bf1bceb6239cde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a085655336dcd4d06db5b51269f6b72d8d7174767f0b2990796d29cd410fb90adc884b86df3cf97087e75b35d387f655ed557628145c3af9badf17d3b29c50e
|
7
|
+
data.tar.gz: d8e0741301b1504f7714077ef435a987b51c520fcc3788f85acaf42ad3785fcec7bf435e897666a5f9a16050d2f503cfab5daa68525a1fc86a18b5219018a6ed
|
data/README.md
CHANGED
@@ -5,31 +5,82 @@
|
|
5
5
|
[![The MIT License](https://img.shields.io/badge/license-MIT-orange.svg)](LICENSE.txt)
|
6
6
|
[![DOI](https://zenodo.org/badge/281373245.svg)](https://zenodo.org/badge/latestdoi/281373245)
|
7
7
|
|
8
|
+
|
9
|
+
<img src="https://user-images.githubusercontent.com/5798442/182540876-c3ca2906-7d05-4c93-9107-ce4135ae9765.png" align="right">
|
10
|
+
|
8
11
|
## Installation
|
9
12
|
|
10
|
-
Requirement:
|
13
|
+
Requirement :
|
14
|
+
|
15
|
+
* [Ruby](https://github.com/ruby/ruby)
|
16
|
+
* [IGV (Integrative Genomics Viewer)](http://software.broadinstitute.org/software/igv/)
|
17
|
+
* [Enable IGV to listen on the port](https://software.broadinstitute.org/software/igv/Preferences#Advanced)
|
18
|
+
* View > Preference > Advanced > Enable port ☑
|
11
19
|
|
12
20
|
```ruby
|
13
21
|
gem install ruby-igv
|
14
22
|
```
|
15
23
|
|
24
|
+
## Quickstart
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'igv'
|
28
|
+
|
29
|
+
igv = IGV.start # This launch IGV
|
30
|
+
igv.genome 'hg19'
|
31
|
+
igv.load 'http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/' \
|
32
|
+
'wgEncodeUwRepliSeq/wgEncodeUwRepliSeqK562G1AlnRep1.bam'
|
33
|
+
igv.go 'chr18:78,016,233-78,016,640'
|
34
|
+
igv.snapshot 'region.png'
|
35
|
+
igv.exit
|
36
|
+
```
|
37
|
+
|
16
38
|
## Usage
|
17
39
|
|
18
|
-
|
40
|
+
### docs
|
41
|
+
|
42
|
+
See [the list of Batch commands](https://github.com/igvteam/igv/wiki/Batch-commands).
|
19
43
|
|
20
44
|
```ruby
|
21
|
-
igv
|
22
|
-
igv.genome 'hg19'
|
23
|
-
igv.load 'http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeUwRepliSeq/wgEncodeUwRepliSeqK562G1AlnRep1.bam'
|
24
|
-
igv.go 'chr18:78,016,233-78,016,640'
|
25
|
-
igv.save '/tmp/r/region.svg'
|
26
|
-
igv.save '/tmp/r/region.png'
|
27
|
-
igv.snapshot_dir = '/tmp/r2/'
|
28
|
-
igv.save 'region.jpg' # save to /tmp/r2/region.png
|
29
|
-
igv.send 'echo' # whatever you want
|
45
|
+
igv.commands # Show the IGV command reference in your browser
|
30
46
|
```
|
31
47
|
|
32
|
-
|
48
|
+
[docs](https://rubydoc.info/gems/ruby-igv)
|
49
|
+
|
50
|
+
### send
|
51
|
+
|
52
|
+
Not all commands are implemented in Ruby. Commands that are not implemented can be sent using the send method.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
igv.send("maxPanelHeight", 10)
|
56
|
+
```
|
57
|
+
|
58
|
+
|
59
|
+
### Launch IGV
|
60
|
+
|
61
|
+
Launch IGV from Ruby scripot.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
igv = IGV.start # launch IGV app using spawn
|
65
|
+
```
|
66
|
+
|
67
|
+
### Open socket connection to IGV
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
igv = IGV.new # create an IGV object. Then you will type `igv.connect`
|
71
|
+
igv = IGV.open # create an IGV object and connect it to an already activated IGV.
|
72
|
+
```
|
73
|
+
|
74
|
+
### Close IGV
|
75
|
+
|
76
|
+
The behavior of the following methods is different.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
igv.close # close the socket connection
|
80
|
+
igv.exit # send exit command to IGV
|
81
|
+
igv.quit # alias method to exit
|
82
|
+
igv.kill # kill group pid created with IGV.start
|
83
|
+
```
|
33
84
|
|
34
85
|
## Contributing
|
35
86
|
|
data/lib/igv/version.rb
CHANGED
data/lib/igv.rb
CHANGED
@@ -9,103 +9,292 @@ require 'fileutils'
|
|
9
9
|
class IGV
|
10
10
|
class Error < StandardError; end
|
11
11
|
|
12
|
-
attr_reader :host, :port, :
|
12
|
+
attr_reader :host, :port, :history
|
13
13
|
|
14
14
|
def initialize(host: '127.0.0.1', port: 60_151, snapshot_dir: Dir.pwd)
|
15
15
|
@host = host
|
16
16
|
@port = port
|
17
|
+
@snapshot_dir = File.expand_path(snapshot_dir)
|
17
18
|
@history = []
|
18
|
-
connect
|
19
|
-
set_snapshot_dir(snapshot_dir)
|
20
19
|
end
|
21
20
|
|
22
|
-
|
23
|
-
|
21
|
+
def self.open(host: '127.0.0.1', port: 60_151, snapshot_dir: Dir.pwd)
|
22
|
+
igv = new(host: host, port: port, snapshot_dir: snapshot_dir)
|
23
|
+
igv.connect
|
24
|
+
return igv unless block_given?
|
24
25
|
|
25
|
-
|
26
|
+
begin
|
27
|
+
yield igv
|
28
|
+
ensure
|
29
|
+
@socket&.close
|
30
|
+
end
|
31
|
+
igv
|
32
|
+
end
|
33
|
+
|
34
|
+
# Launch IGV from ruby script
|
35
|
+
|
36
|
+
def self.start(port: 60_151, command: 'igv')
|
37
|
+
r, w = IO.pipe
|
38
|
+
pid_igv = spawn(command, '-p', port.to_s, pgroup: true, out: w, err: w)
|
39
|
+
pgid_igv = Process.getpgid(pid_igv)
|
40
|
+
Process.detach(pid_igv)
|
41
|
+
puts "\e[33m"
|
42
|
+
while (line = r.gets.chomp("\n"))
|
43
|
+
puts line
|
44
|
+
break if line.include? "Listening on port #{port}"
|
45
|
+
end
|
46
|
+
puts "\e[0m"
|
47
|
+
igv = open(port: port)
|
48
|
+
igv.instance_variable_set(:@pgid_igv, pgid_igv)
|
49
|
+
igv
|
50
|
+
end
|
51
|
+
|
52
|
+
# Kill IGV process by process group id
|
53
|
+
|
54
|
+
def kill
|
55
|
+
if instance_variable_defined?(:@pgid_igv)
|
56
|
+
warn \
|
57
|
+
'This method kills the process with the group ID specified at startup. ' \
|
58
|
+
'Please use exit or quit if possible.'
|
59
|
+
else
|
60
|
+
warn \
|
61
|
+
'The kill method terminates only IGV commands invoked by the start method.' \
|
62
|
+
'Otherwise, use exit or quit.'
|
63
|
+
return
|
64
|
+
end
|
65
|
+
pgid = @pgid_igv
|
66
|
+
Process.kill(:TERM, -pgid)
|
67
|
+
close
|
68
|
+
end
|
69
|
+
|
70
|
+
# Connect to IGV server
|
71
|
+
|
72
|
+
def connect(host2 = @host, port2 = @port, connect_timeout: nil)
|
73
|
+
@socket&.close
|
74
|
+
@socket = Socket.tcp(host2, port2, connect_timeout: connect_timeout)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Close the socket.
|
78
|
+
# This method dose not exit IGV.
|
79
|
+
|
80
|
+
def close
|
26
81
|
@socket&.close
|
27
|
-
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
|
28
|
-
addr = Socket.sockaddr_in(port, host)
|
29
|
-
@socket.connect(addr)
|
30
82
|
end
|
31
83
|
|
32
|
-
def
|
33
|
-
|
84
|
+
def closed?
|
85
|
+
return true if @socket.nil?
|
86
|
+
|
87
|
+
@socket.closed?
|
88
|
+
end
|
89
|
+
|
90
|
+
# Send batch commands to IGV.
|
91
|
+
# @param [String] cmds
|
92
|
+
|
93
|
+
def send(*cmds)
|
94
|
+
cmd = \
|
95
|
+
cmds
|
96
|
+
.compact
|
97
|
+
.map do |cmd|
|
98
|
+
case cmd
|
99
|
+
when String, Symbol, Numeric then cmd.to_s
|
100
|
+
when ->(c) { c.respond_to?(:to_str) } then cmd.to_str
|
101
|
+
else raise ArgumentError, "#{cmd.inspect} is not a string"
|
102
|
+
end.strip.encode(Encoding::UTF_8)
|
103
|
+
end
|
104
|
+
.join(' ')
|
105
|
+
@history << cmd
|
106
|
+
@socket.puts(cmd)
|
107
|
+
@socket.gets&.chomp("\n")
|
108
|
+
end
|
109
|
+
|
110
|
+
# Show IGV batch commands in the browser.
|
111
|
+
# https://github.com/igvteam/igv/wiki/Batch-commands
|
112
|
+
|
113
|
+
def commands
|
114
|
+
require 'launchy'
|
115
|
+
Launchy.open('https://github.com/igvteam/igv/wiki/Batch-commands')
|
116
|
+
end
|
117
|
+
|
118
|
+
# Writes the value of "param" back to the response
|
119
|
+
#
|
120
|
+
# @param param [String] The parameter to echo.
|
121
|
+
# @return [String] The value of "param". If param is not specified, "echo".
|
122
|
+
|
123
|
+
def echo(param = nil)
|
124
|
+
send :echo, param
|
34
125
|
end
|
35
|
-
|
126
|
+
|
127
|
+
# Selects a genome by id, or loads a genome (or indexed fasta) from the supplied path.
|
128
|
+
#
|
129
|
+
# @param name_or_path [String] The genome to load
|
36
130
|
|
37
131
|
def genome(name_or_path)
|
38
132
|
path = File.expand_path(name_or_path)
|
39
133
|
if File.exist?(path)
|
40
|
-
send
|
134
|
+
send :genome, path
|
41
135
|
else
|
42
|
-
send
|
136
|
+
send :genome, name_or_path
|
43
137
|
end
|
44
138
|
end
|
45
139
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
140
|
+
# Loads a data or session file by specifying a full path to a local file or a URL.
|
141
|
+
#
|
142
|
+
# @param path_or_url [String] The path to a local file or a URL
|
143
|
+
# @param index [String] The index of the file
|
144
|
+
|
145
|
+
def load(path_or_url, index: nil)
|
146
|
+
path_or_url = if URI.parse(path_or_url).scheme
|
147
|
+
path_or_url
|
148
|
+
else
|
149
|
+
File.expand_path(path_or_url)
|
150
|
+
end
|
151
|
+
index = "index=#{index}" if index
|
152
|
+
send :load, path_or_url, index
|
153
|
+
end
|
154
|
+
|
155
|
+
# Go to the specified location
|
156
|
+
#
|
157
|
+
# @param location [String] The location to go to.
|
158
|
+
|
159
|
+
def goto(position)
|
160
|
+
send :goto, position
|
52
161
|
end
|
162
|
+
alias go goto
|
53
163
|
|
54
|
-
|
55
|
-
|
164
|
+
# Defines a region of interest bounded by the two loci
|
165
|
+
#
|
166
|
+
# @param chr [String] The chromosome of the region
|
167
|
+
# @param start [Integer] The start position of the region
|
168
|
+
# @param end_ [Integer] The end position of the region
|
169
|
+
|
170
|
+
def region(chr, start, end_)
|
171
|
+
send :region, chr, start, end_
|
56
172
|
end
|
57
173
|
|
58
174
|
def sort(option = 'base')
|
59
|
-
|
60
|
-
|
61
|
-
|
175
|
+
vop = %w[base position strand quality sample readGroup]
|
176
|
+
raise "options is one of: #{vop.join(', ')}" unless vop.include? option
|
177
|
+
|
178
|
+
send :sort, option
|
179
|
+
end
|
62
180
|
|
63
|
-
|
181
|
+
# Expands the given track.
|
182
|
+
#
|
183
|
+
# @param track [String] The track to expand.
|
184
|
+
# If not specified, expands all tracks.
|
185
|
+
|
186
|
+
def expand(track = nil)
|
187
|
+
send :expand, track
|
188
|
+
end
|
189
|
+
|
190
|
+
# Collapses a given track.
|
191
|
+
#
|
192
|
+
# @param track [String] The track to collapse.
|
193
|
+
# If not specified, collapses all tracks.
|
194
|
+
|
195
|
+
def collapse(track = nil)
|
196
|
+
send :collapse, track
|
64
197
|
end
|
65
198
|
|
66
|
-
|
67
|
-
|
199
|
+
# Squish a given track.
|
200
|
+
#
|
201
|
+
# @param track [String] The track to squish.
|
202
|
+
# If not specified, squishes all tracks.
|
203
|
+
|
204
|
+
def squish(track = nil)
|
205
|
+
send :squish, track
|
68
206
|
end
|
69
207
|
|
70
|
-
|
71
|
-
|
208
|
+
# Set the display mode for an alignment track to "View as pairs".
|
209
|
+
#
|
210
|
+
# @param track [String] The track to set.
|
211
|
+
# If not specified, sets all tracks.
|
212
|
+
|
213
|
+
def viewaspairs(track = nil)
|
214
|
+
send :viewaspairs, track
|
72
215
|
end
|
73
216
|
|
74
217
|
def clear
|
75
|
-
send
|
218
|
+
send :clear
|
76
219
|
end
|
77
220
|
|
221
|
+
# Exit (close) the IGV application.
|
222
|
+
|
78
223
|
def exit
|
79
|
-
send
|
224
|
+
send :exit
|
225
|
+
@socket.close
|
80
226
|
end
|
81
227
|
alias quit exit
|
82
228
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
229
|
+
# Sets the directory in which to write images.
|
230
|
+
# Retruns the current snapshot directory if no argument is given.
|
231
|
+
#
|
232
|
+
# @param path [String] The path to the directory.
|
233
|
+
|
234
|
+
def snapshot_dir(dir_path = nil)
|
235
|
+
return @snapshot_dir if dir_path.nil?
|
236
|
+
|
237
|
+
dir_path = File.expand_path(dir_path)
|
238
|
+
return if dir_path == @snapshot_dir
|
88
239
|
|
89
|
-
|
90
|
-
snapshot_dir =
|
91
|
-
|
240
|
+
r = snapshot_dir_internal(dir_path)
|
241
|
+
@snapshot_dir = dir_path
|
242
|
+
r
|
243
|
+
end
|
92
244
|
|
93
|
-
|
94
|
-
|
95
|
-
|
245
|
+
private def snapshot_dir_internal(dir_path)
|
246
|
+
dir_path = File.expand_path(dir_path)
|
247
|
+
FileUtils.mkdir_p(dir_path)
|
248
|
+
send :snapshotDirectory, dir_path
|
96
249
|
end
|
97
|
-
alias set_snapshot_dir snapshot_dir=
|
98
250
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
251
|
+
# Saves a snapshot of the IGV window to an image file.
|
252
|
+
# If filename is omitted, writes a PNG file with a filename generated based on the locus.
|
253
|
+
# If filename is specified, the filename extension determines the image file format,
|
254
|
+
# which must be either .png or .svg.
|
255
|
+
# @note In Ruby-IGV, it is possible to pass absolute or relative paths as well as file names;
|
256
|
+
# the Snapshot directory is set to Dir.pwd by default.
|
257
|
+
#
|
258
|
+
# @param file_path [String] The path to the image file.
|
259
|
+
|
260
|
+
def snapshot(file_path = nil)
|
261
|
+
return send(:snapshot) if file_path.nil?
|
262
|
+
|
263
|
+
dir_path = File.dirname(file_path)
|
264
|
+
filename = File.basename(file_path)
|
265
|
+
if dir_path != @snapshot_dir
|
266
|
+
snapshot_dir_internal(dir_path)
|
267
|
+
r = send :snapshot, filename
|
268
|
+
snapshot_dir_internal(@snapshot_dir)
|
269
|
+
r
|
106
270
|
else
|
107
|
-
send
|
271
|
+
send :snapshot, filename
|
108
272
|
end
|
109
273
|
end
|
110
|
-
|
274
|
+
|
275
|
+
# Temporarily set the preference named key to the specified value.
|
276
|
+
#
|
277
|
+
# @param key [String] The preference name
|
278
|
+
# @param value [String] The preference value
|
279
|
+
|
280
|
+
def preferences(key, value)
|
281
|
+
send :preferences, key, value
|
282
|
+
end
|
283
|
+
|
284
|
+
# Show "preference.tab" in your browser.
|
285
|
+
|
286
|
+
def show_preferences_table
|
287
|
+
require 'launchy'
|
288
|
+
Launchy.open('https://raw.githubusercontent.com/igvteam/igv/master/src/main/resources/org/broad/igv/prefs/preferences.tab')
|
289
|
+
end
|
290
|
+
|
291
|
+
# Save the current session.
|
292
|
+
# It is recommended that a full path be used for filename. IGV release 2.11.1
|
293
|
+
#
|
294
|
+
# @param filename [String] The path to the session file
|
295
|
+
|
296
|
+
def save_session(file_path)
|
297
|
+
file_path = File.expand_path(file_path)
|
298
|
+
send :saveSession, file_path
|
299
|
+
end
|
111
300
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-igv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kojix2
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: launchy
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|