<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://egpbos.nl/feed.xml" rel="self" type="application/atom+xml" /><link href="https://egpbos.nl/" rel="alternate" type="text/html" /><updated>2025-03-24T08:49:32+00:00</updated><id>https://egpbos.nl/feed.xml</id><title type="html">egpBos.nl</title><subtitle>Evert Gerardus Patrick Bos&apos; website -  incomplete, unoriginal, unsubstantiated, without necessary nuance - subpar standards, for subpar readers like me and you!</subtitle><entry><title type="html">Moving to Jekyll part 4: Minima v3 theme</title><link href="https://egpbos.nl/blog/tech/2024/01/28/jekyll-minima-v3.html" rel="alternate" type="text/html" title="Moving to Jekyll part 4: Minima v3 theme" /><published>2024-01-28T00:00:00+00:00</published><updated>2024-01-28T00:00:00+00:00</updated><id>https://egpbos.nl/blog/tech/2024/01/28/jekyll-minima-v3</id><content type="html" xml:base="https://egpbos.nl/blog/tech/2024/01/28/jekyll-minima-v3.html"><![CDATA[<p>After my <a href="/blog/tech/2024/01/02/jekyll-favicon.html">previous Jekyll favicon hackery</a>, I found out last week there was a better way.</p>

<p>I was actually looking for a nicer theme (didn’t find one), but while doing so I also saw that the theme I’m using currently, Minima, didn’t look the same in the official demo as the one I was using.
It turns out that this theme has been developing quite a lot on GitHub, but all that development has not been released officially (unofficially it’s referred to as v3), so we cannot use it through the regular channel of installing it as a Gem.</p>

<p>Luckily, it seems there is a way around this.
A “remote theme”, activated through the <code class="language-plaintext highlighter-rouge">jekyll-remote-theme</code> plugin (add it to your plugins list in <code class="language-plaintext highlighter-rouge">_config.yml</code>), is the solution.
Instead of specifying the <code class="language-plaintext highlighter-rouge">theme</code> in <code class="language-plaintext highlighter-rouge">_config.yml</code>, I now have a line saying <code class="language-plaintext highlighter-rouge">remote_theme: jekyll/minima</code>.
This may look the same, but apparently now it is using the master branch GitHub version.</p>

<p>This theme has a bunch of extra social link icons in the footer, among which Google Scholar and StackOverflow, very nice.</p>

<p>But, of course, the reason I came here was favicons.
Who the hell needs any of that social stuff.
I just want an awesome favicon and I want it with minimum hassle!
And that’s exactly what I get, because now instead of having to maintain a full <code class="language-plaintext highlighter-rouge">head</code> template, now there is a <code class="language-plaintext highlighter-rouge">custom_head</code> include which is empty and just gets in included in the <code class="language-plaintext highlighter-rouge">head</code> part of the HTML.
Excellent!
I just add a line there to add my favicon to all the pages and there’s no need to keep the rest of the file up to date when the template updates things in the default <code class="language-plaintext highlighter-rouge">head</code> include.</p>

<p>In the meantime, I also added back to the site some final permalinks to GIFs that I served from my previous site for <a href="https://academic.oup.com/mnras/article/488/2/2573/5530784">my 2019 paper on Barcode</a> (I guess GIPHY might have been a good place for those; oh well).
However, it turns out that Minima by default adds links to all “miscellaneous” pages (i.e. everything other than blog posts, I guess) in the header, so all of a sudden I had three weird links with acronyms that nobody understands except those 4 others in the particular scientific niche the paper is about.
Luckily, Minima also has a way to shut itself up: we can add a</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">header_pages</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="s">about.markdown</span>
</code></pre></div></div>
<p>section to <code class="language-plaintext highlighter-rouge">_config.yml</code> to make the list explicit.</p>

<p>I think this concludes my move to Jekyll!
I’ll probably be tweaking things still in the future, but at least all the files I kept after the export are now used somewhere.</p>

<p>Overall, so far, I like the whole Jekyll experience.
Especially writing blogposts in markdown is ideal, although I would like a quick post-generator that autofills dates and title and some other default header stuff, but just copy-pasting the last one works for now.
Publishing changes takes a few minutes, because GitHub Actions needs to regenerate the site on every push.
Let’s hope I never post my private keys in a blogpost by accident, I guess.</p>]]></content><author><name></name></author><category term="blog" /><category term="tech" /><category term="jekyll" /><category term="minima" /><summary type="html"><![CDATA[After my previous Jekyll favicon hackery, I found out last week there was a better way.]]></summary></entry><entry><title type="html">Kapitalisme of liberalisme?</title><link href="https://egpbos.nl/politiek/2024/01/22/kapitalisme-of-liberalisme.html" rel="alternate" type="text/html" title="Kapitalisme of liberalisme?" /><published>2024-01-22T00:00:00+00:00</published><updated>2024-01-22T00:00:00+00:00</updated><id>https://egpbos.nl/politiek/2024/01/22/kapitalisme-of-liberalisme</id><content type="html" xml:base="https://egpbos.nl/politiek/2024/01/22/kapitalisme-of-liberalisme.html"><![CDATA[<p>Sinds ik het <a href="https://www.penguinrandomhouse.com/books/751443/technofeudalism-by-yanis-varoufakis/">boek van Yanis Varoufakis over techno-feodalisme</a> heb gelezen (aanrader!) ben ik anders gaan kijken naar de termen <strong>kapitalisme</strong> en (rechts) <strong>liberalisme</strong>.
Voor mij waren die termen politiek gezien altijd min of meer inwisselbaar: kapitalisten zijn liberalen en liberalen geloven in het kapitalisme.
Maar klopt dit eigenlijk wel?</p>

<p>Varoufakis, bekend als Grieks minister van financiën, destijds lid van de Griekse socialisten, beschrijft zichzelf als een libertarische Marxist…
Daar gingen mij de oren wel even van klapperen.</p>

<p>In het boek legt Varoufakis vervolgens uit hoe kapitalisme kan werken als systeem om de hele samenleving vooruit te helpen. En hoe het niet werkt, of dat zelfs tegenwerkt.</p>

<p>Kapitalisme werkt als je een bakker bent en je je brood sneller of lekkerder kunt bakken door een betere oven. Het werkt ook als je als broodfabriek een efficiëntere productielijn opzet door slimmere organisatie. In beide gevallen maak je eventjes dikke winst door je innovatie. Het vooruitzicht op die beloning motiveerde je om die verbeteringen te maken, om daarin te investeren. Vrij snel zal de concurrentie je weer inhalen en zal je winst weer op normaal niveau komen om je eigen brood op de plank te brengen. Uiteindelijk is iedereen er beter van geworden: meer of beter brood voor hetzelfde (of minder) geld, top!</p>

