a=9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
print(a)
print(type (a))
b=a+1
print(b)
print(type (a))

a=99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
a = a*2
a = a/2
print(a)
print('The type of "a" has been changed to {} this is called :'.format(type(a)))
print(' "Operator overloading" ')

# Now we define b as we first defined a
b=99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
print(b)

print(' "a" is equal to {}'.format(a))
print(' "b" is equal to {}'.format(b))
print('Is "a" the same as "b" ? the answer is: {0}'.format(a == b))
print('the type of "a" is {0}, and of "b" is {1}'.format(type(a),type(b)))

b /= 3
print('Dividing a long integer by 3 gives: {0}'.format(a))
print(type(a))
b *= 3
print('Multyplying the result by 3 gives: {0}'.format(a))
print(type(a))

print('the type of "a" is {0}, the type of "b" is {1}'.format(type(a),type(b)))
print(a-b)
c = a - b
print('The difference "a" minus "b" is {0}, and its type is {1}'.format(c,type(c)))


# As we have int the lenght can be as long as one can possibly imagine
# but it there is change of type to float this is no more possible
#b=a
b *= 10
print(b)
print(type(b))
print(id(b))


import sys
sys.float_info


"""
Explanation: Florilège des "Type" de base rencontrés dans Python
Table of Types to be seen in this lecture


Numbers (float and int)
Chains (str)
Lists
Dictionnaries
Tuples
Files


Integrated objects are almost always more optimized than any of the structures you may invent, so using existing object types is highly recommended.
1) The numbers
|Name | Extension|
|-----|----------|
| Int | Long Integer, of illimited size |
| Float | Floating point numbers comprised between -1e+308 and 1e+308 |
|   | The minimum is  2.2250738585072014e-308 |
|   | The maximum is  1.7976931348623157e+308 |
Some usual operations on numbers

|Operation | Interpretation|
|-----|----------|
| a += b | a = a + b |
| a -= b | a = a - b |
| a *= b | a = a * b |
| a /= b | a = a / b |
1.1) Introduction to int and float
End of explanation
"""


s1 = "\n"
print('Hello' + s1 + 'World !')

# This is the traditionnal way for formating strings
situation="a parot is %s" % 'dead' # Note that a str 'situation' has been defined
print(situation)

# This is more modern and practical way, no need to declare any new str 
print('a parot is {}'.format('dead'))

'a parot is %s' % 'dead'

"mia" in "mama-mia" 

s2='1234'
for x in s2:
    print(x)
    #x=int(x) 
    #otherwise x is stays as a string
    print(type(x))

s2 = range(1,4)
for x in s2:
    print(x)
    print(type(x))

"""
Explanation: 1.2) The Floating Point Accuracy


If  there   is  no  integer  p  such    that    x * (2 ** p)    is  a   whole   number, then    internal    representation  is  always  an  approximaMon
I Suggest   that test   equality    of  floats  should not use exact comparison


~~~ python
    x == y
    # Should be replaced by:
    abs(x-y) < 0.0001 # Is a precision of 1/10000 is enough
~~~


Why    does    print(0.1)  return  0.1, if not exact?  (Python designers   set it  up  this way    to automatically round)


2) The Chain of characters (str)
It is the way we use to store character data. The chains in Python are non-modificable  (immutable instances )of characters. These are sequence objects.
Some usual operations on Chains

|Operation | Interpretation|
|-----|----------|
| s1 = "" | Empty chain |
| s1 = "\n" | Carriage return |
| s2 = "This is ISEP" | Double quote |
| bloc = """...""" | Triple quote is a bloc |
| s1 + s2, s2 * 3 | Concatenation, Repetition |
| s1[i],len(s2) | Index, Lenght |
|s[start:end] | items start through end-1 |
|s[start:]    | items start through the rest of the array |
|s[:end]      | items from the beginning through end-1 |
|s[:]         | a copy of the whole array |
|"a parot is %s" % 'dead'| String formating |
| for x in s2, "mia" in "mama-mia" | Iteration, Substring Searches |
End of explanation
"""


s='sausage'
# Indexing
#First element
print(s[0])
#Last element, same as s[len(s)-1]
print(s[-1])
# Extraction
# from index 1 to 3 not included
print(s[1:3])
# from index 1 to the end
print(s[1:])
# from index 0 to the last element not included
print(s[:-1])

