Modern Evolutionary Synthesis: Natural Selection and Genetics Together Forever

So Darwin had A Big Idea ™ which has caused a ridiculous amount of debate/screaming/studying over the past 150 years. Everyone knows that, right? It’s caused so much uproar that recently the Texas school board has had near never-ending debates about the merits of teaching such Big Ideas to poor innocent children.

I live here! Awesome.

But I (sarcastically) digress. My main point for this essay is to discuss an interesting development that occurred nearly 50 years after Darwin wrote his abstract “On the Origin of Species by Natural Selection.”

(Did you notice that I called it an “abstract?” You see, Darwin had been working on his book for over 20 years when it finally came out–and it only came out when it did because another young scientist had happened upon the same idea and Darwin didn’t want 20 years of thought and work to go down the drain. So instead of publishing the 1200 page opus he originally planned, Darwin cut it down to a svelt few hundred pages and called it an abstract. Just an historical tidbit).

Oh Kanye...will this never get old?

Anyhow, Darwin’s ideas have not been taken at face value since the moment his pen hit paper. As with most scientific ideas, they have been analyzed, discussed, tested, reworked, and improved upon until they are almost unrecognizable in their original form. This is why I love science so much–the ideas are constantly changing and improving, and each member of the community has the opportunity, nay, duty, to suport or falsify the concepts that came before.

But that’s a bit too “philosophy of science” for this post. No, what I’m attempting to explain here is the concept of modern evolutionary synthesis, commonly called “the new synthesis” or “neo-Darwinism.”

So, in 1859 Darwin published On the Origin of Species, and it sparked a huge reaction. His main ideas can be summed up in four major points:

1. There is variation within species

2. These variations can be passed on to offpsring

3. Each generation sees too many offspring born than can possibly survive

4. The survival and subsequent reproduction of offspring isn’t random; those that do survive long enough to reproduce, or those that reproduce the most have the most favorable characteristics. Those characteristics are passed on to offspring. Those characteristics are naturally selected.

What’s interesting is Darwin did not put for the idea of evolution–in fact, the word “evolved” is only used once in the entire book, and is the last word of the last chapter. Evolution as a concept had been around since the mid 1700’s, and was generally accepted even by the devoutly religious as a plausible explanation of animal life. What people didn’t know was HOW evolution worked, and there were many scientists putting forth various hypothesis to explain the mechanism.

Darwin came up with his ideas after years on board a ship, and collecting and observing all manner of life forms across the world. He then let the idea fester in his mind for over 20 years and slowly developed the over arching idea that evolution occurs through small variation from generation to generation, and that the most beneficial variations are conserved through natural selection.

The biggest problem with the idea of natural selection back in Darwin’s day, however, was no one could quite figure out how it actually worked. The evidence made sense (and Darwin does a beautiful job of beating the reader over the head with chapter after chapter of evidence for natural selection), but the actual mechanisms of inheritance still eluded the best scientists of the time. The debate raged on.

Meanwhile, off in Germany, a little known monk by the name of Gregor Mendel was doing some experiments with pea plants.

I eat my peas with honey, I've done it all my life....

Mendel figured out that traits were passed from generation to generation in a mathematically predictable manner. The problem was few people knew about his work. He published it in 1865, about 6 years after the first edition of On the Origin of Species, but all evidence suggests that Darwin never read the paper. Both Darwin and Mendel died before someone figured out to link the two ideas together.

But get linked together they did (Yay for literature searches!!). The 20th century saw some clever person pick up both pieces of work and think “Huh. This seems to work well together!” Mix in the discovery of genes and the idea of population genetics, and you get an explosion of evolutionary ideas that united a formerly divided group of scientists.

After a few decades of experiments and nobel prizes, the New Synthesis was born, and incorporated the ideas of both natural selection and genetics:

1. Populations contain randomly derived genetic variation accomplished through mutation and recombination

2. Gene frequency within populations changes through genetic drift (allele frequency change due to random sampling), gene flow (the transfer of alleles from one population to another), and natural selection

3. Most adaptive genetic variants have slight phenotypic effects, so change in phenotype is gradual

4. Speciation involves gradual evolution of reproductive isolation among populations, and is what causes diversification

5. The processes of speciation over a long enough time cause changes so great that higher taxonomic levels are necessary (genera, families, orders, etc.).

Basically, the modern evolutionary synthesis is the application of Darwin’s idea of natural selection to Mendel’s idea of inherited characteristics, with a little bit of Watson and Crick mixed in.

Hey! We discovered the structure of DNA!

Of course, listing the 5 major ideas of any paradigm simplifies it a little too much. These ideas were created by numerous scientists over the course of a decade, and represent some of the greatest ideas evolutionary biologists have had.

The major names associated with modern evolutionary synthesis are Julian Huxley, R.A. Fisher, J.B.S. Haldane, Sergei Chetverikov, Theodosius Dobzhansky, E.B. Ford, Ernst Mayr, Sewall Wright, George Gaylord Simpson, G. Ledyard Stebbins, and Bernhard Rensch.

Julian Huxley is credited with coining the term “modern evolutionary synthesis” in a book he wrote in 1942 Evolution: The Modern Synthesis. Julian Huxley was the grandson of Thomas Henry Huxley, the man known as “Darwin’s bulldog” due to his dogged defense of Darwin’s ideas. So I suppose it’s no surprise that Julian Huxley would carry on that tradition two generations later by bringing Darwin’s ideas into the 20th century. Julian’s book merges the revolutionary ideas of population genetics and genetic inheritance with natural selection by approaching genes from a natural selection standpoint. The book has two major editions, and has just recently been rereleased.

Of course, Huxley did quite a bit more than simply write a book–the years up to the writing of this work were filled with evolutionary research and the years after were filled with the same. He will forever be known as the man who coined the term, however.

R.A. Fisher is the guy responsible for such statistical break throughs as Fisher’s exact test and the ANOVA. I blame him for making stats such a pain in the butt! And so very useful. Thanks Fisher! Anyhow, Fisher was an active mathematician and geneticist during the first half of the 20th century. His interest in eugenics, mathematics, and evolution gave him the tools to become the founder of quantitative genetics. He spent much of his time attempting to calculate the distribution of gene frequencies among populations. Geez! I also had problems with those calculations in  my molecular ecology courses! Apparently this guy is responsible for all the difficult homework I’ve had over the last two years. Thanks, Fisher.

JBS Haldane is the second of three important mathematicians that helped to quantify rates of changes in gene frequencies (the first being RH Fisher). In 1932 Haldane penned a book entitled The Causes of Evolution, which summarized his work on the mathematical theory of natural selection.  Haldane went on to write an essay called On Being the Right Size, which postulates that physical size is often what determines the equipment necessary for life in a given species. This idea is referred to as Haldane’s principle by modern biologists. On a humorous note, Haldane famously answered the question “What can be inferred about the mind of the Creator form the works of His Creation” with “An inordinate fondness of beetles.”

Funny and sarcastic scientists are the best!

Sergei Chetverikov was one of several Russian scientists that ventured into the world of evolutionary biology in the early 20th century. Chetverikov worked with fruit flies, and in 1926 wrote a paper that bridged early theories of genetic evolution with real world populations. He found that the process of mutation was the same in natural, laboratory, and domesticated populations; most mutations are deleterious but there  ere some that do not reduce viability; a randomly mating population is stable; new mutations are absorbed by heterozygous individuals; mutations gradually spread through the population by chance (a very early concept of genetic drift); and isolation and genotypic variability lead to differentiation. These concepts are just a few put forth in his major work, which, unfortunately, was only published in Russian. Luckily, Haldane had a translated copy and was able to make use of these concepts during the new synthesis.

Theodosius Dobzhansky is another influential Russian scientist, although he had the distinction of moving to America during his seminal research years. Dobzhansky, a geneticist by trade, is credited with writing a major work on modern evolutionary synthesis: Genetics and the Origin of Species. This work defines evolution as “a change in the frequency of an allele within a gene pool” and is responsible for spreading the idea that natural selection takes place through mutations on genes. He is also credited with the famous phrase “Nothing in Biology Makes Sense Except in the Light of Evolution,” which is the title to a famous article in which he articulates the conflict of evolution and creation.

E.B. Ford was a student of Julian Huxley at Oxford, and spent his career working on insects. He is responsible for the field of ecological genetics, and was on good working terms with Dobzhansky and Fisher, with whom he exchanged numerous letters and ideas. Ford formalized the definition of genetic polymorphism (when two or more clearly different genotypes exist within a single species), and used his knowledge of Lepidoptera to test and eventually prove many of Fisher’s predictions. Ford’s most famous student was Bernard Kettlewell, who conducted experiments on the evolution of melanism in the peppered moth, an experiment which delights and annoys students to this day.  On a side note, Ford campaigned for the legalization of male homosexuality in his native Britain. Just an FYI.

Ernst Mayr (pronounced “Mire”) was a taxonomist and naturalist who was the youngest of the modern synthesis boys (he died only recently in 2005). His major book was Systematics and the Origin of Species in 1942, in which he helped to define the biological species concept: a species is not just a group of morphologically similar individuals, but a group that can breed exclusively among themselves. He suggest the concept of peripatric speciation, in which populations of adjacent yet isolated individuals will, though genetic drift and natural selection, evolve into distinct species over a period of time. Mayr was a voice of dissension among the modern synthesis crew, insisting that natural selection acted upon the whole organism and not individual genes. He also criticized molecular evolutionary studies. Huh. Maybe he was kind of a jerk. A smart jerk, but a jerk none the less.

Sewall Wright is the third mathematician that I blame for all those damn calculations I had to do in molecular ecology. He worked with Fisher and Haldane on the concept of population genetics, and discovered the inbreeding coefficient.

George Gaylord Simpson (hee! Gaylord) was an influential paleontologist during the early 20th century, and lent a much needed historical perspective to the new synthesis. He wrote several works including The Meaning of Evolution and The Major Features of Evolution, and was an expert on extinct mammals and their migratory patterns. He is known for coining the term hypodigm (a sample from which the characteristics of a population may be inferred), and he predicted the concept of punctuated equilibrium years before it was officially put forth by Dawkins.

