Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Thursday, March 10, 2016

DATA SIMPLIFICATION: System Calls


Over the next few weeks, I will be writing on topics related to my latest book, Data Simplification: Taming Information With Open Source Tools (release date March 23, 2016). I hope I can convince you that this is a book worth reading.


Blog readers can use the discount code: COMP315 for a 30% discount, at checkout.


A system call is a command line, inserted into a software program, that interrupts the script while the operating system executes the command line. Immediately afterwords, the script resumes, at the next line. Any utility that runs from the command line can be embedded in any scripting language that supports system calls, and this includes all of the languages discussed in this book.

Here are the properties of system calls that make them useful to programmers:

1. System calls can be inserted into iterative loops (e.g., while loops, for loops), so that they can be repeated any number of times, on collections of files, or data elements.

2. Variables that are generated at run-time (i.e.,during the execution of the script) can be included as arguments added to the system call.

3. The results of the system call can be returned to the script, and used as variables.

4. System calls can utilize any operating system command and any program that would normally be invoked through a command line, including external scripts written in other programming languages. Hence, a system call can initiate an external script written in an alternate programming language, composed at run-time within the original script, using variables generated in the original script, and capturing the output from the external script for use in the original script!

System calls enhance the power of any programming language by providing access to a countless number of external methods and by participating in iterated actions using variables created at run-time.

How does the system call help with the task of data simplification? Data simplification is very often focused on uniformity and reproducibility. If you have 100,000 images, data simplification might involve calling ImageMagick to resize every image to the same height and width. If you need to convert spreadsheet data to a set of triples, than you might need to provide a UUID string (see prior blog) to every triple in the database, all at once. If you are working on a Ruby project, and you need to assert one of Python's numpy methods, on every data file in a large collection of data files, then you might want to create a short Python file that you can be accessed, via a system call, from your Ruby script.

Once you have gotten the hang of including system calls in your scripts, you will probably use them in most of your your data simplification tasks. It's important to know how system calls can be used to great advantage, in Perl, Python, and Ruby. A few examples follow.

The following short Perl script makes a system call, consisting of the DOS "dir" command:
#!/usr/bin/perl
system("dir");
exit; 
The "dir" command, launched as a system call, displays the files in the current directory. Here is the equivalent script, in Python:
#!/usr/local/bin/python
import os
os.system("dir")
exit
Notice that system calls in Python require the importation of the os (operating system) module into the script.

Here is an example of a Ruby system call, to ImageMagick's "Identify" utility [note: this only works if you have pre-installed ImageMagick]. The system call instructs the "Identify" utility to provide a verbose description of the image file3320_out.jpg, and to pipe the output into the text file, myimage.txt.
#!/usr/bin/ruby
system("Identify -verbose c:/ftp/3320_out.jpg >myimage.txt")
exit
Here is an example of a Perl system call, to ImageMagick's "convert" utility, that incorporates a Perl variable ($file, in this case) that is passed to the system call [note: this only works if you have pre-installed ImageMagick].
#!/usr/local/bin/perl
$file = "try2.gif";
system("convert -size 350x40 xc:lightgray -font Arial -pointsize 32 -fill black
-gravity north -annotate +0+0 \"Hello, World\" $file");
exit;
The following Python script opens the current directory and parses through every filename, looking for jpeg image files. When a jpeg file is encountered, the script makes a system call to imagemagick, instructing imagemagick's "convert" utility to copy the jpeg file to the thumb drive (designated as the f: drive), in the form of a grayscale image. If you try this script at home, be advised that it requires a mounted thumb drive, in the "f:" drive [note: this only works if you have pre-installed ImageMagick].
#!/usr/local/bin/python
import os, re, string
filelist = os.listdir(".")
for file in filelist:
  if ".jpg" in file:  
    img_in = file
    img_out = "f:/" + file 
    command = "convert " + img_in + " -set colorspace Gray -separate -average " + img_out
    os.system(command)
exit
Let's look at a Ruby script that calls a Perl script, a Python script, and another Ruby script, from within one Ruby script.

