2015 September

Nompy: a neat calorie calculator

Posted by | English, Programming, Python | No Comments

Nompy 0.1Currently I’m trying to improve my diet, and calculating calories of meals became kind of annoying. Then a great idea formed, why not make a neat program to do most of the annoying stuff for me? Python was the obvious choice at the time, since I’ve been doing a lot of Python courses in the past, and all the scripts I wrote didn’t really serve any practical purpose. It was time I created something useful, and that’s how Nompy came to existence. It’s a project that I’m doing to improve my skills as a programmer, but at the same time, I’ll be using its features on a daily basis.

So as I started brainstorming on what technologies I’ll have to use. I knew two things:

– I needed a way to store all the nutritional facts, that food packages have listed
– I had to decide on what graphical user interface library I’m going to learn

For storing nutritional facts, I discovered YAML, and really liked the concept behind it. I wanted the data to be easily readable and editable by users, and it would work great for that purpose. But later I changed my mind, as I wanted to use as little external libraries as possible, and I learned that JSON was something I’d need to use at some point one way or another. Entering data in JSON format by hands is something I wouldn’t expect of an end user, so I plan on making a GUI feature in my application somewhere down the road.

As goes for GUI library, the only one that’s part of Python is Tkinter, but I don’t like the spartan look it has. I’ve always been a fan of Qt, and how the applications built on it looked awesome on all platforms (Windows, OSX and Linux). I knew I wanted to use it, but the next question was on which project to use, PyQt or PySide? After a brief googling session I came up with a few sources that described the current situation of both projects. PyQt has a larger user base, and is actively developed unlike PySide. PySide has one huge plus, it doesn’t have a limiting license like PyQt does. While PyQt is completely free for all open-source projects, Riverbank software charges about 480 euros for a commercial license. At the end I chose PyQt anyways, because the deciding factor was simply the fact, that it already supports Qt5, while PySide is still stuck with Qt4. I’m pretty sure that porting an application of this size to PySide 2 shouldn’t be a problem if it ever matures.

nompy01_interfaceAfter doing some research, I knew I wanted to separate my back end algorithms from UI logic. Designing an interface in Qt Designer is kind of straightforward, although widget alignment and their relative size can be challenging to configure. Designer generates an XML file with an extension of “.ui”, which can then be translated to Python by using pyuic5 tool bundled with PyQt. I created a third Python script, that links the PyQt and my back end. So this is the structure of files I ended up with:

– nompy.py (bridge between core and interface)
– nompy_core.py (back end)
– nompy_interface.py (PyQt5 project)

Script pulls data from two files, ingredients.json and dishes.json. Ingredients JSON contains nutritional facts for each ingredient, and dishes JSON contains ingredient names and their amount for every dish, so it’s basically a recipe.

Dish example:

{
	"Kosmiči z mlekom": {
		"Crispy z ječmenovo vlaknino" 	: 30,
		"Alpsko mleko (3,5)"			: 2
	}
}

And now its ingredients:

{
	"Crispy z ječmenovo vlaknino": {
		"unit"         : "gram",
		"amount"       : 10,
		"fat"          : 0.17,
		"saturatedFat" : 0.04,
		"carbs"        : 7.93,
		"fiber"        : 0.7,
		"protein"      : 0.65,
		"salt"         : 0.091,
		"iron"         : 0,
		"calories"     : 37.3
	},

	"Alpsko mleko (3,5)": {
		"unit"         : "deciliter",
		"amount"       : 1,
		"fat"          : 3.5,
		"saturatedFat" : 2.3,
		"carbs"        : 4.7,
		"fiber"        : 0,
		"protein"      : 3.3,
		"salt"         : 0.12,
		"iron"         : 0,
		"calories"     : 64
	}
}

Currently adding multiple same dishes to the list isn’t intuitive (e.g. if I want to eat two sandwiches, I have to add a sandwich dish twice), so I plan on making some interface changes in version 0.2. It’ll also have a search function, and it will display stats for every selected dish immediately.

If you want to give it a try, here is an archive of the script. You’ll have to have Python 3 and PyQt5 installed, then you can run nompy.py. It’s licensed under GNU GPLv3 license so feel free to modify any part of the script.