<p>Kapitalisme werkt echter niet als je Microsoft bent en 95% van alle computers (in de jaren 90 in elk geval) beheerst en daarom koppelverkoop kunt forceren (alternatieven wordt het moeilijk gemaakt). Of als je Amazon bent en alle goederen via jouw platform verkocht worden (zelfde verhaal). Als het “kapitaal” te groot wordt <strong>verdwijnt de concurrentiekracht</strong>. Op dat moment kun je je klanten gaan uitpersen; ze hebben geen alternatief. Dan ben je in feite een middeleeuwse landsheer, geen kapitalist.
Dit geldt niet alleen voor monopolies, maar ook voor economische kartels.</p>

<p>Een overtuigd, ideologisch kapitalist, die gelooft dat het kapitalisme het beste systeem voor de meeste mensen is, die gelooft dat we daarmee uiteindelijk als collectief en als individuën beter uit zijn dan met elk ander systeem, kan dus geen ongelimiteerd economisch liberalisme steunen.
Als je gelooft in kapitalisme, in de kracht van concurrentie en het nastreven van winst door hogere productiviteit, dan moet je absoluut tegen monopolies en kartels zijn.
Daarvan weet je zeker dat de drijvende krachten van het kapitalisme verdwenen zijn.
Daar worden we als samenleving en als individuën dus niet beter van.</p>

<p>Een overtuigd kapitalist zal monopolies en kartels dus willen tegengaan.
Misschien door ze op te knippen.
Misschien door als overheid rechtstreeks met monopolisten te concurreren, schaamteloos gesubsidieerd.
Misschien door een monopolist aan strenge democratische controle en invloed onderhevig te maken, waardoor je effectief zo’n monopolist onderdeel maakt van de samenleving, een volksorgaan.</p>

<p>Kapitalisten kunnen zo bekeken trouwens zelfs onder een socialistisch systeem bestaan.
Zolang er geen 100% winstbelasting of 100% kapitaalbelasting is kun je als individu kapitaal verzamelen.
Ok, dit is waarschijnlijk niet het meest ideale kapitalistische stelsel, maar hun punt is: het kan wel.</p>

<p>Dat laat dus zien dat liberalisme en kapitalisme niet onlosmakelijk verbonden zijn, integendeel.
Ongelimiteerd liberalisme leidt onvermijdelijk tot monopolies en kartels waardoor het kapitalisme niet meer werkt.</p>

<p>Zou dit geen politieke stroming op zichzelf kunnen zijn?
Democratisch kapitalisme?</p>]]></content><author><name></name></author><category term="politiek" /><category term="kapitalisme" /><category term="liberalisme" /><summary type="html"><![CDATA[Sinds ik het boek van Yanis Varoufakis over techno-feodalisme heb gelezen (aanrader!) ben ik anders gaan kijken naar de termen kapitalisme en (rechts) liberalisme. Voor mij waren die termen politiek gezien altijd min of meer inwisselbaar: kapitalisten zijn liberalen en liberalen geloven in het kapitalisme. Maar klopt dit eigenlijk wel?]]></summary></entry><entry><title type="html">Reading PEP 646</title><link href="https://egpbos.nl/tech/2024/01/22/reading-pep-646.html" rel="alternate" type="text/html" title="Reading PEP 646" /><published>2024-01-22T00:00:00+00:00</published><updated>2024-01-22T00:00:00+00:00</updated><id>https://egpbos.nl/tech/2024/01/22/reading-pep-646</id><content type="html" xml:base="https://egpbos.nl/tech/2024/01/22/reading-pep-646.html"><![CDATA[<p>After the <a href="/tech/2024/01/02/python-array-shape-type-hints.html">previous post on Python array shape type hints</a>, I decided to fully read <a href="https://peps.python.org/pep-0646/">PEP 646</a>, which makes this possible.</p>

<p>On January 3rd, I read the specification, which is rather dry stuff. No big surprises here, it just details all the ways in which <code class="language-plaintext highlighter-rouge">TypeVarTuple</code>s can and cannot be used.</p>

