# Matplotlib figures generated in external figure windows
# %matplotlib qt
# Matplotlib figures generated in the notebook inline with the rest of the script
%matplotlib inline
import numpy as np # Import NumPy for arrays and basic linear algebra
import matplotlib.pyplot as plt # Import PyPlot for basic plotting.
import matplotlib as mpl # Import Matplotlib for advanced plotting.
from mpl_toolkits.mplot3d import Axes3D # Import Matplotlib 3D Plots
Software is a balance of code efficiency and performance, hence the developer of Python makes the following point:
“At some point, you end up with one little piece of your system, as a whole, where you end up spending all your time. If you write that just as a sort of simple-minded Python loop, at some point you will see that that is the bottleneck in your system. It is usually much more effective to take that one piece and replace that one function or module with a little bit of code you wrote in C or C++ rather than rewriting your entire system in a faster language, because for most of what you’re doing, the speed of the language is irrelevant.” - Guido van Rossum
Good software is not designed, fabricated and distrubted. It is grown over time using careful planning to maintain a healthy developement environment. Hene, code is continuously in a state of flux and must be tested regularly to ensure quality. The procedure for developing code is as follows:
Make it work in the easiest, most readable way.
Test it.
If necessary, optimize the code.
Test it, again.
Compiled languages catch many syntax errors early, whereas scripting languages only detect these errors at run-time. Compliers do not detect database errors, within large numerical arrays, and they do not detect logistical errors in an interactive application. Therefore, the only way to truely maximize software quality is to implement unit testing (steps 2. and 4. above), and integration testing.
Finally, there is no correct programming language for all applications. Good applications are written using multiple programming languages, each with complimentary attributes as shown below:
Every idea starts out as a sketch. Start by sequentially proving the concept in a script that is broken down into cells.
IPython should be installed using the following steps.
Launch the IPython Notebook by calling “ipython -notebook” in the terminal. It is recomended that the following code is run at the beginning of all IPython notebooks:
Let’s compare some plotting tools: ### Matplotlib
import skrf as rf
from skrf import plotting
warning: data module didnt load. dont worry about it.
WARNING: pyvisa not installed, virtual instruments will not be available
sweep = np.linspace(5/4*np.pi,7/4*np.pi, 10)
x,y = 0.7*np.cos(sweep), 0.7*np.sin(sweep)
ax = plt.subplot(1, 1, 1)
plotting.smith(smithR=1, chart_type='z', draw_labels=True, border=False, ax=ax)
ax.scatter(-0.5, 0.5, c='b', s=500)
ax.scatter(0.5, 0.5, c='b', s=500)
ax.plot(x,y)
[<matplotlib.lines.Line2D at 0x10a427cc0>]
import plotly
plotly.plotly.sign_in("DylanBespalko", "q76nbogdwh")
x = np.arange(0.0, 20.0, 0.1)
y = 4/3*np.sin(x) + 1/3*np.sin(3*x)
trace0 = plotly.graph_objs.Scatter(x=x,y=y, name="Sin")
plotly.plotly.iplot([trace0])
import bokeh.plotting
bokeh.plotting.output_notebook()
# create a new plot with a a datetime axis type
TOOLS = "hover,crosshair,pan,wheel_zoom,box_zoom,reset,save,box_select,lasso_select"
p = bokeh.plotting.figure(tools=TOOLS, width=800, height=350)
# add renderers
p.scatter(x, y)
# NEW: customize by setting attributes
p.title = "Fourier Series Square-Wave Approximation"
p.legend.orientation = "top_left"
p.grid.grid_line_alpha=0
p.xaxis.axis_label = 'Time [s]'
p.yaxis.axis_label = 'Amplitude'
p.ygrid.band_fill_color="olive"
p.ygrid.band_fill_alpha = 0.1
# show the results
bokeh.plotting.show(p)
Now that idea is clear, it needs to be implemented in software using an interactive design environment (IDE). Copy the code from the IPyhhon notebook into a well-structured object-oriented software design.
Write the underlying logic of the software in a self-contained command-line program with an externally configurable API.
Write the Delegate to connect the View and the Model in both directions.
While a compiler or IDE may catch simple errors, they can not catch run-time errors which are more predominant in math and science applications that use data containers (arrays). Therefore testing is essential for catching most bugs in the software. Two types of testing are needed:
Unit-testing is useful for testing each component of the software in isolation. Unit-tests can be run interactively inside PyCharm.
Integration-testing is used to test cross-component interactions that are not covered in individual unit-tests. They are a final test certification that is performed under realistic operating conditions.
Do not optimize your software unless you need to. Only optimize a mature solution and only optimize where needed by profiling the software.
If additional performance is desired, there are multiple solutions for optimizing the performance of the software. The following table presents several methods organized left-to-right from easiest-to-hardest effort and slowest-to-fastest performance
Strategy | Vectorization | Multi-Processing | Numba | Cython | Write C++ |
---|---|---|---|---|---|
Methodology | Use NumPy array operations to replace for loops. | Use Multi-Processing to perform specific tasks in parallel. | Just-In-Time (JIT) compile code during first function call using static data types. | Generate C-Code and compile it using static data types. | Re-write code in C++ |
Process |
|
|
|
|
|
Generally speaking, there are two types of optimization.
Vectorization with NumPy uses statically-typed data arrays, hence it is unlikely that Cython compilation will optimize a process that is heavily implemented in NumPy. Cython is used to optimize loops that cannot be vectorized and can be combined with NumPy arrays. Hence, NumPy and Cython should cover most processing-bounded issues, while I/O bounded issues are solved using multi-processing.
Repeat Step 2. to enusre the optimized software has the same functionality as the origional code.