Sunday 18 December 2011

The Very Simple JavaScript Formula Class

A small Javascript program I wrote a while back but didn't get round to releasing until now.

The Very Simple JavaScript Formula class takes a simple string of characters written with a standard keyboard and translates it into HTML code that attempts to visually represent the mathematical notation. The purpose of this class is to make maths on the web easier to write, display and understand - users won't need to learn LaTeX or other markup languages or use desktop/server-side applications to create visual Formulas. All you need to do now is type the formula and VSJSFormula will display the rendered formula. The source code is at:
http://code.google.com/p/vsjsformula/

Friday 11 November 2011

Phenotype Ontology search resources

I just spent a while looking for these so I thought I'd share my findings.

This is a list of website URI's associated with ontologies, mouse/mammalian phenotype ontology term ids specifically. Where I couldn't find a specific website that shows the details of the ontology, I used the EBI's general ontology lookup search.

For each of the term types, replace the %s with a full term id like MP:0010053. You can use the sprintf() function to do this :-).

MP:
http://www.informatics.jax.org/searches/Phat.cgi?id=%s
BSPO:
http://www.ebi.ac.uk/ontology-lookup/?termId=%s
CHEBI:
http://www.ebi.ac.uk/chebi/searchId.do?chebiId=%s
CL:
http://www.ebi.ac.uk/ontology-lookup/?termId=%s
ENVO:
http://www.ebi.ac.uk/ontology-lookup/?termId=%s
GO:
http://amigo.geneontology.org/cgi-bin/amigo/term_details?term=%s
IMR:
http://www.ebi.ac.uk/ontology-lookup/?termId=%s
MA:
http://www.informatics.jax.org/searches/AMA.cgi?id=%s
PATO:
http://www.ebi.ac.uk/ontology-lookup/?termId=%s

Friday 4 November 2011

Quick JQuery expanding vertical menu

I'm just posting this as a reference for myself primarily, but if it helps anyone else then that's great. This is a super quick expanding vertical menu. You can animate it by passing 'slow' or 'fast' as an argument to the toggle() method.

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
    $('.branch').click(function(){
        $(this).children('.subbranch').each(function(){
            return $(this).toggle();
        });
    });
});
</script>


<ul class='tree'>
<li class='branch'><a href='#'>Super Title 1</a>
<ul class='subbranch' style='display:none'>
    <li><a href="#">Item 1</a></li>
    <li><a href="#">Item 2</a></li>
    <li><a href="#">Item 3</a></li>
</ul></li>
<li class='branch'><a href='#'>Super Title 2</a>
<ul class='subbranch' style='display:none'>
    <li><a href="#">Item 4</a></li>
    <li><a href="#">Item 5</a></li>
    <li><a href="#">Item 6</a></li>
</ul></li>
</ul>

Thursday 13 October 2011

New Largest Virus Discovered

The largest virus yet discovered has been isolated from ocean water pulled up off the coast of Chile.
Called Megavirus chilensis, it is 10 to 20 times wider than the average virus.
It just beats the previous record holder, Mimivirus, which was found in a water cooling tower in the UK in 1992.
Scientists tell the journal PNAS that Megavirus probably infects amoebas, single-celled organisms that are floating free in the sea.
The particle measures about 0.7 micrometres (thousandths of a millimetre) in diameter.
"It is bigger than some bacteria," explained Prof Jean-Michel Claverie, from Aix-Marseille University, Marseille, France.
"You don't need an electron microscope to see it; you can see it with an ordinary light microscope," he told BBC News.
Viruses cannot copy themselves; they need to invade a host cell if they want to replicate.
Like Mimivirus, Megavirus has hair-like structures, or fibrils, on the exterior of its shell, or capsid, that probably attract unsuspecting amoebas looking to prey on bacteria displaying similar features.
A study of the giant virus's DNA shows it to have more than a thousand genes, the biochemical instructions it uses to build the systems it requires to replicate once inside its host.
In the lab experiments conducted by Professor Claverie and colleagues, in which they infected fresh-water amoebas, Megavirus was seen to construct large trojan organelles - the "cells within cells" that would produce new viruses to infect other amoebas.
"Everything is initiated from a single particle, and then grows and grows to become this virion factory," explained Prof Claverie. "That's why it needs all these genes."
Megavirus was found off the coast of Las Cruces, central Chile. It was recovered as part of a general trawl in the ocean for biology of interest.
"This is a new way of doing virology," said Prof Claverie.
"Previously, we only discovered viruses because they caused disease in humans, or animals and plants. But now we are initiating what might be called environmental virology and we are looking for viruses everywhere.
"You just go to lakes, seas and oceans and pick up the water, and then you filter it, and try to rescue the virus by co-cultivating it with some potential host."
More generally, there is interest in ocean viruses because they have a major influence on populations of plankton, the microscopic organisms that form the base of many marine food chains. And when they kill plankton, viruses are also helping to regulate the planet's geochemical cycles as the dead organisms sink into the deep, locking away their carbon for aeons.

