Class: RawImageFile

Inherits:
Object
  • Object
show all
Defined in:
lib/metamri/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.

Primarily used to instantiate a #RawImageDataset

Constant Summary collapse

MIN_HDR_LENGTH =

:stopdoc:

400
MIN_HDR_SUMMARY_LENGTH =
100
DICOM_HDR =
"dicom_hdr"
RDGEHDR =
"rdgehdr"
PRINTRAW =
"printraw"
PRINTRAW_SUMMARY =

“printraw_summary”

"cat"
RUBYDICOM_HDR =
"rubydicom"
VALID_HEADERS =
[DICOM_HDR, PRINTRAW, RDGEHDR, RUBYDICOM_HDR,PRINTRAW_SUMMARY]
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)


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/metamri/raw_image_file.rb', line 99

def initialize(pathtofile)
  # raise an error if the file doesn't exist
  absfilepath = File.expand_path(pathtofile)
   puts "initialize raw image file ="+absfilepath
  raise(IOError, "File not found at #{absfilepath}.") if not File.exists?(absfilepath)
  @filename = File.basename(absfilepath)
  @warnings = []

  #if P*.7.summary need different read_header_summary
  if @filename =~ /^P*\.summary/
     @hdr_reader = PRINTRAW_SUMMARY
  end
  # try to read the header, raise an IOError if unsuccessful
  begin
    @hdr_data, @hdr_reader = read_header(absfilepath)
    if @hdr_reader == nil
         puts " hdr_reader is nil"
    end
  rescue Exception => e
    raise(IOError, "Header not readable for file #{@filename} using #{@current_hdr_reader ? @current_hdr_reader : "unknown header reader."}. #{e}")
  end
  
  # 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 ScriptError or NoMethodError 
  # if any required attributes are not found
  begin
    import_hdr
  rescue ScriptError, NoMethodError => e
    # puts e.backtrace
    raise e, "Could not find required DICOM Header Meta Element: #{e}"
  rescue StandardError => e
    raise e, "Header import failed for file #{@filename}.  #{e} . Has the scanner software version changed? A new version of the p-file reading software (printraw or rdgehdr) might be needed. "
  end
  
  # deallocate the header data to save memory space.
  @hdr_data = nil
end

Instance Attribute Details

#acquisition_matrix_xObject (readonly)

Voxels in x axis.



67
68
69
# File 'lib/metamri/raw_image_file.rb', line 67

def acquisition_matrix_x
  @acquisition_matrix_x
end

#acquisition_matrix_yObject (readonly)

Voxels in y axis.



69
70
71
# File 'lib/metamri/raw_image_file.rb', line 69

def acquisition_matrix_y
  @acquisition_matrix_y
end

#bold_repsObject (readonly)

Number of bold reps in the complete functional task run.



73
74
75
# File 'lib/metamri/raw_image_file.rb', line 73

def bold_reps
  @bold_reps
end

#dicom_headerObject (readonly)

Serialized RubyDicomHeader Object (for DICOMs only)



77
78
79
# File 'lib/metamri/raw_image_file.rb', line 77

def dicom_header
  @dicom_header
end

#dicom_image_uidObject (readonly)

DICOM SOP Instance UID (from the scanned file)



81
82
83
# File 'lib/metamri/raw_image_file.rb', line 81

def dicom_image_uid
  @dicom_image_uid
end

#dicom_series_uidObject (readonly)

DICOM Series UID



83
84
85
# File 'lib/metamri/raw_image_file.rb', line 83

def dicom_series_uid
  @dicom_series_uid
end

#dicom_study_uidObject (readonly)

DICOM Study UID



85
86
87
# File 'lib/metamri/raw_image_file.rb', line 85

def dicom_study_uid
  @dicom_study_uid
end

#dicom_taghashObject (readonly)

