All you needed to know about MFCC

RG: Amir Poorjam

cv2.imwrite/cv2.imread are faster than on numpy matrices with integers

In one of the ongoing projects, I generate a lot of small matrices (~1000 entries). These are often written to the disk and read from it. I was trying to optimize this step since this step run in a REST api.

The standard way is and numpy.load which works fine. My experience with opencv made me wonder if cv2.imwrite and cv2.imread can be used. The later saves the matrices to png file which works without any loss of data if you have 8 or 16 bit integer values in your matrices. I do.

Here are some benchmarks using %timeit.

Only saving matrices

I generate a random matrix of 400 entries and save it to a png file using OpenCV and also using numpy. OpenCV is roughly 3.6 times faster.

In [8]: %timeit cv2.imwrite('/tmp/a.png', np.random.randint(0, 255, (20,20)))                                                                                     
142 µs ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [10]: %timeit'/tmp/a.npy', np.random.randint(0, 255, (20,20)))                                                                                        
517 µs ± 96.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

The trend continues (OpenCV is ever so slightly faster here) for matrices with 900 entries. I did not test with larger matrices.

In [14]: %timeit cv2.imwrite('/tmp/a.png', np.random.randint(0, 255, (30,30))); a = cv2.imread('/tmp/a.png')                                                      
215 µs ± 2.93 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [15]: %timeit'/tmp/a.npy', np.random.randint(0, 255, (30,30))); np.load('/tmp/a.npy')                                                                 
791 µs ± 29.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Saving and reading matrices

Reading back into matrices is also faster with OpenCV. Following micro-benchmarks write and read a randomly generated matrix using OpenCV and numpy.

In [12]: %timeit cv2.imwrite('/tmp/a.png', np.random.randint(0, 255, (20,20))); a = cv2.imread('/tmp/a.png')                                                      
192 µs ± 2.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [13]: %timeit'/tmp/a.npy', np.random.randint(0, 255, (20,20))); np.load('/tmp/a.npy')                                                                 
770 µs ± 23.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

I guess I’ll be using OpenCV to save data whenever I have integer matrices.

I used Python3.6 on OpenSUSE-15.1 server.

Farm Bill | Err on the side of caution

My father is a farmer. He works and lives in western U.P., a relatively prosperous area in terms of ground-water and road connectivity. He is not sufficiently poor. He managed to pay for my college (circa 2007). I spent the first 21 years of my life in the village, often working on the farms. It is a hard life once you have experienced the alternatives.

We are sugar-cane farmers and are well organized. Usually, politicians don’t like to mess up with organized farmers. But a hyper-centralized state can. After all, everyone is living in their own bubbles these days. Some powerful people will always believe that they know best what is good for everyone else. This is not true even when they have the noblest of intentions and act in good faith. And this bill was not passed in a good faith.

We wouldn’t know the effect of this bill for a year or two. Strong fluctuations in prices is a routine for farmers, especially near harvesting season (can’t tell why!). But there is something odd about this bill. Like demonetization, GST, and CAA, the long term benefits of this Farm Bill are doubtful at best (call me anti-national), but the short term dangers are real.

Let’s consider the simplest possible scenario. I spend 3 to 4 months on my rice or wheat crop. During these months, I paid school fees, medical bills (not all days are achche din) often by borrowing money from a local money-lender at an interest rate of 15% to 50% (What? That can never happen in our glorious country. I must be lying! After all, the best government is at the helm. Off with an FIR!). As soon as I harvest my crop, the first thing on my mind is to pay back the loan and plan for the next crop. I can’t store for a very long time or delay the payment on the loan even if the loan is from a Sarkari bank. I am not Ambani, Adani, or that Kingfisher guy (I am sure this list is long!).

The local vendor (khalifa) comes to my village and offers me a price which is usually less than the minimum support price given by the govt. He picks up the crop from my house. Saves me the time and hassle of transporting the crop to the Sarkari mandi which is at least 30km away. Selling in Mandi usually means wait there for a whole day to sell, and for a couple of months for the money in the bank. If the vendor offers me 10 to 15% less than the Sarkari price, I happily sell it to him. If he offers less, I take the trouble to go to Mandi, usually in a group of 4-5 farmers. Unlike what others have been telling you, farmers always had the choice to sell their corp to anyone. This bill brings nothing new in this regard! Isn’t it obvious? I’ll sell anyone who offers me MSP-1. The question has always been at what price? No vendor has ever, ever, offered more money than the MSP!

If all local vendors lower the price for a month or two then only a few farmers would be able to wait and watch till prices go up again, if ever. Almost all farmers will go for stress selling. It is worse for farmers who grow perishable crops like tomatoes and papaya. They can hardly wait for a week. It is not a hypothetical situation to malign the reputation of your favorite politician. It happens all the time: just talk to a real farmer in good faith.

Let’s take a leaf from your life and talk about education and health. You must have had some experience with these two sectors. I see them somewhat functional in the cities and towns, much better in the southern part of the country. These sectors have roughly the same social and economic dynamics and roughly the same arguments about public and private ownership.

If your local government school is bad, I bet, most private schools are only slightly better. Aren’t they? There is no incentive for a private school to do much better than the best government school in the locality. They do slightly better and you get enough candidates. Not sure what is the situation is with your hospitals. My guess is that private hospitals need to do just slightly better in diagnostics but has to look much better (they have color TV at reception). I read all the fantastic stories about how nicely and humanely they treat their patients! Why would you think farmers will get any different treatment from similar corporates entities?

The government should strive for a decent baseline: MSP for crops, minimum wages, minimum education, and minimum health coverage, even when the private sector is helping and not exploiting the lack of government presence. This is not too much to ask from a government for its people, democratic or otherwise, left or right, sikular or fascist. And every decent society should strive for it.