G. Ledyard Stebbins is the lone botanist in this crew, and studied the evolutionary biology of plants at Berkeley. He wrote Variation and Evolution in Plants, which, by many, is considered a core of the evolutionary synthesis. His work on polyploidy and speciation in plants has influenced nearly all botanists since his time. When speaking of his own work, he never considered his contributions unique; he simply thought he was applying evolutionary biology and genetics to plants, and describing how these concepts affected botany as a whole.

Bernhard Rensch is the lone German of this group, and is responsible for popularizing the new synthesis in his native country. His primary work involved explaining how the concepts that drove speciation could be used to describe higher taxa. He also worked in areas of animal behavior.

It’s almost magical how just the right people with the right backgrounds in the right areas all were studying at the same time, isn’t it? It’s a tribute to the beauty of the scientific method, I think, to see how each man’s ideas were disseminated and used by the others to eventually create a paradigm shift in the way biologists think about evolution.

–Adrienne

Sales Tax & Your First Amendment Rights

This morning I heard a story about a large corporation and a judiciary both acting in favor of privacy over taxes.  It warmed my cockles.

As the recession continues states look for ways to fix budget shortfalls.  Raising or enacting taxes is politically incendiary in an election year but one state saw a way to increase revenue.  Last year North Carolina asked Amazon for information about goods it shipped (complete with names & addresses) to residents between 2003 and 2010.  It intended to collect sales tax owed by the good people of NC.

Even though Amazon does not charge sales tax on purchases the buyer may be responsible for paying come April 15th.  North Carolina asked for records revealing identities and purchases as part of a tax audit of the online retailer.  Amazon replied with detailed information regarding the items purchased, dates, amount of purchases, and county to which the items were shipped, but no personally identifying information.  The state acknowledged the information is sufficient to assess sales taxes, but pressed for all the requested details.

With the aid of the ACLU Amazon fought back citing the First Amendment, specifically the Video Privacy Protection Act which bars “wrongful disclosure of video tape rental or sale records.”  Since passage in 1988 the protection was extended to cover DVDs, video games and books.  The federal district court in Seattle, Washington ruled in favor of Amazon.

Withholding the information was financially disadvantageous to the company because Amazon could not claim potential deductions, resulting in a higher tax bill.  They did the right thing in the face of monetary loss.

The cynic in me sees Amazon putting up a great public relations campaign in favor of privacy, all the while selling our personal information in secret to other companies.  Other states, including my home state of Texas, are pursuing uncollected tax revenue from Amazon and making a strong showing against the Tar Heel State may bolster their other cases.

Overall it is a win for privacy and I’ll take it.

References:

Pseudomonas aeruginosa and Biofilms

So I’ve taken this week to focus on information required by my microbiology professor :”Know about biofilms and quorum sensing.” No detail on *what* I should know about those two huge topics, but I need to know about them. All of it, I guess.

This is my brain. Bystanders beware!

I guess I’ll work on just knowing what I can. Let’s get to it, shall we?

First up, my plan of attack. There’s a lot of information out there about biofilms (they’re the darling of the microbiology world at the moment, and lots of time and effort is going into studying them), so there’s no way I’ll be able to memorize everything about them in the next few weeks. What I can do, however, is focus on a model specimen, and know everything about that particular model.

Pseudomonas aeruginosa is a bacterium that is frequently found in biofilms, and happens to be one of the most studied species in the biofilm world. (This is probably due to its annoying tendency to infect humans).

Skin lesions caused by aeruginosa. So gross!

This makes it the perfect subject for me to use as my model specimen. Let’s get to it!

First and foremost: what are biofilms?

Biofilms are communities of microorganisms embedded and immobilized in an extracellular polymeric substance (EPS) attached to a solid surface. The biofilm gives microorganisms protection from things like desiccation, predation, and antibiotics, and allows them to share water and nutrients. It has also been proposed that biofilms allow for the sharing of DNA, thereby facilitating the transfer of beneficial genes from cell to cell. This community organization is in direct opposition to the way we have studied microorganisms for many years: as free living single-celled organisms (called planktonic organisms).

Bacteria in a biofilm in a creek. Kinda gross looking.
Planktonic bacteria just being all lonely.

Biofilms are highly variable, and their exact make up and structure changes with species, temperature, stress, nutrients, and other environmental factors. While this is super annoying for those of us who want to know everything about biofilms, it’s actually a very good strategy for the micro communities that utilize these biofilms as environments: great diversity keeps a single organsim from decimating the world-wide biofilm population.

What makes a biofilm a biofilm is the presence of the extracellular polymeric substance (EPS for short).

"Extracellular" is outside the cell; "polymeric" is a repeated molecular unit

This stuff was originally called “extracellular polysaccharides” until scientists figured out that there were lipids, proteins and DNA involved as well. Luckily, they were able to come up with a phrase that kept the EPS acronym, so everything worked out in the end.

In order to form biofilms, planktonic bacteria go through five primary stages of biofilm development:

1. Initial attachment

2. Irreversible attachment

3. Maturation I

4. Maturation II

5. Dispersal

The five stages.

I’ll look at these in order, using P. aeruginosa as a model organism.

1. Initial attachment.

First and foremost, the planktonic bacteria need to get to the surface of something in order to form a biofilm (remember that the definition of a biofilm is a community of bacteria embedded in an external matrix attached to a solid surface). Pseudomonas aeruginosa does this via diffusive transport

Remember this type of diffusion drawing from your bio classes? Yep, bacteria move the same way.

convective transport

convective transport is when the bacteria gets carried along with the movement of a fluid...kinda like a surfer on a wave

and active transport driven by bacterium flagella.

This species has a single, polar flagellum that it uses to move.

Once the bacterial cells arrive at an appropriate spot, they attach to the surface. They are able to attach due to their flagellum, type IV pili, extracellular DNA, and Psl polysaccharides.

The flagellum is involved in attachment due to its stators.

The stator is the green stuff

You see, the flagellum works by spinning. There’s a spinning rotor portion, and a stationary stator portion, within which the rotor spins. In P. aeruginosa there are two stators, and both must be present for biofilm attachment. Truthfully, though, we don’t know exactly what the stators do to facilitate this attachment–we just know that mutants that don’t have the stators (either one or both) are unable to attach to surfaces and form biofilms.

Extra cellular DNA (eDNA) is an interesting discovery–scientists knew that it existed, but thought it was simply an artifact of lysed cells in the EPS. However, in depth studies of P. aeruginosa revealed that biofilm formation was impossible without it, and the bacterium produced such large amounts of eDNA by creating releasing vesicles from the cells which house DNA.

The yellow is the eDNA, the green is living cells, and the red is dead cells

So far, eDNA is simply refereed to as an “adhesion factor.” This is science code for “we know it’s important, but we don’t know how or why.” Basically, scientists have found that when cells don’t make eDNA, or when bacteria are flooded with something that breaks down the eDNA, these cells cannot form biofilms. If the eDNA is present, biofilms are present. Pretty convincing argument that eDNA is required, but there’s little information as to what it does exactly.

One article mentioned that eDNA may react with N-acyl-glucosamine, a major component of cell walls in bacteria. This reaction would cause a a bond to form between the eDNA and the cell walls, which would cause the cells to stick together. This may be the mechanism by which eDNA causes biofilm formation–flagella and type IV pilli are used to attach to a solid surface, while eDNA is used for cell to cell attachment. I wonder then if biofilms that are not attached to a solid surface (although some purists don’t consider these flocs biofilms at all) have a disproportionately high amount of eDNA? This is what’s neat about science…there’s so much to find out!

During this stage of initial attachment, some cells attach to the substrate and some don’t.

2. Irreversible attachment

This stage is characterized by most cells being attached, and the community differentiating into two parts: parts of the new community that are motile, and parts that are immotile. This seems to be a function of the nutrient availability of the environment where the bacteria are forming a biofilm. If there’s plenty of glucose in the environment (which P. aeruginosa uses as a carbon source), then part of the bacterial cells become immediately nonmotile, while another part are motile.

At this point, the Las quorum sensing system became active (that is the subject of the next blog, so I’ll let you wait for an explanation).

The nonmotile cells form microcolonies, which are used as “stalks” for mushroom-shaped structures. The motile bacteria climb up the stalks and form the “caps.”

Mushroom-shaped colonies formed from a bunch of motile and nonmotile cells

If citrate is used as a carbon source, however, the cells are all motile to begin with, and none of them stop to form these stalks. The resulting biofilm is flat.

The top ones have the mushroom shapes, while the bottom ones are flat

Man, phenotypic variation due to differences in nutrient availability! How much more complex can we get?!?

During this time, the extracellular polymeric substance is produced. The EPS is involved in attachment (naturally), interactions between subpopulations and therefore cell-t0-cell intercommunications, tolerance, and exchange of genes. As I said above, the matrix is made of polysaccharides, lipids, proteins and eDNA. We know the most about the polysaccharides, proteins and eDNA (it only has recently be discovered that lipids are more prevalent than we thought…that’s always how it goes, isn’t it?). The exact make up of this matrix is, once again, dependent upon environmental conditions. That makes sense, doesn’t it? The armor you wear, the communication you use, and the way you attach to things is always going to be dependent upon what is going on around you.

These different environmental conditions are sensed and regulated by a series of kinase/response regulators called LadS, RetS, and GacS.

Oh dear, new terms. Ok, what the heck are kinase/response regulators?

Let’s start with a kinase. Notice that -ase suffix on the word? That means it’s an enzyme. This particular enzyme is responsible for transferring phosphate groups from high-energy donor molecules (such as ATP) to some sort of substrate.

A phosphate group is just a phosphorus molecule with some oxygen and hydrogen attached.