http://www.bbc.co.uk/news/science-environment-15242386

Friday 26 August 2011

Copying radio button values to a group of radio buttons

My javascript is a little rusty and I've just spent a few hours trying to solve this problem: How do you copy the checked value of a radio button to a set/group of radio buttons?

I have this radio button group as the master group, the one that when I change what's checked I want it to modify the rest of the other set of radio buttons when a button was clicked:

<input type="radio" name="master" value="1"> Yes
<input type="radio" name="master" value="0"> No
<input type="radio" name="master" value=""> --
<input type="button" name="radiocopy" onclick="copydown()" value="Change All" ></button>

And the other groups are found in some rows of data and one of the columns requires a choice to be made: Yes, No, or missing.

<input type="radio" name="slaveRow1" value="1"> Yes
<input type="radio" name="slaveRow1" value="0"> No
<input type="radio" name="slaveRow1" value=""> --

<input type="radio" name="slaveRow2" value="1"> Yes
<input type="radio" name="slaveRow2" value="0"> No
<input type="radio" name="slaveRow2" value=""> --

<input type="radio" name="slaveRow3" value="1"> Yes
<input type="radio" name="slaveRow3" value="0"> No
<input type="radio" name="slaveRow3" value=""> --

Now what I wanted was that when I set the master to Yes, the rest of the radio buttons would change to Yes as well when I click the Change All button. Here's what I wrote:

function copydown(){
    var fm = document.forms["thenameofyourform"];

    //find out which master radio button is checked and assign value to masterValue
    var masterValue = null;
    for(i = 0; i < fm.elements['master'].length; i++){
        if(fm.elements['master'][i].checked == true)
            masterValue = fm.elements['master'][i].value;
    }

    //loop through all the form elements in the page
    for(i = 0; i < fm.elements.length; i++){
        //select only the radio buttons
        if( fm.elements[i].type == "radio" && fm.elements[i].name.indexOf("slaveRow") != -1){
            //check the value of each slave radio button and if it matches the
            //checked value of the master then check it
            if(fm.elements[i].value == masterValue)
                fm.elements[i].checked = true;
        }
    }
}

That seemed to do the trick. I must admit my Javascript is rusty. If you don't want to implement this with a button you can add a listener to the master radio buttons group.

Monday 8 August 2011

Enums in PHP and Java

This is mainly for my personal reference. Enums are quite useful to use in projects and save typing and make sure Strings/Integers match, because it's not uncommon that, for example, you type "list" instead of the expected word "List" or misspell things and other such tirivial issues.

PHP:

<?php

//PHP has no native Enum type so you need to manipulate
//a normal class to work how you want it to
final class Season
{
    //class constants are inherantly public and static
    const SPRING = 'Spring';
    const SUMMER = 'Summer';
    const AUTUMN = 'Autumn';
    const WINTER = 'Winter';

    public function __toString()
    {
        //default return
        return self::SPRING;
    }
}

//Test the enum... prints out Spring.
echo ( new Season() );
//And if I wanted to choose just Summer
echo Season::SUMMER;


Java:

public enum Season {
    //define the values
    SPRING, SUMMER, AUTUMN, WINTER;
   
    //for extra useability have it return a string of the chosen enum when needed
    @Override
    public String toString(){
        switch(this){
            case SPRING: return "Spring";
            case SUMMER: return "Summer";
            case AUTUMN: return "Autumn";
            case WINTER: return "Winter";
            default: return "Spring";
        }
    }
}

//usage - prints out Summer
System.out.println( Season.SUMMER );

Friday 29 July 2011

String DB

