text:
Text Version
OVERLOAD CONTENTS OVERLOAD 84 April 2008 ISSN 1354-3172 Editor Alan Griffiths firstname.lastname@example.com Advisors Overload is a publication of ACCU For details of ACCU, our publications and activities, visit the ACCU website: www.accu.org Phil Bass firstname.lastname@example.com Richard Blundell firstname.lastname@example.com Alistair McDonald firstname.lastname@example.com Anthony Williams firstname.lastname@example.com Simon Sebright firstname.lastname@example.com Paul Thomas email@example.com Ric Parkin firstname.lastname@example.com Simon Farnsworth email@example.com Advertising enquiries firstname.lastname@example.com Cover art and design 4 Watersheds and Waterfalls Stuart Golodetz continues his survey of algorithms for segmenting images into regions. 9 The Model Student: A Knotty Problem, Part 1 Richard Harris explores more of the mathematics of modelling problems with computers. 16 The Way of the Consultant Teedy Deigh offers some observations on how consultants can meet the challenge of achieving effective communication. Pete Goodliffe email@example.com Copy deadlines All articles intended for publication in Overload 85 should be submitted to the editor by 1st May 2008 and for Overload 86 by 1st July 2008. ACCU Copyrights and Trade Marks ACCU is an organisation of programmers who care about professionalism in programming. That is, we care about writing good code, and about writing it in a good way. We are dedicated to raising the standard of programming. Some articles and other contributions use terms that are either registered trade marks or claimed as such. The use of such terms is not intended to support nor disparage any trade mark claim. On request we will withdraw all references to a specific trade mark and its owner. The articles in this magazine have all been written by ACCU members - by programmers, for programmers - and have been contributed free of charge. By default, the copyright of all material published by ACCU is the exclusive property of the author. By submitting material to ACCU for publication, an author is, by default, assumed to have granted ACCU the right to publish and republish that material in any medium as they see fit. An author of an article or column (not a letter or a review of software or a book) may explicitly offer single (first serial) publication rights and thereby retain all other rights. Except for licences granted to 1) Corporate Members to copy solely for internal distribution 2) members to copy source code for use on their own computers, no material can be copied from Overload without written permission from the copyright holder. Overload | 1 EDITORIAL ALAN GRIFFITHS After Four Years After four years as editor of Overload it is time for a change. Changing times Out of curiosity I looked up the first editorial I wrote after taking over the editorship of Overload (the June 2004 issue). By a curious coincidence this editorial started by discussing change: I was optimistic that software development practices are evolving and new ideas are being put into practice. By another coincidence, the previous editorial had – like the one before this one – been written by a guest: Mark Radford, who observed a (less positive) tendency for organisations to try techniques that are known to be ineffective. After four years one might hope that evidence would be mounting to support my view of a changing industry. I do see wider adoption of good practices – for example I rarely have to 'sell' unit tests or continuous integration. But I also see some of the same bad ideas that have been around since they were debunked in 'The Mythical Man-Month'. (Adding people to a late project? It still happens, and it still makes things harder!!) Why is change so slow? Well we are talking about changes to human behaviour – and that happens very slowly. Over a long time-scale things definitely do change in the software development world – although it has spent decades trying to model development processes into a model that assumes that correcting errors is so expensive that it justifies elaborate and costly precautions to avoid them. This may have been partially true once – in the 1970s I can remember working in environments where one got one or two attempts to compile a program each day and hand checking for code syntax errors was an essential part of making progress towards actually executing the code. In these circumstances, checking in advance was necessary. Since then the technology supporting software development has changed. The discipline of hand checking the code became obsolete decades ago, when it became possible to run a compile and get the results faster than checking by hand. It became far more effective to throw the code at the compiler and deal with any diagnostics it produced. The changes have gone further than that. In a typical modern development environment, syntax errors are highlighted as one types and when the file is saved the code is automatically compiled and tested: the results appear in a moment. This leads to a mode of working where the tests and code are developed in parallel and to some developers making the (unsurprising) observation that if one makes the tests easy to write the corresponding code is easy to use. Throughout the development cycle the costs of automation have fallen: building and testing an entire system to a point where it can be deployed can be automated and run at intervals ranging from every commit to every day. Automation of deployment is also feasible with a consequent reduction in the cost of a release over extended manual checking and deployment. Given this, it is hardly surprising that in software-for-use projects there is an increasing emphasis on delivering a partial solution as early as is feasible and regularly making incremental corrections and improvements based on user feedback. While these practices are not yet universal – and are less applicable to software-for-sale projects – the reduction in overall development costs and time to deliver are driving adoption. Another sign of the times In the early days of desktop computers a lot of effort went into moving data from one system to another. Even though I was working for a company whose main business was selling furniture, developing software for it involved writing device drivers, file transfer utilities and translators between different data formats and character encodings. I'm sure that mine wasn't the only company incurring costs when dealing with EBCDIC, ASCII line termination, national currency symbols and the like – not really part of the core business. And as the IBM PC became popular there were also IBM's 'extended' ASCII code pages to deal with too. On the other hand, as PCs became popular file transfer and transformation utilities became readily available. But similar problems popped up in another area office applications (like word processing) – each supplier created its own incompatible format – and the developers of these must have expended considerable effort reverse-engineering each other's formats and writing import and export functions. These worked inconsistently, and if you didn't know what someone else used then the only reliable format was plain text (although, as noted above, there were still issues with the character encoding). Eventually, one of these application suites (Microsoft Office) established dominance and its developers at least could relax and let the others worry about reverse engineering competitors' products. Nice for them and an extra effort for anyone else wanting to compete in the 'office' market. And that has been the case for some years now. However, a number of other parties have reason for wanting this to change: other software developers who want to compete in this market; other OS vendors that want to supply desktop systems; customers who want to use alternative products; and organisations that have a need to ensure continued access to documents. This conflict of interest has been focussed around Microsoft's attempts to get ISO to ratify its 'Office Open XML' standard. Ms. Geraldine FraserMoleketi the South Africa Minister of Public Service and Administration recently described [Idlelo] the situation as follows: Alan Griffiths is an independent software developer who has been using "Agile Methods" since before they were called "Agile", has been using C++ since before there was a standard, has been using Java since before it went server-side and is still interested in learning new stuff. His homepage is http://www.octopull.demon.co.uk and he can be contacted at email@example.com 2 | Overload | April 2008 ALAN GRIFFITHS ...The adoption of open standards by governments is a critical factor in building interoperable information systems which are open, accessible, fair and which reinforce democratic culture and good governance practices... ODF is an open standard developed by a technical committee within the OASIS consortium. The committee represents multiple vendors and Free Software community groups. OASIS submitted the standard to the International Standards Organisation in 2005 and it was adopted as an ISO standard in 2006. South Africa is amongst a growing number of National Governments who have adopted ODF over the past year. This past year has been marked by a raising in the tension between the traditional incumbent monopoly software players and the rising champions of the Free Software movement in Africa. The flashpoints of conflict have been particularly marked around the development and adoption of open standards and growing concerns about software patents... It is unfortunate that the leading vendor of office software, which enjoys considerable dominance in the market, chose not to participate and support ODF in its products, but rather to develop its own competing document standard which is now also awaiting judgement in the ISO process. If it is successful, it is difficult to see how consumers will benefit from these two overlapping ISO standards. I would like to appeal to vendors to listen to the demands of consumers as well as Free Software developers. Please work together to produce interoperable document standards. The proliferation of multiple standards in this space is confusing and costly.... An issue which poses a significant threat to the growth of an African software development sector (both Free Software and proprietary) is the recent pressure by certain multinational companies to file software patents in our national and regional patent offices. Whereas open standards and Free Software are intended to be inclusive and encourage fair competition, patents are exclusive and anti-competitive in their nature. Whereas there are some industries in which the temporary monopoly granted by a patent may be justified on the grounds of encouraging innovation, there is no reason to believe that society benefits from such monopolies being granted for computer program 'inventions'. The continued growth in the quantity and quality of Free Software illustrates that such protection is not required to drive innovation in software. Indeed all of the current so-called developed countries built up their considerable software industries in the absence of patent protection for software. For those same countries to insist on patent protection for software now is simply to place protectionist barriers in front of new comers. As the economist, Ha-Joon Chang, observed: having reached the top of the pile themselves they now wish to kick away the ladder. Between the time I'm writing this and the time you read it, the next round in this conflict will be over: toward the end of March ISO will chose EDITORIAL whether to adopted Microsoft's OOXML as a new standard by way of its 'Fast Track' process or not. As you will know from past editorials, I'm of the opinion that OOXML is not currently fit to be a standard – and my opinion hasn't been changed by the changes voted at the recent Ballot Resolution Meeting. As an illustration of why I feel this way I refer you to Rob Wier's study 'How many defects remain in OOXML?' [Weir]. His conclusion (my emphasis): That's as far as I've gone. But this doesn't look good, does it? Not only am I finding numerous errors, these errors appear to be new ones, ones not detected by the NB 5-month review, and as such were not addressed in Geneva. Since I have not come across any error that actually was fixed at the BRM, the current estimate of the defect removal effectiveness of the Fast Track process is < 1/64 or 1.5%. That is the upper bounds. (Confidence interval? I'll need to check on this, but I'm thinking this would be based on standard error of a proportion, where SE=sqrt((p*(1-p))/N)), making our confidence interval 1.5% ± 3%) Of course, this value will need to be adjusted as my study continues. However, it is starting to look like the Fast Track review was very shallow and that detected only a small percentage of the errors in the DIS. The number of errors isn't really surprising given the speed with which this draft standard has been produced – we all know how hard it is to produce accurate technical information. And a standard of this size (it is bigger than SQL) needs a couple of years worth of review – not the few months allowed by the Fast Track process. Closer to home The reason I was looking back to my first editorial during this term as editor is that I'm giving up the role again. I've enjoyed my time with the magazine, but I'm no longer moving it forward and it is time that someone else has the opportunity to do something with it. That someone is Ric Parkin who has been on the editorial team for some time now and, while I disappeared on holiday, edited the October issue last year (so he does know what he's getting into). The team that has been supporting me for the last year remains in place so I'm sure that it is in good hands. Good luck Ric! References [Idlelo] http://www.raffee.co.za/post/29079077 [Weir] http://www.robweir.com/blog/2008/03/how-many-defectsremain-in-ooxml.html April 2008 | Overload | 3 FEATURE STUART GOLODETZ Watersheds and Waterfalls (Part 2) Stuart Golodetz continues his survey of algorithms for segmenting images into regions. I n my last article [Golodetz], I described a way of segmenting images using the watershed transform and commented that the biggest problem with the results was one of oversegmentation: the image gets divided into too many regions because a region is generated for every regional minimum in the image, regardless of whether it's of any interest to us. The waterfall algorithm [Marcotegui], the subject of this article, is a hierarchical approach which attempts to solve this problem. (Readers may wish to consult the original paper for a more detailed justification of some of the methods involved.). Gaussian blurring Before we start looking at the algorithm in detail, though, it's worth observing that there are useful pre-processing steps we can take to reduce the initial number of regional minima before even applying the watershed transform. In particular, it's well worth our time to apply a Gaussian blur to the original image before taking its gradient. (There are other useful things we should do here as well, but this is an area I'm still looking into.) Figure 1 Gaussian blurring is essentially a form of weighted pixel averaging based on a discrete approximation to the 2D version of the normal distribution. Many of you will doubtless be familiar with the 1D Gaussian from statistics: ⎛ –x2 ⎞ 1 g σ ( x ) = -------------- exp ⎜ --------2-⎟ σ 2π ⎝ 2σ ⎠ Its 2D version can be obtained by multiplying a 1D Gaussian in the x direction with one in the y direction: ⎛ – ( x 2 + y 2 )⎞ 1 G σ ( x, y ) = g σ ( x ) × g σ ( y ) = ------------2- exp ⎜ -----------------------⎟ ⎝ 2σ 2 ⎠ 2πσ In 1D, its graph is the familiar bell-shaped curve; in 2D, we get a bellshaped surface (see Figure 1). To use this for image blurring, we form a symmetric mask (see Figure 2) from the values of G σ ( x, y ) at discrete points in a grid centred at the origin (e.g. for a 3x3 mask, we calculate values at (-1,-1), (0,-1), (1,-1), …, (0,0), …, (1,1)). We then normalize the mask by dividing by the sum of all the values in it (this is done to ensure that regions of uniform intensity in the image will be unaffected by smoothing). This procedure can be used to generate masks of other sizes as well. As an example (Figure 2), we'll calculate a 3x3 mask for the 2D Gaussian G 1 ( x, y ) (i.e. the Gaussian with standard deviation σ = 1 ). First we calculate the values of G 1 ( x, y ) at the grid points (i.e. we calculate Stuart Golodetz has been programming for 13 years and is studying for a computing doctorate at Oxford University. His current work is on the automatic segmentation of abdominal CT scans. He can be contacted at email@example.com 4 | Overload | April 2008 Figure 2 G 1 ( – 1, – 1 ) , …, G 1 ( 1, 1 ) to give us the unnormalized mask (left); then, we normalize it by dividing through by the sum of all the values in the mask to give the final result (right). The actual blurring is done by what is known as convolving the image with the mask. This basically means overlaying the mask on each pixel of the image in turn, multiplying the value of each pixel in the mask by the value of the pixel beneath it, summing the results and using the value thus obtained as the value of the centre pixel in the blurred image. For the 3x3 mask with σ = 1 , this means that if I ( x, y ) is the source image, M ( x, y ) is the mask and I′ ( x, y ) is the blurred image, then: I'(x,y) = 0.0751 x (I(x-1,y-1) + I(x+1,y-1) + I(x-1,y+1) + I(x+1,y+1)) + 0.1238 x (I(x,y-1) + I(x,y+1) + I(x-1,y) + I(x+1,y)) + 0.2042 x I(x,y) Introducing the Waterfall Having talked about pre-processing, we can now turn our attentions to the actual waterfall algorithm. The basic idea is to take the result of the watershed transform on the gradient of the original image and use it to produce a sequence of images by merging some adjacent regions (see Figure 3). The waterfall algorithm produces a hierarchical sequence of segmentations, starting from the original watershed result (far left). The final image will eventually be a single region (not shown). The algorithm described in [Marcotegui] works on the region adjacency graph (RAG) of the watershed result. This is a graph with one vertex for STUART GOLODETZ FEATURE the weights on the edges essentially determine the order of region merging Figure 3 each region in the watershed, and weighted edges joining adjacent regions (see Figure 4). As we will see, the weights on the edges essentially determine the order of region merging, and we have a number of different options when calculating them. For now, we'll assume that we already have a suitably weighted graph, and focus on how to use it to iterate from one stage in the waterfall sequence to the next. Figure 4 shows a set of regions (left) and their region adjacency graph (right) – note that edges to the surrounding region are not shown to make things clearer. Figure 5 Given a graph G = (V,E,w) with vertex set V, edge set E and weight function + w:E → Z , the set of spanning trees ST(G) of G is the set of subgraphs of G which are both trees (i.e. they're acyclic) and which span G (i.e. they contain every vertex in V): see Figure 5 for an example, which shows a graph and one possible spanning tree for it. A minimum spanning tree is then simply one with a minimum total cost, i.e. a spanning tree T = ( V, E′, w ) ∈ ST(G) such that ∀( V, E″, w ) ∈ ST(G) ° ∑ e′ ∈ E′ w(e′) ≤ ∑ w(e″) e″ ∈ E″ Constructing a minimum spanning tree can be done straightforwardly using Kruskal's algorithm. This involves sorting the edges in the graph into ascending order by weight, then adding the edges in ascending order to the minimum spanning tree provided they wouldn't create a cycle and invalidate the tree. Data structures Figure 4 The basic idea of a waterfall iteration involves doing something very like a watershed algorithm on the RAG. First of all, we have to find the regional minima of the graph, which in this case means its regional minimum edges (we'll define what we mean by this shortly). We then mark each such edge with a different label and carefully propagate the labels to the rest of the edges of the graph (this is an implementation of the watershed-frommarkers algorithm, where the regional minimum edges are the markers). This induces a new labelling of the various regions, resulting in some of the adjacent regions being merged. In practice, we don't run the algorithm on the RAG itself; for reasons that are fully explained in the referenced paper, the minimum spanning tree (MST) of the graph contains sufficient information that we can simply run the algorithm on that, with a corresponding gain in efficiency. To briefly recap for those who are unfamiliar with MSTs, they can be defined as follows. To implement the waterfall efficiently, we're going to have to learn a bit about data structures. One of the key things we need to know about is Tarjan's data structure for disjoint set forests (I mentioned this briefly last time). This structure, designed for maintaining a collection of (mutually) disjoint sets that change over time, is widely useful and not merely restricted to our current purposes. Indeed it's the sort of thing that crops up in Computer Science degree courses [Worrell]! In the previous article and this one alone, this structure gets used during the fletching stage of the watershed algorithm and as part of Kruskal's algorithm, and that's before we've even mentioned its usage in maintaining the regions for the actual waterfall algorithm itself. The idea, then, is to represent each disjoint set as a rooted tree. Finding which set an element is in is as simple as walking up the tree to the root. Unioning two sets involves finding the roots of two separate trees, and making one tree root a child of the other. For efficiency reasons, it makes sense to keep the paths to the roots of the trees as small as possible. Two tricks used to accomplish this are union-by-rank and path compression. Without dwelling on the details, the first of these tries to ensure that we're making the root of the smaller tree a child of that of the larger one, and the second changes all the parent pointers on a path to the root to point directly April 2008 | Overload | 5 FEATURE STUART GOLODETZ In the waterfall algorithm, we use such a disjoint set forest to store which regions are connected to each other MAKE-SET(x) parent[x] ? x rank[x] ? 0 FIND-SET(x) if x ? parent[x] then parent[x] ? FIND-SET(parent[x]) return parent[x] LINK(x,y) if rank[x] > rank[y] then parent[y] ? x else parent[x] ? y if rank[x] = rank[y] then rank[y] = rank[y] + 1 UNION(x,y) LINK(FIND-SET(x), FIND-SET(y)) Listing 1 to the root when a 'find root' call is made: this ensures that subsequent calls on any element on the path will be constant time. The code to implement all this is shown in Listing 1, which shows Tarjan's Disjoint Set Forest. was originally given by the watershed transform: this can then be used to look up the correct region value in the disjoint set forest associated with any given level of the waterfall. The space savings are also noticeable: instead of storing a full image of labels for each waterfall iteration, we need only store the results of the watershed and a disjoint set forest for each level of the hierarchy. The other data structures we'll use are for maintaining edges. The layout is as shown in Figure 6. We maintain an array (in practice, a std::vector) which stores all the edges we'll be referring to (these can either be all the edges in the RAG, or all the edges in the initial MST if we want to be particularly space-efficient). The MST is represented as a list of edge pointers sorted in ascending order of edge weight. Finally, we store an edge adjacency table, which stores lists of pointers to edges which are adjacent to each of the various regions. Figure 6 shows the data structures used for the waterfall algorithm: some of the pointers aren't shown for reasons of clarity. Step 1: Finding the Regional Minimum Edges A regional minimum edge (RME) of a graph G is a connected subgraph of G whose own edges have equal weight and whose adjacent edges in G have strictly higher weights (see Figure 7). Figure 7 shows an example graph and its RMEs (drawn as triple edges). Note that the two edges with a weight of 1 are part of the same RME. In the waterfall algorithm, we use such a disjoint set forest to store which regions are connected to each other. Initially, we have a tree for each region in the watershed result; as we merge regions (see Edge Elision below), we then union their respective trees. This makes region merging a very fast process, since we don't have to update the region indices for all the individual pixels in the regions. Instead, each pixel maintains the label it To find all the regional edges in the MST, we run through all the edges in the MST and flood outwards from each one to determine (a) whether it's part of an RME and (b) the extent of the RME if so (see Listing 2, the flooding algorithm for finding RMEs). We do this by maintaining two things: an equal edges list, which holds all the edges that may form part of the current hypothetical RME, and an adjacent edges queue, which holds Figure 6 Figure 7 6 | Overload | April 2008 STUART GOLODETZ all unprocessed edges which are adjacent to one of the aforementioned equal edges. We process all adjacent edges one at a time. If we see a lower edge, this isn't an RME. If we see an equal edge, we add it to the list of edges which may be in the RME and add its adjacent edges to the queue. If we see a higher edge, we ignore it. If we empty the adjacent edges queue without seeing a lower edge, we've found an RME, so we add it to the list, mark all the edges in it as being part of an existing minimum (to avoid later duplication) and continue from the top with the next MST edge. Edge elision In my implementation of the waterfall, no actual relabelling of the regions is done. Instead, the same effect is achieved by merging regions via the Vector
rmeArray; foreach(Edge startEdge mst) // The edge is already part of a regional // minimum edge. If we processed it, we'd // end up duplicating that minimum edge, // so skip over it. if(startEdge->minimum) continue; // Maintain a list of equally-valued edges // which may form part of the same RME. EdgeList equalEdges; EdgeQueue adjacentEdges; FEATURE mechanism of eliding (i.e. removing) edges in the RAG. The process of edge elision is slightly intricate because all the relevant data structures need to be updated. We need to union the disjoint set forest trees associated with the regions at either end of the edge, we need to splice the edge adjacency lists together (thus adding the list of all the edges adjacent to one of the regions to that of the other) and we need to do various bits of additional housekeeping (see Listing 3, edge elision). One important step is to mark the edge as elided, so that it can be removed from the MST in Step 4 of the algorithm (see below). Step 2: Eliding the RMEs Having found the RMEs in Step 1 (above), the next part of the actual algorithm is to elide them. This is done as an alternative to assigning them all the same label (as per the original waterfall description). Step 3: Marker propagation Once we've 'labelled' the marker regions by eliding all the RMEs connecting them, the next step is to propagate the markers to the rest of the MST using a flooding process, at each stage processing an adjacent edge with lowest cost. The ideal data structure for this is a priority queue. The algorithm (see Listing 4, marker propagation) works as follows: we initialise the queue with any edges which are adjacent to RMEs and mark the regions joined by the RMEs as already processed. We then repeatedly pop the lowest cost edge from the queue, merging the regions it connects if one of them is unmarked, and ignoring it otherwise. If an edge is elided, its own adjacent edges are also added to the queue. // Maintain a queue of pending edges so they // can be unmarked again later. EdgeQueue pendingEdges; // Mark the initial edge to ensure it isn't // wrongly identified as being adjacent to // itself. startEdge->pending = true; pendingEdges.push(startEdge); add_adjacent_edges(startEdge, adjacentEdges, pendingEdges); bool isMinimum = true; while(!adjacentEdges.empty()) Edge adjacent = adjacentEdges.pop(); if(adjacent->value < startEdge->value) // If its value is less than the start // edge, then the start edge is not a // minimum. isMinimum = false; break; elseif(adjacent->value == startEdge->value) equalEdges.push_back(adjacent); add_adjacent_edges(adjacent, adjacentEdges, pendingEdges); // Unmark all the pending edges. while(!pendingEdges.empty()) Edge e = pendingEdges.pop(); e->pending = false; if(isMinimum) // Add the start edge to the list now that // we know we've found a minimum. equalEdges.push_front(startEdge); for(Edge e equalEdges) e->minimum = true; rmeArray.push_back(equalEdges); Listing 2 ELIDE-EDGE(e) unsigned int u = e->u; unsigned int v = e->v; unsigned int setU = forest.find_set(u); unsigned int setV = forest.find_set(v); forest.union_nodes(u, v); // Mark the edge as elided for when we come to // later rebuild the MST. e->value = -1; // forest.find_set(u) == forest.find_set(v) unsigned int parent = forest.find_set(u); // Add all the edges adjacent to the child // regions to the parent region in the // adjacency table. EdgeList parentList = adjacencyTable[parent]; if(setU != parent) parentList.splice(parentList.end(), adjacencyTable[setU]); if(setV != parent) parentList.splice(parentList.end(), adjacencyTable[setV]); // Remove the elided edge from the parent list. parentList.remove(e); // Update the region values. Value parentValue = forest.value_of(parent); Value uValue = forest.value_of(setU); Value vValue = forest.value_of(setV); if(uValue > parentValue) parentValue = uValue; if(vValue > parentValue) parentValue = vValue; Listing 3 April 2008 | Overload | 7 FEATURE STUART GOLODETZ Step 4: Rebuilding the MST The final step of the algorithm is to rebuild the MST so that it's ready for the next waterfall iteration. This turns out to be an almost trivial process, since we just have to remove any elided edges from the tree. Since we carefully marked them all with a value of -1 when they were elided, all we have to do is run through the list representing the MST and remove any edges whose value is -1 (in C++, this can be handled extremely simply using a remove_if call). Edge valuations One issue we haven't yet touched on is how to generate suitable weights for the edges of the region adjacency graph. Since these weights determine the order of region merging, they have a substantial effect on the output of the whole algorithm, so it's important to choose them carefully. There are a number of different options available. The simplest approach, known as lowest pass, valuates each edge with the height of the lowest pass point on the border between the regions it joins. One advantage of this method is that it's easy to calculate: you just run through all the pixels in the watershed result, find any border pixels (pixels which have at least one neighbour with a different label) and update the lowest pass between any two regions as necessary. Lowest pass isn't always the best method to use, however, and several other sensible valuations have been proposed. These generally focus on the idea of dynamics, which involves thinking about either the height (contrast dynamics), the surface area (area dynamics) or the volume (volume dynamics) of the water in the catchment basins of the adjacent regions at the point when they would meet during the flooding process (i.e. the point where a watershed is built to keep them apart). These all produce different results and some experimentation is needed to see which may be the most appropriate in a given situation. Another interesting valuation can be found in [Climent], where the authors use some knowledge about the human perception of shapes to define a dynamic which (on their test images at any rate) produces more visually-pleasing results than (in particular) the volume dynamic, with which they contrast it. My own work is currently using lowest pass, but I plan to experiment further with the other valuations in due course. Conclusion From my own experiments with the waterfall algorithm, I can attest to the fact that the results of waterfall segmentation seem to be much more useful than the original watershed result. It's not that any particular image in the waterfall sequence gives us the ideal segmentation: that would be far too easy. What the waterfall does give us is a lot of connected regions (in the various different images in the sequence) to work with further. With these results, we can go on to use region analysis and classification strategies to identify which regions in the various waterfall iterations correspond to features of interest in our original image. Waterfall thus takes us one step closer to our original goal of automatic segmentation. How to do the actual region analysis and classification is still a research problem, but one I hope to continue working on in the near future. Till next time... References [Climent] 'Visually Significant Dynamics for Watershed Segmentation', Joan Climent and Alberto Sanfeliu. In Proceedings of the 18th International Conference on Pattern Recognition (ICPR '06), 2006. [Golodetz] 'Watersheds and Waterfalls (Part 1)', Stuart Golodetz, Overload 83, February 2008. [Marcotegui] 'Fast Implementation of Waterfall Based on Graphs', Beatriz Marcotegui and Serge Beucher. In Mathematical Morphology: 40 Years On, Springer Netherlands, 2005. [Worrell] 'Data Structures for Disjoint Sets', James Worrell. Advanced Data Structures and Algorithms course notes, Oxford University, 2006. 8 | Overload | April 2008 // Flags indicating whether a region has been // marked or not. Vector
markedRegion(forest.node_count()); PriorityQueue
pq; EdgeQueue pendingEdges; // Add all the edges adjacent to RMEs to the // priority queue. foreach(EdgeList rme rmeArray) foreach(Edge e rme) add_adjacent_edges(e, pq, pendingEdges); int setU = forest.find_set(e->u); int setV = forest.find_set(e->v); markedRegion[setU] = 1; markedRegion[setV] = 1; // Process each edge in ascending order of // value, adding adjacent edges to the priority // queue each time. while(!pq.empty()) Edge e = pq.pop(); int setU = forest.find_set(e->u); int setV = forest.find_set(e->v); // If this region connects a marked region to // an unmarked one, it needs processing. // Otherwise it should be ignored. Note that // because of the way the propagation works, // any edge will either connect a marked // region to an unmarked one, or it will // connect two marked regions. if(!markedRegion[setU] || !markedRegion[setV]) ELIDE-EDGE(e); markedRegion[setU] = 1; markedRegion[setV] = 1; add_adjacent_edges(e, pq, pendingEdges); // Unmark all the pending edges. while(!pendingEdges.empty()) Edge e = pendingEdges.pop(); e->pending = false; Listing 4 RICHARD HARRIS FEATURE The Model Student: A Knotty Problem, Part 1 Richard Harris explores more of the mathematics of modelling problems with computers. I f there's one thing that's guaranteed to irritate me, it's headphones. I don't mean the continual tinny noise pollution that thoughtless public transport patrons inevitably inflict upon their unfortunate fellow passengers; I'm far too busy inflicting my own tinny noise pollution on them to pay it any heed. No, I refer instead to their annoying tendency to tie themselves up in knots at every conceivable opportunity. As foolish as it is to anthropomorphise, I can't help but suspect that they are possessed of a demonic nature; that they will not rest until they have damned all of humanity to an eternal tortured state of minor inconvenience. It's not just headphones either. If anything, fairy lights are even more belligerent. It seems that no matter how carefully I pack them away with the other Christmas decorations they will, 11 months or so later, have contrived to rearrange themselves into a tangle of Gordian complexity. Thus far I have resisted the temptation to assume the mantle of Alexander and take a pair of scissors to the blasted things; I suppose that it's only a matter of time before I succumb. X Figure 1 I am not alone in my frustration. Jerome K. Jerome [Jerome89] made the same observation of tow-lines as long ago as 1889: There may be tow-lines that are a credit to their profession – conscientious, respectable tow-lines – tow-lines that do not imagine that they are crotchet-work, and try to knit themselves up into antimacassars the instant they are left to themselves. I say there may be such tow-lines; I sincerely hope there are. But I have not met with them. So are I and my illustrious forebears suffering from an overactive imagination or do we really live in a universe in which strings and cables spontaneously tie themselves into knots? Believe it or not, there is an entire field of mathematics dedicated to the study and classification of knots that does, in fact, have something to say on the matter (Brian Hayes [Hayes] has an interesting discussion on the subject of random closed knots). Unfortunately, it's an extremely difficult subject. So much so that even determining whether or not two knots are equivalent is still an unsolved problem. Whilst knot theory would certainly shed a great deal of light upon the subject, I'm afraid I might sprain something trying to understand it. Instead, I shall propose a simpler model which, with luck, won't cause me any permanent injury. That model is a random walk. Generally speaking, a random walk is a sequence generated by a series of random steps from some given starting position. In this case, we will model a string as a chain of finitely sized inflexible links. We can divide the two dimensional surface onto which we lower it, a table for example, into a discrete grid. We can then hypothesise that each link will occupy the location of the previous link or of one of its eight neighbours with equal probability, as illustrated in figure 1 (which shows the candidate steps in a two dimensional random walk). Figure 2 illustrates one such walk (a 9step random walk). The properties of random walks have been studied for a great many years since they are, in the continuous limit, the mathematical model for Figure 2 Brownian motion. This is the random motion of tiny particles suspended in liquid or gas named after Robert Brown who observed it for pollen grains floating in water in 1827 [Brown28]. Some fifty years later, the mathematics of Brownian motion was described by Thorvald Thiele [Thiele80]. Since then it has been a subject of great interest to mathematicians and physicists, and more recently financiers. The latter has grown into a lucrative field since there are strong theoretical arguments that share prices exhibit a form of Brownian motion [Bachelier00, Hull05]. The relationship between random walks and knots has not escaped the attention of mathematicians. Nechaev [Nechaev98] provides a thorough review of the current state of the art, a state which I must admit is sufficiently advanced that I am reticent to tackle it. Richard Harris has been a professional programmer since 1996. He has a background in Artificial Intelligence and numerical computing and is currently employed writing software for financial regulation. April 2008 | Overload | 9 FEATURE RICHARD HARRIS each time the cable crosses itself it is presented with an opportunity to tangle So how should an amateur like me relate random walks to the question at hand? Well, each time the cable crosses itself it is presented with an opportunity to tangle. In my experience cables are loathe to pass up such opportunities lightly, so the number of self crossings should hopefully give some insight into their tendency to become knotted. Their implementation is fairly simple, the only trap being ensuring that operator< is a strict weak ordering. We can ensure this by making it a lexicographical comparison. Note that this has no real mathematical meaning and serves only to make position compatible with associative containers. Listing 2 shows an implementation of move and comparison. The obvious way to measure the number of self crossings is to generate every possible walk of a given length and simply count the number of times each of them crossed itself, or other words returns to a point it has already visited. Equally obvious is that this will be extremely computationally expensive. Since each step has nine possible outcomes, a walk of n steps will have a total of 9n distinct outcomes. Once again, we'll need a histogram to keep track of the number of self crossings of the random walks. The histogram shall assume that every self crossing results in a knot, thus measuring the worst possible outcome. Apart from some of the names, this is pretty much identical to the one we used for the travelling salesman problem. Nevertheless, it's worth pursuing since it leads to some interesting C++. Before we start we'll need some classes to manage the random walks and keep track of the number of crossings. Let's start with a class to represent a position on the planar grid. Listing 1 shows a class to represent a position in a random walk. The important features of this class are that it supports moving from one position to another with the move member function and that it defines a strict weak ordering with operator<, making it possible to use it as a key in a std::set or std::map. namespace knots { class position { public: position(); position(long x, long y); position move(long dx, long dy) const; bool operator<(const position &rhs) const; bool operator==(const position &rhs) const; private: long x_; long y_; }; } Listing 1 knots::position knots::position::move(long dx, long dy) const { return position(x_+dx, y_+dy); } bool knots::position::operator<( const position &rhs) const { return x_
histogram_type; typedef histogram_type::const_iterator const_iterator; typedef const value_type & const_reference; typedef histogram_type::size_type size_type; knot_histogram(); explicit knot_histogram(size_t length); knot_histogram(size_type buckets, size_t knots_per_bucket); bool empty() const; size_type size() const; size_type walk_length() const; const_iterator begin() const; const_iterator end() const; const_reference operator[](size_type i) const; const_reference at(size_type i) const; void add(size_t knots); private: void init(); size_type knots_per_bucket_; histogram_type histogram_; }; } Listing 3 RICHARD HARRIS FEATURE We need only divide the number of knots by the knots per bucket to identify the correct bucket knots::knot_histogram::knot_histogram() { } knots::knot_histogram::knot_histogram( size_t length) : knots_per_bucket_(1), histogram_(length) { init(); } knots::knot_histogram::knot_histogram( size_type buckets, size_t knots_per_bucket) : knots_per_bucket_(knots_per_bucket), histogram_(buckets) { init(); } Listing 4 those that require some care. Listing 4 shows construction of the knot histogram. By default we use one bucket per step of the walk since we know that the maximum possible number of self crossings results from every step staying in the same cell. As before, the init member function initialises the buckets (Listing 5). This time it's slightly simpler since we've forced the user to pass in the number of knots per bucket in the histogram. Note that we're using the proportion of the walk that's knotted, rather than the absolute number of void knots::knot_histogram::init() { if(empty()) throw std::invalid_argument(""); histogram_type::iterator first = histogram_.begin(); histogram_type::iterator last = histogram_.end(); size_t knots = 0; --last; while(first!=last) { knots += knots_per_bucket_; *first++ = value_type( double(knots)/double(walk_length()), 0); } *first = value_type(1.0, 0); } Listing 5 void knots::knot_histogram::add(size_t knots) { knots /= knots_per_bucket_; if(knots
element of which contains a value in the range zero up to and including eight. In addition to a typedef formalising this definition of a random walk, the following includes the declaration for a function to count the number of crossings: namespace knots { typedef std::vector
walk; size_t crossings(const walk &w); } The implementation of crossings needs to iterate through each position in the walk and check whether or not it has already been visited. Since we went out of our way to make position compatible with std::set, it seems to be a natural choice to keep track of the visited positions. April 2008 | Overload | 11 FEATURE RICHARD HARRIS Whilst recursion can greatly simplify the expression of these kinds of operations, it can, in some situations at least, be less efficient than iteration size_t knots::crossings(const walk &w) { size_t knots = 0; position p(0, 0); std::set
visited; walk::const_iterator first = w.begin(); walk::const_iterator last = w.end(); visited.insert(p); while(first!=last) { if(*first>8) throw std::invalid_argument(""); long dx = long(*first)%3 - 1; long dy = long(*first)/3 - 1; p = p.move(dx, dy); if(!visited.insert(p).second) ++knots; ++first; } return knots; void knots::full_crossings( walk &w, knot_histogram &h, size_t n) { if(n==w.size()) { h.add(crossings(w)); } else { for(size_t i=0;i!=9;++i) { w[n] = i; full_crossings(w, h, n+1); } } } void knots::full_crossings(knot_histogram &h) { walk w(h.walk_length()); full_crossings(w, h, 0); } Listing 8 } Listing 7 Listing 7 shows counting the self crossings. The principal trick we're exploiting to update the position as we iterate through the walk is the use of integer division and modulus to generate the nine distinct steps. At the risk of labouring the point, figure 3 (mapping the step id to the offsets) illustrates how this works. step step%3-1 step/3-1 0 -1 -1 1 0 -1 2 1 -1 3 -1 0 4 0 0 5 1 0 6 -1 1 7 0 1 8 1 1 Figure 3 12 | Overload | April 2008 Ideally, instead of throwing an exception when a step in a walk is too large we should create a class to represent a limited range integer and use it instead of unsigned char. That would be a little too much work for this article however, so I'm not going to bother. So now we're ready to start generating random walks and taking some measurements. The temptation to use a recursive algorithm to generate the full set of walks of a given length is strong; the approach is a natural fit for this kind of problem. At each step we can iterate over every possible move and then recursively generate the remainder of the walk. Each time we reach the end of a walk we add the number of crossings to the histogram to record the results. Listing 8, which calculates the histogram of self crossings, illustrates how we might implement this. Whilst recursion can greatly simplify the expression of these kinds of operations, it can, in some situations at least, be less efficient than iteration. Is it possible to express this operation succinctly with an iterative approach? Well, std::next_permutation provides us with a clue as to how to go about it. It takes an iterator range and transforms it to the lexicographically next greatest permutation of the contained values. What we need is a next_state function that transforms the values in an iterator range to the lexicographically next greatest set of values. To make it as general as possible, we shouldn't assume that the values are integer types. We must assume a method for transforming a value to the next greatest, however. We have a likely candidate in operator++; it RICHARD HARRIS FEATURE the complexity arises from setting up the digits and printing out the states rather than from iterating through them template
bool rotate_state(BidIt it, const T &lb, const T &ub) { bool last = ++*it==ub; if(last) *it=lb; return last; } Listing 9 template
bool next_state(BidIt first, BidIt last, const T &ub, const T &lb = T()) BidIt it = last; while(it!=first && rotate_state(--it, lb, ub)); return first!=last && (it!=first || *it!=lb); } Listing 10 we have reached the state in which every digit has the minimum value. Assuming that this was the starting state, have exhausted all possible states and return false to indicate this. Note that we pass in the lower and upper bounds in decreasing order. This is because there is a reasonable value for the lower bound, namely the default constructed value. Note that built in types will be zero initialised which is very likely to be what we want for integer valued states. typedef std::vector
digits_type; typedef std::vector< digits_type::const_iterator> state_type; digits_type digits[0] = digits[1] = digits[2] = digits(3); " "; "o"; "x"; state_type state(2, digits.begin()); std::cout << "12" << std::endl; do { do { } while(next_state(state.begin(), state.end(), 2)); Listing 11 already does what we need for integer types and can be overloaded for user defined classes. If overloading is not appropriate, perhaps the state transformation is too computationally expensive or our state is formed from classes that we cannot modify, we could instead use iterators into a container of states. So how should the algorithm operate? Well, we need simply observe that iterating through a set of states is equivalent to counting through a set of integers. Each time a digit takes its maximum value, or upper bound, we set it to its minimum value, or lower bound, and perform a carry; i.e. increment the next most significant digit. We begin with a helper function to increment a digit and indicate whether or not we need to carry. Listing 9 shows rotating a digit of the state. Figure 4 Listing 11 illustrates the use of next_state for states with integer valued digits and Figure 4 illustrates the output from this code snippet. std::vector
state(3, 0); std::ostream_iterator
out(std::cout); std::copy(state.begin(), state.end(), out); std::cout << std::endl; 000 001 010 011 100 101 110 111 state_type::const_iterator first = state.begin(); state_type::const_iterator last = state.end(); while(first!=last) std::cout << **first++; std::cout << std::endl; } while(next_state(state.begin(), state.end(), digits.end(), digits.begin())); Listing 12 Listing 12 illustrates the more complex task of iterating through states with a compound type for its digits, in this case std::string. As discussed earlier, if we store the set of digits in a container we can use iterators to represent the current value of a digit. The output of Listing 12 is shown in Figure 5. Given this we need only take care that the carry operation ripples through the iterator range correctly. Listing 10 shows generating the next state. As can be seen, the complexity arises from setting up the digits and printing out the states rather than from iterating through them, which remains as simple as it was in the integer case. All of the work is done in the while statement. We iterate backwards through the range, rotating the state for as long as we need to carry. If we have reached the first digit and it has been rotated back to the lower bound, Rewriting full_crossings to exploit next_state is relatively straightforward. If anything, it's even simpler now than it was with a recursive implementation. 12 o x o oo ox x xo xx Figure 5 April 2008 | Overload | 13 FEATURE RICHARD HARRIS I shall continue to use the iterative approach because of the surprising fact that it actually simplifies the code void knots::full_crossings(knot_histogram &h) { if(h.walk_length()) { walk w(h.walk_length(), 0); h.add(crossings(w)); while(next_state(w.begin(), w.end(), 9)) { h.add(crossings(w)); } } } Listing 13 Listing 13 shows calculating the histogram of self crossings. the number of knots as a proportion of the length of the walk, so the histograms will record counts from 0.0 to 1.0. So how are the knots distributed? Is there a standard statistical distribution that describes them? Well, I have my suspicions, but before we can check them we need to know the average, or mean, number of knots for a walk of a given length. We can calculate the observed mean number of crossings directly from these histograms. Firstly we should note that the walks recorded in each bucket are those with lengths less than the label, but greater than or equal to that of the previous bucket. For these short walks, we have one knot count per bucket, so the number of knots must be the previous bucket's value and zero for the first bucket. To calculate the mean, we simply add up the proportion of the walks in each bucket multiplied by the number of knots it represents. Recall that the mean is defined as the expected number of knots and that we use E(x) to denote the expected value of x. n But is it any more efficient? Sadly, not very much so, as Figure 6, which shows the computational expense of generating knot histograms, clearly illustrates. So why not? Could it be that the cost of counting the number of self crossings vastly outweighs the cost of recursively constructing the walk; the use of std::set to keep track of the visited locations results in O(n ln n) complexity for n crossings. Or perhaps that my compiler and the hardware I'm using are able to mitigate the cost of recursion that I recall from my youth. E (knots) = --------------------n i–1 count(i) - × -----------------∑ --------n n 9 –1 i=1 As pointed out above, we're ignoring the walk with the maximum number of knots, so there are only 9n-1 walks. The results of this calculation are given in Figure 8, which shows the expected proportional number of knots for walks of length 6, 7, 8 and 9. So can we deduce an explicit, or closed form, formula for the expected number of knots? Well, we shall have a go at it next time. Actually, no. Had I profiled the code in the first place as did one of the reviewers (thanks Roger), I'd have noticed that most of the time is spent inserting and erasing elements from std::set. Unfortunately I've not given myself enough time to replace std::set with something more efficient. Acknowledgements With thanks to Andrey Biryuk and Chris Morris for proof reading this article. However, I shall continue to use the iterative approach because of the surprising fact that it actually simplifies the code. So what do the histograms look like? Figure 7 shows the results for exhaustive enumeration of walks of lengths from six to nine steps. Before looking at them, it's worth pointing out again that our histogram records n recursed time (seconds iterated time (seconds) 5 0.17 0.17 6 1.80 1.69 7 17.80 16.89 8 175.56 167.51 9 1701.56 1650.41 Figure 6 14 | Overload | April 2008 References and further reading [Bachelier00] Bachelier, L., Théorie de la Spéculation, PhD thesis, 1900. [Brown28] Brown, R., 'A brief account of microscopical observations made in the months of June, July and August, 1827, on the particles contained in the pollen of plants; and on the general existence of active molecules in organic and inorganic bodies', Edinburgh New Philosophical Journal, July-September, pp. 358-371, 1828. [Feller68] Feller, W., An Introduction to Probability Theory and its Applications, vol. 1, 3rd ed., Wiley, 1968. [Hayes97] Hayes, B., 'Square Knots', American Scientist, vol. 85, num. 6, pp. 506-510, 1997 [Hull05] Hull, J., Options, Futures and Other Derivatives, 6th ed., Prentice Hall, 2005. [Jerome89] Jerome, J. K., Three Men in a Boat, J. W. Arrowsmith, 1889. RICHARD HARRIS [Nechaev98] Nechaev, S., 'Statistics of Knots and Entangled Random Walks', arXiv:cond-mat/9812205 v1, www.arxiv.org, 1998. [Press92] Press et al., Numerical Recipes in C, 2nd ed., Cambridge, 1992 [Robbins55] Robbins, H., 'A Remark on Stirling's Formula', American Mathematical Monthly, vol. 62, pp. 26-29, 1955. FEATURE [Thiele80] Theile, T. N., 'Om Anvendelse af mindste Kvadraters Methode i nogle Tilfælde, hvor en Komplikation af visse Slags uensartede tilfældige Fejlkilder giver Fejlene en 'systematisk' Karakter', Vidensk. Selsk. Skr. 5. Rk., naturvid. og mat. Afd., vol. 12, pp. 381-408, 1880. Figure 7 . n E(knots)/n 6 0.2492 7 0.2623 8 0.2737 9 0.2837 Figure 8 April 2008 | Overload | 15 FEATURE TEEDY DEIGH The Way of the Consultant Effective communication is a challenging reponsibility of the communicator – Teedy Deigh offers some observations on how consultants can meet this challenge. A s with many other skills in life, there are different levels of mastery and achievement in reviewing things such as code, architecture or development process. At the pinnacle of achievement is the master level of consultant, where the meaning of any statement is shrouded in deep mystery, opportunistic ambiguity, tenebrous circumlocution and consultancy fees. But how can one distinguish between the different levels? Consider the following response to a questionable system implementation: What do I think? This code sucks! Although brief and honest, it is clearly the response of someone who has not even been initiated on the path. The following, however, shows some promise, but no more than that of an infant Padawan: What do I think? Well... it's not all bad! Nothing that some aggressive, merciless and inconsiderate refactoring couldn't solve. By contrast the following response demonstrates a superior command of the panoply of techniques involved in consultancy: What do I think? Although there are aspects of the system's design that are sound, the solution as a whole may be better aligned with the needs of the business by leveraging the synergies of complementary solution paths. The resulting amelioration of quality 16 | Overload | April 2008 will be further enhanced by the displacement of vestigial solution components extant from the status quo. Only when the other person looks completely perplexed, appears hypnotised, has fallen asleep or has wandered off, can one know that they have ascended to an introductory level of mastery. The principal consultant, however, is one who has passed through the gate without even bothering to shut it once through. A true Jedi master of consultancy is able to present a dazzling array of possibilities with the swiftness of a light sabre, the sharpness of an Overload reviewer's feedback and the simplicity of a US President: What do I think? It depends. Here ends the lessen (sic). Following the valuable insights and success of her April 2007 article, A Practical Form of OO Layering, Teedy Deigh has found herself increasingly involved in the rarefied atmosphere of software development consultancy. She is only too happy to pass off her subjective whims as sound advice, and her opinions as grounded in objective reality. It is almost as much fun as programming Singletons!
File Information
Link or Click Back
portlet Settings
Here will be a configuration form
Site Map 1
Site Map 2
Site Map 3
Site Map 4
Site Map 5
Site Map 6
Site Map 7
Site Map 8
Site Map 9
Site Map 10
Site Map 11
Site Map 12
Site Map 13
Site Map 14
Site Map 15
Site Map 16
Site Map 17
Site Map 18
Site Map 19
Site Map 20
Site Map 21
Site Map 22
Site Map 23
Site Map 24
Site Map 25
Site Map 26
Site Map 27
Site Map 28
Site Map 29
Site Map 30
Site Map 31
Site Map 32
Site Map 33
Site Map 34
Site Map 35
Site Map 36
Site Map 37
Site Map 38
Site Map 39
Site Map 40
Site Map 41
Site Map 42
Site Map 43
Site Map 44
Site Map 45
Site Map 46
Site Map 47
Site Map 48
Site Map 49
Site Map 50
Site Map 51
Site Map 52
Site Map 53
Site Map 54
Site Map 55
Site Map 56
Site Map 57
Site Map 58
Site Map 59
Site Map 60
Site Map 61
Site Map 62
Site Map 63
Site Map 64
Site Map 65
Site Map 66
Site Map 67
Site Map 68
Site Map 69
Site Map 70
Site Map 71
Site Map 72
Site Map 73
Site Map 74
Site Map 75
Site Map 76
Site Map 77
Site Map 78
Site Map 79
Site Map 80
Site Map 81
Site Map 82
Site Map 83
Site Map 84
Site Map 85
Site Map 86
Site Map 87
Site Map 88
Site Map 89
Site Map 90
Site Map 91
Site Map 92
Site Map 93
Site Map 94
Site Map 95
Site Map 96
Site Map 97
Site Map 98
Site Map 99
Site Map 100
Site Map 101
Site Map 102
Site Map 103
Site Map 104
Site Map 105
Site Map 106
Site Map 107
Site Map 108
Site Map 109
Site Map 110
Site Map 111
Site Map 112
Site Map 113
Site Map 114
Site Map 115
Site Map 116
Site Map 117
Site Map 118
Site Map 119
Site Map 120
Site Map 121
Site Map 122
Site Map 123
Site Map 124
Site Map 125
Site Map 126
Site Map 127
Site Map 128
Site Map 129
Site Map 130
Site Map 131
Site Map 132
Site Map 133
Site Map 134
Site Map 135
Site Map 136
Site Map 137
Site Map 138
Site Map 139
Site Map 140
Site Map 141
Site Map 142
Site Map 143
Site Map 144
Site Map 145
Site Map 146
Site Map 147
Site Map 148
Site Map 149
Site Map 150
Site Map 151
Site Map 152
Site Map 153
Site Map 154
Site Map 155
Site Map 156
Site Map 157
Site Map 158
Site Map 159
Site Map 160
Site Map 161
Site Map 162
Site Map 163
Site Map 164
Site Map 165
Site Map 166
Site Map 167
Site Map 168
Site Map 169
Site Map 170
Site Map 171
Site Map 172
Site Map 173
Site Map 174
Site Map 175
Site Map 176
Site Map 177
Site Map 178
Site Map 179
Site Map 180
Site Map 181
Site Map 182
Site Map 183
Site Map 184
Site Map 185
Site Map 186
Site Map 187
Site Map 188
Site Map 189
Site Map 190
Site Map 191
Site Map 192
Site Map 193
Site Map 194
Site Map 195
Site Map 196
Site Map 197
Site Map 198
Site Map 199
Site Map 200
Site Map 201
Site Map 202
Site Map 203
Site Map 204
Site Map 205
Site Map 206
Site Map 207
Site Map 208
Site Map 209
Site Map 210
Site Map 211
Site Map 212
Site Map 213
Site Map 214
Site Map 215
Site Map 216
Site Map 217
Site Map 218
Site Map 219
Site Map 220
Site Map 221
Site Map 222
Site Map 223
Site Map 224
Site Map 225
Site Map 226
Site Map 227
Site Map 228
Site Map 229
Site Map 230
Site Map 231
Site Map 232
Site Map 233
Site Map 234
Site Map 235
Site Map 236
Site Map 237
Site Map 238
Site Map 239
Site Map 240
Site Map 241
Site Map 242
Site Map 243
Site Map 244
Site Map 245
Site Map 246
Site Map 247
Site Map 248
Site Map 249
Site Map 250
Site Map 251
Site Map 252
Site Map 253
Site Map 254
Site Map 255
Site Map 256
Site Map 257
Site Map 258
Site Map 259
Site Map 260
Site Map 261
Site Map 262
Site Map 263
Site Map 264
Site Map 265
Site Map 266
Site Map 267
Site Map 268
Site Map 269
Site Map 270
Site Map 271
Site Map 272
Site Map 273
Site Map 274
Site Map 275
Site Map 276
Site Map 277
Site Map 278
Site Map 279
Site Map 280
Site Map 281


text:
You may have reached this page due to new security upgrades that have been implemented regarding multiple user logins. For security reasons, only one user is able to be signed in to an account per session. If multiple users at a single site need online access, please contact firstname.lastname@example.com for firm access reduced pricing. If, however, you believe your login information has been compromised, please call customer service at 1-800-451-9998 to determine how to reset your password. Already a paid subscriber but not registered for online access yet? For instructions on how to get premium web access, click here.
Bill in N.C. House would protect payments to appraisers
Last fall, a company called ES Appraisal Services, based in Florida, went bankrupt. That the company went under isn't unusual, as companies fold every day. But ES was the latest of three appraisal management companies that went out of business recently, all with the same troubling trend for real estate appraisers.

subset: commoncrawl


text:
If you've been around the sport of MMA, you definitely have heard of Arizona's Rage in the Cage. The man behind Rage in the Cage is Roland Sarria. Sarria has been promoting since 1998, and he knows virtually everything about the MMA scene in Arizona. He has also trained many fighters, including several UFC and King of the Cage veterans.
Sarria not only brings us up to date on Rage in the Cage, he talks about his experiences with Joe Riggs, Edwin Dewees, Gilbert Aldana, John Levenson, Michelle "Grapple Girl" Farrow, Jimmy Ambriz, Eric Prindle and much more! Sarria has plenty of Rage in the Cage shows coming up and he gives us the latest on what's happening with his promotion.
After this interview, Bob releases news on the upcoming Affliction show, the EliteXC - CBS connection, the IFL, Anderson Silva, "Minotauro" Nogueira and more. And, as always, listener emails are answered.
To listen, click here: http://carsonscorner.podomatic.com/


text:
The Virginia Center for School and Campus Safety (VCSCS) located within the DCJS Division of Law Enforcement reflects Virginia's commitment to providing safe and productive learning environments for all students and staff in our schools today. The VCSCS is a resource and training center for information and research about national and statewide school safety efforts and initiatives.
The VCSCS was created through Virginia Code § 9.1-184. and is mandated to provide training for Virginia public school personnel, serve as a resource and referral center for Virginia school divisions, collect and disseminate information on school safety initiatives and school safety data, among other things.
The path towards academic excellence should be free from the fear of crime and violence. Through the VCSCS, schools and communities have access to proactive trainings, topical resources, public-private partnerships, data collection and evaluation, and an annual school safety conference. Thank you for your interest in the Virginia Center for School and Campus Safety. We hope that this site serves you well in your school safety efforts. For additional information, please contact us.
Donna Michaelis, Manager, School and Campus Safety
Virginia Department of Criminal Justice Services
1100 Bank Street
Richmond, VA 23219
Contact the Director
Contact Private Security Services
Contact Regulatory Affairs
Contact Law Enforcement Services
Contact Victims Services
Contact Juvenile Services
Contact Correctional Services
Contact Research Center
Director's Bio
Human Trafficking
Report Campus or Local Emergency
Forfeited Asset Sharing Program
Blueprints for Change: Criminal Justice Policy Issues in Virginia
Strategic & Service Area Plans
Virginia Law Enforcement Professional Standards Commission
Integrated Justice Program


text:
Stay healthy with a healthy Valentine's trip that includes romantic jogging, hiking, and nature watching opportunities. Enderts Beach is in the Del Norte Coast Redwoods State Park in California. It is just off Highway 101 and a day trip from Fresno. Why is this included as part of a Valentine's Day Guide. The reason is simple. It is extremely easy to drive to from Fresno with large roads the majority of the way so your attention can be split between driving and your honey with minimal risk. Additionally Enderts beach is close to Highway 101 so you can quickly go from the beach to a convenient store in case you forgot anything, such as supplies for a romantic picnic lunch for your love. The key reason it was included as part of a Valentine's Day Guide is because it is extremely peaceful and quick. There is solitude like nothing you have ever seen here. The ocean is relatively calm and birds are few. You have the soft sounds of nature and your loved one as the only noise. Additionally this is included as part of a Valentine's Day Guide because the beach is long and straight so you can walk or jog without worry of getting lost along the way. As an added treat there are whales not far away. You can give that girl a Valentine's to remember as you point out the whale in the distance, noticeable but the spout of water.
What Valentine's Day Guide would be complete without a hotel recommendation. If you are looking for inexpensive consider the Comfort Inn and Suites Redwood Coast. Based on personal experience it is clean, the staff is polite and it is relatively inexpensive. Another relatively inexpensive option is the Best Western Northwoods Inn. If you are looking for a smaller locale that is a bit more private and closer to the beach you might consider the Crescent Beach Motel. It is also relatively reasonably priced.
The best thing about this Valentine's Day Guide is that going to Endert Beach you can get your exercise on so you stay looking fit and great for that special someone and have no "I overate" regrets.


text:
This book is a sampling of the variety of work that the artist has done over the years and contains subject matter such as wildlife, landscape, seascape, portrait and figurative.
The mediums include oil, watercolor, pastel and mixed media.
Born Western Pennsylvania 1927. Art Institute of Pittsburgh 1947-48 Worked as Electrical designer for 30 years. Full time artist since 1980 Prints published by Mill Pond Press and Krapf Images. Collector plates by Bradford Eschange. Major Wildlife Art shows such as Pac Rim, Southeastern, Ducks Unlimited, etc.
Comment posted.
RBMcGrath says This Art book is beautiful. The paintings are wonderfully and realistically rendered. Kudos to Paul Krapf
posted at 07:28PM Jul 29 PST
Log in or create an account to post a comment.
Roughs, Sketches, Drawings, some for Paintings Published April 28, 2016
'Becca' (My Muse, who I've never met) Published January 30, 2016
Additional Artworks of Paul Krapf Published November 03, 2009
More Artworks of Paul Krapf Published October 26, 2009
Artworks of Paul Krapf Published August 10, 2009


text:
Oct. 29, 2011
Final Stats | Quotes | Notes
Tulane/East Carolina Game Book In PDF Format
GREENVILLE, N.C. - A strong second half, both offensively and defensively, vaulted East Carolina to a 34-13 victory over Tulane Saturday afternoon in front of an announced crowd of 49,410 at Dowdy-Ficklen Stadium on the Pirates' homecoming.
Tulane (2-7, 1-4 C-USA) trailed 17-13 at halftime in the blustery Fall weather conditions, but ECU (4-4, 3-1 C-USA) managed two second-half touchdowns and a field goal and held the Green Wave scoreless to pull away with their third straight victory and send Tulane home with a sixth straight loss.
The Green Wave collected 178 yards on 33 plays in the opening two quarters, but was held to just 88 yards on 33 plays in the final two quarters. ECU gained 461 yards of total yards for the game, including 336 through the air.
"In a tight game in this environment against a quality team like East Carolina, you need to make the most of your chances," Tulane interim head coach Mark Hutson said. "We knew this would be a tough challenge because they weathered a tough non-conference schedule and they are hitting their stride.
"Defensively, we knew they would get their passing yards and we wanted to rally up and keep their receivers in front of the chains and tackle. We did that for the most part, but their quarterback had another outstanding game and made several plays with his feet. He was able to get loose on the some read-zone plays in the redzone and score. We need to correct this because we're going to see more read-zone offenses down the road. The defense made several stops inside the redzone and held them to field goals."
Orleans Darkwa once again provided the bulk of the offense for the Green Wave. The sophomore running back gained 89 yards on 15 carries and scored the only touchdown of the afternoon. He rattled off a long rush of 21 yards and averaged 5.9 yards per carry.
"I feel like we were able to execute early," Darkwa said. "We were able to drive and our defense forced a turnover. But when we got in the redzone, we needed to score more than three points. We need to score touchdowns when we get down there and make the most of our opportunities."
Freshman Robert Kelley added 31 yards on the ground on seven carries to go with his 111 kickoff return yards for 142 all-purpose yards, the seventh 100-plus yard game for the Tulane freshman.
Junior quarterback Ryan Griffin connected on 16 of 31 pass attempts with 132 yards for Tulane, while sophomore receiver Wilson Van Hooser pulled in four of those passes for 28 yards.
ECU opened the scoring with a nine-play, 69-yard drive that resulted in a five-yard run by quarterback Dominique Davis on the team's second possession of the game with 7:59 remaining in the first quarter. The Pirates' drive started after Tulane kicker Cairo Santos' 48-yard field goal attempt went wide right.
Tulane got on the board with a 20-yard field goal by Santos that followed an ECU fumble recovered and returned by junior linebacker Trent Mackey to the Pirates' five-yard line.
Mackey finished with a game-high 15 tackles, while Ryan Travis added a career-high 12 stops. Dezman Moses had seven tackles, including 1.5 sacks to increase his season total to 7.5 sacks.
"We had a pretty good game defensively," Mackey said. "We gave good effort and played hard, but just came up short."
The Green Wave then took the lead with a two-play, 47-yard drive that ended with a seven-yard run by Darkwa. Santos' extra point gave Tulane a 10-7 lead. The drive began after ECU's punter, Ben Ryan, managed only an 11-yard kick.
The Pirates retook the lead on the ensuing drive when Davis found Lance Lewis on a crossing route for a one-yard touchdown strike with 11:09 left in the second quarter.
Santos answered with his second of two field goals of the day, a 26-yarder with 5:48 left in the half, cutting the deficit to one, 14-13.
An ECU 35-yard field goal from the foot of Mike Barbour with 4:32 left in the second completed the scoring for the first half, giving the Pirates a 17-13 lead at the break.
Including that Barbour field goal, ECU outscored Tulane 20-0 the rest of the way.
Davis finished the game for the Pirates with 329 passing yards on 29 of 46 with one touchdown. He also added 43 yards on the ground with two touchdowns on eight carries.
Tulane will once against serve as the homecoming opponent next Saturday when they visit SMU in Gerald J. Ford Stadium in Dallas for a 2 p.m. CT kickoff.


text:
Event Date: 11/07/2012Event Time: 12:00 PM - 3:00 PMLocation: Rosemont College, Rosemont, PADescription: All students and alumni are invited to attend this SEPCHE sponsored event on Rosemont College's campus. Meet with over 50 employers looking to fill full and part-time, as well as seasonal recruitment needs. Internships opportunities will also be available. The event is free. Pre-registration is not required. Dress professionally and bring at least 25 excellent resumes.The following organizations have signed up: Aflac Bard College Globalization and International Affairs Program,CCRES,City Year Greater Philadelphia,County of Chester,Devereux,EducationWorks,Fastenal Foundations, Behavioral Health,Holy Family University,Immaculata College of Graduate Studies,ING, Financial Partners,NAVSUP WSS Neumann University,Northwest Mutual Financial Network,PA STATE CIVIL SERVICE COMMISSION, Pennsylvania Department of Revenue,Philadelphia District Attorney's Office, Philadelphia Police Department,Relative Care, LLC ReMed Recovery Care Centers,ReminderMedia,Rosemont College,State of Delaware,Sunoco Inc. (R&M) Temple Univ School of Social Work Van service is available, but space is limited. Sign up for the van in GH 150.
© 2012


text:
Perfect your cupcake decorating skills, learn how to make scrapbooks on Shutterfly, pick up a new hobby in jewelry making and discover paranormal research – all during Moraine Park Technical College's free Saturday Sampler event, set for Saturday, Nov. 23, on Moraine Park's Fond du Lac campus.
Two Saturday Sampler sessions will take place between 9-11:15 a.m. Participants can choose between Decorating Delicious Turkey-Themed Cupcakes or Snapshots of Shutterfly from 9-10 a.m., then Beautiful Beaded Earrings or Paranormal Phenomena Update With an Expert from 10:15-11:15 a.m.
To register for the event, call Melissa Koppenhaver at 1-920-929-2117. Registration deadline for both courses is Wednesday, Nov. 20, or until sessions are filled.
Moraine Park Technical College was established in 1912 and is one of 16 technical college districts that make up the Wisconsin Technical College System. With campuses in Beaver Dam, Fond du Lac and West Bend, Moraine Park offers more than 100 associate of applied science degrees, technical diplomas, apprenticeships and certificates delivered in a variety of formats — classroom, online and blended. Training and technical assistance for businesses is also offered.
Moraine Park Technical College is accredited by the HigherLearning Commission
Contact Info/Legal / TERMS OF USE
Moraine Park Technical College | 235 North National Avenue | Fond du Lac, WI 54936-1940 | An Equal Opportunity College | © 2013


text:
Promising; positive; pleasant. "Her review of the new restaurant was favorable, as she had been very pleased by the service she received and the food she tasted." "As he planned his camping trip, he hoped the weather conditions would be favorable for all their planned activities."
Use favorable in a sentence


text:
I am writing this in regard to all these commercials by lawyers who are telling the public they "can sue." I don't know how many I have seen on TV this afternoon alone. This goes from office workers, construction work, medical situations, etc.
When will they have commercials telling the public to take care of themselves, stay in school, do your best, don't look for a "ride" in life, take a job that you may not like to get by until you can find something better?
It seems like there is no direction, since people seem not to have it, to take care of oneself. It is, "Let me sit back and be taken care of." It makes me sad. The era I grew up in was nothing like what it is today. There was pride, respect and honesty. Will it ever go back the way it should be? Who knows. I hope so, but hope only goes so far. We need action.
Barbara Carreiro
Location, ST | website.com


text:
Tour the Sanctuary
Meet Our Residents
Education Center
Main Barn
2 or 3 Stall Barn
Feed Room
Outdoor Arena
Paddock Graphics
Pond & Picnic Area
In Memory
Pond & Picnic Area
The pond and picnic areas at Equine Advocates Rescue & Sanctuary were created from what appeared to be unusable swampy land. Through innovative land management design, we created one of the most serene and beautiful spots on the property.
It is home to a family of muskrats, hundreds of frogs, lots of rabbits, turtles, visiting geese and deer.
This area is the perfect setting for a relaxing picnic lunch or meditation, but you will always be watched by the horses nearby!


text:
These are great! I love that they are sweet, but not TOO sweet. I made them with my 2 1/2 year old and we "painted" them with icing. I didn't have pasteurized egg whites, so I just made a powdered sugar icing (with vanilla and milk), and that turned out great as well. It still hardens, it's just not shiny like the decorator's icing would be. Thanks for the recipe for a cookie that has a little nutrition in it!
Holiday Cookie Cutouts
From EatingWell: Fall 2002
There is no need to wait for December to enjoy crisp sugar cookies in fanciful shapes. Capture the spirit of fall by baking maple leaf- or pumpkin-shaped cookies. And when the festive season arrives, have fun with holiday shapes like stars and wreaths. Use the Cinnamon-Sugar Topping for crisp cookies that make perfect teatime treats or finish with Decorator Icing for more elaborate cookies.


text:
Verizon Moto G Android 4.4 KitKat update now rolling out
Verizon's version of the Moto X getting Android 4.4 KitKat first was an exception. The carrier sometimes nicknamed Big Red is usually the last to roll out software updates for its smartphones, and that has once again happened in the case of the Moto G.
Motorola's budget offering is incredibly cheap at Verizon, going for just $99.99 sans contract, but it launched running Android 4.3 Jelly Bean. Now though, the update to Android 4.4 KitKat has finally started rolling out for units bought at Verizon, bringing them in line with all the other Moto Gs sold across the world. The KitKat update first started making its way to the Moto G in December, and last month it started to arrive in more and more countries.
If you own a Moto G and got it from Verizon, it should be notifying you that an update is available any day now. If, however, you're impatient and feel that you can't wait for that to happen, you could try manually checking for the update by going to Settings > About phone. Who knows, maybe you'll be lucky.
After applying the update you'll be running Android 4.4.2. The estimated installation time is around ten minutes.
Via Android Central


text:
Interiors with a touch of the outdoors!
Give your bedroom that unique earthy touch with the Eden Bedroom Range. The moment you step into a bedroom furnished with the Eden range, you will notice something pure and natural about the room. With a dual-colour headboard, a curvilinear profile and stylish burn marks, the bed exudes a natural charm and poise. This earthen look is also translated into the drawer chest, wardrobe and other elements in this range. An amalgam of finish, style and freshness; the Eden Bedroom Range is perfect for those who like to live at one with nature.


text:
Last week, millions of you (literally!) supported your countries and favorite pop stars by participating in the first round of our 2012 Pop Olympics. We're super grateful for the enormous patience and dedication you showed during the occasionally buggy process, and we promise that this week will be a much smoother experience.
PHOTOS: 25 Awesome Things About South Korea
PHOTOS: 25 Awesome Things About Great Britian
This week, the field has been narrowed from the initial 16 participating artists to your four finalists, vying for the title of World's Greatest Pop Star. They are: JUSTIN BIEBER (Canada), GIRLS' GENERATION (South Korea), TAYLOR SWIFT (U.S.A.) and THE WANTED (Great Britain). During the week, our four Pop Olympians will face off in a series of five musical competitions–a pop pentathalon–and, as always, you and only you get to determine the winner with your vote. Among the week's events: Best Song, Best Video, and Best YouTube Moment. You can vote in each event as many times as you'd like, and the voting for each will remain open throughout the week. The results will be tallied at week's end (midnight on Sunday, August 5), and on Monday, Aug. 6, we will announce the Gold, Silver and Bronze metal winners in the 2012 Pop Olympics.
PHOTOS: 25 Awesome Things About the U.S.
PHOTOS: 25 Awesome Things About Canada
And now, the second event: Best YouTube Moment. Watch through some of our competitors' most viral videos below, and vote for which one you think is the best. And if you haven't yet, be sure to head back over to our Best Song poll as well to vote in that.
CONTEST: Be A Pop Olympics Team Coach And Win A T-Shirt!
Who Has the Best YouTube Moment?
Justin Bieber - "Call Me Maybe" Lip Dub
301 votes0%
Girls' Generation - Individual Talents
33,437 votes0%
Taylor Swift - "Super Bass" Radio Rap
964 votes0%
The Wanted - Christina Aguilera Dis
9,558 votes100%
Total Votes: 0


text:
Klara Vyskocilova completed her career as the two-time Louisiana Player of the Year.
June 1, 2014
New Orleans - Tulane senior standout Klara Vyskocilova has been named the 2014 Louisiana Player of the Year and was also tabbed to the All-Louisiana first team, as it was announced by the Louisiana Sports Writers Association (LSWA) on Sunday morning.
A native of Klatovy, Czech Republic, Vyskocilova earned the state's player of the year honor for the second straight season after claiming co-player of the year honors a year ago, and she is a repeat performer to the all-state first team.
Vyskocilova turned in one of the finest seasons in school history in 2013-14. The 2014 Conference USA Player of the Year and All C-USA first team selection, she completed the season with a 20-7 overall record but was undefeated during the spring in dual matches with an impressive 13-0 record at the top singles spot. She won 15 of her final 16 singles matches, chalked up a 5-3 mark against nationally ranked players, including a pair of Top-25 upsets along the way this season.
Vyskocilova was selected to the 2014 NCAA Division I Women's Tennis Singles Championships and became the first player to represent Tulane at the national singles championship since Jenny Kuehn in 2005. Vyskocilova suffered her first and only loss of the spring to the nation's sixth-ranked player in the first round. She completed her career with a singles record of 84-37 and doubles mark of 72-42.
Vyskocilova was a two-year letterwinner for the Green Wave and earned her bachelor's degree in finance last month. She was awarded with the prestigious Tulane 34 Award, which is presented annually to 34 graduates who have distinguished themselves throughout their collegiate lives. Students are recognized for their exemplary leadership, service and academic excellence. Named for the year the University was founded, 1834, Tulane 34 is among the most coveted honors bestowed upon the student body.
She claimed C-USA Player of the Week honors three times during her career, was twice named to the C-USA Commissioner's Honor Roll and was voted to the 2014 C-USA All-Academic Women's Tennis Team. Vyskocilova also worked on the Greening Yulman project, which aimed to help build the Green Wave's new on-campus football stadium while benefiting the environment and improving the University's LEED ranking.


text:
The Oldest Lunar Calendar - Aurignacian (32,000 BCE)
Tashi Delek Losar! while this usually means 'Joyous New Year' in Tibetan, this year it also includes 'Happy Valentine's Night!!'
Most calendars associated with Tantric practices are lunar. That is, they measure time from one new moon to another, and years are composed of 13 new lunations. The relationship between lunar calendars and Tantra has to do with spiritual practices that are woven into women's fertility cycles, the energy of which is especially potent at New (tirsthi) and Full (purna) phases.
The Tibetan New Year (Losar) is celebrated on the 2nd New Moon after the Winter Solstice. This year it turns out that the Tibetan calendar starts on February 14, concurrent with Valentine's Day. This coincidence points to a quiet conjunction between the Neoplatonic idea of 'sacred union' or hierogamos, and the middle-Asian development of Tantra. There are two invitational Tantric events in Austin on that weekend, each drawing different sides of that conjunction:
- Charla Hathaway's Bodyjoy's Tantra Puja on February 13, is taking place at Galaxy Dance Studios.
- A four-day Vajrakila Sadhana, February 10-14, led by Lama Yeshe Wangmo, which will culminate in a Losar Feast Offering.
Puja and sadhana are both Sanskrit terms, broadly interchangeable -- but their meanings have been shaped by use in the West. Puja is more often associated with worship - July 6, for example is called 'Gurupuja' in India and is the day set aside for honoring your primary mentor. Puja in the West is the preferred term for rites that honor one's Tantric partner. In contrast there is Sadhana, which also has a ritual component but is an interior process, designed to change the very mechanisms of perception. Sadhana can be a daily or longer process - ritual sadhana such as the Vajrakila can go on for several days.
We have a rare opportunity to have both types of ritual in Austin for this "Valentine's Losar." Even if you are not able to attend Charla's puja or Wangmo's sadhana, there are things you can do to prepare for Valentantra's Day. Stay tuned...
In February: Austin Tantra Examiner interviews Charla Hathaway, founder of BodyJoy, author and certified Sexologist.
Mysti Easterwood, under the pen name Eleusis D, writes Tantra for Bobos! Creative Conversations on Art, Sex and Awakening.


text:
Enjoy an Enchanting and Tantalizing eveningat our 5th Kosher Food & Wine Experience at 6:30PM Tuesday, February 22 at Pier 60 Chelsea Piers in New York City. Taste from a diverse selection of top quality wines from around the world, and sample mouth-watering dishes from the finest purveyors of kosher food. Meet and chat with world-renowned winemakers and proprietors of famous kosher wines.
KFWE 2011 is SOLD OUT! We'll see you there!
As this event involves the consumption of alcoholic beverages, entrance will be permitted only to persons 21 years of age and older. A designated driver is recommended.


text:
Anne Frank: A History for Today
Anne Frank was one of more than a million Jewish children murdered during the Holocaust. Her diary gives us insight into her thoughts. This exhibit gives us insight into the family and world events that shaped her life.
Anne lived for nearly two years in a secret annex in Amsterdam, hiding from the Nazis. She kept a diary in which she recorded her fears, dreams and experiences. Anne's diary, published after her untimely death, is one of the most widely read books after the Bible. Her story has inspired countless children worldwide and is available in 67 languages.
Anne Frank: A History for Today takes you beyond the pages of her diary by providing a wide perspective on the Holocaust, human rights, the Nazis, and the Frank family's experiences in hiding.
The exhibit is in Spanish and English.
Spring Break Events: March 7 through 25
Explore and learn with family-friendly activities throughout Spring Break!
Theater Performances: March 18 through 19 at Museum. Conversations with Anne. Two live performances each day
at 2 p.m. and 6:30 p.m.
Exhibit Sponsors: Clampitt Paper, Dallas Tourism Public Improvement District, Dallas Office of Cultural Affairs, The Catholic Foundation.
Anne Frank: A History for Today was developed by the Anne Frank House and is sponsored in North America by the Anne Frank Center USA.
Image © AFF Basel / AFS Amsterdam


text:
Register now for free, or sign in with any of these services:
915 E Prien Lake Rd, Lake Charles, LA 70601
Phone: (337) 478-1600
2.0 mi
3241 E Prien Lake Rd, Lake Charles, LA 70615
Phone: (337) 480-3788
3.4 mi
2610 Dillard Loop, Lake Charles, LA 70607
Phone: (337) 478-2888
5.8 mi
Can't find a business you think should be on NOLA.com?
Advertise your business with us. Discover all the advantages of being a member of NOLA.com


text:
Skydiving.com now has a network skydiving location serving Hallsboro and Columbus County in North Carolina. Call Skydiving.com at 1-800-617-7948 for details, free information and specials on skydiving in Hallsboro, NC today!
Popular Tags for Skydiving Hallsboro:
Skydiving Hallsboro, Skydiving in Hallsboro, Sky Diving Hallsboro, Skydive Hallsboro NC, Skydiving 28442, Hallsboro Skydiving, Skydiving Hallsboro North Carolina, Skydiving near Hallsboro, Skydiving in Hallsboro North Carolina, Hallsboro Sky Diving, Skydive 28442, Skydiving Hallsboro NC, Skydive Hallsboro, Skydiving Columbus County, Skydive in 28442, Skydiving NC, Sky Diving Hallsboro NC, Hallsboro, North Carolina
Sign up for our newsletter and receive updatesand specials on skydiving across America!


text:
Subaru WRX vs. Mitsubishi Evo
This isn't quite to the point of being embarrassed to be seen in, but suddenly we take back all the smack we said about previous Subaru's sky-high wings and gold wheels. In reflection, nudging past the line of tastefulness was better than the slightly larger '08's unappealing blandness.
Interior design - 7/10
Ignore the outside looks and the new WRX interior is a better place to be. Prior cars weren't just no-nonsense, they were cheap inside. Backseat passengers had little room and a decent sound system meant big bucks. This time around, better quality materials and more room befit the price and dimensions.
Sound system/goodies - 7/10
Always home to a capable sound system (for a price), the WRX for 2008 now offers an 80-watt 4-speaker system standard. It includes an in-dash, single-CD player with auxiliary jack and speed-sensitive volume adjustment. You still have to cough up extra for the 100-watt, six-disc system (part of the $2,100 Premium Package), but the standard and available options are more in tune with the character and price range.
Bang for the buck - 15/20
A good value in this redesign, if not the steal of the century. It's obvious Subaru has taken note of complaints surrounding standard equipment and appointments with the new WRX.
Driving experience - 17/20
If you can stand being seen in what some will mistake for a Nissan rental, the experience from the cockpit will probably make up for it. A tick slower off the line, the midrange is still formidable. Subaru also reminds us the engine is as easily tuned as ever, plus they feel the WRX will stand more distinctly from the upcoming STi.
Overall score - 70/100
Like a comic actor trying to appeal to a more grown-up audience, the WRX takes on a more serious role for 2008. The visual makeover is questionable and the laughs are a little more cerebral, but it's still a crowd-pleaser.
Mitsubishi Lancer Evolution XMSRP (Base, est): $32,000
Engine: 2.0-liter turbocharged inline 4-cylinder
Horsepower (est): 285 bhp
Torque (est): 265 ft-lbs
MPG (city/highway, est): 20/25
Performance - 17/20
If you thought the old car was hot, this car is outstanding. Mitsubishi has been generous with official photos for some time now, but we're still waiting for the steak (testing, or at least official stats) to accompany that visual sizzle. Early suggestions at 300-plus horsepower may have been a little optimistic; our educated guess is a still-healthy 285, with 265 ft-lbs of torque, give or take on either figure. A couple highlights we can share are in the handling and transmission details. First, the new Evo will come with multi-mode Super All-Wheel Control. It combines active stability control, an active center differential, active yaw control and antilock brakes. If it sounds like the fun police have won, think again. This all works to deliver superior handling, we're told, and even hedonistic drifting if so desired. Also, the Twin Clutch Sport Shift Transmission will come with odd and even gears on separate shafts and clutches, making for faster shifts with reduced power loss compared to a conventional automatic. If you insist on exercising your left foot, a five-speed manual can be had instead.
Find out more about the Lancer Evolution...
Have a question? Get it answered by AskMen's guyQ.


text:
Footballers are better at predicting opponents' movements, MRI research finds
Ever wondered what makes Cristiano Ronaldo so good at intercepting the ball?
By studying brain scans, Brunel University researchers have discovered that highly-skilled footballers are able to activate more areas of their brain than novices when they see an opponent heading towards them, making them better able to anticipate their moves. The research, published in the Journal of Sport and Exercise Psychology, found that experienced players seem to have developed a 'checking' system that suppresses the urge to react instinctively, making them less likely to fall for deceptive feints.
The research, which looks to discover the neural basis for cognitive superiority, involved 39 participants ranging from semi-professional footballers to novices. The participants lay in an MRI scanner whilst watching clips of a junior international-level player dribbling a ball toward them. On some occasions the oncoming player performed a deceptive manoeuvre and participants had to decide in which direction to move, while their brain activity was monitored. They were then grouped according to how well they performed. The skilled footballers were more attuned to the actions and deceptive movements of opponents than their less-skilled counterparts.
The results also showed evidence of stronger activation of the Mirror Neuron System (MNS) when predicting an opponent's actions. The MNS is active not only when performing an action within our personal repertoire, but also when viewing that same action performed by others. Hence, there was clear evidence of 'recognition' of the opponents' movements in the more skilled performers.
Notes to editors
For more information or for interviews contact Rebecca Griffiths at Communications Management on email@example.com or 07584 392347


text:
On Sunday, the same day that bad weather on the East Coast forced delays in Atlantic Ocean sailing schedules for Norwegian Dawn and Golden Princess, gale-force winds in the Mediterranean disrupted the much-ballyhooed inaugural voyage of easyCruiseOne.
The first ship in the brand-new, Britain-based easyCruise line -- uniquely targeted at budget-conscious travelers in their 20's, 30's and 40's who are seeking to spend more time in port than at sea -- departed from Nice as scheduled on Friday and completed a port of call in Cannes before running into 55-mile-per-hour winds en route to St. Tropez on Sunday morning.
For safety reasons, the captain decided to divert the ship to less-than-glamorous Toulon, a place described by Rough Guides as having "all the paranoia of a big city but with few of the charms". As such, the line's founder, serial entrepreneur Stelios Haji-Ioannou, who was onboard the inaugural, announced that the ship's normally a la carte food and drink service would be free. He also arranged for complimentary buses to take travelers between Toulon and St. Tropez, about an hour's ride (though it took the ship some four hours to get to Toulon in rough seas).
Barring further mishap, the sold-out maiden voyage will continue to Monaco, Genoa, Portofino and Imperia before returning to Nice.
Your Ultimate Cruise Guide
- Reviews
- Find A Cruise
- Deals
- Cruises to
- All Destinations
- Alaska Cruises
- Australia & New Zealand
- Bahamas Cruises
- Bermuda
- Canada & New England
- Caribbean Cruises
- Caribbean - Eastern
- Caribbean - Southern
- Caribbean - Western
- Europe Cruises
- Europe - Baltic Sea
- Europe - British Isles & Western
- Europe - Eastern Mediterranean
- Europe - Western Mediterranean
- Mexican Riviera
- Panama Canal
- How to Cruise
- News
Home >
easyCruiseOne Embarks on Rocky Maiden Voyage
easyCruiseOne Embarks on Rocky Maiden Voyage
May 10, 2005