When a phosphate group is added to another molecule or substrate, that substrate changes (duh…it’s got something added to it!). That change can change the shape of the molecule, opening up some receptor site that was closed before. Or it can allow the molecule to react with a new substrate. Whatever happens, the phosphorilation (addition of a phosphate group) causes a change in the substrate which starts a cascade of reactions within a cell.

It’s a neat system, actually…since cells don’t want reactions happening all the time, they can regulate them by requiring a phosphate group inorder to make a substance reactive. That phosphate group won’t be added with out kinase, and that kinase won’t even be around until the right time. Regulation at it’s finest!

Ok, now we know what kinase is, what about response regulators?

Response regulators are exactly what they sound like–proteins that regulate a response, usually the transcription/translation of a gene. They work with kinases by accepting the phosphate groups.

HDS=histadine kinsase; RR=response regulator; P=phosphate group

So, a kinase is usually in contact with the outside of the cell somehow. When it gets the signal it’s looking for, it takes a phosphate group and attaches it to a response regulator. The response regulator changes shape and becomes active, when then causes something in the cell to happen.

The kinase/response regulators involved in matrix production in biofilms are LadS, RetS and GacS. These three things are membrane associated proteins (proteins that span the membrane) and therefore search the environment for signals.

See those red things? Those are proteins embedded in the membrane.

What do the proteins search for? We don’t know. But it’s something, and when they find that special something it triggers the histadine kinase to phosphorelate the response regulators. In turn, the response regulators turn on groups of genes which do all manner of things, including producing the matrix.

Look at it go!

Once the matrix is in place, the cells are immobile and go on living as a community.

This formation of stalks and caps is characteristic of

3. Maturation stage 1

At this point, the layers of cells become greater than 10 micrometers thick.

The formation of mushroom caps involves the presence of some of the same things as initial attachment: eDNA, flagella, and type IV pili. The type IV pili may bind to the eDNA, while the flagellum allows the cell to get to its required place on the stalk.

During this stage, a second quorum-sensing system is switched on: the Rhl system.

This differentiation continues on until the thickness of the biofilm reaches a maximum of 100 micrometers, which introduces:

4. Maturation 2

This stage is characterized by the cell layers at their thickest points, the cells are nonmotile, and most of the cells are differentiated. At this point, the biofilm is at its most mature, and involves water channels, a highly organized system of cell colonies, and the ability to share genes among individual cells.

5. Dispersal

After several days of maturation, cells at the center of many of these clusters become motile and begin to disperse into the surrounding liquid.

Of course, the problem with attempting to characterize stages of development is that a mature biofilm may exhibit all 5 stages of development at any given time.

Well, that’s it in a nutshell. Biofilms are becoming more and more important in all manner of things, from medicine to engineering. I’m betting that this is the direction that microbiology will go in the future (and is probably why I need to know everything I can about the glory that is biofilm).

–Adrienne

PCR, Pyrosequencing, and all that Jazz

So for the past few months I’ve been frantically studying for not the GRE, but for my preliminary exams for my PhD. I will therefore be adding blogs that answer potential questions from my prelims in addition to GRE questions. This should be fun for all!

This is my brain
This is my brain.
This is my brain on Prelims.

My advisors have been giving me “hints” (i.e. “know everything in the world”) about the type of questions they are going to ask me, and one such hint made it perfectly clear that I better have a very clear understanding about the techniques I am using in my research. I won’t go into detail, but my research involves flies and bacteria, and I’m identifying that bacteria with pyrosequencing. I’ll then figure out the concentration of bacteria using qPCR or rtPCR, whichever our lab can afford. What the best way to understand these techniques? Explain them to you, good readers! Here we go.

First, a little bit of background. Both PCR and pyrosequencing involve DNA, and therefore you have to know a little bit about how DNA replicates. Long story short: DNA is made of long chains of 4 nucleotides: A, T, G, and C. The sequence of these nucleotides (called bases) determines which amino acids are produced, which in turn determines which proteins are produced, which then make up all that we see as life. Neat! DNA is packaged into cells in double strands…each strand is complimentary to the other. When these complimentary strands unzip, they can pair up with free nucleotides and make copies of themselves. This is what all these techniques are based on.

DNA replicating

Ok, lets get into a little bit more detail about how this replication works exactly, shall we? Nucleotides are made up of a nucleobase (adenine, guanine, cytosine, or thymine-A,G,C or T), a five carbon sugar, and some phosphate groups. Don’t let those terms “5 carbon sugar” and “phosphate group” scare you–a 5 carbon sugar is just what it sounds like…a sugar with 5 carbon molecules arranged in a ring:

See the numbers? You count the carbons clockwise, from 1' to 5'.

Hello there 5 carbons! Ok, we’ve got one of our bases attached to this ring of carbons, plus a phosphate group:

Isn't it cute? Just a little phosphorus surrounded by oxygen.

See? Phosphate groups are simple. I always get a little freaked out when scientists start changing the endings of words–all those “-ates” and “-ites” throw me off. However, they are really just word parts that tell me a bit about the compound. I won’t go into them here, but you can read about them on Wikipedia. Thanks Wiki!

Ok, so now we’ve got our complex compound: A,T,C, or G attached to that 5 carbon ring, which has some phosphate groups hanging on it.

Look at this whole thing put together! Ain't it cute?

Now, phosphate groups are reactive–they like attaching to what we call hydroxyl groups. Hydroxyl groups are simple things with confusing names (like most things in chemistry, I think). It is simply an oxygen bonded to a hydrogen. How simple is that?

See? In this case we've got our hydroxyl group bonded to a carbon. How cozy they look!

So phosphate groups and hydroxyl groups totally love each other, and they want to bond ALL THE TIME. It’s actually kinda cute. And a little gross. Anyhow, nucleotides have all these groups in particular places on their carbon rings. Let’s look at that picture of the five carbon ring again:

Notice the phosphate group up in the top left.

Ok, see the numbers? We pronounce those numbers as “five prime” or “three prime.” On nucleotides, the phosphate group is attached to the five prime carbon. See it? A hydroxyl group is attached to the three prime carbon. When two nucleotides are lined up next to each other, the 5′ (five prime) phosphate group bonds with the 3′ (three prime) hydroxyl group, and they totally make out. And make long chains of nucleotides, which become DNA. Whatever.

The make out sessions are circled in blue.

Therefore, in order for a nucleotide to attach to the end of a chain of nucleotides, the 3′ end has to be exposed at the end of the chain. Don’t worry, you’ll understand why I’ve explained all this in a second.

Now that we have the basics of how DNA replicates and how nucleotides stick together to facilitate that replication, let’s move on to some of the procedures I promised I’d explain forever ago.

PCR

PCR is short for Polymerase Chain Reaction, and is a method we can use to clone sequences of DNA. We often want to clone these sequences a whole bunch (on the order of a billion copies of a single sequence!), so technology is obviously involved. This is how it works:

DNA is collected from somewhere. It can be anything, really, and we only technically need a single copy (although more DNA makes this much easier). We take that DNA and break it apart. Knowing what we know about the structure of DNA makes this process simple. The two complimentary strands of DNA are attached via hydrogen bonds. Heat can break those hydrogen bonds (this is one of the reasons living things can only tolerate so much heat–DNA actually breaks apart). The temperature at which the two strands of DNA disassociate is called the DNA’s melting temperature, and varies with the DNA sequences.

You see, base pairs are attached by slightly different bonds: A attaches to T via a double bond, while G attaches to C via a triple bond. The more bonds present, the more heat it takes to break those bonds. Therefore, GC bonds take more heat than AT bonds.

See those two Hs in the middle? Those are the hydrogen bonds. There are two of them.
See how there are three Hs here? That's a triple bond.

If a strand of DNA has a bunch of GC pairs, then it’s going to take more heat to cause the complimentary strands to disassociate. More heat means a higher melting temperature. But I digress.

The DNA is heated until all the hydrogen bonds are broken, and then we can focus in on the particular part of the DNA that we want to copy (called “amplify”). I suppose we could do the entire genome, but that would take FOREVER and use up a lot of reagents. We don’t want that. Let’s focus on a single gene, or section, or tiny little part instead, shall we?

So, what part do we amplify? Well, that depends on the question you’re asking. Most of the time you do PCR so you can identify a particular species, or look to see if two people are related, or identify a person, or something like that, and the regions you choose to amplify vary for each of these questions. My research involves using PCR to identify a species, so I’m going to look at a particular section of RNA called the 16S rRNA region. Let me explain (because you know you want me to).

All organisms, be them eukaryotic (having membrane bound organelles) or prokaryotic (no membrane bound organelles) have ribosomes. Ribosomes are those parts of a cell that take amino acids and knit them together into proteins. Without ribosomes, proteins would never be made, and life as we know it wouldn’t exist. Thanks ribosomes!

Anyhow, ribosomes are able to do what they do because they are made up of RNA (RNA is that compliment to DNA that takes information all over the place). The RNA in ribosomes is broken up into two subunits: a large subunit and a small subunit, with messenger RNA (mRNA) smashed between the two subunits.

The amount of RNA in the ribosome depends on if the organism is a prokaryote or a eukaryote. Eukaryotes have larger chunks of RNA, and therefore the subunits are larger. The size of RNA is measured a little strangely–it doesn’t have to do with length or weight or mass or some simple measuring tool like that. Things this small are hard to measure with a ruler anyhow. No, RNA is measured by where it floats in a liquid while spinning in a centrifuge: the bigger it is, the lower it will sink when spun around. The smaller it is, the higher it will float.

Think of it this way: you know those spinning roller coasters at amusement parks where you stand against a wall and then the floor drops out and you stick? The ones where they say “if you are going to vomit, cover your mouth and raise your hand!” because if someone pukes EVERYONE is gonna have a bad day?

OMG, nobody throw up! Also, I always wanted to hang upside down on these, but I was never brave enough.

You ever been on one of these? They’re super fun. Did you ever look around while it was spinning, though? If you had, you would have noticed that larger people tended to slide down the wall (sometimes coming to rest on the floor ), while smaller people could stay really high up on the wall. This is a good way to separate the really big people from the really small people–the smaller a person is, the higher on the wall he’ll sit while the ride is spinning.

