class BioanalyzerRun < ActiveRecord::Base has_many :quality_traces, :dependent => :destroy def BioanalyzerRun.import_new # not sure why this is necessary, but without it # a NameError occurs when trying to do # QualityTrace.new below require 'quality_trace' #bioanalyzer_pickup_location = "/users/bmarzolf/tmp/bioa_test" bioanalyzer_pickup_location = SiteConfig.bioanalyzer_pickup # get a list of the XML and JPG files xml_file_pattern = File.join(bioanalyzer_pickup_location,"/","**", "*.xml") xml_files = Dir.glob(xml_file_pattern) jpg_file_pattern = File.join(bioanalyzer_pickup_location,"/","**", "*.jpg") jpg_files = Dir.glob(jpg_file_pattern) # find all the bioanalyzer runs that are already in the database existing_runs = BioanalyzerRun.find(:all) existing_run_names = Array.new for run in existing_runs existing_run_names << run.name end for xml_file in xml_files # name of run is filename minus extension run_name = xml_file.scan(/.*\/(.*?)\.xml/i).to_s # only process xml files that haven't been loaded yet if( !existing_run_names.include?(run_name) ) # get chip name file_root = xml_file.scan(/(.*?)\.xml/i).to_s # parse XML doc = REXML::Document.new( File.new(xml_file) ) # find the chip-wide lab group chip_lab_name = doc.elements["Chipset/Chips/Chip/Files/File/FileInformation/Comment"].text if( chip_lab_name != nil ) # get rid of trailing whitespace chip_lab_name = chip_lab_name.scan(/(.*)\n*/)[0] chip_lab_group = LabGroup.find(:first, :conditions => [ "name = ?", chip_lab_name]) end # create an array to hold traces traces = Array.new quality_rating = 0 concentration = 0 ribosomal_ratio = 0 # grab each sample-specific node in the XML doc.elements.each("Chipset/Chips/Chip/Files/File/Samples/Sample") do |node| # only use lanes that have data if( node.elements["HasData"].text == "true" ) number = node.elements["WellNumber"].text # figure out sample name and type full_name = node.elements["Name"].text if( full_name.downcase.match(/(.*)_(total|crna|frag|fragmented)/) != nil ) elements = full_name.split(/_/) type = elements.pop name = elements.join("_") elsif( full_name.downcase.match(/(.*)\ (total|crna|frag|fragmented)/) != nil ) elements = full_name.split(/ /) type = elements.pop name = elements.join(" ") else name = full_name end concentration = node.elements["DAResultStructures/DARConcentration/Channel/TotalConcentration"].text # look for sample-specific lab group lab_name = node.elements["Comment"].text lab_group = nil if(lab_name != nil) lab_group = LabGroup.find(:first, :conditions => [ "name LIKE ?", lab_name]) end # if there wasn't a spcific lab group specified for this sample, # try to use the chip-wide lab group if(lab_group == nil) lab_group = chip_lab_group end # need to treat ladder differently if( name == "Ladder") # associate a jpeg current_jpg_file = file_root + "_EGRAM_Ladder.jpg" # set type as Ladder type = "ladder" else # associate a jpeg current_jpg_file = file_root + "_EGRAM_Sample" + number + ".jpg" quality_rating = node.elements["DAResultStructures/DARRIN/Channel/RIN"].text ribosomal_ratio = node.elements["DAResultStructures/DARFragment/Channel/rRNARatio"].text end # ensure that sample is tagged with a type, and that image exists if( type != nil && lab_group != nil && jpg_files.include?(current_jpg_file) ) # create new image name, and drop spaces to make the URL easier new_image_name = "#{run_name}-#{name}-#{type}.jpg".tr(" ","") image_path = "/quality_traces/#{new_image_name}" FileUtils.cp( current_jpg_file, "#{RAILS_ROOT}/public#{image_path}") # find any existing trace with this name existing_traces = QualityTrace.find(:all, :conditions => ["name = ?", name]) # if there are traces with the same root name, look for repeats if( existing_traces.size > 0 ) repeat_traces = QualityTrace.find(:all, :conditions => ["name LIKE ?", "%#{name}%_r%"]) highest_repeat = 0 # find highest repeat number and store it for repeat in repeat_traces repeat_number = repeat.name.scan( /.*_r(.)/ )[0][0].to_i if( repeat_number != nil && repeat_number > highest_repeat ) highest_repeat = repeat_number end end name = name + "_r" + (highest_repeat + 1).to_s end trace = QualityTrace.new(:image_path => image_path, :quality_rating => quality_rating, :name => name, :number => number, :sample_type => type, :concentration => concentration, :ribosomal_ratio => ribosomal_ratio, :lab_group_id => lab_group.id ) traces << trace end end end # only save bioanalyzer_run if there are > 1 samples (more than just ladder) if( traces.size > 1 ) # grab the date from the XML time_date = doc.elements["Chipset/Chips/Chip/ChipInformation/CreationDate"].text date = time_date.scan(/(\d{4}\-\d{2}\-\d{2}).*/).to_s run = BioanalyzerRun.new(:name => run_name, :date => date ) # save the traces if the run itself saves if( run.save ) for trace in traces trace.bioanalyzer_run_id = run.id trace.save end end end end end end def destroy_warning quality_traces = QualityTrace.find(:all, :conditions => ["bioanalyzer_run_id = ?", id]) return "Destroying this Bioanalyzer Run will also destroy:\n" + quality_traces.size.to_s + " trace(s)\n" + "Are you sure you want to destroy it?" end end