Ruby Create Dictionary.html from double colon files

This takes a text file of the form below and creates an html dictionary version with a TOC :


Ambiguous Genitalia

Overview:: Four major defects can cause gender confusion in the neonate: 1) female pseudohermaphroditism or adrenogentital syndrome, 2) male pseudohermaphroditism, 3) true hermaphroditism, and 4) mixed gonadal dysgenesis. A physical examination and a chromosome analysis can make the correct diagnosis with approximately 90% accuracy. Gonadal symmetry is sought for - if there is symmetry in the gonadal findings, then the diagnosis is most likely a causative agent applied equally to both sides, such as an androgenized genetic female (=female pseudohermaphroditism) or an incompletely virilized genetic male (= male pseudohermaphroditism). Asymmetry refers to position of one gonad to the other, relative to the external inguinal ring. A buccal smear is felt by some to be useful in that Barr or Chromatin bodies (indicative of the presence of the second female X chromosome) may be found. Therefore: 1) Chromatin Positive, Symmetry = Fem pseudoherm; 2) Chromatin Positive, Asymmetry = True herm; 3) Chromatin Negative,Symmetry = Male pseudoherm; 5) Chromatin Negative, Asymmetry = Mixed gonad dysgen.

Caveats:: Genetic females recognized in the neonatal period historically were raised as female no matter how virilized. This is not currently the case. In genetic males the gender assignment was traditionally based on the phallus size - anyone with an 'inadequate' phallus is raised as a female. What constitutes an inadequate phallus ? Absolute values are impossible, but the measurements are made from the dorsum to the tip of the stretched glans. The following are 'inadequate': < 2.5 cm in the term infant; < 2.0 cm in the 34 week premie; < 1.5 cm in the 30 week preemie. Additionally, a thin (< 1 to 1.5 cm diameter) phallus is of concern. An elevated or normal MIS levels signifies a functioning testis.

Clinical:: The following work-up of the child with AG (ambiguous genitalia) may be indicated:H & P, HCG stimulation and enzyme ratios, Family pedigree, Genitogram, Maternal drug history, Cystoscopy, Buccal smear with Y fluorescence, Laparoscopy, Urinary steroids, Gonadal biopsy (longitudinal), Electrolytes,Androgen receptors (genital skin).

Female pseudohermaphroditism - Description:: (approximately 1/3 of all patients). This refers to 46, XX karyotype patients with severe masculinization secondary to exposure in utero to either endogenous or exogenous androgens.

Female pseudohermaphroditism - Etiology::The most common cause is the adrenogenital syndrome (CAH). CAH is the only cause of ambiguous genitalia that is life-threatening in the newborn period. 95% of these patients will have a 21-hydroxlyase deficiency. The gene for 21 hydroxylase has 2 alleles coded for in the Class II MHComplex, and there is therefore an A and B form of 21 OHase deficiency - the common form is the B variant. Mutations in the A genes result in milder, later onset forms of the disease. 21 hydroxylase deficiency results in aldosterone (mineralocorticoid) and cortisol (glucocorticoid) deficiencies, resulting in salt-wasting, hypotension, and adrenal crises. Other etiologies include 3 beta and 11 hydroxylase deficiencies. The 21, 3, and 11 are all forms of congenital adrenal hyperplasia (CAH). 11Beta OHase deficiency results in mild virilism (in affected females) and hypertension. In this variant, both mineralocorticoid and steroid replacement should be provided, since steroids alone may suppress the mineralocorticoid.