You can use this same principle to separate different sizes of RNA in the ribosome. You put some RNA in a liquid, spin it around, and then find out how high up on the wall it stuck. A Swedish chemist named Theodor Svedberg figured this out sometime in the 20th century. (I wonder if he went on one of these rides before going into the lab one day? I kinda hope he did). He spun RNA around and then numbered the places that it stuck to the wall. The lower the number, the higher up on the wall it stuck, and therefore the smaller the size. Naturally, he named these number units after himself, so now we have the strangely named “Svedberg unit” (hee!) to measure RNA. We abbreviate the Svedberg as S (because spelling “Svedberg” is hard).

Therefore, when you see a number followed by “S,” it means that you can tell the size of that RNA. For example, eukaryotic RNA is broken up in to a large subunit, which is 60S, and a small subunit, which is 40S. The 60S means that the larger subunit sunk down to the 60 mark in the spinning tube, while the smaller subunit only sunk down to the 40 mark. Make sense?

Now, of course we can break up the subunits of RNA into smaller and smaller bits. So we do. In bacteria (prokaryotes), the RNA is made of two subunits: the 50S and the 30S. We break up the 30S subunit into tiny, bite sized pieces because it’s easier to deal with that way. A long time ago some super smart scientist realized that a small portion of the 30S subunit was highly conserved, and could be easily used to tell species apart. This is called the 16S rRNA in prokaryotes, and the 18S rRNA in eukaryotes. It’s used all of the time, and there has been a lot of study on these regions, so most scientific studies use this in some way.

So I am, too. Since I want to be able to tell species of bacteria apart, I chose to use the 16S rRNA region to amplify and look at for my study. This is really nice, because there are primers out there that will amplify this region very easily. Ah, the perks of looking at a well-studied bit of RNA!

But I need to have enough RNA so I can look at it, and RNA is tiny…especially when I’m talking about just the 16S region. What’s a girl to do? Amplify!

PCR is the amplification of regions of DNA or RNA. (Am I repeating myself? Probably). Knowing the properties of DNA/RNA allows us to target specific regions (like the 16S region) and selectively amplify that region alone. Step one: break up double strands. Remember how to do that? Yep, heat (go over those double bonds above if you forget). As luck would have it, we know the melting temperature of DNA and RNA (due to calculations of CG content), and so if we heat up our sample to around 94 C, those bonds will rupture and we’ll be left with single stranded DNA. (For simplicity, I’m going to talk about DNA from here on out, but the same process holds true for RNA).

Once we have our single strand, we need to focus in on just the region we want (like the 16S region). To do that, we need to tell the DNA what to replicate, and then give it the means to do so. We do this by using enzymes and primers.

Enzymes are proteins which speed up reactions without being consumed themselves. The most important enzyme in a PCR reaction is called Taq polymerase (you know it’s an enzyme when you see the -ase suffix at the end of the word). A polymerase is an enzyme that attaches molecules together (and we just so happen want to have many nucleotides attached together, so it works out for us).

Every cell that has DNA (so, pretty much every cell ever) has its own polymerase that takes care of replication of DNA and of translating bits of DNA to do work in the cell. PCR uses a polymerase from a species of bacteria, Thermus aquaticus, which normall lives in hot springs.

So steamy! Who knew there would be life in such unfavorable conditions?!?

Have you been to any hot springs? They are ridiculous. I heard a story once about someone who jumped in one at Yellowstone national park. The meat fell off his bones before he was able to resurface. That’s stupid hot. Anyhow, bacteria are able to survive in these conditions, and do quite well, thankyouverymuch. Why am I telling you this? Well, cells that live happily at lower temperatures have enzymes that work perfectly at lower temperatures. If the temps get too high, the enzymes denature and no longer work. When we run PCR, we first start out with that melting step where we raise the temperature to break apart double stranded DNA. If we use enzymes in the PCR reaction that are denatured during that step, we either can’t continue, or we have to add more enzyme after we cool the reaction down. This is EXACTLY how PCR used to work–some poor grad student (because you KNOW professors weren’t in the lab doing this for hours on end) would have to add enzyme every 3-4 minutes during a reaction, all day. Talk about a crappy job!

Imagine doing this every 2-3 minutes, for several hundred little tubes, 30-40 times a day. Worst. Job. Ever.

So after a few years of having to manually add more and more enzyme every PCR cycle, someone thought “you know, there’s gotta be a better way!” Necessity is the mother of invention and all that, and some brilliant soul thought that there must be DNA polymerase that is stable at high temperatures. Sure enough, our friendly, heat-loving bacterium saved the day, and gave us a polymerase that doens’t denature at 95 C. Because it came from the bacterium Thermus aquaticus, we now call it Taq polymerase.

Aright, so now we have our sample of DNA, heat to break those double strands apart, and an enzyme that is stable during hot spells that will facilitate copying of regions of DNA. Now it’s time to tell the polymerase which region we want to copy!

We do this by using what are called primers. Primers are short bits of DNA that selectively attach to certain regions. Scientists design primers to attach to the parts of the DNA on either side of the region we want to amplify:

See? Primers on either side.

These primers are simply short bits of DNA that attach to the 3′ end of the single stranded DNA. These primers attach to the regions we’re after, and form stable hydrogen bonds. Of course, we can’t do this at the high temperature we used to break apart the DNA, so we have to cool the reaction down to 45-55 C for the primers to attach. We call the the annealing temperature and the annealing step. The exact temperature needed depends on how big your primers are, and how many Cs and Gs are involved.

The longer your primer is, the less likely it is to accidentally attach to random regions of the DNA, but the more likely it is to miss the region you actually want to amplify (long primers take a lot of time to attach, and we may not give them enough time). If you want a primer that is very specific, you design one that is really long (since it won’t attach to any other region of the DNA just by chance). If you want a primer that is sensitive, however, you design one that is shorter (since it will defiantly get the region you’re after, even if you don’t give it a lot of time). Therefore, when scientists design primers, they have to think about how specific and sensitive they want their primers, and how many mistakes they’re willing and able to put up with (called “noise”).

They also have to consider the GC content, due to those pesky triple bonds. The higher the GC content in a primer, the higher your annealing temperature. As a general rule of thumb, you want to have an annealing temperature about 5 C below the melting temperature of your primers.

Primer design is considered a little bit of science, and a little bit of art. Designers use published DNA sequences to choose good primer sites, then send off to specialized companies that make the primers for them. This is why you often see people using well-studied areas of DNA or RNA for research–the primers are already in existence, you can probably buy them in bulk, and there are certain regions that are found in all living things so you can use what are called “universal primers” to amplify DNA even in species you haven’t identified. Another plus for using the 16S region in my work!

So, we’ve broken apart the double stranded DNA, gotten our heat-resistant polymerase ready to make more DNA, and found our primers to tell that polymerase where to do its work. Now what?

Well, now we let nature take its course. We supply the Taq polymerase with all the tools it needs to do its job: the perfect environment (PCR buffer that puts everything at the optimal pH and the perfect temperature), a DNA template (our sample DNA which we broke apart), a bunch of nucleotides (in lab manuals this is called dNTP, and is really just a bunch of As, Ts, Cs, and Gs), and enough time to get the job done. We provide this in the extension or elongation step, where we raise the temperature to around 72 C (which is optimal temperature for Taq polymerase) and let it do its work. The enzyme takes all those free-floating nucleotides and lines them up all nice and neat on the template DNA.

Look at it go!

Depending on how long our target site is, we give the polymerase 1-3 minutes to do its job (the longer the site, the longer it’s gonna take to copy it, naturally). We then repeat the process 30-40 times. After we’ve repeated it that many times, we do a final extension step at the very end, just to give the polymerase some extra time to copy all the remaining single stranded DNA (usually 7 minutes does the job nicely), and then we cool the whole reaction down to refrigerator-type temperatures to hold the DNA until we’re ready to use it.

Notice how I keep saying we change the temperature of this reaction to do the different steps? We have to have precise control over the temperature to make sure everything happens in the correct sequence. (After all, what happens if we try to copy regions of the DNA before the primers are attached? Or before the DNA goes from double stranded to single stranded? Anarchy, I tell you! Actually, the reaction just wouldn’t work. Whatever).  We control the temperature by doing this entire reaction in a piece of lab equipment called the thermocycler.

...and here it is! Looks kinda boring, doesn't it?

We put all of our PCR reaction stuff in tiny PCR tubes…

Who knew everything in microbiology was so...micro?

…which we then place in the thermocycler and press the “go” button. Ah, automation at its best!

So here are the steps of PCR in a nut shell:

1. Put all the ingredients in a PCR tube: DNA, Taq polymerase, nucleotides (dNTP), buffer, primers

2. Place the tubes in the thermocycler and press “go”

3. Denaturation step: the thermocycler raises the temperature to 94 C  for 20-30 seconds to melt the hydrogen bonds between the double strands of DNA and create single strands of DNA, ready for copying.

4. Annealing step: the thermocycler lowers the temperature to 45-55 C for 20-40 seconds to allow the primers to find the area on the DNA we want to amplify and attach.

5. Elongation/Extension step: the thermocycler raises the temperature to 72 C for 1-3 minutes (1 minute if the target sequence is under 500 bp long, 3 minutes if it’s over 500 bp long) and Taq polymerase goes to work copying the target sequence.

6. Repeat steps 3-5: the thermocycler then starts from the beginning again, raising the temperature to break apart the newly formed DNA, lowers the temp to anneal the primers, and raises the temp to elongate the DNA. Each time it goes through steps 3-5 it’s called a “cycle,” and the thermocycler is programed to run 30-50 cycles.

7. Final elongation step: after 30 or so cycles, the thermocycler raises the temperature to 72 C for 7 minutes just to make sure all the left over single strands of DNA have time to be copied.

8. Final hold step: the thermocycler lowers the temperature to 4-15 C (4 C is about what your refrigerator is at to keep your milk cold) to keep the DNA fresh until you’re ready to use it.