Hash of all DICOM Tags including their Names and Values (See #dicom_taghash for more information on the structure)



79
80
81
# File 'lib/metamri/raw_image_file.rb', line 79

def dicom_taghash
  @dicom_taghash
end

#exam_numberObject (readonly)

An identifier unique to a Study Session - AKA Exam Number



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

def exam_number
  @exam_number
end

#file_typeObject (readonly)

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



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

def file_type
  @file_type
end

#filenameObject (readonly)

The file name that the instance represents.



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

def filename
  @filename
end

#genderObject (readonly)

M or F.



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

def gender
  @gender
end

#hdr_readerObject (readonly)

Which header reading utility reads this file, currently ‘rdgehdr’(old p-files&wimr) or ‘dicom_hdr’ or ‘printraw’(new p-files->waisman).



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

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.



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

def num_slices
  @num_slices
end

#operator_nameObject (readonly)

Scan Tech Initials



87
88
89
# File 'lib/metamri/raw_image_file.rb', line 87

def operator_name
  @operator_name
end

#patient_nameObject (readonly)

Patient “Name”, usually StudyID or ENUM



89
90
91
# File 'lib/metamri/raw_image_file.rb', line 89

def patient_name
  @patient_name
end

#protocol_nameObject (readonly)

A short string describing the study protocol. These come from the scanner.



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

def protocol_name
  @protocol_name
end

#reconstruction_diameterObject (readonly)

AKA Field of View, in millimeters.



65
66
67
# File 'lib/metamri/raw_image_file.rb', line 65

def reconstruction_diameter
  @reconstruction_diameter
end

#rep_timeObject (readonly)

Time for each bold repetition, relevent for functional scans.



71
72
73
# File 'lib/metamri/raw_image_file.rb', line 71

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.



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

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.



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

def series_description
  @series_description
end

#slice_spacingObject (readonly)

Gap between slices in millimeters.



63
64
65
# File 'lib/metamri/raw_image_file.rb', line 63

def slice_spacing
  @slice_spacing
end

#slice_thicknessObject (readonly)

Given in millimeters.



61
62
63
# File 'lib/metamri/raw_image_file.rb', line 61

def slice_thickness
  @slice_thickness
end

#sourceObject (readonly)

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



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

def source
  @source
end

#study_descriptionObject (readonly)

A short string describing the study sequence. These come from the scanner.



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

def study_description
  @study_description
end

#timestampObject (readonly)

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



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

def timestamp
  @timestamp
end

#warningsObject (readonly)

Import Warnings - Fields that could not be read.



75
76
77
# File 'lib/metamri/raw_image_file.rb', line 75

def warnings
  @warnings
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.



212
213
214
# File 'lib/metamri/raw_image_file.rb', line 212

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).



248
249
250
251
252
253
254
255
# File 'lib/metamri/raw_image_file.rb', line 248

def db_fetch!( db_file )
  ####db = SQLite3::Database.new( db_file )
  ####db_row = db.execute( db_fetch )
  ####db.close
  ####return db_row
  puts "SQLite" 
  return nil
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.



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/metamri/raw_image_file.rb', line 198

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})"  
   puts "Old no raw_image_files table"
end

#db_insert!(db_file) ⇒ Object

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



225
226
227
228
229
230
231
232
233
234
235
# File 'lib/metamri/raw_image_file.rb', line 225

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
  puts "SQLite3"
end

#db_removeObject

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



218
219
220
# File 'lib/metamri/raw_image_file.rb', line 218

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.



238
239
240
241
242
243
# File 'lib/metamri/raw_image_file.rb', line 238

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

#dicom?Boolean

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

Returns:

  • (Boolean)


157
158
159
# File 'lib/metamri/raw_image_file.rb', line 157

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

#geifile?Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/metamri/raw_image_file.rb', line 161

def geifile?
  return @file_type == "geifile"
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)


144
145
146
# File 'lib/metamri/raw_image_file.rb', line 144

def image?
  return ( VALID_HEADERS.include? @hdr_reader )
end

#image_uidObject

The UID unique to the raw image file scanned



264
265
266
# File 'lib/metamri/raw_image_file.rb', line 264

def image_uid
  @dicom_image_uid || @image_uid
end

#pfile?Boolean

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

Returns:

  • (Boolean)


151
152
153
# File 'lib/metamri/raw_image_file.rb', line 151

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

#series_uidObject

The series ID (dicom_series_uid [dicom] or series_uid [pfile/ifile]) This is unique for DICOM datasets, but not for PFiles



259
260
261
# File 'lib/metamri/raw_image_file.rb', line 259

def series_uid
  @dicom_series_uid || @series_uid
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.



181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/metamri/raw_image_file.rb', line 181

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.



169
170
171
172
173
174
175
# File 'lib/metamri/raw_image_file.rb', line 169

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