# 4.3 Magnetic Anomaly Jupyter Notebook

Instructions

• To use this page, read the text between each of the python code windows, then press RUN to execute the code in the box.
• It is necessary to run each of the boxes in order.
• Don't click restart in the cells unless you come back to the top of the page and start over.
• If you modify the code, this modification will not remain after you leave or refresh this page.
• You must run simulations/cells that require user input to completion. Make sure you see the Message informing you a cell is complete before continuing to the next cell. Here's why you must do this:
• These cells may not be re-run until the simulation is completed, otherwise no output will be generated.
• All following cells will not run until the user input cell is completed.
• For Dropdown Menus: You do not need to rerun the cells with the menu to change your selection. However, you must rerun all of the following cells to implement the change.

Be patient, some times it can take 1-2 minutes for the juypter kernel to start.

An example about the distribution and patterns of seafloor magnetic anomalies, using real data.

• What is unique about the pattern of the seafloor stripes when there is a ridge in the data?
• When the spreading rate is increased, do the magnetic anomalies get closer to each other or farther apart? Stated differently, when the spreading rate is increased is the distance between the youngest and oldest age larger or smaller?
• When the spreading rate is decreased, why does it become difficult to distinguish individual anomalies?

First, let's import the necessary libraries, and load the data file. This cell is going to output a lot of information from the wget command, this is not an error and you may ignore this. This command searches the given url to load the file into the code cell, then np.loadtxt loads the data into a numpy array.

import numpy as np
import matplotlib.pyplot as plt
from pylab import rcParams
!wget "https://geo.libretexts.org/@api/deki/files/9811/polarity.txt?origin=mt-web"
print('The libraries are imported and the data is loaded, move on to the next cell')

Now that the data is loaded it must be organized. This dataset only listed the times that bound polarity changes, so to plot, we must assign a value of 0 for reverse polarity, or 1 for normal polarity.  The last piece of the cell defines some constants for conversion.

my_array = data.flatten()
seafloor_data = np.empty((len(my_array),2))
seafloor_data[:,0] = my_array
for i in range(len(my_array)):
if i % 2 == 0:
seafloor_data[i,1] = 0 # Reverse Polarity
else:
seafloor_data[i,1] = 1 # Normal Polarity

yr2my = 1e6   # yr/my
sec2yr = 3600*24*365   # s/yr

print('The data is organized and conversion constants defined')

This cell will guide you to create a magnetic polarity profile. The minimum time refers to the youngest age that you wish to view, and maximum time refers to the oldest age you wish to view. The rest of the questions are self-explanatory, so go ahead and create your model and use it to answer the key questions. Note: If you select the dead ridge option, the changes in the graph may not be that obvious so be sure to look at the distance axis and the information printed below the graph.

bbox = dict(boxstyle ="round", fc = '1')
print('First Let\'s examine an age range to look at the data. It is recommended not to exceed a 25 Ma age range for viewing purposes')
print('Please Enter Your Minimum Age as a multiple of 5 between 0 (active ridge) and 110 Ma:')

start_time = float(input())
while start_time < 0 or start_time > 110 or start_time % 5 != 0:
print('Invalid minimum age, Please Enter a time between 0 and 110 Ma (as a multiple of 5)')
start_time = float(input())
print('Now enter a maximum age, between',start_time,'Ma and 115 Ma (as a multiple of 5)')
end_time = float(input())
while end_time <= start_time or end_time > 115 or end_time % 5 != 0:
print('Invalid maximum age, Please Enter a time between', start_time,' and 115 Ma (as a multiple of 5)')
end_time = float(input())
if start_time == 0:
ridge = 'yes'
else:
print('Is the start time you Selected the Location of a dead ridge? Yes or No')
print('Note: If the location is not actually a dead ridge in the data, it will still be plotted symmetrically as if it were.')

ridge = input()
while ridge.lower() != 'yes' and ridge.lower() != 'no':
ridge = input()
ridge = ridge.lower()
subset_1 = seafloor_data[seafloor_data[:,0] >= start_time,:]
subset = subset_1[subset_1[:,0] <= end_time,:]
u_current = float(input())
while u_current < 1 or u_current >6:
print('Invalid spreading rate, please enter a number between 1 and 6 cm/yr')
u_current = float(input())

agesec = subset[:,0]*yr2my*sec2yr #s

x_new = agesec * (u_current/ 3.15e7 / 100) #m
handle = display(None, display_id=True)
if ridge == 'yes':

symm_subset = np.empty(np.shape(subset))
symm_subset[:,0] = (start_time-(subset[:,0])+start_time)
symm_subset[:,1] = (subset[:,1])
x_max = np.max(agesec * (6/ 3.15e7 / 100)) # m
x_min = np.min(agesec * (1/ 3.15e7 / 100)) # m
while u_current > 0 and u_current <= 6:
fill_list = []
plt.rcParams['figure.figsize'] = u_current+6, 5
fig, ax = plt.subplots()