Here is a good video that goes through the whole process: PCR on YouTube

How neat is that? And so simple! Of course, I’m saying that after writing 3700 words to explain exactly how it works, but whatever. It’s simple.

By the time PCR is finished, we’re left with 1 billion identical copies of our DNA. That’s enough to do whatever we want! And you know what we want to do with all those copies of the 16S region? Pyrosequencing!

Pyrosequencing

Ok, now we know a bit about DNA, replication, and PCR. The next bit of information we want about all of this is what is the exact genetic code for various regions of DNA. This information can tell us a lot about the organism from which it came, their relationship to other organisms in the world, and even the presence of mutations within particular genes. In short, knowing the actual sequence of a strand of DNA opens up a whole world of possibilities for scientists.

I want to know the particular genetic code so I can identify the bacteria I’m working with. Sure, I could use various other techniques to identify my bacteria, but conventional laboratory methods take a lot of time (as in weeks), and I have other things to do. Instead, I could extract my DNA, take a couple of hours and amplify the 16S region, and then load it all into a pyrosequencing machine and have my identifications by the end of the day. The other up side to this method is my ids are positive beyond a shadow of a doubt. No one questions identifications by genetic methods. This is why DNA is so powerful as evidence.

So, how does pyrosequencing work? I must say, this technique is brilliant…I was super excited the first time I learned about it (also? I’m a bit of a nerd). It’s a method based on sequencing by synthesis, and takes advantage of some byproducts of DNA replication.  It then uses enzymes from various organisms to show us (well, technically a computer) our sequence.

Remember how I talked about how DNA polymerase facilitates the addition of nucleotides to a DNA strand? (No? Look a few hundred words above this and you’ll find out). Well, what I didn’t mention at that time was that when it does this, that reaction has a byproduct: pyrophosphate.

Look! Phosphorus and oxygen all bonded together.

This is a molecule of phosphorus and oxygen that can be used to make ATP (energy).  So every time a single nucleotide, no matter which one, is added to a strand of DNA, this molecule is produced and sent out into the environment.

Now, if I happened to mix pyrophosphate (abbreviated PPi so I don’t have to type that long, hard-to-spell word again) with adenosine phosphosulfate (APS), I can get ATP. Isn’t that neat? So all I need to do is make that reaction happen–can you guess what I need to do that? Yep, and enzyme.

That enzyme is ATP sulfurylase, and converts PPi from nucleotide incorporation to ATP. That newly formed ATP goes floating off into the environment, all primed and ready to do some work.

We wouldn’t want to disappoint ATP, now would we? Nope, so we give it some work to do. We have provided this newly formed energy with a reaction to run: the conversion of luciferin into oxyluciferin. Why is that important work to do, you ask? Because this reaction causes a pretty glowing light–like in fireflies!

It glows with the power of luciferase!

Notice the word “luciferin” conjures up images of fire and brimstone. That’s on purpose–it’s supposed to remind you of something fiery and burning…that’s how you remember that it’s a substance that glows. Many animals in the world use this reaction all the time…fireflies are just one type. They take a substance we call luciferin, add some energy and the enzyme luciferase and cause a beautiful glow on summer evenings.

Well, some brilliant scientist thought this was neat, and decided to bring the luciferin/luciferase combo into the lab. So during the pyrosequencing reaction we take newly formed ATP and give it to the luciferase enzyme, which turns luciferin into oxyluciferin, causing it emit light.

I don't even know what to put here. Look! Reactions!

Why do we want it to emit light? I’ll tell you in a minute. Stay tuned.

Once all the reactions are finished, we want to clean up our solution so we can run the next cycle and continue on our path to sequencing DNA, so we put in a clean up enzyme in the form of apyrase, which degrades any excess nucleotides that are floating around. This leaves us with a nice, clean slate (or, more specifically, a nice clean solution).

Alright, so in order to run a pyrosequencing reaction we need some DNA, several enzymes, and some luciferin to make glow. Lets see how those things work together to give us some information, shall we?

Step 1: Put the DNA you want to sequence in a tube (this DNA usually consists of a bunch of PCR product, so you have over a billion copies of the target sequence–the more copies, the easier it is to sequence your DNA) along with primers for your sequence (so you can get synthesis started), DNA polymerase, ATP sulfurylase, luciferin, luciferase, and apryase. This gets put into the pyrosequencing machine so the computer can take over.

Another boring looking machine that does something quite neato.

Step 2: Press “go” on the machine. The computer adds one of the four nucleotides (A,T,C, or G) at a time–let’s say it starts with A. It floods the tube with the A nucleotide, and the enzymes take over.

Step 3: Your DNA strand is primed and ready, so if the first nucleotide on the template strand is a T, then the A that just flooded the solution will be added by DNA polymerase on the new complimentary strand. (If you forget how DNA replication works, check out my other blogs, or watch this video).

Step 4: The incorporation of that A into the new strand causes PPi to be released. That PPi is taken by the ATP sulfurylase and converted into ATP.

Step 5: The ATP is used as an energy source to allow luciferase to turn luciferin into oxyluciferin, which emits light.

Step 6: The light given off by the reaction is recorded by a camera attached to the computer, and logged as a peak called a pyrogram.

Step 7: Once DNA polymerase has used up all the A nucleotides it needs, apyrase degrades all the extra nucleotides floating around and gets the solution ready for the next one.

Step 8: The computer floods the solution with another nucleotide (let’s say G), and the process starts again.

The general sequence of steps

If there is more than one identical nucleotide in sequence (say GGG or TT), then more PPi is released (if there are two nucleotides in a row, then twice as much PPi is released; if there are three then 3x as much is released, etc.). More PPi means more ATP. More ATP means more luciferase action. More luciferase action means a brighter light. A brighter light is recorded as a higher peak by the computer.

The above steps are repeated until the entire sequence of DNA has been replicated. The computer then looks at they pyrogram and translates the peaks into a DNA sequence.

Hey, you know what would make this easier? A Video!! Watch and enjoy.

Wasn’t that neat? So pyrosequencing can kick back the sequence of up to 20,000 different DNA strands in 6 hours. How super awesome is that?!? I know!!

Well, at nearly 5000 words, that’s PCR and pyrosequencing in a nut shell. I hope you learned something!

–Adrienne

Cafélatté Homebrew – I ain’t talking about coffee

Cafélaté about to boil

The state of the art

Like many homebrew beer makers I also roast coffee.  It’s quick and simple to produce better java than you can buy in most shops.  While not a natural pairing, beer and coffee go together.  There’s coffee porter, coffee stout, ..uh… espresso porter….  I like to do things differently.

I thought about putting hops in my coffee grounds just to turn things on their head.  May still do that….  Instead, I picked a coffee drink and set about translating it to beer.  Astute readers have already picked up that I decided upon cafélatté – a mix of espresso and steamed milk.  This decision came mostly from the availability of lactose, milk sugar, for brewing.

The creative process

With one ingredient chosen I went a-browsing for the remainder of the grist.  To my surprise I discovered Coffee malt, a moderately roasted 2-row barley (130-170L).  My grain bills are almost always simple, with one or two specialty malts, so I decided to limit the beer to that one roast.  I also had an idea for a fourth ingredient.

The third grain is, of course, the base malt.  My normal favorite, Maris Otter, would likely be too nutty or biscuity for this beer.  Again looking for new things to try I cane across Golden Promise.  The description promised a “sweet, clean flavor” which I deemed perfect.  Although the beer will be malt-dominant, it should show the coffee flavors more than anything else.

To round the grain bill off I decided on rolled oats to give the beer body and a smooth mouthfeel.  The beer should feel like you are drinking a creamy latte and oats are just the thing.  With the four ingredients selected, I placed my order.

Days later it arrived.  Although the ingredients came 32 hours ahead of brew-day I was eager to taste my creation.  Originally the coffee malt was to make up 15% of the grist, but I ordered enough to make 20.  I mixed some of the Golden Promise and coffee malt and bit into a small handful.

Coffee malt does indeed smell and taste like coffee.  It has that burnt bean starbucks flavor that I do not care for.  But as the grain stewed in my mouth the base malt stepped forward to compliment the ash and roast.  I nearly couldn’t stop myself from eating the entire grainbill.

Enough already, get to the recipe

OG 1.042
IBU ~23
Efficiency 75%
BU:GU 0.5

Fermentables

  • 70% Golden Promise
  • 20% Coffee Malt
  • 5% Lactose
  • 5% Rolled Oats

I use a water to grist ratio of two quarts per pound.  Aimed for a single 60 minute step at 158ºF but hit 160º.  Collected six gallons of sweet wort at 1.041 SG.

Kettle

  • 23 IBUs of Hallertau at 45 minutes
  • Irish moss and lactose at 15 minutes

Yes, this is a 45 minute boil.  Chilled and pitched onto a healthy yeast cake of White Labs London Ale yeast.  OG came out to 1.045.

Whatsit taste like?

I like to taste my beers at many steps.  Right out of the chiller is an important place.  I am quite pleased with the way this beer matched my expectations of it.  The lactose really gives the impression of milk.  One of my tasters remarked that he expected a hot coffee drink from the aroma.

The wort smells of burnt grains and steamed milk.  The lactose and rolled oats combine to give the beer noticeable body, but a the malty sweetness remains thin, like something you would expect from a beer of ten SG points lower.  Hop bitterness is mild and should be nearly undetectable after fermentation.

I’ll edit link to the review when it’s done.

A Request to Friends

It has been sixteen months since Adrienne had a hysterectomy.  Saying “we’ve been through a lot” is meaningless truth.  Adie and I will never be parents.  Ultimately the decision was ours, heavily influenced by cold biological facts.  This blog is small catharsis, but its material is not for those with a weak emotional constitution.

We have seen two Mother’s and Father’s Days since the decision.  Each one is easier than the previous.  The first one Adrienne wrote

“There is no I-had-my-uterus-and-ovaries-taken-at-32-so-I-will-never-have-children-of-my-own day. If someone makes one, I hope it’s in August. I don’t have anything else to celebrate in August.”

