<?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[Knowledge Stockpile]]></title><description><![CDATA[Links, tutorials and articles related to economics and coding]]></description><link>http://blog.bharatbhole.com</link><generator>NodeJS RSS Module</generator><lastBuildDate>Fri, 06 Mar 2026 03:18:57 GMT</lastBuildDate><atom:link href="http://blog.bharatbhole.com/rss/" rel="self" type="application/rss+xml"/><author><![CDATA[Bharat Bhole]]></author><ttl>60</ttl><item><title><![CDATA[Using fabric to automate command line tasks]]></title><description><![CDATA[<!--  
    Using fabric to automate command line tasks
-->

<p>Python library <a href='http://docs.fabfile.org/en/1.8/' ><code>fabric</code></a> is a great way to automate command line tasks. If you use command line, know Python, and don't know bash-scripting (or prefer using Python to bash-scripting) then you are likely to find <code>fabric</code> extremely useful in automating repetitive tasks. In this "live" post I will record different ways in which I use <code>fabric</code>. </p>

<h3 id="usingfabrictorunalocalcommandexamplersync">Using <code>fabric</code> to run a local command (example: <code>rsync</code>)</h3>

<p>The following is a simple code snippet that shows how you can use <code>fabric</code> to fetch files from a remote folder (say, <code>/home/fabricuser/projects/myproject</code>) to a local folder (say, <code>~/localProjects/myproject</code>) using <code>rsync</code>. </p>

<p>Of course, replace the pathnames as necessary. But for the code snippet to work: </p>

<p>(1) you must save the code snippet locally with the name <code>fabfile.py</code>. A <code>fabric</code> script must be named <code>fabfile.py</code>; </p>

<p>(2) you must save the code snippet in the folder that contains the local folder that you want to sync. In the example here we are syncing the folder <code>myproject</code> that is contained within <code>~/localProjects</code> folder; so the code snippet must be saved as <code>fabfile.py</code> in <code>~/localProjects</code>. </p>

<p>Also, replace <code>fabricuser</code> by your username and <code>123.456.78.90</code> by the ip address of your server.</p>

<pre><code>from fabric.api import local

# absolute remote path
remotePath = '/home/fabricuser/projects/myproject' 

# relative path from ~/localProjects
localPath = './' 


def getFiles():                
    local( 'rsync -avz fabricuser@123.456.78.90:{0} {1}'\
                        .format(remotePath, localPath) )
</code></pre>

<p>Once you have saved the above code snippet in <code>~/localProjects</code> as <code>fabfile.py</code>, you can get files from the remote server by navigating to <code>~/localProjects</code> using the terminal, and running <code>fab getFiles</code>. This is so much easier that typing out the entire <code>rsync -avz &lt;source&gt; &lt;destination&gt;</code> command repeatedly. </p>

<p>The only fabric specific command in the above snippet is the <code>local()</code> command. <code>local()</code> says that "run the shell command in the parantheses on the local machine". In the above snippet we are running the standard <code>rsync</code> command on the local machine. </p>

<p>A fabric script can contain multiple functions, and you can then use <code>fab &lt;function name&gt;</code> to execute the tasks specified by that function. The code snippet below expands the above script with two additional functions:</p>

<pre><code>from fabric.api import local


def getFiles():        
    # absolute remote path
    remotePath = '/home/fabricuser/projects/myproject' 

    # relative path from ~/localProjects
    localPath = './' 

    local( 'rsync -avz fabricuser@123.456.78.90:{0} {1}'\
                        .format(remotePath, localPath) )


def sendFiles():
    # absolute remote path
    remotePath = '/home/fabricuser/projects' 

    # relative path from ~/localProjects
    localPath = './myproject' 

    local( 'rsync -avz {0} fabricuser@123.456.78.90:{1}'\
                        .format(localPath, remotePath) )


def syncBothWays():
    getFiles()
    sendFiles()
</code></pre>