ax1 = ax.twiny()

ax1.fill_betweenx((5,6),7,8,color='black',label = 'Normal Polarity')
ax1.fill_betweenx((5,6),7,8,color='white',label = 'Reverse Polarity')

x_new = agesec * (u_current/ 3.15e7 / 100) #m

ax.set_xlabel('Distance from Ridge (km)')
step, = ax1.step(subset[:,0],subset[:,1],color='black')
for j in range(len(subset[:,1])):
if j == 0:
continue
if subset[j,1] == 1:
ax1.fill_betweenx((0,1),subset[j-1,0],subset[j,0],color='black')
age_new = np.arange(x_min,x_max) / (u_current/ 3.15e7 / 100) / yr2my / sec2yr #my
x_new /= 1000

tick_locations = np.concatenate(((np.arange(start_time-(end_time-start_time),start_time,5),np.arange(start_time,end_time+5,5))))
tick_labels = np.concatenate((np.arange(end_time,start_time-5,-5),np.arange(start_time+5,end_time+5,5)))
dist_tick_locations = tick_locations *yr2my*sec2yr*(u_current/ 3.15e7 / 100)/1000 #km
median_index = np.where(dist_tick_locations == np.median(dist_tick_locations))[0][0]
dist_tick_labels = np.concatenate((np.flip(dist_tick_locations[median_index+1:]),dist_tick_locations[median_index:]))

ax1.step(symm_subset[:,0],symm_subset[:,1],color='black')
for j in range(len(symm_subset[:,1])):
if j == 0:
continue
if symm_subset[j,1] == 1:
fill_list.append(ax1.fill_betweenx((0,1),symm_subset[j-1,0],symm_subset[j,0],color='black'))

ax1.set_ylim(0,1)
ax1.set_yticks([0,1])
ax1.set_xticks(tick_locations)
ax1.set_xticklabels(tick_labels)
ax.set_xticks(dist_tick_locations)
ax1.set_xlim(np.min(tick_locations),np.max(tick_locations))
ax.set_xlim(np.min(dist_tick_locations),np.max(dist_tick_locations))
ax.set_xticklabels(np.round(dist_tick_labels))
ax1.set_xlabel('Age (Ma)')
ax1.legend(bbox_to_anchor=(1.01, 1))

center_txt = ax.text(np.min(dist_tick_locations),-.2,'Dead Ridge Location: '+'{:.2f}'.format(np.min(x_new))+' km',bbox=bbox)
text = ax.text(np.min(dist_tick_locations),-.3,'Distance from Dead Ridge to the farthest selected time: '+'{:.2f}'.format(np.max(x_new)-np.min(x_new))+' km',bbox=bbox)
handle.update(fig)
step.remove()
for i in fill_list:
i.remove()
center_txt.remove()
text.remove()
dist_tick_labels = []
dist_tick_loc = []
print('Enter a number outside of the range to end the simulation')
u_current = float(input())
plt.close()
print('The simulation is complete. You can rerun for different ages by going back up and clicking on Run again.')
else:
fig, ax = plt.subplots(figsize=(15,5))
ax1 = ax.twiny()

ax.set_xlabel('Distance from Ridge (km)')

x_max = np.max(agesec * (6/ 3.15e7 / 100)) # m
x_min = np.min(agesec * (1/ 3.15e7 / 100)) # m

ax.fill_betweenx((5,6),7,8,color='black',label = 'Normal Polarity')
ax.fill_betweenx((5,6),7,8,color='white',label = 'Reverse Polarity')
ax.set_xlim(x_min/1000,x_max/1000)

ax.set_ylim(0,1)
ax.set_yticks([0,1])
ax.set_yticklabels(['Reversed Polarity','Normal Polarity'])
ax1.set_xlabel('Age (Ma)')
line4, = ax1.plot(subset[:,0],-np.ones(len(subset[:,0])))
while u_current > 0 and u_current <= 6:
print('Now plotting:',u_current,'cm/yr')

x_new = agesec * (u_current/ 3.15e7 / 100)
age_new = x_new / (u_current/ 3.15e7 / 100) / yr2my / sec2yr #my
ax1.set_xlim(np.min(age_new),np.max(age_new))
step, = ax.step(x_new/1000,subset[:,1],color='black')
fill_list = []
for j in range(len(subset[:,1])):
if j == 0:
continue
if subset[j,1] == 1:
fill_list.append(ax.fill_betweenx((0,1),x_new[j-1]/1000,x_new[j]/1000,color='black'))
line4.set_ydata(-np.ones(len(age_new)))
line4.set_xdata(age_new)

ax.legend(bbox_to_anchor=(1.01, 1))
print('Note: Data is not shown for the ages outside the range you selected')
handle.update(fig)

step.remove()
for i in fill_list:
i.remove()

print('Enter a number outside of the range to end the simulation')
print('The simulation is complete. You can rerun for different ages by going back up and clicking on Run again.')