Class: VisitRawDataDirectory
- Inherits:
-
Object
- Object
- VisitRawDataDirectory
- Defined in:
- lib/metamri/visit_raw_data_directory.rb
Overview
Encapsulates a directory of data acquired during one participant visit. These are the raw data directories that are transfered directly from the scanners and archived in the raw data section of the vtrak filesystem. After initializing, the visit can be scanned to extract metadata for all of the images acquired during the visit. The scanning is done in a fairly naive manner: the visit directory is recursively walked and in each subdirectory any and all pfiles will be imported in addition to one single dicom if any exist. Thus, only a single dicom file among many in a scan session is used to retrieve information. checking the individual files for data integrity must be handled elsewhere if at all.
Constant Summary collapse
- PREPROCESS_REPOSITORY_DIRECTORY =
'/Data/vtrak1/preprocessed/visits'
- DATAPANDA_SERVER =
'https://adrcdev2.dom.wisc.edu'
Instance Attribute Summary collapse
-
#database_id ⇒ Object
The id of the visit to be used when doing reverse-lookup in data panda.
-
#datasets ⇒ Object
An array of :RawImageDataset objects acquired during this visit.
-
#db ⇒ Object
Returns the value of attribute db.
-
#dicom_study_uid ⇒ Object
readonly
DICOM Study UID (Visit/Study Unique Identifier).
-
#exam_number ⇒ Object
scanner-defined study id / exam number.
-
#rmr_number ⇒ Object
RMR number for this visit.
-
#scan_procedure_name ⇒ Object
readonly
scan_procedure name.
-
#scanid ⇒ Object
Scan ID is the short name for the scan (tbiva018, tbiva018b).
-
#scanner_source ⇒ Object
scanner source.
-
#timestamp ⇒ Object
Timestamp for this visit, obtained from the first :RawImageDataset.
-
#visit_directory ⇒ Object
readonly
The absolute path of the visit directory, as a string.
Instance Method Summary collapse
-
#attributes_for_active_record ⇒ Object
use this to initialize Visit objects in the rails app.
-
#db_insert!(db_file) ⇒ Object
Inserts each dataset in this visit into the specified database.
- #default_preprocess_directory ⇒ Object
-
#initialize(directory, scan_procedure_name = nil) ⇒ VisitRawDataDirectory
constructor
A new Visit instance needs to know the path to its raw data and scan_procedure name.
-
#scan(options = {}) ⇒ Object
Recursively walks the filesystem inside the visit directory.
-
#to_nifti!(output_directory = Dir.tmpdir) ⇒ Object
Walks through the dicom datasets in this Scan Visit directory and performs naive file conversion to nifti format, which is useful for basic quality checking.
- #to_s ⇒ Object
Constructor Details
#initialize(directory, scan_procedure_name = nil) ⇒ VisitRawDataDirectory
A new Visit instance needs to know the path to its raw data and scan_procedure name. The scan_procedure name must match a name in the database, if not a new scan_procedure entry will be inserted.
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 70 def initialize(directory, scan_procedure_name=nil) raise(IOError, "Visit directory not found: #{directory}") unless File.directory? File.(directory) @visit_directory = File.(directory) @working_directory = Dir.tmpdir @datasets = Array.new @timestamp = nil @rmr_number = nil @scan_procedure_name = scan_procedure_name.nil? ? get_scan_procedure_based_on_raw_directory : scan_procedure_name @db = nil @exam_number = nil initialize_log end |
Instance Attribute Details
#database_id ⇒ Object
The id of the visit to be used when doing reverse-lookup in data panda.
59 60 61 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 59 def database_id @database_id end |
#datasets ⇒ Object
An array of :RawImageDataset objects acquired during this visit.
43 44 45 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 43 def datasets @datasets end |
#db ⇒ Object
Returns the value of attribute db.
55 56 57 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 55 def db @db end |
#dicom_study_uid ⇒ Object (readonly)
DICOM Study UID (Visit/Study Unique Identifier)
61 62 63 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 61 def dicom_study_uid @dicom_study_uid end |
#exam_number ⇒ Object
scanner-defined study id / exam number
53 54 55 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 53 def exam_number @exam_number end |
#rmr_number ⇒ Object
RMR number for this visit.
47 48 49 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 47 def rmr_number @rmr_number end |
#scan_procedure_name ⇒ Object (readonly)
scan_procedure name
49 50 51 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 49 def scan_procedure_name @scan_procedure_name end |
#scanid ⇒ Object
Scan ID is the short name for the scan (tbiva018, tbiva018b)
57 58 59 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 57 def scanid @scanid end |
#scanner_source ⇒ Object
scanner source
51 52 53 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 51 def scanner_source @scanner_source end |
#timestamp ⇒ Object
Timestamp for this visit, obtained from the first :RawImageDataset
45 46 47 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 45 def @timestamp end |
#visit_directory ⇒ Object (readonly)
The absolute path of the visit directory, as a string.
41 42 43 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 41 def visit_directory @visit_directory end |
Instance Method Details
#attributes_for_active_record ⇒ Object
use this to initialize Visit objects in the rails app
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 132 def attributes_for_active_record { :date => @timestamp.to_s, :rmr => @rmr_number, :path => @visit_directory, :scanner_source => @scanner_source ||= get_scanner_source, :scan_number => @exam_number, :dicom_study_uid => @study_uid } end |
#db_insert!(db_file) ⇒ Object
Inserts each dataset in this visit into the specified database. The specifics of the database insert are handled by the #RawImageDataset class.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 145 def db_insert!(db_file) @db = SQLite3::Database.new(db_file) @db.results_as_hash = true @db.type_translation = true begin # checks scan_procedure in db, inserts if neccessary, returns id scan_procedure_id = fetch_or_insert_scan_procedure # insert or update visit as needed if visit_is_new? # this is a new visit visit_id = insert_new_visit(scan_procedure_id) else # visit already exists in DB visit_id = get_existing_visit_id update_existing_visit(visit_id, scan_procedure_id) end # insert each dataset from the visit, also insert an entry in series descriptions table if necessary. @datasets.each do |dataset| update_series_descriptions_table(dataset.series_description) if dataset_is_new?(dataset) insert_new_dataset(dataset, visit_id) else # dataset is already in DB dataset_id = get_existing_dataset_id(dataset) update_existing_dataset(dataset, dataset_id) end end rescue Exception => e puts e. puts e.backtrace ensure @db.close @db = nil end end |
#default_preprocess_directory ⇒ Object
181 182 183 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 181 def default_preprocess_directory return File.join(PREPROCESS_REPOSITORY_DIRECTORY, scan_procedure_name, scanid) end |
#scan(options = {}) ⇒ Object
Recursively walks the filesystem inside the visit directory. At each subdirectory, any and all pfiles are scanned and imported in addition to one and only one dicom file. After scanning exception if no valid rmr is found in the datasets, be prepared to catch it.
Options
-
:ignore_patterns
– Array of Regex’es. An array of Regular Expressions that will be used to skip heavy directories.
92 93 94 95 96 97 98 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 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 92 def scan( = {}) flash "Scanning visit raw data directory #{@visit_directory}" if $LOG.level <= Logger::INFO = {:ignore_patterns => []} = .merge() unless [:ignore_patterns].empty? puts "Ignoring directories matching: #{[:ignore_patterns].join(", ")}" if $LOG.level <= Logger::INFO end d = Pathname.new(@visit_directory) d.each_subdirectory do |dd| flash "ppppppppp #{dd}" if $LOG.level <= Logger::INFO begin matches = [:ignore_patterns].collect {|pat| dd.to_s =~ pat ? dd : nil }.compact next unless matches.empty? # if dd is P*.7.bz2 or P*.7 , check for P*.7.summary dd.each_pfile_non_bz2 { |pf| @datasets << import_dataset(pf, dd); @datasets.last.print_scan_status if $LOG.level == Logger::INFO } dd.each_pfile { |pf| # check for p*.7.summary @datasets << import_dataset(pf, dd); @datasets.last.print_scan_status if $LOG.level == Logger::INFO } dd.first_dicom { |fd| @datasets << import_dataset(fd, dd); @datasets.last.print_scan_status if $LOG.level == Logger::INFO } if (dd.to_s).include?("scan_archives") and (dd.to_s).include?("raw_data") dd.each_scanner_archive_summary { |sa| @datasets << import_dataset(sa, dd); @datasets.last.print_scan_status if $LOG.level == Logger::INFO } end rescue StandardError => e raise(e, "There was an error scaning dataset #{dd}: #{e}") end end unless @datasets.size == 0 @timestamp = @rmr_number = get_rmr_number @scanner_source = get_scanner_source @exam_number = get_exam_number @study_uid = get_study_uid unless dicom_datasets.empty? flash "Completed scanning #{@visit_directory}" if $LOG.level <= Logger::DEBUG else raise(IndexError, "No datasets could be scanned for directory #{@visit_directory}") end end |
#to_nifti!(output_directory = Dir.tmpdir) ⇒ Object
Walks through the dicom datasets in this Scan Visit directory and performs naive file conversion to nifti format, which is useful for basic quality checking. Accepts an output directory as an optional argument, defaults to the system temp directory. Returns an array of the created nifti files.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 190 def to_nifti!(output_directory = Dir.tmpdir) flash "Converting raw data directory #{@visit_directory} to Niftis in #{output_directory}" nifti_output_files = Array.new scan if @datasets.empty? @datasets.each do |dataset| nifti_output_path = output_directory #v_basename =File.basename(dataset.directory).gsub(/-/,"").gsub(/_/,"").gsub(/\:/,"").gsub(/\//,"") #v_series_description = "."+dataset.series_description.gsub(/ /,"").gsub(/-/,"").gsub(/_/,"").gsub(/\:/,"").gsub(/\//,"") # 20171120 addition v_basename =File.basename(dataset.directory) v_series_description = "."+dataset.series_description v_series_description_full_replace = v_series_description # need to get the scan series numbers - take the v_basename/folder name -- replace all the series description stuff # end up with scan series number - add to the end of the series_description to get the nii file nam if !v_basename.nil? v_basename = v_basename.gsub(/ /,"").gsub(/\-/,"").gsub(/\_/,"").gsub(/\(/,"").gsub(/\)/,"").gsub(/\=/,"").gsub(/\+/,"").gsub(/\'/,"").gsub(/\^/,"").gsub(/\,/,"").gsub(/\:/,"").gsub(/\*/,"star") end if !v_series_description_full_replace.nil? v_series_description_full_replace = v_series_description_full_replace.gsub(/ /,"").gsub(/\-/,"").gsub(/\_/,"").gsub(/\(/,"").gsub(/\)/,"").gsub(/\=/,"").gsub(/\+/,"").gsub(/\'/,"").gsub(/\^/,"").gsub(/\,/,"").gsub(/\:/,"").gsub(/\*/,"star") end #puts "ccccc end v_basename="+v_basename #puts "dddd end v_series_description_full_replace="+v_series_description_full_replace if v_basename.include? v_series_description # want the scan series number - e.g. 00001 at the end v_tmp_filename = v_basename.gsub(v_series_description,"") nifti_filename = "#{scanid}_#{dataset.series_description.escape_filename}_#{v_tmp_filename}.nii" else nifti_filename = "#{scanid}_#{dataset.series_description.escape_filename}_#{File.basename(dataset.directory).escape_filename}.nii" end #nifti_filename = "#{scanid}_#{dataset.series_description.escape_filename}_#{File.basename(dataset.directory).escape_filename}.nii" Pathname.new(dataset.directory).all_dicoms do |dicom_files| nifti_input_path = File.dirname(dicom_files.first) nifti_conversion_command, nifti_output_file = dataset.to_nifti!(nifti_output_path, nifti_filename, :input_directory => nifti_input_path, :append_modality_directory => true) nifti_output_files << nifti_output_file end end return nifti_output_files end |
#to_s ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/metamri/visit_raw_data_directory.rb', line 240 def to_s puts; @visit_directory.length.times { print "-" }; puts puts "#{@visit_directory}" puts "#{@rmr_number} - #{@timestamp.strftime('%F')} - #{@scanner_source} - #{@exam_number unless @exam_number.nil?}" puts puts RawImageDataset.to_table(@datasets) return rescue NameError => e puts e if @datasets.first.class.to_s == "RawImageDatasetResource" @datasets = @datasets.map { |ds| ds. } end # puts @datasets.first.class.to_s # puts @datasets # Header Line printf "\t%-15s %-30s [%s]\n", "Directory", "Series Description", "Files" # Dataset Lines @datasets.sort_by{|ds| [ds., File.basename(ds.directory)] }.each do |dataset| printf "\t%-15s %-30s [%s]\n", File.basename(dataset.directory), dataset.series_description, dataset.file_count end # Reminder Line puts "(This would be much prettier if you hirb was installed (just type: gem install hirb)." return end |