# Build better hardware. Write clean, versioned and tested code
Joaquin Matres <jmatres@jmatres.com>
---

---
# Outline
1. Git :two_women_holding_hands:
2. Clean code :sparkles:
3. Packaging :package:
---

---

---
# Git for collaborative writing
- Keep track of history
- Develop new features safely
- Swap between versions
---
# Terminology
- Git takes snapshots of all the files in a folder. This folder is called a repository or repo.
- Create a commit to take a snapshot of a file or files.
- Add information about your changes in a commit message.
---
# Git commands
- `git init`: new project :small_blue_diamond:
- `git clone`: to your computer :arrow_down::cloud:
- `git add fileName`: track file :white_check_mark:
- `git commit`: commits your changes :camera:
- `git push`: changes to remote server :arrow_up::cloud:
- `git pull`: changes to your computer :arrow_down::cloud:
- `git status`: check status :question:
- `git log`: read log :book:
---
# plain text :smiley_cat:
- python (.py)
- markdown (.md)
- restructured Text (.rst)
# binary :scream_cat: :elephant: :horse:
- power point
---
# Git Remote services
- Github (free for public repos)
- Gitlab (free for public repos), you can also self-host it
- Bitbucket Atlassian (private repos up to 5 collaborators)
---
# Learn Git
- type `git help` in a terminal
- [Atlassian](https://www.atlassian.com/git/tutorials/setting-up-a-repository)
- [github](https://try.github.io/levels/1/challenges/1)
- [Software carpentry](http://swcarpentry.github.io/git-novice/01-basics/)
- [Git notebooks](https://github.com/computerproductivity/git_notebooks)
---

---

[1]
---
# Docstrings

---
# Google style
``` python
def func(arg1, arg2):
""" Summary
Args:
arg1 (int): Description of arg1
arg2 (str): Description of arg2
Returns:
bool: Description of return value
"""
return True
```
---
# Numpy style
``` python
def func(arg1, arg2):
"""Summary line.
Parameters
----------
arg1 : int
Description of arg1
arg2 : str
Description of arg2
Returns
-------
bool
Description of return value
"""
return True
```
---
# Code readability
Code is read many more times than written!
In many cases, that person is probably going to be you, six months from now.
- [pep8](https://pep8.org/)
- black: autoformatter
- pylint/pyflakes: syntax checker
---
``` python
def GetArea(l, w):
return l*w
l=3
w=4
A=GetArea(l,w)
```
---
``` python
def area_rectangle(length, width):
return length*width
length = 3
width = 4
area = area_rectangle(length, width)
```
---
# Style guides
- [PEP8](https://www.python.org/dev/peps/pep-0008/)
- [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html)
Formatting tools:
- [black]()
- [pep8, flake8](http://flake8.pycqa.org/en/latest/index.html)
- [pylint](https://www.pylint.org/)
---
# Classes
``` python
class SampleClass(object):
"""Summary of class here.
Longer class information....
Attributes:
likes_spam: boolean indicates if we like SPAM or not.
eggs: An integer count of the eggs we have laid.
"""
def __init__(self, likes_spam=False):
"""Inits SampleClass with blah."""
self.likes_spam = likes_spam
self.eggs = 0
def public_method(self):
"""Performs operation blah."""
```
---
``` python
def rmse(x, y):
return np.sqrt(((x-y)**2).mean())
```
---
``` python
def root_mean_square_error(observed, modelled):
error = observed - modelled
return np.sqrt((error**2).mean())
```
---
``` python
def root_mean_square_error(measured, simulated):
""" Root Mean Square Error (RMSE)
Args:
measured: numpy array of measured data
simulated: numpy array of simulated data
Returns:
mean square error numpy array
"""
error = observed - modelled
return np.sqrt((error**2).mean())
```
---
# PEP8 Indentation
- Four spaces (no tab!)
- Most editors can be set to convert a tab that you type to four spaces in the file
---
# PEP8 Maximum line length
- PEP8 recommends 79 characters
- We use 88 characters (default for [black autoformatter](https://github.com/ambv/black))
---
# PEP8 Line spacing
- Two blank lines around top level functions
- Two blank lines around classes
- One blank line between functions in a class
- One blank line between logical groups in a function (sparingly)
---
# No
``` python
a_var = 1
def one_function():
return something
def other_function():
return something_else
result = one_function()
```
---
# Yes
``` python
a_var = 1
def one_function():
return something
def other_function():
return something_else
result = one_function()
```
---
# PEP8 Imports are typically grouped:
- standard library imports
- related third party imports
- local application/library specific imports
``` python
import os
import sys
import numpy as np
import pandas as pd
import my_module
```
---
| type | Name convention |
| -------------------------- | ---------------- |
| Packages/Modules/Functions | lower_with_under |
| Classes/Exceptions | CapWords |
| Global/Class Constants | CAPS_WITH_UNDER |
| Global/Class Variables | lower_with_under |
| Instance/Local Variables | lower_with_under |
| Function/Method Parameters | lower_with_under |
---
``` python
from statistics import mean, stdev
import numpy as np
def MyFunction(ARGUMENT):
m=mean(ARGUMENT)
s=stdev(ARGUMENT)
gt3sd = 0
ls3sd = 0
for m in ARGUMENT:
if m > m + (s * 2):
gt3sd +=1
elif m < m - (s * 2):
ls3sd +=1
return(gt3sd,ls3sd)
def AnotherFunction(anumber, anothernumber):
l = np.random.randint(anothernumber, size = anumber)
return(MyFunction(l))
a,b=AnotherFunction( anumber = 1000, anothernumber = 1000)
print('found %d random values greather than 2 * sd and %d less than 2 * sd' % (a, b))
```
---
``` python
from statistics import mean, stdev
import numpy as np
def MyFunction(ARGUMENT):
m = mean(ARGUMENT)
s = stdev(ARGUMENT)
gt3sd = 0
ls3sd = 0
for m in ARGUMENT:
if m > m + (s * 2):
gt3sd += 1
elif m < m - (s * 2):
ls3sd += 1
return gt3sd, ls3sd
def AnotherFunction(anumber, anothernumber):
l = np.random.randint(anothernumber, size=anumber)
return MyFunction(l)
a, b = AnotherFunction(anumber=1000, anothernumber=1000)
print('found %d random values greather than 2STD and %d less than 2STD' % (a, b))
```
---
``` python
from statistics import mean, stdev
import numpy as np
def my_function(value):
m = mean(value)
s = stdev(value)
gt3sd = 0
ls3sd = 0
for m in value:
if m > m + (s * 2):
gt3sd += 1
elif m < m - (s * 2):
ls3sd += 1
return gt3sd, ls3sd
def another_function(highest, size):
l = np.random.randint(highest, size=size)
return my_function(l)
a, b = AnotherFunction(highest=1000, size=1000)
print('found %d random values greather than 2STD and %d less than 2STD' % (a, b))
```
---

[1]
---
# 3. Python packaging :package:
- Setuptools modularizes your projects
- Pytest tests your code
- Sphinx bulds your documentation
---
# Python package
- directory with the package's name
- `__init__.py` file inside the directory
- the actual code
---
# How to use this package?
- Hack sys.path
```
import sys
sys.path.append("/home/user/my_modules")
```
- Make a distributable/installable package
- add `setup.py`
- `pip install -e .`
---
# Pytest
```python
def func(x):
return x + 1
def test_answer():
assert func(4) == 5
```
---
```rst
reStructuredText
-----------------------------------
Write in **bold**, *italic* or `code`
* use
* lists
Code blocks::
a = 1
.. plot::
:include-source:
import matplolib as plt
plt.plot([0, 1, 2])
.. image:: images/my_image.png
`link websites <http://klayout.de/>`_
```
---
```rst
Sphinx
-----------------------------------
.. autofunction:: my_function
.. autoclass:: MyClass
.. automodule:: my_module
:members:
```
---
# `#` markdown title
## `##`subtitle

``` bash
```python
def function(var1, var2):
return var1 + var2
```
```
---
# markdown tables
```bash
order | topic
------ | ----
1 | git
2 | clean code
3 | packaging
```
order | topic
------ | ----
1 | git
2 | clean code
3 | packaging
---
# References
1. [The Art of Readable Code: by Dustin Boswell and Trevor Foucher](http://shop.oreilly.com/product/9780596802301.do)
2. [Software engineering best practices for scientists: Paris Saclay](https://github.com/lightwave-lab/python-workshop.git)
3. [git pro book](https://git-scm.com/book/en/v2)
4. [interesting jupyter notebooks](https://github.com/jupyter/jupyter/wiki/A-gallery-of-interesting-Jupyter-Notebooks)
5. [git cheatsheet](http://cheat.errtheblog.com/s/git)
6. [python notebooks](https://github.com/computerproductivity/python)
---
# Bonus tips
- Choose editor wisely
- vim
- sublime
- atom
- IDEs can be helpful
- Spyder
- PyCharm
- VisualCode
- Linux philosophy:
- provide small programs that do `one` thing well and
- provide mechanisms for joining programs together
- ` ls | grep Python`
---
# Thank you
---
# Summary
1. Git :two_women_holding_hands:
2. Clean code :sparkles:
3. Packaging :package:
{"metaMigratedAt":"2023-06-14T20:20:34.102Z","metaMigratedFrom":"YAML","title":"Build better hardware. Write clean, versioned and tested code","breaks":true,"slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"502c9c70-abff-40e6-8f85-3bd77aafd255\",\"add\":15509,\"del\":5557}]"}