<p>Function <code>sendFiles</code> sends files from the local folder to the remote folder. To use this we need to run <code>fab sendFiles</code> at the command prompt. To get files and send files using a single command, you can run <code>fab syncBothWays</code>. In each case, you must be in the folder where <code>fabfile.py</code> is saved.</p>]]></description><link>http://blog.bharatbhole.com/using-fabric-to-automate-command-line-tasks/</link><guid isPermaLink="false">d30c3a1d-459b-40da-9574-c570e4dbc7ad</guid><dc:creator><![CDATA[Bharat Bhole]]></dc:creator><pubDate>Mon, 06 Jan 2014 03:08:56 GMT</pubDate></item><item><title><![CDATA[Inserting pages from an external PDF document within a LaTeX document]]></title><description><![CDATA[<!--  
    Inserting pages from an external PDF document within your LaTeX document
-->

<p>Suppose you are using the <code>pdflatex</code> command to generate a PDF from your LaTeX document, and you need to insert pages from an external PDF document in the PDF document that you are creating. You can do this quite easily using the <a href='http://mirror.unl.edu/ctan/macros/latex2e/contrib/pdfpages/pdfpages.pdf' >pdfpages package</a> by Andreas Matthias. I learnt about this package from <a href='http://stackoverflow.com/questions/2739159/inserting-a-pdf-file-in-latex' >this post</a> on Stackoverflow. The <a href='http://mirror.unl.edu/ctan/macros/latex2e/contrib/pdfpages/pdfpages.pdf' >documentation</a> accompanying the package is very good and quite easy to understand.  Nevertheless, I find it helpful to have some ready examples for common use cases. The following code snippets provide some such examples. They build on the answer in the linked Stackoverflow post.</p>

<p>First, add <code>\usepackage{pdfpages}</code> to the preamble of your LaTeX document. All the snippets below assume that you have done this.</p>

<p>The command syntax is:</p>

<pre><code>\includepdf[key1=val1, key2=val2, key3=val3]{pathToFile}
</code></pre>

<p>where:</p>

<p><code>\includepdf</code> is the name of the command <br />
<code>key=val</code> is a comma separated list of options <br />
<code>pathToFile</code> is path to the external PDF file that you want to include.</p>

<p>For this post we will assume that the external PDF file is in the same directory where the LaTeX file is, and is called <code>external.pdf</code>.</p>

<hr />

<h4 id="mostbasicusenooptionsarespecified">Most basic use (no options are specified)</h4>

<pre><code>%--------------
%% Snippet 1
%--------------
\includepdf{external.pdf} 
</code></pre>

<p>This will insert the first page of <code>external.pdf</code> without numbering the inserted page. </p>

<hr />

<h4 id="thepagecommandoption">The <code>pagecommand</code> option</h4>

<p>If you want to the inserted page to have a page number add the option <code>pagecommand={}</code>. With this option, the command will be:</p>

<pre><code>%--------------
%% Snippet 2
%--------------
\includepdf[pagecommand={}]{external.pdf}
</code></pre>

<p>Now you will have the first page of the external.pdf file and it will numbered as if it were part of your LaTeX document. The default value of the <code>pagecommand</code> option is <code>{ \thispagestyle{empty} }</code>, which is why page number was missing in the output of Snippet 1. By including <code>pagecommand = {}</code> you override this option. In general, according to the documentation, "[<code>pagecommand</code>] declares LaTeX commands, which are executed on each sheet of paper". </p>

<hr />

<h4 id="includingspecificpages">Including specific pages</h4>

<p>Snippets 1 and 2 insert only the first page of <code>external.pdf</code> document. What if you wanted to insert more pages or other pages? For this you would use the <code>pages</code> option. I have left the <code>pagecommand</code> option in there so that you can see how different options can be combined. It is not required for including specific pages.</p>

<p>To insert all pages from external.pdf, use:</p>

<pre><code>%--------------
%% Snippet 3
%--------------
\includepdf[pages=-, pagecommand={}]{external.pdf}   
</code></pre>

<p>To insert specific pages, say pages 2, 4, and 7, use:</p>

<pre><code>%--------------
%% Snippet 4
%--------------
\includepdf[pages={2, 4, 7}, pagecommand={}]{external.pdf}
</code></pre>

<p>To insert a range of pages, say pages 9 through 13, use:</p>

<pre><code>%--------------
%% Snippet 5
%--------------
\includepdf[pages={9-13}, pagecommand={}]{external.pdf}
</code></pre>

<p>If you want to include specific pages and a range of pages, you can combine snippets 4 and 5 as:</p>

<pre><code>%--------------
%% Snippet 6
%--------------
\includepdf[pages={2, 4, 7, 9-13}, pagecommand={}]{external.pdf}
</code></pre>

<hr />

<h4 id="scalingthepages">Scaling the pages</h4>

<p>According to the documentation, pages are scaled automatically as they are inserted. This can be prevented by including <code>noautoscale = true</code> option. However, for a more fine-grained control on scaling you can use the <code>scale</code> option provided by the <code>graphicx</code> package. For example, you can use:</p>

<pre><code>%--------------
%% Snippet 7
%--------------
\includepdf[pages=-, scale=0.9, pagecommand={}]{external.pdf}
</code></pre>

<p>Value of <code>scale</code> option should be between 0 and 1.</p>]]></description><link>http://blog.bharatbhole.com/inserting-pages-from-an-external-pdf-document-within-a-latex-document/</link><guid isPermaLink="false">4793d4ba-540e-4760-8fdc-831f4b885f48</guid><dc:creator><![CDATA[Bharat Bhole]]></dc:creator><pubDate>Sat, 14 Dec 2013 23:28:25 GMT</pubDate></item><item><title><![CDATA[Rubinstein on real-world applicability of Game Theory]]></title><description><![CDATA[<p>If you have ever wondered about the real-world applicability of Game Theory you should read the following post by Ariel Rubinstein. In case you do not already know, Rubinstein is one of the distinguished researchers in the field of Game Theory.</p>

<p><a href='http://www.faz.net/aktuell/feuilleton/debatten/game-theory-how-game-theory-will-solve-the-problems-of-the-euro-bloc-and-stop-iranian-nukes-12130407.html' >Rubinstein: How game theory will solve the problems of the Euro Bloc and stop Iranian nukes</a></p>]]></description><link>http://blog.bharatbhole.com/rubinstein-on-real-world-applicability-of-game-theory/</link><guid isPermaLink="false">a5204fd5-2ea5-401f-9380-d80eda81073f</guid><dc:creator><![CDATA[Bharat Bhole]]></dc:creator><pubDate>Sun, 08 Dec 2013 23:41:26 GMT</pubDate></item><item><title><![CDATA[Ubuntu 12.04 server: Basic setup]]></title><description><![CDATA[<p>This article describes the steps one can take to setup a Ubuntu 12.04 server with some basic security. I wrote the article as I was setting up such a server on <a href='https://www.digitalocean.com/' >Digital Ocean</a>. However, I believe that these steps are applicable even if you are not using Digital Ocean. </p>

<p>The article assumes that you have root access to a remote Ubuntu 12.04 server and know its IP address. For the sake of this post let us assume that the IP address of the server is 111.222.333.444</p>

<h4 id="step1sshintotheserverasrootuser">Step 1: SSH into the server as root user.</h4>

<p>Type the following and hit <code>enter</code></p>

<pre><code>ssh root@111.222.333.444
</code></pre>

<p>You will be shown a RSA key fingerprint and asked whether you want to continue connecting. Choose <em>yes</em> and hit <code>enter</code>. You will be prompted for your password. Enter the password and you will be logged into the server.</p>

<h4 id="step2createanewuser">Step 2: Create a new user</h4>

<p>Create a new user on this server. For security reasons it is best to access your server as a different user than the root user. Let us call the new user <code>trialuser</code>. You create this user using the command</p>

<pre><code>adduser trialuser
</code></pre>

<p>and answering the questions that follow that command. </p>

<h4 id="step3addthenewusertothesudogroup">Step 3: Add the new user to the sudo group</h4>

<p>Add the newly created user to the sudo group so that the user will have sudo privilege. This is done using the command:</p>

<pre><code>usermod -a -G sudo trialuser
</code></pre>

