Andrew Que
Sites list
Photos
Computers
Projects
Contact
Main
Next week Previous week
 Jun 30 to Jun 24 -  Jun 23 to Jun 17  -  Jun 16 to Jun 10  -  Jun 9 to Jun 3  -  Jun 2 to May 27 
September - August - July - June - May - April - March
2013 - 2012 - 2011 - 2010 - 2009
Current week

- jQuery and Firebug + Add a comment
Madison Fireworks
(600x600) (900x900) (1800x1800) (Full size)
Show all photos from 2012-06-30
   My gallery rewrite project is the first time I have used jQuery, and now I hardly know how I use to live without it.  I have always found Javascript a tricky language because of what it takes to make projects work the same in different browsers.  jQuery helps with this, although I have found some things that do not work across all browsers).  One item that takes some getting use to is the heavy use of anonymous functions (sometimes called Lambda functions).  Almost everything in jQuery gets a callback function, and a completely legitimate (and useful) way of implementing these functions are by using anonymous functions.  Although these parts of the code are separate function calls, they are coded and look as if they are inline.  This is both good and bad.  It's good because you do not have to break the code into several smaller functions that are all declared by themselves.  So relevant code is located close together.  However, because the callbacks can be asynchronous one must be careful to understand the the linear look to the code may be deceiving.  For example, some of the AJAX functionality of jQuery allows a callback function to be defined after the data has been returned.  Using an anonymous function for the callback makes the code look as though all of that code will run sequentially.  However, the code after the anonymous function will run first, because the AJAX call will not run the callback function until the server has returned data.  This is similar to writing threaded code and one must understand how things can get out of synchronization.  One thing that makes this consideration easier is that Javascript is single-threaded, and test-and-set semaphores are not required.
   Writing the scripts has been greatly aided by a Firefox plug-in called Firebug.  This debugger does a really good job of providing a powerful tool to developers.  The only downfall of this plug-in is that sometimes simple syntax errors, such as missing a coma in function parameters will cause an entire Javascript file not to be included at all.  This may have something to do with how Firefox parses the script, but the complete lack of any feedback can be a pain.  But the benifits of this tool far out weight it's shortcomings.
No comments have been added
- Gallery Rewrites + Add a comment
Monona Bay
(600x600) (900x900) (1800x1800)
Show all photos from 2012-06-27
   For the last several days I've been working on rewriting my image gallery interface.  This is work long over due—my current setup is so 200x.  Seriously though, a lot has changed in PHP, Javascript, and HTML since I first wrote those scripts.  Those were also the scripts that taught me PHP and MySQL.  I wanted to go back and do things a little cleaner.
   The first things I started with is was the PHP scripts that query the database.  PHP 5 added a wonderful class interface, and I have long wanted a good project I could implement in it.  The database for an image gallery is laid out into 3 main categories: pictures, galleries, and gallery groups.  Gallery groups contains sets of galleries, and galleries contain sets of pictures.  There are more tables than this, but these categories are perfect demarcations for classes. 
   The first class I implemented is a child of 'mysqli'.  I overloaded the 'query' function to throw an exception when the query fails.  It also has the names of tables found in the gallery.  Table names have a unique name appended to the front so multiple galleries can be assigned to a single database. 
   The next class I call a database field.  It is an abstract class that has two major functions: get attribute and set attribute.  These are driven by two internal function: fetch from database, and push to database.  It needs a database, the name of the table, and an id for the record each instance will represent.  Now when a record is to be read or written, this class handles the database side of life.  In this way, the child class only needs to know basics about the table it works with.  Each of my gallery implementation could have different table layouts for pictures.  In the main gallery on DrQue.net pictures have information about the ISO, lens, f-stop, ext.  Other galleries have other settings.  This I did not want to matter at this level—the classes should be able to represent themselves without knowing all the details about what they will contain.  So the get/set attribute interface allows the class to be mostly ignorant of the table layout—there are just a few key fields required to make the gallery run.  Everything else is optional and handled at a lower-level, such as the scripts that will build HTML from the gallery data.
   The child classes of the database field are then pictures, galleries, and gallery groups.  A gallery group has the ability to retrieve an array of galleries, and a gallery an array of pictures.  But neither class cares if the table has an entry for the name of the gallery group/gallery.  They only need the ID field for the record their instance represents.
   This system allows a lot of flexibility while remaining very simple.  The largest class, the picture class, is currently only 200 lines of code, and several of those lines are comments.  On the implementation side, things have been very smooth.  Although I have a lot of aesthetic work to do yet the gallery view is completely functional requiring no rework to this class system.
   The picture today is one I took in the early morning hours.  I tried some more High Dynamic Range (HDR) work, this time outside under the stars.  There were two problems with this shoot: wind, and the Earth's rotational speed.  Both of these caused my images not to align completely, resulting in strange artifacts when I applied the HDR process.  As for the wind, I can simply try again on a calm day.  But the star field movement because of the Earth's rotation isn't anything I can work around.  So interesting pictures, but not the greatest.
