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


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
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/metamri/raw_image_file.rb', line 107

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
  if @filename =~ /^ScanArchive*\.h5.json/
     @hdr_reader = nil #PRINTRAW_H5_JSON
  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.



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

def acquisition_matrix_x
  @acquisition_matrix_x
end

#acquisition_matrix_yObject (readonly)

Voxels in y axis.



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

def acquisition_matrix_y
  @acquisition_matrix_y
end

#bold_repsObject (readonly)

Number of bold reps in the complete functional task run.



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

def bold_reps
  @bold_reps
end

#dicom_headerObject (readonly)

Serialized RubyDicomHeader Object (for DICOMs only)



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

def dicom_header
  @dicom_header
end

#dicom_image_uidObject (readonly)

DICOM SOP Instance UID (from the scanned file)



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

def dicom_image_uid
  @dicom_image_uid
end

#dicom_series_uidObject (readonly)

DICOM Series UID



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

def dicom_series_uid
  @dicom_series_uid
end

#dicom_study_uidObject (readonly)

DICOM Study UID



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

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)



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

def dicom_taghash
  @dicom_taghash
end

#exam_numberObject (readonly)

An identifier unique to a Study Session - AKA Exam Number



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

def exam_number
  @exam_number
end

#file_typeObject (readonly)

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



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

def file_type
  @file_type
end

#filenameObject (readonly)

The file name that the instance represents.



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

def filename
  @filename
end

#genderObject (readonly)

M or F.



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

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



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

def hdr_reader
  @hdr_reader
end

#mri_coil_nameObject (readonly)

head coil



93
94
95
# File 'lib/metamri/raw_image_file.rb', line 93

def mri_coil_name
  @mri_coil_name
end

#mri_manufacturer_model_nameObject (readonly)

mri model name



97
98
99
# File 'lib/metamri/raw_image_file.rb', line 97

def mri_manufacturer_model_name
  @mri_manufacturer_model_name
end

#mri_station_nameObject (readonly)

staion name



95
96
97
# File 'lib/metamri/raw_image_file.rb', line 95

def mri_station_name
  @mri_station_name
end

#num_slicesObject (readonly)

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



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

def num_slices
  @num_slices
end

#operator_nameObject (readonly)

Scan Tech Initials



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

def operator_name
  @operator_name
end

#patient_nameObject (readonly)

Patient “Name”, usually StudyID or ENUM



91
92
93
# File 'lib/metamri/raw_image_file.rb', line 91

def patient_name
  @patient_name
end

#protocol_nameObject (readonly)

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



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

def protocol_name
  @protocol_name
end

#reconstruction_diameterObject (readonly)

AKA Field of View, in millimeters.



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

def reconstruction_diameter
  @reconstruction_diameter
end

#rep_timeObject (readonly)

Time for each bold repetition, relevent for functional scans.



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

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.



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

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.



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

def series_description
  @series_description
end

#slice_spacingObject (readonly)

Gap between slices in millimeters.



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

def slice_spacing
  @slice_spacing
end

#slice_thicknessObject (readonly)

Given in millimeters.



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

def slice_thickness
  @slice_thickness
end

#sourceObject (readonly)

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



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

def source
  @source
end

#study_descriptionObject (readonly)

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



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

def study_description
  @study_description
end

#timestampObject (readonly)

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



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

def timestamp
  @timestamp
end

#warningsObject (readonly)

Import Warnings - Fields that could not be read.



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

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.



226
227
228
# File 'lib/metamri/raw_image_file.rb', line 226

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



262
263
264
265
266
267
268
269
# File 'lib/metamri/raw_image_file.rb', line 262

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.



212
213
214
215
216
217
218
219
220
221
222
# File 'lib/metamri/raw_image_file.rb', line 212

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.



239
240
241
242
243
244
245
246
247
248
249
# File 'lib/metamri/raw_image_file.rb', line 239

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.



232
233
234
# File 'lib/metamri/raw_image_file.rb', line 232

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.



252
253
254
255
256
257
# File 'lib/metamri/raw_image_file.rb', line 252

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)


171
172
173
# File 'lib/metamri/raw_image_file.rb', line 171

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

#geifile?Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/metamri/raw_image_file.rb', line 175

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)


155
156
157
# File 'lib/metamri/raw_image_file.rb', line 155

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

#image_uidObject

The UID unique to the raw image file scanned



278
279
280
# File 'lib/metamri/raw_image_file.rb', line 278

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)


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

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

#scan_archive_h5_json?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/metamri/raw_image_file.rb', line 166

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



273
274
275
# File 'lib/metamri/raw_image_file.rb', line 273

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.



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

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.



183
184
185
186
187
188
189
# File 'lib/metamri/raw_image_file.rb', line 183

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