RAS, RAF, MEK, MAPK... or something like that. That's what I remember as being the chain of gene activation to activate an oncogene leading to cancer (P53 getting its ass kicked) . No I can't remember the details but these activation/interactions form a tree of what gene up or downregulates the function of another and it's quite a complicated part of genetics and bioinformatics. But I found a website recently that I hadn't seen before and thought of sharing it because apart from getting a nice little description of what the gene does in different species, it has nice spider diagrams like this showing gene relationships:





http://string-db.org/
A search example, PAX6: http://string-db.org/newstring_cgi/show_network_section.pl?caller_identity=expasy_api&identifier=pax6
If you click continue at the bottom of that page you see the diagram.

Wednesday 13 July 2011

Ladybird vs. Aphid.... vs. Spider?

I thought Ladybirds ate Aphids and kept their population down. But apparently that isn't the whole truth! Check this out:



I don't know about you but I really do wonder if this is at all true. The roles of both the spider and the Ladybird seem so passive. I reckon there's something missing in the equation.

http://www.bbc.co.uk/nature/life/Coccinella_septempunctata#p0039ryj

Tuesday 5 July 2011

Belly button fluff - bacterial haven


The human navel should be designated as a bacterial nature reserve, it seems. The first round of DNA results from the Belly Button Biodiversity project are in, and the 95 samples that have so far been analysed have turned up a whopping total of more than 1400 bacterial strains. In 662 cases, the microbes could not even be classified to family, "which strongly suggests that they are new to science", says team leader Jiri Hulcr of North Carolina State University in Raleigh.

The project was conceived as a light-hearted exercise in science communication, but is making a serious contribution to the understanding of microbial diversity. Since New Scientist wrote about the initiative in April, samples of bacteria taken when volunteers swabbed their navels with Q-tips have had their "DNA barcodes" read by sequencing the gene for 16S ribosomal RNA, widely used in studies of bacterial evolutionary relationships.

My own sample was among 10 per cent of those in the first round in which reactions to amplify the DNA present failed - so the next installment of the comparison of my belly button biome with that of fellow science writer Carl Zimmer will have to wait for another day. Still, Zimmer has already been having some fun with his results, finding among other things that his belly button hosts Georgenia bacteria, previously found in Asian soils.

Results like this reflect our ignorance of microbial diversity, Hulcr suggests: the inhabitants of our navels seem weird because biologists haven't sampled sufficiently extensively to document the full diversity of microbial life in a variety of habitats. He likens reactions to the first round of belly button results to the astonishment of the first European explorers seeing African big game - which today seem commonplace. "Now you're expecting rhino and elephants," Hulcr says.

Also, identifying bacteria to species is difficult. Noah Fierer's team at the University of Colorado, Boulder, classified them into "operational taxonomic units" having 16S ribosomal RNA gene sequences that differed by 3 per cent or less. Apply this standard to mammals, Hulcr explains, and dogs and cats would be lumped together. It means that a "match" between a belly button strain and a species known from the deep ocean, for instance, may actually represent two microbes separated by several million years of divergent evolution.

Although the total number of strains recorded was large, the results so far indicate that a small group of about 40 species accounts for around 80 per cent of the bacterial populations of our belly buttons. "It is tempting to think of the abundant species as the good, core biome of bacteria and the rare ones as transients, struggling to take hold, sometimes at our expense," says Rob Dunn, author of The Wild Life of Our Bodies, and head of the lab in which Hulcr works.

Confirming that theory will require studies on a new scientific frontier: belly button ecology.

Source: http://www.newscientist.com/blogs/shortsharpscience/2011/06/peter-aldhous-san-francisco-bu.html
Also see: http://idle.slashdot.org/story/09/03/02/1742219/Science-Unlocks-The-Mystery-Of-Belly-Button-Lint

Saturday 25 June 2011

Loading CSS, JS and images from CodeIgniter

Just a quick tip for newbs (me included). If you're having trouble loading css, js or image files into your views/templates in CodeIgniter and you do a Google search to find the solution, you'll find many websites telling you to use the base_url() function. This didn't work for me!

The reason why it didn't work was because I hadn't loaded the url helper class... DUH! Stick this in the constructor of your controller or autoload it in your autoload.php configuration file.

$this->load->helper('url');

Now you can use the base_url() function to get the url path from where to look for those files, e.g.:

<link rel="stylesheet" href="<?php echo base_url(); ?>styles/main.css" type="text/css">

This will load a css file called main.css from a folder called styles which is just under the base url folder codeigniter. On my PC it will find the file from: C:\wamp\www\codeigniter\styles\main.css

I reckon the creators of CodeIgniter should have added a constant through which to refer to the base_url and similar paths, or at least make the url class have static functions so url::base_url() can be called instead of base_url() which could be confused for a normal PHP function.

Friday 10 June 2011

That's one wierd looking bear - The water bear (Tardigrade)

Check out this stunning photo:

In 2007, a little known creature called a tardigrade became the first animal to survive exposure to space.
It prevailed over sub-zero temperatures, unrelenting solar winds and an oxygen-deprived space vacuum.
On Monday, this microscopic cosmonaut has once again hitched a ride into space on the Nasa shuttle Endeavour.
Its mission: to help scientists understand more about how this so-called "hardiest animal on Earth" can survive for short periods off it.

More: http://www.bbc.co.uk/nature/12855775

Thursday 5 May 2011

Unset function in Javascript

Here's my version of an occasionally required function, Unset(). I wrote this before I found the version on phpjs.org so I thought I might as well publish it online because it's easier to make sense of than the one they wrote.

To briefly explain how it works:

There are three different things that you might want to "unset" in javascript - 1. Individual array elements, 2. a property of an object (which could be a variable, function or an object) and 3. a normal variable, which actually may hold a simple value like 1 or more complex items like an array or an object reference/definition. Each one of these different types of variable are unset in a different way:

1. myarray.splice(index,1);
myarray is the name of an array. index is the index number of the item in the array starting from 0. And the second argument (1), is the number of items to splice/cut out of the array.

2. delete myclass.myproperty;
This simply deletes the variable myproperty from the object myclass. Of course, in javascript, myproperty could contain a simple value, a method or an object.

3. myvar = undefined;
If I've previously defined a variable like so: var myvar = "hello"; then I can undefine it by setting it to the javascript equivalent of null which is "undefined". You can also unset a whole array/object using the same command.

Anyway, here's my general purpose javascript unset() function:

/**
* Unset variables, objects, array elements and object 
* properties in Javascript much like you can in PHP
* @author Ahmad Retha
* @license Public Domain
*/
function unset()
{
    for(var _i = 0; _i < unset.arguments.length; _i++){
        //where item to unset is an array element (var[index])
        if(_m = unset.arguments[_i].match(/(\w+)\[(\d+)\]/)){
            eval(_m[1] + ".splice(" + _m[2] + ", 1);");
        //where item to unset is an object item
        }else if(unset.arguments[_i].match('.')){
            eval("delete " + unset.arguments[_i] + ";");
        //where item to unset is a normal variable
        }else{
            eval(unset.arguments[_i] + " = undefined;");
        }
    }
}

You pass the names of the variables, classes, elements of arrays and object properties as strings and it removes them. You can pass as many arguments to the unset() function as you like. Usage example:

var x = 1;
var y = ['a','b','c'];
var z = {'one':1, 'two':2, 'three':3};

unset("x", "y[1]", "z.three");

Variable x is now undefined. Array y now holds two elements, a and c. Class z is now an object with two properties.

Friday 29 April 2011

Javascript using PHP functions

Ever wanted to use functions easily available in the PHP library but with Javascript?

I found a new project called the PHP-JS project and it's pretty cool. They have covered most of the PHP functions and written some really good Javascript. The other day I needed a snippet of Javascript code to Uppercase the first letters of new words, which is the ucwords() function in PHP. Here's their code:

function ucwords (str) {
    return (str + '').replace(/^([a-z])|\s+([a-z])/g, function ($1) {
        return $1.toUpperCase();
    });
}

So to use it I write:

//Capitalizes the words to 'The Cat Sat On The Mat'
alert( ucwords('the cat sat on the mat') );

Nice. Visit the site at http://www.phpjs.org/.

Saturday 23 April 2011

PHP array to Javascript array format

Just been messing around with ajax and a particular jQuery plugin... The easiest way to convert a PHP array to a Javascript array is to use the json_encode() function (PHP 5.2+).

<?php 
echo json_encode(array("One","Two","Three"));
?>

This will output the Javascript array notation:

["One","Two","Three"]

If I use an ordered map array like this:

<?php 
echo json_encode(array("1"=>"One","2"=>"Two","3"=>"Three"));
?>


It will convert it to a Javascript object:

{"1":"One","2":"Two","3":"Three"}

Monday 4 April 2011

Bacteriophages and... introducing Virophages

Bacteriophages are viruses that infect/kill bacteria as part of their natural programming. Just like a typical viral infection may give you a sore throat, using a mechanism of infecting the cells in your throat by inserting RNA/DNA into your cells causing your body's immune system to fight back by killing the infected cells - bacteriophages infect bacteria and make them produce more of its viral clones and/or they end up killing the bacteria they infect.

We've known about bacteriophages for a long time and today we use them to insert genetically engineered fragments of DNA into cells so they start expressing the new genes. This is standard practice in genetics labs nowadays.

But up until 2 or 3 years ago we had not come across Virophages - a virus that infects another virus! How such a discovery managed to slip by silently without anyone making a big hoohah about it is crazy!

I'm only speculating that one application of gene therapy using virophages might be, and I haven't given this much thought, is to infect a genetically modified stalwart virus similar to HIV to continually produce a virus that carries a beneficial gene such as the CFTR-coding gene to help sufferers of systic fibrosis. You stick the infected virus into a human being and it starts creating the virus that carries the gene to cure the disease or at least to provide consistent and longer-lasting gene therapy.

The possibilities and applications of this discovery have great potential. Here's an article nature published a few days ago in which I first found out about virophages: http://www.nature.com/news/2011/110328/full/news.2011.188.html