Here are the Perl, Python and Ruby scripts that will be called from within a Ruby script:
hi.py
#!/usr/local/bin/python
print("Hi, I'm a Python script")
exit

hi.pl
#!/usr/local/bin/perl
print "Hi, I'm a Perl script\n";
exit;

hi.rb
#!/usr/local/bin/ruby
puts "Hi, I'm a Ruby script"
exit
Here is the Ruby script, call_everyone.rb, that calls external scripts, written in Python, Perl and Ruby:
#!/usr/local/bin/ruby
system("python hi.py")
system("perl hi.pl")
system("ruby hi.rb")
exit
Here is the output of the Ruby script, call_everyone.rb:
c:\ftp>call_everyone.rb
Hi, I'm a Python script
Hi, I'm a Perl script
Hi, I'm a Ruby script
If you have some facility with a variety of language-specific methods and utilities, you can deploy them all from within your favorite scripting language.

- Jules Berman

key words: computer science, data analysis, data repurposing, data simplification, data wrangling, information science, simplifying data, taming data, complexity, system calls, Perl, Python, Ruby, jules j berman

Sunday, December 13, 2015

Greyscale Batch Conversion of Image Files

Using ImageMagick, it's easy to convert all the image files in a directory to black and white. Here are short scripts implemented in Perl, Python, and Ruby that open the current directory, parse through all the filenames in the directory, to create greyscale versions of jpg, gif, bmp, or png images. Each greyscale copy of an image file is provided with a new filename consisting of "_bw" appended to the filename prefix (e.g., dog.png is copied as the greyscale file, dog_bw.png)
#!/usr/bin/perl
opendir(FILES, ".") || die ("Unable to open directory");
@in_files = readdir(FILES);
closedir(FILES);
foreach $filename (@in_files)
   {
   if ($filename =~ /([a-z0-9\_]+)(\.[gifbmpjpgn]{3}) *$/i)
     {
     $out_file = $1 . "_bw" . $2;
     system("convert ${filename} -set colorspace Gray -separate -average ${out_file}");
     }
   }
exit;

#!/usr/local/bin/python
import os, re, string
filelist = os.listdir(".")
for file in filelist:
  if ".jpg" in file or ".bmp" in file or ".gif" in file or ".png" in file: 
    outfile = "bw_" + file 
    command = "convert " + file + " -set colorspace Gray -separate -average " + outfile
    os.system(command)
    #print command
exit

#!/usr/local/bin/ruby
filelist = Dir.glob("*.*")
filelist.each do
 |file|
 if file =~ /([a-z0-9\_]+)(\.[gifbmpjpgn]{3}) *$/i
    out_file = $1 + "_bw" + $2
    system("convert " + file + " -set colorspace Gray -separate -average " + out_file)
  end
end
exit
© 2008 Jules Berman

As with all of my scripts, lists, web sites, and blog entries, the following disclaimer applies. This material is provided by its creator, Jules J. Berman, "as is", without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. in no event shall the author or copyright holder be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the material or the use or other dealings.

Saturday, January 23, 2010

Batch image conversions

I'm interrupting a series of blogs on the topic of complexity to provide a pointer to my recently constructed web page on batch image conversions.

When you write your own image software, you can automate activities that would otherwise require repeated operations, on multiple image files, with off-the-shelf image processing software. For example, you might want to delete, add, or modify annotations for a group of images, or you might want to resize an image collection to conform to specified dimensions. When you have more than a few images, you will not want to repeat the process by hand, for each image. When you have thousands of images, stored in a variety of image formats, it will be impossible to implement global conversions, if you do not know how to batch your operations.

The Batch conversions: Perl, Python, Ruby page provides three equivalent scripts, in Perl, Python and Ruby, that converts a batch of images from color to greyscale. The scripts are preceded by a step-by-step explanation of the code.

- © 2010 Jules Berman