Female pseudohermaphroditism - Evaluation::The prenatal diagnosis of CAH can be made from DNA analysis of CVS (chorionic villous sampling) or amniotic fluid hormone levels during or after the 2nd trimester. The best way to test for CAH is to look for elevated precursors: {Deficiency,Elevated Precursor,Frequency} = [21 Hydroxylase; 17 hydroxyprogesterone; 95% cases] and [3BetaSteroid dehydrogenase; 17 hydroxypregnenolone: < 5% cases] and [11 Beta hydroxylase; 11 deoxycortisol; rare]. Clinically, prompt identification of patients with CAH is critical. Virilization is present in the female, and in the male only barely identifiable hyperpigmentation of the scrotum may be present. The history of an early or unexplained death in a sibling should alert one to the possibility. A filter-paper test for the most common defect (test is for 17 hydroxyprogesterone) is available. ECG findings of peaked T waves or arrhythmia's may be the first sign. Internal structures are normal, and only the external structures are affected (this is true because the adrenal develops after the 11th week of gestation when the internal structures are already formed). All genetically female patients have the potential to be fertile and should be raised as females. The phenotype is variable from very male appearing to milder forms. The life-threatening electrolyte abnormalities (hyperkalemia, hyponatremia) may not occur until 3 - 5 days after birth, and the adrenal crisis may not occur until 1-2 weeks of age.

