<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[imitatingai]]></title><description><![CDATA[imitatingai]]></description><link>https://imitatingai.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 11:48:03 GMT</lastBuildDate><atom:link href="https://imitatingai.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[compiling ncdu for synology]]></title><description><![CDATA[Ncdu is a command line tool that evaluates disk space. I wanted to run this on my Synology NAS, so I decided to compile it. Note that ncdu is available for Synology, for instance as part of https://sy]]></description><link>https://imitatingai.com/compiling-ncdu-for-synology</link><guid isPermaLink="true">https://imitatingai.com/compiling-ncdu-for-synology</guid><dc:creator><![CDATA[James O'Grady]]></dc:creator><pubDate>Thu, 02 Apr 2026 23:52:30 GMT</pubDate><content:encoded><![CDATA[<p>Ncdu is a command line tool that evaluates disk space. I wanted to run this on my Synology NAS, so I decided to compile it. Note that ncdu is available for Synology, for instance as part of <a href="https://synocommunity.com/"><strong>https://synocommunity.com/</strong></a> which uses spksrc (<a href="https://github.com/SynoCommunity/spksrc"><strong>https://github.com/SynoCommunity/spksrc</strong></a>) but this is about the raw compile. Also, I cheat here and take a short cut that might not otherwise work, except I’m relying on a slow pace of change for both the ncurses package and ncdu.</p>
<p>This is being compiled on ubuntu on a Oracle VirtualBox VM on an intel mac.</p>
<p>The first step is to download a DSM tool chain as described here. <a href="https://help.synology.com/developer-guide/compile_applications/manual.html"><strong>https://help.synology.com/developer-guide/compile\_applications/manual.html</strong></a></p>
<p>As suggested, I untarred it into <em>/usr/local.</em> I have a DS220j which I used to figure out what toolchain was required.</p>
<p>Then, I downloaded ncdu version 1.20. ncdu comes with a configure script and you have to call it pointing to the cross-compile environment, that is with the -host option set to <em>“aarch64-unknown=linux-gnua”.</em> The DSM tool chain adds some compilation tools to /<em>usr/local/aarch64-unknown-linux-gnu/bin/,</em> so configure will need pointers to these tools. CC should be set to the compiler from this directory (<em>aarch64-unknown-linux-gnu-gcc</em>) and LD to the loader (<em>aarch64-unknown-linux-gnu-ld</em>).</p>
<p>The resulting <em>./configure</em> failed, as the ncurses library was not present in the synology sde. Looking at the NAS itself, we see ncurses libraries present but we don't see the ncurses header files. The ncurses library is present on the NAS and can be used as long as you compile it.</p>
<p>We don't off-hand know the version of the package on the NAS. One option is to write a ncurses application that prints out the version, but instead, I took a short cut to assume that both ncdu and ncurses don't make fundamental changes often, so basically the latest version is fine. I eventually added a <em>–disable-dependency-tracking</em> option to configure due to this shortcut.</p>
<p>On my linux build machine, I installed the libncurses-dev package in the standard locations so I had access to the required header files. However, they need to be in the cross-compilation environment for the compile to work.for, here <em>/usr/local/aarch64-unknown-linux-gnu/sysroot.</em> It's straightforward to copy the header files in the ncurses-dev package from /usr/include to <em>/usr/local/aarch64-unknown-linux-gnu/sysroot/usr/include</em>. For the headers, I just copied them from the nas itself to <em>/usr/local/aarch64-unknown-linux-gnu/sysroot//lib</em>.</p>
<p>Rather than copy one file at a time, I copied everything the package added to the system into the proper directories, headers from the linux system itself and library .so files from the NAS.</p>
<p>At this point, configure and make creates a ncdu executable, which can be transferred to the NAS and used.</p>
]]></content:encoded></item><item><title><![CDATA[The earth may not be flat II]]></title><description><![CDATA[This isn’t really going to be a blog about flat earth. One more thing.
My last post was about how observed daylight doesn’t work on a purported flat earth map, as the day and night make unusual shapes which cannot be explained. The way the light real...]]></description><link>https://imitatingai.com/the-earth-may-not-be-flat-ii</link><guid isPermaLink="true">https://imitatingai.com/the-earth-may-not-be-flat-ii</guid><category><![CDATA[Python]]></category><category><![CDATA[astral]]></category><dc:creator><![CDATA[James O'Grady]]></dc:creator><pubDate>Fri, 19 Sep 2025 16:49:40 GMT</pubDate><content:encoded><![CDATA[<p>This isn’t really going to be a blog about flat earth. One more thing.</p>
<p>My last post was about how observed daylight doesn’t work on a purported flat earth map, as the day and night make unusual shapes which cannot be explained. The way the light really works is explained here.</p>
<p>On the earth, the sun lights up slightly over ½ of the world at one time, leaving slightly less than ½ in darkness. Since light bends in the atmosphere, the light refracts over into the half of the world that is not directly lit by the sun, leaving somewhat more of the planet lit up than in than dark.</p>
<p>One could demonstrate this by determining a position that the sun was directly overhead (the noon point). Then, figure out the positions where at that time the sun was rising or setting. We’d expect that the radius between the noon point and the sunrise/sunset positions would form a circle. Furthermore, there would be an antipode of the noon point and the sunrise/sunset points would also form a circle around those points. You could show this by calculating distances between the points.</p>
<p>If the results show two circles, the earth could not be a flat plane. On a flat plane, the arc that circles around the noon point could not also circle the antipode of that point. Thus, we are trying to generate noon points, the antipode of that point, sunrise and sunset points and distances between them.</p>
<p>This isn’t really about the shape of the earth, but about generating this data with python using two packages, astral to calculate solar positions and geopy to calculate distance. Note that both of these packages rely on the earth being a globe, so it would be no surprise that they behave as expected, but the use here is to give observations about day, night and distances on the earth. If the observations the program makes match reality, the earth must be round. For the earth to be flat, some observations must be disproved.</p>
<p>The python script I wrote for this is in <a target="_blank" href="https://github.com/jamesdogrady/sunGleason">https://github.com/jamesdogrady/sunGleason</a>, called daylightDistance.py.</p>
<p>To find the circles we need to calculate the point at which the sun is most over head on the earth. From there, we can determine the antipode of this point, which would be the center of darkness. The edges of the circles can be calculated by finding sunrise and sunset at various latitudes. Most of the time, some portions of the planet have 24 hour darkness or daylight, so the circle edges must account for this as well.</p>
<p>I’m mis-using astral here rather than a package that calculates the edges directly, so we have to find the points we require by using the astral package for a set of latitude and longitudes. This requires searching for the proper points which makes the program less direct. This will lead to errors as we may not calculate the edges of the circle with absolute precision. This make the exercise less about showing the earth is a globe and more about using astral to make observations to support a globe.</p>
<p>First, we have to find the noon point. We can tell where it is solar noon currently by looking on the equator and getting the time for solar noon, and calculating from that the longitude at which it’s currently noon. This looks like this.</p>
<pre><code class="lang-python">obs_lat=<span class="hljs-number">0</span>
obs_long=<span class="hljs-number">0</span>
obs=Observer(obs_lat,obs_long);
noon_tm=noon(obs,tm,tzinfo=utc);
dps=<span class="hljs-number">15</span>/(<span class="hljs-number">60</span>*<span class="hljs-number">60</span>)
<span class="hljs-comment"># calculate the longitude where it is noon currently.</span>
<span class="hljs-comment"># noon has either passed or is coming, so we can tell where it is.</span>
<span class="hljs-keyword">if</span> ( noon_tm &gt; tm ) :
    <span class="hljs-comment"># noon is coming.</span>
    noon_time=(noon_tm - tm).seconds
    noon_long=obs_long + noon_time *dps