tags: perl programming, python programming, ruby programming, image magick, imagemagick, grayscale, greyscale, big data, metadata, data preparation, data analytics, data repurposing, datamining, data mining, conversion, image format, image processing, perl, python, Ruby Jules J. Berman Ph.D., M.D.
My book, Principles of Big Data: Preparing, Sharing, and Analyzing Complex Information was published in 2013 by Morgan Kaufmann.



I urge you to explore my book. Google books has prepared a generous preview of the book contents.

Thursday, December 18, 2008

CDC Mortality Data: 10

This is the tenth in a series of posts on the CDC's (Centers for Disease Control and Prevention) public use mortality data sets. In yesterday's blog in this series, we reviewed the steps taken to create our coccidioidomycosis mashup.

In today's blog, we'll look at how we can tweak our scripts to combine data from different data lists, to change occurrence data to incidence data, and to enhance the visual results.

Let's skip ahead in the discussion and look at the final mashup map, which contains incidence data for two different fungal diseases: coccidioidomycosis and histoplasmosis.


The red circles represent the coccidioidomycosis rates of infection, as recorded on death certificates. The blue circles represent histoplasmosis rates.

The map shows that coccidioiodomycosis is endemic in the Southwest U.S. Histoplasmosis is endemic in the Eastern half of the U.S. It took under a minute to generate this mashup map, parsing over one gigabyte of de-identified death certificate data records, extracting data on occurrences of both diseases and the states in which they were recorded, and producing a visual output that conveys a detailed epidemiologic study that can be understood at a glance.

To achieve this output, we simply tweaked the two scripts discussed in prior blogs in this series: the perl script that collects cases based on diagnosis; and the ruby script that draws circles on an outline map.

Conveniently, ICD codes for conditions resulting from C. immitis infection (coccidioidomycosis) all begin with B38. Conditions for H. capsulatum (histoplasmosis) begin with B39. Virtually the same code collects occurrences of either disease. The key difference between today's graphic output and that shown in an earlier blog in this series is that today's graph shows the rate of occurrence in the different states, not just total number of occurrences. By "rate", we refer to the number of occurrences divided by the at-risk population. As shown in the code below, as the script parses through the ICD data records, it collects the number of records from each state (keeping a state record tally in the %state_total hash) and the number of occurrences in each state (keeping a state disease tally in the %state_disease hash).

while ($line ne "")
{
$line = <ICD>;
$state = 0;
$code = substr($line,20,2);
$state = $statehash{$code};
$state_total{$state}++;
$codesection = substr($line,161,140);
if ($codesection =~ /B39/)
{
$state_disease{$state}++;
}
}
open (DATAFILE, ">state_count.txt");
while ((my $key, my $value) = each(%state_disease))
{
$rate = int(($value / $state_total{$key})*50000);
print "$key $value $rate $state_total{$key}\n";
print DATAFILE "$key $rate\n";
}

The resulting rate is determined in the following line:

$rate = int(($value / $state_total{$key})*50000);

We note that the ratio is multiplied by the number 50000. We multiply the ratio by this number to produce an output that produces a graphically pleasing circle size. There is no scientific significance to the number 50000. The circles are proportionate symbols, not measurements.

What is the difference between a disease rate and a disease incidence? Incidence is a formal epidemiologic concept represented by cases perl 100,000 members of a living population. I believe that the way we have treated the data (death certificate occurrences of disease as a proportion of all death certificate records) is a valid way to represent the data, but if you want to work with living populations, you will need to use state population data. The CDC data dictionary for the mortality files provides this information.



If you want to go one step further, and obtain age-adjusted incidence rates, you'll need to extract patient ages for the occurrences of disease (a simple process, as age is provided in the mortality data sets) and use the stratified population age data tables, also provided in the CDC data dictionary file.



The data dictionary file is available by anonymous ftp from ftp.cdc.gov at the following subdirectory:

/pub/Health_Statistics/NCHS/
Dataset_Documentation/mortality/
Mort99doc.pdf

As I remind readers in almost every blog post, if you want to do your own creative data mining, you will need to learn a little about computer programming.

For Perl, Ruby, or Python programmers, methods and scripts for using a wide range of publicly available biomedical databases, are described in detail in my prior books:

