SEMESTER 2:
LOGBOOK MOVED TO NEW SITE:
https://sites.google.com/a/physics.umd.edu/cmsanalysis/sahir
************************************************************
SEMESTER 1:
11/27/18
From Github, we downloaded the deep dreams python code (https://github.com/keras-team/keras/blob/master/examples/deep_dream.py). This code contained the following
from __future__ import print_function
from keras.preprocessing.image import load_img, save_img, img_to_array
import numpy as np
import scipy
import argparse
from keras.applications import inception_v3
from keras import backend as K
parser = argparse.ArgumentParser(description='Deep Dreams with Keras.')
parser.add_argument('base_image_path', metavar='base', type=str,
help='Path to the image to transform.')
parser.add_argument('result_prefix', metavar='res_prefix', type=str,
help='Prefix for the saved results.')
args = parser.parse_args()
base_image_path = args.base_image_path
result_prefix = args.result_prefix
# These are the names of the layers
# for which we try to maximize activation,
# as well as their weight in the final loss
# we try to maximize.
# You can tweak these setting to obtain new visual effects.
settings = {
'features': {
'mixed2': 0.2,
'mixed3': 0.5,
'mixed4': 2.,
'mixed5': 1.5,
},
}
def preprocess_image(image_path):
# Util function to open, resize and format pictures
# into appropriate tensors.
img = load_img(image_path)
img = img_to_array(img)
img = np.expand_dims(img, axis=0)
img = inception_v3.preprocess_input(img)
return img
def deprocess_image(x):
# Util function to convert a tensor into a valid image.
if K.image_data_format() == 'channels_first':
x = x.reshape((3, x.shape[2], x.shape[3]))
x = x.transpose((1, 2, 0))
else:
x = x.reshape((x.shape[1], x.shape[2], 3))
x /= 2.
x += 0.5
x *= 255.
x = np.clip(x, 0, 255).astype('uint8')
return x
K.set_learning_phase(0)
# Build the InceptionV3 network with our placeholder.
# The model will be loaded with pre-trained ImageNet weights.
model = inception_v3.InceptionV3(weights='imagenet',
include_top=False)
dream = model.input
print('Model loaded.')
# Get the symbolic outputs of each "key" layer (we gave them unique names).
layer_dict = dict([(layer.name, layer) for layer in model.layers])
# Define the loss.
loss = K.variable(0.)
for layer_name in settings['features']:
# Add the L2 norm of the features of a layer to the loss.
if layer_name not in layer_dict:
raise ValueError('Layer ' + layer_name + ' not found in model.')
coeff = settings['features'][layer_name]
x = layer_dict[layer_name].output
# We avoid border artifacts by only involving non-border pixels in the loss.
scaling = K.prod(K.cast(K.shape(x), 'float32'))
if K.image_data_format() == 'channels_first':
loss += coeff * K.sum(K.square(x[:, :, 2: -2, 2: -2])) / scaling
else:
loss += coeff * K.sum(K.square(x[:, 2: -2, 2: -2, :])) / scaling
# Compute the gradients of the dream wrt the loss.
grads = K.gradients(loss, dream)[0]
# Normalize gradients.
grads /= K.maximum(K.mean(K.abs(grads)), K.epsilon())
# Set up function to retrieve the value
# of the loss and gradients given an input image.
outputs = [loss, grads]
fetch_loss_and_grads = K.function([dream], outputs)
def eval_loss_and_grads(x):
outs = fetch_loss_and_grads([x])
loss_value = outs[0]
grad_values = outs[1]
return loss_value, grad_values
def resize_img(img, size):
img = np.copy(img)
if K.image_data_format() == 'channels_first':
factors = (1, 1,
float(size[0]) / img.shape[2],
float(size[1]) / img.shape[3])
else:
factors = (1,
float(size[0]) / img.shape[1],
float(size[1]) / img.shape[2],
1)
return scipy.ndimage.zoom(img, factors, order=1)
def gradient_ascent(x, iterations, step, max_loss=None):
for i in range(iterations):
loss_value, grad_values = eval_loss_and_grads(x)
if max_loss is not None and loss_value > max_loss:
break
print('..Loss value at', i, ':', loss_value)
x += step * grad_values
return x
"""Process:
- Load the original image.
- Define a number of processing scales (i.e. image shapes),
from smallest to largest.
- Resize the original image to the smallest scale.
- For every scale, starting with the smallest (i.e. current one):
- Run gradient ascent
- Upscale image to the next scale
- Reinject the detail that was lost at upscaling time
- Stop when we are back to the original size.
To obtain the detail lost during upscaling, we simply
take the original image, shrink it down, upscale it,
and compare the result to the (resized) original image.
"""
# Playing with these hyperparameters will also allow you to achieve new effects
step = 0.01 # Gradient ascent step size
num_octave = 3 # Number of scales at which to run gradient ascent
octave_scale = 1.4 # Size ratio between scales
iterations = 20 # Number of ascent steps per scale
max_loss = 10.
img = preprocess_image(base_image_path)
if K.image_data_format() == 'channels_first':
original_shape = img.shape[2:]
else:
original_shape = img.shape[1:3]
successive_shapes = [original_shape]
for i in range(1, num_octave):
shape = tuple([int(dim / (octave_scale ** i)) for dim in original_shape])
successive_shapes.append(shape)
successive_shapes = successive_shapes[::-1]
original_img = np.copy(img)
shrunk_original_img = resize_img(img, successive_shapes[0])
for shape in successive_shapes:
print('Processing image shape', shape)
img = resize_img(img, shape)
img = gradient_ascent(img,
iterations=iterations,
step=step,
max_loss=max_loss)
upscaled_shrunk_original_img = resize_img(shrunk_original_img, shape)
same_size_original = resize_img(original_img, shape)
lost_detail = same_size_original - upscaled_shrunk_original_img
img += lost_detail
shrunk_original_img = resize_img(original_img, shape)
save_img(result_prefix + '.png', deprocess_image(np.copy(img)))
The code relies heavily on another package called inception to do most of the image processing. Then, I uploaded a small test image to my google drive to feed into the code as an argument:
Next, we used in a code in the Google Colab notebook to mount our google drive, giving us access to the files contained in the drive like the images:
from google.colab import drive
drive.mount('/content/gdrive')
which gave the output Drive already mounted at /content/gdrive; to attempt to forcibly remount, call drive.mount("/content/gdrive", force_remount=True).
Now that our Google Drive has been mounted, we upload our images through Colab's self-contained VM using the following lines of code:
!cp /content/gdrive/My\ Drive/deep_dream.py deep_dreams.py
!cp /content/gdrive/My\ Drive/test.jpg test.jpg
which would not give an output if it ran successfully. Now that we have the images and the python file, we can finally run the deep dream program with the following
!python deep_dreams.py test.jpg /content/gdrive/My\ Drive/dreamimage-myimage
Output: Using TensorFlow backend.
Model loaded. WARNING:tensorflow:Variable += will be deprecated. Use variable.assign_add if you want assignment to the variable value or 'x = x + y' if you want a new python Tensor object. Processing image shape (306, 408) ..Loss value at 0 : 0.68178344 ..Loss value at 1 : 0.92338943 ..Loss value at 2 : 1.2198982 ..Loss value at 3 : 1.5674462 ..Loss value at 4 : 1.9447178 ..Loss value at 5 : 2.328177 ..Loss value at 6 : 2.710359 ..Loss value at 7 : 3.119226 ..Loss value at 8 : 3.5039186 ..Loss value at 9 : 3.877778 ..Loss value at 10 : 4.245368 ..Loss value at 11 : 4.6129293 ..Loss value at 12 : 4.977573 ..Loss value at 13 : 5.343236 ..Loss value at 14 : 5.663364 ..Loss value at 15 : 5.9787173 ..Loss value at 16 : 6.3079576 ..Loss value at 17 : 6.608721 ..Loss value at 18 : 6.9266543 ..Loss value at 19 : 7.220291 Processing image shape (428, 571) ..Loss value at 0 : 1.5292866 ..Loss value at 1 : 2.423019 ..Loss value at 2 : 3.1588666 ..Loss value at 3 : 3.7490237 ..Loss value at 4 : 4.338011 ..Loss value at 5 : 4.8563128 ..Loss value at 6 : 5.315939 ..Loss value at 7 : 5.7940655 ..Loss value at 8 : 6.216748 ..Loss value at 9 : 6.5945964 ..Loss value at 10 : 6.974104 ..Loss value at 11 : 7.3472347 ..Loss value at 12 : 7.6861534 ..Loss value at 13 : 8.034979 ..Loss value at 14 : 8.359201 ..Loss value at 15 : 8.677179 ..Loss value at 16 : 8.983475 ..Loss value at 17 : 9.277063 ..Loss value at 18 : 9.559473 ..Loss value at 19 : 9.837258 Processing image shape (600, 800) ..Loss value at 0 : 1.6606051 ..Loss value at 1 : 2.5734684 ..Loss value at 2 : 3.2963066 ..Loss value at 3 : 3.9260507 ..Loss value at 4 : 4.5102196 ..Loss value at 5 : 5.0446568 ..Loss value at 6 : 5.5388265 ..Loss value at 7 : 5.9945507 ..Loss value at 8 : 6.427807 ..Loss value at 9 : 6.8410187 ..Loss value at 10 : 7.2280397 ..Loss value at 11 : 7.5954967 ..Loss value at 12 : 7.9630146 ..Loss value at 13 : 8.295062 ..Loss value at 14 : 8.641787 ..Loss value at 15 : 8.963283 ..Loss value at 16 : 9.270809 ..Loss value at 17 : 9.57118 ..Loss value at 18 : 9.867915
Even though it produced a very long output, the code did run successfully and created a dream image in my Google Drive that was the following:
We also repeated this process with images of clouds:
We had to run
!cp /content/gdrive/My\ Drive/deep_dream.py deep_dreams.py
!cp /content/gdrive/My\ Drive/cloud.jpg clouds.jpg
first to make sure the images had been uploaded properly. Then we could run the python code just as above to obtain the dream image:
The neural network used to adjust the images appears to have been trained on images of dogs, whose characteristic it is recognizing and simply emphasizing, creating the strange images we end up with.
11/15/18
Now, we will complete some exercises using what we have learned about Python so far:
real_madrid=['zidane', 'ramos', 'marcelo']
barcelona=['valverde', 'messi', 'pique']
# two arrays representing Coach and players on two soccer teams initialized
teams = [real_madrid, barcelona]
# we create a 2-d dimensional array that stores all of the information we have
# on each team
def losing_team_captain(team_list):
return teams[len(teams) - 1][1]
# return the second element of the last array in the list of arrays, which
# should always be the osing captain
print(losing_team_captain(teams))
Output: messi
This code identifies the losing team's captain and returns their name based on an input of an array containing the names of the relevant players and coach on a team. Then, we. created a code that represents a "purple shell" in Mario Kart that switches the players in first and last:
standings=['mario', 'bowser', 'luigi','peach']
# initial array with the beginning standings in the race
def purple_shell(racers):
temp = racers[0]
# temp variable to save the value of the racer in first place
racers[0] = racers[len(racers) - 1]
# switches the value of the racer in first placce to the one in last
racers[len(racers) - 1] = temp
# makes the last place racer the one that used to be in first
return racers
# returns the editted array
print(purple_shell(standings))
Output: ['peach', 'bowser', 'luigi', 'mario']
Now, we can move on and use loops that carry out many processes and make use of the computational power of the computer:
def list_contains_seven(my_list):
for element in my_list:
# loop will run for each element in the list
if element ==7:
# if the element stores 7, the method will return true
return True
return False
# if a 7 is not found, the method will return false
print(list_contains_seven([6,14,5,7]))
print(list_contains_seven([6,14,5,9]))
Output: True
False
This code shows how a for loop can be instantiated in Python and how we can use and if statement to go through code based on conditions. Like C++, we can also use while loops as shown here:
def count_to_10(num):
while(num<10):
# loop runs as long as the variable num is less than 10
num=num+1
# increments num
print(num)
count_to_10(0)
# method will print out all integers from 1 to 10
count_to_10(5)
# method will print out all integers from 6 to 10
count_to_10(11)
# method will not do anything
Output:
1 2 3 4 5 6 7 8 9 10 6 7 8 9 10
Note that Python uses indentation instead of brackets to identify where loops begin and end. We can continue with our use of Python by using loops to detect how many elements of an array are divisible by 7:
list=[1,21,7,-14,49,74,700]
def seven_counter(my_list):
frequency = 0
# frequency of numbers divisible by 7 present in the list
for element in my_list:
# loop will run for each element in the list
if(element % 7 == 0):
# this code will run if the given element is divisible by 7
frequency=frequency+1
# increments the frequency
return frequency
print(seven_counter(list))
Output: 5
A unique feature of Python that is not in any of the other languages we have explored is the dictionary object, which we will give an example of here:
capitals={'United States': 'DC', 'France': 'Paris', 'Mexico': 'DF'}
# defines a dictionary called capital that has names of countries as its keys
# and their capitals as its values
populations={'UMD':40000, 'Towson': 30000, 'UMBC': 20000}
# defines a dictionary called populations that has the names of Maryland
# colleges as its keys and their populations as their values
print(populations.get('UMD'))
# we call one of the built in functions of the dictionary data type to access
# the UMD data in the populations dictionary
Output: 40000
Dictionaries use keys to refer to a series of values stored in the given key. Now, we give a more complex examples involving a deck of cards:
deck={} #represents a deck of cards where the keys are the suits and values are lists of card values
hearts=[] # represents the hearts in the deck
clubs=[] # represents the clubs in the deck
diamonds=[] # represents the diamonds in the deck
spades=[] # represents the spades in the deck
values=['ace', 'two', 'three', 'four', 'five', 'six','seven', 'eight', 'nine', 'jack', 'queen', 'king']
# stores all the possible values of a card
def create_cards(suit):
for value in values:
# runs 13 times, once for each possible value of the card
suit.append(value)
# adds each value to the suit arrays created above
create_cards(hearts)
# creates all the heart card values
create_cards(clubs)
# creates all the club card values
create_cards(diamonds)
# creates all the diamond card values
create_cards(spades)
# creates all the spade card values
# all of the arrays created at the beginning should be filled now
#Use the strings 'h', 's', 'c', 'd' as keys, and add the lists of values to the dictionary.
deck.update(h = hearts)
deck.update(s = spades)
deck.update(c = clubs)
deck.update(d = diamonds)
# updates the dictionary deck with each key and the corresponding array that
# will be its values
#Print a view of dictionary (key, value) pairs
print(deck.items())
#Print a view of all of the keys
print(deck.keys())
#Print a view of all of the values
print(deck.values())
#Remove all of the spades from the deck
deck.pop('s')
print(deck.keys())
#Add a new entry to the dictionary with key 'j' and values 'joker1' and 'joker2'
deck.update(j = ['joker1','joker2'])
print(deck.keys())
#Clear the dictionary
deck.clear()
print(deck.keys())
Output:
dict_items([('h', ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king']), ('s', ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king']), ('c', ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king']), ('d', ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king'])]) dict_keys(['h', 's', 'c', 'd']) dict_values([['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king'], ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king'], ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king'], ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'jack', 'queen', 'king']]) dict_keys(['h', 'c', 'd']) dict_keys(['h', 'c', 'd', 'j']) dict_keys([])
Dictionaries are also interesting things to look at because they have their own methods to access the data, print the data, or adjust the data in various ways. While dictionaries are useful, there are still many functions that none of the data structures in Python can carry out naturally on their own. To do more complex functions, we need to import Python External Libraries, which have more complex code to run the functions we require:
import math
print(math.pi, math.log(32, 2))
# prints the value of pi contained in the math library and then calculates the
# base 2 logarithm of 32, which is 5.0 and prints that to the console
print(math.gcd(75348597,979531683))
# accesses the greatest common denominator method in the math library and prints
# it to the console
print(math.cos(10))
# prints the cosine of 10 to the console
# Here's a more advanced example.
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# allows access to the three libraries for simple use in the code below
# Data for plotting
t = np.arange(0.0, 2.0, 0.01)
# accesses the arrange method in the numpy class to create an array of evenly
# spaced values from 0 to 2 with a 0.01 increment
s = 1 + np.sin(2 * np.pi * t)
# creates a new array called s which is equal to 1 + the sine of all the elements
# in t times 2 times pi
fig, ax = plt.subplots()
# creates a new figure with subplots
ax.plot(t, s)
# plots t on the x axis with s on the y axis
# aince each is an array, we get a set of points
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='About as simple as it gets, folks')
# sets axis labels and a title
ax.grid()
plt.show()
# displays the plot we have created
Output:
3.141592653589793 5.0 3 -0.8390715290764524
In this example, we imported several external libraries from Python and used them to perform some basic calculations, as well as create a graph of a shifted sine function. We can also create more complex graphs like scatter plots using the following code:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# imports the libraries we need to plot a graph and do math
data = {'a': np.arange(50),
'c': np.random.randint(0, 50, 50),
'd': np.random.randn(50)}
# creates a dictionary to store data
# 'a' holds an array with every integer value from 0 to 49
# 'c' holds an array with 50 randomly chosen integers from 0 to 49
# 'd' holds 50 numbers that represent a Guassian distribution (all the values
# are from -1 to 1
data['b'] = data['a'] + 10 * np.random.randn(50)
# creates the dictionary entry with key 'b' to have the data in 'a' multiplied by
# the Gaussian distribution we have created
data['d'] = np.abs(data['d']) * 100
# sets the dictionary entry with key 'd' equal to the absolute value of the data
# in 'd' times 100
plt.scatter('a', 'b', c='c', s='d', data=data)
# sets the data in 'a' as the x-axis and the data in 'b' as the y-axis data, 'c'
# provides a shape for the given point of the plot, s provides the color of the
# scatter plot point
plt.xlabel('entry a')
plt.ylabel('entry b')
plt.show()
# creates axis labels for the plot and shows it
Output:
I also created the graph of y = |x| as an exercise using the methods of Python and the external library:
Now that we know how to use Python and its many functions, we can finally use it for CMS analysis:
# imports some software packages we'll use
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
inline_rc = dict(mpl.rcParams)
# a hashtag tells the program "don't read the rest of the line"
# That way we can write "comments" to humans trying to figure out what the code does
# reads a csv file with data from a github repository
two_u = pd.read_csv('https://github.com/adamlamee/HEP-data/raw/master/Double_Muon_Run2011A.csv')
# two_e = pd.read_csv('https://github.com/adamlamee/HEP-data/raw/master/Double_Electron_Run2011A.csv')
# one_u = pd.read_csv('https://github.com/adamlamee/HEP-data/raw/master/Single_Muon_Run2011A.csv')
# one_e = pd.read_csv('https://github.com/adamlamee/HEP-data/raw/master/Single_Electron_Run2011A.csv')
# saves the data that was read from the csv file into a two-dimensional array
data = two_u
# The .head(n) command displays the first n rows of a file.
data.head(3)
# The .shape command displays the (number of rows , number of columns) in a file.
data.shape
# You can specify a column by dataset.columnName (e.g., two_u.E1)
# This makes a new column called "totalE" and fills it with (E1 + E2) for each event
data['totalE'] = data.E1 + data.E2
# This makes a new column called "Esquared" and fills it with E1^2 for each event
data['Esquared'] = data.E1**2
# makes the histogram
plt.hist(data.totalE, bins=10, range=[0,120], log=False)
plt.title("Dimuon Events")
plt.xlabel("x-axis label")
plt.ylabel("number of events")
Output:
Text(0,0.5,'number of events')
We have created a histogram that maps out dimuon events read from a csv data file we pulled from the web. We can use the different files given and any others that we have access to in order to create various graphs to help our analysis of CMS data, which makes Python a very useful tool in particle physics studies.
11/13/18
Using the Colaboratory app in Google Drive, we can write code in Python that looks like the following:
which we can also run in the notebook itself. Our first exercise with python was to create a code that calculated the area of a circle, which we did with the code:
pi = 3.14159 #Approximation
diameter = 10
area = pi*(diameter/2)**2 # The **2 operator squares the value in parenthesis
print(area) # Much like C++, we can print variables using the print function
which gave the output 78.53975, displayed in the small section below the code after we ran the code. We can reassign variables using the following code:
#####Method 1########
a = [1, 2, 3]
b = ['cat', 'dog', 'fish']
a=b
b=a
# a becomes the array stored in b, while the value stored in a is lost so this method fails to effectively reassign the values
print('Method 1')
print(a)
print(b)
#####Method 2########
a = [1, 2, 3]
b = ['cat', 'dog', 'fish']
temp = a
a = b
b = temp
print('Method 2')
print(a)
print(b)
The first method does not work because the value of a is completely lost and not saved anywhere. The second method works because it saves the array stored in a before reassigning everything.
dog_legs = 0
human_legs = 4
goldfish_legs = 2
# we have three variables now representing the amount of legs the given animal has but they store incorrect values
temp = goldfish_legs
# creates temp variable equal to the gold_fish legs so we can save it
goldfish_legs = dog_legs
# reassigns the goldfish_legs variable
dog_legs = human_legs
# reassigns the dog_legs variable
human_legs = temp
# reassigns the human_legs variable
This method effectively reassigns the values so that they now represent the correct values through the use of a temp variable. Next, we examine functions by creating a function that can round a number to some number of decimal places:
def round_to_n_places(num,n):
return round(num,n)
# we defined (def) a function that takes an input and calls the round function
# to return the number rounded to n decimals, where n is the second argument
print(round_to_n_places(4.325456463,5))
# prints the value of the input number after it has been rounded to 5 places
def denies a new function that we can call just like in C++. We can print the value we get, which comes out as 4.32546. However, there are still more functions that we can use that are built into the standard Python library. In the following code, we use several of the functions built into Python:
a=[1,5435,324,3,645365,23,4,5665,435,31, -543]
# creates an array of numbers stored in a
b=-10
# sets b equal to the value of -10
c='cat'
# sets c equal to the string 'cat'
print(c)
print(abs(b)) #absolute value
print(min(a)) #min value
print(max(a)) #max value
print(sum(a)) #sum
print(len(c)) #length of a string
print(sorted(a)) #sorts a list
We call on several functions here from Python that can be used, and this code out as
We can use these built in functions to write our own method that returns the product of the maximum values contained in an array:
a=[3243,645645,54346]
b=[7,3,2]
# creates two integer arrays
def product_of_maxes(a,b):
return max(a)*max(b)
#function takes two integer paramters and calls the max() function to find the
# maximum value stored in each array
# it then multiplies them and returns the product
print(product_of_maxes(a,b))
#prints the results of the arrays being fed into the function I wrote
This code outputs the value that is the product of the maximum values in a and b or 645645*7 which is 4519519. We can also use logical and conditional statements just as we did with C++. See the following code:
print(3==10)
#prints False because 3 does not equal 10 (== operator checks for equality)
print(len('abc')==3)
# prints True because the the length of the string is 3 (len() returns the
# length of the string parameter)
print(max([10,40,53]) < 25)
#prints False because the max value of the array, 53, is greater than 25 and the
# expression is False
print (5 != 3)
# prints True because 5 does not equal 3 (!= operator checks for inequality)
This code outputs:
False
True
False
True
The code uses the same Boolean ideas as C++. We can show another example here:
a = [1,2,3]
# creates an array with the three values
print(max(a) == 3)
# prints True because the maximum value in the array is equal to 3
print(sum(a) == 7)
#prints False because the sum of the values in the array is 6, not 7
print(min(a) == max(a))
# prints False because the minimum value in the array does not equal the maximum
Output:
True
False
False
Now, we can use conditionals to make our code more complex and actually do something:
a=20
b=10
# creates two variables with values 10 and 20
if(a>b):
print(a, 'is greater than', b)
# if the value of a is greater than the value of b, this print statement will
# print '[value of a] is greater than [value of b]'
elif(a<b):
print(b, 'is greater than', a)
# if the value of a is less than b, then this print statement will
# print '[value of b] is greater than [value of a]'
else:
print("they're equal")
# if neither of the previous if conditions are satisfied, then this print
# statement will run
This code uses simple if and else statements to check equality between two variables, and we can adjust them to modify our output as we have done in C++ code. We usually use logic statements in a function, which can return several variables or return nothing. See the code here:
def longer_string(string1, string2):
if(len(string1) > len(string2)):
return string1
elif(len(string1) < len(string2)):
return string2
else:
return
# defines a funciton intended the longer of the two string parameters it is
# given, if the strings have equal length, nothing will be returned
print(longer_string('abc', 'jfkdla;s'))
# prints out 'jfkdla;s' because it is the longer string
print(longer_string('abcfdsafdasg', 'jfkdla;s'))
#prints out 'abcfdsafdsag' because it is the longer string
print(longer_string('abc', 'def'))
#prints out none because neither string is longer
The function returns the longer string, and when the strings are equal in length, the function returns the word None. We can write other functions that use a myriad of variables to check more specific conditions:
def can_make_cake(eggs, flour, milk, almond_milk):
#I can make cake if I have some kind of milk AND flour AND eggs
return (milk or almond_milk) and flour and eggs > 0
# this method returns true if milk or almod_milk are true, flour is true, and
# the value stored in eggs is greater than 0
print('Can I make cake?')
#What is the following line implying?
# it implies that the method will return true and that you can make cake
print(can_make_cake(10, True, False, True))
# prints true because the can_make_cake method will return true
#redo the above call to the function with 0 eggs
print('Can I make cake?')
print(can_make_cake(0, True, False, True))
# prints false because the can_make_cake method will return false
which outputs:
Can I make cake? True Can I make cake? False
The return function uses a series of Boolean operators, which have different syntax here then in C++. We can make more functions that use the same modulus operator from C++ using remainders and other standard Python functions like here:
a = [-35423,-5432654,-352435,53252]
# instantiates new array with some values
def abs_of_min_is_odd(a):
return abs(min(a))% 2 == 1
# method returns true if the absolute value of the minimum value of the array
# parameter odd because the modulus operator divides it by 2 and checks for a
# remainder, which odd number will have
print(abs_of_min_is_odd(a))
# should print false because the absolute value of the minimum of the array a is
# even
We can also use arrays to create two-dimensional arrays show n here with the variable list_of_lists:
def select_third_element(my_list):
if(len(my_list) < 3):
return None
# checks to make sure tha paramer has at least 3 elements so that we can find
# the third element, returns none if there aren't three elements
else:
return my_list[2] #remember index 0, so third element is index 2
# returns true
foo = ['a', 'b', 'c', 'd']
# creates new array foo with a series of strings inside
print(select_third_element(foo))
# prints c, the third element foo
list1=[1,2,3]
list2=[4,5,6]
# creates two lists
list_of_lists=[list1,list2]
# creates a list of lists, which is essentially. a 2-d array
print(list_of_lists[1][2])
# prints 6 because it finds the second element of the list_of_lists and the third
# element within that list
print(list_of_lists[0])
# prints the list1 array because it is the first element in list_of_lists
print(list_of_lists[1])
# prints the list2 array because it is the second element in list_of_lists
print(list_of_lists[0][1])
# prints 2 because that is the second element of the first array in list_of_lists
print(list_of_lists[0][2])
# prints 3 because that is the third element of the first array in list_of_lists
print(list_of_lists[1][0])
# prints 4 because it is the first element of the second array in list_of_lists
list_of_lists represents a 2-d array that we can access with two parameters. We can use 2-d arrays to store and mimic various processes. 2-d arrays can be extremely useful for storing large amounts of data effectively and accessing that data easily.
11/8/18
We can now use the TLORENTZ vector class to find the invariant mass of the Higgs Boson. First, we downloaded a package from http://hepcms-hn.umd.edu/~jabeen/Analysis/
(Links to an external site.)LHC-Higgs-Graviton.tgz (Links to an external site.)
Then, we unpacked it to get a series of root files. Inside root, we run one of these files and to enter root and then create a class called "HiggsAnalysis" using the command HZZ4LeptonsAnalysisReduced->MakeClass("HiggsAnalysis"). This creates a class using information in the roots files called HiggsAnalysis.C which has the TLORENTZ vector class and we can use to get the Higgs Boson mass.
Then, we write the HiggsAnalysis.C code with as follows:
#define HiggsAnalysis_cxx
#include "HiggsAnalysis.h"
#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
void HiggsAnalysis::Loop()
{
// In a ROOT session, you can do:
// Root > .L HiggsAnalysis.C
// Root > HiggsAnalysis t
// Root > t.GetEntry(12); // Fill t data members with entry number 12
// Root > t.Show(); // Show values of entry 12
// Root > t.Show(16); // Read and show values of entry 16
// Root > t.Loop(); // Loop on all entries
//
// This is the loop skeleton where:
// jentry is the global entry number in the chain
// ientry is the entry number in the current Tree
// Note that the argument to GetEntry must be:
// jentry for TChain::GetEntry
// ientry for TTree::GetEntry and TBranch::GetEntry
//
// To read only selected branches, Insert statements like:
// METHOD1:
// fChain->SetBranchStatus("*",0); // disable all branches
// fChain->SetBranchStatus("branchname",1); // activate branchname
// METHOD2: replace line
// fChain->GetEntry(jentry); //read all branches
//by b_branchname->GetEntry(ientry); //read only this branch
if (fChain == 0) return;
Long64_t nentries = fChain->GetEntriesFast();
Long64_t nbytes = 0, nb = 0;
TFile* output = TFile::Open("Dielectron_MC.root", "RECREATE"); // "RECREATE" would produce a new root file with name Dielectron_MC.root every time you run the code
TH1F* Z_ee = new TH1F("Z_ee", "Di-electron candidate invariant mass", 200, 0, 200);
double el1mt = 0.0;
double el1pt = 0.0;
double el1eta = 0.0;
for (Long64_t jentry=0; jentry<nentries;jentry++) {
Long64_t ientry = LoadTree(jentry);
if (ientry < 0) break;
nb = fChain->GetEntry(jentry); nbytes += nb;
// if (Cut(ientry) < 0) continue;
TLorentzVector el1, el2;
el1.SetPtEtaPhiM(f_lept1_pt, f_lept1_eta, f_lept1_phi, 0.0);
el2.SetPtEtaPhiM(f_lept2_pt, f_lept2_eta, f_lept2_phi, 0.0);
TLorentzVector zCandidate = el1 + el2;
Z_ee->Fill(zCandidate.M());
el1mt = el1.Mt();
cout << el1mt << endl;
}
Z_ee->Write();
output->Close();
}
We can run this program by first entering ROOT. Then we use .L HiggsAnalysis.C and HiggsAnalysis t to create a new HiggsAnalysis object. Then, we call the loop method of the HiggsAnalysis class to get the data about the energy the Z boson produced from the lepton collisions:
Then, we run the Dielectron_MC.root file created by the HiggsAnalysis.C code and then opened it in the ROOT browser using TBrowser t.
However, to find the Higgs Boson, we need to have two Z bosons collide when generated from a four lepton event. Therefore, we need to add another set of two leptons by inserting the following code into our HiggsAnalysis.C code:
TLorentzVector el3, el4;
el3.SetPtEtaPhiM(f_lept3_pt, f_lept3_eta, f_lept3_phi, 0.0);
el4.SetPtEtaPhiM(f_lept4_pt, f_lept4_eta, f_lept4_phi, 0.0);
Then, we must add these two TLorentzVector objects together to produce the second Z boson with the following line:
TLorentzVector zCandidate2 = el3 + el4;
Finally, we have to combine both Z bosons to form the Higgs Boson using the line
TLorentzVector Higgs = zCandidate + zCandidate2;
We then define a new histogram to display our Higgs Boson energy data and write it into the Dielectron_MC.root file mentioned earlier with the following two commands:
TH1F* H_zz = new TH1F("H_zz", "ZZ candidate invariant mass", 200, 0, 300);
H_zz->Fill(Higgs.M());
H_zz->Write();
When we repeat the steps to create the histogram as we did above, we get the final graph as
According to the histogram, the mass of the resulting particle is approximately 125 GeV, which means we have in fact discovered the Higgs Boson.
11/6/18
Once we have converted and opened the Root file through Root, we can open up TBrowser t. Then, we can observe the data by going into the events generated and looking at the specific files included in the folder as seen below:
PIDX is the global particle ID for a particle, which can be used to track that particle (also called the Monte Carlo particle ID). For example, the electron has an ID of 11. The top quark has a Monte Carlo ID of 6.
11/1/18
First, we installed the MadGraph package from the website and unpacked the file using the command tar -xvzf MG5_aMC_v2.6.0.tar.gz.
Then, we opened MadGraph using ./bin/mg5_aMC from within the directory created by the package we downloaded.
Now, we can start using MadGraph to make simulations of collisions at the LHC. We can generate a collision using the command MG5_aMC>generate p p > t t~ display the associated processes using MG5_aMC>display processes. To display the particles involved in the process, we use the commands MG5_aMC>display particles and MG5_aMC>display multiparticles. The results of these commands are shown here in order:
Now, we can adda second process using the command MG5_aMC>add process p p > W+ j, W+ > l+ vl. This adds a process that creates a W+ boson which then decays into a lepton and its corresponding neutrino.
We can create the output of this process for use in calculations using the command MG5_aMC>output MY_FIRST_MG5_RUN:
We can then generate generate the events using MG5_aMC> launch MY_FIRST_MG5_RUN, which redirects us to FireFox and gives us the following information:
This gives us valuable information about many aspects of the simulated collision. Now, we also have the file "unweighted_events.lhe", which contains 1000 simulations that we need to convert to ROOT. To do this, we have a Python file called "lhe2root.py". We run this python script using python lhe2root.py MY_FIRST_MG5_RUN/Events/run_01/unweighted_events.lhe MY_FIRST_MG5_RUN.root. Then, we run the resulting file as a root file using root -l MY_FIRST_MG5_RUN.root. This gives the following result:
10/25/18
Computing Homework 6 using Root:
First, I created the resolutions file as .C file containing the following code:
#include "Riostream.h"
// this allows the C program to input and output Root files, which is needed for our code
#include <iostream>
#include <fstream>
void resolutions(){
// this is the main method of the C program
bool idebug = 0;
// sets the debug mode with a boolean variable
// if this variable is set to 1, we are in debug mode
// the following code sets up the display
gROOT->Reset();
// gROOT allows the code to access ROOT objects to create a display
gROOT->SetStyle("Plain");
// sets the ROOT browser to the standard style
gStyle->SetOptStat(0);
// uses a basic style for the ROOT browser display
gStyle->SetOptFit(11);
// creates a fit for two histograms to be included in the ROOT browser
gStyle->SetErrorX(0);
// this method removes the drawing of errors because the argument being passed is 0
c1 = new TCanvas("c1","Our data",200,10,700,500);
// creates a new TCanvas in the ROOT display in ROOT
c1->SetFillColor(0);
// fills the canvas wuth an empty color
c1->SetBorderMode(0);
// sets a standard border size
c1->SetBorderSize(1);
// sets border size to 1 on the display
c1->SetFrameBorderMode(0);
// creates the standard border frame
// book some histograms
TH1F *histo1 = new TH1F("histo1","mass",1000,0.,200.);
// setup random number generator
gRandom->SetSeed();
// get the secret parameters
ifstream myfile;
myfile.open("secretparameters.txt");
double mass, resE, resA;
myfile>>mass>>resE>>resA;
myfile.close();
// the code above creates a file stream object and uses it to stream in the secretparameters.txt file
// it also saves the parameters given in the text file into the three double variables listed
// make N bosons at rest
// each boson will decay to 2 back-to-back daughter particles
// they will be back-to-back by conservation of momentum, since the momentum of the mother was zero
// assume that the mass of the daughter particles is small compared to the mother mass so we can
// assume that their energy will be large compared to their mass and we can treat them as massless.
// and thus their energy is equal to the magnitude of their momenta
// by conservations of energy, their energy
// work in 2D. Can always choose my coordinate system so that the 2 daughters are in the same plane
int N=1000;
// represent the number of bosons we want to analyze
double etrue1,etrue2,phitrue1,phitrue2; // true energy of the 2 daughters
double e1,px1,py1,phi1; // smeared 4-momenta of daughter 1
double e2,px2,py2,phi2; // smeared 4-momenta of daughter 2
double masssmeared;
for(int i=0;i<N;i++) {
// run the loop for each boson we had created
// set true energy
etrue1=mass/2.;
etrue2=mass/2.;
// if we wish to debug by setting the idebug variable equal to 1, this print statement will run to display the value of the energies and make sure they have been calculated correctly
if(idebug) cout<<"etrue "<<etrue1<<" "<<etrue2<<endl;
// choose phi for daughter 1 and daughter 2 (phi is an angle)
phitrue1=2*TMath::Pi()*gRandom->Rndm();
phitrue2 = phitrue1+TMath::Pi();
// the phi values are randomly generated by calling a math function and a ROOT random generator
// if we set idebug to 1 in order to debug, the console will print the values of phi to assess how the program is proceeding
if(idebug) cout<<"phitrue "<<phitrue1<<" "<<phitrue2<<endl;
// smear true energy with resolution of detector
e1=etrue1+resE*gRandom->Gaus(0.,1.);
e2=etrue2+resE*gRandom->Gaus(0.,1.);
// calls the Gaus method of the gRandom class to skew the observed energy value based on the detector's resolution
// if we wish to debug, this will print the observed energy to help us debug
if(idebug) cout<<"e "<<e1<<" "<<e2<<endl;
// smear angles with resolution of the detector
phi1=phitrue1+resA*gRandom->Gaus(0.,1.);
phi2=phitrue2+resA*gRandom->Gaus(0.,1.);
// this will print the angle if we are in debug mode
if(idebug) cout<<"phi "<<phi1<<" "<<phi2<<endl;
//calculate 4 momenta after smearing
px1=e1*cos(phi1);
py1=e1*sin(phi1);
px2=e2*cos(phi2);
py2=e2*sin(phi2);
// print the 4 momenta if we are in debug mode
if(idebug) cout<<"pxs "<<px1<<" "<<py1<<" "<<px2<<" "<<py2<<endl;
// calculate smeared mass
masssmeared=sqrt((e1+e2)*(e1+e2) - (px1+px2)*(px1+px2) - (py1+py2)*(py1+py2));
// print the smeared mass if we are in debug mode
if(idebug) cout<<"masssmeared "<<masssmeared<<endl;
// put the smeared mass into the histogram display
histo1->Fill(masssmeared);
// print the display with the value of the smeared mass
histo1->Draw("");
// updates the display
c1->Update();
// saves the display as gif file that can be reopened for later use
c1->SaveAs("c1.gif");
}
}
Running this in the ROOT prompt with N=1, we obtain the following histogram:
Based on this, the mass of the mother particle appears to be approximately 65 GeV. However, this is not entirely accurate because of the smearing due to the resolution of the detector. We cannot give an accurate estimate of how far away from the actual value the estimate is because we only have one data point, which does not give us enough information to conclude anything. However, when we increase N to 10, we get the following:
Now, we have a range of data and see that the mother particle could have a mass anywhere from around 45 GeV to around 105 GeV. Based on the range of the histogram and the center of the distribution, we can say that the mother particle is approximately 75 GeV. This is still a very uncertain measurement, so we should increase N to 100:
The histogram is now starting to take the shape of the bell curve we expect. While the spread of possible values increases due to the increased number of trials, there is a peak forming between 80 and 90 GeV. The range of the distribution is approximately 140 GeV, or 70 GeV in each direction from the mean. If we say the peak of the distribution is at 85 GeV and assume that it is a normal distribution, then some basic statistics using the empirical rule leads us to conclude that there is an approximately 68% chance that the actual mass of the mother particle is between 62 GeV and 108 GeV. These values were calculated by assuming that 70 GeV represented a distance of three standard deviations from the mean of 85 GeV, which means that 23 GeV should represent 1 standard deviation. However, increasing N to 1,000 leads to a much clearer normal distribution:
The normal curve is much more obvious now. Based on the approximate location of the center peak, we can assume that the peak or center of this distribution is at around 90 GeV. If we approximate 3 standard deviations as 60 GeV, then the empirical rule tells us that there is a 68% chance that the actual mass of the mother particle lies between 70 GeV and 110 GeV. This is an extremely accurate estimate considering that the actual parameter entered for the mass of particle in the secret parameters file was 91. In the second part of this exercise, we change the first parameter of secretparameters.txt to 1 and create the histogram with N = 1, 10, 100, and 1000:
As the number of bosons created and analyzed increased, the histogram became clearer and points to the mass of the boson having a mass of approximately 10-15 GeV. This shows the amount of error the resolution of the detectors can produce given the fact that the actual mass value entered by the secret parameters text was only 1. At extremely small values, the detectors can observe some variance in the particle’s mass that leads to incorrect estimates. Also, when using the detectors, it takes thousands and thousands of measurements of the same particle before truly accurate estimates can be made. Experimentalists need to understand the resolution of their detectors precisely because it can have a massive impact on their estimates of the particle’s energy, which is especially important for smaller particles where more precise measurements may be needed.
10/23/18
Computing Homework Assignment 6:
First, I wrote out the code for the pseudo-random number generator given on the homework page. The code takes a seed, which should be a large odd number, and performs a series of calculations with other random constants. It returns a number that is then used to determine which element of an array will be incremented. This process is repeated as many times as the user requires, which leads to each element of the array being incremented a random number of times and giving us ten random numbers.
This code returns the random number in the form of a collection equals signs, representing how many times the element of the array was incremented and what number would be stored in that element of the array. Then, we tested what would happen if we removed the '&' character from the parameter of the double getFlatRandom. That led to the following:
Using C++ terminology, we say that the ‘&’ character allows creates a reference to a given variable much like a pointer would and permanently edit the variable. The variable is permanently edited by changing the value stored at its memory address, rather than creating a separate variable of the same value and editing that (this would occur if we did not include the ‘&’ character). At this point, we should also mention how data is stored in the computer. When storing data in a computer, we use bits and bytes. Bits are binary digits that store a 0 or 1 through the presence or absence of an electrical current. 1 bit can store 2 possible values (0 or 1). 2 bits can store 4 possible values (00, 01, 10, or 11), which corresponds to the numbers 0-3. 3 bits can store 8 possible values corresponding to the numbers 0-7 (000, 001, 010, 011, 100, 101, 110, or 111). As we can see from this pattern, each additional bit doubles the amount of values that we can possibly store. Therefore, if we have n bits, we can store 2^n values, or every integer from 0 up to 2^n-1. Now, we can define a byte as 8 ordered bits. A byte can then store every integer from 0 up to 2^8-1. If we have n bytes, this corresponds to 8n bits. Thus, a collection of n bytes can store every integer value from 0 to 2^(8n)-1.
We should now return to the original code and discuss how to directly print the random number we generated. For this question, we return to the code above in question 1. We replace the nested for loop that uses the index variable j with the following cout statement: “cout<< histo[i];”. This gives us the following loop which is different from the original code and the output:
When we run the code multiple times with the same seed and the same number of loop iterations, the same random numbers are generated over and over. This is why our code is not a true random number generator, but a pseudo-random number generator. Changing either the seed or the number of loop iterations should result in different numbers. First, I’ll change the seed to 4567. This leads to the following random numbers:
By changing the seed, we have an entirely new set of random numbers. We can also change the number of iterations to get new sets of random numbers:
All the random numbers generated are centered around the number of iterations divide by 10, and are never more than 9 away from this number in either the positive or negative direction. When using C++, it is much more useful to use the srand() and rand() functions in the C++ standard library. These functions take in the current time as a seed, which allows them to generate completely randomized numbers. We can then use the mod operator to ensure that our random numbers are only in the range we want them to be in. A quick demonstration of the rand() function is given below:
10/18/18
Building on how classes can be used in object-oriented programming, we can now use classes to take the dot product of vectors in the following code:
We created a dotprod.cpp file that did a basic dot product calculation. Then, we created a text file with some numbers listed. Then, we created an object of the class input file stream in our main C++ code to read in the text from the vectors.txt file we created. We used this object to take the numbers from the text file and store them into two vectors. We called the dot_prod function with the two vectors we created as arguments and found that the dot product was equal to 32. Now, we will modify this program to include a scalar multiplication program and a modified output here:
The scalar function is very basic and only performs one basic command based on a set of inputs. With classes, we can create any number of functions and have one input text file to deliver values for our calculations. This should make completing physics calculations much easier when we have to work with complicated vectors.
10/16/18
Now, we learn about arrays and their use in programs.
Arrays can store a given amount of values of a certain variable type. Two-dimensional arrays can store more values based on a set of two coordinates. Arrays are useful because we can manipulate or run through a series of variables with a loop much more easily than if we declared several separately-named variables. Another useful feature of all programming languages that we need to know is commenting. We can amend the code above and add an entire section of comments:
Comments do not appear nor affect the output of a code and can make a code more readable. Comments are useful so that other people can see a code and immediately understand exactly how different parts of the code work. We have already used comments in all of our code up to this point, so it seems redundant to continue exploring comments. Instead, we should move on to using C++ to read data from a file. This can be done with the following code:
In the code, we used a file stream to create a new text file and put some text into it. We created an object of the output file stream class, used it to open up a new text file, and insert text into that file, all through a C++ code. In the future, we could use this to put variables and other data into text files for further analysis. Also, note that ofstream is a class, which is a feature unique to object-oriented programming languages like C++ and Java.
10/11/18
Homework Assignment 5: Computing Exercises
First, I have written an example code using if and while statements. The code is designed to print the numbers from 1 to a specific value that can be divided by another number. These two unknown values are given as variables that can be changed before the code runs to get the desired values. It is easier to understand if you take a look at the actual code:
For the second exercise, I edited the script given on the homework page and simplified it to just three lines of actual code. This code lists out all the files that have been edited in the current month through the use of a single variable and a list command.
The comments basically describe each function in the code. I removed all of the original code relating to the current day because it was irrelevant to finding out what code had been edited in the current month, so the code is now much more streamlined and clean.
10/9/18
Now, we study logic statements and how they can be used in code.
This code in includes an if-else statement that has two segments of code. The first segment runs if the boolean condition given in the parenthesis of the if statement is found to be true, and the second segment will run if it is found to be false. This code creates a loop that should run infinitely, but the return 0; statement at the end of the loop tells the computer that the code has run to completion. Now, we can learn about pointers and memory addresses.
We can use pointers to find where variables are stored in memory and make sure our programs are efficient with their memory use. Pointers use the * operator to tell the computer to open up the data stored at the memory address they contain, which is also how pointers can store memory addresses of variables. We will now explore the pointers with two programs.
By comparing the two programs here, we see how pointers can be used to alter variables and vice versa because of their intrinsic connection through memory. However, we don't have to create an integer to create a pointer variable that stores data. See the following example:
We have created a pointer and assigned its memory address to store an integer without actually declaring or naming that integer. This is how we can deal directly with integers through memory using pointers.
10/2/18
Now, we start directly coding with C++ in our virtual machine. We can use emacs to create a .cpp file. For our first test of code, we create the classic "Hello World!" program as follows:
#include <iostream>
io stands for input/output, and including the input/output stream allows the code to take inputs and output things on the console
using namespace std;
The code written will use the standard(std) keywords included in the namespace, so we can use all the necessary commands of C++ that we need to
int main()
The main method of our code where everything will start and the majority of our code will be written. Because it is specified as an int return type, we should expect an integer returned at the end of the code.
cout << "Hello World!" << endl;
Prints something on the console. In this case, "Hello World!" is specified as the output. endl at the end of the command indicates that the output line is over and the cursor will begin the next output command on the next line.
return 0;
End of code. The value of 0 indicates that no errors were encountered in running the code.
g++ main.cpp
Instructs the system how to interpret the .cpp file and to compile it using a C++ compiler. The first time this command is used, it will produce an a.out file.
./a.out
Runs the most recently compiled .cpp file and lists the output in the next line.
The last two commands describe how we run a command. Now that we have explained how to create and run a basic C++ command, we must also look at the specifications of the C++ system we are using. The following commands will search the system for files related to C++, the compiler we use to run the code, and the version of these systems that we are using.
find /usr/include/c++ -name "4*"
Searches for files in the C++ directory that contain the character 4 to find the C++ version name. We have a 4.4.4 version and a 4.4.7 version of C++.
g++ dumpspecs
Gives libraries and version systems of the C++ compiler.
ls /usr/include/c++/4.4.4/
Lists the libraries and sub files contained in our version of C++, which is 4.4.4 in this case.
ls /usr/include/math.h
Lists the primary math file that can be added to the C++ function.
ls /usr/include/bits/*math*.h
Lists all the possible math functions that can be included in a given cpp file.
Now we create a C++ program that creates several variables and modifies them to understand how to declare and initialize variables.
int i = 2;
Creates a variable of the integer type and sets it equal to the value of 2.
double a = 3.3;
Creates a variable of the double type and sets it equal to the value of 3.3. Doubles represent floating point numbers so they can be decimals.
int j = a*I;
Creates an integer j that is equal to the value of a times the value of i. Ordinarily, this would be 6.6. However, Since j has been specified to be an integer, C++ will truncate 6.6 to 6 so that the value matches the specified type.
Now that we have created variables, we can try and alter variables using elementary operations.
n--;
Decrements the value of n by one; in this case, n goes from 10 to 9.
n++;
Increments the value of n by one; in this case n goes from 9 to 10.
So far, we have focused solely on numeric variables. A commonly used nonnumeric variable type used in many programming languages is the boolean type. Booleans store true and false values and represent them as a 1 or a 0 respectively in the console and memory.
bool prop;
Declares a Boolean variable prop but does not initialize it with a value.
prop = (5>1);
The arithmetic expression is true, so prop is now given a value of 1 corresponding to true.
prop = (1>5);
The arithmetic expression is false, so prop is now given a value of 0 corresponding to the value false.
prop = (1 != 5);
The "!=" operator is known as a boolean operator that compares the value of the two operands. The "!" character is called the "not" operator and "!=" means not equal to. Essentially, if the two operands are not equal, then the operator will return true. If they are, the operator will return false.
When the value of prop is printed, it is printed as 1s and 0s. This differs from Java, where booleans are printed as true and false. Now that we have covered many basic variables, we should move on to using variables in computing. To access the power of the computer, we need to use loops and repeat many processes quickly, like complex calculations.
while (n>0) {}
This is a while loop. The code written in the brackets will repeat as long as the boolean condition in the parenthesis evaluates to true. In this case, n must be greater than 0. One should be careful with while loops because you can easily create infinite loops by accident.
Another commonly used type of loop is the for loop, shown in the coding example below.
for(int n = 10; n > 0; n--) {}
For loops start by creating an index variable that serves as a counter. The second section in parenthesis gives the condition the index variables has to meet for the loop to continue running. This condition is a boolean expression that is checked before each iteration of the loop and must be true. The final statement in the parenthesis of the for loop indicates how the index variable changes after each iteration of the loop. In this case, the index variable is decremented by one at the end of each loop. This example loop will run ten times. Outside the for loop, the index variable is not in scope so it cannot be called or used in any calculations.
A really useful property of loops when making larger and more complex programs is the ability to nest loops inside one another and create larger outputs. The next example depicts this property.
These nested loops allow each subsequent line to have a different, more expanded output. Through tactical nested loops we can make creative outputs like this.
9/25/18
Researched piping in Linux and discovered how it can be used top create new commands and funnel multiple commands on a single line. Then, I used the find and replace command here to alter a text from a Charles Dickens novel:
sed -i -e 's/was/is/g' test.txt
Searches and replaces a keyword with another keyword
In our example, we initially had an unaltered
After the command “sed -i -e ‘s/was/is/g’ test.txt”:
The text has been successfully altered to the present tense.
9/18/18
We practiced writing scripts and created a testscript to search for files.
***Note: ARG gives the variable itself while $ARG gives the value of the variable.
set ARG=$1
Set the variable ARG to the value of the first input
echo $ARG
Prints the value of the variable ARG
find / -name "*$ARG*" - print
First, the find command indicates that this command will find some files in the home directory. It will search the "/" directory, which is the home directory. Then, it will search for files whose names contain $ARG, which is whatever is actually stored in the ARG variable. Finally, the command will print out all the pathways and locations of the files the find command found.
tcsh ./testscript.tcsh argument
This is how we run a test script we have written and insert a value to the variable ARG.
chmod +x testscript.tcsh
Changes the permission access of the testscript so that it can access certain directories and actually return the results you want it to. If you do not use it correctly, you will receive the following results.
Here, I wrote a basic home search script to find files with a certain argument in their name and save that list to a text file. We use the same commands as the testscript.tcsh file above, but we add the ">" command to addd the output of the find command into a new text file. We tested it by setting $ARG = testfile and searching for files with testfile in their name. This result was eventually stored in the text file and when we used the cat command to display the text file, we get the following list.
9/13/18
Linux Commands
echo $0
Outputs the shell type in Linux, which was bash for my system.
echo $SHELL
Outputs what directory you are in within the shells and how "deep" you are within the shell.
pwd
Outputs which directory you are currently in.
ls
Lists which files are contained in the current directory and which sub-directories are in the current directory (these are printed in blue).
ls -l
Creates a long list of the files with more data about file sizes and files creation times.
ls --help
Lists the other possible methods that can be used with the ls command and what they do.
mkdir new_directory
Makes a new directory titled "new_directory" (useful when reorganizing files).
cd new_directory
Changes current directory to "new_directory".
ls ..
Lists the files and directories contained one directory back from the current directory.
cd ..
Changes directory and shifts it back one directory.
rmdir new_directory
Removes elected directory but only if said directory is empty.
ls -CFx /usr/bin
Lists the files contained in the bin, which is the standard subdirectory for the root directory.
ls -l /bin
Lists the root files and methods contained in the bin
find /usr -name "*g++*" -print
Lists out files with the phrase "g++" in their name inside the user's bin library.
which g++
Gives the pathway to the "g++" file where the files from above were taken.
whoami
Prints which user you are.
touch file1 file2 test1 test2
Creates empty text files with names file1, file2, test1, and test2.
find . -name "test*"
Reveals files within the directory that start with name test.
find . -name "*1"
Reveals files within the current directory that end with a 1.
rm file1 file2 test1 test2
Deletes the 4 files listed so they can no longer be found when the the list command is used.
emacs -nw test.txt
Creates new text document in Emacs that looks like the following picture. It can be saved with control-x, control-c, y or with control-xs.
cat test.txt
Prints whatever is in the test.txt file in the terminal.
more test.txt
Same function as cat except it displays the text part by part for a particularly large text file.
> & >>
Commands that can be used to shift text into a text file without actually opening the text file and editing it.
We also used a 3D model of the collider at http://ispy-webgl.web.cern.ch/ispy-webgl/# and modeled some collisions. In the some of the events in the electron folder on the site, I observed positively charged leptons which I believe are actually positrons. This leads me to wonder how anti-matter was created in the collision and how exactly the leptons and neutrinos interacted within the accelerator. Also, it was interesting to see the different parts of the accelerator and put it together with different components.When I observed the reactions, there were a lot of colorful areas that I didn't understand what they were supposed to represent, but I'm sure I will soon enough.
10 New Commands I Found:
1. “sed -i ‘s/originaltext/replacement/g’ filename.txt”: This is a simple find and replace command where you can substitute strings of characters within a given text file. The example is quite clear below.
2. “locate -i *keyword*keyphrase*”: This command allows you to find the location of a file with certain keywords or phrases in its name. This is useful if you forget where a certain file was located and need to find it quickly.
3. “cat a.txt b.txt >> ab.txt”: This command is useful because it concatenates two text files and combines their content into one. We can use it when we begin to have a lot of data spread out over multiple files and want to simplify into only a single text.
4. “wget [insert url here]”: This command can be used to download files and directories from outside websites and save them to the virtual machine. It can be useful when we need to download additional data for analysis or more programs for further study.
5. “clear” : This is a very straightforward and simple command but is nonetheless quite useful. It removes all the lines in the terminal and reprints it as if you had just opened the terminal, which saves time and effort especially when dealing with commands and scripts that produce many output lines. I used the clear command to clean the terminal above and get it back to the following:
6. “top” and “kill”: This command reveals which processes are taking up the most memory and processing power in the CPU. If you need to run larger programs that require more processing power, you can use the kill command to stop unnecessary programs or scripts you don’t want to run anymore (need to know PID -> Process ID).
7. “history”: This command displays the history of previous commands used in the terminal. This can be extremely useful if something goes wrong with the virtual machine or some file is lost. You can retrace your steps and see which commands were used and how they affected the files in question.
8. “grep -iRl “keyword” ./”: This command searches the current directory for files that contain a given keyword as indicated in the command. For example, when the keyword is linux, the following files are found:
9. “/keyword”: When a text file is opened in terminal and you need to search for a keyword, you can use this command to find it. This command highlights all instances of the keyword so you can move through the document more easily. This is also helpful when using the find and replace command. In the screenshot below, the command was “/the”. Note that this command only works if the text document is opened using the less command.
10. “cmp file1 file2”: The command compares two text files and identifies where the difference is. This is useful for comparing data when the data or information is stored in text files.