Skip to content
Snippets Groups Projects
Commit f8f0927a authored by cprutean's avatar cprutean
Browse files

Update 2 files

- /CourseNotes/bugs.ipynb
- /Checkpoints/Checkpoint6.ipynb
parent 0f12a0e9
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:51574bca tags:
## Checkpoint 6
### Aim
To write a Python program to calculate the volume of molecules made up of overlapping spherical atoms; it is also an example in using OOP to simpify the task.
To write a Python program to calculate the volume of molecules made up of overlapping spherical atoms; it is also an example in using OOP to simpify the task. Don't get frightened, for this checkpoint you will be given part of the code to help you progress (***this also simulates pretty well how multi-person software development works***).
## Monte Carlo estimate of π
Consider a circle of radius r within a square of side 2r$\times$2r as shown in the figure below.
![dynamicpng-width_300.png](dynamicpng-width_300.png)
### Calculation of π by estimation of area.
If we randomly pick N points evenly distributed within the square and N$_i$ of them are inside the circle, then an estimate of the area of the circle A is given by the fraction falling inside the circle multiplied by the area of the square, so
$$ A=4r^ 2 \frac{N_i}{N} $$
Noting that A=$\pi r^2$, we get an estimate for the value of π given by,
$$ π≈4 \frac{N_i}{N} $$
So provided the selection of points is evely distributed over the whole square, than as N becomes large you will get a good estimate for $\pi$. This is the basis of Monte Carlo integration and can be used to estimate the internal area of any closed object.
See an example Python code that uses the random.uniform() function to form random points:
- Code example to calculate $\pi$ [here](../CodeExamples/PiExample.ipynb)
Take a look at this and experiment, you will find that for N>200,000 you get a reasonable estimate for $\pi$, and that as N gets larger the estimate gets better.
This is clearly a "very bad" way to calcuate π but is very useful for finding the area of overlapping objects in two-dimensions as shown in the figure below; which is otherwise analytically tricky.
![dynamicpng-width_250.png](dynamicpng-width_250.png)
This can also easily be extended to three-dimensions so for example overlapping spheres as shown below.
![dynamicpng-width_2502.png](dynamicpng-width_2502.png)
Here the method is to form a bounding box of dimensions Vb=a×b×c that totally encloses the object. If N points are in the bounding box and N$_i$ are inside the object, then the volume of the object is simply given by
$$ V_0=V_b \frac{N_i}{N} $$
This technique is used in computer simulations of molecules to calculate the volume of molecules that are made up of overlapping spherical atoms.
#### Code Structure
This is rather tricky program but it can be vastly simplied by use of OOP; the suggested structure is
1. Form an Atom class by extending the Vector3d class given by Vector3d Class
2. The Atom class should add an extra internal variable radius and have a boolean method isInside(v) which takes argument v being a Vector3d and returns True if v is inside the atom. (Note the distance(v) method of Vector3d is useful here.)
3. Form a Molecule class that has a list of objects of type Atom and a boolean method isInside(v), which takes argument v being a Vector3d and returns True if v is inside the molecule.
- You also need to consider how to read in the location of the atoms; this is similar to Checkpoint 4.
4. Form a BoundingBox class where the constructor takes a populated Molecule and finds and stores internally the minima / maxima of the box round the molecule (you need 6 floats). This class should have two methods:
- volume() that gets the volume of the box.
- getRandomPoint() which should return a random Vector3d that is randomly distributed inside the box.
(This is the most “messy” bit of the code to write.)
If you have this structure, then what your main program has to do is:
- Ask for the file containing the Atom data and read this into a Molecule.
- Construct a BoundingBox from the Molecule
- Go round a while loop,
- Getting a random Vector3d from the BoundingBox
- Testing if it isInside() the Molecule and incrementing a counter if it is.
- Finally calculating the estimate for the Molecule volume and printing it out.
It is also useful to monitor the progress of the estimate as was done in the example code for estimation of π to check how the integration is going.
#### Format of Data
There are two data files suppied (in the current directory, so they can be read in and executed directly upon here), these being :
- [oxygen.data](oxygen.data) : single oxygen atom
- [water.data](water.data) : water molecule)
each consists of a comma delimited CSV file with one atom per line in the format,
Name , r , x , y , z
with comment lines delimited by # being the same format as coded in [Parsing Input](../CourseNotes/ParsingInput.ipynb) and used in [Checkpoint 4](Checkpoint4.ipynb).
#### Computing Task
Write a Python program based on the above structure to
1. Read in the data file defining the atom locations.
2. Prompt the user for the number of points to run in the calculation.
3. Calculate the volume of the molecule using Monte Carlo integration and output the final value.
4. Optionally plot a graph of the convergence of the algorithm, being the estimate against number of points. The graph should have 100 data points at regular intervals, see Pi example for how to to this easily.
5. Test your code with a single oxygen atom and with water, see “Hint” for expected values.
5. Test your code with a single oxygen atom and with water. ***For a pass, only the atom is strictly necessary to run.***
> #### Note
> The volume of a single oxygen atom of radius 1.4 \r{A} is 11.494 \r{A}$^3$. The volume of water is $\approx$ 15.5 \r{A}$^3$. Use these values to check your results before calling a demonstrator.
6. Have another careful read of [final weekly task](../WeeklyTasks/Week6.ipynb).
%% Cell type:code id:9376506d tags:
``` python
""""
A more developed Vector class for simple 3d vectors
"""
import math
import random
class Vector3d(object):
"""
Simple vector 3d class
"""
def __init__(self, x, y, z):
"""
Constructor to form a vector
"""
self.x = float(x)
self.y = float(y)
self.z = float(z)
def __str__(self):
"""
Method to format a vector as a string (implments str())
"""
return "[" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + "]"
def copy(self):
"""
Method to return a copy of current vector
"""
return Vector3d(self.x,self.y,self.z)
def magnitude(self):
"""
Return the magnitude
"""
return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
def distance(self,b):
"""
Distance from self to vector b
"""
dx = self.x - b.x
dy = self.y - b.y
dz = self.z - b.z
return math.sqrt(dx*dx + dy*dy + dz*dz)
def normalise(self):
"""
Normalise current vector so its magnitude is 1.0 (unit vector)
"""
mag = self.magnitude()
if mag != 0.0 : # if not already zero
self.x /= mag # dveive throgh by mag
self.y /= mag
self.z /= mag
def add(self,b):
"""
Add a vector b to self and return a new vector.
"""
x = self.x + b.x
y = self.y + b.y
z = self.z + b.z
return Vector3d(x,y,z)
def addTo(self,b):
"""
Add a vector b to self in place.
"""
self.x += b.x
self.y += b.y
self.z += b.z
def dot(self,b):
"""
Form dot product between self and vector b
"""
return self.x*b.x + self.y*b.y + self.z*b.z
def cross(self,b):
"""
Form cross product between self and vector b.
"""
x = self.y*b.z - self.z*b.y
y = self.z*b.x - self.x*b.z
z = self.x*b.y - self.y*b.x
return Vector3d(x,y,z)
def main():
"""
Simple test program to test the vectors
"""
a = Vector3d(1,2,3)
b = Vector3d(4,5,6)
print("Magnitde of a is " + str(a.magnitude()))
c = a.cross(b) # Form cross product
#
# the str() function call the __str__(self) method
print("Cross product of a x b is : " + str(c))
#main()
```
%% Cell type:code id:e0aad9ca tags:
``` python
### Atom class
class Atom(Vector3d):
"""
The Atom class to extends the Vector3d that hold position
"""
def __init__(self,x,y,z,r):
"""
Constructor to form an atom with x,y,z,r parameters
"""
# Your code here
def __str__(self):
"""
Implemnts str()
"""
# Your code here
def isInside(self,v):
"""
isInside method, returns True of v in inside atom
"""
# Your code here
```
%% Cell type:code id:fccc8a4e tags:
``` python
### Molecule class
class Molecule(list):
"""
Molecule, being a list to hold Atoms
"""
def __init__(self,*args):
"""
Constructor to form a Molecule with optional arguments each one assumed to be an Atom
"""
list.__init__(self) # Init underlying list
for a in args: # Append any args to list
self.append(a)
def __str__(self):
""" Format string of all atoms
"""
s = ""
for a in self:
s += str(a) + "\n"
return s
def inInside(self, v):
"""
Method to check if vector is inside moleule.
"""
# Your code here
return False # if here then outside
def fromFile(self,file):
"""
Read Atoms from a file
"""
# Your code here
```
%% Cell type:code id:663fe126 tags:
``` python
### BoundingBox class
class BoundingBox(object):
"""
Class to define a bounding box class round the molecule
"""
def __init__(self, molecule):
"""
The Constructor, which takes a molecule
"""
self.xmin = float("inf") # Initially set limits to +/- infty
self.ymin = float("inf")
self.zmin = float("inf")
self.xmax = float("-inf")
self.ymax = float("-inf")
self.zmax = float("-inf")
for a in molecule: # update limits for each atom in molecule
# Your code here
def volume(self):
"""
Get the volume of the box
"""
# Your code here
def getRandomPoint(self):
"""
Get a random point in the bounding box as a Vector3d.
"""
# Your code here
```
%% Cell type:code id:3e01a08e tags:
``` python
def main():
""" Main program to do the simulation"
"""
file = open(str(input("File : ")),"r") # Open file
mol = Molecule().fromFile(file) # Read in molecule
print("Molecule is \n" + str(mol)) # Print out info
box = BoundingBox(mol) # Form Bounding box
maxpoint = float(input("Number of points : ")) # Max number of points
plotInterval = maxpoint/100 # Plot internal for monitoring
# Your code here
while p < maxpoint: # Loop counting internal points
# Your code here
print("Final estimate is : " + str(estimate))
plt.plot(xData,yData) # Draw graph (with default plot)
plt.ylim(0.9*estimate,1.1*estimate)
plt.title("Estimate of volume for " + str(maxpoint) + " points.")
plt.show()
main()
```
......
%% Cell type:markdown id: tags:
%% Cell type:markdown id:d6bdf840 tags:
# Finding bugs
As you will quickly realise, find the *Bug*, is the pain of all
programmers' existence.
Computers are inanimate pieces of electronics with no inherent
intelligence or malice; they do “exactly” what *you* tell them to do,
*wrong though it may be*!
A non-working program means **you** have made a mistake in it, it's not
the computer’s fault!
The computer is also utterly pedantic, a **single** spelling mistake,
missing Capital, lost in your code is a *bug*: it will fail, either
straight away or at some random time in the future!
Trying to find “bugs” in someone’s code is **really hard**. Staff and TA
on this course have experience in *hunting for bugs*, sometimes a decade
of experience, but that does not mean that we can always find them or
fix them. There will be times where we will get you to:
- Rewrite in a alternative / simpler way
> ### Highlight
> The syntax (colour) highlighting help here; if the colours
>“look wrong” then you have a syntax error!. This will **not** find all
> the errors, but do not try and run any program until the colour
>highlighting is correct.
Editors (Spider/VSCode/PyCharm/etc.) will also try and “match brackets”. The corresponding “left”
bracket will flash when you insert the “right” one. This is not
foolproof, but a good indication.
There are *three* basic types of *bugs* that you will encounter; some
examples, and suggestions how to fix them follow:
## Syntax Errors
There is something in you code that is not a legal statement, in this
case will fail to even start running your program and you will get a
*Trackback* that typically looks like:
File "BugTest.py", line 7
for i in range(0,10)
^
SyntaxError: invalid syntax
This will give you the name of the file, the line number, which it will
print with $\wedge$ where it *thinks* the error has occured; here it is
a missing ":" in the loop; very common error.
Here there too many possible errors to enumerate, but the most
common are:
1. Indentation of someething does not make sense *or* an isolated line in the code
has the wrong indenatation. ```Python``` is very pedantic here, be very careful
that there is not an extra space before the start of a line.
> The editor usually sorts out tab-space errors by
aligning code correctly; however if you “cut-and-paste” from either
the terminal window or a web-page your are likely to get extra
spaces or mixed tab-spaces so even if the line “looks ok” in the
editor its indent level may be wrong.
> If this happens:
1. delete all white-space (spaces/tabs)
2. re-indent to the corect level with spaces (or in tabs)
2. This almost always means that you have missed the closing at the end
of a string and has ran off the end-of-line looking for it.
Here the editor syntax highlighting will find this.
3. , almost always means that you have forgotten to close a style
comment and all your whole progam has been treated as a comment.
4. , random “catch all” for for *something wrong*, look for;
- unmatched brakets in arithmetic expressions
- missing sign in assignments,
- , or statements with no logical test, or missplaced
- stray random characters on the line etc.
se will fail at the *first* syntax error and will *not* look at the
rest of the program so you have to fix these errors “one-at-a-time”.
Note that will attempt to identify where the error occured, but what it
really does it identify when it realises that it has **“gone wrong”**,
so the actual bug may be on previous lines(s).
## Run-Time Errors
These errors occur when the program is syntactically correct, but
something is wrong when the program is actually ran. does very little
checking before the program runs so in pratcice this is the most common
error you will run into. Again you get a *Traceback*, with file and line
number, so for example
Traceback (most recent call last):
File "BugTest.py", line 13, in <module>
main()
File "BugTest.py", line 9, in main
total += math.coss(math.pi*i/10)
AttributeError: 'module' object has no attribute 'coss'
Here you have tried to call a function which does not exist. Here the
most common problem is you have spelt it wrong! (as in this case), or
forgotten to the reqiured module. This is by far the most common error.
Other common errors are:
1. , mean if a list has elements you have tried to access a element
outwith the range $0\rightarrow n-1$. Remember the index start at 0!
2. , this is an obscure one, but what it means is that you have tried
to access a list element with the syntax when the object is *not* a
list.
3. various errors where the wrong type has been found, most common are:
- trying to index a list element with a ,
- passing a to a function that takes a single or value,
- trying to print a , or without converting to a .
Here the list is endless. This is where the convenient auto-typing
in gets it own back; this can be the source of almost endless bugs!
4. rather missleading error, means that the specifed cannot be found,
but is also the error you get if or fails to convert a string.
5. , again complex error for simple problem, here it has found the
variable or the right hand side of an equation before it has been
declared, often a simple spelling error.
er Your program will crash on the *first* error, as you have to fix them
one-at-a-time, also remember a single execution of your program will
*only* test the lines of code that your actually execute.
This means that any of the above *bugs* could be lurking in the sections
of the that did not get executed.
## Working program, wrong results
The *fun one*, sometimes know as *bugs of the third kind*, where you
program run without any errors but either just sits there (perhaps in an
inifite loop), or worse still runs perfectly but gives wrong results!
### Program not responding
If there is no response for about 10 seconds then your program is either
“waiting-for-input” or stuck in an infite loop; it could also be doing
something very ineffeicent, but unlikely for simple programs. To halt
the program type , this will force crash your program and give a
*Traceback* to where it was.
1. If waiting for input check that the or are not inside an uninteded
loop. This type of bug is usually easy.
Graphics window Also remember that matplotlib displays a graph and
then suspends the program until you close the window, so what looks
like a “stuck” program may simply be waiting for *you* to close the
plot window…
In this case does not help either; you *must* close the plot window.
2. If infinite loop look for
- misspelt termination variable (updating the wrong variable as
you go round the loop),
- termination at wrong indentation level, so the code that updates
the termination varaible never gets executed (this is a very
common error and is difficult to find!)
- whole body of the loop at wrong indentation level, so you have a
null loop.
- variables becoming , note this will *not* crash your porgram.
3. If you can spot it by just looking at the code, add a to print out
the value of the key variables to try and get insight to what is
happening.
debuggers Puting in statements is the “old-way” of debugging, the
correct and modern way is to use an interactice debugger of profile
tool; these allow inspection of variables, setting break points etc,
but are either syntactically difficult to operate
or are part of an *Integrated Development Environment* (IDE),
in both cases they are rather heavyweight and difficult to learn,
and for simple programs,most novice programmers initially stick with
statements.
### Working Program – Wrong Results
This is the real *fun* one! If the program produces:
1. **Utter Rubbish**: For example a *constant* no matter what input you
supply. The most likely problem is a program bug as discussed above.
For example forgetting to assign a value to a variable, mistake in a
loop which means that it never get executed etc. Search for bugs as
described in the *Runtime Errors* above.
2. **Almost Right Results**: For example the right results with some
data, wrong for others. This is not likely to be simple coding
error, much more likely to be an error in the logic of the code, for
example some conditional statement is wrong. This is tough to find.
There is also the worse-case synario, you have the underlying
mathematics and/or physics of the calculation wrong. Then no matter
how much you “play” with the program it will still *always* produce
wrong results!
save Finally when you do make changes to the source code with `emacs`
remember to use *Save Buffer* to update the source file on disk. I would
prefer not to think about how many times I have failed to do one or
other of these!
## Problems with the Systems
Big computer system do sometimes “go wrong”. This usual symptom is they
become *very slow* to respond or *stop* responding all together. This
can be caused by anything from too many people trying to run big
programs to a hardware fault on the server. If this happens:
1. Stop trying to do anything. Trying to open a new window or “playing”
with the mouse will only make things worse. If however you are
running a program that may have “looped” it may be *you* causing the
problem. Try stopping it with `Ctrl-C` as discussed above or using
the *Kill* option to stop the terminal window.
2. If nothing improves within about 30 secs:
1. Call a demonstrator or see
2. If there is nobody else the laboratory try and *Exit* the Window
Manager, (try and log-off). If this also fails, leave the system
alone, **do not** switch-off but leave a note on the terminal.
## Myths, General Miss-conceptions and Classic Excuses
Round computing there are a whole series of *myths*, *miss-conceptions*
and *total rubbish*, a few of which are:
1. The computer does “*what you tell it*” it is a deterministic, but
very pedantic, machine *without* intelligence. It does *not* have a
personal vendetta against you, despite what you may feel when all
the other students programs run perfectly and yours completely
fails!
2. Repeating the same *execute* many times “*in case the computer made
a mistake*” just wastes your time and add to your frustration and
stress levels. You *will* get the same answer each time. Your
program will *not* magically start working.
3. Recipes on *StackOverflow* are *correct*, no, they often for
different version of or different environments, but also sometime
are just *totally wrong!*
4. The chance of the “*computer being wrong*”, that is *you* finding a
mistake in the *compiler* or system is about the same as you been
struck by lightening (at least twice) on the way home! All
non-trivial pieces of software do have “bugs” but the bugs in the
language are likely to be so obscure that none of the simple
programs that you will write will show them up.
5. The *PC urban myth* of “*the program getting corrupted on disk*
would result on the whole computer system crashing with lots of
“panic” messages. It would *not* just effect your program.
6. The “*the computer lost my program*” is just possible, but it would
not loose *just* yours. Lost files mean a computer hard disc fault
which typically looses many files with lots of “panic” messages. In
this unlikely event we are able to “restore” your files to the state
they were in “yesterday evening”. This has only happened once in 8
years of running the CP-Lab, so it is very unlikely. If a file
vanishes from the system it almost always means that *you deleted
it*.
7. The “*somebody hacked into my account and changed my files*” is very
unlikely *unless* you gave them your password; in which case tough!
There is a finite chance of a machine being “hacked into” but if
somebody does succeed in doing this is is rather unlikely they would
modify one persons file when there is a whole system to muck up!
Experimental observation of the probability of “*occurances*” 4,5, & 6
suggest a relation of the form $\exp(-\lambda\Delta T^2)$ where
$\Delta T$ is the time (in hours) left before a programming submission
deadline is due and $\lambda$ is the *importance coefficienet* that
depends on the percentage weight allocated to the impending submission.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment