Sunday, October 14, 2012

Getting Putty to Work with Byobu

I often times use Ubuntu Linux, and because I use the command line extensively, as is true of many Linux users, I want a way to keep my command line programs running even when I log out or close my terminal.  Of course the hold fashioned UNIX way to do this was to use nohup.  But there have been leaps and bounds since about 25 years ago.
When I was introduced to screen about 5 years ago I found what I was looking for.  The ability to run multiple shells with multiple command line programs in a single terminal session that stays persistent.  So even if I log out, when I come back, all my programs are running just as they were when I left them.  Hopefully in the case of running jobs, they have completed when I get back.  I can leave a program compiling overnight, come back in the morning, and find the output ready for me--all the gcc errors in their glory.
Byobu is a wrapper on top of screen (and a couple additional options) that gives you more cool stuff you can do.  The problem is that I wanted to use it with PuTTY from a Windows machine and it uses the F keys as shortcuts.  In putty you simply have to select the Xterm R6 radio in the Terminal -> Keyboard part of the PuTTY session preferences.  That fixes it.

Sunday, October 7, 2012

Fun With Roots

I was recently investigating the graph of the cubic root function.  Someone I know that is taking a business calculus class believed their professor have wrongly plotted the graph of the cubic root function.  Their calculator did not define the cubic root function for negative numbers, and this professor had drawn the function as defined for those numbers.  As it turns out the answer is interesting, and involves the very important Fundamental Theorem of Algebra by Gauss.
A consequence of the fundamental theorem is that all nth roots have n answers.  So there are 2 possible answers for the square, or 2nd, root; \(\sqrt{4}\) namely 2, and -2, since \(2^2 = 4\) and \((-2)^2 = 4\).  In the case of the cubic, or 3rd, root there would be three possible answers.
\begin{array}{lcl}
\sqrt[3]{-8} & = & -2 \\
 & = & i\sqrt{3} + 1 \\
 & = & i\sqrt{3} - 1
\end{array}
What is striking is that
\begin{array}{lcl}
|-2| & = & 2 \\
|i\sqrt{3} + 1| & = \\
|i\sqrt{3} - 1| & =
\end{array}
And so the roots form a circle of radius 2 around the origin of the complex plane.  The same is true of the nth roots of any given x; they will all have the same absolute value.  This demonstrates a very interesting symmetry among the nth natural number roots of any given x on the complex plane.  There will be n of them, and they will be the same distance from the origin.


It will be noted that one of the roots lies on the real axis above.  The same will be true for any odd numbered root of a real--there will always be at least one real root.  So one of the cube roots of x is real for any real x, and the function is defined for that x.  But it is also true that there are complex roots too.  As it turns out, both he and the professor were right.  Sadly the calculator didn't specify there is more to roots than meets the eye.

Tuesday, September 25, 2012

Statistical Distribution Fitter

This particular code is modified source from the pyeq2.  pyeq2 provides the backend that powers the ZunZun curve fitting site.  It's a fantastic site; a rather unique one which delivers well fitted curves for a given data set, fit statistics, and inspiring Bible quotes all together. Taking the code statistical distribution fitting code I was able to free this fragment, and made some improvements for debugging purposes.
Fitting distributions to data points is a common operation for me, because I commonly analyze data from different sources, apply wavelet filtering and so on.  Frequently I find myself in need of fitting a distribution to a given data set, I don't want to bog down ZunZun with requests.  Future improvements might include computing the K-S statistic along with the AIC criteria that is computed below.  Implementers may want to check the exec line and ensure that the scipy.statistics module is loaded under the alias spst.  Else the source line can be changed to match the requirements.

Statistical Distribution Fitter Code