"""
Explanation: 2.1) Indexing the chain
<div class="highlight"><pre> <span class="o">+---+---+---+---+---+---+---+</span>
 <span class="o">|</span> <span class="n">S</span> <span class="o">|</span> <span class="n">A</span> <span class="o">|</span> <span class="n">U</span> <span class="o">|</span> <span class="n">S</span> <span class="o">|</span> <span class="n">A</span> <span class="o">|</span> <span class="n">G</span> <span class="o">|</span> <span class="n">E</span> <span class="o">|</span>
 <span class="o">+---+---+---+---+---+---+---+</span>
 <span class="mi">0</span>   <span class="mi">1</span>   <span class="mi">2</span>   <span class="mi">3</span>   <span class="mi">4</span>   <span class="mi">5</span>   <span class="mi">6</span>   <span class="mi">7</span>
<span class="o">-</span><span class="mi">7</span>  <span class="o">-</span><span class="mi">6</span>  <span class="o">-</span><span class="mi">5</span>  <span class="o">-</span><span class="mi">4</span>  <span class="o">-</span><span class="mi">3</span>  <span class="o">-</span><span class="mi">2</span>  <span class="o">-</span><span class="mi">1</span>
</pre></div>

Indexes correspond to the place to hold the sausage from left to right
End of explanation
"""


S1="lamb"
S1[0]='x'

S2="beef"
S=s + ' of ' + S2
S

S1="lamb"
S1[1] + 'nd'

S=s + ' of ' + S2 + ' ' + S1[1] + 'nd ' + S1
S

"""
Explanation: 2.2) Changing and formating
Chains are non-modifiable, so to change a chain we must define a new one
End of explanation
"""


i=0
j=1
L2 = [0,1,2,3]
L3 = [['abc','truc'],['def','ghi']]

print(L2[i])
print(L3[i][j])

matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]
line1=matrix[0]
line1[0]

L2 = [0,1,2,3]
L3 = [['abc','truc'],['def','ghi']]
L3 + L2

L2.append(0)
print(L2)

L2.sort()
print(L2)
L2.reverse()
L2[3] = 0.5
print(L2)

for x in range(4): print(x)

L4=[1,2,3]
L4[:0]=[0]
L4

"""
Explanation: 3) The lists
List can contain all kind of objects such as, numbers, chains, and even list themselves
Some usual operations on Lists

|Operation | Interpretation|
|-----|----------|
| L1 = [] | Empty list |
| L2 = [0,1,2,3] | Four elements of type int|
| L3 = ['abc',['def','ghi']] | Included lists |
| L4 = [(0,1,2,3),(0,1,2,3)] | Coordinates of points |
| L2[i] | Index i|
| len(L2) | Lenght |
| L2 + L3 | Concatenation |
| L3 * 3 | Repetition |
| for x in L2 | Iteration |
| 3 in L2 | Belonging |
| L[:0]=[2] | append 2 at the left  |
| L2.append(4)  | Increasing right with 4 |
| L2.sort()| Sort the items of the list in place|
| L2.index(X) | Search the index corresponding to value X |
| L2.reverse() | Reverse the List order |
| del L2[k], L2[i:j]=[] | Delete, since lists are modifiables |
| L2[i] = 1 | Declaration by index |
| L2[i:j] = [4,5,6] | Declaration by range |
| range(n)| Creation of a list of n integers |
End of explanation
"""


L = [['abc', 'truc'], ['def', 'ghi'], 0, 1, 2, 3]
L.append(['bidule'])
type(L)

"""
Explanation: Les methodes sont comme des fonctions, sauf qu'elles sont associés à un objet en particulier Quand vous utilisez des attributs comme append et sort, les objets sont modifiés par effet de bord, et il n'y a donc pas de raison de ré-affecter
~~~ python
L = [['abc', 'truc'], ['def', 'ghi'], 0, 1, 2, 3]
L = L.append(['bidule'])
print(L)
~~~
None
End of explanation
"""


# On va remplacer le bacon par 
# El l'on ajoute du café des cereales et de la confiture et du pain
D2 = {'bacon': 2, 'eggs': 3}
D2['eggs'] -= 1 
del D2['bacon']