<span class="hljs-keyword">else</span> :
    noon_time=(tm - noon_tm).seconds
    noon_long=obs_long - noon_time * dps
</code></pre>
<p>The noon latitude is between the Tropic of Cancer and the Tropic of Capricorn, and we search within this range to find it.</p>
<pre><code class="lang-python">eq_obs=Observer(<span class="hljs-number">0</span>,noon_long);
eq_zenith=zenith(eq_obs,tm);
north_obs= Observer(tropic_cancer,noon_long);
south_obs= Observer(tropic_capricorn,noon_long);
north_zen=zenith(north_obs,tm);
south_zen=zenith(south_obs,tm);

done=<span class="hljs-literal">False</span>
first=<span class="hljs-literal">True</span>
north_lat=tropic_cancer
south_lat = tropic_capricorn
<span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> done :
    <span class="hljs-comment"># if the zenith is the same at both endpoints the correct value is in the middle.</span>
    <span class="hljs-keyword">if</span> north_zen == south_zen :
        noon_lat = (north_lat + south_lat) /<span class="hljs-number">2</span>
        done=<span class="hljs-literal">True</span>

    <span class="hljs-comment"># are we close enough to stop?</span>
    diff = abs(abs(north_lat) - abs(south_lat))

    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> first <span class="hljs-keyword">and</span> diff &lt; precision ) :
        noon_lat = north_lat
        done=<span class="hljs-literal">True</span>
    first=<span class="hljs-literal">False</span>;
    <span class="hljs-keyword">if</span> ( north_zen &lt; south_zen ) :
        <span class="hljs-comment"># between center and south.</span>
        south_lat = ( north_lat + south_lat)/<span class="hljs-number">2</span>
        south_obs= Observer(south_lat,noon_long);
        south_zen=zenith(south_obs,tm)
    <span class="hljs-keyword">else</span> :
        north_lat = ( north_lat + south_lat)/<span class="hljs-number">2</span>
        north_obs= Observer(north_lat,noon_long);
        north_zen=zenith(north_obs,tm);
