metamri 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Manifest +16 -0
- data/README.rdoc +43 -0
- data/Rakefile +34 -0
- data/VERSION +1 -0
- data/bin/import_study.rb +170 -0
- data/bin/import_visit.rb +74 -0
- data/lib/metamri.rb +6 -0
- data/lib/mysql_tools.rb +33 -0
- data/lib/raw_image_dataset.rb +147 -0
- data/lib/raw_image_file.rb +418 -0
- data/lib/series_description_parameters.rb +81 -0
- data/lib/visit_raw_data_directory.rb +395 -0
- data/metamri.gemspec +61 -0
- data/test/raw_image_dataset_test.rb +46 -0
- data/test/raw_image_file_test.rb +135 -0
- data/test/visit_duplication_test.rb +24 -0
- data/test/visit_test.rb +77 -0
- metadata +76 -0
data/.gitignore
ADDED
data/Manifest
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
bin/import_study.rb
|
2
|
+
bin/import_visit.rb
|
3
|
+
ImageData.gemspec
|
4
|
+
lib/metamri.rb
|
5
|
+
lib/mysql_tools.rb
|
6
|
+
lib/raw_image_dataset.rb
|
7
|
+
lib/raw_image_file.rb
|
8
|
+
lib/series_description.rb
|
9
|
+
lib/visit_raw_data_directory.rb
|
10
|
+
Manifest
|
11
|
+
Rakefile
|
12
|
+
README.rdoc
|
13
|
+
test/raw_image_dataset_test.rb
|
14
|
+
test/raw_image_file_test.rb
|
15
|
+
test/visit_duplication_test.rb
|
16
|
+
test/visit_test.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
== ImageData
|
2
|
+
|
3
|
+
A small library that can be used to extract metadata from large collections of research MR imaging data sets. Support is also provided to insert the metadata into a Wisconsin ADRC Imaging Core compatible database. Several
|
4
|
+
command line utilities are provided as well as a minimal API that is useful for building ruby on rails rake tasks.
|
5
|
+
|
6
|
+
You will most likely be interested in either:
|
7
|
+
|
8
|
+
= import_visit.rb CLU
|
9
|
+
|
10
|
+
== Synopsis
|
11
|
+
A simple utility for importing imaging data collected during one visit into the WADRC Data Tools web
|
12
|
+
application. Data from a visit is contained in one big directory that may have many subdirectories.
|
13
|
+
Each individual imaging scan may be composed of an entire directory of dicom files or one single p-file.
|
14
|
+
This utility scans through all of the image data sets and retrieved meta-data about the scans from their
|
15
|
+
header information.
|
16
|
+
|
17
|
+
== Examples
|
18
|
+
import_visit.rb /path/to/raw/mri/data study.codename /path/to/db/db.sqlite3
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
import_visit.rb <raw_data_directory> <scan_procedure_codename> <database_file>
|
22
|
+
|
23
|
+
For help use: import_visit.rb -h
|
24
|
+
|
25
|
+
== Options
|
26
|
+
-h, --help Displays help message
|
27
|
+
-v, --visit Visit raw data directory, absolute path
|
28
|
+
-p, --scan_procedure scan_procedure codename, e.g. johnson.alz.visit1
|
29
|
+
-d, --database Database file into which information will imported
|
30
|
+
|
31
|
+
== Author
|
32
|
+
K.J. Kosmatka, kk4@medicine.wisc.edu
|
33
|
+
|
34
|
+
== Copyright
|
35
|
+
Copyright (c) 2009 WADRC Imaging Core.
|
36
|
+
|
37
|
+
|
38
|
+
or:
|
39
|
+
|
40
|
+
|
41
|
+
= VisitRawDirectory class
|
42
|
+
|
43
|
+
see the doc directory
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# To change this template, choose Tools | Templates
|
3
|
+
# and open the template in the editor.
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rake'
|
7
|
+
# require 'echoe'
|
8
|
+
#
|
9
|
+
# Echoe.new('metamri', '0.1.0') do |p|
|
10
|
+
# p.description = "Extraction of MRI metadata and insertion into compatible sqlite3 databases."
|
11
|
+
# p.url = "http://github.com/brainmap/metamri"
|
12
|
+
# p.author = "Kristopher J. Kosmatka"
|
13
|
+
# p.email = "kk4@medicine.wisc.edu"
|
14
|
+
# p.ignore_pattern = ["nbproject/*"]
|
15
|
+
# p.development_dependencies = []
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
19
|
+
|
20
|
+
|
21
|
+
begin
|
22
|
+
require 'jeweler'
|
23
|
+
Jeweler::Tasks.new do |gemspec|
|
24
|
+
gemspec.name = "metamri"
|
25
|
+
gemspec.summary = "MRI metadata"
|
26
|
+
gemspec.description = "Extraction of MRI metadata and insertion into compatible sqlite3 databases."
|
27
|
+
gemspec.email = "kk4@medicine.wisc.edu"
|
28
|
+
gemspec.homepage = "http://github.com/brainmap/metamri"
|
29
|
+
gemspec.authors = ["Kristopher J. Kosmatka"]
|
30
|
+
end
|
31
|
+
Jeweler::GemcutterTasks.new
|
32
|
+
rescue LoadError
|
33
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
34
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/import_study.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# == Synopsis
|
4
|
+
# A simple utility for importing imaging data for an entire study into the WADRC Data Tools web
|
5
|
+
# application. Scans each visit within a particular protocol and inserts all the appropriat meta-data
|
6
|
+
# into the given database. Can be run as a command line utility, or the function can be required by other packages.
|
7
|
+
#
|
8
|
+
# == Examples
|
9
|
+
# import_study.rb alz_1 /path/to/the/rails/db/production.sqlite3
|
10
|
+
#
|
11
|
+
# == Usage
|
12
|
+
# import_visit.rb <study_code> <database_file>
|
13
|
+
#
|
14
|
+
# Study codes are one of:
|
15
|
+
# alz_1, alz_2, cms_wais, cms_uwmr, esprit_1, esprit_2, gallagher_pd, pib_pilot, ries_pilot, ries_1,
|
16
|
+
# tbi1000_1, tbi1000_2, tbi1000_3, tbiva, wrap140
|
17
|
+
#
|
18
|
+
# For help use: import_study.rb -h
|
19
|
+
#
|
20
|
+
# == Options
|
21
|
+
# -h, --help Displays help message
|
22
|
+
#
|
23
|
+
# == Author
|
24
|
+
# K.J. Kosmatka, kk4@medicine.wisc.edu
|
25
|
+
#
|
26
|
+
# == Copyright
|
27
|
+
# Copyright (c) 2009 WADRC Imaging Core.
|
28
|
+
#
|
29
|
+
|
30
|
+
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
|
31
|
+
|
32
|
+
require 'visit_raw_data_directory'
|
33
|
+
require 'pathname'
|
34
|
+
require 'rdoc/usage'
|
35
|
+
require 'logger'
|
36
|
+
|
37
|
+
#:stopdoc:
|
38
|
+
STUDIES = {
|
39
|
+
:alz_1 => { :dir => '/Data/vtrak1/raw/alz_2000',
|
40
|
+
:logfile => 'alz.visit1.scan.log',
|
41
|
+
:filter => /^alz...$|^alz..._[AB]/i,
|
42
|
+
:codename => 'johnson.alz.visit1'
|
43
|
+
},
|
44
|
+
:alz_2 => { :dir => '/Data/vtrak1/raw/alz_2000',
|
45
|
+
:logfile => 'alz.visit2.scan.log',
|
46
|
+
:filter => /^alz..._2$/,
|
47
|
+
:codename => 'johnson.alz.visit2'
|
48
|
+
},
|
49
|
+
:bendlin_wmad => { :dir => '/Data/vtrak1/raw/bendlin_WMAD/ge3T_750_scanner',
|
50
|
+
:logfile => 'bendlin.wmad.scan.log',
|
51
|
+
:filter => /^wmad/,
|
52
|
+
:codename => 'bendlin.wmad.visit1'
|
53
|
+
},
|
54
|
+
:cms_wais => { :dir => '/Data/vtrak1/raw/cms/wais',
|
55
|
+
:logfile => 'cms.wais.scan.log',
|
56
|
+
:filter => /^pc/,
|
57
|
+
:codename => 'johnson.cms.visit1.wais'
|
58
|
+
},
|
59
|
+
:cms_uwmr => { :dir => '/Data/vtrak1/raw/cms/uwmr',
|
60
|
+
:logfile => 'cms.uwmr.scan.log',
|
61
|
+
:filter => /^cms...$/,
|
62
|
+
:codename => 'johnson.cms.visit1.uwmr'
|
63
|
+
},
|
64
|
+
:esprit_1 => { :dir => '/Data/vtrak1/raw/esprit/baseline',
|
65
|
+
:logfile => 'esprit.baseline.scan.log',
|
66
|
+
:filter => /^esp3/,
|
67
|
+
:codename => 'carlsson.esprit.visit1.baseline'
|
68
|
+
},
|
69
|
+
:esprit_2 => { :dir => '/Data/vtrak1/raw/esprit/9month',
|
70
|
+
:logfile => 'esprit.9month.scan.log',
|
71
|
+
:filter => /^esp3/,
|
72
|
+
:codename => 'carlsson.esprit.visit2.9month'
|
73
|
+
},
|
74
|
+
:gallagher_pd => { :dir => '/Data/vtrak1/raw/gallagher.pd',
|
75
|
+
:logfile => 'gallagher.scan.log',
|
76
|
+
:filter => /^pd..._/,
|
77
|
+
:codename => 'gallagher.pd.visit1'
|
78
|
+
},
|
79
|
+
:pib_pilot => { :dir => '/Data/vtrak1/raw/pib_pilot_mri',
|
80
|
+
:logfile => 'pib.mri.pilot.scan.log',
|
81
|
+
:filter => /^cpr0/,
|
82
|
+
:codename => 'johnson.pibmripilot.visit1.uwmr'
|
83
|
+
},
|
84
|
+
:ries_1 => { :dir => '/Data/vtrak1/raw/ries.aware.visit1',
|
85
|
+
:logfile => 'ries.aware.visit1.scan.log',
|
86
|
+
:filter => /^awr0/,
|
87
|
+
:codename => 'ries.aware.visit1'
|
88
|
+
},
|
89
|
+
:ries_pilot => { :dir => '/Data/vtrak1/raw/ries.aware.visit1',
|
90
|
+
:logfile => 'ries.aware.pilot.scan.log',
|
91
|
+
:filter => /^awrP/,
|
92
|
+
:codename => 'ries.aware.pilot'
|
93
|
+
},
|
94
|
+
:tbi1000_1 => { :dir => '/Data/vtrak1/raw/tbi_1000',
|
95
|
+
:logfile => 'tbi1000.visit1.scan.log',
|
96
|
+
:filter => /^tbi...$/,
|
97
|
+
:codename => 'johnson.tbi1000.visit1'
|
98
|
+
},
|
99
|
+
:tbi1000_2 => { :dir => '/Data/vtrak1/raw/tbi_1000',
|
100
|
+
:logfile => 'tbi1000.visit2.scan.log',
|
101
|
+
:filter => /^tbi..._2/,
|
102
|
+
:codename => 'johnson.tbi1000.visit2'
|
103
|
+
},
|
104
|
+
:tbi1000_3 => { :dir => '/Data/vtrak1/raw/johnson.tbi.aware.visit3',
|
105
|
+
:logfile => 'tbiaware.visit3.scan.log',
|
106
|
+
:filter => /^tbi..._3$/,
|
107
|
+
:codename => 'johnson.tbiaware.visit3'
|
108
|
+
},
|
109
|
+
:tbiva => { :dir => '/Data/vtrak1/raw/johnson.tbi-va.visit1',
|
110
|
+
:logfile => 'tbiva.scan.log',
|
111
|
+
:filter => /^tbi/,
|
112
|
+
:codename => 'johnson.tbiva.visit1'
|
113
|
+
},
|
114
|
+
:wrap140 => { :dir => '/Data/vtrak1/raw/wrap140',
|
115
|
+
:logfile => 'wrap140.scan.log',
|
116
|
+
:filter => /^wrp/,
|
117
|
+
:codename => 'johnson.wrap140.visit1'
|
118
|
+
}
|
119
|
+
}
|
120
|
+
#:startdoc:
|
121
|
+
|
122
|
+
|
123
|
+
# == Function
|
124
|
+
# Imports an entire study.
|
125
|
+
#
|
126
|
+
# == Arguments
|
127
|
+
# study -- a hash specifying the following keys:
|
128
|
+
# :dir => the directory holding all the individual visit directories for this study
|
129
|
+
# :logfile => a file name where logging can be written
|
130
|
+
# :filter => a regex that matches all of the visit directory names that should be scanned
|
131
|
+
# :codename => the study codename, e.g. 'johnson.alz.visit1'
|
132
|
+
#
|
133
|
+
# dbfile -- the database into which meta-data will be inserted
|
134
|
+
#
|
135
|
+
def import_study(study, dbfile)
|
136
|
+
studydir = Pathname.new(study[:dir])
|
137
|
+
log = Logger.new(study[:logfile], shift_age = 7, shift_size = 1048576)
|
138
|
+
|
139
|
+
studydir.entries.each do |visit|
|
140
|
+
next if visit.to_s =~ /^\./
|
141
|
+
next unless visit.to_s =~ study[:filter]
|
142
|
+
visitdir = studydir + visit
|
143
|
+
v = VisitRawDataDirectory.new( visitdir.to_s, study[:codename] )
|
144
|
+
begin
|
145
|
+
v.scan
|
146
|
+
v.db_insert!(dbfile)
|
147
|
+
rescue Exception => e
|
148
|
+
puts "There was a problem scanning a dataset in #{visitdir}... skipping."
|
149
|
+
puts "Exception message: #{e.message}"
|
150
|
+
log.error "There was a problem scanning a dataset in #{visitdir}... skipping."
|
151
|
+
log.error "Exception message: #{e.message}"
|
152
|
+
ensure
|
153
|
+
v = nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
if File.basename(__FILE__) == File.basename($PROGRAM_NAME)
|
159
|
+
RDoc::usage() if (ARGV[0] == '-h' or ARGV.size != 2)
|
160
|
+
study = STUDIES[ARGV[0].to_sym]
|
161
|
+
raise(IndexError, "Study Not Recognized.") if study.nil?
|
162
|
+
dbfile = ARGV[1]
|
163
|
+
raise(IOError, "DB File not writable or not existant") unless File.writable?(dbfile)
|
164
|
+
begin
|
165
|
+
import_study(study, dbfile)
|
166
|
+
rescue IndexError, IOError => e
|
167
|
+
puts "There was an error importing study #{study}. #{e}"
|
168
|
+
raise e
|
169
|
+
end
|
170
|
+
end
|
data/bin/import_visit.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# == Synopsis
|
4
|
+
# A simple utility for importing imaging data collected during one visit into the WADRC Data Tools web
|
5
|
+
# application. Data from a visit is contained in one big directory that may have many subdirectories.
|
6
|
+
# Each individual imaging scan may be composed of an entire directory of dicom files or one single p-file.
|
7
|
+
# This utility scans through all of the image data sets and retrieved meta-data about the scans from their
|
8
|
+
# header information.
|
9
|
+
#
|
10
|
+
# == Examples
|
11
|
+
# import_visit.rb /Data/vtrak1/raw/alz_2000/alz001 johnson.alz.visit1 /path/to/the/rails/db/production.sqlite3
|
12
|
+
# import_visit.rb /Data/vtrak1/raw/wrap140/wrp001_5917_03042008 johnson.wrap140.visit1 /path/to/the/rails/db/production.sqlite3
|
13
|
+
#
|
14
|
+
# == Usage
|
15
|
+
# import_visit.rb <raw_data_directory> <scan_procedure_codename> <database_file>
|
16
|
+
#
|
17
|
+
# For help use: import_visit.rb -h
|
18
|
+
#
|
19
|
+
# == Options
|
20
|
+
# -h, --help Displays help message
|
21
|
+
# -v, --visit Visit raw data directory, absolute path
|
22
|
+
# -p, --scan_procedure scan_procedure codename, e.g. johnson.alz.visit1
|
23
|
+
# -d, --database Database file into which information will imported
|
24
|
+
#
|
25
|
+
# == Author
|
26
|
+
# K.J. Kosmatka, kk4@medicine.wisc.edu
|
27
|
+
#
|
28
|
+
# == Copyright
|
29
|
+
# Copyright (c) 2009 WADRC Imaging Core.
|
30
|
+
#
|
31
|
+
|
32
|
+
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
|
33
|
+
|
34
|
+
require 'visit_raw_data_directory'
|
35
|
+
require 'pathname'
|
36
|
+
require 'rdoc/usage'
|
37
|
+
require 'logger'
|
38
|
+
|
39
|
+
# == Function
|
40
|
+
# Imports imaging data collected during a single visit into the WADRC Data Tools web application database.
|
41
|
+
#
|
42
|
+
# == Usage
|
43
|
+
# import_visit(raw_directory, scan_procedure_codename, database)
|
44
|
+
#
|
45
|
+
# == Example
|
46
|
+
# import_visit('/Data/vtrak1/raw/alz_2000/alz001','johnson.alz.visit1','/path/to/the/rails/db/production.sqlite3')
|
47
|
+
#
|
48
|
+
def import_visit(raw_directory, scan_procedure_codename, database)
|
49
|
+
log = Logger.new(File.basename(raw_directory))
|
50
|
+
v = VisitRawDataDirectory.new(raw_directory, scan_procedure_codename)
|
51
|
+
puts "+++ Importing #{v.visit_directory} as part of #{v.scan_procedure_name} +++"
|
52
|
+
begin
|
53
|
+
v.scan
|
54
|
+
v.db_insert!(database)
|
55
|
+
rescue Exception => e
|
56
|
+
puts "There was a problem scanning a dataset in #{v.visit_directory}... skipping."
|
57
|
+
puts "Exception message: #{e.message}"
|
58
|
+
log.error "There was a problem scanning a dataset in #{v.visit_directory}... skipping."
|
59
|
+
log.error "Exception message: #{e.message}"
|
60
|
+
ensure
|
61
|
+
v = nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
if File.basename(__FILE__) == File.basename($PROGRAM_NAME)
|
68
|
+
RDoc::usage() if (ARGV[0] == '-h' or ARGV.size != 3)
|
69
|
+
raw_directory = ARGV[0]
|
70
|
+
scan_procedure_codename = ARGV[1]
|
71
|
+
database = ARGV[2]
|
72
|
+
raise(IOError, "Database #{database} not writable or doesn't exist.") unless File.writable?(database)
|
73
|
+
import_visit(raw_directory, scan_procedure_codename, database)
|
74
|
+
end
|
data/lib/metamri.rb
ADDED
data/lib/mysql_tools.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'mysql'
|
2
|
+
|
3
|
+
class Mysql
|
4
|
+
def summary
|
5
|
+
self.list_tables.each do |tbl|
|
6
|
+
next if tbl =~ /^tws/
|
7
|
+
puts "+" * 160
|
8
|
+
puts "%80s" % tbl
|
9
|
+
puts "+" * 160
|
10
|
+
columns = self.query("select * from #{tbl}").fetch_hash.keys
|
11
|
+
columns.in_chunks_of(6).each do |chunk|
|
12
|
+
puts "%-25s " * chunk.size % chunk
|
13
|
+
end
|
14
|
+
puts "\n\n"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
class Array
|
22
|
+
def chunks(number_of_chunks)
|
23
|
+
chunks_of( (self.size/number_of_chunks.to_f).ceil )
|
24
|
+
end
|
25
|
+
def in_chunks_of(chunk_size)
|
26
|
+
nchunks = (self.size/chunk_size.to_f).ceil
|
27
|
+
chunks = Array.new(nchunks) { [] }
|
28
|
+
self.each_with_index do |item,index|
|
29
|
+
chunks[ index/chunk_size ] << item
|
30
|
+
end
|
31
|
+
return chunks
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'sqlite3'
|
4
|
+
|
5
|
+
=begin rdoc
|
6
|
+
A #Dataset defines a single 3D or 4D image, i.e. either a volume or a time series
|
7
|
+
of volumes. This encapsulation will provide easy manipulation of groups of raw
|
8
|
+
image files including basic reconstruction.
|
9
|
+
=end
|
10
|
+
class RawImageDataset
|
11
|
+
|
12
|
+
# The directory that contains all the raw images and related files that make up
|
13
|
+
# this data set.
|
14
|
+
attr_reader :directory
|
15
|
+
# An array of #RawImageFile objects that compose the complete data set.
|
16
|
+
attr_reader :raw_image_files
|
17
|
+
# From the first raw image file in the dataset
|
18
|
+
attr_reader :series_description
|
19
|
+
# From the first raw image file in the dataset
|
20
|
+
attr_reader :rmr_number
|
21
|
+
# From the first raw image file in the dataset
|
22
|
+
attr_reader :timestamp
|
23
|
+
# A key string unique to a dataset composed of the rmr number and the timestamp.
|
24
|
+
attr_reader :dataset_key
|
25
|
+
# the file scanned
|
26
|
+
attr_reader :scanned_file
|
27
|
+
# the scanner source
|
28
|
+
attr_reader :scanner_source
|
29
|
+
|
30
|
+
|
31
|
+
=begin rdoc
|
32
|
+
* dir: The directory containing the files.
|
33
|
+
* files: An array of #RawImageFile objects that compose the complete data set.
|
34
|
+
|
35
|
+
Initialization raises errors in several cases:
|
36
|
+
* directory doesn't exist => IOError
|
37
|
+
* any of the raw image files is not actually a RawImageFile => IndexError
|
38
|
+
* series description, rmr number, or timestamp cannot be extracted from the first RawImageFile => IndexError
|
39
|
+
=end
|
40
|
+
def initialize(directory, raw_image_files)
|
41
|
+
@directory = File.expand_path(directory)
|
42
|
+
raise(IOError, "#{@directory} not found.") if not File.directory?(@directory)
|
43
|
+
raise(IOError, "No raw image files supplied.") if (raw_image_files.nil? or raw_image_files.empty?)
|
44
|
+
raw_image_files.each do |im|
|
45
|
+
raise(IndexError, im.to_s + " is not a RawImageFile") if im.class.to_s != "RawImageFile"
|
46
|
+
end
|
47
|
+
@raw_image_files = raw_image_files
|
48
|
+
@series_description = @raw_image_files.first.series_description
|
49
|
+
raise(IndexError, "No series description found") if @series_description.nil?
|
50
|
+
@rmr_number = @raw_image_files.first.rmr_number
|
51
|
+
raise(IndexError, "No rmr found") if @rmr_number.nil?
|
52
|
+
@timestamp = get_earliest_timestamp
|
53
|
+
raise(IndexError, "No timestamp found") if @timestamp.nil?
|
54
|
+
@dataset_key = @rmr_number + "::" + @timestamp.to_s
|
55
|
+
@scanned_file = @raw_image_files.first.filename
|
56
|
+
raise(IndexError, "No scanned file found") if @scanned_file.nil?
|
57
|
+
@scanner_source = @raw_image_files.first.source
|
58
|
+
raise(IndexError, "No scanner source found") if @scanner_source.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
=begin rdoc
|
62
|
+
Generates an SQL insert statement for this dataset that can be used to populate
|
63
|
+
the Johnson Lab rails TransferScans application database backend. The motivation
|
64
|
+
for this is that many dataset inserts can be collected into one db transaction
|
65
|
+
at the visit level, or even higher when doing a whole file system scan.
|
66
|
+
=end
|
67
|
+
def db_insert(visit_id)
|
68
|
+
"INSERT INTO image_datasets
|
69
|
+
(rmr, series_description, path, timestamp, created_at, updated_at, visit_id,
|
70
|
+
glob, rep_time, bold_reps, slices_per_volume, scanned_file)
|
71
|
+
VALUES ('#{@rmr_number}', '#{@series_description}', '#{@directory}', '#{@timestamp.to_s}', '#{DateTime.now}',
|
72
|
+
'#{DateTime.now}', '#{visit_id}', '#{self.glob}', '#{@raw_image_files.first.rep_time}',
|
73
|
+
'#{@raw_image_files.first.bold_reps}', '#{@raw_image_files.first.num_slices}', '#{@scanned_file}')"
|
74
|
+
end
|
75
|
+
|
76
|
+
def db_update(dataset_id)
|
77
|
+
"UPDATE image_datasets SET
|
78
|
+
rmr = '#{@rmr_number}',
|
79
|
+
series_description = '#{@series_description}',
|
80
|
+
path = '#{@directory}',
|
81
|
+
timestamp = '#{@timestamp.to_s}',
|
82
|
+
updated_at = '#{DateTime.now.to_s}',
|
83
|
+
glob = '#{self.glob}',
|
84
|
+
rep_time = '#{@raw_image_files.first.rep_time}',
|
85
|
+
bold_reps = '#{@raw_image_files.first.bold_reps}',
|
86
|
+
slices_per_volume = '#{@raw_image_files.first.num_slices}',
|
87
|
+
scanned_file = '#{@scanned_file}'
|
88
|
+
WHERE id = '#{dataset_id}'"
|
89
|
+
end
|
90
|
+
|
91
|
+
def db_fetch
|
92
|
+
"SELECT * FROM image_datasets
|
93
|
+
WHERE rmr = '#{@rmr_number}'
|
94
|
+
AND path = '#{@directory}'
|
95
|
+
AND timestamp LIKE '#{@timestamp.to_s.split(/\+|Z/).first}%'"
|
96
|
+
end
|
97
|
+
|
98
|
+
def attributes_for_active_record
|
99
|
+
{ :rmr => @rmr_number,
|
100
|
+
:series_description => @series_description,
|
101
|
+
:path => @directory,
|
102
|
+
:timestamp => @timestamp.to_s,
|
103
|
+
:glob => glob,
|
104
|
+
:rep_time => @raw_image_files.first.rep_time,
|
105
|
+
:bold_reps => @raw_image_files.first.bold_reps,
|
106
|
+
:slices_per_volume => @raw_image_files.first.num_slices,
|
107
|
+
:scanned_file => @scanned_file }
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
=begin rdoc
|
113
|
+
Returns a globbing wildcard that is used by to3D to gather files for
|
114
|
+
reconstruction. If no compatible glob is found for the data set, nil is returned.
|
115
|
+
This is always the case for pfiles. For example if the first file in a data set is I.001, then:
|
116
|
+
<tt>dataset.glob</tt>
|
117
|
+
<tt>=> "I.*"</tt>
|
118
|
+
including the quotes, which are necessary becuase some data sets (functional dicoms)
|
119
|
+
have more component files than shell commands can handle.
|
120
|
+
=end
|
121
|
+
def glob
|
122
|
+
case @raw_image_files.first.filename
|
123
|
+
when /^E.*dcm$/
|
124
|
+
return 'E*.dcm'
|
125
|
+
when /\.dcm$/
|
126
|
+
return '*.dcm'
|
127
|
+
when /^I\./
|
128
|
+
return 'I.*'
|
129
|
+
when /^I/
|
130
|
+
return 'I*.dcm'
|
131
|
+
when /\.0/
|
132
|
+
return '*.0*'
|
133
|
+
else
|
134
|
+
return nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
# Gets the earliest timestamp among the raw image files in this dataset.
|
141
|
+
def get_earliest_timestamp
|
142
|
+
@timestamp = (@raw_image_files.sort_by { |i| i.timestamp }).first.timestamp
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
end
|
147
|
+
#### END OF CLASS ####
|