<p>On January 8th (yeah, this is dry stuff, I need days to recuperate), I read the Rational and Rejected Ideas. Interesting to note is that some cases are explicitly not supported by this PEP, but are planned for future PEPs. One example is lack of support for</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">repeat_each_element</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">Array</span><span class="p">[</span><span class="n">N</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Array</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">N</span><span class="p">]:</span>
    <span class="p">...</span>
</code></pre></div></div>

<p>which could actually be a big problem for the ML purposes I have in mind, for instance for preprocessing functions.
<a href="https://peps.python.org/pep-0646/#unspecified-type-parameters-tuple-vs-typevartuple">Another problematic omission</a> is that arbitrary length ranks like batch or time are also planned to be supported “explicitly in a future PEP with a syntax such as <code class="language-plaintext highlighter-rouge">Array[Batch, Time, ...]</code>. That’s nice, but doesn’t help right now. Is it crucial? Dunno. Continuing…</p>

<p>The <a href="https://peps.python.org/pep-0646/#alternatives">Alternatives</a> section reiterates perfectly and succinctly the need for a static shape checking mechanism. It’s good to read we aren’t the only ones struggling with this.</p>

<p>It also gives some nice pointers to three existing alternative tools that enable dynamic shape checking. That means you have to run code and wait for it to fail, but at least it should then fail at the front and with helpful error messages. For those of you that cannot wait until all this type hint stuff is working, it may be worth looking into these tools. The three they mention are ShapeGuard, tsanley, and PyContracts. I know neither of them, but I applaud their devs for their noble work.</p>

<p>I wonder, by the way, whether in the meantime (i.e. since PEP 646 was published) these projects have included anything from this PEP… A quick GitHub search on their repos doesn’t reveal any hits on keywords PEP and 646, and also the README examples don’t seem to include any 646-like syntax… except <a href="https://github.com/AndreaCensi/contracts">PyContracts</a>! It offers three alternative syntaxes, but number two looks a lot like that suggested in PEP 646, except in strings instead of just in plain Python. Given the example, this makes sense, because it goes beyond what 646 intends; PyContracts can also encode numerical lower limits, it seems.</p>

<p>Ok, back to PEP 646.</p>

<p>The next section, Grammar Changes, holds some fun <a href="https://peps.python.org/pep-0646/#implications">implications</a> as well. Due to the grammar change introduced in this PEP, star-unpacking of iterables can now also be used within brackets. This means we can now also index arrays using star-unpacking, something that wasn’t possible before and that can sometimes lead to very nice shorthand notation. Consider for instance the pre-646, slightly over-dramatic example</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">index</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">some_big_array</span><span class="p">[</span><span class="n">index</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">index</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">index</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">index</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">index</span><span class="p">[</span><span class="mi">4</span><span class="p">]]</span>
</code></pre></div></div>

<p>This can now be written</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">index</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">some_big_array</span><span class="p">[</span><span class="o">*</span><span class="n">index</span><span class="p">]</span>
</code></pre></div></div>

<p>Noice.</p>

<p>After some uneventful postambles (is that a word?), the first appendix brings some slightly bad news. Yes, we can annotate array shapes, i.e. the numerical sizes of ranks within the shape. This is good. However, we cannot at the same time annotate rank <em>semantics</em> consistently across multiple functions. Unpacking that sentence: when we have two functions annotated as</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">f1</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">Array</span><span class="p">[</span><span class="n">Batch</span><span class="p">,</span> <span class="n">Time</span><span class="p">,</span> <span class="n">Stuff</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Array</span><span class="p">[</span><span class="n">Batch</span><span class="p">,</span> <span class="n">Time</span><span class="p">],</span> <span class="n">Array</span><span class="p">[</span><span class="n">Stuff</span><span class="p">]:</span> <span class="p">...</span>
<span class="k">def</span> <span class="nf">f2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">Array</span><span class="p">[</span><span class="n">Time</span><span class="p">,</span> <span class="n">Batch</span><span class="p">,</span> <span class="n">Stuff</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Array</span><span class="p">[</span><span class="n">Stuff</span><span class="p">],</span> <span class="n">Array</span><span class="p">[</span><span class="n">Batch</span><span class="p">,</span> <span class="n">Time</span><span class="p">]:</span> <span class="p">...</span>
</code></pre></div></div>

<p>the <code class="language-plaintext highlighter-rouge">Batch</code> in <code class="language-plaintext highlighter-rouge">f1</code> has no relation to the <code class="language-plaintext highlighter-rouge">Batch</code> in <code class="language-plaintext highlighter-rouge">f2</code> and similarly for <code class="language-plaintext highlighter-rouge">Time</code> and <code class="language-plaintext highlighter-rouge">Stuff</code>. The scope of these names is purely within the function definitions and has no meaning outside of the scope; the names are used to describe relations between input and output types. In this case, you can pass <code class="language-plaintext highlighter-rouge">Literal[64]</code> as one of the rank names to indicate that the array must have a size of <code class="language-plaintext highlighter-rouge">64</code>. Then you also know that one of the output shapes will be <code class="language-plaintext highlighter-rouge">64</code>. Quite useful, but you do lose semantics. If we pass the same array to these two functions, it will be wrong at least one of the times, semantically.</p>

<p>The appendix mentions another usecase where semantics are preserved, for instance by declaring the rank names in the global scope:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Batch</span><span class="p">:</span> <span class="p">...</span>
<span class="k">class</span> <span class="nc">Time</span><span class="p">:</span> <span class="p">...</span>
<span class="k">class</span> <span class="nc">Stuff</span><span class="p">:</span> <span class="p">...</span>
</code></pre></div></div>

<p>Now, the names in <code class="language-plaintext highlighter-rouge">f1</code> and <code class="language-plaintext highlighter-rouge">f2</code> are no longer just names within the functions definitions’ scopes.
Arrays must now have these actual classes in their type hints to be allowed to pass them to the functions.
However, there is now no way to specify explicit axis sizes.</p>

<p>… although, perhaps it is possible? In the <a href="https://peps.python.org/pep-0646/#why-not-both">‘Why not both?’</a> section, “exploration of this approach” is left “to the future”.
One option that the current syntax should allow is to have types with yet another bracketed sub-property that could be used to indicate size, e.g. something like <code class="language-plaintext highlighter-rouge">Array[Batch[BatchSize]]</code> where <code class="language-plaintext highlighter-rouge">class Batch: ...</code> somehow takes the size in.
Who is brave enough to explore this option?
Will this work at all in mypy or other checkers?
One cannot assume that this syntax will only be used for this, so it will probably require a lot of work to make this work without some additional explicit language support (i.e. moar fancy new syntax).</p>

<p>Finally, on January 22nd, I read the last part of the PEP: appendix B.
This discusses why “named tensors” don’t suffice.
<a href="https://docs.xarray.dev/en/stable/">Xarray</a> and other libraries take this approach of labeling axes with strings.
However, you can’t check labels statically, they are dynamic by nature, so they cannot solve the same problems that type annotations do.
While labels can certainly be an improvement over plain old meaningless numerical indices, in practice it turns out their usefulness is limited.
In <a href="https://github.com/dianna-ai/dianna">DIANNA</a>, we also internally use Xarray and named axes as a first stab at this problem.
It solves some problems for now, but also introduces new ones, for instance because there is no support for this approach in other libraries, making it is still quite a hassle to work with.</p>

<p>Conclusion: this is promising stuff.
I would love to spend a week trying to get something based on this working…</p>]]></content><author><name></name></author><category term="tech" /><category term="python" /><category term="type hints" /><summary type="html"><![CDATA[After the previous post on Python array shape type hints, I decided to fully read PEP 646, which makes this possible.]]></summary></entry><entry><title type="html">Moving to Jekyll part 3: favicons? And some local hiccups</title><link href="https://egpbos.nl/blog/tech/2024/01/02/jekyll-favicon.html" rel="alternate" type="text/html" title="Moving to Jekyll part 3: favicons? And some local hiccups" /><published>2024-01-02T21:30:00+00:00</published><updated>2024-01-02T21:30:00+00:00</updated><id>https://egpbos.nl/blog/tech/2024/01/02/jekyll-favicon</id><content type="html" xml:base="https://egpbos.nl/blog/tech/2024/01/02/jekyll-favicon.html"><![CDATA[<p>My Jekyll site is online, as you, my dear reader, can see. The publishing process has been quite flawless and smooth, very nice.</p>