</code></pre>
<p>We are looking for the lowest zenith and thus the point where the sun is highest in the sky. The point on the opposite side of the earth from this noon point have the opposite latitude. For longitude, we add 180 to western (negative) values and subtract 180 from eastern (positive) values.</p>
<p>To calculate the edges of daylight and night, we write a function to search for the points.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find_true_value</span>(<span class="hljs-params">low,high ,val,tm,fcn</span>) :</span>
    done=<span class="hljs-literal">False</span>
    <span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> done :
        ret_bool = <span class="hljs-literal">False</span>;
        t=abs(high - low)
        <span class="hljs-comment"># for longitude, if you are more than 180 apart, you are going the long way around.  </span>
        <span class="hljs-keyword">if</span> t &gt; <span class="hljs-number">180</span> :
            t=<span class="hljs-number">360</span>-t
        diff = t/<span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> ( diff &lt; precision  ) :
            <span class="hljs-keyword">return</span> low
        mid = low+diff
        <span class="hljs-comment"># this could be a latitude but it won't be that big</span>
        <span class="hljs-keyword">if</span> mid &gt; <span class="hljs-number">180</span> <span class="hljs-keyword">or</span> mid &lt; <span class="hljs-number">-180</span> :
            mid=conv_long(mid);
        (res,v) = fcn(mid,val,tm);
        <span class="hljs-keyword">if</span> v != <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> v :
            ret_bool=<span class="hljs-literal">True</span>
        <span class="hljs-keyword">if</span> res :
            high=mid
        <span class="hljs-keyword">else</span> :
            low=mid
</code></pre>
<p>The point we are searching for is between low and high. fcn is a helper function for the search. If it returns True, the point we are looking for is between low and mid. if it returns False, the point we are looking for is between mid and high. This function works for both latitude and longitude searches. If low/high are latitudes, val must be a longitude and fcn must understand which value is being passed in and vice versa.</p>
<p>The helper function that finds the 24 hour sun is shown below.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">twenty_4_hour</span>(<span class="hljs-params">lat, long,tm</span>) :</span>
        obs= Observer(lat,long)
        noRise=<span class="hljs-literal">False</span>
        light=<span class="hljs-literal">False</span>;
        <span class="hljs-keyword">try</span> :
            rise=sunrise(obs,tm);
            noRise=<span class="hljs-literal">False</span>
        <span class="hljs-keyword">except</span> ValueError <span class="hljs-keyword">as</span> e :
            noRise=<span class="hljs-literal">True</span>
            found_24_hour=<span class="hljs-literal">True</span>
            <span class="hljs-keyword">if</span> <span class="hljs-string">"above"</span> <span class="hljs-keyword">in</span> e.args[<span class="hljs-number">0</span>] :
                light=<span class="hljs-literal">True</span>;
            <span class="hljs-keyword">else</span>:
                light=<span class="hljs-literal">False</span>;
        <span class="hljs-keyword">if</span> ( lat &lt; <span class="hljs-number">0</span>) :
            <span class="hljs-keyword">return</span>( <span class="hljs-keyword">not</span> noRise,light);
        <span class="hljs-keyword">return</span>(noRise,light);