I will observe this day on August 11th and I am asking our friends to do so with me.  The name isn’t catchy, the sentiment too raw, and it risks emphasizing our infertility.  With a little effort we can all turn this day into something positive. This day we should:

Celebrate the life and happiness we have

We let go of a lifetime of desires and expectations while simultaneously redefining and reorienting ourselves.  This process is not over, but our goal on this day is to be happy with all we have.

Emphasize accomplishments

Birthing and raising children is often quoted as the biggest accomplishment a person can make.  We do not believe it.  Your affirmation drives us on to other altruistic endeavors.

Show that we are whole people

Any -ectomy takes something away from a person.  We felt “broken” and may not get over that.

We are not the only ones

So many couples and singles struggle with their sense of childless self worth.
Think of them on this day.  If you would like to help, it is simple as a phone call, email, tweet or Facebook post just to say “hi” or to remind someone of the good they do.

This day is not about trying or failing to be a parent.  We need neither sympathy nor reminders of our “enviable freedom” and that parenthood is “not all joy“.  At the same time the day’s purpose is not to belittle family.  Reinforce the good things that all of do.

I would like to recognize Mandy Tompkins’ kind help in putting this together.  She has been there before us and gone on.

Hard-plumbing The Stand

Just a quick homebrew update.  My three-tier stand is great, but I kept melting hoses when they would touch the hot metal.  Luckily none ever burst and spewed hot wort all over, but I knew that was just a matter of time.

So a friend and I got out the torches and hard-plumbed the stand.  The hoses are now short jumpers that connect vessels to the center line.  Brewed a dunkelweiss with the new setup on Thursday.  Works well and no burned hoses.

Some eye candy:

Easy Thunderbird Account Management Using MCD

Ford Thunderbird Console
From myoldpostcards

Continuing my series on Mission Control Desktop, this post covers some enhancements I made for configuring email accounts in Thunderbird.  The mail.* branch is one of the largest group of preferences you can manipulate using autoconfig.  Setting up the right combination of mail.accountmail.server, mail.identity and mail.smtpserver is just a little tricky.

With the exception of the special “local folders” account, an email account in Thunderbird has four components: an account, a server, one or more identities, and an smtp server.  There are a few preference strings gluing each of these elements together. Each account you create is differentiated from the others by a unique label, defaulting to account<num>, with incrementing numbers. You can also use your own, more meaningful labels, such as mail.account.work-email and mail.account.gmail.

Element Branch
Account mail.account.accountN Glues POP/IMAP, SMTP servers and identities together
Server mail.server.serverN Settings for the IMAP or POP server
Identity mail.identity.idN Name, email address, drafts & stationery folders
SMTP Server mail.smtpserver.smtpN Settings for the SMTP server
Glue settings
Accounts list mail.accountmanager.accounts Comma-separated list of mail.account labels
Default account mail.accountmanager.defaultaccount The label of the default mail account
SMTP servers mail.smtpservers Comma-separated list of mail.smtpserver server labels
Default SMTP mail.smtp.defaultserver The label of the default SMTP server

Here is a quick example:

// Identity
defaultPref("mail.identity.id1.fullName", "Dean Brundage");
defaultPref("mail.identity.id1.draft_folder", "imap://dean.brundage@example.com@mail.example.com/Drafts");
defaultPref("mail.identity.id1.smtpServer", "smtp1");
 
// IMAP server settings
defaultPref("mail.server.server1.type", "imap");
defaultPref("mail.server.server1.hostname", "mail.example.com");
// etc
 
// SMTP server settings
defaultPref("mail.smtpserver.smtp1.auth_method", 1);
defaultPref("mail.smtpserver.smtp1.hostname", "smtp.example.com");
// etc
 
// Glue it all together
defaultPref("mail.account.account1.identities", "id1");
defaultPref("mail.account.account1.server", "server1");
 
defaultPref("mail.accountmanager.accounts", "account1");
defaultPref("mail.accountmanager.defaultaccount", "account1");
 
defaultPref("mail.smtp.defaultserver", "smtp1");
defaultPref("mail.smtpservers", "smtp1");

As you add more email accounts the code can get unmanageable when you try to remember to twiddle the right branches so all the accounts, their identities and smtp servers show up. I would like to present an alternative.

This code builds upon the PreferenceFactory prototype covered earlier.  I put together an object prototype for an account, containing a server, one or more identities, and an smtp server.  There is also a singleton for the account manager.  Now you can instantiate an object and call preference setters on it.  The code is more readable and less error prone.

   // Create an email account
   var workAccount = AccountManager.newAccount({ isDefault: true,
                                                 label: "work",
                                                 type: "imap" });
 
   // Lock Preferences on the IMAP server
   workAccount.server.setPrefs({ hostname: "mail.example.com",
                                 type: "imap" }, "lock" );
   // Default Preferences
   workAccount.server.setPrefs({ check_new_mail: true,
                                 name: "Corporate eMail" });
 
  // Lock Preferences on the SMTP server
  workAccount.smtpServer.setPrefs({ auth_method: 1,    /* User/pass */
                                    username: "dean.brundage@example.com" }, "lock" );
  // Default Preferences
  workAccount.smtpServer.setPrefs({ description: "Corporate SMTP server",
                                     hostname: "mail.example.com"});
 
  // And now a personal account
  var myGmailAccount = AccountManager.newAccount({ label: "gmail", type: "imap" });
  // Go about setting preferences on myGmailAccount as before

Download the source

That block of code replaces the tedious series of defaultPref and lockPref required to set up an email account.  It produces preference settings like these:

defaultPref("mail.accountmanager.accounts", "work-account1,gmail-account2");
defaultPref("mail.accountmanager.defaultaccount", "work-account1");
 
defaultPref("mail.account.work-account1.identities", "work-id1");
defaultPref("mail.account.work-account1.server", "work-server1");
lockPref("mail.server.work-server1.type", "imap");
 
defaultPref("mail.server.gmail-server2.type", "imap");
// etc
 
defaultPref("mail.smtp.defaultserver", "work-smtp1");
defaultPref("mail.smtpservers", "work-smtp1");

Download the source