<p>Note that since we are still logged in as the root user, we don't need to add <code>sudo</code> in front of the above commands.</p>

<h4 id="step3logoutfromtherootaccountandloginasthetrialuser">Step 3: Logout from the root account and login as the trialuser</h4>

<p>Logout of the root account and log back in as the trialuser using </p>

<pre><code>ssh trialuser@111.222.333.444
</code></pre>

<h4 id="step4installvim">Step 4: Install vim</h4>

<p>We will need to make changes to various configuration files. For this I prefer to use the vim editor. If you don't want to use vim you can skip this step. Before installing vim run:</p>

<pre><code>sudo apt-get update
sudo apt-get upgrade
</code></pre>

<p>After those two commands, run:</p>

<pre><code>sudo apt-get install vim
</code></pre>

<h4 id="step4disablerootloginandallowonlytrialusertologin">Step 4: Disable root login and allow only <code>trialuser</code> to login</h4>

<p>The next step is to secure your server by disabling the root login. </p>

<p>Open <code>/etc/ssh/sshd_config</code> using vim (<code>sudo vim /etc/ssh/sshd_config</code>). Find line <code>PermitRootLogin</code> and change from </p>

<pre><code>PermitRootLogin yes
</code></pre>

<p>to </p>

<pre><code>PermitRootLogin no
</code></pre>

<p>Also add the line</p>

<pre><code>AllowUsers trialuser
</code></pre>

<p>at the bottom of <code>sshd_config</code> file. This will ensure that only you, <code>trialuser</code>, (remember to replace <code>trialuser</code> with your username) can login into the server. </p>

<p>The changes you made above will not take effect until you reload ssh. To do so, enter the command:</p>

<pre><code>sudo reload ssh
</code></pre>

<h4 id="step5installfail2ban">Step 5: Install <code>fail2ban</code></h4>

<p><code>fail2ban</code> is an awesome utility which (amongst other things) bans IP addresses with repeated failed login attempts. This helps against brute force attacks on your server. To install fail2ban run:</p>

<pre><code>sudo apt-get install fail2ban
</code></pre>

<p>According to the <a href='https://www.digitalocean.com/community/articles/how-to-protect-ssh-with-fail2ban-on-ubuntu-12-04' >fail2ban installation guide</a> on Digital Ocean, to configure fail2ban we must copy <code>/etc/fail2ban/jail.conf</code> to <code>/etc/fail2ban/jail.local</code> and make any configuration changes to <code>jail.local</code> file. </p>

<pre><code>sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
</code></pre>

<p>You can make configuration changes to the <code>/etc/fail2ban/jail.local</code> file such as changing <strong>bantime</strong> (time for which an IP address is banned). You can find more information in the <a href='https://www.digitalocean.com/community/articles/how-to-protect-ssh-with-fail2ban-on-ubuntu-12-04' >fail2ban article</a> on Digital Ocean.</p>

<p>Once you have made the changes in the /etc/fail2ban/jail.local file restart <code>fail2ban</code> for those changes to take effect by running:</p>

<pre><code>sudo /etc/init.d/fail2ban restart
</code></pre>

<p>If you have a static ip address, you can add it to the <code>ignoreip</code> line in file <code>/etc/fail2ban/jail.local</code>, so that <code>fail2ban</code> does not accidentally lock you out. If you have more than one IP address, separate them by space.</p>

<p>A couple of hours after your server is online take a look at <code>/var/log/fail2ban.log</code> to see pesky IP addresses that fail2ban has banned for attempting to break in into your server.</p>

<h4 id="step6setupsshkeys">Step 6: Setup SSH keys</h4>

<p>On your local computer, navigate to <code>~/.ssh</code> folder. In this folder see if there exist two files <code>id_rsa</code> and <code>id_rsa.pub</code>. If so, you already have a ssh key and don't need to generate a new one. </p>

<p>If you don't see those two files, then you need to generate an ssh key. You can do so using the command:</p>

<pre><code>ssh-keygen -t rsa
</code></pre>