</code></pre>
<p>For each trial, we see if there is a 24 hour sun at the given latitude. If there is, we know the latitude we are looking for is south of us in the northern hemisphere and north of us in the southern hemisphere, so we return a different value. For example, the southern light point is found by starting from -90 and going to just north of the antarctic circle (-65)</p>
<pre><code class="lang-python">(south_lat)=find_true_value(<span class="hljs-number">-90</span>,<span class="hljs-number">-65</span>,noon_long,tm,twenty_4_hour);
</code></pre>
<p>We have similar helper functions for sunrise and sunset for latitudes at which the sun does rise and set to find the points where this occurs. Note that while the sun travels at 15 degrees per hour, you cannot calculate sunrise/sunset longitudes because while the earth is rotating on it’s axis, it’s also revolving around the sun, so the longitude of sunset/sunrises varies slightly due to the tilt of the earth. Unless you. account for this, the positions of sunrise/sunset are wrong.</p>
<p>Once we’ve calculated the points where the sun is rising or setting, we can calculate distances. geopy has a geodesic function to calculate distances using great circles accounting for the oblate spheroid shape of the earth. The program also calculates distances assuming a sphere. geodesic takes two points, so we do calculations like this</p>
<pre><code class="lang-python">     radius =geodesic((noon_lat,noon_long),(lat,sunrise_long)).kilometers
</code></pre>
<p>In order to confirm the observations, there are check functions to be sure than sunrise, sunset and noon are close to where the program calculates they are. Here is check_sunset</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">check_sunset</span>(<span class="hljs-params">lat,long,tm</span>) :</span>
    s=<span class="hljs-string">" sun is up"</span>
    <span class="hljs-keyword">if</span> debug :
        print(<span class="hljs-string">"check_sunset"</span>,lat,long);
    lat_obs = Observer(lat,long)
    set_time = sunset(lat_obs,tm) 
    <span class="hljs-keyword">if</span> ( set_time &gt; tm) :
        diff = set_time - tm
    <span class="hljs-keyword">else</span>:
        s=<span class="hljs-string">"sun has already set"</span>
        diff = tm - set_time
    <span class="hljs-keyword">if</span> debug :
        print(<span class="hljs-string">"check_sunset("</span>,lat,<span class="hljs-string">","</span>,long,<span class="hljs-string">") "</span>,diff.seconds,<span class="hljs-string">" different"</span>);
    <span class="hljs-keyword">if</span> ( diff.seconds &lt; assert_seconds ) :
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>assert_seconds and precision define how accurate the search is.</p>
<p>To handle 24 hour sun/darkness, we need to find where the edge is of darkness or light. If there is 24 hour daylight at say 85 ° N and the noon longitude is 120 degrees E, it will be light at the 120 E latitude up to the north pole. It won’t be dark until you get to 85 degrees N at the opposite longitude. We’ve calculated this longitude before, it’s the longitude of the antipode of the noon point. So that’s the edge of the daylight/night circles in the arctic regions.</p>
<p>We calculate all the radius’s for daylight and nighttime and put them in pandas data frame so we can do analysis on the results.</p>
<blockquote>
<p><a target="_blank" href="http://daylightDistance.py"><code>daylightDistance.py</code></a>       <code>-g -s</code></p>
<p><code>Time is  09-09-2025 16:47</code></p>
<p><code>Noon Point is      (5.05,-72.70)</code></p>
<p><code>Anti Noon Point is (-5.05,107.30)</code></p>
<p><code>value                           average    range    std dev</code></p>
<p><code>----------------------------  ---------  -------  ---------</code></p>
<p><code>daylight radius (sphere)       10095.59    59.85       8.56</code></p>
<p><code>darkness radius (sphere)        9919.52    59.85       8.56</code></p>
<p><code>circumference (great circle)   40030.23     0.00       0.00</code></p>
<p><code>daylight_radius (actual)       10099.64    71.37      11.27</code></p>
<p><code>darkness radius (actual)        9923.83    71.37      11.71</code></p>
</blockquote>
<p>Here, we see that as expected, there is a rough circle around both the noon point and the anti-noon point. While not all radius’s are the same as measured, they are within a fairly narrow range, 59.85 km of around 40075 km earth circumference . The standard deviation of these errors is also low. Note that the calculated circumference in a great circle model is based on the observed radius and not on the actual circumference so it differs from the accepted value of the circumference. On the oblate spheroid earth, we would expect less circular shapes as the flattening introduces distortion on the circles and we do see this.</p>
<p>With this program, there is an option to show the points which we think of the edges of the circle. We’ll show this at the 2025 winter solstice. (the -l option shows points every 20° ).</p>
<p><code>python3.13</code> <a target="_blank" href="http://daylightDistance.py"><code>daylightDistance.py</code></a> <code>-l 20  -g  -t "12-21-2025 9:03" -v</code></p>
<blockquote>
<p><code>Time is  12-21-2025 15:03</code></p>
<p><code>Noon Point is      (-23.05,-46.19)</code></p>
<p><code>Anti Noon Point is (23.05,133.81)</code></p>
<p><code>value                       average    range    std dev</code></p>
<p><code>------------------------  ---------  -------  ---------</code></p>
<p><code>daylight_radius (actual)   10108.20   131.56      40.25</code></p>
<p><code>darkness radius (actual)    9914.09   131.56      41.25</code></p>
<p><code>Radius Data Oblate Spheroid</code></p>
<p><code>point               distance from noon (km)    distance from anti-noon (km)</code></p>
<p><code>----------------  -------------------------  ------------------------------</code></p>
<p><code>(-40, 66.33)                       10141.58                         9876.64</code></p>
<p><code>(-40, -158.76)                     10145.79                         9872.42</code></p>
<p><code>(-20, 53.79)                       10123.83                         9904.50</code></p>
<p><code>(-20, -146.22)                     10129.73                         9898.59</code></p>
<p><code>(0, 44.64)                         10100.77                         9931.62</code></p>
<p><code>(0, -137.07)                       10107.14                         9925.24</code></p>
<p><code>(20, 35.63)                        10074.72                         9953.85</code></p>
<p><code>(20, -128.06)                      10080.26                         9948.32</code></p>
<p><code>(-65.78, 133.81)                   10154.87                         9849.06</code></p>
<p><code>(67.34, -46.19)                    10023.31                         9980.63</code></p>
</blockquote>
<p>Note that the program does worse calculating the distances as we move closer to winter. This is because more of the sunlight and darkness is over the somewhat flattened polar regions.</p>
<p>Two options control the accuracy of the calculations. -p specifies how close to a point we need to look. This defaults to .05 and is in degrees. -a will cause the program to delete points for which the difference between sunrise/sunset and the current time is greater than the specified value. The default is 30. Playing with these values doesn’t really impact the results that much. You see a more consistent radius, but not by that much.</p>
<p>The results match our expectations. We see the circles we expect to see. While of course a point opposite the noon point has no meaning on a flat plane, the fact that we can identify a point where darkness forms a curve indicates that this point would be real and have significance. The noon point, sunrise and sunset are all observations that can be made on the earth.</p>
<p>I took a look at the values calculated for the circle around the antipode of the noon point for various times over the course of year. As you might expect, the calculations for a oblate spheroid are within a narrow range, but not that even.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758039318758/f4a23ea3-922b-455b-aaf1-d024aea33e49.png" alt class="image--center mx-auto" /></p>
<p>The results for spherical model are quite narrowly defined. Here, outliers are excluded from the histogram, but the counts are not significant in this range.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758039396600/86a8cacc-fb63-42ff-8fb0-bbe2dc10ae35.png" alt class="image--center mx-auto" /></p>
<p>It might perhaps be possible for daylight on a flat earth to form a circle around an overhead sun at the noon point. It would not be possible for the night to form a circle at the same time as we see here. The edge between daylight and night curves between two points on the earth at the same time, all the while moving over the course of a day and year. The geometry that support this is a globe earth.</p>
<p>The only way out would be to claim that the distances calculated here are not accurate. The problem this creates is that the same calculations are used regularly to measure distances on the planet accurately, for instance, for airline flights. There is not a way to resolve this problem. An attempt to claim distances are different than calculated will inevitably bump up against known distances on the planet.</p>
]]></content:encoded></item><item><title><![CDATA[The Earth may not be flat.]]></title><description><![CDATA[This is the last article about a git project, https://github.com/jamesdogrady/sunGleason where I take a purported flat earth map and see what sunlight looks like on this map. In reality, ½ of the earth is illuminated by the sun (slightly more due to ...]]></description><link>https://imitatingai.com/the-earth-may-not-be-flat</link><guid isPermaLink="true">https://imitatingai.com/the-earth-may-not-be-flat</guid><category><![CDATA[Python]]></category><category><![CDATA[astral]]></category><dc:creator><![CDATA[James O'Grady]]></dc:creator><pubDate>Fri, 22 Aug 2025 16:11:41 GMT</pubDate><content:encoded><![CDATA[<p>This is the last article about a git project, <a target="_blank" href="https://github.com/jamesdogrady/sunGleason">https://github.com/jamesdogrady/sunGleason</a> where I take a purported flat earth map and see what sunlight looks like on this map. In reality, ½ of the earth is illuminated by the sun (slightly more due to refraction). The part of the earth that is in darkness is in darkness because it’s turned away from the sun. On “flat earth” , the part of the earth that’s in darkness is in darkness because the sun is too far away and can no longer be seen. Part of this model assumes a local sun thousands of miles away of course. A sun 93 million miles away would illuminate the entire surface of a flat disk.</p>
<p>Here are daylight pictures at the start of each season in 2025.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750272127640/438961d1-89f6-44e0-b28a-0c3add3c29a0.jpeg" alt="Spring Equinox" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750272309381/f31f4dea-2f9a-4d47-b5b5-367bf826b248.jpeg" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750272336723/bed7923c-eea8-4daa-bd3c-b7ba2fb41bc9.jpeg" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750272364518/5a6d4a20-6745-4b22-b875-ce2f0bb35a33.jpeg" alt class="image--center mx-auto" /></p>
<p>It’s important to note in those places on earth where there is not 24 hours of day or night, the sun is experienced that same way in all places. It rises in the east, sets towards the west and is the same size throughout the day and throughout the year. In the north during the winter, you see the same sort of sun you see during the summer just farther south in the sky.</p>
<p>Given that all people experience the sun in the same way, the question is why the sun casts a different pattern of light and darkness when it is overhead at different spots in the earth. The point at which the sun is overhead will change from the Tropic of Cancer, to the Tropic of Capricorn over the course of the change of seasons but the daylight pattern changes dramatically from season to season for no physical reason.</p>
<p>Lets take for example the Spring and Fall, when the sun is overhead at the equator. We’d expect the pattern to be similar and it is. We see the light here making basically a straight line through the north pole and illuminating the entire planet below that line. Spring and Fall on this drawing does show one important observation that matches reality. At any point in time, roughly ½ of the surface of the planet is in daylight and ½ is in darkness. Spring and fall are the only time that that’s true on this map.</p>
<p>As the sun moves north from Spring to Summer, towards the Tropic of Cancer, the northern edge becomes a curve instead of a straight line. There’s nothing that can account for this change. if the daylight edge is straight when it is over the equator, how can it be less straight as the sun moves north? Also, the sun becomes less able to light up the south as it goes north. When the sun is overhead at the equator, it can light up half the planet 90 degrees south of the equator. When the sun is overhead at 23.5 degrees N, only part of the planet 90 degrees south of that can be illuminated. For some reason, the summer sun is much less effective at lighting the surface of the planet than it is at other times of the year.</p>
<p>In winter, the situation changes. Suddenly the sun can illuminate virtually the entire surface of the earth, leaving only a small portion in night at any given time. Once again, to accept this map, one would have to explain this property of light.</p>
<p>Of course, the reason for the pseudo-conundrum is that this map is just a projection of the globe earth. At the equinoxes, when the pattern of daylight forms a more or less straight line though a longitude, the projection shows half the earth illuminated with the straight line being that line of longitude, just the edge of where daylight reaches on the globe earth.</p>
<p>For summer and fall, the pattern is explained by distortions on the map. The parts of the earth above the equator occupy less space on the map than in reality and the parts below the equator occupy much more of the space than on the real earth. If you were to measure the length of the 10 degree north lattitude line, the equator and the 10 degrees south latitude line, the 10 degree north and south lines will be roughly equal while the equator will be longer. On the map, the length of each latitude line increases as you go south all the way to end. The deviation from reality increases the farther south you go so the edge of the earth has a circumference that is well above anything measured on an actually existing earth.</p>
<p>The result of this is that shapes shown in the north are too small and shapes drawn in the south are far too large. This creates an illusion that the December solstice sun covers large portions of the earth leaving a modest oval of night, and the June solstice daylight forms an oval shape.</p>
<p>The project allows you to change the projection and we can change it for a point where the sun is roughly overhead at the December solstice, 23.4 S, 45.93 W. (these are estimates based on points examined by the program). The result looks like what you’d expect.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750274480542/92284ff3-8714-40af-bf09-fd5fc795691d.jpeg" alt class="image--center mx-auto" /></p>
<p>While the shapes of the continents are distorted, you see that daylight forms a circle over the noon point. Daylight forms a circle on the earth. This is expected on a globe and required on a flat earth with an overhead sun. Since this Gleason map doesn’t show daylight as a circle, it cannot be an accurate earth map.</p>
]]></content:encoded></item><item><title><![CDATA[Daylight on a globe earth]]></title><description><![CDATA[This is about a github project https://github.com/jamesdogrady/sunGleason.
Sometimes, I’ll click on YouTube videos that debunk the flat earth theory. One common map used in this theory is the so called Gleason map, from the late 1800s which looks lik...]]></description><link>https://imitatingai.com/daylight-on-a-globe-earth</link><guid isPermaLink="true">https://imitatingai.com/daylight-on-a-globe-earth</guid><dc:creator><![CDATA[James O'Grady]]></dc:creator><pubDate>Wed, 06 Aug 2025 18:09:25 GMT</pubDate><content:encoded><![CDATA[<p>This is about a github project <a target="_blank" href="https://github.com/jamesdogrady/sunGleason">https://github.com/jamesdogrady/sunGleason</a>.</p>
<p>Sometimes, I’ll click on YouTube videos that debunk the flat earth theory. One common map used in this theory is the so called Gleason map, from the late 1800s which looks like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749152105310/f5528541-ff8d-45c8-86d8-7d82575b5a0f.jpeg" alt class="image--center mx-auto" /></p>
<p>The map has many problems, but its youtube plausible since you can travel west or east around the map without falling off the edge, unlike other maps. To fall off the edge, you have to travel to interior Antartica which is more possible now, but was out of reach when the map was published. Sometimes, when showing this map, someone will show how the sunlight works on this map with a flashlight and in fact, it doesn’t. I wanted to show that and cartopy in python lets you do that, which is what the project is about.</p>
<p>This map is a Azimuthal Equidistant projection of the globe with the center at the north pole. This is one of the projections offered by cartopy.crs, so we can show a similar map very easily.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> cartopy.crs <span class="hljs-keyword">as</span> ccrs
<span class="hljs-keyword">import</span> cartopy.feature <span class="hljs-keyword">as</span> cfeature