The MSP is set at 1.5 times the cost of the crop. The real market can’t afford to give this much to the farmers hence the MSP was proposed in the first place. If you think that market must be able to pay that much or more ( balle balle!), then it does not matter if you leave the MSP alone. If you think the market is fair, then it wouldn’t matter if you leave the legal provision for appeal in the court there (it won’t ever be used). Even if you think, these are needless in your somewhat utopian view of markets, my request is to err on the side of caution.

It may not be politically correct, but it is decent to act in good faith!

And by the way, the Chinese have figured out quantum supremacy ( this week.

Generate Android Bundle (.aab file) for a Cordova app

Cordova 8.1+ supports generating Android Bundle (.aab file). Usually cordova generates an .apk file for your app. Playstore often warns about .apk file about it’s bloated size.

To generate an .aab file, add --packageType=bundle option to your cordova build command.

cordova build android --release -- --packageType=bundle

Signed bundles

Here is the command I use to generate a singed bundle.

cordova build android --release  -- --keystore=~/keystore/dilawar.jks --storePassword=$(KEYSTORE_PASSWORD)  --alias=dilawar --password=$(KEYSTORE_PASSWORD)  --packageType=bundle --webpack.mode=production

The old way to generate bundle

See the discussion here. And feature request here .

These instructions were posted here They worked for me.

  1. Launch Android Studio
  2. Go To Import Project (Eclipse ADT, Gradle, etc).
  3. Select Android platform directory in your project (/platforms/android).
  4. Wait for finish the Sync
  5. Go to Build > Generate Sign Bundle
  6. Complete sign data
  7. Upload de .aab file generated (in path /platforms/android/outputs/

I did not find any significant reduction in the app size when using the .aab format (signed bundle). My app was reduced from 6.8MB to 6.5MB :neutral_face:

Getting X11 (XQuartz) to work on OSX

Today I finally managed to get XQuartz to work on a mac mini. I use this machine as server to test my code for OSX. Its a horrible machine to do any development (I am an OSX noob and a terminal junkie).

Usually, I login to this machine (named strudel) from my Linux workstation over ssh and once a while, I need graphics. Some app just don’t have a good cli. I never managed to open graphics after login. Today, I looked around and found a potential solution called XQuartz.

I installed xquartz following these instructions. Rebooted and logged in over ssh. Still I couldn’t launch xeyes. I keep getting Error: Can't open display: error. Note that DISPLAY is not set.

The solution is straightforward if one reads the XQuartz FAQ carefully which I didn’t :-(.

One my OSX machine strudel, I needed to make sure that /etc/ssh/sshd_config has following two lines.

 X11Forwarding yes                                                               
 X11UseLocalhost yes   

And that’s it. You probably need to reboot after mcking these changes.

argmax in pure Python

Python does not have an inbuilt argmax function. numpy does.

Here is one implementation.

def argmax(ls : list) -> int:
    _m, _mi = -math.inf, 0   # requires `import math` at top
    for i, v in enumerate(ls):
        if v > _m:
            _m = v
            _mi = i
    return _mi

There is also a one-liner which I often use: max(zip(ls, range(len(ls))))[1] where ls is the input list. To my surprise, the one liner is slower than argmax defined above (Python3.9 on openSUSE-Tumbleweed/Intel).

In [1]: a = [1,2,3,9,5,6,3,2]                                                                                                                                     
In [2]: max(zip(a, range(len(a))))[1]                                                                                                                                                         
Out[2]: 3

In [4]: %timeit max(zip(a, range(len(a))))                                                                                                                        
1.34 µs ± 28.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)                                                                                                                                 

In [7]: %timeit argmax(a)                                                                                                                                         
837 ns ± 8.65 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

On large list,

In [11]: a = [random.randint(0, 111111) for x in range(1000)]                                                                                                     

In [12]: %timeit argmax(a)                                                                                                                                        
67.7 µs ± 446 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [13]: %timeit max(zip(a, range(len(a))))                                                                                                                       
86.1 µs ± 739 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Adding google-analytics to your vue application

I am using Google’s global site gags (gtags) on my framework7+vue application to collect data. The gtag official documentation has an easy to use example. Anyway, I prefer vue-gtag library.

  • install vue-gtag npm install vue-gtag
  • Add following to your vue app. Usually you have to edit src/js/app.js file or equivalent file where vue is being initialized.
// Init google analytics
import VueGtag from "vue-gtag";
Vue.use(VueGtag, {
   config: { id: "UA-180198765-1" }

where id key in config dictionary is your tracking id.

Official documentation here


  • [vue-gtag] Ops! Something happened and gtag.js couldn't be loaded.


fd is an awesome replacement of find command

Recently, I came across fd command. It is written in Rust and suppose to replace find command.

fd is amazing, PERIOD. It has much better user experience. Check out the official demo below,


My pet peeve with find command is not that it has too many options, but that these options are hard to figure out. I don’t use find so often to build a muscle memory. So a simpler version is most welcome.

To give one particular example, yesterday I wanted to know the list of sub-directories I’ve touched 2 days ago. I played with -mmin and -mtimes options and got lost. With fd, I could just do the following

$ fd --changed-within 2d

Do I need to say more?

tldr fd


  An alternative to find.
  Aims to be faster and easier to use than find.
  More information:

  - Find files matching the given pattern in the current directory:
    fd pattern

  - Find files that begin with "foo":
    fd '^foo'

  - Find files with a specific extension:
    fd --extension txt

  - Find files in a specific directory:
    fd pattern path/to/dir

  - Include ignored and hidden files in the search:
    fd --hidden --no-ignore pattern