<p>There were some slight hiccups in between the <a href="/blog/tech/2023/12/31/importing_wordpress.html">previous Jekyll post</a> and this one.
For some reason (I don’t think I did anything stupid… perhaps it was due to switching out the Jekyll Gem dependency in the Gemfile with the GitHub Pages Gem, as instructed by GitHub… not sure), things broke a bit, and <code class="language-plaintext highlighter-rouge">jekyll serve</code> wouldn’t run anymore.
I found out that there is a <code class="language-plaintext highlighter-rouge">jekyll doctor</code> command that’s supposed to help out when things break, but apparently this was not such a case, because the good doctor sent me home with some aspirine and told me to come back in three months if my head still ached.
I also did do a stupid thing btw, which was to try fixing things in a terminal that still had Ruby 3.3 loaded from before I downgraded to 3.2 (see <a href="/blog/tech/2023/12/27/bootstrap.html">previous post</a>, so the error messages were allround confusing.</p>

<p>In the end (in a fresh, proper terminal), an apt error message told me that <code class="language-plaintext highlighter-rouge">&lt;internal:/Users/patrick/.rubies/ruby-3.2.2/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb&gt;:37:in </code><code class="language-plaintext highlighter-rouge">require': cannot load such file -- webrick (LoadError)</code>.
The fix, then, was to explicitly add webrick using <code class="language-plaintext highlighter-rouge">bundle add webrick</code>. Done! My <code class="language-plaintext highlighter-rouge">jekyll serve</code>ing needs could again be fulfilled.</p>

<p>From whence did such needs stem? Foresooth, from getting me a fancy favicon! The default one is unacceptable to a man of my fine tastes, and I’m sure to yours as well, dearest scholar of my humble works.</p>

<p>Unfortunately, I cannot seem to get it in by simply overriding the <code class="language-plaintext highlighter-rouge">head</code> include with a appropriate <code class="language-plaintext highlighter-rouge">link</code> tag, as <a href="https://medium.com/@xiang_zhou/how-to-add-a-favicon-to-your-jekyll-site-2ac2179cc2ed">suggested here</a> and suggested by common sense as well. Perhaps, though, the issue is simply with <code class="language-plaintext highlighter-rouge">jekyll serve</code> and putting it on GitHub will fix things through the use of a proper HTTP server? Let’s try it out, together with this post…</p>

<p><em>Edit 5 minutes later:</em> nope, something else must be wrong, because as you can see, the favicon is still not being picked up… at least on the home page… But wait! It is in fact there on this very post! Did I add it to the wrong include? Is <code class="language-plaintext highlighter-rouge">head</code> not included in all pages? Nope, it does seem to be everywhere… Then what? The other older posts also don’t have it, only this favicon page…</p>

<p>Ok, well, at least something is working. Just gotta find the gremlins later.</p>

<p><em>Edit another 5 minutes later:</em> ah, it just seems to be a browser cache issue. Favicon up and running!</p>]]></content><author><name></name></author><category term="blog" /><category term="tech" /><category term="jekyll" /><summary type="html"><![CDATA[My Jekyll site is online, as you, my dear reader, can see. The publishing process has been quite flawless and smooth, very nice.]]></summary></entry><entry><title type="html">Fixing machine learning in Python: type hints for array shapes</title><link href="https://egpbos.nl/tech/2024/01/02/python-array-shape-type-hints.html" rel="alternate" type="text/html" title="Fixing machine learning in Python: type hints for array shapes" /><published>2024-01-02T21:09:00+00:00</published><updated>2024-01-02T21:09:00+00:00</updated><id>https://egpbos.nl/tech/2024/01/02/python-array-shape-type-hints</id><content type="html" xml:base="https://egpbos.nl/tech/2024/01/02/python-array-shape-type-hints.html"><![CDATA[<p>While working on machine learning projects (right now I’m working with <a href="https://github.com/cwmeijer">Chris</a> on <a href="https://research-software-directory.org/software/explainable-embeddings">explainable embeddings</a>, before I worked on <a href="https://research-software-directory.org/projects/understanding-visually-grounded-spoken-language-via-multi-tasking">“Spoken Language”</a> and <a href="https://research-software-directory.org/projects/dianna">DIANNA</a>), there is one major pain in the ass that I’m quite sure costs millions of hours of debugging time daily worldwide: <em>array shapes</em>.</p>

<p>It makes sense, because people try to build software generically. Nobody wants an image recognition tool that only works on images of 224 by 224 pixels. But, GODDAMNIT, if you do build a tool like that, I want it to fail IMMEDIATELY when I shove my mongrel of an array into its input face. <em>Please, for the love of all that is holy</em>, fail early, so that I know that I am an idiot, do not let me dive into your tool’s (and, usually, your dependencies’) code to figure this out all on my own over a full hour or two. It should be banned under some kind of international convention.</p>

<p>Now, of course, if only things were so simple. Usually, tools don’t hardcode shapes. What could happen instead, for instance, is that generic tools (without fixed shape constraints) basically get configured by one piece of input (the first, a reference item, whatever) and then that determines the kind of input you can feed the code from then on. To get type checking to work on such a code, you would probably have to use some kind of functional programming language or framework. The usual suspects in Python ML world are not that. They do their magic inside their bowels, as befits proper object oriented code. Worry not about my bowel-work, mortal, it doth not concern thine puny brains.</p>

<p>Nevertheless, after having sketched the urgency of the matter (at least to my puny brain), let’s say there are cases where it is possible to specify at the interface side of some function the desired shape. There are then several ways to do so:</p>

<ol>
  <li>One could write it in a docstring, but this can become quite tedious when another function in turn needs to copy this information in their docstring and so on. Someone at some point will neglect to include it and gone is your info.</li>
  <li>One could simply check the input data’s shape dynamically inside the function. In performance critical applications, this is definitely out of the question; a check at every call would be too costly if the call is done a million times in a row. Also, an explicit check in code is kinda ugly and detracts from the actual business code.</li>
  <li>One could use a language that does have built-in static type checks, hahaha no just kidding.</li>
  <li>One could try to use type hints…</li>
</ol>

<p>But do type hints allow for shape definition?</p>

<p>This is the question we asked ourselves in our final project session of the year. Since I’m now on holiday, and apparently I’m a workaholic, I went ahead and started looking into whether there’s already something out there on this front.</p>

<p>Of course, the first go-to stop is to check out <a href="https://numpy.org/devdocs/reference/typing.html">what Numpy, the grandparent (a fit kind of grandparent, the kind that just keeps on living actively into their 90s, blatantly defying the laws of aging that ravage normal people, possibly some kind of alien?) of Python arrays, has to offer</a>.
Unfortunately, that turns out to be too little for shape typing purposes. Numpy can only say “this is an array of type <code class="language-plaintext highlighter-rouge">x</code>”, but nothing about shape or even number of dimensions. (It also has an <code class="language-plaintext highlighter-rouge">ArrayLike</code> type, which is nice, but totally irrelevant here.)</p>