No comments have been added
- The Kobold's Cave + Add a comment
Kobold's Cave
(600x600) (900x900) (1800x1800)
Show all photos from 2012-06-17
   It has been a long time since I updated any of the information on me work area, so I decided to make a page about my current setup in Madison called the Kobold's Cave.
   Pictured is my primary work area in the Kobold's Cave.  This is actually the first time I have used High Dynamic Range (HDR) imaging.  Since this work area has fairly extreme contrast this shot was a good candidate.  The image is comprised of 9 images, from -6 to +2 F-stops.
1 comment has been made
From Pluvius
Platteville, WI
June 18th, 2012 at 10:41PM
   Very nice shot! Did not realize HDR could be so useful.
- Least-Square Regression Demo + Add a comment

The other day I received an e-mail with questions about my least-square regression PHP class. I haven't touched this implementation since I wrote it for an article on least-square regression in June of 2009, so it's time for a demo.

The original implementation used Cramer's Rule to solve the resulting system of equations. I wrote in May of 2011 an article about a faster method for doing this. So I decided to implement that method and then make a demo to show how the regression curve fits data.

 _fcksavedurl=
 

This demo has a number of black points that can be moved around to form a polynomial curve. The thin red line in the center represents the true polynomial curve. The blue dots represent data points along the true curve with random error introduced. The scatter and concentration of the error can be controlled with the two sliders. The higher the concentration value, the closer the error will fall toward the curve. The scatter magnitude controls how much it is possible for the error to deviate from the true data. The data with the random errors is then used as input to the least-square regression function, and the output of that function is displayed in green. So the green curve should match closely the red curve.

What this simulation shows is the ability of the regression function to recover polynomial coefficients from a signal with a fairly low signal-to-noise ratio with pretty good accuracy. The function must assume the data is from a polynomial of a specific degree. The real-world applications are probably limited, but surely exist—especially with lower degree polynomials.

From experimentation, it seems that curves that have higher curvature are reconstructed the best. That is, curve that change a lot do better than curves that are fairly flat.

The fit of the curve is being measured with residual sum of squares. The lower this value, the closer to the regression curve is to the actual curve with zero being perfect. In this graph, values below 0.5 are pretty good fits, and values below 0.01 put the true curve (in red) in the regression curve (green).

I updated the least-square regression PHP class page with the new version of the class, added some documentation, and some examples. If one person found this class useful, maybe more people will as well.

No comments have been added
- Unevenly Weighted Random Numbers + Add a comment

A couple of weeks ago, I wrote about weighted random numbers. After implementation and some experimentation, I settled on a versatile function that incorporates all the fetchers of the weighting system. Mathematically, it's a little ugly because there is an “if” statement and we end up with a piecewise function.

Where m is the minimum value, M is the maximum value, c is the center point (mcM), S is the concentration coefficient (useful range 1 ≤ S < ∞), and α and β are random numbers between 0 and 1. The core of this function is the weighting.

This has been scaled so the output is in a given range.

Here, mwsM were as 0 ≤ w ≤ 1. From here, the body of the function is split before and after the center point. For this we require a second random number, α. This value is used to determine of the value is to the left or right of center, and the min and max of the function are adjusted accordingly.

Min (m)
Max (M)
Center (c)
Concentration (S)

The top graph shows the distribution of 1,000 samples, and the lower graph shows a histogram of the distribution. The average is calculated over all the samples. If the center value is half-way between min and max, the average should be the center value (or close to). The center value reflects the highest peak value in the histogram, which should always be close to the specified center.

There are some things you can do with this function that are not meaningful. Having a center value outside the min and max value will still generate values, but probably not useful for anything.

You can also use a concentration coefficient less than one and greater than zero (0 ≤ S < ≤ 1) . This has the effect of pushing the concentration away from the center point and toward the min and max values—basically the acting in the reverse of the normal algorithm. This may be useful for generating a value that is usually either one value or an other, with very little in between.

Here the min is 0, max is 100, center is 20, and the concentration coefficient is 0.1. Notice how the center point is the least populated area of the graph.

There are some ways to use this function to generate some of the other weighted functions. For example, let c = ½ (M – m) + m. This will make the function have equal distribution on both sides of the center point.

Here, the function C is a centered function, c is the center point, and s is the span that can be deviated from the center.

For a simple left or right weighted version of the function, simply set the center point to the min value (left weighted) or max value (right weighted).

Using a concentration coefficient of one (S =1) results in just random uniform random data (assuming β is random). Small values of S are harder to notice in this demo, but become pronounced when more samples are used.

Here is an example of a center at 70, min of 0, max of 100, and a concentration coefficient of 2. At 1000 samples it is not apparent there is any concentration, but at 100,000 samples it is easier to see. The higher sample set also makes the histogram more clear. Notice how the histogram falls to around 100 on both sides, but more rapidly to the right of center. This is necessary because of the uneven weight. So a 0 or a 100 are both equally likely (or unlikely as the case may be), but a 60 and 80, despite being equal distance from the center point are not both as likely as one an other (higher likelihood of 60 over 80).