Perl Programming for Medicine and Biology

Ruby Programming for Medicine and Biology

Methods in Medical Informatics: Fundamentals of Healthcare Programming in Perl, Python, and Ruby

An overview of the many uses of biomedical information is available in my book,
Biomedical Informatics.

More information on cancer is available in my recently published book, Neoplasms: Principles of Development and Diversity.

© 2008 Jules Berman

As with all of my scripts, lists, web sites, and blog entries, the following disclaimer applies. This material is provided by its creator, Jules J. Berman, "as is", without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. in no event shall the author or copyright holder be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the material or the use or other dealings.

In June, 2014, my book, entitled Rare Diseases and Orphan Drugs: Keys to Understanding and Treating the Common Diseases was published by Elsevier. The book builds the argument that our best chance of curing the common diseases will come from studying and curing the rare diseases.



I urge you to read more about my book. There's a generous preview of the book at the Google Books site.

tags: common disease, orphan disease, orphan drugs, rare disease, disease genetics, epidemiology, perl, Ruby

Friday, April 4, 2008

Generating prime numbers in Ruby, Python and Perl

If you need to generate prime numbers, the classic algorithm is the Sieve of Eratosthenes. Both the Sieve and a simpler, but slower method (the one shown here) are discussed in Mastering Algorithms with Perl, by Orwant, Hietaniemi, and Macdonald (O'Reilly, 1999).

Here are the equivalent Ruby, Python and Perl scripts.

As with all of my scripts, the following disclaimer applies. Each of these three scripts are provided by its creator, Jules J. Berman, "as is", without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. in no event shall the author or copyright holder be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.

For information about using Ruby for biomedical projects, you may want to read my recently published book:

Ruby Programming for Medicine and Biology


For information about using Perl for biomedical projects, you may want to read my recently published book:

Perl Programming for Medicine and Biology


Here is the Ruby script:

#!/usr/local/bin/ruby
state = Numeric.new
print "2,3,"
(4..10000).each do
|i|
(2..(Math.sqrt(i).ceil)).each do
|thing|
state = 1
if (i.divmod(thing)[1] == 0)
state = 0
break
end
end
print "#{i}\," unless (state == 0)
end
exit


Here is the equivalent Python script:

#!/usr/local/bin/python
import math
print "2,3,"
state = 1
for i in range(4, 10000):
upper = math.sqrt(i)
upper = int(upper)
for thing in range(2, upper):
state = 1
if (i % thing == 0):
state = 0
break
if (state == 1):
print i,
exit


Here's the equivalent Perl script.

#!/usr/local/bin/perl
print "2,3,";
for($i=4;$i<10000;$i++)
{
for $thing (2 .. int(sqrt($i)))
{
$state = 1;
if ($i % $thing == 0)
{
$state = 0;
last;
}
}
print "$i\," unless ($state == 0);
}
exit;

Sample output of the scripts is available.

The scripts are pretty straightforward. A prime number cannot be the product of two integers. We test each number up to 10,000 to determine if it is a prime number. If the number is prime, then there will be no smaller number that will divide into the number with a remainder of 0. So we test each number smaller than the number, to see if it divides into the number with anything other than a zero remainder. If not, then the number is a prime.

We stop when we get up to the square root of the number. If there were an integer larger than the square root of the number, which could be multiplied by another integer to give the number, then the other integer would need to be smaller than the square root of the number (otherwise, the two integers would produce a product larger than the number). But we've already tested all of the numbers smaller than the square root of the number, and they all yielded a non-zero remainder. So we don't need to test the integers greater than the square root of the number.

- Jules J. Berman, Ph.D., M.D. tags: prime numbers, prime number generation, calculating prime numbers, ruby programming, perl programming, python programming
Science is not a collection of facts. Science is what facts teach us; what we can learn about our universe, and ourselves, by deductive thinking. From observations of the night sky, made without the aid of telescopes, we can deduce that the universe is expanding, that the universe is not infinitely old, and why black holes exist. Without resorting to experimentation or mathematical analysis, we can deduce that gravity is a curvature in space-time, that the particles that compose light have no mass, that there is a theoretical limit to the number of different elements in the universe, and that the earth is billions of years old. Likewise, simple observations on animals tell us much about the migration of continents, the evolutionary relationships among classes of animals, why the nuclei of cells contain our genetic material, why certain animals are long-lived, why the gestation period of humans is 9 months, and why some diseases are rare and other diseases are common. In “Armchair Science”, the reader is confronted with 129 scientific mysteries, in cosmology, particle physics, chemistry, biology, and medicine. Beginning with simple observations, step-by-step analyses guide the reader toward solutions that are sometimes startling, and always entertaining. “Armchair Science” is written for general readers who are curious about science, and who want to sharpen their deductive skills.

Sunday, February 10, 2008

Correction to Ruby Programming for Medicine and Biology

Sorting the lines in large files is a frequent task for informaticians (e.g., sorting the lines from a long list of terms, with a different term on each line of the file).

For very large files, the built-in sort function of programming languages just cannot do the job because the lines are put into an array (held in memory), and even computers with lots of memory tend to choke.

An easy short-cut involves only sorting the first few characters of each line (10 characters in the script provided below), instead of the entire line. In this way, the array of lines from the file can be shortened to ten characters per line, and this saves lots of memory.

I provided a short Ruby script (bigsort.pl) in my book, Ruby Programming for Medicine and Biology. The bigsort.pl script on page 150 of Ruby Programming for Medicine and Biology, has a few quirks. First, it assumes that the text file (to be sorted) is a DOS-style file with a two character (carriage-return,line-feed) linebreak. Also, it assumes that every line (in the file to be sorted) contains alphanumeric text.

Provided here is a minor modification to the bigsort.pl Ruby script. It should work for any type of text file and does not require text to appear on each line of the file that is being sorted. As with all my posted scripts, the method is provided by its creator, Jules J. Berman, "as is", without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. in no event shall the author or copyright holder be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.

Thanks goes to Dr. Tim Rand, who spotted the error and sent me his own version of a fix on February 6, 2008.

#!/usr/local/bin/ruby
text = File.open("terms.txt", "r")
out = File.open("terms.put", "w")
linearray = Array.new
begin_position = 0
text.each_line do
|line|
old_position = begin_position
begin_position = text.pos
line = line.chomp! + " " #pad ten spaces
linearray << line.slice(0..9) + old_position.to_s
end
linearray.sort!
linearray.each do
|value|
seekplace = value.slice(10..20).to_i
text.seek(seekplace, IO::SEEK_SET)
out.puts(text.readline)
end
exit

-Jules Berman
Science is not a collection of facts. Science is what facts teach us; what we can learn about our universe, and ourselves, by deductive thinking. From observations of the night sky, made without the aid of telescopes, we can deduce that the universe is expanding, that the universe is not infinitely old, and why black holes exist. Without resorting to experimentation or mathematical analysis, we can deduce that gravity is a curvature in space-time, that the particles that compose light have no mass, that there is a theoretical limit to the number of different elements in the universe, and that the earth is billions of years old. Likewise, simple observations on animals tell us much about the migration of continents, the evolutionary relationships among classes of animals, why the nuclei of cells contain our genetic material, why certain animals are long-lived, why the gestation period of humans is 9 months, and why some diseases are rare and other diseases are common. In “Armchair Science”, the reader is confronted with 129 scientific mysteries, in cosmology, particle physics, chemistry, biology, and medicine. Beginning with simple observations, step-by-step analyses guide the reader toward solutions that are sometimes startling, and always entertaining. “Armchair Science” is written for general readers who are curious about science, and who want to sharpen their deductive skills.

Friday, October 19, 2007

Adding a comment to a PNG or JPG header with Ruby and RMagick

Whenever you create and distribute an image, you should consider putting information in the header, such as the image title and your name and usage restrictions (if any). If you're putting the image into the public domain, you should specify that the image is a public domain image.

These issues are discussed in depth in my web page, Implementing an RDF Schema for Pathology Images.

The header of an image is a text block that is not visible when the image is viewed, but which can easily be stripped from the image.

Here is are two short Ruby scripts. The first script enters a comment into an image header. The second script extracts and displays the comment.


script pdfadd.rb
#!/usr/local/bin/ruby
require 'RMagick'
include Magick
walnut = ImageList.new("neo1.png")
walnut.cur_image[:Comment] = "Developmental Lineage
Classification
of Neoplasms
Copyright (C) 2007
by Jules J. Berman
and distributed under
the GNU Free
Documentation License"
walnut_copy = ImageList.new
walnut_copy = walnut.cur_image.copy
walnut_copy.write("out.jpg")
exit


script pdf2.rb
#!/usr/local/bin/ruby
require 'RMagick'
include Magick
walnut = ImageList.new("out.jpg")
walnut.properties{|name, value|
print "#{name} #{value}\n"}
exit




This scripts require RMagick, and instructions for acquiring RMagick are available.

The first script, pdfadd.rb, adds a comment to an image and copies the png image to
a jpg image.

The second script, pdf2.rb, extracts and prints the comment from the jpeg image.

The output of the second script is:



C:\ftp>pdf2.rb
Comment Developmental Lineage
Classification
of Neoplasms
Copyright (C) 2007
by Jules J. Berman
and distributed under
the GNU Free
Documentation License
JPEG-Colorspace 1
JPEG-Sampling-factors 1x1



The image, neo1.png, is:





In June, 2014, my book, entitled Rare Diseases and Orphan Drugs: Keys to Understanding and Treating the Common Diseases was published by Elsevier. The book builds the argument that our best chance of curing the common diseases will come from studying and curing the rare diseases.



I urge you to read more about my book. There's a generous preview of the book at the Google Books site. If you like the book, please request your librarian to purchase a copy of this book for your library or reading room.

- Jules J. Berman, Ph.D., M.D. tags: common disease, orphan disease, orphan drugs, rare disease, disease genetics

Tuesday, October 9, 2007

Ruby scripts from Ruby Programming for Medicine and Biology

For those interested, here is a list of Ruby scripts that are included and described in Ruby programming for Medicine and Biology, my book that was published last month (September, 2007).

SCRIPTS IN RUBY PROGRAMMING FOR BIOLOGY AND MEDICINE

1.3.1. Getinput.rb retrieves a line of keyboarded text.

1.4.1. Grow.rb simulates six generations of bacterial growth.

1.4.3. Grow2.rb uses explicit Ruby objects and statements.

1.5.1. Lowclass.rb provides syntax for user-created classes.

1.5.3. Noclass.rb requires an external Person class definition.

1.5.4. Person_class_file.rb, a class library for script no_class.rb.

2.7.1. Combo.rb parses an array into all possible ordered subarrays.

2.8.1. Hash.rb creates and displays key/value pairs for a Hash instance object.

2.8.4. Neohash.rb creates three hash instances for the Neoplasm Classification.

2.10.1. Glob.rb demonstrated the Dir class glob method.

2.10.3. Dirlist.rb lists the files in the current directory.

2.12.1. Time.rb measures the length of time for any process.

3.4.2. Mod1.rb defines and includes a simple module.

3.4.3. Mod2.rb calls a module with the scope operator.

3.4.4. Mod3.rb embeds a module within a class.

6.2.1. Readsome.rb reads the first 20 lines of the MRCONSO file.

6.3.2. Zipf.rb prints the number of occurrences of words in a string.

6.3.4. Zipf2.rb creates a Zipf distribution of the words in OMIM.

6.4.1. Snom_get.rb extracts SNOMED-CT terms from UMLS.

6.5.1. Disease.rb collects SNOMED-CT diseases from UMLS.

6.6.1. Neosdbm.rb creates three persistent database objects.

6.7.1. Sdbmget.rb retrieves data from persistent object.

7.3.1. Sentence.rb, a simple sentence parser.

7.6.1. Search.rb searches through any file for lines matching a Regex expression.

7.7.1. Pubemail.rb extracts e-mail addresses from a PubMed search.

8.3.1. Base64.rb encodes strings in Base64 notation.

8.4.1. Dircopy.rb copies files from one directory to another.

8.5.1. Dcm2jpg.rb converts a DICOM file into a jpeg file.

8.5.3. Dcmsplit.rb converts a DICOM file into a jpeg and a text file.

8.6.1. Jpeg_add.rb inserts textual information into a jpeg image.

9.2.1. Concord.rb creates a concordance.

9.3.1. Indexer.rb creates an index.

10.2.1. Haystack.rb performs a binary search on a file.

10.3.2. Tinysort.rb sorts the lines of a file.

10.3.4. Bigsort.rb sorts large files quickly.

10.4.1. Anatomy.rb extracts SQL data from the Functional Model of Anatomy.

10.5.2. Alldata.rb sums the census districts to yield the total U.S. population.

11.2.1. Scrubit.rb scrubs and deidentifies any input line.

12.2.2. Autocode.rb provides nomenclature terms and codes for an input sentence.

12.3.1. Fastcode.rb improves performance compared with aucode.rb.

12.4.3. Icd.rb collects ICD10AM codes from the UMLS Metathesaurus.

12.5.1. Seer.rb determines the occurrences in the U.S. of tumor types found in the SEER public-use data files.

13.5.1. Fibo.rb computes the first twenty elements of the Fibonacci series.

13.6.1. Mean.rb computes the mean from an array of numbers.

13.7.1. Std_dev.rb computes the standard deviation for an array of numbers.

13.8.1. Randtest.rb simulates 600,000 casts of the die.

13.10.1. Error.rb uses resampling to simulate runs of errors.

14.6.2. Thresh.rb divides a text file into two threshold files.

14.6.5. Threshrv.rb computes original file from two threshold files.

15.2.2. Neopull.rb searches a server file for a web client query.

15.3.1. Neosafe.rb improves the security of neopull.rb.

17.3.1. Biohack.rb, converts a gene sequence into a protein sequence.

18.14.2. Rdf3.rb extracts triples from an RDF document.

18.19.2. Jpg2b64 inserts a Base64 jpeg image into an RDF file.

19.2.2. Ancestor.rb determines the ancestor lineage for organisms.

19.2.4. Class_lineage.rb determines ancestral lineage.

19.3.1. Neoself.rb provides tag hierarchy for XML file.

20.5.1. Conflict.rb overrides a class assignment.

-Jules Berman tags: bioinformatics, biomedical informatics, medical informatics, Ruby, ruby language, Ruby programming, scripts

Science is not a collection of facts. Science is what facts teach us; what we can learn about our universe, and ourselves, by deductive thinking. From observations of the night sky, made without the aid of telescopes, we can deduce that the universe is expanding, that the universe is not infinitely old, and why black holes exist. Without resorting to experimentation or mathematical analysis, we can deduce that gravity is a curvature in space-time, that the particles that compose light have no mass, that there is a theoretical limit to the number of different elements in the universe, and that the earth is billions of years old. Likewise, simple observations on animals tell us much about the migration of continents, the evolutionary relationships among classes of animals, why the nuclei of cells contain our genetic material, why certain animals are long-lived, why the gestation period of humans is 9 months, and why some diseases are rare and other diseases are common. In “Armchair Science”, the reader is confronted with 129 scientific mysteries, in cosmology, particle physics, chemistry, biology, and medicine. Beginning with simple observations, step-by-step analyses guide the reader toward solutions that are sometimes startling, and always entertaining. “Armchair Science” is written for general readers who are curious about science, and who want to sharpen their deductive skills.


Friday, June 15, 2007

Ruby Programming

I've recently written a book, "Ruby Programming for Medicine and Biology." The Table of Contents is available at the Jones and Bartlett Web Site.

In my opinion, it's important that biomedical informaticians become self-sufficient and less reliant on vendor-supplied applications. The simple act of writing your own programs is an empowering experience and permits us to develop and try new ideas, something that would not be feasible with commercial software.

For a long time, I've been an advocate of Perl (see my book).

Perl is very good when you want to do imperative programming (sometimes called procedural programming). Basically, in imperative programming, the program consists of the implementation of an algorithm in the syntax of the programming language. Each line of the program is another command that executes a step in the algorithm. Procedural programming is virtually the same as imperative programming. The only difference is that in procedural programming, a step in the algorithm may involve calling an external method (i.e., another algorithm). You can think of procedural programs as imperative programs with subroutines. This is what Perl does very well. Because it's easy to learn Perl syntax and because the built-in Perl commands and the available Perl modules provide most of the functionality that anyone would need in the biomedical field, Perl has become a very popular language among bioinformaticians.

The problem with Perl is that it is not well suited as a language that models and integrates biomedical classifications and ontologies. This last jargon-heavy sentence deserves a little explanation, but you probably don't need the standard essay on the data-intensive aspects of modern biomedicine. Suffice it to say that when you have lots and lots of complex data, you need some way to simplify the data and to relate one kind of data to other kinds of data. The best way to simplify data is with classifications or ontologies that can annotate data in a manner that everyone can understand and exchange. When you talk about classifications and ontologies, you're talking about data objects, object (instance) methods, class methods, inheritance, metadata descriptions, specifications, on and on. These are the things that object oriented languages provide.

Ruby is a great object oriented language because it is free, open source, has a very simple and logical syntax, and gracefully models existing biomedical classifications and ontologies. I tried using object-oriented Perl for my work with classifications and ontologies, but it just was not a good fit. I dabbled in Python (an excellent object-oriented programming language that has many of the features I was seeking), but it lacked a few things that I wanted.

Let's not get into an endless argument over Ruby v Python v Java. Let me just say that Python is fine (I won't get into my peeves regarding Java), but I chose Ruby because 1) its syntax was beautiful and simple, and I had no trouble learning the language; 2) it enforces single lineage inheritance (which greatly simplifies the language and fits well with the biological classifications that I work with), and 3) it uses the so-called open world paradigm for evaluating assertions, returning true, false or nil (rather than the true/false dichotomy of Perl and Python). I really need Ruby's "nil".

