Class: RawImageFile

Inherits:
Object
  • Object
show all
Defined in:
lib/raw_image_file.rb

Overview

Implements a collection of metadata associated with a raw image file. In this case, by image we mean one single file. For the case of Pfiles one file corresponds to a complete 4D data set. For dicoms one file corresponds to a single 2D slice, many of which are assembled later during reconstruction to create a 4D data set. The motivation for this class is to provide access to the metadata stored in image file headers so that they can be later reconstructed into nifti data sets.

Constant Summary collapse

MIN_HDR_LENGTH =

:stopdoc:

400
DICOM_HDR =
"dicom_hdr"
RDGEHDR =
"rdgehdr"
MONTHS =
{
  :jan => "01", :feb => "02", :mar => "03", :apr => "04", :may => "05", 
  :jun => "06", :jul => "07", :aug => "08", :sep => "09", :oct => "10", 
  :nov => "11", :dec => "12" 
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pathtofile) ⇒ RawImageFile

Creates a new instance of the class given a path to a valid image file.

Throws IOError if the file given is not found or if the available header reading utilities cannot read the image header. Also raises IOError if any of the attributes cannot be found in the header. Be aware that the filename used to initialize your instance is used to set the “file” attribute. If you need to unzip a file to a temporary location, be sure to keep the same filename for the temporary file.

Raises:

  • (IOError)


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/raw_image_file.rb', line 71

def initialize(pathtofile)
  
  # raise an error if the file doesn't exist
  absfilepath = File.expand_path(pathtofile)
  raise(IOError, "File not found.") if not File.exists?(absfilepath)
  @filename = File.basename(absfilepath)
  
  # try to read the header, raise an ioerror if unsuccessful
  @hdr_data, @hdr_reader = read_header(absfilepath)
  raise(IOError, "Header not readable.") if @hdr_reader.nil?
  
  # file type is based on file name but only if the header was read successfully
  @file_type = determine_file_type
  
  # try to import attributes from the header, raise an ioerror if any attributes
  # are not found
  begin
    import_hdr
  rescue
    raise(IOError, "Header import failed.")
  end
  
  # deallocate the header data to save memory space.
  @hdr_data = nil
end

Instance Attribute Details

#acquisition_matrix_xObject (readonly)

Voxels in x axis.



53
54
55
# File 'lib/raw_image_file.rb', line 53

def acquisition_matrix_x
  @acquisition_matrix_x
end

#acquisition_matrix_yObject (readonly)

Voxels in y axis.



55
56
57
# File 'lib/raw_image_file.rb', line 55

def acquisition_matrix_y
  @acquisition_matrix_y
end

#bold_repsObject (readonly)

Number of bold reps in the complete functional task run.



59
60
61
# File 'lib/raw_image_file.rb', line 59

def bold_reps
  @bold_reps
end

#file_typeObject (readonly)

File types are either ‘dicom’ or ‘pfile’.



32
33
34
# File 'lib/raw_image_file.rb', line 32

def file_type
  @file_type
end

#filenameObject (readonly)

The file name that the instance represents.



28
29
30
# File 'lib/raw_image_file.rb', line 28

def filename
  @filename
end

#genderObject (readonly)

M or F.



43
44
45
# File 'lib/raw_image_file.rb', line 43

def gender
  @gender
end

#hdr_readerObject (readonly)

Which header reading utility reads this file, currently ‘rdgehdr’ or ‘dicom_hdr’.



30
31
32
# File 'lib/raw_image_file.rb', line 30

def hdr_reader
  @hdr_reader
end

#num_slicesObject (readonly)

Number of slices in the data set that includes this file, used by AFNI for reconstruction.



45
46
47
# File 'lib/raw_image_file.rb', line 45

def num_slices
  @num_slices
end

#reconstruction_diameterObject (readonly)

AKA Field of View, in millimeters.



51
52
53
# File 'lib/raw_image_file.rb', line 51

def reconstruction_diameter
  @reconstruction_diameter
end

#rep_timeObject (readonly)

Time for each bold repetition, relevent for functional scans.



57
58
59
# File 'lib/raw_image_file.rb', line 57

def rep_time
  @rep_time
end

#rmr_numberObject (readonly)

An identifier unique to a ‘visit’, these are assigned by the scanner techs at scan time.



38
39
40
# File 'lib/raw_image_file.rb', line 38

def rmr_number
  @rmr_number
end

#series_descriptionObject (readonly)

A short string describing the acquisition sequence. These come from the scanner. code and are used to initialise SeriesDescription objects to find related attributes.



41
42
43
# File 'lib/raw_image_file.rb', line 41

def series_description
  @series_description
end

#slice_spacingObject (readonly)

Gap between slices in millimeters.



49
50
51
# File 'lib/raw_image_file.rb', line 49

def slice_spacing
  @slice_spacing
end

#slice_thicknessObject (readonly)

Given in millimeters.



47
48
49
# File 'lib/raw_image_file.rb', line 47

def slice_thickness
  @slice_thickness
end

#sourceObject (readonly)

The scanner used to perform this scan, e.g. ‘Andys3T’.



36
37
38
# File 'lib/raw_image_file.rb', line 36

