<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The world (and word) of jaymz &#187; python</title>
	<atom:link href="http://jaymz.eu/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://jaymz.eu</link>
	<description></description>
	<lastBuildDate>Tue, 14 Feb 2012 11:52:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Automatic superusers via Active Collab for django</title>
		<link>http://jaymz.eu/2011/02/automatic-superusers-via-active-collab-for-django/</link>
		<comments>http://jaymz.eu/2011/02/automatic-superusers-via-active-collab-for-django/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 21:20:42 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[active-collab]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=553</guid>
		<description><![CDATA[Two things I use a lot at work &#8211; Django and Active Collab. One is the python framework we build everything on and the other is a project management tool that we use &#8211; think a local install of Basecamp roughly. It can get annoying when we create development versions of things we&#8217;re working on [...]]]></description>
			<content:encoded><![CDATA[<p>Two things I use a lot at work &#8211; <a href="http://www.djangoproject.com/">Django</a> and <a href="http://www.activecollab.com">Active Collab</a>. One is the python framework we build everything on and the other is a project management tool that we use &#8211; think a local install of Basecamp roughly.</p>
<p>It can get annoying when we create development versions of things we&#8217;re working on and have to go and create test users for people; so I thought since writing an auth backend for django is so easy why not just use that to allow any user with a valid Active Collab account to login to the dev admin.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2011/02/ac-authbackend.jpg"><img class="aligncenter size-full wp-image-560" title="ac-authbackend" src="http://jaymz.eu/wp-content/uploads/2011/02/ac-authbackend.jpg" alt="" width="525" height="295" /></a></p>
<p>The <a href="https://github.com/jaymzcd/django-acollabauth">code is on github</a> and will automatically create a superuser in django&#8217;s auth table. Users can then login with their active collab emails &amp; passwords without having to pass around test accounts. It also means users wont suddenly lose access when you nuke the database for imports saving you some earache. Just add your base active collab url to the <em>AC_URL</em> variable in settings.py and add &#8216;<em>acollabauth.backends.ActiveCollabBackend</em>&#8216; to your AUTHENTICATION_BACKENDS tuple.</p>
<p>I have also blogged about this <a href="http://www.u-dox.com/blog/2011/02/22/using-active-collab-to-authenticate-django-sites/">over at udox</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2011/02/automatic-superusers-via-active-collab-for-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Active Collab library in Python</title>
		<link>http://jaymz.eu/2011/02/active-collab-library-in-python/</link>
		<comments>http://jaymz.eu/2011/02/active-collab-library-in-python/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 12:31:23 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[active-collab]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=537</guid>
		<description><![CDATA[We use active collab at work to manage our various projects and track issues on sites we&#8217;re building. It comes complete with a REST API which returns results in XML. So I&#8217;ve written some code that abstracts out the process of making a request and displaying the returned data. It&#8217;s, predictably, on github. Here&#8217;s an example [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jaymz.eu/wp-content/uploads/2011/02/ac-library.jpg"><img class="aligncenter size-full wp-image-538" title="ac-library" src="http://jaymz.eu/wp-content/uploads/2011/02/ac-library.jpg" alt="" width="525" height="295" /></a></p>
<p>We use active collab at work to manage our various projects and track issues on sites we&#8217;re building. It comes complete with a REST API which returns results in XML. So I&#8217;ve written some code that abstracts out the process of making a request and displaying the returned data. It&#8217;s, predictably, on <a href="https://github.com/jaymzcd/pyacollab">github</a>.</p>
<p>Here&#8217;s an example based on the 0.2.0 code which is simply outputting data for now allowing me to check on open tickets easily from code. Remember, to enable write methods to work (setting a ticket to complete for example) you need to have <em>Write Access</em> enabled <a href="http://www.activecollab.com/docs/manuals/developers/api/api-status">via the config.php</a> file.</p>
<div id="wpshdo_1" class="wp-synhighlighter-outer"><div id="wpshdt_1" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_1"></a><a id="wpshat_1" class="wp-synhighlighter-title" href="#codesyntax_1"  onClick="javascript:wpsh_toggleBlock(1)" title="Click to show/hide code block">Code block</a></td><td align="right"><a href="#codesyntax_1" onClick="javascript:wpsh_code(1)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_1" onClick="javascript:wpsh_print(1)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_1" class="wp-synhighlighter-inner" style="display: block;"><pre class="python">In <span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>: <span class="kw1">from</span> activecollab.<span class="me1">library</span> <span class="kw1">import</span> ACRequest
&nbsp;
In <span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>: req = ACRequest<span class="br0">&#40;</span><span class="st0">'projects'</span><span class="br0">&#41;</span>
&nbsp;
In <span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span>: req.<span class="me1">execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="nu0">34</span>: AC <span class="nu0">101</span>: http://my.<span class="me1">ac</span>-<span class="kw3">site</span>.<span class="me1">com</span>/projects/<span class="nu0">34</span>
<span class="co1"># More results trimmed</span>
&nbsp;
In <span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span>: req = ACRequest<span class="br0">&#40;</span><span class="st0">'projects'</span>, item_id=<span class="nu0">34</span>, subcommand=<span class="st0">'tickets'</span><span class="br0">&#41;</span>
&nbsp;
In <span class="br0">&#91;</span><span class="nu0">5</span><span class="br0">&#93;</span>: req.<span class="me1">execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="nu0">2208</span>: ie6 error when zooming on <span class="kw2">map</span>: http://my.<span class="me1">ac</span>-<span class="kw3">site</span>.<span class="me1">com</span>/projects/<span class="nu0">34</span>/tickets/<span class="nu0">1</span>: <span class="nu0">1</span>
<span class="nu0">2216</span>: <span class="kw3">new</span> <span class="kw3">user</span> accounts <span class="kw1">for</span> testing: http://my.<span class="me1">ac</span>-<span class="kw3">site</span>.<span class="me1">com</span>/projects/<span class="nu0">34</span>/tickets/<span class="nu0">3</span>: <span class="nu0">3</span></pre></div></div>
<p>I&#8217;ve also blogged about this over at our udox <a href="http://www.u-dox.com/blog/2011/02/16/python-library-for-active-collab/">company site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2011/02/active-collab-library-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redirecting users in django based on client IP</title>
		<link>http://jaymz.eu/2011/02/redirecting-users-in-django-based-on-client-ip/</link>
		<comments>http://jaymz.eu/2011/02/redirecting-users-in-django-based-on-client-ip/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 10:34:55 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=541</guid>
		<description><![CDATA[geoip-redirect is available on my github page.]]></description>
			<content:encoded><![CDATA[<p><a href="http://jaymz.eu/wp-content/uploads/2011/02/redirect-vans.jpg"><img class="aligncenter size-full wp-image-542" title="redirect-vans" src="http://jaymz.eu/wp-content/uploads/2011/02/redirect-vans.jpg" alt="" width="525" height="295" /></a><a href="https://github.com/jaymzcd/geoip-redirect"></a></p>
<p><a href="https://github.com/jaymzcd/geoip-redirect">geoip-redirect</a> is available on my github page.</p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2011/02/redirecting-users-in-django-based-on-client-ip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrating ooyala in django (or just python)</title>
		<link>http://jaymz.eu/2010/07/integrating-ooyala-in-django-or-just-python/</link>
		<comments>http://jaymz.eu/2010/07/integrating-ooyala-in-django-or-just-python/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 11:34:26 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[ooyala]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=495</guid>
		<description><![CDATA[Ooyala is a feature rich video hosting platform. Something I needed recently was some way to link the data over at ooyala into a django site I&#8217;m building. So I wrote myself a library. It&#8217;s available over at github and it&#8217;s called (predictably) django-ooyala. Currently there is a management command syncooyala to pull in all [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jaymz.eu/wp-content/uploads/2010/07/django-ooyala-logo.png"><img class="aligncenter size-full wp-image-497" title="django-ooyala-logo" src="http://jaymz.eu/wp-content/uploads/2010/07/django-ooyala-logo.png" alt="" width="350" height="133" /></a></p>
<p>Ooyala is a feature rich video hosting platform. Something I needed recently was some way to link the data over at ooyala into a django site I&#8217;m building. So I wrote myself a library. It&#8217;s available over at github and it&#8217;s called (predictably) <em><a href="http://github.com/jaymzcd/django-ooyala">django-ooyala</a>.</em> Currently there is a management command <strong>syncooyala</strong> to pull in all the data using the Backlot Query API. These imported items are then linked to a specific URL. Finally in your templates there is a <em>ooyala_video</em> tag which when given the current path (via request.path) returns the &lt;script&gt; tags needed for it to render.</p>
<p>Expect some updates as I flesh it out into the front end over the next few days.</p>
<p><strong><em>Updated (11th August): <span style="font-weight: normal;">I have added in analytics support. You can now make requests for video stat&#8217;s for a given account or video. The facebook SDK has also been added with a new template tag to output the headers in your template for a given video. Remember to request whitelisting from facebook for SWF embeds to work.</span></em></strong></p>
<div id="wpshdo_2" class="wp-synhighlighter-outer"><div id="wpshdt_2" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_2"></a><a id="wpshat_2" class="wp-synhighlighter-title" href="#codesyntax_2"  onClick="javascript:wpsh_toggleBlock(2)" title="Click to show/hide code block">Code block</a></td><td align="right"><a href="#codesyntax_2" onClick="javascript:wpsh_code(2)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_2" onClick="javascript:wpsh_print(2)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_2" class="wp-synhighlighter-inner" style="display: block;"><pre class="python"><span class="kw1">from</span> django.<span class="me1">http</span> <span class="kw1">import</span> HttpResponse
<span class="kw1">from</span> ooyala.<span class="me1">library</span> <span class="kw1">import</span> OoyalaAnalytics
<span class="kw1">from</span> ooyala.<span class="me1">constants</span> <span class="kw1">import</span> OoyalaConstants as O
<span class="kw1">from</span> ooyala.<span class="me1">models</span> <span class="kw1">import</span> OoyalaItem
&nbsp;
<span class="kw1">def</span> backlot_query<span class="br0">&#40;</span>request<span class="br0">&#41;</span>:
    req = OoyalaAnalytics<span class="br0">&#40;</span>video=OoyalaItem.<span class="me1">objects</span>.<span class="me1">all</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">embed_code</span>, \
        method=O.<span class="me1">ANALYTIC_METHODS</span>.<span class="me1">VIDEO</span><span class="br0">&#41;</span>
    ooyala_response = req.<span class="me1">process</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="kw1">return</span> HttpResponse<span class="br0">&#40;</span>ooyala_response.<span class="me1">toprettyxml</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, mimetype=<span class="st0">&quot;text/xml&quot;</span><span class="br0">&#41;</span></pre></div></div>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/07/integrating-ooyala-in-django-or-just-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google Blogger to Django integration</title>
		<link>http://jaymz.eu/2010/06/google-blogger-to-django-integration/</link>
		<comments>http://jaymz.eu/2010/06/google-blogger-to-django-integration/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 21:45:57 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[blogger]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=447</guid>
		<description><![CDATA[I&#8217;ve been working a lot on Vans recently and they have a large number of blogs that are currently hosted on the blogger platform. This works really well for them, they have a straightforward &#38; easy to use blog platform that does what they need it to do.  The sites themselves work great as they [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working a lot on <a href="http://www.vans.com">Vans</a> recently and they have a large number of blogs that are currently hosted on the blogger platform. This works really well for them, they have a straightforward &amp; easy to use blog platform that does what they need it to do.  The sites themselves work great as they are but the integration into the main site isn&#8217;t quite as nice.</p>
<p>If you go to the <a href="http://www.vans.com/vans/teamblog.asp">blogs section</a> on vans as it stands it will pull in an XML feed of all the current blogs and display them on one giagantic page. It can take a fair bit of time to load and its hard to see how each different blog gets displayed as its really one big list. For now it&#8217;s not so easy to pull in bits of content from the various blogs without someone having to mess with files or copy &amp; paste, with the build in django I wanted to create a much cleaner &amp; easier way to work with this content.</p>
<p><a href="http://github.com/jaymzcd/django-blogger"><img class="aligncenter size-full wp-image-460" title="blogger-django-logo" src="http://jaymz.eu/wp-content/uploads/2010/06/blogger-django-logo.png" alt="" width="100" height="99" /></a></p>
<p>For this I introduce <a href="http://github.com/jaymzcd/django-blogger">django-blogger</a>, a django application which will integrate Google Blogger blogs via their RSS feeds. As it is it will import the blogs for a given profile id and then sync up with the latest data via their RSS feeds. These can be <a href="http://www.google.com/support/blogger/bin/answer.py?hl=en&amp;answer=97933">enabled easily</a> for your given blogs. When you first install it comes with some admin actions which will all ow you to sync up the blogs manually all at once. There is also a management command, <em>syncblogs,</em> which is more suited to scheduling an update via cron (if you&#8217;re going to use cron you might be interested in <a href="http://code.google.com/p/django-crontab/">django-crontab</a>).</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/06/djangoblogs-syncing-command.png"><img class="aligncenter size-full wp-image-451" title="djangoblogs-syncing-command" src="http://jaymz.eu/wp-content/uploads/2010/06/djangoblogs-syncing-command.png" alt="" width="514" height="252" /></a></p>
<p>This works on the feeds and not an archive, so it doesn&#8217;t require authentication, just access to the feed URL. A basic template is included to show how to render out the blog posts &amp; blogs as a menu, I override these myself for the format I need. The app itself now lets me pull content from any of the blogs and use it within the rest of the django based site cleanly &amp; easily. Rather than directly reading and displaying via the feed URL I&#8217;m creating actual objects for each post and blog so it&#8217;s easily extendible also, say to return posts in various formats or pulling images from each blog post to create blog galleries automatically.</p>
<p><img src="http://jaymz.eu/wp-content/uploads/2010/06/blogs-4.png" alt="" /></p>
<p>The code is available from <a href="http://github.com/jaymzcd/django-blogger">GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/06/google-blogger-to-django-integration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Image color analysis for your ecom site</title>
		<link>http://jaymz.eu/2010/04/image-color-analysis-for-your-ecom-site/</link>
		<comments>http://jaymz.eu/2010/04/image-color-analysis-for-your-ecom-site/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 00:42:29 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[color]]></category>
		<category><![CDATA[pil]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=262</guid>
		<description><![CDATA[Recently we&#8217;ve been working rather hard on a new look and complete re-launch of the underlying code for the whole of crookedtongues.com We&#8217;re a python shop these days so its running on django with a host of apps and the best part of over 100,000 lines of code. One of the things that I was [...]]]></description>
			<content:encoded><![CDATA[<p>Recently we&#8217;ve been working rather hard on a new look and complete re-launch of the underlying code for the whole of crookedtongues.com We&#8217;re a python shop these days so its running on django with a host of apps and the best part of over 100,000 lines of code.</p>
<p>One of the things that I was tasked with was the data migration and import and I&#8217;ll write about that post launch, what I fancy getting out now is how I&#8217;ve worked on adding color codes automagically to the store&#8217;s entire product database. More or less, its a little rough round the edges but gives fairly good results on a lot of our products. First off you can find the source code in a raw (read that as &#8216;I&#8217;m still working on it personally so take it as it comes&#8217;) way <a href="http://github.com/jaymzcd/color-analysis/blob/master/imagescan.py">over at github</a>. As a taste of what it does, here&#8217;s a couple of existing product shots:</p>
<p style="text-align: center;"><a href="http://jaymz.eu/wp-content/uploads/2010/04/color-output.png"><img class="aligncenter size-full wp-image-263" title="color-output" src="http://jaymz.eu/wp-content/uploads/2010/04/color-output.png" alt="" width="601" height="342" /></a>It works quite well for colors that fall into the center areas of the color wheel. For my analysis I&#8217;ve segmented it by 30° so there are 12 bands of color. I&#8217;ve found that yellow &amp; light greens are the most tricky to pull out accurately from an instinctive perception view of the result. By that I mean what looks very much yellow can get labelled as a bright orange instead as values close to the segment boundary (45°) cause an imbalance towards the orange side.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/04/colorwheel.jpg"><img class="aligncenter size-full wp-image-265" title="colorwheel" src="http://jaymz.eu/wp-content/uploads/2010/04/colorwheel.jpg" alt="" width="450" height="426" /></a></p>
<p>The basic process is working well for products with one dominating color, for multi-color shots it can pull out the relative levels of each tones hue band but blindly chooses the largest, however slight and uses that for its naming output. A better way would be to do some further analysis on the collected results for each image &#8211; one way to enforce some confidence that the main hue really <em>is the main </em>color would be to compare its standard deviation from the average across the sample set. A small <strong>σ</strong> would indicate a more uniform mix of colors &#8211; as we have already sampled out low saturation points this would indicate an image of strong multicolor. Taking the set of hue/tones within the 90th percentile and then comparing their relative deviations of count would allow identifying (and quantifying) the number of colors &#8211; so it would be possible to say <em>mainly dark blue with a little light red</em>.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/04/process.png"><img class="aligncenter size-full wp-image-268" title="process" src="http://jaymz.eu/wp-content/uploads/2010/04/process.png" alt="" width="350" height="839" /></a></p>
<p>If two bands had similar counts it is also more likley that the color in question is <em>not</em> two separate closely aligned colors but in fact a single color at the midpoint (or thereabouts) of them. A scheme to compare these before the final decision would no doubt improve the detection of yellow which seems to constantly tip into the orange side of the wheel. All in all working on this has been a decidedly pleasant break from data imports, javascript and enough MVC style code to do me a lifetime.</p>
<p>Since I wrote the above I&#8217;ve tweaked it somewhat to pull out gray (and black/white) counts also. It works out the rough percentage that corresponds to and if its over a certain limit for black or white will output a value for that also (with a lot of the product shots they&#8217;re on a white background so I need to be more granular with that than just regular colors).</p>
<div id="wpshdo_3" class="wp-synhighlighter-outer"><div id="wpshdt_3" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_3"></a><a id="wpshat_3" class="wp-synhighlighter-title" href="#codesyntax_3"  onClick="javascript:wpsh_toggleBlock(3)" title="Click to show/hide code block">image_scan.py</a></td><td align="right"><a href="#codesyntax_3" onClick="javascript:wpsh_code(3)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_3" onClick="javascript:wpsh_print(3)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_3" class="wp-synhighlighter-inner" style="display: block;"><pre class="python"><span class="co1">#!/usr/bin/python</span>
<span class="co1"># -*- coding: utf-8 -*-</span>
&nbsp;
<span class="co1"># A color analysis script to help you label your store's products with color data</span>
<span class="co1"># automagically. It will take either a single file or scour an entire folder for</span>
<span class="co1"># folders of images and do each one individually printing a summary of what it</span>
<span class="co1"># thinks is the correct color value. A work in progress...</span>
<span class="co1">#</span>
<span class="co1"># ~jaymz | @jaymzcampbell | jaymz.eu</span>
<span class="co1">#</span>
<span class="co1">#</span>
<span class="co1"># MIT Licesnsed for what its worth, copy: http://www.opensource.org/licenses/mit-license.php</span>
&nbsp;
<span class="kw1">import</span> Image
<span class="kw1">import</span> ImageFilter
<span class="kw1">import</span> <span class="kw3">os</span>
<span class="kw1">import</span> <span class="kw3">glob</span>
<span class="kw1">import</span> <span class="kw3">sys</span>
<span class="kw1">import</span> <span class="kw3">colorsys</span>
<span class="kw1">import</span> <span class="kw3">re</span>
<span class="kw1">from</span> <span class="kw3">copy</span> <span class="kw1">import</span> <span class="kw3">copy</span>
<span class="kw1">from</span> <span class="kw3">operator</span> <span class="kw1">import</span> itemgetter
<span class="kw1">from</span> <span class="kw3">decimal</span> <span class="kw1">import</span> Decimal
&nbsp;
output = <span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">'colors.csv'</span>, <span class="st0">'w'</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Pixels will be first compared to these values before being</span>
<span class="co1"># added to the data list of color information on the first pass</span>
LBOUND = <span class="nu0">0</span>
UBOUND = <span class="nu0">255</span>
&nbsp;
MIN_SATURATION = <span class="nu0">30</span> <span class="co1"># avoid washed out pixels influencing counts</span>
&nbsp;
<span class="co1"># Base folder for the processFolder function, it'll iterate over here on subfolders</span>
FOLDER = <span class="st0">'/home/jaymz/documents/crooked-docs/data-export/store-migration/product-images/'</span>
&nbsp;
<span class="co1"># Meh, i need to flip between these two, you can probably tweak this </span>
SUMMARY_FORMAT, SQL_FORMAT = <span class="kw2">True</span>, <span class="kw2">True</span>
&nbsp;
<span class="co1"># Names based off: http://bluelobsterart.com/wordpress/wp-content/uploads/2009/03/rgb-color-wheel-lg.jpg</span>
COLOR = <span class="br0">&#91;</span><span class="st0">'RED'</span>, <span class="st0">'ORANGE'</span>, <span class="st0">'YELLOW'</span>,
    <span class="st0">'LIME'</span>, <span class="st0">'GREEN'</span>, <span class="st0">'TURQUOISE'</span>,
    <span class="st0">'CYAN'</span>, <span class="st0">'OCEAN'</span>, <span class="st0">'BLUE'</span>,
    <span class="st0">'VIOLET'</span>, <span class="st0">'MAGENTA'</span>, <span class="st0">'RASPBERRY'</span>,
    <span class="br0">&#93;</span>
TONE = <span class="br0">&#91;</span><span class="st0">'DARK'</span>, <span class="st0">''</span>, <span class="st0">'BRIGHT'</span><span class="br0">&#93;</span>
&nbsp;
<span class="co1"># via the createColorSQL.py file , addition added in GRAY/BLACK/WHITE to after this</span>
SQL_IDS = <span class="br0">&#123;</span><span class="st0">'DARK YELLOW'</span>: <span class="nu0">7</span>, <span class="st0">'DARK ORANGE'</span>: <span class="nu0">4</span>, <span class="st0">'BRIGHT GREEN'</span>: <span class="nu0">15</span>, <span class="st0">'BRIGHT ORANGE'</span>: <span class="nu0">6</span>, <span class="st0">'DARK RED'</span>: <span class="nu0">1</span>, <span class="st0">'BRIGHT OCEAN'</span>: <span class="nu0">24</span>, <span class="st0">'BRIGHT RED'</span>: <span class="nu0">3</span>, <span class="st0">'DARK OCEAN'</span>: <span class="nu0">22</span>, <span class="st0">'YELLOW'</span>: <span class="nu0">8</span>, <span class="st0">'OCEAN'</span>: <span class="nu0">23</span>, <span class="st0">'BRIGHT YELLOW'</span>: <span class="nu0">9</span>, <span class="st0">'RASPBERRY'</span>: <span class="nu0">35</span>, <span class="st0">'GREEN'</span>: <span class="nu0">14</span>, <span class="st0">'BRIGHT TURQUOISE'</span>: <span class="nu0">18</span>, <span class="st0">'CYAN'</span>: <span class="nu0">20</span>, <span class="st0">'MAGENTA'</span>: <span class="nu0">32</span>, <span class="st0">'RED'</span>: <span class="nu0">2</span>, <span class="st0">'ORANGE'</span>: <span class="nu0">5</span>, <span class="st0">'BLUE'</span>: <span class="nu0">26</span>, <span class="st0">'TURQUOISE'</span>: <span class="nu0">17</span>, <span class="st0">'LIME'</span>: <span class="nu0">11</span>, <span class="st0">'BRIGHT LIME'</span>: <span class="nu0">12</span>, <span class="st0">'DARK MAGENTA'</span>: <span class="nu0">31</span>, <span class="st0">'DARK LIME'</span>: <span class="nu0">10</span>, <span class="st0">'BRIGHT MAGENTA'</span>: <span class="nu0">33</span>, <span class="st0">'BRIGHT VIOLET'</span>: <span class="nu0">30</span>, <span class="st0">'DARK VIOLET'</span>: <span class="nu0">28</span>, <span class="st0">'DARK BLUE'</span>: <span class="nu0">25</span>, <span class="st0">'BRIGHT BLUE'</span>: <span class="nu0">27</span>, <span class="st0">'VIOLET'</span>: <span class="nu0">29</span>, <span class="st0">'BRIGHT RASPBERRY'</span>: <span class="nu0">36</span>, <span class="st0">'DARK TURQUOISE'</span>: <span class="nu0">16</span>, <span class="st0">'DARK CYAN'</span>: <span class="nu0">19</span>, <span class="st0">'BRIGHT CYAN'</span>: <span class="nu0">21</span>, <span class="st0">'DARK GREEN'</span>: <span class="nu0">13</span>, <span class="st0">'DARK RASPBERRY'</span>: <span class="nu0">34</span><span class="br0">&#125;</span>
&nbsp;
pcnt = <span class="nu0">0</span>
&nbsp;
<span class="kw1">def</span> trimFloat<span class="br0">&#40;</span>val, places=<span class="nu0">2</span><span class="br0">&#41;</span>:
    <span class="kw1">return</span> <span class="kw2">float</span><span class="br0">&#40;</span><span class="kw2">repr</span><span class="br0">&#40;</span>val<span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span>:places<span class="nu0">+2</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw1">def</span> withinBounds<span class="br0">&#40;</span>allowance, _rgb<span class="br0">&#41;</span>:
    rgb = <span class="kw3">copy</span><span class="br0">&#40;</span>_rgb<span class="br0">&#41;</span>
    diff = <span class="nu0">0</span>
    allowance = Decimal<span class="br0">&#40;</span><span class="kw2">repr</span><span class="br0">&#40;</span>allowance<span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="kw1">for</span> c <span class="kw1">in</span> rgb:
        <span class="kw1">for</span> d <span class="kw1">in</span> rgb:
            dec_d = Decimal<span class="br0">&#40;</span><span class="kw2">repr</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">quantize</span><span class="br0">&#40;</span>allowance<span class="br0">&#41;</span>
            dec_c = Decimal<span class="br0">&#40;</span><span class="kw2">repr</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">quantize</span><span class="br0">&#40;</span>allowance<span class="br0">&#41;</span>
&nbsp;
            diff = <span class="kw2">abs</span><span class="br0">&#40;</span>dec_d-dec_c<span class="br0">&#41;</span>
&nbsp;
            <span class="kw1">if</span> <span class="br0">&#40;</span>d != c<span class="br0">&#41;</span> <span class="kw1">and</span> diff&gt;allowance:
                <span class="kw1">return</span> <span class="kw2">False</span>
    <span class="kw1">return</span> <span class="kw2">True</span>
&nbsp;
<span class="kw1">def</span> processImage<span class="br0">&#40;</span>i, name=<span class="kw2">None</span><span class="br0">&#41;</span>:
  <span class="st0">&quot;&quot;</span><span class="st0">&quot; Scales down the image, blurs it to ease the blending of the color values
and reduce spikes from anomolies. It then samples pixels creating a list of
colors. This list is then looped over to build counts which are placed into
bins of 30° hue's seperated into three based on their value. Pixels less than
a certain saturation are discarded. &quot;</span><span class="st0">&quot;&quot;</span>
&nbsp;
  <span class="kw1">global</span> pcnt
&nbsp;
  i = i.<span class="me1">resize</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>,<span class="nu0">200</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
  i = i.<span class="me1">convert</span><span class="br0">&#40;</span><span class="st0">&quot;RGB&quot;</span><span class="br0">&#41;</span>
  i = i.<span class="kw2">filter</span><span class="br0">&#40;</span>ImageFilter.<span class="me1">BLUR</span><span class="br0">&#41;</span>
  d = i.<span class="me1">getdata</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
  cnt = <span class="nu0">0</span>
&nbsp;
  h = <span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="co1">#holds the hsv info</span>
  grays = <span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="co1">#holds just gray content</span>
  black_count = <span class="nu0">0</span>
  white_count = <span class="nu0">0</span>
  total_samples = <span class="nu0">0</span>
&nbsp;
  <span class="kw1">for</span> p <span class="kw1">in</span> d:
      cnt = cnt + <span class="nu0">1</span>
      <span class="kw1">if</span> cnt == <span class="nu0">8</span>: <span class="co1">#take every 4th pixel</span>
        <span class="kw1">if</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>&gt;LBOUND <span class="kw1">and</span> p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>&gt;LBOUND <span class="kw1">and</span> p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>&gt;LBOUND <span class="kw1">and</span> p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>&lt;UBOUND <span class="kw1">and</span> p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>&lt;UBOUND <span class="kw1">and</span> p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>&lt;UBOUND:
            r = trimFloat<span class="br0">&#40;</span><span class="kw2">float</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span>/<span class="nu0">255</span><span class="br0">&#41;</span>
            g = trimFloat<span class="br0">&#40;</span><span class="kw2">float</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>/<span class="nu0">255</span><span class="br0">&#41;</span>
            b = trimFloat<span class="br0">&#40;</span><span class="kw2">float</span><span class="br0">&#40;</span>p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span>/<span class="nu0">255</span><span class="br0">&#41;</span>
&nbsp;
            <span class="kw1">if</span> <span class="kw1">not</span> withinBounds<span class="br0">&#40;</span><span class="nu0">0.02</span>, <span class="br0">&#40;</span>r,g,b<span class="br0">&#41;</span><span class="br0">&#41;</span>:
                h.<span class="me1">append</span><span class="br0">&#40;</span><span class="kw3">colorsys</span>.<span class="me1">rgb_to_hsv</span><span class="br0">&#40;</span>r,g,b<span class="br0">&#41;</span><span class="br0">&#41;</span>
            <span class="kw1">else</span>:
                <span class="kw1">if</span> <span class="br0">&#40;</span>r+g+b<span class="br0">&#41;</span>/<span class="nu0">3</span>&gt;<span class="nu0">0.94</span>:
                    white_count += <span class="nu0">1</span>
                <span class="kw1">elif</span> <span class="br0">&#40;</span>r+g+b<span class="br0">&#41;</span>/<span class="nu0">3</span>&lt;<span class="nu0">0.3</span>:
                    black_count += <span class="nu0">1</span>
                <span class="kw1">else</span>:
                    grays.<span class="me1">append</span><span class="br0">&#40;</span><span class="kw3">colorsys</span>.<span class="me1">rgb_to_hsv</span><span class="br0">&#40;</span>r,g,b<span class="br0">&#41;</span><span class="br0">&#41;</span>
            total_samples += <span class="nu0">1</span>
        cnt = <span class="nu0">0</span> <span class="co1">#reset sample counter</span>
&nbsp;
  h.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
  grays.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
  bin_width = <span class="nu0">30</span> <span class="co1"># size of hue slices (degress)</span>
  max_bin = <span class="nu0">360</span>
&nbsp;
  darks = <span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> * <span class="kw2">int</span><span class="br0">&#40;</span>max_bin/bin_width<span class="br0">&#41;</span>
  mids = <span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> * <span class="kw2">int</span><span class="br0">&#40;</span>max_bin/bin_width<span class="br0">&#41;</span>
  lites = <span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> * <span class="kw2">int</span><span class="br0">&#40;</span>max_bin/bin_width<span class="br0">&#41;</span>
&nbsp;
  <span class="kw1">for</span> p <span class="kw1">in</span> h<span class="br0">&#91;</span>::<span class="br0">&#93;</span>:
      hue = p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>*<span class="nu0">360</span>
      sat = p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>*<span class="nu0">100</span>
      val = p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>*<span class="nu0">100</span>
      <span class="kw1">if</span> sat &gt;= MIN_SATURATION:
        bin_number = <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw2">int</span><span class="br0">&#40;</span>hue<span class="br0">&#41;</span><span class="nu0">+15</span><span class="br0">&#41;</span>/bin_width<span class="br0">&#41;</span>%<span class="br0">&#40;</span>max_bin/bin_width<span class="br0">&#41;</span>
        <span class="kw1">if</span> val&lt;<span class="nu0">33</span>:
            darks<span class="br0">&#91;</span>bin_number<span class="br0">&#93;</span> += <span class="nu0">1</span>
        <span class="kw1">elif</span> val&gt;<span class="nu0">33</span> <span class="kw1">and</span> val &lt; <span class="nu0">66</span>:
            mids<span class="br0">&#91;</span>bin_number<span class="br0">&#93;</span> += <span class="nu0">1</span>
        <span class="kw1">else</span>:
            lites<span class="br0">&#91;</span>bin_number<span class="br0">&#93;</span> += <span class="nu0">1</span>
        <span class="co1">#print &quot;HUE BIN: %s VALUE : %d&quot; % (int(hue)/bin_width, int(hue))</span>
&nbsp;
  c = <span class="nu0">0</span>
  data = <span class="kw2">zip</span><span class="br0">&#40;</span>darks, mids, lites<span class="br0">&#41;</span>
&nbsp;
  <span class="kw1">if</span> SUMMARY_FORMAT:
    <span class="kw1">for</span> x <span class="kw1">in</span> data:
        <span class="kw1">print</span> <span class="st0">'%d %s : %s %d°'</span> % <span class="br0">&#40;</span>c, COLOR<span class="br0">&#91;</span>c<span class="br0">&#93;</span>, x, c*bin_width<span class="br0">&#41;</span>
        c += <span class="nu0">1</span>
&nbsp;
  <span class="co1"># the following area needs a rework. the index technique works alright as long</span>
  <span class="co1"># as counts and values dont all match up, then it starts picking the first one</span>
  <span class="co1"># so this needs re-writing to better order the list data</span>
&nbsp;
  darks_sort, mids_sort, lites_sort = darks<span class="br0">&#91;</span>::<span class="br0">&#93;</span>, mids<span class="br0">&#91;</span>::<span class="br0">&#93;</span>, lites<span class="br0">&#91;</span>::<span class="br0">&#93;</span>
  darks_sort.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
  mids_sort.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
  lites_sort.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
  sorted_counts = <span class="br0">&#40;</span>darks_sort, mids_sort, lites_sort<span class="br0">&#41;</span>
&nbsp;
  primary_idx = <span class="br0">&#40;</span>darks.<span class="me1">index</span><span class="br0">&#40;</span>sorted_counts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>, mids.<span class="me1">index</span><span class="br0">&#40;</span>sorted_counts<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>, lites.<span class="me1">index</span><span class="br0">&#40;</span>sorted_counts<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
  primary_cnts = <span class="br0">&#40;</span>darks<span class="br0">&#91;</span>primary_idx<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#93;</span>, mids<span class="br0">&#91;</span>primary_idx<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#93;</span>, lites<span class="br0">&#91;</span>primary_idx<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
  tone = primary_cnts.<span class="me1">index</span><span class="br0">&#40;</span><span class="kw2">max</span><span class="br0">&#40;</span>primary_cnts<span class="br0">&#41;</span><span class="br0">&#41;</span>
  max_hbin = primary_idx<span class="br0">&#91;</span>tone<span class="br0">&#93;</span>
&nbsp;
  pcnt += <span class="nu0">1</span>
&nbsp;
  <span class="kw1">if</span> SUMMARY_FORMAT:
    <span class="kw1">print</span> <span class="st0">&quot;<span class="es0">\n</span>Dominant Hue: %s %s&quot;</span> % <span class="br0">&#40;</span>TONE<span class="br0">&#91;</span>tone<span class="br0">&#93;</span>, COLOR<span class="br0">&#91;</span>max_hbin<span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp;
  <span class="kw1">if</span> SQL_FORMAT <span class="kw1">and</span> name <span class="kw1">and</span> <span class="kw2">max</span><span class="br0">&#40;</span>primary_cnts<span class="br0">&#41;</span> &gt; <span class="nu0">30</span>:
    output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'%d, %s, %s<span class="es0">\n</span>'</span> % <span class="br0">&#40;</span>pcnt, name, SQL_IDS<span class="br0">&#91;</span><span class="st0">' '</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#91;</span>TONE<span class="br0">&#91;</span>tone<span class="br0">&#93;</span>, COLOR<span class="br0">&#91;</span>max_hbin<span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp;
  sorted_counts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span>, sorted_counts<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span>, sorted_counts<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span> = <span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#41;</span> <span class="co1"># kind of reset the primary to null</span>
  <span class="kw1">for</span> l <span class="kw1">in</span> sorted_counts:
      l.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
  primary_idx = <span class="br0">&#40;</span>darks.<span class="me1">index</span><span class="br0">&#40;</span>sorted_counts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>, mids.<span class="me1">index</span><span class="br0">&#40;</span>sorted_counts<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>, lites.<span class="me1">index</span><span class="br0">&#40;</span>sorted_counts<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
  primary_cnts = <span class="br0">&#40;</span>darks<span class="br0">&#91;</span>primary_idx<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#93;</span>, mids<span class="br0">&#91;</span>primary_idx<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#93;</span>, lites<span class="br0">&#91;</span>primary_idx<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
  tone = primary_cnts.<span class="me1">index</span><span class="br0">&#40;</span><span class="kw2">max</span><span class="br0">&#40;</span>primary_cnts<span class="br0">&#41;</span><span class="br0">&#41;</span>
  max_hbin = primary_idx<span class="br0">&#91;</span>tone<span class="br0">&#93;</span>
&nbsp;
  <span class="kw1">if</span> SUMMARY_FORMAT:
    <span class="kw1">print</span> <span class="st0">&quot;Secondary Hue: %s %s&quot;</span> % <span class="br0">&#40;</span>TONE<span class="br0">&#91;</span>tone<span class="br0">&#93;</span>, COLOR<span class="br0">&#91;</span>max_hbin<span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp;
  <span class="kw1">if</span> SQL_FORMAT <span class="kw1">and</span> name <span class="kw1">and</span> <span class="kw2">max</span><span class="br0">&#40;</span>primary_cnts<span class="br0">&#41;</span> &gt; <span class="nu0">30</span>:
    pcnt += <span class="nu0">1</span>
    output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'%d, %s, %s<span class="es0">\n</span>'</span> % <span class="br0">&#40;</span>pcnt, name, SQL_IDS<span class="br0">&#91;</span><span class="st0">' '</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#91;</span>TONE<span class="br0">&#91;</span>tone<span class="br0">&#93;</span>, COLOR<span class="br0">&#91;</span>max_hbin<span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp;
  <span class="co1"># area to rewrite ends...</span>
&nbsp;
  gray_total = <span class="br0">&#91;</span><span class="br0">&#40;</span>g<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>+g<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>+g<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span>/<span class="nu0">3</span> <span class="kw1">for</span> g <span class="kw1">in</span> grays<span class="br0">&#93;</span>
  gray_average = <span class="kw2">reduce</span><span class="br0">&#40;</span><span class="kw1">lambda</span> x,y : x+y, gray_total<span class="br0">&#41;</span>/<span class="kw2">len</span><span class="br0">&#40;</span>gray_total<span class="br0">&#41;</span>
&nbsp;
  black_percent = black_count/<span class="kw2">float</span><span class="br0">&#40;</span>total_samples<span class="br0">&#41;</span>*<span class="nu0">100</span>
  gray_percent = <span class="kw2">len</span><span class="br0">&#40;</span>gray_total<span class="br0">&#41;</span>/<span class="kw2">float</span><span class="br0">&#40;</span>total_samples<span class="br0">&#41;</span>*<span class="nu0">100</span>
  white_percent = white_count/<span class="kw2">float</span><span class="br0">&#40;</span>total_samples<span class="br0">&#41;</span>*<span class="nu0">100</span>
&nbsp;
  <span class="kw1">if</span> SUMMARY_FORMAT:
    <span class="kw1">print</span> <span class="st0">&quot;<span class="es0">\n</span>Average Gray: %s (samples: %0.1f%%), White count: %s (%0.1f%%), Black count: %s (%0.1f%%)&quot;</span> % <span class="br0">&#40;</span>gray_average, gray_percent, white_count, white_percent, black_count, black_percent<span class="br0">&#41;</span>
    <span class="kw1">print</span> <span class="st0">&quot;Total samples taken: %s<span class="es0">\n</span><span class="es0">\n</span>&quot;</span> % total_samples
&nbsp;
  <span class="kw1">if</span> SQL_FORMAT:
    <span class="kw1">if</span> black_percent &gt; <span class="nu0">10</span>:
        pcnt += <span class="nu0">1</span>
        output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'%d, %s, %d<span class="es0">\n</span>'</span> % <span class="br0">&#40;</span>pcnt, name, <span class="nu0">38</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="kw1">if</span> gray_percent &gt; <span class="nu0">10</span>:
        pcnt += <span class="nu0">1</span>
        output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'%d, %s, %d<span class="es0">\n</span>'</span> % <span class="br0">&#40;</span>pcnt, name, <span class="nu0">37</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="kw1">if</span> white_percent &gt; <span class="nu0">30</span>:
        pcnt += <span class="nu0">1</span>
        output.<span class="me1">write</span><span class="br0">&#40;</span><span class="st0">'%d, %s, %d<span class="es0">\n</span>'</span> % <span class="br0">&#40;</span>pcnt, name, <span class="nu0">39</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Helper functions follow along with __main__ def</span>
&nbsp;
<span class="kw1">def</span> processFolder<span class="br0">&#40;</span>folder<span class="br0">&#41;</span>:
    <span class="kw1">for</span> image_folder <span class="kw1">in</span> <span class="kw3">glob</span>.<span class="kw3">glob</span><span class="br0">&#40;</span>folder+<span class="st0">'*'</span><span class="br0">&#41;</span>:
        <span class="kw1">try</span>:
            folder_images = <span class="br0">&#91;</span><span class="br0">&#93;</span>
            <span class="kw1">for</span> image <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">listdir</span><span class="br0">&#40;</span>image_folder<span class="br0">&#41;</span>:
                <span class="kw1">if</span> <span class="st0">&quot;jpg&quot;</span> <span class="kw1">in</span> image <span class="kw1">and</span> <span class="st0">&quot;._&quot;</span> <span class="kw1">not</span> <span class="kw1">in</span> image:
                    folder_images.<span class="me1">append</span><span class="br0">&#40;</span>image<span class="br0">&#41;</span>
            folder_images.<span class="me1">sort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
            j = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>image_folder, folder_images<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
            <span class="kw1">if</span> SUMMARY_FORMAT:
                <span class="kw1">print</span> <span class="st0">&quot;working: &quot;</span>+j
            i = Image.<span class="kw2">open</span><span class="br0">&#40;</span>j<span class="br0">&#41;</span>
            processImage<span class="br0">&#40;</span>i, image_folder.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">'/'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
        <span class="kw1">except</span>:
            <span class="kw1">pass</span>
&nbsp;
<span class="kw1">def</span> processFile<span class="br0">&#40;</span>_file<span class="br0">&#41;</span>:
    i = Image.<span class="kw2">open</span><span class="br0">&#40;</span>_file<span class="br0">&#41;</span>
    processImage<span class="br0">&#40;</span>i<span class="br0">&#41;</span>
&nbsp;
<span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:
    <span class="kw1">try</span>:
        <span class="kw1">if</span> <span class="st0">'product-images'</span> <span class="kw1">not</span> <span class="kw1">in</span> <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>:
            processFile<span class="br0">&#40;</span><span class="st0">'product-images/'</span>+<span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
        <span class="kw1">else</span>:
            processFile<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="kw1">except</span> <span class="kw2">IndexError</span>:
        processFolder<span class="br0">&#40;</span>FOLDER<span class="br0">&#41;</span>
    output.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/04/image-color-analysis-for-your-ecom-site/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google&#8217;s results plotted for repeated character strings</title>
		<link>http://jaymz.eu/2010/02/googles-results-plotted-for-repeated-character-strings/</link>
		<comments>http://jaymz.eu/2010/02/googles-results-plotted-for-repeated-character-strings/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 21:12:20 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[musing]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=239</guid>
		<description><![CDATA[Don&#8217;t ask why but out of interest I googled for the string &#8220;AAAAAAAA&#8221; earlier and after looking at the millions of pages that came back and thinking &#8220;wtf&#8221;, I searched again only making the string much longer. I was expecting it to just keep going down but at around 20 characters there was a significant [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">Don&#8217;t ask why but out of interest I googled for the string<em> &#8220;AAAAAAAA&#8221; </em>earlier and after looking at the millions of pages that came back and thinking &#8220;wtf&#8221;, I searched again only making the string much longer. I was expecting it to just keep going down but at around 20 characters there was a significant jump in returned results. I scratched my beard and proclaimed this interesting (as you can probably tell I have <em>no</em> distractions on valentines day). To skip over further bullshit, this is the graph of 3,328 searches &#8211; that is, the number of results for every character (A-Z) repeated one to 128 times. Some of the peaks are interesting.</p>
<p style="text-align: center;"><a href="http://jaymz.eu/wp-content/uploads/2010/02/googleresults-all.jpg"><img class="aligncenter size-large wp-image-240" title="googleresults-all" src="http://jaymz.eu/wp-content/uploads/2010/02/googleresults-all-1024x578.jpg" alt="" width="502" height="284" /></a></p>
<p>Why 128 and not something higher? <a href="http://code.google.com/apis/searchappliance/documentation/46/xml_reference.html#request_limits">Google wont let you</a>, at least via the query string. The raw data for this graph was generated by a simple python script. If you aren&#8217;t coding in python already, please do look into it, its jolly nice.</p>
<div id="wpshdo_4" class="wp-synhighlighter-outer"><div id="wpshdt_4" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_4"></a><a id="wpshat_4" class="wp-synhighlighter-title" href="#codesyntax_4"  onClick="javascript:wpsh_toggleBlock(4)" title="Click to show/hide code block">Code block</a></td><td align="right"><a href="#codesyntax_4" onClick="javascript:wpsh_code(4)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_4" onClick="javascript:wpsh_print(4)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_4" class="wp-synhighlighter-inner" style="display: block;"><pre class="python"><span class="co1">#!/usr/bin/python</span>
&nbsp;
<span class="kw1">from</span> <span class="kw3">urllib</span> <span class="kw1">import</span> FancyURLopener
<span class="kw1">from</span> BeautifulSoup <span class="kw1">import</span> BeautifulSoup
<span class="kw1">import</span> <span class="kw3">csv</span>
<span class="kw1">import</span> <span class="kw3">string</span> 
&nbsp;
BASE = <span class="st0">&quot;http://www.google.com/search?q=&quot;</span>
&nbsp;
<span class="kw1">class</span> MozOpener<span class="br0">&#40;</span>FancyURLopener<span class="br0">&#41;</span>:
    version = <span class="st0">'Mozilla/5.0 (Windows; U; Windows NT 5.1;'</span> +
<span class="st0">' it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11'</span>
ff = MozOpener<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
out = <span class="kw3">csv</span>.<span class="me1">writer</span><span class="br0">&#40;</span><span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">'out.csv'</span>, <span class="st0">'w'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp;
headers = <span class="br0">&#91;</span><span class="st0">'count'</span>,<span class="br0">&#93;</span>
<span class="kw1">for</span> l <span class="kw1">in</span> <span class="kw3">string</span>.<span class="me1">ascii_uppercase</span>:
    headers.<span class="me1">append</span><span class="br0">&#40;</span>l<span class="br0">&#41;</span>
out.<span class="me1">writerow</span><span class="br0">&#40;</span>headers<span class="br0">&#41;</span>
&nbsp;
<span class="kw1">for</span> x <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">1</span>, <span class="nu0">128</span><span class="br0">&#41;</span>: <span class="co1"># 128 is the max length of chars allowed</span>
    results = <span class="br0">&#91;</span>x,<span class="br0">&#93;</span>
    <span class="kw1">for</span> l <span class="kw1">in</span> <span class="kw3">string</span>.<span class="me1">ascii_uppercase</span>:
        qry = l*x
        raw_data = ff.<span class="kw2">open</span><span class="br0">&#40;</span>BASE+qry<span class="br0">&#41;</span>.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        soup = BeautifulSoup<span class="br0">&#40;</span>raw_data<span class="br0">&#41;</span>
        result = soup.<span class="me1">find</span><span class="br0">&#40;</span><span class="kw2">id</span>=<span class="st0">'resultStats'</span><span class="br0">&#41;</span>.<span class="me1">findAll</span><span class="br0">&#40;</span><span class="st0">'b'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>
        result = <span class="kw2">int</span><span class="br0">&#40;</span>result.<span class="me1">contents</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">','</span>, <span class="st0">''</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        results.<span class="me1">append</span><span class="br0">&#40;</span>result<span class="br0">&#41;</span>
        <span class="kw1">print</span> <span class="br0">&#91;</span>result, qry<span class="br0">&#93;</span>
    out.<span class="me1">writerow</span><span class="br0">&#40;</span>results<span class="br0">&#41;</span></pre></div></div>
<p>When that had finished I simply loaded it up into OpenOffice calc (3.2 is out by the way) and plotted it with the result count set to a logarithmic scale so result #1 doesn&#8217;t just skew the thing into one boring L shape. The first thing I noticed was a very visible spiking at length 100.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/02/gresults-100.png"><img class="aligncenter size-full wp-image-250" title="gresults-100" src="http://jaymz.eu/wp-content/uploads/2010/02/gresults-100.png" alt="" width="244" height="260" /></a>This isn&#8217;t so hard to imagine, 100 is a &#8220;nice&#8221; number. It&#8217;s not hard to imagine someone using 100<strong>x</strong> <em>a character</em> as a test input or just a &#8220;long&#8221; string. <em>Every</em> character string of length 100 exhibits this spike. The much bigger blue curve is for the letter <strong>x</strong>. This is used by children and adults alike to mark kisses, and everyone knows the more x&#8217;s the more someone loves you. If you look at many of the results for 100 or 101 character X searches it seems to be when people are using it in this context. Could it be that the much bigger spike for the 101 character string X is simply because its 100 + 1 kisses?? Towards the start of the graph there are a number of interesting spikes, I&#8217;ve marked some of them along with the length.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/02/interesting-points.png"><img class="aligncenter size-full wp-image-251" title="interesting-points" src="http://jaymz.eu/wp-content/uploads/2010/02/interesting-points.png" alt="" width="549" height="466" /></a></p>
<p>Some of these spikes are easy to explain, the biggest number of results returned for a single repeated character phrase is a by product of DNS, yep, its <em>&#8220;WWW&#8221;</em>. This accounts for the slightly higher result count than the simple &#8220;<em>A&#8221; </em>with 17,090,000,000 pages returned versus 12,260,000,000. Another easy one is 6 F&#8217;s &#8211; the hex code for white. I am totally stumped by F&#8217;s latter behaviour though, there is a spike at F-31 and F-33<em> but not F-32</em>. There is a big jump for X-12 and X-34. International mobiles have 12 digits, as do UPC codes but I feel like I&#8217;m clutching at straws <img src='http://jaymz.eu/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  trying to explain that. Down the other end of the graph, between 115 and 128 the characters P, H, A, M and O all have significant spikes for specific counts. For M &amp; O when you browse many of the first few pages of google&#8217;s results many of the pages are using them as part of exaggerated speech. It&#8217;s almost like the collective conciousness of the world has decided that 120 characters is <em>just right</em> to describe a particularly tasty dinner.</p>
<p>A spreadsheet with the data I gathered is <a href="http://spreadsheets.google.com/ccc?key=0AoMNZZdsBVQVdEdJQjV5U3VJQmRFdllPRkpHb3R5M3c&amp;hl=en">available via google docs</a> if you&#8217;d like to investigate yourself. I should note that the python script above gets its data from <em><strong>.com<span style="font-style: normal;">, <span style="font-weight: normal;">if you are using the site to look up some searches it will more than likely switch to your local domain. Depending on your cookies google may also perform extra filtering (e.g. safe searches) so you&#8217;re numbers may not be the exact same as mine. I&#8217;d be interested in any theories as to some of the more prominent spikes. The OpenOffice spreadsheet with the charts done is also available for <a href="http://jaymz.eu/wp-content/uploads/2010/02/output-data.ods">download here</a>.</span></span></strong></em></p>
<p><strong><span style="font-style: normal;"><span style="font-weight: normal;"><em>If you are going to play around then save your fingers &amp; sanity and use python to create you&#8217;re test strings, just drop into a python shell and use <strong>&#8220;X&#8221;*120</strong> etc or <strong>perl -e &#8216;print &#8220;X&#8221;x100&#8242; </strong>from the command line etc.</em></span></span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/02/googles-results-plotted-for-repeated-character-strings/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Importing existing visitor stats from Google Analytics to Piwik</title>
		<link>http://jaymz.eu/2010/02/importing-existing-visitor-stats-from-google-analytics-to-piwik/</link>
		<comments>http://jaymz.eu/2010/02/importing-existing-visitor-stats-from-google-analytics-to-piwik/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 19:37:17 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[google analytics]]></category>
		<category><![CDATA[piwik]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sed]]></category>

		<guid isPermaLink="false">http://jaymz.eu/?p=184</guid>
		<description><![CDATA[Recently at work we had to aggregate a lot of google analytics accounts and do some tracking and custom reporting. We found that it wasn&#8217;t quite as straightforward as we thought, one of the problems we had was getting multiple tracking codes to work on the same page. It was no real surprise that this [...]]]></description>
			<content:encoded><![CDATA[<p>Recently at work we had to aggregate a lot of google analytics accounts and do some tracking and custom reporting. We found that it wasn&#8217;t quite as straightforward as we thought, one of the problems we had was getting multiple tracking codes to work on the same page. It was no real surprise that this wouldn&#8217;t work easily because google themselves <a href="http://www.google.com/support/analytics/bin/answer.py?hl=en&amp;answer=72298">have this to say</a>:</p>
<blockquote><p>Installing multiple instances of the Google Analytics Tracking code  on a single web page<strong> is not a supported implementation</strong>. We suggest you  remove all but one instance, and make sure you have the code from the  correct profile installed on every page you would like to track.</p></blockquote>
<p>With a lot of searching and reading I did find a number of scattered blog posts that suggested that it <em>would</em> work and <em>was </em>possible. But no matter what I tried I couldn&#8217;t get it tracking data into multiple accounts from the same page. I got fed up and was tasked with looking at alternative tracking solutions. That&#8217;s when I came across the <a href="http://en.wikipedia.org/wiki/List_of_web_analytics_software">very handy list</a> at wikipedia and from there <a href="http://piwik.org/">Piwik</a>. Piwik is a GPL license PHP application which aims to mimic the functionality of google analytics. You install it on your server and then add sites to it much like GA. It then gives you a tracking code to install on your site(s).</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/02/pw-dashboard.png"><img class="aligncenter size-medium wp-image-194" title="pw-dashboard" src="http://jaymz.eu/wp-content/uploads/2010/02/pw-dashboard-300x188.png" alt="" width="300" height="188" /></a></p>
<p>As it was so similar to GA but locally ran, I played about with it and decided to go with that, working on the assumption that I could at least get at the db tables and source in the future. I setup a number of sites to track and then installed the codes on each page. One acted as a &#8220;master&#8221; code which was on all pages whilst others only appeared when the domain matched a certain string. I left it for an hour and came back to find the data all populated in each account as I expected. I was jolly pleased.</p>
<p>When it was shown to the intended user they really loved it. The only thing they wanted to sweeten the whole experience even more was to have the visitor count data <em>for the prior month </em>loaded in from Google Analytic&#8217;s.  I wasn&#8217;t over the moon with this as exporting you&#8217;re data from GA isn&#8217;t very straightfoward and certainly not in a simple &#8220;just dump and drop it in&#8221; way either. I had a quick look at what I could export from GA and said I could import in the unique hits per day fairly easily but tying that to specific browsers or page titles etc would be quite a lot of work.</p>
<p>I sort of half expected that that would result in a &#8220;ah, ok, lets forget about it&#8221; conversation with the end agreement being use GA for data prior to the switchover and Piwik for reports since then but nope, they still wanted to have just the hit counts loaded in regardless of if they were not attached to page titles or a users tech setup. Looking at the piwik developers zone the post about <a href="http://dev.piwik.org/trac/ticket/134">an API to push data in</a> was initially promising but it was focusing on apache logs and most recently a user said the timestamps weren&#8217;t coming through. So I looked at another way to get it done. What follows is how I personally went about loading data in. You may find it useful if you end up migrating yourself.</p>
<p>To begin with I installed piwik afresh and dumped out the database. Then I set up just one site and let it record a single hit. Then I went through and compared each table with the previous state. This told me there were 2 places I needed to put data in if I wanted it logged and being used in piwik.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/02/pw-key-tables.png"><img class="aligncenter size-full wp-image-188" title="pw-key-tables" src="http://jaymz.eu/wp-content/uploads/2010/02/pw-key-tables.png" alt="" width="201" height="378" /></a><em><strong>_log_visit</strong></em> &amp;<em><strong> _log_link_visit_action</strong></em> are the two key tables that receive data on each click. The link_visit_action table ties a particular visit to a particular page. I wasn&#8217;t going to b doing this so in <em><strong>log_action </strong></em>I added 2 new rows &#8211; 1 for the url of my &#8220;Google Analytics Dummy page&#8221; and another for its title. Then I noted the id&#8217;s for each of those rows.</p>
<p>Confident that this would be all I required I went over to GA to export out my data. I clicked through to visitors and set the date range for that required. Then clicked export and chose CSV. You will note that the actual data is <em>not</em> by time but instead aggregated for each day. This means that at most this is just going to allow someone to see the total hits per day but no further drilldown by hour etc. I made that clear to the client and they where again (worse luck!) happy with that level of reporting.</p>
<p style="text-align: left;"><a href="http://jaymz.eu/wp-content/uploads/2010/02/pw-ga-export.png"><img class="aligncenter size-full wp-image-187" title="pw-ga-export" src="http://jaymz.eu/wp-content/uploads/2010/02/pw-ga-export.png" alt="" width="601" height="221" /></a>The first thing I needed to do was clean up this data. GA exports it out with day &amp; month names along with some other cruft that wasn&#8217;t required. There would be a myriad of ways to sort this out and I chose to use the unix stalwart, <strong><em><a href="http://en.wikipedia.org/wiki/Sed">sed</a>. </em></strong>The code that follows I saved and chmod&#8217;d and then ran on my GA csv file.</p>
<p style="text-align: left;"><div id="wpshdo_5" class="wp-synhighlighter-outer"><div id="wpshdt_5" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_5"></a><a id="wpshat_5" class="wp-synhighlighter-title" href="#codesyntax_5"  onClick="javascript:wpsh_toggleBlock(5)" title="Click to show/hide code block">Code block</a></td><td align="right"><a href="#codesyntax_5" onClick="javascript:wpsh_code(5)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_5" onClick="javascript:wpsh_print(5)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_5" class="wp-synhighlighter-inner" style="display: block;"><pre class="bash"><span class="re3">#!/bin/<span class="kw2">sed</span> -nrf</span>
s/.*day, //
s/January/<span class="nu0">01</span>,/
s/February/<span class="nu0">02</span>,/
s/March/<span class="nu0">03</span>,/
s/April/<span class="nu0">04</span>,/
s/May/<span class="nu0">05</span>,/
s/June/<span class="nu0">06</span>,/
s/July/<span class="nu0">07</span>,/
s/August/<span class="nu0">08</span>,/
s/September/<span class="nu0">09</span>,/
s/October/<span class="nu0">10</span>,/
s/November/<span class="nu0">11</span>,/
s/December/<span class="nu0">12</span>,/
<span class="nu0">1</span>,10d
s/\<span class="st0">&quot;//
s/([0-9]{1,2}), ([0-9]{1,2}), ([0-9]{4}),(.+)/<span class="es0">\3</span>-<span class="es0">\1</span>-<span class="es0">\2</span> 00:00:00,&quot;</span>\<span class="nu0">4</span><span class="st0">&quot;/
/^[0-9]/p</span></pre></div></div></p>
<p>You can <a href="http://jaymz.eu/wp-content/uploads/piwik-ga/clean.sed">download that here</a>.</p>
<p>That should take</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&quot;Tuesday, February 2, 2010&quot;,21
</div>
</li>
<li class="li1">
<div class="de1">&quot;Wednesday, February 3, 2010&quot;,28
</div>
</li>
<li class="li1">
<div class="de1">&quot;Thursday, February 4, 2010&quot;,26
</div>
</li>
<li class="li1">
<div class="de1">&quot;Friday, February 5, 2010&quot;,29
</div>
</li>
<li class="li2">
<div class="de2">&quot;Saturday, February 6, 2010&quot;,23
</div>
</li>
<li class="li1">
<div class="de1">&quot;Sunday, February 7, 2010&quot;,27
</div>
</li>
<li class="li1">
<div class="de1">&quot;Monday, February 8, 2010&quot;,16
</div>
</li>
<li class="li1">
<div class="de1">&quot;Tuesday, February 9, 2010&quot;,28
</div>
</li>
<li class="li1">
<div class="de1">&quot;Wednesday, February 10, 2010&quot;,25
</div>
</li>
<li class="li2">
<div class="de2">&quot;Thursday, February 11, 2010&quot;,11</div>
</li>
</ol>
</div>
<p>and turn it into:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">2010-02-2 00:00:00,&quot;21&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-3 00:00:00,&quot;28&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-4 00:00:00,&quot;26&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-5 00:00:00,&quot;29&quot;
</div>
</li>
<li class="li2">
<div class="de2">2010-02-6 00:00:00,&quot;23&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-7 00:00:00,&quot;27&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-8 00:00:00,&quot;16&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-9 00:00:00,&quot;28&quot;
</div>
</li>
<li class="li1">
<div class="de1">2010-02-10 00:00:00,&quot;25&quot;
</div>
</li>
<li class="li2">
<div class="de2">2010-02-11 00:00:00,&quot;11&quot;</div>
</li>
</ol>
</div>
<p>Now its still not the most ISO-formatted csv in the world but it <em>will</em> do for what we need. I obviously can&#8217;t just load that into piwik so I then used this as input to a python script that simply magics up the rest of the needed info for the two piwik table&#8217;s. As the visitor stats from GA are the <em>uniques</em> (again I made that clear before starting all this to the client) I just create an md5 hash via the current time as I make my way through the counts. That way piwik records them as unique visitors. If the cookies hashes are the same in the db piwik <em>will</em> consider it a returning visitor even if the return flag is 0.</p>
<div id="wpshdo_6" class="wp-synhighlighter-outer"><div id="wpshdt_6" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_6"></a><a id="wpshat_6" class="wp-synhighlighter-title" href="#codesyntax_6"  onClick="javascript:wpsh_toggleBlock(6)" title="Click to show/hide code block">Code block</a></td><td align="right"><a href="#codesyntax_6" onClick="javascript:wpsh_code(6)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_6" onClick="javascript:wpsh_print(6)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_6" class="wp-synhighlighter-inner" style="display: block;"><pre class="python"><span class="kw1">import</span> <span class="kw3">csv</span>
<span class="kw1">import</span> <span class="kw3">os</span>
<span class="kw1">from</span> <span class="kw3">datetime</span> <span class="kw1">import</span> <span class="kw3">datetime</span>
<span class="kw1">from</span> <span class="kw3">md5</span> <span class="kw1">import</span> <span class="kw3">md5</span>
<span class="kw1">import</span> <span class="kw3">sys</span>
&nbsp;
<span class="kw1">def</span> main<span class="br0">&#40;</span>argv<span class="br0">&#41;</span>:
    <span class="kw1">if</span> argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>:
        COL_ID = <span class="kw2">int</span><span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="kw1">else</span>:
        COL_ID = <span class="nu0">1</span>
    <span class="kw1">if</span> argv<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>:
        LVA_ID = <span class="kw2">int</span><span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="kw1">else</span>:
        LVA_ID = COL_ID
    SITE_ID = <span class="nu0">1</span>
    LOCAL_TIME = <span class="st0">&quot;00:00:00&quot;</span>
    VISITOR_RETURNING = <span class="nu0">0</span>
    GA_ACTION_URL = <span class="nu0">1</span>
    GA_ACTION_NAME = <span class="nu0">1</span>
    TOTAL_ACTIONS = <span class="nu0">1</span>
    VISIT_TOTAL_TIME = <span class="nu0">10</span>
    GOAL_CONVERT = <span class="nu0">0</span>
    REFERER_TYPE = <span class="nu0">1</span>
    CONFIG_OS = <span class="st0">&quot;GA&quot;</span>
    CONFIG_BROWSER = <span class="st0">&quot;GA&quot;</span>
    CONFIG_B_VER = <span class="st0">&quot;0.1&quot;</span>
    CONFIG_RES = <span class="st0">&quot;1600x1200&quot;</span>
    CONFIG_MD5 = <span class="kw3">md5</span><span class="br0">&#40;</span>CONFIG_BROWSER+CONFIG_OS+CONFIG_RES<span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    LOCATION_IP = <span class="st0">&quot;168450866&quot;</span>
    BROWSER_LANG = <span class="st0">&quot;en-gb&quot;</span>
    LOCATION_COUNTRY = <span class="st0">&quot;gb&quot;</span>
    LOCATION_CONTINENT = <span class="st0">&quot;eur&quot;</span>
    LOCATION_PROVIDER = <span class="st0">&quot;GA Import&quot;</span>
    data = <span class="kw3">csv</span>.<span class="me1">reader</span><span class="br0">&#40;</span><span class="kw2">open</span><span class="br0">&#40;</span>argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    piwik_output = <span class="br0">&#91;</span><span class="kw3">csv</span>.<span class="me1">writer</span><span class="br0">&#40;</span><span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">'log_visit-'</span>+argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, <span class="st0">'w'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>,
        <span class="kw3">csv</span>.<span class="me1">writer</span><span class="br0">&#40;</span><span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">'log_vaction-'</span>+argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, <span class="st0">'w'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>
    <span class="kw1">for</span> row <span class="kw1">in</span> data:
        hits = <span class="kw2">int</span><span class="br0">&#40;</span>row<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="st0">','</span>, <span class="st0">''</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">0</span>, hits<span class="br0">&#41;</span>:
            cookie = <span class="kw3">md5</span><span class="br0">&#40;</span><span class="kw3">datetime</span>.<span class="me1">now</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="kw4">__str__</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">hexdigest</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
            action_time = row<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> + LOCAL_TIME
            output = <span class="br0">&#91;</span>COL_ID, SITE_ID, action_time, cookie,
                VISITOR_RETURNING, action_time, action_time, row<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>,
                GA_ACTION_URL, GA_ACTION_NAME, TOTAL_ACTIONS,
                VISIT_TOTAL_TIME, GOAL_CONVERT, REFERER_TYPE, <span class="kw2">None</span>,
                <span class="kw2">None</span>, <span class="kw2">None</span>, CONFIG_MD5, CONFIG_OS, CONFIG_BROWSER,
                CONFIG_B_VER, CONFIG_RES, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">1</span>,
                LOCATION_IP, BROWSER_LANG, LOCATION_COUNTRY,
                LOCATION_CONTINENT, LOCATION_PROVIDER
            <span class="br0">&#93;</span>
            <span class="br0">&#40;</span>piwik_output<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">writerow</span><span class="br0">&#40;</span>output<span class="br0">&#41;</span>
            output = <span class="br0">&#91;</span>LVA_ID, COL_ID, GA_ACTION_URL, <span class="nu0">0</span>, GA_ACTION_NAME, <span class="nu0">0</span><span class="br0">&#93;</span>
            <span class="br0">&#40;</span>piwik_output<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">writerow</span><span class="br0">&#40;</span>output<span class="br0">&#41;</span>
            COL_ID += <span class="nu0">1</span>
            LVA_ID += <span class="nu0">1</span>
&nbsp;
<span class="kw1">if</span> __name__ == <span class="st0">&quot;__main__&quot;</span>:
    main<span class="br0">&#40;</span><span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span>:<span class="br0">&#93;</span><span class="br0">&#41;</span></pre></div></div>
<p>You can <a href="http://jaymz.eu/wp-content/uploads/piwik-ga/createGAtoPiwikCSV.python">download the script here</a>.</p>
<p>The above script outputs 2 csv files which you can then load straight into the piwik tables. You can do that via the console:</p>
<div id="wpshdo_7" class="wp-synhighlighter-outer"><div id="wpshdt_7" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_7"></a><a id="wpshat_7" class="wp-synhighlighter-title" href="#codesyntax_7"  onClick="javascript:wpsh_toggleBlock(7)" title="Click to show/hide code block">Code block</a></td><td align="right"><a href="#codesyntax_7" onClick="javascript:wpsh_code(7)" title="Show code only"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_7" onClick="javascript:wpsh_print(7)" title="Print code"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://jaymz.eu/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://jaymz.eu/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_7" class="wp-synhighlighter-inner" style="display: block;"><pre class="sql"><span class="kw1">LOAD</span> <span class="kw1">DATA</span> <span class="kw1">LOCAL</span> <span class="kw1">INFILE</span> <span class="st0">'output-log_visit.csv'</span> <span class="kw1">INTO</span>
<span class="kw1">TABLE</span> piwik_log_visit <span class="kw1">FIELDS</span> terminated <span class="kw1">BY</span> <span class="st0">','</span>
<span class="kw1">ENCLOSED</span> <span class="kw1">BY</span> <span class="st0">'&quot;'</span> <span class="kw1">LINES</span> terminated <span class="kw1">BY</span> <span class="st0">'<span class="es0">\n</span>'</span>;
&nbsp;
<span class="kw1">LOAD</span> <span class="kw1">DATA</span> <span class="kw1">LOCAL</span> <span class="kw1">INFILE</span> <span class="st0">'output-log_vaction.csv'</span> <span class="kw1">INTO</span>
<span class="kw1">TABLE</span> piwik_log_link_visit_action <span class="kw1">FIELDS</span> terminated <span class="kw1">BY</span> <span class="st0">','</span>
<span class="kw1">ENCLOSED</span> <span class="kw1">BY</span> <span class="st0">'&quot;'</span> <span class="kw1">LINES</span> terminated <span class="kw1">BY</span> <span class="st0">'<span class="es0">\n</span>'</span>;</pre></div></div>
<p>Now I <em>did</em> think that I was all done but there are a couple of caveats before you&#8217;ll finally see that visitor graph take shape. When you add a site to piwik it gives it a creation date in the backend database. This is not editable from the front end and piwik will <em>only</em> examine row data which is <em>greater than</em> that date. So change the  <em><strong>ts_created</strong></em> field for your site to the earliest date of the data you have imported. Finally, drop the <em><strong>archive_blob_* </strong></em>tables, these are caches of calculations piwik has done and when missing will be recreated when the dashboard is loaded.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/02/pw-site-date-change.png"><img class="aligncenter size-full wp-image-190" title="pw-site-date-change" src="http://jaymz.eu/wp-content/uploads/2010/02/pw-site-date-change.png" alt="" width="490" height="189" /></a>With all that done when you refresh your dashboard you should see your visitor graph with actual data! Huzzah! In the below image I&#8217;ve loaded in a csv containing hit data for January into a fresh install of piwik locally.</p>
<p><a href="http://jaymz.eu/wp-content/uploads/2010/02/pw-end-output.png"><img class="aligncenter size-full wp-image-186" title="pw-end-output" src="http://jaymz.eu/wp-content/uploads/2010/02/pw-end-output.png" alt="" width="356" height="213" /></a>Google do provide an export API for GA data but I&#8217;ve not had the time to become familiar with it. In any case it will only export the same level of data that you get on the website, so even connecting via the API you&#8217;ll not get hourly hits. However that could be a starting point for dumping out a list of page data which could be converted into a table of <em><strong>log_actions </strong></em>which is where piwik stores page names and urls for binding to a visit. I&#8217;m open to work with someone on that if anyone&#8217;s interested. For now this should save me a giant ballache of time on Monday morning.</p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/02/importing-existing-visitor-stats-from-google-analytics-to-piwik/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Blender generative art with halos</title>
		<link>http://jaymz.eu/2010/01/blender-generative-art-with-particles-halos/</link>
		<comments>http://jaymz.eu/2010/01/blender-generative-art-with-particles-halos/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 22:44:57 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[3d]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[blender]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.jaymz.eu/?p=99</guid>
		<description><![CDATA[Some time ago when I first started to play with blender, particles where about the only half decent thing I could manage. Whilst working with a little script to draw me some cubes at along a grid (yeah, think city generator), I added a particle system to each one and gave them a random color. [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago when I first started to play with blender, particles where about the only half decent thing I could manage. Whilst working with a little script to draw me some cubes at along a grid (yeah, think city generator), I added a particle system to each one and gave them a random color. When I rendered it I thought it made a pretty cool background and played about with adding more variation.</p>
<p><a href="http://www.jaymz.eu/wp-content/uploads/2010/01/blender-gart.png"><img class="aligncenter size-medium wp-image-100" title="blender-gart" src="http://www.jaymz.eu/wp-content/uploads/2010/01/blender-gart-300x255.png" alt="" width="300" height="255" /></a></p>
<p>The key to nice particles in blender is often to <em>have more of them</em> and <em>bump up the alpha</em>. Then enable the mysterious &#8220;x-alpha&#8221; setting in the halo pipeline. To get that feeling of energy or glowing you normally want to have the alpha quite low and the <em>add</em> setting fairly high.</p>
<p><a href="http://www.jaymz.eu/wp-content/uploads/2010/01/halos-2.png"><img class="aligncenter size-medium wp-image-101" title="halos-2" src="http://www.jaymz.eu/wp-content/uploads/2010/01/halos-2-300x187.png" alt="" width="300" height="187" /></a></p>
<p><a href="http://www.jaymz.eu/wp-content/uploads/2010/01/halos-2.png"></a>An example blend file is here: <a href="http://www.jaymz.eu/wp-content/uploads/2010/01/halos.zip">halos</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/01/blender-generative-art-with-particles-halos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reddit comment/submission vote tracker</title>
		<link>http://jaymz.eu/2010/01/reddit-commentsubmission-vote-tracker/</link>
		<comments>http://jaymz.eu/2010/01/reddit-commentsubmission-vote-tracker/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 22:03:14 +0000</pubDate>
		<dc:creator>jaymz</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[reddit]]></category>
		<category><![CDATA[cherrypy]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.jaymz.eu/?p=82</guid>
		<description><![CDATA[Some time ago I noticed that the up/down count on comments &#38; submissions on reddit would vary wildly under the hood whilst the aggregate displayed would stay fairly steady quite often. By that I mean a comment that had 20 points might be flicking wildy as redditors turn arrows blue &#38; orange. I thought it [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago I noticed that the up/down count on comments &amp; submissions on <a href="http://www.reddit.com/">reddit</a> would vary wildly <em>under the hood</em> whilst the aggregate displayed would stay fairly steady quite often. By that I mean a comment that had 20 points might be flicking wildy as redditors turn arrows blue &amp; orange.</p>
<p>I thought it might be interesting to graph such activity and I had at first thought of using google charts&#8217; fairly decent api but quickly discovered <a href="http://code.google.com/p/flot/"><em>Flot</em></a> and was completely sold. If you have ever needed to create some small chart in a web app and started to roll your own solution (very often people will do some graph drawing server side then send over an image) then <strong>stop!</strong> and go look at Flot. Its an amazing bit of javascript.</p>
<p><a href="http://www.jaymz.eu/wp-content/uploads/2010/01/output-enhanced.png"><img class="aligncenter size-medium wp-image-83" title="output-enhanced" src="http://www.jaymz.eu/wp-content/uploads/2010/01/output-enhanced-300x234.png" alt="" width="300" height="234" /></a></p>
<p>In hindsight the &#8220;battle of your comment&#8221; isn&#8217;t as interesting as I thought it would be but it is quite nice to watch how a submission progresses on the site over time. Its only really useful for semi-popular ones as otherwise there just isn&#8217;t the data. The whole thing works by appending <em>.json</em> to the reddit url given. That&#8217;s the unoffical/offical reddit API. That is then parsed to grab the up/down vote count and then its simply sent back to Flot as JSON itself.</p>
<p>I have noticed that whilst the comment count <em>on the site</em> will vary much more rapidly the JSON file itself doesn&#8217;t and seems to lag behind somewhat. I guess that makes sense from a load/abuse point of view. In real terms this means there&#8217;s not a lot of point setting the timeout on this page to hammer reddit for &#8220;by the second&#8221; data.</p>
<p>Some may find it useful so here it is. I have it currently sitting at <a href="http://jaymzcd.webfactional.com">jaymzcd.webfactional.com</a>. This makes use of cherrypy and jquery. If you&#8217;d like the code its <a href="http://www.jaymz.eu/wp-content/uploads/2010/01/rgraph.zip">here</a>.</p>

<div class="ngg-galleryoverview" id="ngg-gallery-3-82">


	
	<!-- Thumbnails -->
		
	<div id="ngg-image-33" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://jaymz.eu/wp-content/gallery/reddit-graph/sample-output1.png" title=" " class="shutterset_set_3" >
								<img title="sample-output1" alt="sample-output1" src="http://jaymz.eu/wp-content/gallery/reddit-graph/thumbs/thumbs_sample-output1.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-36" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://jaymz.eu/wp-content/gallery/reddit-graph/sample-output2.png" title=" " class="shutterset_set_3" >
								<img title="sample-output2" alt="sample-output2" src="http://jaymz.eu/wp-content/gallery/reddit-graph/thumbs/thumbs_sample-output2.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-37" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://jaymz.eu/wp-content/gallery/reddit-graph/sample-output3.png" title=" " class="shutterset_set_3" >
								<img title="sample-output3" alt="sample-output3" src="http://jaymz.eu/wp-content/gallery/reddit-graph/thumbs/thumbs_sample-output3.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-32" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://jaymz.eu/wp-content/gallery/reddit-graph/sample-output4.png" title=" " class="shutterset_set_3" >
								<img title="sample-output4" alt="sample-output4" src="http://jaymz.eu/wp-content/gallery/reddit-graph/thumbs/thumbs_sample-output4.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 		
	<div id="ngg-image-34" class="ngg-gallery-thumbnail-box"  >
		<div class="ngg-gallery-thumbnail" >
			<a href="http://jaymz.eu/wp-content/gallery/reddit-graph/sample-output5.png" title=" " class="shutterset_set_3" >
								<img title="sample-output5" alt="sample-output5" src="http://jaymz.eu/wp-content/gallery/reddit-graph/thumbs/thumbs_sample-output5.png" width="100" height="75" />
							</a>
		</div>
	</div>
	
		
 	 	
	<!-- Pagination -->
 	<div class='ngg-clear'></div>
 	
</div>


]]></content:encoded>
			<wfw:commentRss>http://jaymz.eu/2010/01/reddit-commentsubmission-vote-tracker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

