A by example guide to learning and applying Python
By
Edward Bell IEng, MIET, ACIBSE
Practical uses of Python for Engineers
As an Electrical Engineer by background, my interest in Python starts and ends with how can I apply it in practice?
As a new user of Python and someone with very little practical programming experience, I have taken the time to read as many of the tutorials that I could find on the python web site . I would advice anyone trying to learn Python to follow the same route, this tutorial is not intended to directly teach Python or programming but is intended, as it says on the tin, to be a by example guide to practical use of Python for Engineers.
To computer scientists and experienced hackers the examples here may seam over simplified and crude, however after 26 years of working in the Engineering environment, I know from experience that many Engineers need to start with simple code that is logical and where practical sequential in its logic. No doubt my work here will be refined over time.
Let us start with a simple basic calculation an Engineer might have carried out 20 years ago before computers where as abundant as they are today. The average light falling on a work surface (working plane) is measured in Lux.
1 Lux = 1 Lumen / square metre = 0.093 foot candle
The calculation to measure the amount of light from a light fitting (Luminaire) is given by the following formula.
E = N x F x UF __________ A
Where :-
E = the light falling on the working plane in Lux. N = the number of light sources (this will be refined later) F = the light output in lumens per source UF = the utilisation factor or efficiency per fitting or source
There are other factors like LLF (light loss factors), we are however ignoring these at the moment to simplify the examples that follow.
If we ignore everything but the basic calculation and if we use an estimated utilisation factor, we can begin to write a simple form of the calculation in Python. Firstly we need to set a few parameters for the example to be used in the program. We will therefore begin by calculating the number of light fittings based on a single source (1 lamp per fitting). The room dimensions will be based on a room 10m long by 5m wide. From the CIBSE code for interior lighting we can see that the recommended light level for a general office area is 500 lux. As a designer, I personally take this as a guide rather than a fixed value; other people treat this as a minimum. For the moment we can ignore these types of discussion. I am of course for the moment putting aside obstructions and other factors, which would influence the true light level on the working plane.
The formula above will need to be manipulated or transposed to begin the design process, as initially we need to arrive at a ballpark number of fittings for our room. We could in theory set up an iterative computer program to solve the problem, but it would not be as instructive as following the process which I used as a young Design Engineer around 26 years ago.
N = E x A ______ F x UF
The value of F we will use is the approximate output of a 58w T26 tube which is 5200 lumen.
Our first simple program therefore looks like this.
e = 500 a = 5*10 f = 5200 uf = 0.85 n = e*a/f*uf print n
If we enter this code into Python without any sense checking at this stage we get an answer of 3.4. If we carry out the same calculation by hand, we would get 5.66 rounding to 2 significant figures. For those unfamiliar with computer programming the cause here may be a mystery, the error is due to the precedence of the operators as the software processes them. The solution is strait forward; the numerator and denominator need to be enclosed in brackets to ensure that the program calculates these factors first. Those who are running ahead of the script here may be asking why the result is not 4.08? I cannot answer this question directly however I can point out that we need to be aware of how Python is interpreting the data we are feeding into the program. Each of the values with one exception is being treated as an integer. The calculation of two integers results in an integer resultant. Where one or more value is a real value, the result will also be a real number. The program also interprets the sum of 50/5200 differently to our pocket calculators. I will leave it to someone more skilled in computer science to explain why the computer arrives at 3.4 precisely; as I was not able to arrive at the same answer myself when using the calculator and various combinations of the formula in Python. For the Engineer, it is more important to be able get the right answer and to reproduce the answer by hand if needed.
So our calculation now reads as follows :-
e = 500 a = 5*10 f = 5200.0 uf = 0.85 n = (e*a)/(f*uf) print n
The output when running this in Python at present is the rather unhelpful sum of 5.65610859729. We can of course interpret this value ourselves and mentally round the value up or down, however the purpose of our exercise is practice computer programming, so let’s change the program to round the output value for us. There are several alternatives, but Python v2.5 has the inbuilt function round, which rounds a real value to the nearest whole integer, so we will use this in our program.
The calculation now looks like this:-
e = 500 a = 5*10 f = 5200.0 uf = 0.85 n = (e*a)/(f*uf) print round(n)
We now get the more useful output value of 6.0.; we will ignore at this stage the fact that this is output as a real number where we perhaps would prefer an integer.
At this stage it makes sense to alter our program to accept values for the variables from the user. We will leave the utilisation value alone at this stage as it has no impact on the exercise we are trying to perform. I will use the input command, to get the variables from the user, our program will then look like this:-
e = input("Enter the light level required in Lux ") l = input("Enter the length of the room ") w = input("Enter the width of the room ") a = l*w f = input("Enter the bare lamp lumens per fitting ") uf = 0.85 n = (e*a)/(f*uf) print round(n)
If we run this program, we see that the user is now asked to enter the various values apart from the utilisation factor that make up the basic lumen calculation. We can improve on the presentation of the information to the user but for the moment we will put that aside in favour of getting a little more basic work done.
I will also introduce some Python programming conventions in the next stage and add an information header to our basic program.
So having estimated the number of light fittings, we can now move onto the more useful task of working out the actual light levels from a luminaire onto our working plane.
Our program now looks like this:-
# Lumen # # A basic light level calculation program # # Created as part of a tutorial for assisting Engineers # to learn programming with Python # # Copyright (c) 2006 to Ted Bell ted dot bell at lineone dot net # Distributed free and without warranty of any kind # # Begin by estimating the number of fittings required. e = input("Enter the light level required in Lux ") l = input("Enter the length of the room ") w = input("Enter the width of the room ") a = l*w f = input("Enter the bare lamp lumens per fitting ") uf = 0.85 # we can amend this to generate a number at a later stage. n = (e*a)/(f*uf) print round(n) # Now calculate the actual light level. N = input("Enter actual number of luminaires to be used ") # we can use capital n here as Python treats n and N as two values. llf = input("Enter light loss factor ") # we can revisit this at a later stage and break it down into parts. E = (N*f*uf*llf)/a # Again we can use capital E here to distinguish it. print E
Before moving on much further I need to cover the topic of the room index. The room index is effectively a correction factor for the size and working plan height of the space we are tying to measure. The room index is not valid in long rooms like corridors and in very small room or odd shaped rooms. We can look at such rooms later with the point method of calculation for now I will set out the room index method. I should also note that you will need manufacturers data showing utilisation values for the fitting you intend to use, the original IES (Illuminating Engineering Society) Guide did provide generic utilisation values for standard fittings but these types of data have fallen out of favour in recent years.
I = Room index L = Length W = Width Hm = Hieght fropm working plan to ceiling A = area (L x W) I = (L x W)/(Hm x (L x W))
Our program is now beginning to provide some sort of useful information, but it is not very user friendly. The next stage is to begin to incorporate some of the GUI look and feel that we have all become familiar with in modern day applications. To do this we will make use of an application known as wxPython. The wxPython web site provides guidance on installation and on how to use the application. I have also referred to the wxPython wiki site
We now need to build a basic frame onto which we can place the individual elements that make up our program. The attached program creats a basic form using forms and the sizer object in wxPython.
# Lumen # # A basic light level calculation program # # Created as part of a tutorial for assisting Engineers # to learn programming with Python # # Copyright (c) 2006 to Ted Bell edward at edwardbellconsulting dot co dot uk # Distributed free and without warranty of any kind # import wx # This allows us to use frames in windows e = 1 # constants set up for testing purposes only l = 1 # I may need to start with some default values w = 1 a = l*w f = 1 uf = 0.85 # amend this to a calculation at a later stage. n = (e*a)/(f*uf) class MyMenu(wx.Frame): # creat the frame def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title='Lumen', pos=(350,200), size=wx.Size(450, 150)) self.SetIcon(wx.Icon('bike.ico', wx.BITMAP_TYPE_ICO)) # adding a distinctive icon is optional menubar = wx.MenuBar() # add the menu bar file = wx.Menu() edit = wx.Menu() help = wx.Menu() file.Append(101, '&Open', 'Open a new document ') # add standard menu items file.Append(102, '&Save', 'Save the document ') file.AppendSeparator() quit = wx.MenuItem(file, 105, '&Quit\tCtrl+Q', 'Quit the application') file.AppendItem(quit) self.Bind(wx.EVT_MENU, self.OnQuit, id=105 ) # provide an exit menubar.Append(file, '&File') menubar.Append(edit, '&Edit') menubar.Append(help, '&Help') self.SetMenuBar(menubar) sizer = wx.BoxSizer(wx.VERTICAL) # set up a sizer to size the window components gs = wx.GridSizer(4, 4, 20, 5) # creat a form gs.AddMany([(wx.StaticText(self, -1, 'Length'), 1, wx.TE_CENTRE), (wx.TextCtrl(self, l), 1, wx.EXPAND), # I need to collect the input from these fields (wx.StaticText(self, -1, 'Width'), 1, wx.TE_CENTRE), (wx.TextCtrl(self, w), 1, wx.EXPAND), (wx.StaticText(self, -1, 'Required Level in Lux'), 1, wx.EXPAND), (wx.TextCtrl(self, e), 2, wx.EXPAND), (wx.StaticText(self, -1, 'Bare Lamp Lumens'), 1, wx.EXPAND), (wx.TextCtrl(self, f), 2, wx.EXPAND), (wx.Button(self, 10, 'Calculate'), 1, wx.EXPAND), #(wx.EVT_BUTTON(self, 10, self.OnClick), 1, wx.EXPAND), (wx.TextCtrl(self, n), 1, wx.TE_LEFT) ]) # I really need to display text here only sizer.Add(gs, 1, 1, wx.EXPAND) self.SetSizer(sizer) self.Centre() def OnQuit(self, event): self.Close() #def OnClick(self,event): #self.Close() #remember to add something here class MyApp(wx.App): def OnInit(self): frame = MyMenu(None, -1, 'lumen.py' ) frame.Show(True) return True app = MyApp(0) app.MainLoop() # Begin by estimating the number of fittings required. print round(n) # Now calculate the actual light level. # N = input("Enter actual number of luminaires to be used ") # we can use capital n here as Python treats n and N as two values. # llf = input("Enter light loss factor ") # we can revisit this at a later stage and break it down into parts. # E = (N*f*uf*llf)/a # Again we can use capital E here to distinguish it. # print E # if __name__ == '__main__': # main()
Lumen_4.py #this is as far as I got, I am still trying to get my head around trying to convert to a GUI version of Lumen_3.py above. I am not sure how to link the file bike.ico so you will need to download this separately to avoid the error message.
The next stage is to take the form and take values entered by the user with perhaps some default values. we need to ensure that division by zero is not possible, some of the input values will in the future be real numbers e.g., the utilization factor. Some will remain as integers e.g., the number of fittings and or the number of lamps. The length, width and much later height will need to accept real values at some stage.
For anyone thinking of offering help, I am currently stuck on the wxPython form, I am not sure how to take in values or how to initiate the calculation. Object programming is not something I find easy. Ted
I have checked the spelling against the Oxford English Dictionary.
To Do Sort out the sizer so the form works, add some code to take input values from the form.
Under construction
Comments are welcome
Please add them below here.