def source
  @source
end

#timestampObject (readonly)

The date on which this scan was acquired, this is a ruby DateTime object.



34
35
36
# File 'lib/raw_image_file.rb', line 34

def timestamp
  @timestamp
end

Instance Method Details

#db_fetchObject

Returns an SQL statement to select this image file row from the raw_image_files table of a compatible database.



177
178
179
# File 'lib/raw_image_file.rb', line 177

def db_fetch
  "SELECT *" + from_table_where + sql_match_conditions
end

#db_fetch!(db_file) ⇒ Object

Finds the row in the raw_image_files table of the given db file that matches this object. ORM is based on combination of rmr_number, timestamp, and filename. The row is returned as an array of values (see ‘sqlite3’ gem docs).



219
220
221
222
223
224
# File 'lib/raw_image_file.rb', line 219

def db_fetch!( db_file )
  db = SQLite3::Database.new( db_file )
  db_row = db.execute( db_fetch )
  db.close
  return db_row
end

#db_insert(image_dataset_id) ⇒ Object

Returns an SQL statement to insert this image into the raw_images table of a compatible database (sqlite3). This is intended for inserting into the rails backend database.



162
163
164
165
166
167
168
169
170
171
# File 'lib/raw_image_file.rb', line 162

def db_insert(image_dataset_id)
  "INSERT INTO raw_image_files
  (filename, header_reader, file_type, timestamp, source, rmr_number, series_description, 
  gender, num_slices, slice_thickness, slice_spacing, reconstruction_diameter, 
  acquisition_matrix_x, acquisition_matrix_y, rep_time, bold_reps, created_at, updated_at, image_dataset_id)
  VALUES ('#{@filename}', '#{@hdr_reader}', '#{@file_type}', '#{@timestamp.to_s}', '#{@source}', '#{@rmr_number}', 
  '#{@series_description}', '#{@gender}', #{@num_slices}, #{@slice_thickness}, #{@slice_spacing}, 
  #{@reconstruction_diameter}, #{@acquisition_matrix_x}, #{@acquisition_matrix_y}, #{@rep_time}, 
  #{@bold_reps}, '#{DateTime.now}', '#{DateTime.now}', #{image_dataset_id})"
end

#db_insert!(db_file) ⇒ Object

Uses the db_insert method to actually perform the database insert using the specified database file.



194
195
196
197
198
199
200
201
202
203
# File 'lib/raw_image_file.rb', line 194

def db_insert!( db_file )
  db = SQLite3::Database.new( db_file )
  db.transaction do |database|
    if not database.execute( db_fetch ).empty?
      raise(IndexError, "Entry exists for #{filename}, #{@rmr_number}, #{@timestamp.to_s}... Skipping.")
    end
    database.execute( db_insert )
  end
  db.close
end

#db_removeObject

Returns and SQL statement to remove this image file from the raw_image_files table of a compatible database.



185
186
187
# File 'lib/raw_image_file.rb', line 185

def db_remove
  "DELETE" + from_table_where + sql_match_conditions
end

#db_remove!(db_file) ⇒ Object

Removes this instance from the raw_image_files table of the specified database.



208
209
210
211
212
# File 'lib/raw_image_file.rb', line 208

def db_remove!( db_file )
  db = SQLite3::Database.new( db_file )
  db.execute( db_remove )
  db.close
end

#dicom?Boolean

Predicate simply returns true if “dicom” is stored in the img_type instance variable.

Returns:

  • (Boolean)


119
120
121
# File 'lib/raw_image_file.rb', line 119

def dicom?
  return @file_type == "dicom"
end

#image?Boolean

Predicate method that tells whether or not the file is actually an image. This judgement is based on whether one of the available header reading utilities can actually read the header information.

Returns:

  • (Boolean)


103
104
105
# File 'lib/raw_image_file.rb', line 103

def image?
  return ( @hdr_reader == RDGEHDR or @hdr_reader == DICOM_HDR )
end

#pfile?Boolean

Predicate simply returns true if “pfile” is stored in the @img_type instance variable.

Returns:

  • (Boolean)


111
112
113
# File 'lib/raw_image_file.rb', line 111

def pfile?
  return @file_type == "pfile"
end

#to_arrayObject

Returns the internal, parsed data fields in an array. This is used when scanning dicom slices, to compare each dicom slice in a folder and make sure they all hold the same data.



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/raw_image_file.rb', line 143

def to_array
  return [@filename,
  @timestamp,
  @source,
  @rmr_number,
  @series_description,
  @gender,
  @slice_thickness,
  @slice_spacing,
  @reconstruction_diameter, 
  @acquisition_matrix_x,
  @acquisition_matrix_y]
end

#to_yamlObject

Returns a yaml string based on a subset of the attributes. Specifically, the @hdr_data is not included. This is used to generate .yaml files that are placed in image directories for later scanning by YamlScanner.



129
130
131
132
133
134
135
# File 'lib/raw_image_file.rb', line 129

def to_yaml
  yamlhash = {}
  instance_variables.each do |var|
    yamlhash[var[1..-1]] = instance_variable_get(var) if (var != "@hdr_data")
  end
  return yamlhash.to_yaml
end