<p>Enter the command and follow the instructions. If you accepted the default location for saving the key, you will find files <code>id_rsa</code> and <code>id_rsa.pub</code> in your <code>~/.ssh</code> folder.</p>

<p>Once you have your ssh key, to use it with the server add the public key (<code>id_rsa.pub</code>) to the <code>~/.ssh/authorized_keys</code> file on your server. As noted in the <a href='https://www.digitalocean.com/community/articles/how-to-set-up-ssh-keys--2' >Digital Ocean article here</a> you can use either of the following two commands to do this:</p>

<pre><code>ssh-copy-id trialuser@111.222.333.444
</code></pre>

<p>or</p>

<pre><code>cat ~/.ssh/id_rsa.pub | ssh user@123.45.56.78 "cat &gt;&gt; ~/.ssh/authorized_keys"
</code></pre>

<p>Your server is now setup with some basic security. You can certainly make it more secure. I will leave it to you to explore those options. </p>]]></description><link>http://blog.bharatbhole.com/basic-setup-ubuntu-12-04-server/</link><guid isPermaLink="false">cf7fddf4-a049-4ae2-a4a5-c07d88c695a2</guid><dc:creator><![CDATA[Bharat Bhole]]></dc:creator><pubDate>Sun, 08 Dec 2013 15:19:44 GMT</pubDate></item><item><title><![CDATA[Creating boxplots with Matplotlib]]></title><description><![CDATA[<p>Let us create some box-and-whisker plots (henceforth, referred to simply as boxplots) using Matplotlib. At the end of the post we will have a boxplot which looks like the following.</p>

<p><img src='http://blog.bharatbhole.com/content/images/2013/matplotlib_bp_1/fig3.png'  alt="" /></p>

<hr />

<h3 id="importthelibrariesandspecifythetypeoftheoutputfile">Import the libraries and specify the type of the output file.</h3>

<p>The first step is to import the python libraries that we will use.</p>

<pre><code>## numpy is used for creating fake data
import numpy as np 
import matplotlib as mpl 

## agg backend is used to create plot as a .png file
mpl.use('agg')

import matplotlib.pyplot as plt 
</code></pre>

<hr />

<h3 id="convertthedatatoanappropriateformat">Convert the data to an appropriate format</h3>

<p>The second step is to ensure that your data is in an appropriate format. We need to provide a collection of values for each box in the boxplot. A collection can be expressed as a python <code>list</code>, <code>tuple</code>, or as a <code>numpy array</code>. Once you have the different collections, one for each box, you combine all these collections together in a <code>list</code>, <code>tuple</code> or a <code>numpy array</code>. That is, the data for the boxplot is in the form of a list of lists, or list of arrays, or a tuple of arrays etc. </p>

<p>Let us create the data for the boxplots. We use <code>numpy.random.normal()</code> to create the fake data. It takes three arguments, <code>mean</code> and <code>standard deviation</code> of the normal distribution, and the number of values desired.</p>

<pre><code>## Create data
np.random.seed(10)
collectn_1 = np.random.normal(100, 10, 200)
collectn_2 = np.random.normal(80, 30, 200)
collectn_3 = np.random.normal(90, 20, 200)
collectn_4 = np.random.normal(70, 25, 200)

## combine these different collections into a list    
data_to_plot = [collectn_1, collectn_2, collectn_3, collectn_4]
</code></pre>

<hr />

<h3 id="createtheboxplot">Create the boxplot</h3>

<p>The list of arrays that we created above is the only required input for creating the boxplot. Using <code>data_to_plot</code> we can create the boxplot with the following code:</p>

<pre><code># Create a figure instance
fig = plt.figure(1, figsize=(9, 6))

# Create an axes instance
ax = fig.add_subplot(111)

# Create the boxplot
bp = ax.boxplot(data_to_plot)

# Save the figure
fig.savefig('fig1.png', bbox_inches='tight')
</code></pre>

<p>This gives:</p>

<p><img src='http://blog.bharatbhole.com/content/images/2013/matplotlib_bp_1/fig1.png'  alt="" /></p>

<p>That was easy. If you are satisfied with the default choices for the axes limits, labels and the look of the plot there is nothing more to do. Most likely that is not the case and you want to customize these features. Matplotlib provides endless customization possibilities.</p>