# on ajoute en vrac, le dictionnaire ne trie pas
D2['corn-flakes'] = 1
D2['coffee'] = 10
D2['confiture'] = 1
D2['bread'] = 1
dict(D2,butter=2) #autre facon de faire mais qui met tout en ordre

table = {'Python': 'Guido van Rossum',
         'C': 'Dennis Ritchie',
         'Perl':   'Larry Wall',
         'Tcl':    'John Ousterhout',
         #'PowerShell': 'Microsoft',
        }

for lang in table.keys():
        print(lang, '\t', table[ lang ])

"""
Explanation: 4) The Dictionary


Acessible trought keywords
Non sorted collection of arbitrary objects
Of variable lenght, heterogeneous and open to any type of inclusion
Object able of mapping keywords to values


Usual operations on dictionaries

| Operation | Interpretation |
|-----------|----------------|
| D1 = { } | Declare empty dictionary |
| D2 = {'bacon': 2, 'eggs': 3} | Two-item dictionary |
| D3 = {'breakfast': D2} | Inclusion |
| D2['eggs'] | Indexing by key |
| 'eggs' in D2 | 'eggs' in D2 membership bolean test |
| D2.keys() | Return a view of the dictionary’s keywords |
| D2.values() | Return a view of the dictionary’s values |
| len(D2) | Number of entries |
| D2['bread']=1 | Update a dictionary by adding a new key entry and a value|
| D2['eggs'] -= 1 | Update a dictionary by substracting a value|
End of explanation
"""


print('Enter the number N, to divide it by D')
N=eval(input('N = '))
D=eval(input('D = '))
quot, rem = divmod(N, D) # Use of tuple assignement
print('The number {0}, divided by {1} can be written {1} times {2} plus {3}'.format(N,D,quot,rem))

t=(7,3)
divmod(* t)

# This imitates the dictionary
# without order

t = [('c', 0), ('b', 1), ('a', 2)]
t.sort()

for letter, number in t:
    print(number, letter)

# Dictionaries and tuples
D = {'a':0, 'b':1, 'c':2}
T = D.items()
print(T)
# Conversely you can use a list of tuples to initialize a new dictionary
t = [('a', 0), ('c', 2), ('b', 1)]
d = dict(t)
print(d)

"""
Explanation: 5) The Tuples
A tuple (t-uplet) is a sequence of non-modifiable values. The values can be any type, and they are indexed by integers, so in that respect tuples are a lot like lists. The important difference is that tuples are immutable.
 Usual operations on tuples

| Operation | Interpretation |
|-----------|----------------|
| T = tuple() | Declare empty tuple |
| t = 'a', 'b', 'c' | Declaration of a tuple |
| a , b = b, a | Elegant tuple assignment |
| T = ('A',) + t[1:] | Way to replace an element of a tuple |
| * T | Allows to scatter the tuple |
| max(1,2,3) | Gives the maximum of the list of numbers (check min)|
| zip(s, T) | Transposes a string and a list |
| t > T  | Comparision operator |
| t.sort() | Sorting the t |
End of explanation
"""


import re
listfileN='noyeaux-RMN.txt'

f=open(listfileN,'rt')

NUClist=[]
lines=f.readlines()

for  i in lines[0:]:
	(isotope,dash,name,receptivity,spin,freq)=i.split()
	Noyeau=dict(Isotope=isotope,Sensibilité=receptivity,Nombre_de_Spin=spin,Frequence_en_MHZ_à_2350mT=freq)
	NUClist.append(Noyeau)

print(NUClist[0])


Noyeau.keys()

"""
Explanation: Some of the above mentioned Useful Commands, can be found for a version 1.5 of Python
http://www.onlamp.com/pub/a/python/excerpt/PythonPocketRef/
6) The Files
exemple : noyeaux-RMN.txt
| Symbol | Name | Sensitivity | Spin | Frequency (MHz) |
|------- |----------------|--------------|--------|---------------|
|   1H   | - Hydrogen     | 5.68E+3       |1/2      |100.000000 |
|   2H    |- Deuterium     |8.21E-3        | 1       |15.35060886|
|   3H    |- Tritium       |1.00E-9       |1/2      |106.663974|
|   3He   |- Helium        |3.26E-3       |1/2      | 76.179437|
End of explanation
"""