Female pseudohermaphroditism - Treatment:: Can even be preventative, if CAH is identified prenatally - dexamethasone is given (1 - 1.5 mg, daily in 2 divided doses) to the mother, starting at the 6 - 7th week of gestation (before sexual differentiation). CVS is used to assess therapy - if the fetus is genetically male, Tx is stopped, if the fetus is female, Tx is continued until amniocentesis during 2nd trimester to confirm the Dx. Fetoscopy has been used to evaluate the external genitalia. Medical management of CAH consists of provision of glucocorticoid (hydrocortisone, 12.5 -15 mg/M2 q 8 hrs, provision of mineralocorticoid (Fludrocortisone 0.1mg q am), hydration, correction of Na, K+ abnormalities. All patients with female pseudohermaphroditism should be raised as females. Surgically, clitoral recession is done in the early neonatal period, and a cutback or flap vaginoplasty is usually done at 3 - 6 months of age. A pull-through vaginoplasty is usually delayed until about 2 years of age. Which of these is required depends on the level of entry of the vagina into the urogenital sinus.

Male Pseudohermaphroditism - General:: Accounts for approximately 1/3 of all patients. These patients have a 46 X,Y karyotype but deficient masculinization of the external genitalia. The effects of androgens on sexual differentiation are via receptors in the nucleus.

etc.......

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
p "Enter a title"
title  = gets.chomp
dict = {}
IO.foreach(title + ".txt") do
|x| 
if
y = /::/.match(x)
y = y.pre_match
z=/::/.match(x)
z = z.post_match
dict[y] = z
end
end
File::open(title + '.htm', 'w') do |f|
	f.puts "<HTML>\n<link href='Level3_3.css' rel='stylesheet' type='text/css'><HEAD><TITLE>" + title + "</TITLE></HEAD>"
	f.puts "<CENTER><A NAME=\"page_top\"><H1>" + title + "</H1></A>"	
  	f.puts "by Charles L. Snyder, MD<BR>\n"
	f.puts "</CENTER>\n<HR>\n"
	dict.keys.sort.each {|s| f.puts "<br>#{s}</br>"}
	f.puts "</CENTER>\n<HR>\n"
  i=0
  while i < (dict.length)
  f.puts "<A NAME=\"$anchor\"><H2>" + dict.keys.sort[i] + "</H2></A>" + dict.values[i] + "<BR>"
	f.puts "<CENTER><A HREF=\'javascript:window.history.back()\'>Back</A>&nbsp"
  f.puts "</CENTER>\n<HR>\n"
  i = i + 1
  end
end

Ruby Code Samples

Tag cloud in ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#Tag cloud in Ruby
def font_size_for_tag_cloud(total,lowest,highest, options={})
 return nil if total.nil? or highest.nil? or lowest.nil?
 #
 # options
 maxf = options.delete( :max_font_size ) || 14
 minf = options.delete( :min_font_size ) || 11
 maxc = options.delete( :max_color ) || [ 0, 0, 0 ]
 minc = options.delete( :min_color ) || [ 156, 156, 156 ]
 hide_sizes = options.delete( :hide_sizes )
 hide_colours = options.delete( :hide_colours )
 #
 # function to work out rgb values
 def rgb_color( a, b, i, x)
  return nil if i <= 1 or x <= 1
  if a > b
   a-(Math.log(i)*(a-b)/Math.log(x)).floor
  else
   (Math.log(i)*(b-a)/Math.log(x)+a).floor
  end
 end
 #
 # work out colours
 c = []
 (0..2).each { |i| c << rgb_color( minc[i], maxc[i], total, highest ) || nil }
 colors = c.compact.empty? ? minc.join(‘,’) : c.join(‘,’)
 #
 # work out the font size
 spread = highest.to_f - lowest.to_f
 spread = 1.to_f if spread <= 0
 fontspread = maxf.to_f - minf.to_f
 fontstep = spread / fontspread
 size = ( minf + ( total.to_f / fontstep ) ).to_i
 size = maxf if size > maxf
 #
 # display the results
 size_txt = "font-size:#{ size.to_s }px;" unless hide_sizes
 color_txt = "color:rgb(#{ colors });" unless hide_colours
 return [ size_txt, color_txt ].join
end

Excel in ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require ‘win32ole’
myfile = ‘C:\Documents and Settings\Charles L.Snyder\My Documents\rvu.xls#put in your path and filename
 
excel = WIN32OLE::new(‘excel.Application)
workbook = excel.Workbooks.Open(myfile)
worksheet = workbook.Worksheets(1) #get the first worksheet - change the name if needed
worksheet.Select
eor = (worksheet.range("a1").end(-4161).address).delete("$")   # >> "$B$7" - end of row (eor)
eoc = (worksheet.range("a1").end(-4121).address).delete("$")
# puts ‘last row is ‘ + eoc
eoc.slice!(0) # just want the number of the last row
eor.slice!(1-5) #just want the letter of the last column
col_titles = []
 
surgeons = ["ANDREWS,WALTER S MD","GATTI,JOHN MD", "HOLCOMB,GEORGE WHIT MD", "MURPHY,JOHN PATRICK MD", "OSTLIE,DANIEL J MD", "SHARP,RONALD MD", "SNYDER,CHARLES MD"]
surgeons.each  do |surg|
    counter =0
        worksheet.Range("a:a").each do |f|
        modf= f.address.delete("$")
         if ((f.value) == surg and worksheet.Range("#{modf}").offset(0,4).value == 54161)
 
         counter +=1
         end
        end
        puts "#{surg}: did  #{counter} operations or encounters during the interval"
end

How to find files /filetypes in Ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 
require 'find'
module Find
  def match(*paths)
    matched = []
    find(*paths) { |path| matched << path if yield path }
    return matched
  end
  module_function :match
end
#---
require 'create_tree'
create_tree './' => 
  [ { 'Music' => ['cancelled_download.MP3', 
                  ['The Snails - Red Rocket.mp3', 'Song contents #1'],
                  ['The Snails - Moonfall.mp3', 'Song contents #2'] 
                 ]
    },
    { 'tmp' => ['empty1', 'empty2', ['README', 'Hi there!']] },
    { 'rubyprog-0.1' => [['rubyprog.rb', '#!/usr/bin/env ruby'], 
                         ['README', 'This Ruby program is great!']
                        ]
    }
  ]
 
#---
# Find the empty files.
Find.match('./') { |p| File.lstat(p).size == 0 }
 
# => ["./tmp/empty2", "./tmp/empty1", "./Music/cancelled_download.MP3"]
 
# Find the MP3s.
Find.match('./') { |p| ext = p[-4...p.size]; ext && ext.downcase == '.mp3' }
# => ["./Music/The Snails - Red Rocket.mp3", 
#     "./Music/The Snails - Moonfall.mp3", 
#     "./Music/cancelled_download.MP3"]
 
 
# Find the README files.
Find.match('./') { |p| File.split(p)[1] == 'README' }
# => ["./tmp/README", "./rubyprog-0.1/README"]
#---
Find.match('./') do |p| 
  Find.prune if p == "./tmp"  
  File.split(p)[1] == "README"
end
# => ["./rubyprog-0.1/README"]
#---
must_start_with = "This Ruby program"
Find.match('./') do |p|
  if File.file? p
    open(p) { |f| f.read(must_start_with.size) == must_start_with }
  else
    false
  end
end
# => ["./rubyprog-0.1/README"]
#---
# Finds files that were probably left behind by emacs sessions.
def emacs_droppings(*paths)
  Find.match(*paths) do |p| 
    (p[-1] == ?~ and p[0] != ?~) or (p[0] == ?# and p[-1] == ?#)
  end
end
 
# Finds all files that are larger than a certain threshold. Use this to 
# find the files hogging space on your filesystem.
def bigger_than(bytes, *paths)
  Find.match(*paths) { |p| File.lstat(p).size > bytes }  
end
 
# Finds all files modified more recently than a certain number of seconds 
# ago.
def modified_recently(seconds, *paths)
  time = Time.now - seconds
  Find.match(*paths) { |p| File.lstat(p).mtime > time }  
end
 
# Finds all files that haven't been accessed since they were last modified.
def possibly_abandoned(*paths)
  Find.match(*paths) { |p| f = File.lstat(p); f.mtime == f.atime }
end
#---

Ruby Word Unscrambler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Unscrambler
    def initialize(wordsFilename = "/usr/share/dict/words")
        @wordsHash = Hash.new{ Array.new }
        File.open(wordsFilename) do |wordsFile|
            wordsFile.each_line do |word|
                word.chomp!
                @wordsHash[Unscrambler::word_to_key(word)] <<= word
            end
        end
    end
 
    def Unscrambler::word_to_key(word)
        return word unless word.size > 3
        array = word.split(//)
        array[1..-2] = array[1..-2].sort
        return array.join;
    end
    def unscramble(word)
        return @wordsHash[Unscrambler::word_to_key(word)]
    end
 
end
 
puts "Loading wordlist..." if $stdin.isatty
 
u = Unscrambler.new
 
puts "Ready." if $stdin.isatty
 
$stdin.each_line do |line|
    line.gsub!(/\w+/) do |match|
        choices = u.unscramble(match.downcase)
        case choices.size
            when 0 then match
            when 1 then choices[0]
            else "[" + choices.join(", ") + "]"
        end
    end

Ruby converter for xml quiz files to Quizmaker Program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
require ‘ostruct’
require "rexml/document"
include REXML
print "What is the name of the xml file?"
p myFile = gets.chomp
doc = File.open("#{myFile}.xml") {|io| Document.new io}
quiz=[]
doc.elements.each("QUIZ/QUESTION") do |el_q|
  question = OpenStruct.new
  quiz.push question.text = el_q.attributes["TEXT"]
  question.explain = el_q.attributes["EXPLAIN"]
  question.answer = el_q.attributes["ANSWER"]
 i=0
  el_q.elements.each("CHOICE") do |el_ch|
    (question.choices||=[]) << el_ch.text
    quiz.push(question.choices[i].to_s)
    if (i.to_s==question.answer)
     quiz.push "Correct! #{question.explain}"
    else
    quiz.push "False! #{question.explain}"
    end
    i+=1
    end
end
File::open("#{myFile}" + ‘.quiz’, ‘w’) do |f|
  f.puts quiz
 end

Create a Histogram in Ruby

1
2
3
4
5
6
7
8
counts = my_array.inject(Hash.new {0}) { |counts, key| counts[key] += 1;
counts }
counts = counts.sort {|a,b| a<=>b}
# Here is an example of the technique:
a=%w(a b c d e f f f g h j j j )
bob = a.inject(Hash.new { 0 }) { |counts, key| counts[key] += 1;
counts }
p bob

Clean out old files with Ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/usr/bin/env ruby
 
action = ‘ARCHIVE’ # ‘LIST’ or ‘DELETE’ or ‘TRASH’ or ‘ARCHIVE’
age = 45 # in days (2 weeks default)
 
# DO NOT CHANGE ANYTHING BELOW THIS LINE
# Save the file somewhere as clean.rb, and in the Terminal (Applications > Utilities), cd to the directory (e.g., cd Desktop if it’s on your Desktop), and type chmod +x clean.rb.
#If you want, you can edit the top of the file.
#There are two settings: what you want to do with the file (list, move to trash, or delete), and how long it must be since you accessed it.
#You can then run the file by typing ./clean.rb Downloads, for example. It will clean out or list the files according to your preference.
#It will only remove whole directories.
 
require ‘fileutils’
 
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
  from_time = from_time.to_time if from_time.respond_to?(:to_time)
  to_time = to_time.to_time if to_time.respond_to?(:to_time)
  distance_in_minutes = (((to_time - from_time).abs)/60).round
  distance_in_seconds = ((to_time - from_time).abs).round
  case distance_in_minutes
  when 0..1
    return (distance_in_minutes==0) ? ‘less than a minute’ : ‘1 minute’ unless include_seconds
    case distance_in_seconds
    when 0..5   then ‘less than 5 seconds’
    when 6..10  then ‘less than 10 seconds’
    when 11..20 then ‘less than 20 seconds’
    when 21..40 then ‘half a minute’
    when 41..59 then ‘less than a minute’
    else1 minute’
  end
 
  when 2..45      then "#{distance_in_minutes} minutes"
  when 46..90     then ‘about 1 hour’
  when 90..1440   then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
  when 1441..2880 then1 day’
  else                 "#{(distance_in_minutes / 1440).round} days"
  end
end
 
def last_accessed(dir_name)
  # puts ‘called’
  best = Time.at(0)
  Dir.chdir(dir_name) do
    Dir.foreach(‘.’) do |entry|
      next if entry == ‘.’ or entry == ‘..’
      # puts entry+’!’
      if File.directory? entry
        x = last_accessed entry
        best = x if x > best
      else
        x = File.atime(entry)
        best = x if x > best
      end
    end
  end
  return best
end
Dir.chdir($*[0] || Dir.pwd) do
  Dir.foreach(‘.’) do |entry|
    # puts entry
    next if entry == ‘.’ or entry == ‘..’
    x = (File.directory?(entry) ? last_accessed(entry) : File.atime(entry))
    if Time.now - x > 60 * 60 * 24 * age
      case action
      when ‘DELETE’
        File.delete(entry)
      when ‘TRASH’
        FileUtils.mv(entry, File.expand_path(‘~/Trash/))
      when ‘ARCHIVE’
          FileUtils.mv(entry, File.expand_path(/Users/charleslsnyder/Archives’))
      else
        puts entry + ‘: ‘ + distance_of_time_in_words(x, Time.now, true)
      end
    end
  end
end

Ruby Web Search

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require ‘net/http’
require ‘rexml/document’
# Web search for "finance"
url = ‘http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=cls31415o&query=finance&results=40'
# get the XML data as a string
xml_data = Net::HTTP.get_response(URI.parse(url)).body
# extract event information
doc = REXML::Document.new(xml_data)
titles = []
links = []
doc.elements.each(‘ResultSet/Result/Title’) do |ele|
   titles << ele.text
end
doc.elements.each(‘ResultSet/Result/Url’) do |ele|
   links << ele.text
end
# print all events
titles.each_with_index do |title, idx|
   print "#{title} => #{links[idx]}\n"
end

Ruby interval between dates

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Date
 
  def distance_to(end_date)
  years = end_date.year - year
  months = end_date.month - month
  days = end_date.day - day
    if days < 0
  days += 30
   months -= 1
; end
    if months < 0
;   months += 12
   years -= 1
 end
    {:years => years, :months => months, :days => days}
  end
end
c = Date.new
c = distance_to(1/1/2009)
puts c

Ruby CSV sum by column

1
2
3
4
5
6
7
8
9
10
11
# This takes csv data, and identifies it by column header (bob), sums the x column, and then adds a column with x/sum x
 
require ‘rubygems’
require ‘fastercsv’
csv="f,bob\na,0\nb,1\nc,2\nd,3\n"
table = FCSV.parse(csv, :headers => true, :converters => :integer)
xs = table['bob'].map{|x| x.to_i}
sum  = Float table['bob'].inject{|sum,i| sum += i}
norm = xs.map{|x| x / sum}
table['n'] = norm
puts table