<p>Despite this first slight but not unexpected disappointment, the Numpy page did offer one useful hint: they are waiting for everyone to have moved to Python 3.11 (I guess?), because that contains <a href="https://peps.python.org/pep-0646/">PEP 646: Variadic Generics</a>.</p>

<p>This PEP is literally made for the exact usecase we’re talking about here!</p>

<p>However, it only provides the <strong>very</strong> basic constructs necessary for making this dream a reality. With this, someone could define a type of array with explicitly named dimensions and even with explicitly sized dimensions, i.e. a fully specified shape. But did someone do this already? And if not, what would it take? Probably defining the type alone is not enough for <code class="language-plaintext highlighter-rouge">mypy</code> to be able to check for its usage? For editors to parse it and provide useful hints while editing? Or is it? This is new territory for me.</p>

<p>I’ll be looking into this some more, because it’s sure as hell promising! The pain that a type like this could prevent… Autocompletion and helpful hints inside my editor powered by this, oh man, I can’t wait.</p>]]></content><author><name></name></author><category term="tech" /><category term="machine learning" /><category term="python" /><summary type="html"><![CDATA[While working on machine learning projects (right now I’m working with Chris on explainable embeddings, before I worked on “Spoken Language” and DIANNA), there is one major pain in the ass that I’m quite sure costs millions of hours of debugging time daily worldwide: array shapes.]]></summary></entry><entry><title type="html">Moving to Jekyll part 2: importing Wordpress content and going live</title><link href="https://egpbos.nl/blog/tech/2023/12/31/importing_wordpress.html" rel="alternate" type="text/html" title="Moving to Jekyll part 2: importing Wordpress content and going live" /><published>2023-12-31T00:00:00+00:00</published><updated>2023-12-31T00:00:00+00:00</updated><id>https://egpbos.nl/blog/tech/2023/12/31/importing_wordpress</id><content type="html" xml:base="https://egpbos.nl/blog/tech/2023/12/31/importing_wordpress.html"><![CDATA[<p>After getting Jekyll going (see <a href="/blog/tech/2023/12/27/bootstrap.html">previous post</a>, next step is getting everything out of my previous website in here. That was a Wordpress site with some static pages and a couple of blog posts.</p>

<p>First question is of course whether we can automate this… The amount of content is so low that SURELY this will not pay off. Such is programmer life.</p>

<p>One annoying part of this is that my previous site was bilingual: it had both Dutch and English version pages. I’d still like that, but I think it’s also causing me to write less often than I’d like, so perhaps I should not make this a top priority for now.</p>

<p>A quick Google shows that indeed there’s a convenient <a href="https://wordpress.org/plugins/jekyll-exporter/">Jekyll exporter</a> plugin. Let’s go!</p>

<p>Logging in to my Wordpress admin page, showing me that again there’s a Wordpress update, I’m again strengthened in my resolve for this move. Why complicate a simple website with junk like a database and regular security updates? Who needs security anyway?! I just want to put a few simple pages online… Static files ftw!</p>

<p>Anyway, back to the exporter. It works as advertised (at least on my poorly maintained Wordpress v6.1.1 site) and outputs everything: both Dutch and English page variants, but also some uploaded files and figures I put on the site over the years. Blog posts are already put in a <code class="language-plaintext highlighter-rouge">_posts</code> folder and have the proper internal structure for Jekyll to immediately use it in my site’s <code class="language-plaintext highlighter-rouge">_posts</code> folder. Neat!</p>

<p>Since I only had a few posts and pages, I manually checked all the files to make sure there’s no nasty stuff in there, and it all seems pretty straightforward. Nice feature: permalinks from the previous website are also kept; they are put into the markdown header. That’s really excellent.</p>

<p>Trying to then step by step adding in the files, starting with</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> ~/Downloads/jekyll-export/_posts/2012-08-28-hoe-wordt-de-rente-op-studieschuld-bepaald.md egpbos.nl/_posts
</code></pre></div></div>

<p>The link Jekyll generates indeed is domain + permalink, very nice! The image I had in this post is still missing. We get that back in using</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> <span class="nt">-r</span> ~/Downloads/jekyll-export/wp-content egpbos.nl/
</code></pre></div></div>

<p>Unfortunately, this doesn’t fix everything completely. The URL to the image itself is not converted correctly, even though link URLs are. Fixing those manually (just <code class="language-plaintext highlighter-rouge">grep -r '!\['</code> to find all images in the Jekyll export directory) involves just taking off the hardcoded domain names.</p>

<p>Also, since I am a dinosaur, my blogposts used <code class="language-plaintext highlighter-rouge">&lt;tt&gt;</code> occasionally instead of backticks, so replaced those here and there.</p>

<p>To keep things clean, you might want to remove empty directories, which the <code class="language-plaintext highlighter-rouge">wp-content</code> directory contains a lot of: <code class="language-plaintext highlighter-rouge">find wp-content -type d -empty -delete</code>. Also the weird <code class="language-plaintext highlighter-rouge">wp-content/uploads/wpcode</code> directory can be removed. And Wordpress generated a lot of thumbnail versions of images that I won’t be needing anymore either: <code class="language-plaintext highlighter-rouge">find wp-content -type f -name '*x*' -delete</code>.</p>

<p>The default Jekyll site only gives you a blog frontpage that shows a list of posts. I want to add some content as well, as I had on my previous website. This is as easy as adding content to <code class="language-plaintext highlighter-rouge">index.markdown</code>. For now, I’m just dumping both my English and Dutch texts and my portrait there. Can always polish later.</p>

<p>The last remaining pieces of content from my previous website are my CV and publications pages; sort of my portfolio. I’m just going to dump all that stuff in the about page that also conveniently was added in the default Jekyll site. I can’t seem to get the thumbnail image widths adjusted, so it’ll be messy.</p>

<hr />

