brainmap-ImageData 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ImageData.gemspec +32 -0
- data/LICENSE +3 -0
- data/Manifest +15 -0
- data/README.rdoc +43 -0
- data/Rakefile +18 -0
- data/lib/CLUs/import_study.rb +161 -0
- data/lib/CLUs/import_visit.rb +73 -0
- data/lib/mysql_tools.rb +33 -0
- data/lib/raw_image_dataset.rb +131 -0
- data/lib/raw_image_file.rb +411 -0
- data/lib/series_description.rb +81 -0
- data/lib/visit_raw_data_directory.rb +356 -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 +85 -0
data/ImageData.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{ImageData}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Kristopher J. Kosmatka"]
|
9
|
+
s.date = %q{2009-08-06}
|
10
|
+
s.description = %q{Extraction of MRI metadata and insertion into compatible sqlite3 databases.}
|
11
|
+
s.email = %q{kk4@medicine.wisc.edu}
|
12
|
+
s.extra_rdoc_files = ["lib/CLUs/import_study.rb", "lib/CLUs/import_visit.rb", "lib/mysql_tools.rb", "lib/raw_image_dataset.rb", "lib/raw_image_file.rb", "lib/series_description.rb", "lib/visit_raw_data_directory.rb", "LICENSE", "README.rdoc"]
|
13
|
+
s.files = ["lib/CLUs/import_study.rb", "lib/CLUs/import_visit.rb", "lib/mysql_tools.rb", "lib/raw_image_dataset.rb", "lib/raw_image_file.rb", "lib/series_description.rb", "lib/visit_raw_data_directory.rb", "LICENSE", "Manifest", "Rakefile", "README.rdoc", "test/raw_image_dataset_test.rb", "test/raw_image_file_test.rb", "test/visit_duplication_test.rb", "test/visit_test.rb", "ImageData.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/brainmap/ImageData}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "ImageData", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{imagedata}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Extraction of MRI metadata and insertion into compatible sqlite3 databases.}
|
21
|
+
s.test_files = ["test/raw_image_dataset_test.rb", "test/raw_image_file_test.rb", "test/visit_duplication_test.rb", "test/visit_test.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
data/LICENSE
ADDED
data/Manifest
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
lib/CLUs/import_study.rb
|
2
|
+
lib/CLUs/import_visit.rb
|
3
|
+
lib/mysql_tools.rb
|
4
|
+
lib/raw_image_dataset.rb
|
5
|
+
lib/raw_image_file.rb
|
6
|
+
lib/series_description.rb
|
7
|
+
lib/visit_raw_data_directory.rb
|
8
|
+
LICENSE
|
9
|
+
Manifest
|
10
|
+
Rakefile
|
11
|
+
README.rdoc
|
12
|
+
test/raw_image_dataset_test.rb
|
13
|
+
test/raw_image_file_test.rb
|
14
|
+
test/visit_duplication_test.rb
|
15
|
+
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,18 @@
|
|
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('ImageData', '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/ImageData"
|
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 }
|
@@ -0,0 +1,161 @@
|
|
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_visit.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__),'..')
|
31
|
+
|
32
|
+
require 'visit_raw_data_directory'
|
33
|
+
require 'pathname'
|
34
|
+
require 'logger'
|
35
|
+
|
36
|
+
#:stopdoc:
|
37
|
+
STUDIES = {
|
38
|
+
:alz_1 => { :dir => '/Data/vtrak1/raw/alz_2000',
|
39
|
+
:logfile => 'alz.visit1.scan.log',
|
40
|
+
:filter => /^alz...$|^alz..._[AB]/i,
|
41
|
+
:codename => 'johnson.alz.visit1'
|
42
|
+
},
|
43
|
+
:alz_2 => { :dir => '/Data/vtrak1/raw/alz_2000',
|
44
|
+
:logfile => 'alz.visit2.scan.log',
|
45
|
+
:filter => /^alz..._2$/,
|
46
|
+
:codename => 'johnson.alz.visit2'
|
47
|
+
},
|
48
|
+
:cms_wais => { :dir => '/Data/vtrak1/raw/cms/wais',
|
49
|
+
:logfile => 'cms.wais.scan.log',
|
50
|
+
:filter => /^pc/,
|
51
|
+
:codename => 'johnson.cms.visit1.wais'
|
52
|
+
},
|
53
|
+
:cms_uwmr => { :dir => '/Data/vtrak1/raw/cms/uwmr',
|
54
|
+
:logfile => 'cms.uwmr.scan.log',
|
55
|
+
:filter => /^cms...$/,
|
56
|
+
:codename => 'johnson.cms.visit1.uwmr'
|
57
|
+
},
|
58
|
+
:esprit_1 => { :dir => '/Data/vtrak1/raw/esprit/baseline',
|
59
|
+
:logfile => 'esprit.baseline.scan.log',
|
60
|
+
:filter => /^esp3/,
|
61
|
+
:codename => 'carlsson.esprit.visit1.baseline'
|
62
|
+
},
|
63
|
+
:esprit_2 => { :dir => '/Data/vtrak1/raw/esprit/9month',
|
64
|
+
:logfile => 'esprit.9month.scan.log',
|
65
|
+
:filter => /^esp3/,
|
66
|
+
:codename => 'carlsson.esprit.visit2.9month'
|
67
|
+
},
|
68
|
+
:gallagher_pd => { :dir => '/Data/vtrak1/raw/gallagher_pd',
|
69
|
+
:logfile => 'gallagher.scan.log',
|
70
|
+
:filter => /^pd..._/,
|
71
|
+
:codename => 'gallagher.pd.visit1'
|
72
|
+
},
|
73
|
+
:pib_pilot => { :dir => '/Data/vtrak1/raw/pib_pilot_mri',
|
74
|
+
:logfile => 'pib.mri.pilot.scan.log',
|
75
|
+
:filter => /^cpr0/,
|
76
|
+
:codename => 'johnson.pibmripilot.visit1.uwmr'
|
77
|
+
},
|
78
|
+
:ries_1 => { :dir => '/Data/vtrak1/raw/ries.aware.visit1',
|
79
|
+
:logfile => 'ries.aware.visit1.scan.log',
|
80
|
+
:filter => /^awr0/,
|
81
|
+
:codename => 'ries.aware.visit1'
|
82
|
+
},
|
83
|
+
:ries_pilot => { :dir => '/Data/vtrak1/raw/ries.aware.visit1',
|
84
|
+
:logfile => 'ries.aware.pilot.scan.log',
|
85
|
+
:filter => /^awrP/,
|
86
|
+
:codename => 'ries.aware.pilot'
|
87
|
+
},
|
88
|
+
:tbi1000_1 => { :dir => '/Data/vtrak1/raw/tbi_1000',
|
89
|
+
:logfile => 'tbi1000.visit1.scan.log',
|
90
|
+
:filter => /^tbi...$/,
|
91
|
+
:codename => 'johnson.tbi1000.visit1'
|
92
|
+
},
|
93
|
+
:tbi1000_2 => { :dir => '/Data/vtrak1/raw/tbi_1000',
|
94
|
+
:logfile => 'tbi1000.visit2.scan.log',
|
95
|
+
:filter => /^tbi..._2/,
|
96
|
+
:codename => 'johnson.tbi1000.visit2'
|
97
|
+
},
|
98
|
+
:tbi1000_3 => { :dir => '/Data/vtrak1/raw/tbi_aware',
|
99
|
+
:logfile => 'tbiaware.visit3.scan.log',
|
100
|
+
:filter => /^tbi..._3$/,
|
101
|
+
:codename => 'johnson.tbiaware.visit3'
|
102
|
+
},
|
103
|
+
:tbiva => { :dir => '/Data/vtrak1/raw/johnson.tbi-va.visit1',
|
104
|
+
:logfile => 'tbiva.scan.log',
|
105
|
+
:filter => /^tbi/,
|
106
|
+
:codename => 'johnson.tbiva.visit1'
|
107
|
+
},
|
108
|
+
:wrap140 => { :dir => '/Data/vtrak1/raw/wrap140',
|
109
|
+
:logfile => 'wrap140.scan.log',
|
110
|
+
:filter => /^wrp/,
|
111
|
+
:codename => 'johnson.wrap140.visit1'
|
112
|
+
}
|
113
|
+
}
|
114
|
+
#:startdoc:
|
115
|
+
|
116
|
+
|
117
|
+
# == Function
|
118
|
+
# Imports an entire study.
|
119
|
+
#
|
120
|
+
# == Arguments
|
121
|
+
# study -- a hash specifying the following keys:
|
122
|
+
# :dir => the directory holding all the individual visit directories for this study
|
123
|
+
# :logfile => a file name where logging can be written
|
124
|
+
# :filter => a regex that matches all of the visit directory names that should be scanned
|
125
|
+
# :codename => the study codename, e.g. 'johnson.alz.visit1'
|
126
|
+
#
|
127
|
+
# dbfile -- the database into which meta-data will be inserted
|
128
|
+
#
|
129
|
+
def import_study(study, dbfile)
|
130
|
+
studydir = Pathname.new(study[:dir])
|
131
|
+
log = Logger.new(study[:logfile], shift_age = 7, shift_size = 1048576)
|
132
|
+
|
133
|
+
studydir.entries.each do |visit|
|
134
|
+
next if visit.to_s =~ /^\./
|
135
|
+
next unless visit.to_s =~ study[:filter]
|
136
|
+
visitdir = studydir + visit
|
137
|
+
v = VisitRawDataDirectory.new( visitdir.to_s, study[:codename] )
|
138
|
+
begin
|
139
|
+
v.scan
|
140
|
+
v.db_insert!(dbfile)
|
141
|
+
rescue Exception => e
|
142
|
+
puts "There was a problem scanning a dataset in #{visitdir}... skipping."
|
143
|
+
puts "Exception message: #{e.message}"
|
144
|
+
LOG.error "There was a problem scanning a dataset in #{visitdir}... skipping."
|
145
|
+
LOG.error "Exception message: #{e.message}"
|
146
|
+
ensure
|
147
|
+
v = nil
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
if __FILE__ == $0
|
155
|
+
study = STUDIES[ARGV[0].to_sym]
|
156
|
+
dbfile = ARGV[1]
|
157
|
+
import_study(study, dbfile)
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
|
@@ -0,0 +1,73 @@
|
|
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__),'..')
|
33
|
+
|
34
|
+
require 'visit_raw_data_directory'
|
35
|
+
require 'pathname'
|
36
|
+
require 'rdoc/usage'
|
37
|
+
|
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
|
+
v = VisitRawDataDirectory.new(raw_directory, scan_procedure_codename)
|
50
|
+
puts "+++ Importing #{v.visit_directory} as part of #{v.scan_procedure_name} +++"
|
51
|
+
begin
|
52
|
+
v.scan
|
53
|
+
puts v
|
54
|
+
v.db_insert!(database)
|
55
|
+
rescue Exception => e
|
56
|
+
puts "There was a problem scanning a dataset in #{visitdir}... skipping."
|
57
|
+
puts "Exception message: #{e.message}"
|
58
|
+
LOG.error "There was a problem scanning a dataset in #{visitdir}... skipping."
|
59
|
+
LOG.error "Exception message: #{e.message}"
|
60
|
+
ensure
|
61
|
+
v = nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
if __FILE__ == $0
|
68
|
+
RDoc::usage() if ARGV[0] == '-h'
|
69
|
+
raw_directory = ARGV[0]
|
70
|
+
scan_procedure_codename = ARGV[1]
|
71
|
+
database = ARGV[2]
|
72
|
+
import_visit(raw_directory, scan_procedure_codename, database)
|
73
|
+
end
|
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,131 @@
|
|
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
|
+
|
28
|
+
|
29
|
+
=begin rdoc
|
30
|
+
* dir: The directory containing the files.
|
31
|
+
* files: An array of #RawImageFile objects that compose the complete data set.
|
32
|
+
|
33
|
+
Initialization raises errors in several cases:
|
34
|
+
* directory doesn't exist => IOError
|
35
|
+
* any of the raw image files is not actually a RawImageFile => IndexError
|
36
|
+
* series description, rmr number, or timestamp cannot be extracted from the first RawImageFile => IndexError
|
37
|
+
=end
|
38
|
+
def initialize(directory, raw_image_files)
|
39
|
+
@directory = File.expand_path(directory)
|
40
|
+
raise(IOError, "#{@directory} not found.") if not File.directory?(@directory)
|
41
|
+
raise(IOError, "No raw image files supplied.") if (raw_image_files.nil? or raw_image_files.empty?)
|
42
|
+
raw_image_files.each do |im|
|
43
|
+
raise(IndexError, im.to_s + " is not a RawImageFile") if im.class.to_s != "RawImageFile"
|
44
|
+
end
|
45
|
+
@raw_image_files = raw_image_files
|
46
|
+
@series_description = @raw_image_files.first.series_description
|
47
|
+
raise(IndexError, "No series description found") if @series_description.nil?
|
48
|
+
@rmr_number = @raw_image_files.first.rmr_number
|
49
|
+
raise(IndexError, "No rmr found") if @rmr_number.nil?
|
50
|
+
@timestamp = get_earliest_timestamp
|
51
|
+
raise(IndexError, "No timestamp found") if @timestamp.nil?
|
52
|
+
@dataset_key = @rmr_number + "::" + @timestamp.to_s
|
53
|
+
@scanned_file = @raw_image_files.first.filename
|
54
|
+
raise(IndexError, "No scanned file found") if @scanned_file.nil?
|
55
|
+
end
|
56
|
+
|
57
|
+
=begin rdoc
|
58
|
+
Generates an SQL insert statement for this dataset that can be used to populate
|
59
|
+
the Johnson Lab rails TransferScans application database backend. The motivation
|
60
|
+
for this is that many dataset inserts can be collected into one db transaction
|
61
|
+
at the visit level, or even higher when doing a whole file system scan.
|
62
|
+
=end
|
63
|
+
def db_insert(visit_id)
|
64
|
+
"INSERT INTO image_datasets
|
65
|
+
(rmr, series_description, path, timestamp, created_at, updated_at, visit_id,
|
66
|
+
glob, rep_time, bold_reps, slices_per_volume, scanned_file)
|
67
|
+
VALUES ('#{@rmr_number}', '#{@series_description}', '#{@directory}', '#{@timestamp.to_s}', '#{DateTime.now}',
|
68
|
+
'#{DateTime.now}', '#{visit_id}', '#{self.glob}', '#{@raw_image_files.first.rep_time}',
|
69
|
+
'#{@raw_image_files.first.bold_reps}', '#{@raw_image_files.first.num_slices}', '#{@scanned_file}')"
|
70
|
+
end
|
71
|
+
|
72
|
+
def db_update(dataset_id)
|
73
|
+
"UPDATE image_datasets SET
|
74
|
+
rmr = '#{@rmr_number}',
|
75
|
+
series_description = '#{@series_description}',
|
76
|
+
path = '#{@directory}',
|
77
|
+
timestamp = '#{@timestamp.to_s}',
|
78
|
+
updated_at = '#{DateTime.now.to_s}',
|
79
|
+
glob = '#{self.glob}',
|
80
|
+
rep_time = '#{@raw_image_files.first.rep_time}',
|
81
|
+
bold_reps = '#{@raw_image_files.first.bold_reps}',
|
82
|
+
slices_per_volume = '#{@raw_image_files.first.num_slices}',
|
83
|
+
scanned_file = '#{@scanned_file}'
|
84
|
+
WHERE id = '#{dataset_id}'"
|
85
|
+
end
|
86
|
+
|
87
|
+
def db_fetch
|
88
|
+
"SELECT * FROM image_datasets
|
89
|
+
WHERE rmr = '#{@rmr_number}'
|
90
|
+
AND path = '#{@directory}'
|
91
|
+
AND timestamp LIKE '#{@timestamp.to_s.split(/\+|Z/).first}%'"
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
=begin rdoc
|
97
|
+
Returns a globbing wildcard that is used by to3D to gather files for
|
98
|
+
reconstruction. If no compatible glob is found for the data set, nil is returned.
|
99
|
+
This is always the case for pfiles. For example if the first file in a data set is I.001, then:
|
100
|
+
<tt>dataset.glob</tt>
|
101
|
+
<tt>=> "I.*"</tt>
|
102
|
+
including the quotes, which are necessary becuase some data sets (functional dicoms)
|
103
|
+
have more component files than shell commands can handle.
|
104
|
+
=end
|
105
|
+
def glob
|
106
|
+
case @raw_image_files.first.filename
|
107
|
+
when /^E.*dcm$/
|
108
|
+
return 'E*.dcm'
|
109
|
+
when /\.dcm$/
|
110
|
+
return '*.dcm'
|
111
|
+
when /^I\./
|
112
|
+
return 'I.*'
|
113
|
+
when /^I/
|
114
|
+
return 'I*.dcm'
|
115
|
+
when /\.0/
|
116
|
+
return '*.0*'
|
117
|
+
else
|
118
|
+
return nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# Gets the earliest timestamp among the raw image files in this dataset.
|
125
|
+
def get_earliest_timestamp
|
126
|
+
@timestamp = (@raw_image_files.sort_by { |i| i.timestamp }).first.timestamp
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
end
|
131
|
+
#### END OF CLASS ####
|