# directly passing the distribution instance can yield "can't pickle instancemethod"
# exceptions, so the distribution name is passed instead
def SolveStatisticalDistribution(distributionName, data, inCriteriaForUseInListSorting):
    criteriaList = ['AIC', 'AICc_BA', 'nnlf']
    if inCriteriaForUseInListSorting not in criteriaList:
        raise Exception('Criteria to calculate for use in sorting was not in', str(criteriaList))

    try:
        exec('distribution = spst.' + distributionName)
    except:
        print 'Unable to find distribution, %s!' % distributionName
        return 0

    # only need to calculate these once
    eps = np.finfo(float).eps * 2.0
    data_min = data.min()
    data_max = data.max()
    data_mean = data.mean()
    data_range = data_max - data_min
    data_std_dev = np.std(data, dtype=np.float32) # note on precision http://docs.scipy.org/doc/np/reference/generated/np.std.html        
    
        
    # Try different starting parameters
    best_nnlf = 1.0E300
    best_parameters = None

    if distribution.name in ['beta']:
        try:
            rangeData = (data - data_min) / data_range
            data_mean = rangeData.mean()
            data_var = rangeData.var()
            
            par_a = data_mean * ((data_mean * (1.0 - data_mean) / data_var) - 1.0)
            par_b = (1.0 - data_mean) * ((data_mean * (1.0 - data_mean) / data_var) - 1.0)
            par0 = (par_a, par_b, data_min - 0.001*data_min, data_range * 1.001)
            par_est = tuple(distribution.fit(data, *(par0[:-2]), loc = data_min - 0.01*data_min, scale = data_range * 1.01))
            nnlf = distribution.nnlf(par_est, data)
            if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
                best_parameters = par_est
                best_nnlf = nnlf
        except:
            print 'Failure fitting a beta!'

    if distribution.name in ['truncnorm','betaprime','reciprocal']:
        try:
            par0 = (data_mean-2.0*data_std_dev, data_mean+2.0*data_std_dev)
            par_est = tuple(distribution.fit(data, loc=data_mean, scale=data_std_dev, *par0))
            nnlf = distribution.nnlf(par_est, data)
            if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
                best_parameters = par_est
                best_nnlf = nnlf
        except:
            print 'Failure fitting a trunk norm!'
        
    try:
        par_est = tuple(distribution.fit(data))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure fitting no values!'

    try:
        par_est = tuple(distribution.fit(data, loc=0.0, scale=1.0))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure to fit location and scale at default!'
        
    try:
        par_est = tuple(distribution.fit(data, loc=data_mean, scale=data_std_dev))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure fitting with mean as location and std as scale!'

    try:
        par_est = tuple(distribution.fit(data, loc=data_max+eps, scale=data_std_dev))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure fitting a +max eps over std!'

    try:
        par_est = tuple(distribution.fit(data, loc=data_min-eps, scale=data_std_dev))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure fitting a min-eps over std!'

    try:
        par_est = tuple(distribution.fit(data, loc=data_max+eps, scale=data_range))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure fitting a +eps over range!'

    try:
        par_est = tuple(distribution.fit(data, loc=data_min-eps, scale=data_range))
        nnlf = distribution.nnlf(par_est, data)
        if np.isfinite(nnlf) and nnlf < best_nnlf and nnlf > 0.0:
            best_parameters = par_est
            best_nnlf = nnlf
    except:
        print 'Failure fitting a -min-eps over range!'

    if (best_nnlf < 1.0E300) and (best_parameters is not None):
        try:
            k = len(best_parameters)
            AIC = 2.0*k + 2.0 * best_nnlf
            n = len(data)
            AICc_BA = AIC + ( (2.0 * k * (k+1.0)) / (n - k - 1.0))

            temp = {}
            temp['distributionName'] = distributionName
            temp['fittedParameters'] = best_parameters
            temp['nnlf'] = best_nnlf
            temp['AIC'] = AIC
            temp['AICc_BA'] = AICc_BA
            
            if inCriteriaForUseInListSorting == 'nnlf':
                return [best_nnlf, temp]
            elif inCriteriaForUseInListSorting == 'AIC':
                return (AIC, temp)
            else:
                return (AICc_BA, temp)
        except:
            print 'Exception in final calculations!'
    else:
        print 'Failed to find best parameters!'
        return 0

Wednesday, September 19, 2012

After Transistors, Memristors

In the late 1940's pioneering work by John Bardeen and Walter Brattain at Bell Labs led to the creation of an electronic component that changed the landscape of the future.  This component is fundamental to nearly all electronic devices in existence today.  It lead to cheaper and more efficient devices, integrated circuits in the 1970's, and eventually modern computers where they are still used.  This device was the transistor.
Thirty years later in the 1970's, still another device was conceived by Leon Chua.  The device related magnetic flux linkage to electric charge.  It's inventor claims it's the oldest known circuit element, and predate the resistor, capacitor and inductor.  The element has the remarkable property that current flowing in one direction increases its resistance, where current flowing the opposite direction decreases it.  The name of this device is the memristor.  Memristor's weren't even physically built until 2008.
Neuromorphic computing is an attempt to mimic biological neurons with electronic devices.  Scientists and engineers seeking to build neuromorphic systems are very interested in the device because of its base property.  Here's why.  Take any neural sensory preceptor (pressure, taste, etc) it produces a response that begins to diminish over time.  In other words, when you first apply pressure to your skin you feel it right away, but if you continue to apply constant pressure, the feeling diminishes.  This is called training.
Now imagine a electronic pressure sensor that produces a current when you apply pressure to it.  Placing a memristor wired into the circuit that is oriented so that it's resistance increases over time when a current is applied decreases the output current over time.  This simulates the diminishing of the response to the stimulus.  In other words, it is an electronic analog of training a neuron.
The memristor can also be wired in reverse to train for reinforcing behaviour as well.  By arranging memristors in a pattern and applying different inputs with positive and negative reinforcement in combination along with using ordinary resistors to apply weighting to the inputs, it can already be seen what a powerful building block we have.  Given the combination memristors, resistors, and economy of scale, it is certainly possible to have powerful problem solving, and maybe even sentient, neuromorphic systems.  Especially when you consider that there are billions of transistors on a modern commercial processor.

The Real Chemistry of Glowsticks

There have been several YouTube videos of individuals showing us so called DIY glowsticks.  To make them they require breaking apart an existing premanufactured one.  This of course defeats the purpose of DIY.  When someone wants to know how to make something DIY, I'm guessing it's because they don't have one on hand to break apart.
Glowstick Reaction
Here is the real chemistry.  A dye is added to a solvent.  This solvent cannot be water, since some of the reactions involved do not occur in water.  An ester, specifically a bi-phenyl ester, is added to provide chemical energy. Since the reaction works better in alkaline conditions, a base is added as well.  To make the ingredients glow hydrogen peroxide is added which decomposes the ester whose byproducts react with the dye to make it glow.
NurdRage's Glowstick Chemistry
The reaction was developed by the US company American Cyanamid in the 1960's.  Other esters can be used like DNPO.  Various bases can be used such as sodium acetate and sodium bicarbonate.  A video that goes into more detail can be viewed here giving specific dyes and reactions that can be put together.  Sadly making DIY glow sticks is more expensive because of economy of scale.