/**
   By Dean Brundage
   Originally published here:
     http://blog.deanandadie.net/2010/06/easy-thunderbird-account-management-using-mcd/
*/
 
 
/* "Inheritance" helper
   http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
   copy all of parent's prototype functions to descendant
*/
function copyPrototype(parent, descendant)
{  var sConstructor = parent.toString(); 
   var aMatch = sConstructor.match( /\s*function (.*)\(/ ); 
   if( aMatch != null )
   {  descendant.prototype[aMatch[1]] = parent;  } 
   for (var m in parent.prototype)
   {  descendant.prototype[m] = parent.prototype[m];  } 
};
 
 
/* "Base" for the Mail.xxxx objects
 
   This requires the PreferenceFactory prototype covered in a previous post:
     http://blog.deanandadie.net/2010/05/manufacturing-user-preferences-for-mcd/
*/
function Mail()
{  this.PreferenceFactory();  // super
   this.addPrefBranch("mail");
   return this;
}
 
copyPrototype( PreferenceFactory, Mail );
 
 
Mail.prototype.joinIds = function(collection,separator)
{  if( ! separator )
      separator = ",";
   if( collection )
   {  ret = collection[0].id
      for( i = 1; i < collection.length; i++ )
         ret = ret + separator + collection[i].id;
   }
   return ret;
};
 
 
/* A thunderbird email "account" consists of
      Mail.Server -- A mail server (IMAP or POP)
      Mail.SMTPServer -- A SMTP server
      One or more Mail.Identities -- Email address and name
 
   A thunderbird local folders "account" has only one Mail.Server, nothing else
      Yup, local folders are "servers"
*/
 
/* Object to manage accounts
      I recommend managing mail accounts with the AccountManager unless you
      know what you are doing.
   var myAccount = AccountManager.newAccount();
   myAccount.doStuff();
 
*/
var AccountManager = new Mail();
 
AccountManager.accounts = [];
AccountManager.addPrefBranch("accountmanager");
 
/* Create a new account
   Alerts Thunderbird to the presence of the new account
   See Mail.Account for valid options
*/
AccountManager.newAccount = function(opts)
{  if( ! opts )
      opts = { };
 
   acct = new Mail.Account(opts);
 
   if( opts.isDefault )
   {  acct.useSMTPServer( new Mail.SMTPServer(opts) );
      this.setDefaultAccount(acct,opts.lockLevel);
   } else
   {  acct.useSMTPServer( Mail.SMTPServer.defaultServer );
   }
 
   this.accounts.push(acct);
   this.setPref( "accounts", this.joinIds(this.accounts) );
   return acct;
}
 
 
AccountManager.setDefaultAccount = function(account,lockLevel)
{  
   this.setPref("defaultaccount", account.id, lockLevel );
 
   /* It's possible to create an account before setting the default
      SMTP server.  Clean them up if this new account is the default
      (Expect Mail.Account to inform Mail.SMTPServer of the new default)
   */
   for( i = 0; i < this.accounts.length; i++ )
      this.accounts[i].useSMTPServer(Mail.SMTPServer.defaultServer);
}
 
 
AccountManager.setLocalFolders = function(folders,lockLevel)
{  this.setPref("localfoldersserver", folders.id, lockLevel);
}
 
 
/* Creates a new generic mail account (identity, server, smtp)
   Arguments
     opts: A hash of options. Valid options are:
           "isDefault": true | false (default false)
           "label": string - A unique label for this account, server & identity
           "lockLevel": "default" | "lock" | "pref" (default "default")
           "type": imap | pop | localFolder
 
   This prototype creates an object representing an email account
   It exposes some objects:
      myAccount.directoryServer  // The (optional) LDAP2Server object
      myAccount.identities       // An array of identites
      myAccount.server           // The IMAP/POP/LocalFolder Mail.Server object
      myAccount.smtpServer       // The Mail.SMTPServer object
 
   (The LDAP2Server object is detailed in a separate post on http://blog.deanandadie.net/)
*/
Mail.Account = function(opts)
{  if( ! opts )
     opts = { };
 
   if( ! opts.type )
      throw("What's my type?");
 
   this.Mail();  // "super"
 
   this.id = "account" + ++Mail.Account.count;
   if( opts.label )
   {  this.id = opts.label + "-" + this.id;  }
 
   // Our preference branch is mail.account.accountN
   this.addPrefBranch( [ "account", this.id ] );
 
   this.identities = [];
 
   this.server = new Mail.Server(opts);  // Need this either way
 
   if( opts.type.match(/^^imap$|^pop$/i) )
   {
      this.server.setPref("type", opts.type, opts.lockLevel);
 
      // Important that addIdentity be before the SMTP server is set up
      this.addIdentity( new Mail.Identity(opts), opts.lockLevel );
 
   } else if( opts.type.match(/^localFolders?$/i) )
   {  this.folders = this.server;
      AccountManager.setLocalFolders(this.folders);
      this.folders.setPref("type", "none", opts.lockLevel );
 
   } else
   {  throw("unrecognized Mail.Account type: " + opts.type);  }
 
   this.useServer(this.server, opts.lockLevel);
 
}
 
copyPrototype( Mail, Mail.Account );
 
Mail.Account.count = 0;                                   // Fake class variable
 
 
// Expects a Mail.Identity object and, optionally, the preference locking level
Mail.Account.prototype.addIdentity = function(identity,lockLevel)
{  if( identity )
   {  if( ! this.identities.contains(identity) )
      {  this.identities.push(identity);
         this.setPref("identities", this.joinIds(this.identities), lockLevel );
      }
   }
}
 
 
/* Helper to set the SMTP server
   Expects a Mail.SMTPServer object & optionally, an options hash
   Valid options:
     lockLevel: lock | default | pref
     force: true | false
*/
Mail.Account.prototype.useDirectory = function(directory, opts)
{  if( ! opts )
      opts = { };
   if( directory )
   {  if( opts.force || typeof(this.directoryServer) == "undefined" )
      {  this.directoryServer = directory;
         for( i = 0; i < this.identities.length; i++ )
            this.identities[i].useDirectory( this.directoryServer, opts );
      }
   }
}
 
/* Helper to set the SMTP server
   Expects a Mail.SMTPServer object & optionally, an options hash
   Valid options:
     lockLevel: lock | default | pref
     force: true | false
*/
Mail.Account.prototype.useSMTPServer = function(smtp,opts)
{  if( ! opts )
      opts = { };
   if( smtp )
   {  if( opts.force || typeof(this.smtpServer) == "undefined" )
      {  this.smtpServer = smtp;
         for( i = 0; i < this.identities.length; i++ )
            this.identities[i].useSMTPServer( this.smtpServer, opts );
      }
   }
}
 
 
// Expects a Mail.Server object and, optionally, the preference locking level
Mail.Account.prototype.useServer = function(server,lockLevel)
{  if( server )
      this.setPref("server", server.id, lockLevel );
}
 
 
/* Creates a new generic mail server
   Arguments
     opts: A hash of options. Valid options are:
           label: string - A unique label for this account, server & identity
*/
Mail.Server = function(opts)
{  if( ! opts )
     opts = { };
 
   this.Mail();
 
   this.id = "server" + ++Mail.Server.count;
   if( opts.label )
   {  this.id = opts.label + "-" + this.id;  }
 
   // Our preference branch is mail.server.serverN
   this.addPrefBranch( [ "server", this.id ] );
}
 
copyPrototype( Mail, Mail.Server );
 
Mail.Server.count = 0;  // Fake class variable
 
 
/* Creates a new mail identity. (name, email address, etc)
   Arguments
     opts: A hash of options. Valid options are:
           "label": string - A unique label for this account, server & identity
*/
Mail.Identity = function(opts)
{  if( ! opts )
     opts = { };
 
   this.Mail();
 
   this.id = "id" + ++Mail.Identity.count;
   if( opts.label )
   {  this.id = opts.label + "-" + this.id;  }
 
   // Our preference branch is mail.identity.idN
   this.addPrefBranch( [ "identity", this.id ] );
   this.hasSMTPServer = false;
};
 
copyPrototype(Mail, Mail.Identity);
 
 
Mail.Identity.count = 0;  // Fake class variable
 
 
/* Expects a LDAP2Server object and a hash of options
   Valid options:
      lockLevel: lock | default | pref
*/
Mail.Identity.prototype.useDirectory = function(ldap2Server,opts)
{  if( ! opts )
      opts = { };
 
   if( ldap2Server )
   {  this.setPref("directoryServer", "ldap_2.servers." + ldap2Server.id, opts.lockLevel);
      this.setPref("overrideGlobal_Pref", true, opts.lockLevel);
   }
};
 
 
/* Expects a SMTPServer object and a hash of options
   Valid options:
      force: true | false
      lockLevel: lock | default | pref
*/
Mail.Identity.prototype.useSMTPServer = function(smtpServer,opts)
{  if( ! opts )
      opts = { }
   if( smtpServer )
   {  if( opts.force || ! this.hasSMTPServer )
      {  this.setPref("smtpServer", smtpServer.id, opts.lockLevel);
         this.hasSMTPServer = true;
      }
   }
};
 
 
/* Creates a new smtp server
   Artuments:
     opts: A hash of options. Valid options are:
       isDefault: true | false (default)
       label: A unique label for this smtp server
   Throws an error if there is already a default smtp server
*/
Mail.SMTPServer = function(opts)
{  if( ! opts )
     opts = { };
 
   this.Mail();
 
   this.id = "smtp" + ++Mail.SMTPServer.count;
   if( opts.label )
   {  this.id = opts.label + "-" + this.id;  }
 
   // Our perference branch is mail.smtpserver.smtpN
   this.addPrefBranch( [ "smtpserver", this.id ] );
 
   if( opts.isDefault && Mail.SMTPServer.defaultServer )
      throw("Default smtp server already configured to " + Mail.SMTPServer.defaultServer);
 
   if( opts.isDefault )
      this.setDefault();
 
   // Register this SMTP server
   if( ! Mail.SMTPServer.servers.contains(this) )
      Mail.SMTPServer.servers.push(this);
 
   // Update mail.smtpservers to include the new one
   defaultPref("mail.smtpservers",  this.joinIds(Mail.SMTPServer.servers) );
 
   return this;
};
 
copyPrototype(Mail, Mail.SMTPServer);
 
// Some "class" variables
Mail.SMTPServer.count = 0;
Mail.SMTPServer.defaultServer = undefined;
Mail.SMTPServer.servers = [];
 
 
Mail.SMTPServer.prototype.setDefault = function()
{  Mail.SMTPServer.defaultServer = this;
   defaultPref("mail.smtp.defaultserver", Mail.SMTPServer.defaultServer.id );
}

Quick diff of Solaris patch levels

Suppose you have two Solaris machines and you want to bring them to the same patch level.  Or you are troubleshooting issues on two machines that are supposed to be identical.  I wrote a perl script that compares patch levels on two machines.

It shows something like this:

malfunction % patch_diff sr-host-01 sr-host-02
 
Patches on each system that are missing from the other.
                        sr-host-01  |  sr-host-02
          Wed Jun  2 11:40:40 2010  |  Wed Jun  2 11:40:59 2010
------------------------------------+-------------------------------------
                         118814-01  |  123252-01
                         118959-03  |  127752-01
                         119090-31  |  137110-01
                                    |  142430-01
                                    |  142436-01
 
Patches on each system that are downrev on the other.
                        sr-host-01  |  sr-host-02
          Wed Jun  2 11:40:40 2010  |  Wed Jun  2 11:40:59 2010
------------------------------------+-------------------------------------
                         137147-04  |  137147-05
                         137000-03  |  137000-06
                         125952-18  |  125952-19

Download patch_diff

First it shows all the patches sr-host-01 has that sr-host-02 does not have and vice-versa.  In this simplified case sr-host-01 has 3 patches sr-host-02 does not have and sr-host-02 has 5 patches sr-host-01 does not have.  It also compares patch revisions and shows the different levels on each host.  The machines share 3 patches that are at different revision levels.

To use patch_diff you must first generate a patch list on each machine.

0 sr-host-01 % patch_diff -g

This makes a directory with a NDBM file containing the patches on sr-host-01. Do the same for sr-host-02 and bring the NDBM files together. (It helps if your home directory is shared between the machines.)

0 malfunction % ls patch_diff
sr-host-01.dir  sr-host-02.dir
sr-host-01.pag  sr-host-02.pag

Download patch_diff

Manufacturing User Preferences For MCD

Bottling Line
From vissago

Nobody likes boring code

Mozilla products like Thunderbird and Firefox represent setting choices in a textual “tree” system. (Read the intro.)  Preferences that begin with print. live on the tree branch dealing with printing while those that begin with app.update. are on the auto-update system’s branch.  An easy concept to grasp. In practice, however, the simplicity will easily become a drone of defalutPref(“app.update.auto”, false); if you are not careful.

// This is a boring autoconfig script
defaultPref("browser.dom.window.dump.enabled", true);
defaultPref("browser.download.manager.retention", 0);
defaultPref("browser.download.manager.showAlertOnComplete", false);
defaultPref("browser.download.manager.showWhenStarting", false);
defaultPref("browser.download.save_converter_index", 0);
defaultPref("browser.feeds.handler", "reader");
defaultPref("browser.feeds.handler.default", "web");
defaultPref("browser.feeds.showFirstRunUI", false);
defaultPref("browser.history_expire_days.mirror", 180);
// and so on....

Working at The Preference Factory

Instead of hand-cranking preferences I developed an object prototype to mechanize large blocks of related settings.  The resulting code is more readable and easier to maintain when it looks something like this:

// Some hypothetical printing preferences
var printPrefs = new PreferenceFactory("print");
 
// Lock out printing background or in color and don't allow font download
printPrefs.setPrefs( { print_bgcolor: false,
                       print_bgimages: false,
                       print_downoadfonts: false,
                       print_in_color: false }, "lock" );
 
// Make some sensible defaults
printPrefs.setPrefs( { print_orientation: 0,  // Letter
                       print_to_file: false } );

Whitespace focuses your attention on the block and the object eliminates monotonous pref-branch statement repetition. For the experienced programmer this approach is the familiar object-oriented one of sending messages to receivers. One goal behind this prototype was to help create elegant code, which can be difficult to do in javascript. There is another purpose to PreferenceFactory which I will cover in a later post.

The Bottling Line

The heart of PreferenceFactory is a wrapper around the autoconfig API.  It performs lockPref(), defaultPref(), pref() and getPref() on a branch of the preference tree that you specify when creating the object. Here is the engine driving the factory:

function PreferenceFactory(arg)
{  this.prefNodes = [];   // Nodes in the preference tree
   this.prefBranch = "";  // String representation of the branch
   if(arg)
      this.addPrefBranch(arg);   // Add nodes to the tree and update the string representation
}
 
/* Preference setting helper function
   myServer.setPref("type", "imap", "lock");
   Arguments
     key: The preference string to set
     value: Value to assign to key
     lockLevel: Locking level.
            Valid values are "default", "lock" and "pref"
            Default level is "defulat"
*/
PreferenceFactory.prototype.setPref = function(key,value,lockLevel)
{  if( lockLevel )
   {  switch( lockLevel.toLowerCase() )
      {  case "default":
            this.defaultPref(key,value);
            break;
         case "lock":
            this.lockPref(key,value);
            break;
         case "pref":
            this.pref(key,value);
            break;
         default:
            throw("Unrecognized locking level: " + lockLevel );
      }
   } else
   {  this.defaultPref(key,value);  }
}
 
PreferenceFactory.prototype.defaultPref = function(key,value)
{  if( key )
      defaultPref( this.prefBranch + "." + key, value );
}
 
PreferenceFactory.prototype.getPref = function(key)
{  if( key )
      getPref( this.prefBranch + "." + key );
}
 
PreferenceFactory.prototype.lockPref = function(key,value)
{  if( key )
      lockPref( this.prefBranch + "." + key, value );
}
 
PreferenceFactory.prototype.pref = function(key,value)
{  if( key )
      pref( this.prefBranch + "." + key, value );
}

The “hypothetical print” code example gets its readability from a final function to set multiple preferences.  It uses a function I copied from JsUnit called trueTypeOf().  Its function is much like javascript’s typeof, but handles more than just the built-in data types.  setPrefs() accepts an array or “hash” and iterates over its elements, calling the above setPref() on each 2-tuple.

/* Sets multiple preferences
   Accepts an array or object "hash" and an optional locking level
*/
PreferenceFactory.prototype.setPrefs = function(prefs,lockLevel)
{  switch( trueTypeOf(prefs) )
   {  case "Object":
         for( thing in prefs )
         {  this.setPref(thing, prefs[thing], lockLevel);  }
         break;
      case "Array":
         if( prefs.length % 2 != 0 )
         {  throw("Need an even number of strings to set multiple preferences with an array");  }
         for( i = 0; i < prefs.length; i = i + 2 )
         {  this.setPref(prefs[i], prefs[i+1], lockLevel);  }
         break;
      default:
         throw("I don't know how to set multiple prefs with a " + trueTypeOf(prefs) );
   }
}

Download the full source

Scene from an upcoming post

I alluded to another purpose for this prototype and this is a glimpse of how I use it with Thunderbird in the real world.  Stay tuned.

   // Create an email account
   var brewingAccount = AccountManager.newAccount({ isDefault: true, type: "imap" });
 
   // Lock Preferences on the IMAP server
   brewingAccount.server.setPrefs({ capability: 81,
                                    hostname: "mail.example.com",
                                    port: 993,
                                    realhostname: "mail.example.com",
                                    realusername: brewingMail,
                                    remember_password: false,
                                    socketType: 3,
                                    type: "imap",
                                    userName: brewingMail }, "lock" );
   // Default Preferences
   brewingAccount.server.setPrefs({ check_new_mail: true,
                                    check_time: 10,
                                    cleanup_inbox_on_exit: true,
                                    delete_model: 1,   /* Move to trash */
                                    directory: userInfo.env_home + "/Mail",
                                    "directory-rel": "[ProfD]../../Mail",
                                    empty_trash_on_exit: false,
                                    empty_trash_threshhold: 0,
                                    name: "Brewing Mail",
                                    login_at_startup: true,
                                    using_subscription: false });
 
  // Lock Preferences on the SMTP server
  brewingAccount.smtpServer.setPrefs({ auth_method: 1,    /* User/pass */
                                       port: 465,
                                       username: brewingMail }, "lock" );
  // Default Preferences
  brewingAccount.smtpServer.setPrefs({ description: "Brewing SMTP server",
                                       hostname: "mail.example.com",
                                       try_ssl: 3 });

The source

/**
   By Dean Brundage
   Originally published here:
     http://blog.deanandadie.net/2010/05/manufacturing-user-preferences-for-mcd/
 
   Mix-in prototype for other objects that want to set defaultPref, lockPref
     or just plain old pref().
   Use the utility function copyPrototype() to copy this object's prototype
     functions to other objects.  This can also be used as a stand-alone object.
     Pass the prefix string to the constructor
   Example [mix-in]:
      function Mail.Server()
      {  // It's very important to update the object's preference path
         this.Mail();
         this.addPrefBranch("server");
         // Continue to define Mail.Server
      }
      copyPrototype(Mail.Server, PreferenceFactory);
      // Define the rest of Mail.Server's prototypes
 
      // Then you can set preferences on your Mail.Server object
      myServer = new Mail.Server();
      myServer.setPref("type", "imap", "lock");  // Lock the type of server to IMAP
 
   Example [stand-alone]:
      var prefFact = new PreferenceFactory( ["mail", "accountmanager"] );
      prefFact.setPref("localfoldersserver", "server2" );
 
*/
function PreferenceFactory(arg)
{  this.prefNodes = [];
   this.prefBranch = "";
   if(arg)
      this.addPrefBranch(arg);
}
 
 
// Add a string or many strings to the preference branch
PreferenceFactory.prototype.addPrefBranch = function(nodes)
{  switch( trueTypeOf(nodes) )
   {  case "String":
         this.prefNodes.push(nodes);
         break;
      case "Array":
         for( i = 0; i < nodes.length; i++ )
            this.prefNodes.push(nodes[i]);
         break;
      default:
         throw("Don't know how to addPrefBranch for a " + trueTypeOf(nodes));
         break;
   }
   this.prefBranch = this.prefNodes.join(".");
}
 
 
PreferenceFactory.prototype.defaultPref = function(key,value)
{  if( key )
      defaultPref( this.prefBranch + "." + key, value );
}
 
 
PreferenceFactory.prototype.getPref = function(key)
{  if( key )
      getPref( this.prefBranch + "." + key );
}
 
 
PreferenceFactory.prototype.lockPref = function(key,value)
{  if( key )
      lockPref( this.prefBranch + "." + key, value );
}
 
 
PreferenceFactory.prototype.pref = function(key,value)
{  if( key )
      pref( this.prefBranch + "." + key, value );
}
 
 
/*
   Preference setting helper function
   myServer.setPref("type", "imap", "lock");
   Arguments
     key: The preference string to set
     value: Value to assign to key
     lockLevel: Locking level.
            Valid values are "default", "lock" and "pref"
            Default level is "defulat"
*/
PreferenceFactory.prototype.setPref = function(key,value,lockLevel)
{  if( lockLevel )
   {  switch(lockLevel.toLowerCase())
      {  case "default":
            this.defaultPref(key,value);
            break;
         case "lock":
            this.lockPref(key,value);
            break;
         case "pref":
            this.pref(key,value);
            break;
         default:
            throw("Unrecognized locking level: " + lockLevel );
      }
   } else
   {  this.defaultPref(key,value);  }
}
 
 
/* Sets multiple preferences
   Accepts an array or object "hash" and an optional locking level
*/
PreferenceFactory.prototype.setPrefs = function(prefs,lockLevel)
{  switch( trueTypeOf(prefs) )
   {  case "Object":
         for( thing in prefs )
         {  this.setPref(thing, prefs[thing], lockLevel);  }
         break;
      case "Array":
         if( prefs.length % 2 != 0 )
         {  throw("Need an even number of strings to set multiple preferences with an array");  }
         for( i = 0; i < prefs.length; i = i + 2 )
         {  this.setPref(prefs[i], prefs[i+1], lockLevel);  }
         break;
      default:
         throw("I don't know how to set multiple prefs with a " + trueTypeOf(prefs) );
   }
}
 
function trueTypeOf(something)
{  // Borrowed from jsUnitCore.js.  Thank you.
   // http://github.com/pivotal/jsunit/blob/master/app/jsUnitCore.js
   var result = typeof something;
   try
   {  switch (result)
      {  case 'string':
            break;
         case 'boolean':
            break;
         case 'number':
            break;
         case 'object':
         case 'function':
            switch (something.constructor)
            {  case new String().constructor:
                        result = 'String';
                        break;
               case new Boolean().constructor:
                        result = 'Boolean';
                        break;
               case new Number().constructor:
                        result = 'Number';
                        break;
               case new Array().constructor:
                        result = 'Array';
                        break;
               case new RegExp().constructor:
                        result = 'RegExp';
                        break;
               case new Date().constructor:
                        result = 'Date';
                        break;
               case Function:
                        result = 'Function';
                        break;
               default:
                  var m = something.constructor.toString().match(/function\s*([^( ]+)\(/);
                  if (m)
                     result = m[1];
                  else
                     break;
            }
            break;
      }
   }
   finally
   {  result = result.substr(0, 1).toUpperCase() + result.substr(1);
      return result;
   }
}

Things Adrienne & Dean Do, Think and Write