class DeterminationsComparison::Comparison
Attributes
baseline_filepath[RW]
filepath_baseline_origin[RW]
filepath_undertest_origin[RW]
hashCategory[RW]
hashStd[RW]
hashTgt[RW]
html_filepath[RW]
png_filepath[RW]
undertest_filepath[RW]
Public Class Methods
new(filepath_baseline,filepath_undertest,opts={})
click to toggle source
# File lib/determinations_comparison.rb, line 20 def initialize(filepath_baseline,filepath_undertest,opts={}) @filepath_comparedeterminations = opts[:filepath_comparedeterminations] @filepath_cpplogreader = opts[:filepath_cpplogreader] hashPropertyThresholds = opts[:hashPropertyThresholds] || {:area=>0,:apex_time=>0,:apex_intensity=>0} @folderpath_with_log = opts[:folderpath_with_log] || File.dirname(filepath_undertest) @filepath_baseline_origin = filepath_baseline @filepath_undertest_origin = filepath_undertest @filepath_keymapping = File.join( LIB_FOLDER,'..','config','key_mapping.yaml') @uuid = UUIDTools::UUID.random_create $log_detercomp = Logger.new File.join(LIB_FOLDER,'..',"log.txt") @hashDiffs = Hash.new differences 'Compound', hashCompoundUnderTest, hashCompoundBaseLine, @hashDiffs differences_extrapolated @hashCategory = categorize hashPropertyThresholds end
Public Instance Methods
as_hash()
click to toggle source
# File lib/determinations_comparison.rb, line 167 def as_hash @hashDiffs end
to_html(folderpath_output)
click to toggle source
# File lib/determinations_comparison.rb, line 46 def to_html(folderpath_output) FileUtils.mkdir_p folderpath_output html_filepath = File.join folderpath_output, "#{@uuid}.html" png_filepath = File.join folderpath_output, "#{@uuid}.png" baseline_filepath = File.join folderpath_output, "#{@uuid}_baseline.json" undertest_filepath = File.join folderpath_output, "#{@uuid}_undertest.json" # these are necessary for cpplogreader @sample_index = hashCompoundBaseLine['Sample_Index'] @analyte_name = hashCompoundBaseLine['Analyte'] begin #coder = HTMLEntities.new FileUtils.copy_file @filepath_baseline_origin, baseline_filepath FileUtils.copy_file @filepath_undertest_origin, undertest_filepath # html for file links strFiles = "<p>baseline file: <a href=#{File.basename(baseline_filepath)}>#{File.basename(@filepath_baseline_origin)}</a></p>" strFiles += "<p>undertest file: <a href=#{File.basename(undertest_filepath)}>#{File.basename(@filepath_undertest_origin)}</a></p>" # html for plot strPlot = nil @plotter = Exe_CompareDeterminations.new @filepath_baseline_origin, @filepath_undertest_origin, @filepath_comparedeterminations retcodePNG,rundetailsPNG = @plotter.generate_png png_filepath if retcodePNG strPlot = "<img src='#{File.basename(png_filepath)}' alt='chromatogram' height='500' width='800' align='top'>" end # html for peak picking logs hashChromHTML = Hash.new @hashDiffs.each_pair do |k,v| chrom_type = k ht = HTML_Table_of_Peak_Picking_Log.new(@folderpath_with_log,@sample_index,@analyte_name,k) str_pp = ht.render unless str_pp.nil? peak_picked = "unknown" arrPP = v.select { |h| h['peak_picked'] } unless arrPP.empty? peak_picked = "#{arrPP.first[0]} #{arrPP.first[1]}" end strChrom = "<p><b>#{chrom_type}</b> - #{peak_picked}</p>" strChrom += str_pp end hashChromHTML[k] = strChrom end # html for property differences arr = Array.new @hashDiffs.each_pair do |k,v| chrom_type = k v.each_pair do |k,v| if k == 'peak' v.each_pair do |k,v| arr << property_diff_to_hash(chrom_type,k,v) end else unless k == 'peak_picked' arr << property_diff_to_hash(chrom_type,k,v) end end end end strProps = nil ht = HTML_Table_of_Property_Differences.new(arr) str_p = ht.render unless str_p.nil? strProps = str_p end strFull = strFiles strFull += strPlot unless strPlot.nil? hashGroups = Hash.new hashGroups['Properties'] = strProps hashChromHTML.each_pair do |k,v| hashGroups["Pick Log - #{k.to_s}"] = v end jt = Jquery_Tabs.new hashGroups strFull += jt.render File.open(html_filepath, "w") do |f| f.write(strFull) end retcode = true rescue Exception => e retcode = false $log_detercomp.error "unable to render html" end @html_filepath = html_filepath @png_filepath = png_filepath @baseline_filepath = baseline_filepath @undertest_filepath = undertest_filepath return retcode end
Private Instance Methods
categorize(hashPropertyThresholds)
click to toggle source
# File lib/determinations_comparison.rb, line 174 def categorize(hashPropertyThresholds) hashCategory = Hash.new hash = Hash.new # peak picked by baseline and not undertest? arr = Array.new @hashDiffs.each_pair do |chrom,hashChrom| hash = Hash.new if hashChrom['peak_picked'] == 'by baseline but not by undertest' hash[:desc] = "peak picked #{hashChrom['peak_picked']}" hash[:chrom] = chrom.to_s hash[:per_diff] = 100 # temporarily using per_diff for a severity level arr << hash end break unless arr.empty? if hashChrom['peak_picked'] == 'by baseline (simpsons rule) but not by undertest' hash[:desc] = "peak picked #{hashChrom['peak_picked']}" hash[:chrom] = chrom.to_s hash[:per_diff] = 50 arr << hash end end unless arr.empty? arr.sort_by! { |h| h[:per_diff] } arr.first.delete(:per_diff) return arr.first end # area, apex_time, apex_intensity within threshold? [:area,:apex_time,:apex_intensity].each do |prop| arr = Array.new @hashDiffs.each_pair do |chrom,hashChrom| hash = Hash.new per_diff = hashChrom['peak'][prop.to_s][:percent_diff] threshold = hashPropertyThresholds[prop] if per_diff > threshold hash[:desc] = "difference in #{prop.to_s}" hash[:chrom] = chrom.to_s hash[:per_diff] = per_diff arr << hash end end unless arr.empty? arr.sort_by! { |h| h[:per_diff] }.reverse return arr.first end end hash[:desc] = 'match within thresholds' return hash end
differences(item, hashUnderTest, hashBaseLine, hashDifferences)
click to toggle source
# File lib/determinations_comparison.rb, line 245 def differences(item, hashUnderTest, hashBaseLine, hashDifferences) hashUnderTest.each_pair do |k_undertest,v_undertest| #if k_undertest == 'expected_retention_time' # puts 'wait' #end v_baseline = get_baseline_and_undertest_values item, hashBaseLine, :k_undertest => k_undertest if v_baseline.nil? $log_detercomp.info "corresponding key for '#{k_undertest}' does not exist in baseline file (if different name than add to key_mapping.yaml" else if k_undertest == 'Compound' || k_undertest == 'chromatogram_list' v_undertest.each do |hashChromUnderTest| @hashChromUnderTest = hashChromUnderTest chromtype_key_undertest = filetype_undertest == 'json' ? 'classifier' : 'SampleType' chromtype_undertest = hashChromUnderTest[chromtype_key_undertest] chromtype_generic = generic_chromtype chromtype_undertest chromtype_baseline = generic_chromtype_to_filetype_specific chromtype_generic, filetype_baseline chromtype_key_baseline = filetype_baseline == 'json' ? 'classifier' : 'SampleType' @hashChromBaseLine = v_baseline.select { |h| h[chromtype_key_baseline] == chromtype_baseline }.first hashDiff_Chrom = Hash.new hashDifferences[generic_key(chromtype_generic)] = hashDiff_Chrom differences 'Chromatogram', hashChromUnderTest, @hashChromBaseLine, hashDiff_Chrom end elsif(k_undertest == 'RawTrace' || k_undertest == 'raw_trace' || k_undertest == 'SmoothTrace' || k_undertest == 'smooth_trace') $log_detercomp.info "'#{k_undertest}' - comparing traces not supported yet" elsif(k_undertest == 'Peaks' || k_undertest == 'peak') @hashPeakUnderTest = v_undertest @hashPeakBaseLine = v_baseline hashDiff_Peak = Hash.new hashDifferences['peak'] = hashDiff_Peak differences 'Peak', @hashPeakUnderTest, @hashPeakBaseLine, hashDiff_Peak elsif v_undertest.respond_to? :each $log_detercomp.info "'#{k_undertest}' - comparison not supported" else if v_undertest.to_s.numeric? #if k_undertest == 'start_intensity' # puts 'wait' #end hashDiff = percentage_difference item , k_undertest , v_baseline , v_undertest hashDifferences[generic_key(k_undertest)] = hashDiff else $log_detercomp.info "'#{k_undertest}' - comparison not supported" end end end end end
differences_extrapolated()
click to toggle source
# File lib/determinations_comparison.rb, line 322 def differences_extrapolated @hashDiffs.each_pair do |k,v| boolPeakPickedByBaseline = v['peak']['area'][:baseline] == 0 ? false:true boolPeakPickedByUnderTest = v['peak']['area'][:undertest] == 0 ? false:true boolSimpsonsRuleByBaseLine = v['peak']['nls_amp'][:baseline] == 0 if boolPeakPickedByBaseline && !(boolPeakPickedByUnderTest) if boolSimpsonsRuleByBaseLine v['peak_picked'] = 'by baseline (simpsons rule) but not by undertest' else v['peak_picked'] = 'by baseline but not by undertest' end elsif !(boolPeakPickedByBaseline) && boolPeakPickedByUnderTest v['peak_picked'] = 'by undertest but not by baseline' elsif boolPeakPickedByBaseline && boolPeakPickedByUnderTest if boolSimpsonsRuleByBaseLine v['peak_picked'] = 'by baseline (simpsons rule) and by undertest' else v['peak_picked'] = 'by baseline and by undertest' end elsif !boolPeakPickedByBaseline && !boolPeakPickedByUnderTest v['peak_picked'] = 'by neither baseline nor by undertest' end end end
file_to_hash(file)
click to toggle source
# File lib/determinations_comparison.rb, line 593 def file_to_hash(file) begin json = File.read(file) hash = JSON.parse(json) rescue Exception => e puts "error retrieving - #{File.basename(file)} - #{e.message}" end hash end
filetype_baseline()
click to toggle source
# File lib/determinations_comparison.rb, line 573 def filetype_baseline @filetype_baseline ||= File.extname(@filepath_baseline_origin)[1..-1] # [1..-1] is to remove '.' from extension name end
filetype_undertest()
click to toggle source
# File lib/determinations_comparison.rb, line 577 def filetype_undertest @filetype_undertest ||= File.extname(@filepath_undertest_origin)[1..-1] end
generic_chromtype(chromtype)
click to toggle source
# File lib/determinations_comparison.rb, line 539 def generic_chromtype(chromtype) case chromtype when 'Q' 'Qual' when 'A' 'Quant' else chromtype end end
generic_chromtype_to_filetype_specific(generic_chromtype, filetype)
click to toggle source
# File lib/determinations_comparison.rb, line 552 def generic_chromtype_to_filetype_specific(generic_chromtype, filetype) case generic_chromtype when 'Quant' filetype == 'json' ? 'Quant' : 'A' when 'Qual' filetype == 'json' ? 'Qual' : 'Q' else 'IS' end end
generic_key(key)
click to toggle source
# File lib/determinations_comparison.rb, line 511 def generic_key(key) unless key.downcase == key key = key.to_snakecase end return key end
get_baseline_and_undertest_values(item, hashParent, opts)
click to toggle source
# File lib/determinations_comparison.rb, line 360 def get_baseline_and_undertest_values(item, hashParent, opts) k_baseline = opts[:k_baseline] k_undertest = opts[:k_undertest] k_generic = opts[:k_generic] unless k_generic.nil? val = get_corresponding_key_value_from_other_file 'baseline', item, hashParent, k_generic end unless k_undertest.nil? #v_undertest = hashParent_undertest[k_undertest] val = get_corresponding_key_value_from_other_file 'baseline', item, hashParent, k_undertest end unless k_baseline.nil? #v_baseline = hashParent_baseline[k_baseline] val = get_corresponding_key_value_from_other_file 'undertest', item, hashParent, k_baseline end return val end
get_corresponding_key_value_from_other_file(file_type_to_get_key_value_for, item, unknown_hashParent, k_known)
click to toggle source
# File lib/determinations_comparison.rb, line 385 def get_corresponding_key_value_from_other_file(file_type_to_get_key_value_for, item, unknown_hashParent, k_known) # guess at name of corresponding baseline key based on convention (i.e. convert snakecase to camelcase or vice-versa) if file_type_to_get_key_value_for == 'baseline' naming_convention_of_unknown = naming_convention_baseline naming_convention_of_known = naming_convention_undertest #naming_convention = naming_convention_baseline keytype_unknown = "#{filetype_baseline}_key" keytype_known = "#{filetype_undertest}_key" else naming_convention_of_unknown = naming_convention_undertest naming_convention_of_known = naming_convention_baseline #naming_convention = naming_convention_undertest keytype_unknown = "#{filetype_undertest}_key" keytype_known = "#{filetype_baseline}_key" end #convert known key to naming convention used by unknown file k_unknown = if naming_convention_of_unknown == 'snakecase' k_known.to_snakecase else k_known.to_camelcase_lower end if unknown_hashParent.has_key? k_unknown v_unknown = unknown_hashParent[k_unknown] else # look in mapping for alternatives to convention arr = mapping[item].select { |h| h[keytype_known] == k_known } unless arr.empty? k_unknown = arr.first[keytype_unknown] v_unknown = unknown_hashParent[k_unknown] end end end
hashCompoundBaseLine()
click to toggle source
# File lib/determinations_comparison.rb, line 585 def hashCompoundBaseLine @hashCompoundBaseLine ||= file_to_hash @filepath_baseline_origin end
hashCompoundUnderTest()
click to toggle source
# File lib/determinations_comparison.rb, line 589 def hashCompoundUnderTest @hashCompoundUnderTest ||= file_to_hash @filepath_undertest_origin end
mapping()
click to toggle source
# File lib/determinations_comparison.rb, line 581 def mapping @mapping ||= YAML.load_file(@filepath_keymapping) end
naming_convention_baseline()
click to toggle source
# File lib/determinations_comparison.rb, line 565 def naming_convention_baseline @naming_convention_baseline ||= filetype_baseline == 'po' ? 'camelcase' : 'snakecase' end
naming_convention_undertest()
click to toggle source
# File lib/determinations_comparison.rb, line 569 def naming_convention_undertest @naming_convention_undertest ||= filetype_undertest == 'po' ? 'camelcase' : 'snakecase' end
normalize_precision(val1,val2)
click to toggle source
# File lib/determinations_comparison.rb, line 521 def normalize_precision(val1,val2) val1_precision = precision(val1) val2_precision = precision(val2) if val1_precision == val2_precision return val1,val2 elsif(val1_precision > val2_precision) return val1.round(val2_precision), val2 elsif(val1_precision < val2_precision) return val1, val2.round(val1_precision) end end
percentage_difference(item,key_undertest,v_baseline,v_undertest)
click to toggle source
# File lib/determinations_comparison.rb, line 428 def percentage_difference(item,key_undertest,v_baseline,v_undertest) hashDiff = Hash.new hashDiff[:baseline] = v_baseline hashDiff[:undertest] = v_undertest #normalize based on least precision betweeen baseline and undertest values v_baseline,v_undertest = normalize_precision v_baseline , v_undertest hashDiff[:baseline_rounded] = v_baseline hashDiff[:undertest_rounded] = v_undertest #check if property has a scale for proportionate comparison arr = mapping[item].select { |h| h["#{filetype_undertest}_key"]== key_undertest } unless arr.empty? hash = arr.first boolHasScale = hash.has_key?('scale') ? true:false end if boolHasScale dif,hashScale = percentage_difference_relative_to_scale v_baseline,v_undertest,hash['scale'] hashDiff.merge! hashScale else dif,calculation = percentage_difference_without_scale v_baseline,v_undertest hashDiff[:calculation] = calculation end hashDiff[:percent_diff] = dif return hashDiff end
percentage_difference_relative_to_scale(val1,val2,scale_description)
click to toggle source
# File lib/determinations_comparison.rb, line 483 def percentage_difference_relative_to_scale(val1,val2,scale_description) # use json keys case scale_description when 'relative_to_apex_intensity' min_scale = 0 # TODO - should this be baseline? max_scale = get_baseline_and_undertest_values 'Peak', @hashPeakBaseLine,:k_generic => 'apex_intensity' when 'relative_to_peak_start_and_end_time' min_scale = get_baseline_and_undertest_values 'Chromatogram', @hashChromBaseLine, :k_generic => 'start_time' max_scale = get_baseline_and_undertest_values 'Chromatogram', @hashChromBaseLine, :k_generic => 'end_time' end scale = max_scale - min_scale if scale == 0 dif,calc = percentage_difference_without_scale val1,val2 else dif = (((val1 - val2).abs / scale ) * 100).round(2) calc = "(((#{val1} - #{val2}.abs / scale ) * 100).round(2)" end dif = dif.abs # use absolute value return dif,{:scale=>scale_description,:min=>min_scale,:max=>max_scale,:calculation=>calc} end
percentage_difference_without_scale(a,b)
click to toggle source
# File lib/determinations_comparison.rb, line 462 def percentage_difference_without_scale(a,b) if (b.to_f == a.to_f) && (a.to_f == 0) chg = 0 calc = '0' elsif b.to_f == 0 diff = b.to_f - a.to_f chg = diff / a.to_f calc = "#{b} - #{a} / #{a}" else a.to_f == 0 diff = a.to_f - b.to_f chg = diff / b.to_f calc = "#{a} - #{b} / #{b}" end diff = (chg * 100.0).round(2) diff = diff.abs return diff, calc end
precision(number)
click to toggle source
# File lib/determinations_comparison.rb, line 535 def precision(number) number.to_s.split('.').last.size end
property_diff_to_hash(chromatogram_type, property_description, hashDif)
click to toggle source
# File lib/determinations_comparison.rb, line 606 def property_diff_to_hash(chromatogram_type, property_description, hashDif) hash = Hash.new begin hash[:chromatogram] = chromatogram_type hash[:property] = property_description if property_description == 'peak_picked' hash[:diff] = 0 hash[:baseline] = 0 hash[:undertest] = 0 hash[:scale] = hashDif hash[:calculation] = '' else hash[:diff] = hashDif[:percent_diff] hash[:baseline] = hashDif[:baseline_rounded] || hashDif[:baseline] hash[:undertest] = hashDif[:undertest_rounded] || hashDif[:undertest] hash[:calculation] = '' if hashDif[:scale].nil? hash[:scale] = '' else hash[:scale] = "#{hashDif[:scale]} (#{hashDif[:min]}-#{hashDif[:max]})" end if hashDif[:calculation].nil? hash[:calculation] = '' else hash[:calculation] = hashDif[:calculation] end end rescue Exception => e $log_detercomp.err "error creating html table for #{property_description}" end return hash end