Skip to content

Python Software - Tips

A collection of tips and code examples for analysis with Python. I did not invent them; typically I faced the problem in my work, searched the web and found hints or similar examples.

Use of lambda function to sort a dictionary

We can use a lambda function to apply functions like min, max, sorted, largeq to a dictionary using keys or its values - lambda functions

A good set of inliners for common tasks

Inliners can be used to perform common tasks in a very efficient and elegant way - inliners

A way to access dictionary elements with dot

A fast solution is to use SimpleNamespace. Here is an example

from types import SimpleNamespace
adict = {'one':1, 'two':2}
adotdict = SimpleNamespace(**adict)
print(adotdict.one) 

Alternatives to doing loops in Python

Loops can be handy but also costly and slow if appied to large lists. Python offers three alternatives: 1. Map : map(function, iterable) apply a function to the elements of the list. Returns a list of the same size. 2. Filter : filter(function, iterable) apply a function to select elements from a list. Returns a reduced-size list depending on the selection 3. Reduce : reduce(function, iterable) apply a function iteratively to all elements of the list. Returns a single value.

Examples

x = [1, 2, 3, 4 ,5]
y = map(lambda a : a**2, x)
list(y)

y = filter(lambda a: a>=3, x)
list(y)

y = reduce(lambda a, b: a+b, x)

Using dot notation to python dicts

In python a simple directory is defined as below:

mydict = {'x': [1,2], 'y': [3,4]}
and the data can be access like:
mydict['x']     --> would return [1,2]
mydict['x'][0]  --> would return [1]
However it is often handy to access the data using a dot notation. This can be easily achieved with the code below!
from types import SimpleNamespace
d = dict(x=[1, 2], y=['a', 'b'])
nsd = SimpleNamespace(**d)
nsd                  # namespace(x=[1, 2], y=['a', 'b'])
nsd.x                
nsd.x[0]
vars(nsd)             # to convert back to a normal dictionary

Figures and plotting

Add a second x-scale in graph

fig, ax = plt.subplots(1,1, figsize=(15,8))
width = 1.0
xscale = dflist['ipslot']*b_h_dist
p1 = plt.bar(xscale, dflist['lrip1'], width,)
p2 = plt.bar(xscale, dflist['lrip2'], width, )
p3 = plt.bar(xscale, dflist['lrip5'], width, )
p4 = plt.bar(xscale, dflist['lrip8'], width, )
lrdf.groupby(['z-pos/m','ip']).count()['RFbucketbeam1'].unstack().plot(marker='o', ms=10.5, label='lpc', ax=ax)
plt.ylabel('Long-range encounters')
plt.xlabel('Distance from IP')
plt.title('LHC - Long-range encounters per IP for bunches colliding at IP1/IP5'.format(fno))
plt.legend((p1[0], p2[0], p3[0], p4[0]), ('IP1', 'IP2', 'IP5', 'IP8'))
plt.grid()

ax2 = ax.twiny()
xlow,xmax = ax1.get_xlim()
new_ticklocations = np.arange(int(xlow/b_h_dist),int(xmax/b_h_dist),5)
new_ticklabels = [str(i) for i in new_ticklocations]
ax2.set_xlim(int(xlow/b_h_dist),int(xmax/b_h_dist))
ax2.set_xticks(new_ticklocations)
ax2.set_xticklabels(new_ticklabels)
ax2.xaxis.set_ticks_position('default')
ax2.xaxis.set_label_position('bottom')
ax2.spines['bottom'].set_position(('outward', 36))
ax2.set_xlabel('Distance from IP [m]')
plt.show()
pltsave(fig,'LRencounters.pdf')

Subplots axis array as simple list

In figures with multiple subplots can be created with the command fig,axes = plt.subplots(nrows=2, ncols=2). However this returns a 2D array if ncols or nrows is specified, otherwise an 1D array - single graph. However we oftern need to access the subplots in iteration thorugh a signle list, here is how:

fig, axes = plt.subplots(nrows=2, ncols=2, squeeze=False)
axlist = axes.flatten()
the squeeze option forces plt.subplots to always return a 2D numpy array, which is then converted to an 1D array.


A good tutorial for matplotlib scientific plotting and references therein.