//----------------------------------------------------------------------------
// Return a weighted random number with an uneven distribution from center.
//   $min - Smallest possible.
//   $max - Largest possible value.
//   $center - Location of highest conentration.
//   $concentration - How strongly to curve number--the higher the value,
//     the strong the curve tends toward center.
//   $alpha - Number between 0 and 1, generally random.
//   $beta - Number between 0 and 1, generally random.
//----------------------------------------------------------------------------
function uneven$min$max$center$concentration$alpha$beta )
{
  
// Curve beta.
  
$numerator   $beta;
  
$denominator $beta * ( $concentration ) + 1;
  
$result      $numerator $denominator;

  
// Get center point.
  
$centerDivide = ( $center $min ) / ( $max $min );

  
// Figure out if this result is to the left or right of center.
  
if ( $alpha $centerDivide )
  {
    
$result *= $center $min;
    
$result  $center $result;
  }
  else
  {
    
$result *= $max $center;
    
$result += $center;
  }

  return 
$result;
}

No comments have been added
- Congratulations Tazz + Add a comment
(600x600) (900x900) (1800x1800)
Show all photos from 2012-05-19
   Congratulations to our good friend Tazz Davies for finishing his degree at UW Madison.  Well done.
No comments have been added
- Weighted Random Number + Add a comment

I've written articles about weighted random number in the past, but today I ran into a use I've been meaning to explain for a long time.

For example when rolling two dice, the mostly likely number to roll is 7. With 4 dice, it's 14. These are weighted rolls in the context of this article as the likely outcomes are not evenly distributed, but tend toward some center point.

One of the weighting algorithm I've written about in the past is Banded Inverse Root Nonuniform Scatter. This is the function:

Where α1 and α2 are random numbers between 0 and 1, and S is the “scatter coefficient”. The root of this function is the banding part.

This weights the roll toward 0. The larger the value of S, strong the pull toward 1. Using two of these functions together give a range the function a peak centered at 0 that goes both positive and genitive. Note that the last part of the function normalizes the output so it is between 0 and 1. The process will be explained in a bit, but this function will be called nb(S). So in parts, the full function is:

This function can be simplified if the square root is removed. The root makes the curve more gradual, but this isn't needed.

The trick to this function is the use of the -1, +1 in the denominator. This allows the scatter coefficient to have a defined range between negative infinity and positive infinity (i.e. -∞ < S < +∞), although the useful range is 0 ≤ S < +∞.

The normalized function looks like this:

Rebuilding the center-weighted function results in:

So g( α1, α2, S ) is our weighted function. α1 and α2 are random numbers between 0 and 1. S is the scatted coefficient 0 ≤ S < ∞. The larger the value of S, the more weighted the output is toward 0.

The graph above shows the histogram for distribution for various scatter values and illustrates how as the scatter coefficient increases, the concentration toward the center increases. Note that this function does not create a bell curve (or normal distribution). Instead it has a sharp point at the center. This means that for larger values of S the likelihood of being away from the center point diminishes very rapidly—much more than it would with a function that has normal distribution. So the function favors the center point more strongly than those producing normal distribution.

Now some of the function's versatility. The function is normally used to generate some range.

Here, M is a scale factor (magnitude) and c is an offset that allows the function to have a range such that -(M + c) < v < (M + c). Now a function can be defined to return a value in a given range with some weight.

Where vmin < w( vmin, vmax, S ) < vmax. The floor function makes sure the values are integer numbers, and can be omitted if real number are desired. The center point will always be half way between vmin and vmax.

This function can be modified slightly to simulate a dice roll. Let n be the number of dice, and s be the number of sides on each die. Then vmin = n, vmax = n * s. The scatter coefficient (S) can be varied, but the distribution will not be identical to that of an actual dice roll.

Here the floor function is required. n < d( n, s, S ) < n*s.

In this histrogram, the difference in distribution can be seen between an actual dice roll (in this case, five 6-sides die) and the simulated function d( n, s, S ) where S = 3. Note they both peak at the same location (between 17 and 18) with roughly the same likelihood for these numbers. However, the chances for rolling a 15 are greater with a true dice roll, and less in the simulated. Likewise, rolling an 8 is less likely with dice, and more likely simulated. Keep in mind that the simulated dice roll can do something an actual dice roll can not: produce fractional results. If the floor function part of d( n, s, S ) is removed, any real number in the range can be returned. So while an exhaustive check for every dice roll is possible, every simulated roll is not. Thus, the graph above used one million samples to produce the simulated histrogram.

There are some additional way the function g( α1, α2, S ) can be used. If an uncentered value desired, the random input can be fixed.

These histrogram show the output of 10,000 samples of the function, where α is a random number (0 ≤ α ≤ 1). Note how in both cases, when S = 1 the distribution is uniform for all values. This is because when S = 1, the weighting function is doing nothing, and the random value α is being returned.

No comments have been added


Designed and maintained by Andrew Que
(C) Copyright 2001-2012