As we're on the subject of microbes, I'd like to take the opportunity to publically complain about Leeds Central Library which has no books on bacteria in its catalogue! (unless they're hiding them somewhere!)

Wednesday 2 March 2011

Donate Stem Cells today!

It seems that my knowledge concerning stem cell donation is out of date, as I discovered today. I was under the impression that you had to have a surgical operation under full general anaesthetic to extract bone marrow containing stem cells from the Iliac crest of the hip bone... not any more!

All they need to do now is give you a jab with a stimulating factor so you start releasing the stem cells into your blood stream and then they harvest them from your blood. It's almost like blood platelet donation. Saving a life just became much easier. How awesome is that?!

You can talk to someone at your local blood donation centre about donating stem cells (and blood/platelets) or get in touch with the Anthony Nolan Trust. They came to our work place today and all I had to do was fill out a form and spit in a tube so that they could get a tissue (cheek cells) sample to match against their patient database. How easy is that!

Craig Venter talks about his synthetic bacterium and future plans on TED

Sunday 13 February 2011

How to reset/restart the position of a HTML5 audio clip

A simple google search didn't turn up with any direct results so this might be what you're looking for:

HTML:

<audio src="samples/brutaldeathmetal.mp3" id="audio" controls>


JavaScript:

var aud = document.getElementById('audio');
aud.addEventListener("ended", function(){
    this.currentTime = 0;
    this.pause();
});

What this does is it sets the playtime back to zero seconds when the audio clip ends.

Among the many javascript functions and properties of this tag you can use .play(), .pause(), .ended, .paused, and .duration to manipulate it. And you can even set the .currentTime property to a number within the range of your clip's playback duration (in seconds) to start midway through the clip if you wanted.

HTML5 Video and Fullscreen

I've just been experimenting with the HTML5 video tag and just realized that neither Google Chrome nor Opera allow you to fullscreen the video (OGG) but Mozilla Firefox does if you right-click the video and select Full Screen...

And what of Internet Explorer 8? It doesn't even render the CSS properly, let alone the video!

I found this great article that shows a code sample of how you would implement captions/subtitles/other based on the position in the video. Pretty cool no? http://randallagordon.com/blog/2009/07/19/jaraoke-html5-audio-tag-demo/

Thursday 10 February 2011

JQuery Hover Effect on Current, Previous and Next elements

I created this simple effect with JQuery and a little bit of CSS. What is does is if you move your mouse cursor over a link it calls the .hover() function and then it applies a class style using .addClass() to the element you hovered over with the mouse and in addition to this is applies a style to its adjacent neighbours using .next() and .prev() to select the links to which to apply the style.
 

The code is really simple. First off, you use a hover function. The first argument you pass to it is what to do when the mouse hovers over the element. I use .addClass() to apply a style to the element being hovered over ($(this)). The next argument to pass to the function is what to do when the mouse moves off the element and I use .removeClass() to reset the style of the element back to how it was. I encapsulate the arguments in anonymous functions.

In order to access the elements adjacent to that being selected you can use the .next() and .prev() functions, so if, for example, I had a list of 3 items and was hovering over the second one, I can use prev() to have access to the first element and next() to access the third element. When I move the mouse to highlight the first element, there is no previous element so it doesn't select anything to the left but the next element is still there and is accessible. If I highlight the third element then there is no next element so it only has the previous element to select.


Anyway, here's the javascript code:

$(document).ready(function(){
    $('a.link').hover(
        /*Carry this out when the mouse hovers over the element*/
        function(){
             $(this).addClass('bigger');
             $(this).next().addClass('big');
             $(this).prev().addClass('big');
        },
        /*Carry this out when the mouse moves off the element*/ 
        function(){
             $(this).removeClass('bigger');
             $(this).next().removeClass('big');
             $(this).prev().removeClass('big');
        }
    )
});

Now, the CSS to align the elements when the font size got bigger was not straightforward. One would assume that you need to use a combination of vertical-align:middle and display:table-cell or display:inline-block but these didn't do what I wanted. In the end I found the best way to solve the problem was to give the container element (div) a height and then use a large line-height, a large margin-top and text-align:bottom to allow the text to get bigger and not interfere with the content above or below it:

div {height:1.2in; width:100%; border:1px solid black;}
a {margin-top:50px; vertical-align:bottom; line-height:100px; text-decoration:none;}

You can download the code here: http://www.mediafire.com/?kydzwwl4bb4ogjk

And it's under the public domain license so you're free to do what you like with it.

Sunday 6 February 2011

Drupal error - warning: Cannot modify header information

Upon uploading my site from the local to the remote server an error (warning) was received when attempting to run update.php. If I ignored the warning and continued using the site I would get a blank white page every now and again on the administration pages although it did carry out the requested operation. I was having none of it and it was something that needed to be solved.

The error message I got:

warning: Cannot modify header information - headers already sent by (output started at /home/{username}/public_html/drupal/sites/all/modules/{modulename}/{modulename}.module:1) in /home/{username}/public_html/drupal/includes/common.inc on line 148.

It took a while to figure out what the problem was. The first thing to say is that the line and file number it says is causing the problem usually is the file and line number causing the problem. So I opened up the custom module I'd written and here was what it had in the first two lines:

<?php
// $Id$

Nothing strange about that. And there was no white space preceding the opening of the php code tag.

To cut a very boring story short, the problem turned out to be that I'd saved the file as UTF-8 and before the opening tag the text-editor had stuck in an invisible UTF-8 marker character which was being sent to the browser before the headers and thus causing the error.

The solution is to change the text file to ASCII (or ANSI as some text-editors call it) or find another way to remove that preceding character(s?) and if any preceding characters show up in the ASCII file then delete them and save the file.

Tuesday 18 January 2011

Buggy JavaScript Regex and parsing speeds in Firefox, Chrome, Opera and IE6

I was working on a little section of a small javascript application I'm writing when I came across this issue and I've decided it's worthy of documenting in the public domain.

The problem: This Javascript fragment of a regular expression replace statement requires exponential run-time to parse a string the longer it gets:

input.replace(/([^\s]+)*&radic;\{(.*?)\}/gi, '<sup>$1</sup>&radic;<span class="ol">$2</span>')

It replaces an example string - "&radic;{123}" - with this - "<sup></sup>&radic;<span class="ol">123</span>".

But with each additional character added inside the curly braces the time taken to replace it increases exponentially. I have 4 browsers installed on my system - Firefox 3.6.13, Google Chrome 5, Opera 11 and Internet Explorer 6. I haven't upgraded IE6 to the latest version because I use it to test how websites look for people using business/government computers whose technology department haven't upgraded the browsers in 10 years! (Shame on you!)

The results are surprising to say the least. The table and charts below show how long it took (in milliseconds) for each browser to parse a string with 1 to 20 characters inside the curly braces and output it to the screen.


 
Str Length Time FF Time CH Time OP Time IE6
1 5 0 0 0
2 5 1 0 0
3 5 0 0 0
4 6 1 0 0
5 8 1 0 0
6 12 1 0 0
7 19 1 0 0
8 33 3 0 0
9 60 5 0 0
10 115 8 0 0
11 224 17 0 0
12 448 35 0 15
13 892 71 0 0
14 1773 143 0 0
15 3544 286 0 15
16 7113 576 0 0
17 14167 1146 0 31
18 28356 2287 0 47
19 58691 4593 0 94
20 113196 9159 0 188




The results are very surprising. At 13 characters long, the browser suddenly starts becoming very slow and a pattern becomes apparent - that the time taken to execute the regex statement is taking exponentially longer.

IE6 only really starts doing this at 17+ characters but is, surprisingly, faster that both Firefox and Chrome! IE6 faster than Chrome! OMG! Oddly, IE6 spontaneously spikes to 15ms every now and again before reaching 17 characters whether 1 or 16 characters are entered.

Another thing to note is that Chrome is more than 10x faster at doing this than Firefox. The JagerMonkey needs to go on a JagerDiet.

What is even more surprising than that is that execution time in Opera is very close to 0ms and does not rise at all! In Opera this operation isn't exponential! I tested it with over 100 characters and performance in Opera is amazing going above no more than 1ms. (Much respect to the Opera Dev team and their Carakan engine!)

When I made this mistake I was really surprised why it took so long but quickly realised my mistake. I can't really explain what's going on under the hood of the regex engine (because I don't really know in that much detail) but I identified the bug in my regex and solved the problem, which is the single asterisk (*) highlighted:

input.replace(/([^\s]+)*&radic;\{(.*?)\}/gi, '<sup>$1</sup>&radic;<span class="ol">$2</span>')

and which should be replaced with a question mark to solve the problem.

input.replace(/([^\s]+)?&radic;\{(.*?)\}/gi, '<sup>$1</sup>&radic;<span class="ol">$2</span>')

What the regex code is doing, and don't blame me if I'm wrong - I'm no expert - is that when you use the * operator it checks to see if the pattern before it exists and it does this by trying to match the whole length of the string with the pattern [^\s] (which means any character but empty space) and then it reads the string one character at a time until it reaches the end and then it back tracks the length of the string to the beginning. It's a greedy operator which tries to find the longest possible matching string. After that, the rest of the regex is interpreted accordingly.

When you replace * with a ? it checks to see if there's anything before &radic; and if there isn't it simply moves on to carry out the rest of the regex. It only checks one character minimum before it moves on while using * checks the length of the string with each character it moves along. That's why using * becomes slow the longer the string gets.

I think the reason Opera is not affected by this coding bug is because their internal regex engine identifies the bug and realizes that it's stupid for the greedy operator to check the whole string when the next regex pattern after it matches instantly so internally it treats the * operator like a ? operator, thus reducing execution time. They have very clever people at Opera. Mozilla and Google should really think about incorporating this performance increasing technique into their own engines.

Saturday 8 January 2011

Dolly the sheep lives

...on through her clones.


Dolly the sheep has been reborn. Four clones have been made by the scientist behind the original research.
The quads, which have been nicknamed ‘the Dollies’, are exact genetic copies of their predecessor, who was put down seven years ago.

Wednesday 5 January 2011

SAS Macro functions and returning values and a bit about macro variable type casting

I wrote an article about this subject before but I was quite new to SAS and it was quite confusing so I'm writing it again better and clearer this time.

The SAS macro programming language is a strange language lacking data types we usually associate with strongly or even weakly typed programming languages. SAS macro variables are intrinsically treated as strings. The equivalent command for casting a type from one to another is an input() command. For example, if I have a string that contains the month and year (MMMYY), then I can convert it to a SAS date format like this:

%let mmmyy = JAN11;
%let datum = %sysfunc(input(&mmmyy., MONYY.)); 
*the second argument defines the format of the data (&mmmyy.) that you want to cast into SAS format. &datum. now holds the SAS date equivalent of 01/01/2011;

Datum now holds the SAS date format of the first of January 2011. SAS macro variable values like the integer date stored in datum are intrinsically stored as strings, so you can't just do anything with them. In order to treat them as an actual integer and do any mathematical operations on them you need to use eval() like so:

%let yesteryear = %eval(&datum. - 1); *holds the SAS date for 31/12/2010;

One problem often encountered with SAS macro variables is when working with dates. Often, people define a date like so:

%let bankholiday = "03JAN11"d;

This is acceptable, but if you try to do any mathematical operations using that variable outside of a data step it will throw an error message and literally show that you tried to carry out an operation on the string ' "03JAN11"d '. The best ways to convert such a date to the SAS date format is to use either intnx() or define the date using mdy():

%let bankholiday = %sysfunc(mdy(01, 03, 11));
or
%let bankholiday = %sysfunc((intnx(day, "03JAN11"d, 0)));

I've yet to figure out how to detect the type of the macro variable before I do anything with it, so I advise you to inform other programmers about the type of the variable your code works with before you let someone else use your code.

Now. When it comes to macro functions, SAS also proves to be strange when compared to other languages. What is a very natural and normal way of working in a procedural/Object Oriented language appears to be missing in SAS. I've yet to see an official documented example that shows a macro returning a value, but it is possible. I doubt I'm the first person to discover or use this method.

What is odd about macro functions that return values is that you should NEVER use single line comments inside the body of the macro otherwise it throws an error! Always use the multi-line comments like /* this comment */. And there is no "return" command preceding the variable to make it return but there is a %return statement and all this does is stop the execution of the rest of the code and jump out of the macro. The way to return a value is to just write the the name of the variable holding the value you wish to return, without a semicolon on the end.

Anyway. Here's an example bit of code that lets you ask if a date is a weekend or not. If it is a weekend it returns 1 else it returns 0.

/**
* %isWeekend(datum)
* Tells you if a date is a weekend or not by returning 1 (true) or 0 (false). If you leave it empty it will check todays date.
* Usage:
%let datum = %sysfunc(mdy(01,01,2011));
%put %isWeekend(&datum.); *shows 1 (true);
*
* @return    boolean    If the date you supplied is a weekend it will return 1, otherwise 0.
* @param    date    date    The date you want to check. If you leave this empty it will use todays date
* @date 20110105
* @author Ahmad Retha
**/

%macro isWeekend(date);
    %if date=  %then %do;
        %let date = %sysfunc(today());
    %end;

    %let wd = %sysfunc(weekday(&date.)) ; /*find the weekday of the date given. Sunday=1, Saturday=7*/

    %let iwe = 0; /*set the variable we wish to retune to 0 (false) initially*/
    %if &wd.=1 or &wd.=7 %then %do;
        %let iwe = 1;
    %end;

    /* return iwe (1 or 0) */
    &iwe.
%mend;


Allow me to explain what this code does. The first part of the code, the %if statement, checks to see if a date argument was supplied and if it isn't it uses today's date. This behaviour of setting an empty parameter to a default value makes our macro function more robust and easy to use - it is a recommended practice.

The next section assigns the weekday, Sunday, Monday, Tuesday through to Saturday to the variable &wd. as a number from 1 to 7, as there are 7 days in a week. In SAS, the week starts on Sunday, 1, and ends on Saturday, 7.

Next we create a macro variable, iwe, which holds the value we wish to to return. We want to return 1 (true) if the date is a weekend, or 0 (false) if it's not. Initially we set the value to 0 (false) as most days of the week return false.

The next part checks if the weekday is Sunday (1) or Saturday(7) and if the date's day is a weekend it sets iwe to 1 (true). If it's not a weekend then iwe already holds 0 (false).

Finally, we return the value held in iwe (either 1 or 0) by just writing the variable &iwe. by itself - note that you should NOT put a semicolon on the end otherwise it will throw an error. There is no "return" command - just put the variable name on a line of its own.

That's it. Easy right?

You can write many really useful macro functions that you will use often and stick them into a file and make a library of useful functions to %include and use in your projects. For example, for my job I wrote a macro called %isWeekend(date), like the one above (though as I'm writing this from home I couldn't just copy and paste and I wrote the above on the fly from memory), another macro called %getNext(day) which returns the date of the next weekday you give it, %getLast(day) which is similar but looks backwards, %isHoliday(date) and %getLastWorkday(date). I stuck those into a SAS file, a library, and now include it into my other scripts when I need the functionality. This approach promotes code re-use and makes coding quicker and easier and as there is less duplicate code it is easier to maintain. Naturally, all my code is highly documented and I recommend you comment up your code as well.

I hope this little tutorial proves useful.

- Ahmad Retha