When do you use Perl, and when do you use Ruby? I use Perl whenever I want to create simple utility scripts (transforming one file into another file of a different structure, performing a single algorithm on an input, and so on). In the past, most of my work was this sort of thing. I don't use Ruby to create short utilities because Ruby is slower than Perl. A Ruby script will execute in about twice the time as a Perl script for the same algorithm. This is true of all object-oriented languages. The primary reason they run slowly is because they need to traverse their object libraries when methods are sent to objects.

I use Ruby for modeling biomedical domains. This usually means that if I'm using RDF, ontologies, classifications, objects, object libraries, I use Ruby.

Some of you may have heard of Ruby on Rails (RoR). This is a web server programming environment for creating simple, quick, elegant, object-oriented Web applications. It is wildly popular at the moment. It's just one more perk to learning Ruby.


-Jules Berman
Science is not a collection of facts. Science is what facts teach us; what we can learn about our universe, and ourselves, by deductive thinking. From observations of the night sky, made without the aid of telescopes, we can deduce that the universe is expanding, that the universe is not infinitely old, and why black holes exist. Without resorting to experimentation or mathematical analysis, we can deduce that gravity is a curvature in space-time, that the particles that compose light have no mass, that there is a theoretical limit to the number of different elements in the universe, and that the earth is billions of years old. Likewise, simple observations on animals tell us much about the migration of continents, the evolutionary relationships among classes of animals, why the nuclei of cells contain our genetic material, why certain animals are long-lived, why the gestation period of humans is 9 months, and why some diseases are rare and other diseases are common. In “Armchair Science”, the reader is confronted with 129 scientific mysteries, in cosmology, particle physics, chemistry, biology, and medicine. Beginning with simple observations, step-by-step analyses guide the reader toward solutions that are sometimes startling, and always entertaining. “Armchair Science” is written for general readers who are curious about science, and who want to sharpen their deductive skills.