proj=ccrs.AzimuthalEquidistant(central_latitude=<span class="hljs-number">90</span>, central_longitude=<span class="hljs-number">-90</span>);
ax = plt.axes(projection=proj)
ax.set_global()
ax.coastlines()
ax.gridlines(draw_labels=<span class="hljs-literal">True</span>, linewidth=<span class="hljs-number">0.5</span>, color=<span class="hljs-string">'gray'</span>, alpha=<span class="hljs-number">0.5</span>)
ax.add_feature(cfeature.BORDERS, linewidth=<span class="hljs-number">0.5</span>)
ax.add_feature(cfeature.LAND, facecolor=<span class="hljs-string">'lightgray'</span>)
ax.add_feature(cfeature.OCEAN, facecolor=<span class="hljs-string">'lightblue'</span>)

<span class="hljs-comment"># Chicago IL</span>
lat=<span class="hljs-number">41.8781</span>
long=<span class="hljs-number">-87.6298</span>
ax.plot(long,lat,<span class="hljs-string">'o'</span>,markersize=<span class="hljs-number">10</span>,transform=ccrs.PlateCarree(),color=<span class="hljs-string">'red'</span>);
plt.show()
</code></pre>
<p>Central latitude is 90 for the North Pole. We use the central longitude of 90 W to replicate the engraving. Western longitudes and southern latitudes are negative. The location of Chicago is plotted on the map with too large of a circle (The ‘o’ in ax.plot). The result looks like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749152824888/ab3eae6c-dc28-4f23-9e3d-5516b2c4aeb7.png" alt class="image--center mx-auto" /></p>
<p>To show the daylight, we’ll use the astral package for python. This package allows you to calculate sunrise and sunset based on latitude and longitude. We’ll mark each point with a different color depending on whether it’s day or night. There are two approaches here. I chose to use astral to calculate whether it’s day or night in individual locations. It’s probably better to calculate the lines that separate day and night and draw polygons to show this. I think using sunrise/sunset is more verifiable since the times are widely available, for instance in local newspapers.</p>
<p>Note that north of the Arctic Circle and south of the Antarctic Circle, 24 hour night and day is possible. This causes the astral.sun.sunrise and astral.sun.sunset to throw an exception. The text of the exception tells you whether it’s night or day. Essentially, the code for the daylight check looks like this.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytz
utc= pytz.UTC
<span class="hljs-keyword">from</span> astral <span class="hljs-keyword">import</span> Observer
<span class="hljs-keyword">from</span> astral.sun <span class="hljs-keyword">import</span> sunrise,sunset
<span class="hljs-keyword">from</span> astral.sun <span class="hljs-keyword">import</span> zenith
<span class="hljs-keyword">from</span> shapely.geometry <span class="hljs-keyword">import</span> Point 
<span class="hljs-comment"># p is a Point, date is the date</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_day</span>(<span class="hljs-params">p,date</span>) :</span>
    obs = Observer(p.y,p.x)
    <span class="hljs-keyword">try</span> :
        rise_time = sunrise(obs,date).replace(tzinfo=utc)
        set_time = sunset(obs,date).replace(tzinfo=utc)
    <span class="hljs-keyword">except</span>  ValueError <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># 24 hour sun</span>
        <span class="hljs-keyword">if</span> <span class="hljs-string">"above"</span> <span class="hljs-keyword">in</span> e.text() :
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
        <span class="hljs-keyword">else</span> :
            <span class="hljs-comment"># 24 hour night.</span>
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>    
    <span class="hljs-keyword">if</span> ( rise_time &gt; set_time ) :
        <span class="hljs-comment"># the period of light crosses a day boundary.  the sun will be up between midnight</span>
        <span class="hljs-comment"># and set_time, down between set_time and rise_time and up after rise_time.</span>
        <span class="hljs-keyword">if</span> ( date &lt; set_time ) :
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
        <span class="hljs-keyword">if</span> ( date &gt;= rise_time ) :
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>;
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-comment"># here, rise_time &lt; set_time</span>
    <span class="hljs-keyword">if</span> ( date &gt;= rise_time <span class="hljs-keyword">and</span> date &lt; set_time) :
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>;
    <span class="hljs-keyword">else</span> :
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>;
</code></pre>
<p>What remains now is just to plot points. Here, we are using circles ( parameter “o”). The size of the circle is marker_size and it’s transparency is alpha which is point_alpha. These are configurable in the actually application.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> ( is_day(p,date ) :
    color=<span class="hljs-string">"yellow"</span>
<span class="hljs-keyword">else</span> :
    color=<span class="hljs-string">"black"</span>
ax.plot(p.x,p.y,<span class="hljs-string">'o'</span>, markersize=marker_size, transform=ccrs.PlateCarree(),color=color,alpha=point_alpha)
</code></pre>
<p>You can add a title to the plot using</p>
<pre><code class="lang-python">ax.set_title(date.strftime(<span class="hljs-string">"%m/%d/%Y %H:%M"</span> + <span class="hljs-string">" UTC"</span>));
</code></pre>
<p>We may want to add text to the bottom of the plot as well, but the coordinates make this tricky in this projection system. This puts text off to the side on the button away from the labels. This isn’t in the github.</p>
<pre><code class="lang-python">lon_min, lon_max, lat_min, lat_max = ax.get_extent()
ax.text( (lat_max-lat_min)/<span class="hljs-number">2</span>,lon_min<span class="hljs-number">-30</span>, <span class="hljs-string">"some text, ha='left', fontsize=12,transform=self.proj)</span>
</code></pre>
<p>The defaults here are an alpha of .01, a markersize of 1 and plotting points every degree. For the summer solstice, June 20, 2025 at 9:41 PM CDT, you get a picture like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750181313904/105ca461-0b47-463f-be1a-6ece8469f915.jpeg" alt class="image--center mx-auto" /></p>
<p>The Orange dot here is the point with the lowest zenith amount the points looked at. This is roughly where the sun is overhead.</p>
<p>To check the visualization, you can look at other web visualizations, for instance, that of timeanddate.com for the same time which looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754503582519/4e1282ae-461a-460e-89ed-7a7929288ffe.jpeg" alt class="image--center mx-auto" /></p>
<p>If one looks at the github, there’s more going on that what’s described here. The whole application is a Python QT application. I don’t cover that because it’s just how you’d wrap matplotlib into a python qt application which others cover already and what I want to cover is integrating daylight into a Gleason map. Also, some of the glue here is from ChatGPT which to be fair also pointed me toward cartopy when I had started with geopandas.</p>
<p>There is a preferences dialog also, which is also basically also from ChatGPT. You can specify the size and transparency of how the day or night markers are shown. You can also update the latitude and longitude the project is centered on. As you do this, you move off of the Gleason map, but visualizing the projection centered on where the sun is overhead is useful. I also allow you to specify a distance between latitudes and longitudes that are plotted. This allows you to draw pictures much more quickly, but the visualization isn’t as good. The defaults don’t show the individual points but spreading out the interval makes the points show up, e..g.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750699622376/31e4fffd-f445-4e2b-bc99-4c7621095a85.jpeg" alt class="image--center mx-auto" /></p>
<p>uses 5 degrees apart and plot much fewer points more quickly, but the points show up and more of the underlying plot is exposed between the points and it’s harder to see the shape daylight or nighttime make on the map..</p>
<p>This is not a fully fleshed out application. Much more could be done, but this has a pretty limited utility. The earth is not flat, so this is not a map of the earth and the drawings the application makes of daylight are not real so it’s unclear beyond what it already does how much more time is useful to spend on this.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction]]></title><description><![CDATA[This blog is inspired by a book “Writing to Learn: How to Write - and Think - Clearly About Any Subject at All” by William Zinsser. The claim on this book is that it’s more effective to learn something if you write about it. So that’s what I’m here t...]]></description><link>https://imitatingai.com/introduction</link><guid isPermaLink="true">https://imitatingai.com/introduction</guid><dc:creator><![CDATA[James O'Grady]]></dc:creator><pubDate>Fri, 30 May 2025 18:38:22 GMT</pubDate><content:encoded><![CDATA[<p>This blog is inspired by a book “Writing to Learn: How to Write - and Think - Clearly About Any Subject at All” by William Zinsser. The claim on this book is that it’s more effective to learn something if you write about it. So that’s what I’m here to do.</p>
<p>In a connected world, of course, you can publish what you write. This doesn’t seem to be a necessary step for writing. The value of publishing seems limited as well. The world is unlikely to need another discussion of what variables are in programming languages and I’m unlikely to be the person that could fill that need anyway. On the other hand, maybe there is something I could contribute and with search engines, maybe people can find it. On the off-chance you read this, as long as we both limit our expectations, we should be ok.</p>
<p>This is likely to be annoying because I’m at the point after a long software engineering career where what I want to learn about is eclectic and not necessarily systematic.</p>
<p>I’m interested in AI, machine learning and data, even though up to now, that hasn’t been any particular focus of my career, so maybe that will show up here more than other stuff, but we’ll find out.</p>
<p>Generative AI is hot right now, but perhaps is better and more sarcastically described as imitative AI. That leads to the title of this blog.</p>
<p>Once in my career, I decided to write some data gathering scripts I needed in Python, a language I did not know. I watched a youtube video and decided to get to it. Previously, I learned languages by reading books, which results in a pretty good end-to-end view of the language, but this time, I decided to just use google. Because of this, I was asking a lot of dumb Python questions, which normally resulted in going to stackoverflow.com and getting both the answer and comments about reading the manual before you ask trivial questions.</p>
<p>Now, since search engines like to preempt you actually going to a website with the answer, it summarizes the answer for you. It does this without judgement, so you can ask as silly a question as you like and it’s unlikely to say that’s silly. It will also give you a code segment on the concept. This is great for putting together scripts, but perhaps something gets lost if you abstract key ideas out of the concept. You no longer have to put up with being shamed for asking dumb questions, but maybe the shame encouraged a deeper dive. I guess we’ll find out.</p>
]]></content:encoded></item></channel></rss>