<hr />

<h3 id="changecoloroftheboxeswhiskerscapsandthemedian">Change color of the boxes, whiskers, caps and the median</h3>

<p>The <code>bp</code> variable in the code snippet above is a python dictionary with keys <code>boxes</code>, <code>whiskers</code>, <code>caps</code>, <code>fliers</code> and the <code>median</code>. The values in this dictionary are the geometric instances that we see in the plot. For example, the values <code>bp['boxes']</code> are the polygon instances that we see as boxes; values <code>bp['whiskers']</code> are the line instances that we see as whiskers. To change the colors of boxes, whiskers etc., we need to access these instances from the <code>bp</code> dictionary and change their properties. The code below shows how to do this. In addition to changing the colors we also increase the line width to make the differences in color easier to see. Add the following code before the <code>fig.savefig('fig1.png', bbox_inches='tight')</code> line in the above snippet.</p>

<pre><code>## add patch_artist=True option to ax.boxplot() 
## to get fill color
bp = ax.boxplot(data_to_plot, patch_artist=True)

## change outline color, fill color and linewidth of the boxes
for box in bp['boxes']:
    # change outline color
    box.set( color='#7570b3', linewidth=2)
    # change fill color
    box.set( facecolor = '#1b9e77' )

## change color and linewidth of the whiskers
for whisker in bp['whiskers']:
    whisker.set(color='#7570b3', linewidth=2)

## change color and linewidth of the caps
for cap in bp['caps']:
    cap.set(color='#7570b3', linewidth=2)

## change color and linewidth of the medians
for median in bp['medians']:
    median.set(color='#b2df8a', linewidth=2)

## change the style of fliers and their fill
for flier in bp['fliers']:
    flier.set(marker='o', color='#e7298a', alpha=0.5)
</code></pre>

<p>This gives:</p>

<p><img src='http://blog.bharatbhole.com/content/images/2013/matplotlib_bp_1/fig2.png'  alt="" /></p>

<hr />

<h3 id="changexaxislabelsandremovetickmarksfromthetopandrightaxes">Change x-axis labels and remove tick marks from the top and right axes.</h3>

<p>This is easy. To do this pass a <code>list</code> of custom labels to <code>ax.set_xticklabels()</code> function. The list should have the same length as the number of boxes in the boxplot. For example, suppose instead of the default x-axis labels that we see in the plots above, we want labels 'Sample1', 'Sample2', 'Sample3' and 'Sample4'. We can modify the labels using the following line (add it before the line where the figure is saved):</p>

<pre><code>## Custom x-axis labels
ax.set_xticklabels(['Sample1', 'Sample2', 'Sample3', 'Sample4'])
</code></pre>

<p>To remove the tick-marks from top and right spines, or rather to keep ticks only on the bottom and left axes, add the following lines to the code. </p>

<pre><code>## Remove top axes and right axes ticks
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
</code></pre>

<p>With the custom x-axis labels and removal of top and right axes ticks, the boxplot now looks like the following:</p>

<p><img src='http://blog.bharatbhole.com/content/images/2013/matplotlib_bp_1/fig3.png'  alt="" /></p>

<p>If you are curious to learn more about creating boxplots with matplotlib, you may find the following links helpful.</p>

<ol>
<li><p><a href='http://matplotlib.org/api/axes_api.html?highlight=boxplot' #matplotlib.axes.Axes.boxplot">Official matplotlib documentation on boxplots</a></p></li>
<li><p><a href='http://matplotlib.org/examples/pylab_examples/boxplot_demo2.html' >Boxplot example on matplotlib website</a></p></li>
</ol>]]></description><link>http://blog.bharatbhole.com/creating-boxplots-with-matplotlib/</link><guid isPermaLink="false">390ee225-014b-4f6b-a14c-e402f6fe7ec2</guid><dc:creator><![CDATA[Bharat Bhole]]></dc:creator><pubDate>Sun, 01 Dec 2013 17:58:25 GMT</pubDate></item></channel></rss>