class VAExtractor
Public Class Methods
new()
click to toggle source
# File lib/vaextractor.rb, line 27 def initialize @usedsnellen = {} @@snellenlevels.each do |k| @usedsnellen[k] = -Math.log(20.0 / k) / Math.log(10.0) end end
Public Instance Methods
aligntokens(s)
click to toggle source
# File lib/vaextractor.rb, line 34 def aligntokens(s) arr = Textoken(s).tokens ret = [] lasti = 0 arr.each do |w| subs = s[lasti, s.size] i = subs.index(w) ret.push [w, lasti + i] lasti += i end return ret end
extract(rawtext)
click to toggle source
# File lib/vaextractor.rb, line 143 def extract(rawtext) lines = rawtext.split("\n") debug = false rfound = false lfound = false found = false vas = {"OD" => [], "OS" => []} alreadychecked = {} debugtxt = "" for i in (0...lines.count) next if lines[i].strip=~ /^IOP/ or lines[i].strip =~ /^Ta\s/ or lines[i].strip =~ /^Tp/i next if alreadychecked.has_key?(i) arr = lines[i].scan(@@varegex) lines[i].enum_for(:scan, @@varegex).each do |val| #puts "=============================================" debugtxt += "NEW VA DETECTED\n" debugtxt += "#{lines[i-1]}\n" debugtxt += "#{lines[i]}\n" debugtxt += "#{lines[i+1]}\n" debugtxt += "#{val}\n" val.shift next if val[3] != nil and val[3].to_i >= 5 pos = Regexp.last_match.begin(0) tokens = aligntokens(lines[i]) lat,debughash = findlaterality(pos, tokens, lines[i]) debugtxt += "#{pos}\n" debugtxt += "#{tokens}\n" debugtxt += "#{debughash}\n" #p lat if lat == "OU" vas["OD"].push [val, i, 5] vas["OS"].push [val, i, 5] elsif lat != nil vas[lat].push [val, i, 5] elsif lat == nil and vas["OD"].count == 0 and vas["OS"].count == 0 lat = searchpriorlines(lines[i-3..i-1].reverse) if lat == nil and vas["OD"].count == 0 and vas["OS"].count == 0 # most likely the VAs are either two in one line OD/OS or on two consecutive lines found = false arr2 = lines[i+1].scan(@@varegex) if arr2.count > 0 and arr.count > 0 arr.each do |row| row.shift next if row[0] != nil and row[3].to_i >= 5 vas["OD"].push [row, i, 0] end arr2.each do |row| row.shift next if row[0] != nil and row[3].to_i >= 5 vas["OS"].push [row, i+1, 0] end alreadychecked[i+1] = 1 found = true elsif arr.count == 2 arr[0].shift arr[1].shift next if arr[0] != nil and arr[0][3].to_i >= 5 next if arr[1] != nil and arr[1][3].to_i >= 5 vas["OD"].push [arr[0], i, 0] vas["OS"].push [arr[1], i, 0] found = true end if not found # worst case scenario, count up all the occurences of r/l and then take highest occuring freq lat = runentirefreq(rawtext) if lat == nil #puts "ERROR: Laterality not found for #{val}" raise ErrorLateralityNotFound else vas[lat].push [val, i, 0] end end else vas[lat].push [val, i, 3] end #exit end end end if vas["OD"].count == 0 and vas["OS"].count == 0 #puts "ERROR: No valid visual acuities found" return {:RE => nil, :LE => nil, :RElogmar => nil, :LElogmar => nil} else bcva = {"OD" => nil, "OS" => nil} puts "=================NEW PT" if debug puts rawtext if debug puts "===DEBUG" if debug puts debugtxt if debug puts "===OD" if debug vas["OD"].each do |varr,line,priority| puts "new va" if debug p varr if debug p lines[line] if debug p priority if debug lva = logmar(varr) p lva if debug if bcva["OD"] == nil or (bcva["OD"][0] <= priority and lva[0] < bcva["OD"][1]) bcva["OD"] = [priority, lva[0].round(4), lva[1]] end end puts "===OS" if debug vas["OS"].each do |varr,line,priority| puts "new va" if debug p varr if debug p lines[line] if debug p priority if debug lva = logmar(varr) p lva if debug if bcva["OS"] == nil or (bcva["OS"][0] <= priority and lva[0] < bcva["OS"][1]) bcva["OS"] = [priority, lva[0].round(4), lva[1]] end end bcva["OD"] = [nil, nil, [nil,nil,nil,nil]] if bcva["OD"] == nil bcva["OS"] = [nil, nil, [nil,nil,nil,nil]] if bcva["OS"] == nil return {:RE => bcva["OD"][2], :LE => bcva["OS"][2], :RElogmar => bcva["OD"][1], :LElogmar => bcva["OS"][1]} end end
findlaterality(pos, tokens, linestr)
click to toggle source
# File lib/vaextractor.rb, line 109 def findlaterality(pos, tokens, linestr) walls = {"." => 10, "!" => 10, "?" => 10, "," => 5, "and" => 5} answers = {} debug = "" revtoken = {} tokens.each do |w, i| revtoken[i] = w end tokens.each do |w, i| w = w.upcase if @@validtokens.has_key?(w) score = 0 l = i r = pos l = pos if i > pos r = i if i > pos (l...r).each do |j| next if not revtoken.has_key?(j) score += walls[revtoken[j]] if walls.has_key?(revtoken[j]) end if not answers.has_key?(score) answers[score] = [] end answers[score].push [@@validtokens[w], (i-pos).abs] end end return nil if answers.keys.count == 0 bestscore = answers.sort_by {|k, v| k}.first.last sorted = bestscore.sort_by {|r| r[1]} return sorted.first[0], answers end
logmar(va)
click to toggle source
# File lib/vaextractor.rb, line 62 def logmar(va) if va[0] == "20" manual = @usedsnellen[va[1].to_i] if va[2] == "+" va[3] = "1" if va[3] == nil denom = @@snellenlevels.index(va[1].to_i) denom -= 1 denom = @usedsnellen[@@snellenlevels[denom]] manual = 1.0 * va[3].to_i * (denom - manual) / 5.0 + manual elsif va[2] == "-" va[3] = "1" if va[3] == nil denom = @@snellenlevels.index(va[1].to_i) denom += 1 denom = @usedsnellen[@@snellenlevels[denom]] manual = 1.0 * va[3].to_i * (denom - manual) / 5.0 + manual end return manual, va[0...4] elsif va[0] == "3E" or va[0] == "3" or va[0] == "E" denom = va[1].to_i return -Math.log(3.0 / denom) / Math.log(10.0), va[0...4] elsif va[4] == "CF" return 2.0, [va[4],va[8],va[9],nil] elsif va[4] == "HM" return 2.4, [va[4],va[8],va[9],nil] elsif va[4] == "LP" return 2.7, [va[4],va[8],va[9],nil] elsif va[4] == "NLP" return 3.0, [va[4],va[8],va[9],nil] end return nil, nil end
runentirefreq(rawtext)
click to toggle source
# File lib/vaextractor.rb, line 47 def runentirefreq(rawtext) tokens = aligntokens(rawtext) scores = Hash.new(0) tokens.each do |w, i| w = w.upcase if @@validtokens.has_key?(w) and @@validtokens[w] != "OU" scores[@@validtokens[w]] += 1 end end return nil if scores.keys.count == 0 #p scores return scores.sort_by {|k,v| v}.last.first end
searchpriorlines(lines)
click to toggle source
# File lib/vaextractor.rb, line 94 def searchpriorlines(lines) lines.each do |l| return nil if l.strip == "" arr = Textoken(l).tokens arr.each do |w| if @@validtokens.has_key?(w.upcase) next if @@validtokens[w.upcase] == "OU" return @@validtokens[w.upcase] end end end return nil end