<p>Having imported everything, the final steps to get the site online are described well in the <a href="https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/creating-a-github-pages-site-with-jekyll">GitHub documentation</a>. Done, here we are!</p>]]></content><author><name></name></author><category term="blog" /><category term="tech" /><summary type="html"><![CDATA[After getting Jekyll going (see previous post, next step is getting everything out of my previous website in here. That was a Wordpress site with some static pages and a couple of blog posts.]]></summary></entry><entry><title type="html">Moving to Jekyll part 1: Getting to know Jekyll</title><link href="https://egpbos.nl/blog/tech/2023/12/27/bootstrap.html" rel="alternate" type="text/html" title="Moving to Jekyll part 1: Getting to know Jekyll" /><published>2023-12-27T12:45:25+00:00</published><updated>2023-12-27T12:45:25+00:00</updated><id>https://egpbos.nl/blog/tech/2023/12/27/bootstrap</id><content type="html" xml:base="https://egpbos.nl/blog/tech/2023/12/27/bootstrap.html"><![CDATA[<p>Using Jekyll for this website was a chore. At least, installing it was. At least, installing Ruby was. Python package management haters: eat your heart out.</p>

<p>In all honesty, perhaps it was my own fault? Not really sure…</p>

<p>In the end, what fixed my issues (thanks to a hint here: https://www.moncefbelyamani.com/the-definitive-guide-to-installing-ruby-gems-on-a-mac/#keep-using-the-system-ruby-by-changing-the-installation-path-not-recommended) was to remove the .gemrc file that contained –user-install as a default option. This broke my stuff subtly, because it doesn’t play nice with ruby-install? Or at least not the way https://jekyllrb.com/docs/installation/macos/ suggests you use it? I think the point is that –user-install tries to install to .gem, but actually ruby-install expects things under .rubies/[your ruby version]/gems or something like that, so that doth not jive.</p>

<p>No matter how I try, installing Jekyll that way using gem doesn’t give me a runnable executable. If I follow the instructions blindly, I simply get a command not found. If I pay a bit more attention to the warning the gem installation process gives me (“WARNING:  You don’t have /Users/patrick/.gem/ruby/3.2.0/bin in your PATH,
	  gem executables will not run.”) and add that to my PATH (even though I’m actually using Ruby 3.2.2… suspicious) then I get an even more obscure error:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/Users/patrick/.rubies/ruby-3.2.2/lib/ruby/site_ruby/3.2.0/rubygems.rb:259:in `find_spec_for_exe': can't find gem jekyll (&gt;= 0.a) with executable jekyll (Gem::GemNotFoundException)
	from /Users/patrick/.rubies/ruby-3.2.2/lib/ruby/site_ruby/3.2.0/rubygems.rb:278:in `activate_bin_path'
	from /Users/patrick/.gem/ruby/3.2.0/bin/jekyll:25:in `&lt;main&gt;'
</code></pre></div></div>

<p>Bizarre. Of course, the mismatch there in versions is a big red flag, but what is a complete Ruby noob to do?</p>

<p>After finding the aforementioned link, I ended up deleting .gemrc, the entire .gem and .rubies folders (.rubies is where ruby-install installs ruby (btw, why the hell does it have to completely compile the things?! conda ftw)). Then reinstalled ruby with ruby-install… update the chruby command in .zshrc (because the version changed from the previous time), and then redo the jekyll install.</p>

<p>There’s no need for “user-install” this way, because ruby-install is already in your home dir, so a “system-install” is also a user install.</p>

<p>Now stuff worked, finally!</p>

<p>… that is, I could run Jekyll to create a, but serving the site didn’t. Neither the command Jekyll itself suggests (<code class="language-plaintext highlighter-rouge">bundle exec jekyll serve</code>) nor the command suggested <a href="https://github.com/jekyll/jekyll/issues/9451">here</a> (<code class="language-plaintext highlighter-rouge">jekyll serve -l</code>, also without <code class="language-plaintext highlighter-rouge">-l</code>) worked.</p>

<p>Let’s try <code class="language-plaintext highlighter-rouge">ruby-install 3.2</code> then? 3.3 was only 2 days old at this point, a day after Christmas, so perhaps some bugs still had to be ironed out.</p>

<p>Another day later due to lack of patience to wait for the compilation to finish…</p>

<p>… it works! Had to regenerate the site with <code class="language-plaintext highlighter-rouge">jekyll new egpbos.nl</code>, because it complained about missing dependencies when I wouldn’t, but then it all works and <code class="language-plaintext highlighter-rouge">jekyll serve -l</code> serves the fresh site on localhost:4000.</p>]]></content><author><name></name></author><category term="blog" /><category term="tech" /><summary type="html"><![CDATA[Using Jekyll for this website was a chore. At least, installing it was. At least, installing Ruby was. Python package management haters: eat your heart out.]]></summary></entry><entry><title type="html">Plannen vermogensbelasting 2015: wie betaalt meer, wie betaalt minder?</title><link href="https://egpbos.nl/nl/financieel/plannen-vermogensbelasting-2015/" rel="alternate" type="text/html" title="Plannen vermogensbelasting 2015: wie betaalt meer, wie betaalt minder?" /><published>2015-08-31T06:39:46+00:00</published><updated>2015-08-31T06:39:46+00:00</updated><id>https://egpbos.nl/nl/financieel/plannen-vermogensbelasting-2015</id><content type="html" xml:base="https://egpbos.nl/nl/financieel/plannen-vermogensbelasting-2015/"><![CDATA[<p><em>Update September 2016: grafiek voor 2017 toegevoegd waarin de plannen (in gewijzigde vorm) daadwerkelijk in werking zullen treden.</em></p>

<p>Nieuwe plannen voor de vermogensbelasting:</p>

<ul>
  <li>Nog steeds 30% belasting over een fictief rendement</li>
  <li>Het fictieve rendement wordt nu bepaald aan de hand van rentes van de afgelopen 5 jaar (vergelijkbaar met de berekening van de studieschuldrente)</li>
  <li>Het fictieve rendement wordt progressief, wat in veel gevallen realistischer zal zijn (hoe meer vermogen, hoe meer risico je je kunt permitteren en dus hoe meer rendement over de lange termijn):
    <ul>
      <li>Schijf 0: t/m € 25k belastingvrij (is nu voor 2015 € 21.330)</li>
      <li>Schijf 1: € 25k t/m €125k 2,7%</li>
      <li>Schijf 2: € 125k t/m €1M 4,7%</li>
      <li>Schijf 3: vanaf € 1M 5,5%</li>
    </ul>
  </li>
</ul>

<p>Dit kunnen we vergelijken met de huidige vlaktaks van 30% op 4% fictief rendement. Bij welke vermogens betaal je minder en bij welke betaal je meer in dit nieuwe tarievenschema?</p>

<p><img src="/wp-content/uploads/2015/08/vermogensbelasting2015.png" alt="vermogensbelasting2015" /></p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
</span><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="nn">scipy.optimize</span> <span class="k">as</span> <span class="n">opt</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="n">plt</span><span class="p">.</span><span class="n">style</span><span class="p">.</span><span class="n">use</span><span class="p">(</span><span class="s">'ggplot'</span><span class="p">)</span>

<span class="n">b_nieuw</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="mf">0.3</span> <span class="o">*</span> <span class="p">(</span> <span class="p">(</span><span class="mf">0.027</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">v</span><span class="o">-</span><span class="mi">25000</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">100000</span><span class="p">))</span> <span class="o">+</span> <span class="p">(</span><span class="mf">0.047</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">v</span><span class="o">-</span><span class="mi">125000</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">875000</span><span class="p">))</span> <span class="o">+</span> <span class="p">(</span><span class="mf">0.055</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nb">max</span><span class="p">((</span><span class="n">v</span><span class="o">-</span><span class="mf">1e6</span><span class="p">,</span> <span class="n">np</span><span class="p">.</span><span class="n">zeros_like</span><span class="p">(</span><span class="n">v</span><span class="p">)),</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">))</span> <span class="p">)</span>
<span class="n">b0</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="mf">0.3</span><span class="o">*</span><span class="p">(</span><span class="mf">0.04</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nb">max</span><span class="p">((</span><span class="n">np</span><span class="p">.</span><span class="n">zeros_like</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="p">(</span> <span class="n">v</span> <span class="o">-</span> <span class="mi">21330</span> <span class="p">)),</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">2e6</span><span class="p">,</span> <span class="mi">100000</span><span class="p">)</span>

<span class="n">d_b</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="n">np</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">b0</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">-</span> <span class="n">b_nieuw</span><span class="p">(</span><span class="n">v</span><span class="p">))</span>

<span class="n">break_even</span> <span class="o">=</span> <span class="n">opt</span><span class="p">.</span><span class="n">fmin</span><span class="p">(</span><span class="n">d_b</span><span class="p">,</span> <span class="mi">200000</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>

<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">b0</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">label</span><span class="o">=</span><span class="s">'oud'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">b_nieuw</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">label</span><span class="o">=</span><span class="s">'nieuw'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">xlim</span><span class="p">(</span><span class="mi">10000</span><span class="p">,</span> <span class="mf">2e6</span><span class="p">)</span>

<span class="n">ylim</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">ylim</span><span class="p">()</span>
<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">((</span><span class="n">break_even</span><span class="p">,)</span><span class="o">*</span><span class="mi">2</span><span class="p">,</span> <span class="p">(</span><span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)),</span> <span class="s">'k--'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">((</span><span class="n">plt</span><span class="p">.</span><span class="n">xlim</span><span class="p">()[</span><span class="mi">0</span><span class="p">],</span> <span class="n">break_even</span><span class="p">),</span> <span class="p">(</span><span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">),</span> <span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)),</span> <span class="s">'k--'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">title</span><span class="p">((</span><span class="s">'Break even punt: {0:.2f} euro ({1:.2f} euro belasting)'</span>
           <span class="p">).</span><span class="nb">format</span><span class="p">(</span><span class="n">break_even</span><span class="p">,</span> <span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)))</span>

<span class="n">plt</span><span class="p">.</span><span class="n">grid</span><span class="p">(</span><span class="n">b</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">which</span><span class="o">=</span><span class="s">'both'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s">'best'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p>Het effectieve percentage belasting dat je over je totale bedrag betaalt ziet er als volgt uit:</p>

<p><img src="/wp-content/uploads/2015/08/vermogensbelasting2015_rente.png" alt="vermogensbelasting2015_rente" /></p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># effectieve rente
</span><span class="n">effectief_0</span> <span class="o">=</span> <span class="n">b0</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">/</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">100</span>
<span class="n">effectief_nieuw</span> <span class="o">=</span> <span class="n">b_nieuw</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">/</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">100</span>

<span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">()</span>

<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">effectief_0</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'oud'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">effectief_nieuw</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'nieuw'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">xlim</span><span class="p">(</span><span class="mi">10000</span><span class="p">,</span> <span class="mf">2e6</span><span class="p">)</span>

<span class="n">ylim</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">ylim</span><span class="p">()</span>
<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">((</span><span class="n">break_even</span><span class="p">,)</span><span class="o">*</span><span class="mi">2</span><span class="p">,</span> <span class="p">(</span><span class="n">ylim</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)</span> <span class="o">/</span> <span class="n">break_even</span> <span class="o">*</span> <span class="mi">100</span><span class="p">),</span> <span class="s">'k--'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">semilogx</span><span class="p">((</span><span class="n">plt</span><span class="p">.</span><span class="n">xlim</span><span class="p">()[</span><span class="mi">0</span><span class="p">],</span> <span class="n">break_even</span><span class="p">),</span> <span class="p">(</span><span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)</span> <span class="o">/</span> <span class="n">break_even</span> <span class="o">*</span> <span class="mi">100</span><span class="p">,</span> <span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)</span> <span class="o">/</span> <span class="n">break_even</span> <span class="o">*</span> <span class="mi">100</span><span class="p">),</span> <span class="s">'k--'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">title</span><span class="p">((</span><span class="s">'Break even punt: {0:.2f} euro ({1:.2f} procent effectieve belasting)'</span>
           <span class="p">).</span><span class="nb">format</span><span class="p">(</span><span class="n">break_even</span><span class="p">,</span> <span class="n">b0</span><span class="p">(</span><span class="n">break_even</span><span class="p">)</span> <span class="o">/</span> <span class="n">break_even</span> <span class="o">*</span> <span class="mi">100</span><span class="p">))</span>

<span class="n">plt</span><span class="p">.</span><span class="n">grid</span><span class="p">(</span><span class="n">b</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">which</span><span class="o">=</span><span class="s">'both'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s">'best'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><em>Update september 2016:</em></p>

<p><a href="http://www.belastingdienst.nl/wps/wcm/connect/bldcontentnl/belastingdienst/prive/vermogen_en_aanmerkelijk_belang/vermogen/belasting_betalen_over_uw_vermogen/grondslag_sparen_en_beleggen/berekenen_belasting_over_uw_inkomsten_uit_vermogen_vanaf_2017">De plannen gaan in enigszins gewijzigde vorm in 2017 in werking</a>. Voor mensen met een flink vermogen zijn de aanpassingen nog iets minder gunstig dan de oorspronkelijke plannen; zie de figuur hieronder.</p>

<p><img src="/wp-content/uploads/2015/08/vermogensbelasting2017_rente.png" alt="vermogensbelasting2017_rente" /></p>

<p>Hiervoor kun je in het bovenste stukje Python <code class="language-plaintext highlighter-rouge">b_nieuw</code> vervangen met de volgende regels.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># versie 2017:
</span><span class="n">perc1</span> <span class="o">=</span> <span class="mf">0.0163</span>
<span class="n">perc2</span> <span class="o">=</span> <span class="mf">0.055</span>
<span class="n">tarief1</span> <span class="o">=</span> <span class="mf">0.67</span> <span class="o">*</span> <span class="n">perc1</span> <span class="o">+</span> <span class="mf">0.33</span> <span class="o">*</span> <span class="n">perc2</span>
<span class="n">tarief2</span> <span class="o">=</span> <span class="mf">0.21</span> <span class="o">*</span> <span class="n">perc1</span> <span class="o">+</span> <span class="mf">0.79</span> <span class="o">*</span> <span class="n">perc2</span>
<span class="n">tarief3</span> <span class="o">=</span> <span class="n">perc2</span>
<span class="n">b_nieuw</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">v</span><span class="p">:</span> <span class="mf">0.3</span> <span class="o">*</span> <span class="p">((</span><span class="n">tarief1</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">v</span> <span class="o">-</span> <span class="mi">25000</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">75000</span><span class="p">))</span> <span class="o">+</span>
<span class="err">                          </span> <span class="p">(</span><span class="n">tarief2</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">v</span> <span class="o">-</span> <span class="mi">100000</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">900000</span><span class="p">))</span> <span class="o">+</span>
<span class="err">                          </span> <span class="p">(</span><span class="n">tarief3</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nb">max</span><span class="p">((</span><span class="n">v</span> <span class="o">-</span> <span class="mf">1e6</span><span class="p">,</span> <span class="n">np</span><span class="p">.</span><span class="n">zeros_like</span><span class="p">(</span><span class="n">v</span><span class="p">)),</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)))</span>
</code></pre></div></div>]]></content><author><name>Patrick</name></author><category term="Financieel" /><category term="Politiek" /><category term="Rekenen" /><category term="belasting" /><category term="numpy" /><category term="scipy.optimize" /><summary type="html"><![CDATA[Update September 2016: grafiek voor 2017 toegevoegd waarin de plannen (in gewijzigde vorm) daadwerkelijk in werking zullen treden.]]></summary></entry><entry><title type="html">Dropbox syncing between OS X and Linux</title><link href="https://egpbos.nl/computing/dropbox-syncing-between-os-x-and-linux/" rel="alternate" type="text/html" title="Dropbox syncing between OS X and Linux" /><published>2014-11-07T15:06:47+00:00</published><updated>2014-11-07T15:06:47+00:00</updated><id>https://egpbos.nl/computing/dropbox-syncing-between-os-x-and-linux</id><content type="html" xml:base="https://egpbos.nl/computing/dropbox-syncing-between-os-x-and-linux/"><![CDATA[<p>Troubles arise when dealing with this situation. Too often now, at some point I noticed that a file had gone missing on my Linux system. In blind panic I would check my Mac and find that luckily the file was safely where I left it. Also, the file would appear just fine on the Dropbox website. What’s up?</p>

<p>In my case, this seems to be caused by not having extended attributes support on my Linux system. In general, this could be caused by either simply not having enabled it at mount time (there’s a flag for that) or by using NFS which does not support them at all. In my case, it was both and since I’m not root I can’t change either.</p>

<p>If, like me, you’re stuck with such a system and still want to use Dropbox to synchronize from your OS X (which at any moment could strike upon your files with some metadata voodoo) you will need to manually tear out the metadata. The following steps will remedy your syncing issues, at the cost of losing OS X’s precious metadata. Use your Terminal to give the commands (where <code class="language-plaintext highlighter-rouge">file</code> is Schrödinger’s file in question):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;pre class="brush: plain; light: true; title: ; notranslate" title=""&gt;
mv file file_tmp
xattr -c file_tmp
mv file_tmp file
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">xattr -c</code> command removes all extended attributes. The moving might seem useless at first. However, without it, you might find (like I did) that the file still doesn’t sync, despite it having no more metadata. Even when you edit the file itself (e.g. if it’s a text file, add some text) Dropbox doesn’t sync the file to Linux anymore. Perhaps once a file’s “tainted”, Dropbox flags it as forever unusable for unsuitable file systems.</p>

<p>In any case, a little moving around makes Dropbox forget all about it’s past transgressions and starts syncing it just fine again. That is, until OS X does its black magic again and you can start all over. Perhaps scripting the above would be a good idea, but we leave that as an exercise to the reader.</p>]]></content><author><name>Patrick</name></author><category term="Computing" /><category term="Dropbox" /><category term="extended attributes" /><category term="linux" /><category term="OS X" /><summary type="html"><![CDATA[Troubles arise when dealing with this situation. Too often now, at some point I noticed that a file had gone missing on my Linux system. In blind panic I would check my Mac and find that luckily the file was safely where I left it. Also, the file would appear just fine on the Dropbox website. What’s up?]]></summary></entry><entry><title type="html">Condor job with ncurses: add terminal variable</title><link href="https://egpbos.nl/computing/condor-job-with-ncurses-add-terminal-variable/" rel="alternate" type="text/html" title="Condor job with ncurses: add terminal variable" /><published>2014-11-07T09:35:17+00:00</published><updated>2014-11-07T09:35:17+00:00</updated><id>https://egpbos.nl/computing/condor-job-with-ncurses-add-terminal-variable</id><content type="html" xml:base="https://egpbos.nl/computing/condor-job-with-ncurses-add-terminal-variable/"><![CDATA[<p>Running a Condor (7.5.5) job for my c++ program which makes use of the ncurses library, I got an error:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Error opening terminal: unknown.
</code></pre></div></div>

<p>I found a <a href="http://stackoverflow.com/questions/16234620/error-opening-terminal-unknown-when-trying-to-run-a-program-inside-eclipse">related question on Stack Overflow</a>. Adding a <tt>TERM</tt> environment variable turned out to be the solution. To do this in Condor, add a line like this to your Condor script:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>environment    = "TERM=xterm"
</code></pre></div></div>

<p>If you want to add more variables, just use a space to separate them inside the quotation marks.</p>]]></content><author><name>Patrick</name></author><category term="Computing" /><category term="c++" /><category term="condor" /><category term="linux" /><category term="ncurses" /><category term="terminal" /><summary type="html"><![CDATA[Running a Condor (7.5.5) job for my c++ program which makes use of the ncurses library, I got an error:]]></summary></entry></feed>