I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Let's look at some statistics and save the scores we have computed:
Can you write Python code for it?

df = pd.DataFrame( scores, columns=['scores'] )
df.to_csv("transferBasedScoresCanonicalRoot_Var500.csv")
print(df.describe())


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Let's look at the least supported and most supported trees. First, the least supported tree:
Can you write Python code for it?

minScore= np.min(scores)
leastSupportedTree=allTrees[0].copy()
for i in range(len(scores)):
    if scores[i]==minScore:
        leastSupportedTree=allTrees[i].copy()
        break
ts = TreeStyle()
ts.min_leaf_separation= 0
ts.scale = 2020
nstyle = NodeStyle()
nstyle["size"] = 0
for n in leastSupportedTree.traverse():
   n.set_style(nstyle)

leastSupportedTree.render("%%inline", tree_style=ts)


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Let's reopen the scores:
Can you write Python code for it?

df = pd.read_csv("transferBasedScoresCanonicalTree.csv")
scores = df['scores']


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Now we compute more discriminating scores:
Can you write Python code for it?

scores2 = scores - np.min(scores)
df2 = pd.DataFrame( scores2, columns=['scores'] )
print ("Score 2: ")
print(df2.describe())
df2.to_csv("transferBasedScoresCanonicalRoot_Var500_Version2.csv")

def square (x):
    return math.pow(x,2)

def ten (x):
    return math.pow(x,10)

scores3 = list(map(ten, (scores - np.min(scores)) ) )
df3 = pd.DataFrame( scores3, columns=['scores'] )
print ("Score 3: ")
print(df3.describe())
df2.to_csv("transferBasedScoresCanonicalRoot_Var500_Version3.csv")


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Now we find the link between numbers and underlying leaf names.
Can you write Python code for it?

def getNameToLeavesLink( t ):
    node2leaves = t.get_cached_content()
    nodeId2LeafList = dict()
    leafList2NodeId = dict()
    for k in node2leaves.keys():
        if len(node2leaves[k]) == 1: #leaf node
            pass
        else:
            nodelist = list()
            for n in node2leaves[k]:
                nodelist.append( n.name )
            nodelist.sort()
            nodeId2LeafList[k.support] = nodelist
            leafList2NodeId[tuple(nodelist)] = int(k.support) # Need to transform the mutable list into an immutable tuple
    return nodeId2LeafList, leafList2NodeId

nodeId2LeafListRef, leafList2NodeIdRef = getNameToLeavesLink( t )
print ("Number of internal leaves = " + str(len(nodeId2LeafListRef)) )


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Now, the second scores:
Can you write Python code for it?

%matplotlib inline
plotSingleCorrelation(unweightedIntervals, weightedIntervals2,"Unweighted intervals","Weighted intervals")


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Now, the weighted chronogram, using the first scores.
Can you write Python code for it?

weightedChrono = allTrees[0].copy()
weightedAges = list()
for node in weightedChrono.traverse("postorder"):
    id = 0
    if node.name != "":
        id = node.name
    else:
        id = str(node.support)
    v = list()
    for i in id2Heights:
        v.append(i[id])
    sd = np.std(v)
    min = np.min(v)
    max = np.max(v)
    dftempWithWeight = pd.DataFrame({ 'kItem':v, 'scores': normalizedScores }, dtype='float')
    ciMin, ciMax = compute95PcCredibilityIntervalWeightedDF(dftempWithWeight)
    mean, median = computeWeightedMeanAndMedian(dftempWithWeight)
    node.add_features(support=1.0, age_median=median, age_mean=mean, age_sd=sd, age_range="{"+str(min)+","+str(max)+"}", age_quant_5_95="{"+str(ciMin)+","+str(ciMax)+"}")
    # We also change the node age to the median value
    children = node.get_children()
    for c in children:
        c.dist = node.age_median - c.age_median
    weightedAges.append(median)

weightedChrono.write(features=[], outfile="weightedChronogram_Var500.nhx")

weightedChronoFigTree = weightedChrono.write(features=[]).replace("&&NHX:", "&").replace(":age", ",age").replace(":name", ",name").replace(":support", ",support").replace(":dist", ",dist").replace("_0", ",0")

fout = "weightedChronoFigTreeFormat_Var500.tree"

try:
    f=open(fout, 'w')
except IOError:
    print ("Unknown file: "+fout)
    sys.exit()

f.write("#NEXUS\n")
f.write("BEGIN TAXA;\n")
f.write("DIMENSIONS NTAX="+str(len(weightedChrono))+";\n")
f.write("TAXLABELS\n")
for l in weightedChrono:
    f.write(l.name+"\n")

f.write(";\n")
f.write("END;\n")

f.write("BEGIN TREES;\n")

f.write("TREE 0 = [&R] " + weightedChronoFigTree)

f.write("\nEND;\n")

f.close()


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Outputting the weighted trees
Can you write Python code for it?

fout="transferWeightedTrees_Var500.trees"

try:
    f=open(fout, 'w')
except IOError:
    print ("Unknown file: "+fout)
    sys.exit()

i = 0
for t in allTrees:
    f.write("[&W "+str(normalizedScores[i] )+"]"+"\t"+t.write()+"\n")
    i = i+1

f.close()

fout="transferWeightedTrees_Var500_Version2.trees"

try:
    f=open(fout, 'w')
except IOError:
    print ("Unknown file: "+fout)
    sys.exit()

i = 0
for t in allTrees:
    f.write("[&W "+str(normalizedScores2[i] )+"]"+"\t"+t.write()+"\n")
    i = i+1

f.close()

fout="transferWeightedTrees_Var500_Version3.trees"

try:
    f=open(fout, 'w')
except IOError:
    print ("Unknown file: "+fout)
    sys.exit()

i = 0
for t in allTrees:
    f.write("[&W "+str(normalizedScores3[i] )+"]"+"\t"+t.write()+"\n")
    i = i+1

f.close()


I am working on the file "Notebooks/Reweighting a fastdate chronogram distribution that was generated with high variance.ipynb".
The first task is:
Reading the constraints based on transfers detected using ALEml_undated:
Can you write Python code for it?

fileC = "CanonicalRoot_constraints.txt" # in which the first one is older than the second one
try:
    f=open(fileC, 'r')
except IOError:
    print ("Unknown file: "+fileC)
    sys.exit()

constraints = list()
for l in f:
    constraints.append( l.split() )

f.close()

print("Number of constraints: "+str(len(constraints)))


I am working on the file "Notebooks/Rotary_Pendulum.ipynb".
The first task is:
Calculate angular velocity and momentum about $Q$ in $\mathcal C$ frame components
Can you write Python code for it?

iWc = bWc + cCb*iWb
h_Q = I_Q*iWc
iWc,h_Q


I am working on the file "Notebooks/Rotary_Pendulum.ipynb".
The first task is:
Define all the symbols you'll need
Can you write Python code for it?

th,psi,thd,psid,R,g,t,l,thdd,phdd,psidd,N1,N2,N3,mr,tau,J  = \
symbols('theta,psi,thetadot,psidot,R,g,t,l,thetaddot,phiddot,psiddot,N_1,N_2,N_3,m_r,tau,J')
diffdict = {th:thd,thd:thdd,psi:psid,psid:psidd}


I am working on the file "Notebooks/Rotary_Pendulum.ipynb".
The first task is:
Finally, combine the solutions to the disk and rod motions for the full equations of motion
Can you write Python code for it?

simplify(solve([thdd - eom2[thdd],psidd - eom1[psidd].subs(N1,Ns[N1])],(psidd,thdd)))


I am working on the file "Notebooks/Rotary_Pendulum.ipynb".
The first task is:
Now apply Euler's second law for rod about $Q$ (all in $\mathcal C$ frame)
Can you write Python code for it?

dh_Q = transportEq(h_Q,t,diffdict,iWc)
M_Q = Matrix([tau,mr*g*l/2*sin(th),0])
r_QO = cCb*Matrix([0,R,0])
a_QO = simplify(transportEq(transportEq(r_QO,t,diffdict,iWc),t,diffdict,iWc))
dh_Q,M_Q,a_QO

r_QG = Matrix([0,0,-l/2])
eom2 = solve(dh_Q - (M_Q + mr*r_QG.cross(a_QO)),thdd)
eom2


I am working on the file "Notebooks/Rotary_Pendulum.ipynb".
The first task is:
Parallel axis theorem to get MOI matrix for the rod about $Q$
Can you write Python code for it?


I am working on the file "Notebooks/Rotary_Pendulum.ipynb".
The first task is:
Solve for normal forces by applying Euler's first law to rod COM
Can you write Python code for it?

Ns = solve(mr*a_GO - Matrix([N1,N2,mr*g-N3]),(N1,N2,N3));Ns


I am working on the file "Notebooks/Running Code.ipynb".
The first task is:
Beyond a certain point, output will scroll automatically:
Can you write Python code for it?

for i in range(500):
    print(2**i - 1)


I am working on the file "Notebooks/Running Code.ipynb".
The first task is:
Cell menu
The "Cell" menu has a number of menu items for running code in different ways. These includes:

Run and Select Below
Run and Insert Below
Run All
Run All Above
Run All Below

Restarting the kernels
The kernel maintains the state of a notebook's computations. You can reset this state by restarting the kernel. This is done by clicking on the <button class='btn btn-default btn-xs'><i class='fa fa-repeat icon-repeat'></i></button> in the toolbar above.
sys.stdout and sys.stderr
The stdout and stderr streams are displayed as text in the output area.
Can you write Python code for it?

print("hi, stdout")

from __future__ import print_function
print('hi, stderr', file=sys.stderr)


I am working on the file "Notebooks/Running Code.ipynb".
The first task is:
If the Kernel dies you will be prompted to restart it. Here we call the low-level system libc.time routine with the wrong argument via
ctypes to segfault the Python interpreter:
Can you write Python code for it?

import sys
from ctypes import CDLL
# This will crash a Linux or Mac system
# equivalent calls can be made on Windows
dll = 'dylib' if sys.platform == 'darwin' else 'so.6'
libc = CDLL("libc.%s" % dll)
libc.time(-1)  # BOOM!!


I am working on the file "Notebooks/Running Code.ipynb".
The first task is:
Large outputs
To better handle large outputs, the output area can be collapsed. Run the following cell and then single- or double- click on the active area to the left of the output:
Can you write Python code for it?


I am working on the file "Notebooks/Running Code.ipynb".
The first task is:
There are two other keyboard shortcuts for running code:

Alt-Enter runs the current cell and inserts a new one below.
Ctrl-Enter run the current cell and enters command mode.

Managing the IPython Kernel
Code is run in a separate process called the IPython Kernel.  The Kernel can be interrupted or restarted.  Try running the following cell and then hit the <button class='btn btn-default btn-xs'><i class='icon-stop fa fa-stop'></i></button> button in the toolbar above.
Can you write Python code for it?


I am working on the file "Notebooks/SVM/zh-cn/Kernel Methods.ipynb".
The first task is:
和 sklearn 的 SVM 进行比较
Can you write Python code for it?

from sklearn.svm import SVC

svm = SVC()
svm.fit(xc, yc)
visualize2d(svm, xc, yc, True)
print("准确率：{:8.6} %".format((svm.predict(xc) == yc).mean() * 100))
svm.fit(xs, ys)
visualize2d(svm, xs, ys, True)
print("准确率：{:8.6} %".format((svm.predict(xs) == ys).mean() * 100))


I am working on the file "Notebooks/SVM/zh-cn/Kernel Methods.ipynb".
The first task is:
在非线性数据集上进行测试
Can you write Python code for it?

svm = SVM()
svm.fit(xs, ys)
print("准确率：{:8.6} %".format((svm.predict(xs) == ys).mean() * 100))
visualize2d(svm, xs, ys, True)


I am working on the file "Notebooks/SVM/zh-cn/Kernel Methods.ipynb".
The first task is:
核 SVM
用同样的手法不难得出 LinearSVM 的核形式：
$$
L(D)=\frac12\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jK(x_i,x_j)+C\sum_{i=1}^N\left[ 1-y_i\left(\sum_{j=1}^N\alpha_jK(x_i, x_j)+b\right)\right]_+
$$
可知求导仍然并不困难
Can you write Python code for it?

class SVM(KP):
    def fit(self, x, y, kernel="rbf", p=None, gamma=None, c=1, lr=0.0001, batch_size=128, epoch=10000):
        x, y = np.asarray(x, np.float32), np.asarray(y, np.float32)
        if kernel == "poly":
            p = 4 if p is None else p
            self._kernel = lambda x_, y_: self._poly(x_, y_, p)
        elif kernel == "rbf":
            gamma = 1 / x.shape[1] if gamma is None else gamma
            self._kernel = lambda x_, y_: self._rbf(x_, y_, gamma)
        else:
            raise NotImplementedError("Kernel '{}' has not defined".format(kernel))
        self._alpha = np.zeros(len(x))
        self._b = 0.
        self._x = x
        k_mat = self._kernel(x, x)
        k_mat_diag = np.diag(k_mat)
        for _ in range(epoch):
            self._alpha -= lr * (np.sum(self._alpha * k_mat, axis=1) + self._alpha * k_mat_diag) * 0.5
            indices = np.random.permutation(len(y))[:batch_size]
            k_mat_batch, y_batch = k_mat[indices], y[indices]
            err = 1 - y_batch * (k_mat_batch.dot(self._alpha) + self._b)
            if np.max(err) <= 0:
                continue
            mask = err > 0
            delta = c * lr * y_batch[mask]
            self._alpha += np.sum(delta[..., None] * k_mat_batch[mask], axis=0)
            self._b += np.sum(delta)


I am working on the file "Notebooks/SVM/zh-cn/LinearSVM.ipynb".
The first task is:
Mini-Batch 梯度下降法（MBGD）

上述解决方案已经不错，但我们还是有些太“激进”了——我们每次进行梯度下降时，选取的样本点都是使得损失函数最大的样本点，但一般而言使损失函数最大的样本点如果不是关键的样本点（支持向量）的话、通常而言会是噪声。当数据集比较差时，噪声所带来的副作用很有可能就会盖过支持向量带来的正效应
为此，我们应该引入一定的随机性。神经网络的训练中所用的 MBGD 就是很好的方法：每次都从数据集中抽样出一个小 Batch，然后用这个 Batch 来做梯度下降
Can you write Python code for it?

class LinearSVM3(LinearSVM):
    def fit(self, x, y, c=1, lr=0.01, batch_size=128, epoch=10000):
        x, y = np.asarray(x, np.float32), np.asarray(y, np.float32)
        batch_size = min(batch_size, len(y))
        self._w = np.zeros(x.shape[1])
        self._b = 0.
        for _ in range(epoch):
            self._w *= 1 - lr
            # 随机选取 batch_size 个样本
            batch = np.random.choice(len(x), batch_size)
            x_batch, y_batch = x[batch], y[batch]
            err = 1 - y_batch * self.predict(x_batch, True)
            if np.max(err) <= 0:
                continue
            mask = err > 0
            delta = lr * c * y_batch[mask]
            self._w += np.mean(delta[..., None] * x_batch[mask], axis=0)
            self._b += np.mean(delta)


I am working on the file "Notebooks/SVM/zh-cn/LinearSVM.ipynb".
The first task is:
可视化
Can you write Python code for it?

from Util import visualize2d

visualize2d(svm, x, y)
visualize2d(svm, x, y, True)


I am working on the file "Notebooks/SVM/zh-cn/LinearSVM.ipynb".
The first task is:
存在的问题
Top n LinearSVM 和 MBGD LinearSVM 各有优劣，很难直接说谁好谁坏；但它们都有一个共同的问题，那就是它们所运用的梯度下降法都只是朴素的Vanilla Update，这会导致当数据的 scale 很大时模型对参数极为敏感、从而导致持续的震荡（所谓的 scale 比较大，可以理解为“规模很大”，或者直白一点——以二维数据为例的话——就是横纵坐标的数值很大）
可以通过下面这个栗子来直观感受一下 scale 很大的数据所带来的问题：
Can you write Python code for it?

# 将 scale 从 1（默认）调成 5
x, y = gen_two_clusters(center=5, scale=5)
top_n_svm = LinearSVM2()
top_n_svm.fit(x, y)
print("Top n LinearSVM 准确率：{:8.6} %".format((top_n_svm.predict(x) == y).mean() * 100))
mbgd_svm = LinearSVM3()
mbgd_svm.fit(x, y)
print("MBGD  LinearSVM 准确率：{:8.6} %".format((mbgd_svm.predict(x) == y).mean() * 100))

visualize2d(top_n_svm, x, y)
visualize2d(mbgd_svm, x, y)


I am working on the file "Notebooks/SVM/zh-cn/LinearSVM.ipynb".
The first task is:
测试
Can you write Python code for it?

from Util import gen_two_clusters

x, y = gen_two_clusters()
svm = LinearSVM()
svm.fit(x, y)
print("准确率：{:8.6} %".format((svm.predict(x) == y).mean() * 100))


x, y = gen_two_clusters(center=5, dis=1)
svm = LinearSVM2()
svm.fit(x, y)
print("准确率：{:8.6} %".format((svm.predict(x) == y).mean() * 100))
visualize2d(svm, x, y)
visualize2d(svm, x, y, True)


I am working on the file "Notebooks/SVM/zh-cn/LinearSVM.ipynb".
The first task is:
通过下面这张动图，我们能够直观地感受极大梯度下降法下 LinearSVM 的训练过程：

可以看到，LinearSVM 确实卡在了奇怪的地方
原理我不敢乱说，这里只提供一个牵强附会的直观解释：

每次只取使得损失函数极大的一个样本进行梯度下降$\rightarrow$模型在某个地方可能来来回回都只受那么几个样本的影响$\rightarrow$死循环（什么鬼！）

专业的理论就留待专业的观众老爷补充吧 ( σ'ω')σ
解决方案
极大梯度下降法的最大问题很有可能在于它每次都只根据使得损失函数最大的一个样本点来进行梯度下降，这会导致两个问题：
+ 模型的训练将会很不稳定（这点和随机梯度下降类似）
+ 模型对噪声或“不太好的点”极为敏感（因为它们往往会使损失函数最大）
按部就班、我们先解决第一个问题，为此我们只需要多选出几个样本点（比如选出使得损失函数最大的 top n 个样本）、然后取它们梯度的平均即可
Top n 梯度下降法

注：该名字同样只是我瞎编的一个名字（喂）
Can you write Python code for it?

# 继承上一个 LinearSVM 以重复利用代码
class LinearSVM2(LinearSVM):
    # 用参数 batch_size 表示 Top n 中的 n
    def fit(self, x, y, c=1, lr=0.01, batch_size=128, epoch=10000):
        x, y = np.asarray(x, np.float32), np.asarray(y, np.float32)
        # 如果 batch_size 设得比样本总数还多、则将其改为样本总数
        batch_size = min(batch_size, len(y))
        self._w = np.zeros(x.shape[1])
        self._b = 0.
        for _ in range(epoch):
            self._w *= 1 - lr
            err = 1 - y * self.predict(x, True)
            # 利用 argsort 函数直接取出 Top n
            # 注意 argsort 的结果是从小到大的，所以要用 [::-1] 把结果翻转一下
            batch = np.argsort(err)[-batch_size:][::-1]
            err = err[batch]
            if err[0] <= 0:
                continue
            # 注意这里我们只能利用误分类的样本做梯度下降
            # 因为被正确分类的样本处、这一部分的梯度为 0
            mask = err > 0
            batch = batch[mask]
            # 取各梯度平均并做一步梯度下降
            delta = lr * c * y[batch]
            self._w += np.mean(delta[..., None] * x[batch], axis=0)
            self._b += np.mean(delta)


I am working on the file "Notebooks/Sample_fasta_with_mutations.ipynb".
The first task is:
Example from a test dataset on the forward on reverse strand with increasing frequency of mutations
Can you write Python code for it?

a = SeqIO.read("./data/test.fa", "fasta")

with open ("./data/sample.fa", "w") as fp:
    for i in range(1, 51):
        fp.write(">query_{:03d}%_mutation_forward\n".format(i))
        start = randint (0, len(a.seq)-100)
        fp.write("{}\n".format(mutate_seq(str(a.seq)[start:start+100], i/100.0)))
    for i in range(1, 51):
        fp.write(">query_{:03d}%_mutation_reverse\n".format(i))
        start = randint (0, len(a.seq)-100)
        fp.write("{}\n".format(mutate_seq(str(a.seq.reverse_complement())[start:start+100], i/100.0)))


I am working on the file "Notebooks/Sample_fasta_with_mutations.ipynb".
The first task is:
Simple function introducting mutations in a sequence (lower bases) at a given frequency
Can you write Python code for it?

def mutate_seq (seq, freq):
    str= ""
    for i in seq:
        if uniform(0,1) <= freq:
            str+=choice([b for b in ["a","t","c","g"] if b != i.lower()])
        else:
            str+=i.upper()
    return str

mutate_seq ("CTCGATCGCTAGCATGCATCGTCGCATGCTCGATCAGCTAGCAGCATCAGCTAGCTGCATCAGTCA", 0.1)


I am working on the file "Notebooks/Scattering/raygun.ipynb".
The first task is:
Here's some data that sees the caduceus / raygun noise.
Can you write Python code for it?

chan='L1:LSC-POP_A_RF9_I_ERR_DQ'
st=1162024217
dur=600

data=TimeSeries.fetch(chan,st,st+dur)

srate=data.sample_rate.value


I am working on the file "Notebooks/Scattering/raygun.ipynb".
The first task is:
The functions below take a short segment of data, do a zero-padded FFT (to do some extra smoothing), then find the largest peak above and below 120 Hz.
Can you write Python code for it?

twid=int(srate) # Length of short spectra
zpadsec=8 # Length (sec) for oversampled FFT
zpadwid=int(srate*zpadsec)

win1=sig.hann(twid)
def myfft(data,tt):
    idx=int(tt*srate)-twid/2
    tmp=zeros(int(zpadsec*srate))
    tmp[:twid]=win1*data.value[idx:idx+twid]
    tmp=rfft(tmp)
    return tmp[100*zpadsec:140*zpadsec]

def track_lines(data,tt):
    fft1=myfft(data,tt)
    i1=abs(fft1[:20*zpadsec+1]).argmax()
    i2=abs(fft1[20*zpadsec:]).argmax()+20*zpadsec
    return (tt,i1/float(zpadsec)+100.,i2/float(zpadsec)+100) #,fft1[i1],fft1[i2])


I am working on the file "Notebooks/Scattering/raygun.ipynb".
The first task is:
To make the spectrogram look nice, we'll do some bandpassing. This is left over from my previous attempt to do a Hilbert transform and get the phase directly, but I like the results.
Can you write Python code for it?

filt=sig.firwin(int(8*srate),[105./nyq,135./nyq],window='hann',pass_zero=False)
filt.resize(len(data))
ffilt=abs(rfft(filt))

fdata=ffilt*rfft(data.detrend().value)
fdata[0]=0.
newdata=TimeSeries(irfft(fdata)[int(4*srate):-int(4*srate)],sample_rate=srate)

p1=newdata[:int(srate*120)].spectrogram2(1,0.98).plot()
plt.plot(tst[:,0]-4,tst[:,1],c='r')
plt.plot(tst[:,0]-4,tst[:,2],c='r')
#p1.gca().set_yscale('log')
p1.gca().set_ylim(100,140)


I am working on the file "Notebooks/Season_color_new_specs.ipynb".
The first task is:
Check ObitoFlu dataset situation
Can you write Python code for it?

red_alert = contingency_alert(dataset_id=3, year=year, territory_id=territory_id)
red_alert


I am working on the file "Notebooks/Season_color_new_specs.ipynb".
The first task is:
Check SRAGFlu dataset situation
Can you write Python code for it?

orange_alert = contingency_alert(dataset_id=2, year=year, territory_id=territory_id)
orange_alert


I am working on the file "Notebooks/Simple Rotations.ipynb".
The first task is:
As a sanity check, show that ${}^\mathcal{B}C^\mathcal{A} [\mathbf{\hat{n}}] = [\mathbf{\hat{n}}]$
Can you write Python code for it?


I am working on the file "Notebooks/Simulating_phylogenetic_inertia.ipynb".
The first task is:
Are those two traits correlated?
Can you write Python code for it?

from scipy.stats import pearsonr

sns.lmplot("values", "values2", data=simu_tree_1_and_2)
print("Pearson correlation coefficient and p-value: "+ str(pearsonr(simu_tree_1_and_2['values'], simu_tree_1_and_2['values2'])))


I am working on the file "Notebooks/Simulating_phylogenetic_inertia.ipynb".
The first task is:
Does it look like a Normal distribution? We can fit a Normal distribution to our data.
Can you write Python code for it?

from scipy.stats import norm
sns.distplot(end_values, fit=norm)


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Como vemos, dadas las condiciones iniciales, se requiere un tiempo adimensionalizado del orden de $10^{21}$ para que el sistema colapse (suponiendo que el modelo es válido incluso a pequeñas distancias, cosa que en realidad no es cierta).
A continuación, graficamos las cantidades físicas (con dimensiones):
Can you write Python code for it?

fig,eje = plt.subplots(1,1,figsize=(5,5))
eje.plot(t_a,a_m)
eje.set_title(u'Evolución del semieje mayor',fontsize=15)
eje.set_xlabel(r'$t\ (a\~nos)$',fontsize=15)
eje.set_ylabel(r'$a (m)$',fontsize=15)
plt.grid()


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Como vemos, en el tiempo de observación del pulsar binario, aproximadamente 30 años, el decaimiento tanto de $a$ como $e$ será en la práctica a una tasa constante (línea recta en el gráfico en función del tiempo).
Resolvemos nuevamente el sistema, pero sólo en el intervalo de tiempo de 30 años:
Can you write Python code for it?

t_max_a = 30 # tiempo de integración, en años
tt_int_max = 31557600*c*t_max_a/R_ast #tiempo adimensional máximo de integración

tt_int = np.linspace(0,tt_int_max,100000)
print('tt_int_max = '+str(tt_int_max))

tt,t_a,at,e,a_m,T_s = solucion(x0,tt_int)

fig,eje = plt.subplots(1,1,figsize=(5,5))
eje.plot(t_a,at/at0-1)
eje.set_title(u'Evolución del semieje mayor',fontsize=15)
eje.set_xlabel(r'$t\ (a\~nos)$',fontsize=15)
eje.set_ylabel(r'$(a-a_0)/a_0$',fontsize=15)
plt.grid()

fig,eje = plt.subplots(1,1,figsize=(5,5))
eje.plot(t_a,e-e0)
eje.set_title(u'Evolución de la excentricidad',fontsize=15)
eje.set_xlabel(r'$t\ (a\~nos)$',fontsize=15)
eje.set_ylabel(r'$e$',fontsize=15)
plt.grid()

T_h = T_s/3600. # periodo orbital, en horas

fig,eje = plt.subplots(1,1,figsize=(5,5))
eje.plot(t_a,T_h-T_h[0])
eje.set_title(u'Evolución del periodo orbiral',fontsize=15)
eje.set_xlabel(u'$t$ (años)',fontsize=15)
eje.set_ylabel(r'$T-T_0$ (horas)',fontsize=15)
plt.grid()


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Dado que aquí resolveremos el sistema de ecuaciones dos veces (con distintas condiciones iniciales), definiremos una función que nos entrega todas las soluciones:
Can you write Python code for it?

def solucion(x0,tt_int):
    print 'Se resuelve con at0 = %2.f y e0 = %2.f'%(x0[0],x0[1])
    sol = odeint(dotx,x0,tt_int)
    at_todos = sol[:,0]
    # verifica si at llega a 2. En caso positivo corta el arreglo de soluciones
    restriccion = np.where(at_todos<2)[0]
    if len(restriccion) is not 0:
        pos_ttmax = restriccion[0] # determina el tiempo en el que at=2
        print('Acortando intervalo a tt_max = '+str(tt_int[pos_ttmax]))
    else:
        pos_ttmax = len(tt_int)
    tt = tt_int[:pos_ttmax]
    t_a = tt*R_ast/c/31557600 # el tiempo, en años
    at = sol[:pos_ttmax,0]
    e = sol[:pos_ttmax,1]
    a_m = at*R_ast # solución de a, en metros
    T_s = T(a_m) # solución de T, en segundos
    return tt,t_a,at,e,a_m,T_s


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Definimos también un par de funciones que relacionan el periodo orbital $T$ (en segundos) con el semieje mayor $a$ (de la coordenada relativa, en metros), y viceversa:
Can you write Python code for it?

def a(T_s):
    return (m_sol*M*(c*T_s/(2*np.pi))**2)**(1/3)

def T(a_m):
    return (2*np.pi/c)*(a_m**3/(M*m_sol))**(1/2)

a0_m = a(T0_s) # a inicial, en metros
at0 = a0_m/R_ast # a tilde inicial
print('a0 = '+str(a0_m)+' m')
print('at0 = '+str(at0))


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Este valor concuerda con el reportado por Weisberg, Nice y Taylor (2010) (http://arxiv.org/abs/1011.0718v1), ver ec. (4).
Para comparar con los datos observacionales, cargamos los valores del retardo acumulado, obtenidos a partir del gráfico original de Wiesberg, Nice y Taylor (2010) usando WebPlotDigitizer para extraer los valores.
Can you write Python code for it?

data = np.genfromtxt('data-HT.txt')
t_exp = data[:,0]-data[0,0]
Delta_t_exp = data[:,1]

fig,eje = plt.subplots(1,1,figsize=(5,5))
n = np.arange(40000)
t_n = (n*T0_s+dotT*T0_s*n*(n-1)/2.)/31557600. # tiempo, en años
Delta_t_n = dotT*T0_s*n*(n-1)/2 #retraso acumulado, en segundos
eje.plot(t_n,Delta_t_n, label='RG')
eje.hlines(0,0,40, color='red',label='Newtoniano')
eje.set_xlabel(u'Tiempo (años)')
eje.set_ylabel(r'Retraso acumulado (s)')
eje.set_xlim(0,35)
eje.set_ylim(-45,1)
plt.plot(t_exp,Delta_t_exp,'o',label='Datos')
eje.legend(loc=3)
plt.grid()


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Graficando la dependencia de $a$ con $e$
Primero definimos la función $g(e)$ y la graficamos
Can you write Python code for it?

def g(e):
    return e**(12/19)*(1+121*e**2/304)**(870/2299)/(1-e**2)

fig,eje= plt.subplots(1,1,figsize=(5,5))
ee = np.linspace(0,1,100)
eje.plot(ee,g(ee))
eje.set_yscale('log')
eje.set_title(r'$g$ versus $e$',fontsize=15)
eje.set_xlabel(r'$e$',fontsize=15)
eje.set_ylabel(r'$g$',fontsize=15)
#plt.legend(loc='best')
plt.grid()


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
La constante $C_1$ es determinada por la condición inicial $a(e_0)=a_0$ que, luego de ser reemplazada de vuelta en la solución, entrega la misma expresión encontrada por el otro método.
Solución numérica
Can you write Python code for it?

%matplotlib inline

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from __future__ import division


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Si definimos
$$
g(e):= \frac{e^{12/19}}{1-e^2}\left(1+\frac{121}{304} \right)^{870/2299},
$$
entonces la solución para $a(e)$ puede escribirse como
$$
a(e)=a_{0}\frac{g(e)}{g(e_{0})}.
$$
Alternativamente, podemos intentar usar la función dsolve de sympy para resolver directamente la EDO determinada por la expresión de $da/dt$ descrita arriba:
Can you write Python code for it?

af = Function('a')
solucion = dsolve(Derivative(af(e),e)-af(e)*integrando,af(e))
solucion


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Usamos los datos del Pulsar de Hulse y Taulor, de acuerdo a lo por Weisberg, Nice  y Taylor (2010) (http://arxiv.org/abs/1011.0718v1):
Can you write Python code for it?

T0_d = 0.322997448911 # periodo inicial, en días
e0 = 0.6171334 # excentricidad inicial
M_c = 1.3886 # masa de la compañera, en masas solares
M_p = 1.4398 # masa del pulsar, en masas solares
c = 299792458 # rapidez de la luz, en metros por segundo
MGcm3 = 4.925490947E-6 # MG/c^3, en segundos


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
Vemos entonces que el tiempo de colapso es del orden de $10^8$ años.
Podemos también graficar cómo evoluciona la excentricidad:
Can you write Python code for it?

fig,eje = plt.subplots(1,1,figsize=(5,5))
eje.plot(t_a,e)
eje.set_title(u'Evolución de la excentricidad',fontsize=15)
eje.set_xlabel(r'$t\ (a\~nos)$',fontsize=15)
eje.set_ylabel(r'$e$',fontsize=15)
plt.grid()


I am working on the file "Notebooks/Sistema_Binario-Evolucion_Temporal_y_observaciones_HyT.ipynb".
The first task is:
y ahora exponenciamos:
Can you write Python code for it?


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
$$
\left\langle P\right\rangle=\frac{2 G^4 \mu^2 M^3}{15 c^5 a^5 (1 − e^2 )^5} \left\langle g(\varphi)\right\rangle
$$
Can you write Python code for it?

promedio_g = simplify(((1-e**2)**(3/2))/(2*pi))*integrate(g/(1+e*cos(phi-phi0))**2,(phi,0,2*pi))

trigsimp(promedio_g)


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Ahora ingresamos la forma de la órbita Kepleriana, en términos de $a, e, \varphi$ y $\varphi_0$:
Can you write Python code for it?


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Ahora sustituimos los valores de las componentes del momento cuadrupolar en función de las coordenadas del sistema reducido:
Can you write Python code for it?


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Calculo de las derivadas $\dot{M}{ij}$, $\ddot{M}{ij}$ y $\dddot{M}_{ij}$
Ahora calculamos las derivadas respecto al tiempo, usando la regla de la cadena, es decir,
$$\frac{dM_{ij}}{dt}=\frac{dM_{ij}}{d\varphi}\frac{d\varphi}{dt},$$
donde luego sustituiremos
$$\frac{d \varphi}{d t}=\frac{L}{\mu r^2},$$
con
$$L=\omega_0\mu a^2\sqrt{1-e^2}$$
Can you write Python code for it?

L = omega0*mu*(a**2)*sqrt(1-e**2)
dphi_t = L/(mu*r**2)

dphi_t

dM11_t = simplify(dM11_phi*dphi_t)
dM12_t = simplify(dM12_phi*dphi_t)
dM22_t = simplify(dM22_phi*dphi_t)

dM11_t,dM12_t,dM22_t


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Como en el apunte:
$$
g(\varphi) := 2 [1 + e \cos(\varphi − \varphi_{0} )]^4 [ 24 + 13e^2 + 48e \cos(\varphi − \varphi_{0} ) + 11e^2 \cos(2\varphi − 2\varphi_{0} )]
$$
$$
\left\langle g(\varphi)\right\rangle =\frac{(1 − e^2 )^{3/2}}{2\pi}\int_{0}^{2\pi} \frac{g(\varphi)}{[1 + e cos(\varphi − \varphi_{0})]^2} d\varphi
$$
Can you write Python code for it?

M = Symbol('M')
x = Symbol('x')
x0 = Symbol('x0')
g = Function('g')(x)
promedio_g = Symbol('Pg')

g = 2*((1 + e*cos(phi-phi0))**4)*(24 + 13*e**2 + 48*e*cos(phi-phi0) + 11*e**2*cos(2*phi-2*phi0))

g


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Finalmente, hacemos lo mismo, para calcular la tercera derivada temporal:
Can you write Python code for it?

dM11_ttt = simplify(diff(dM11_tt,phi)*dphi_t)
dM12_ttt = simplify(diff(dM12_tt,phi)*dphi_t)
dM22_ttt = simplify(diff(dM22_tt,phi)*dphi_t)

dM11_ttt,dM12_ttt,dM22_ttt


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Momento de inercia: $M_{ij}$
Y ahora definimos los símbolos de las componentes (no nulas) del momento cuadrupolar $M_{ij}$, como funciones de $\varphi$
Can you write Python code for it?

M11 = Function('M11')(phi)
M12 = Function('M12')(phi)
M22 = Function('M22')(phi)
r = Function('r')(phi)


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Momentum angular radiado
Similarmente, para calcular el momento angular radiado usamos
$$
\left\langle\dot{L}{}^{i}\right\rangle=\frac{2 G}{5 c^5} \epsilon^{ijk}\left\langle\ddot{M}{}^{ja}\ddot{M}{}^{ka}\right\rangle .
$$
En nuestro caso, de movimiento en el plano $xy$, encontramos:
\begin{align}
\left\langle\dot{L}{}^{3}\right\rangle &= \frac{2 G}{5 c^5} \left\langle\epsilon^{31k}\ddot{M}{}^{1l}\dddot{M}{}^{kl}+\epsilon^{32k}\ddot{M}{}^{2l}\dddot{M}{}^{kl}\right\rangle\
&= \frac{2 G}{5 c^5} \left\langle\epsilon^{312}\ddot{M}{}^{1l}\dddot{M}{}^{2l}+\epsilon^{321}\ddot{M}{}^{2l}\dddot{M}{}^{1l}\right\rangle \
 &= \frac{2 G}{5 c^5} \left\langle\ddot{M}{}^{11}\dddot{M}{}^{21}+\ddot{M}{}^{12}\dddot{M}{}^{22}-\ddot{M}{}^{21}\dddot{M}{}^{11}-\ddot{M}{}^{22}\dddot{M}{}^{12}\right\rangle \
&=\frac{4 G}{5 c^5} \left\langle\ddot{M}{}^{12}(\dddot{M}{}^{22}-\dddot{M}{}^{11})\right\rangle .
\end{align}
Can you write Python code for it?


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Nuevamente, usando la regla de la cadena, podemos reescribir el promedio requerido en términos de una integral sobre el ángulo $\varphi$:
\begin{align}
\left\langle P(t)\right\rangle &= \frac{1}{T}\int_0^T P(t)\,dt \
&= \frac{1}{T}\int_0^{2\pi} P(\varphi)\frac{dt}{d\varphi}\,d\varphi \
&= \frac{1}{T}\frac{\mu}{L}\int_0^{2\pi} r^2(\varphi)P(\varphi)\,d\varphi \
&= \frac{\mu a^2(1-e^2)^2}{TL}\int_0^{2\pi} \frac{P(\varphi)}{\left[1+e\cos(\varphi-\varphi_0)\right]^2}\,d\varphi \
&= \frac{(1-e^2)^{3/2}}{2\pi}\int_0^{2\pi} \frac{P(\varphi)}{\left[1+e\cos(\varphi-\varphi_0)\right]^2}\,d\varphi.
\end{align}
Can you write Python code for it?

integrando = factor(simplify(((1-e**2)**(3/2))/(2*pi))*(P/(1+e*cos(phi-phi0))**2))

integrando

promedio_P = Symbol('PP')

import time

# tomamos el tiempo de este cálculo, porque es el que más tarda (~ 2 horas!)
st = time.time()
promedio_P =integrate(integrando,(phi,0,2*pi))
ft = time.time()
print(ft-st)

simplify(promedio_P)


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Potencia promedio radiada
A continuación, calcularemos la potencia promedio radiada, evaluando la expresión
$$
\left\langle P\right\rangle=\frac{G}{5 c^5} \left\langle\dddot{Q}{}^{ij}\dddot{Q}{}^{ij}\right\rangle
$$
que, en nuestro caso de movimiento en el plano $xy$, se reduce a
$$\left\langle P\right\rangle=\frac{2G}{15c^5}\, \left\langle \left(\dddot{M}{11}\right)^2+ \left(\dddot{M}{22}\right)^2+3\left(\dddot{M}{12}\right)^2 -\dddot{M}{11}\dddot{M}_{22}\right\rangle .
$$
Primero, definiremos los símbolos de $G, c$ y $P$:
Can you write Python code for it?

G = Symbol('G')
c = Symbol('c')
P = Symbol('P')


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Primero definimos los símbolos de las variables a usar: $a,e,\mu,L,\omega_0,\varphi$ y $\varphi_0$:
Can you write Python code for it?

a = Symbol('a', positive=True)
e = Symbol('e', positive=True)
mu = Symbol('mu', positive=True)
L = Symbol('L',positive=True)
omega0 = Symbol('omega0',positive=True)
phi = Symbol('varphi',positive=True)
phi0 = Symbol('varphi0',real=True)


I am working on the file "Notebooks/Sistema_Binario-Potencia_y_Momentum_promedio_radiado.ipynb".
The first task is:
Repetimos el procedimiento, para calcular las segundas derivadas:
Can you write Python code for it?

dM11_tt = simplify(diff(dM11_t,phi)*dphi_t)
dM12_tt = simplify(diff(dM12_t,phi)*dphi_t)
dM22_tt = simplify(diff(dM22_t,phi)*dphi_t)

dM11_tt,dM12_tt,dM22_tt


I am working on the file "Notebooks/SolveMathProblems/0 - IntroductionToNumericalSolutions.ipynb".
The first task is:
Higher order expansion
First we try fitting the local expansion for \(\theta\) through an
additional point.
This time we assume that the variation in \(\theta(t)\) is quadratic, i.e.
$$
    \theta(t') = \theta_{n-1} + \beta t' + \gamma {t'}^2
$$
The local time coordinate is $t' = t - (n-1)\Delta t$, and when we differentiate
$$
    \frac{d \theta}{dt} = \beta + 2 \gamma t'
$$
To solve for \(\beta\) and \(\gamma\) we fit the curve through the sample points:
$$
    \begin{split}
            \theta_n &= \theta_{n-1} + \beta \Delta t + \gamma (\Delta t)^2 \
            \theta_{n+1} &= \theta_{n-1} + 2 \beta \Delta t + 4 \gamma (\Delta t)^2
     \end{split}
$$
Which solve to give
$$
     \begin{split}
     \beta &= \left( 4 \theta_n - \theta_{n+1} - 3\theta_{n-1} \right) \frac{1}{2\Delta t} \
     \gamma &= \left( \theta_{n+1} + \theta_{n-1} -2 \theta_n \right) \frac{1}{2\Delta t^2}
     \end{split}
$$
We can subsitute this back into the equation above and then into the original differential equation and we obtain the following
$$
     \left. \frac{d\theta}{dt} \right|{t=n\Delta t} = \beta + 2\gamma \Delta t =
     \frac{1}{2\Delta t} \left( \theta{n+1} - \theta_{n-1} \right)  = -k \theta_n
$$
The difference approximation to the derivative turns out to be the average of the expressions for the previous derivative and the new derivative. We have now included information about the current timestep and the previous timestep in our expression for the value of \(\theta\) at the forthcoming timestep:
$$
     \theta_{n+1} = \theta_{n-1} -2k \theta_n \Delta t
$$
Can you write Python code for it?

steps = 100
theta_0 = 1.0
const_k = 10.0
delta_t = 1.0 / steps

theta_values = np.zeros(steps)
time_values  = np.zeros(steps)

theta_values[0] = theta_0
time_values[0] = 0.0

theta_values[1] = theta_values[0] * (1 - const_k * delta_t)
time_values[1] = delta_t

for i in range(2, steps):
    theta_values[i] = theta_values[i-2] - 2.0 * theta_values[i-1] * const_k * delta_t
    time_values[i] = time_values[i-1] + delta_t

exact_theta_values = theta_0 * np.exp(-const_k * time_values)

plot(time_values, exact_theta_values, linewidth=5.0)
plot(time_values, theta_values, linewidth=3.0, color="red")


I am working on the file "Notebooks/SolveMathProblems/0 - IntroductionToNumericalSolutions.ipynb".
The first task is:
The results are more accurate when a smaller timestep is used although it
requires more computation to achieve the greater accuracy. Higher order expansion
also increases the accuracy and may be more efficient in terms of the number of computations
required for a given level of accuracy.
Note, however, that the supposedly better quadratic expansion produces an error which
oscillates as time increases. Does this error grow ? Does this make second order
expansions useless ?
Second Order Runge-Kutta
<img src="images/theta_rk2-1.png" width="66%">
The Runge-Kutta approach to higher order integration methods is
illustrated in the figure above. The idea is to estimate the
gradient \(d \theta / d t\) at the half way point between two
timestep values.  This is done in two stages. Initially a
first order estimate, \( \hat{\theta} \) is made for the value of the function
\( \theta\) at \(t=t+\Delta t /2\) in the future. This value is then
subsituted into the differential equation to obtain the
estimate for the gradient at this time. The revised gradient is
then used to update the original \(\theta(t)\) by an entire timestep.
The first order step is
$$
        \begin{split}
        \hat{\theta}(t+\Delta t /2) & = \theta(t) + \left.  \frac{d \theta}{d t} \right|_t \frac{\Delta t}{2} \
         &= \theta(t) \left[ 1-\frac{k\Delta t}{2} \right]
        \end{split}
$$
Substitute to estimate the gradient at the mid-point
$$
    \left. \frac{d \theta}{d t} \right|_{t+\Delta t /2} \approx -k \theta(t)  \left[ 1-\frac{k\Delta t}{2} \right]
$$
Use this value as the average gradient over the interval \( t\rightarrow t+\Delta t\) to update \(\theta\)
$$
    \begin{split}
        \theta(t+\Delta t) & \approx \theta(t) + \delta t \left(  -k \theta(t)  \left[ 1-\frac{k\Delta t}{2} \right]  \right) \
            & \approx \theta(t) \left( 1 - k \Delta t + k^2 \frac{\Delta t^2}{2} \right)
    \end{split}
$$
It's worth noting that the Taylor expansion of the solution should look like
$$
    e^{-kt} = 1 - kt + \frac{k^2 t^2}{2!} -...
Can you write Python code for it?

steps = 100
theta_0 = 1.0
const_k = 10.0
delta_t = 1.0 / steps

theta_values = np.zeros(steps)
time_values  = np.zeros(steps)

theta_values[0] = theta_0
time_values[0] = 0.0

for i in range(1, steps):
    theta_values[i] = theta_values[i-1] * (1 - const_k * delta_t + const_k**2 * delta_t**2 / 2.0)
    time_values[i] = time_values[i-1] + delta_t

exact_theta_values = theta_0 * np.exp(-const_k * time_values)

plot(time_values, exact_theta_values, linewidth=5.0)
plot(time_values, theta_values, linewidth=3.0, color="red")


I am working on the file "Notebooks/SolveMathProblems/0 - IntroductionToNumericalSolutions.ipynb".
The first task is:
We want to be able to march forward in time from our starting point
(just like the picture above)
where $\theta = \theta_0$ to obtain the value of $\theta$ at
later times. To do this, we need to approximate the original
differential equation, and, in particular, the value of the time
derivative at each time. There are a number of ways to do this.
First order numerical approximation
Assume that the variation in \(\theta(t) \) is linear, i.e.
\[
    \theta(t') = \theta_n + \beta t'
\]
where we use a local time coordinate \(t' = t - n\Delta t\), so that when we differentiate
\[
        \frac{d \theta}{dt} = \beta
\]
To determine the approximation for the derivative therefore
becomes the solution to the following equation:
\[
        \begin{split}
            & \theta_{n+1} = \theta_n + \beta \Delta t \
            & \Rightarrow   \beta = \frac{d \theta}{dt} = \frac{\theta_{n+1} - \theta_n}{\Delta t}
        \end{split}
\]
This is a first order difference expression for the derivative which we
substitute into the original differential equation for radioactive decay at
the current timestep
\[
        \frac{\theta_{n+1} - \theta_n}{\Delta t} = - k \theta_n
\]
This rearranges to give us a time-marching algorithm:
\[
        \theta_{n+1} = \theta_n (1-k \Delta t)
\]
It is an indication of the fact that this problem is really not all that difficult
that this difference equation can be written recursively
to give:
\[
        \theta_{n+1} = \theta_0 (1-k \Delta t)^n
\]
In a moment we will compute some values for this expression to see how
accurate it is. First we consider whether we can improve the accuracy of the
approximation by doing a bit more work.
Can you write Python code for it?

steps = 10
theta_0 = 1.0
const_k = 10.0
delta_t = 1.0 / steps

theta_values = np.zeros(steps)
time_values  = np.zeros(steps)

theta_values[0] = theta_0
time_values[0] = 0.0

for i in range(1, steps):
    theta_values[i] = theta_values[i-1] * (1 - const_k * delta_t)
    time_values[i] = time_values[i-1] + delta_t

exact_theta_values = theta_0 * np.exp(-const_k * time_values)

plot(time_values, exact_theta_values, linewidth=5.0)
plot(time_values, theta_values, linewidth=3.0, color="red")


I am working on the file "Notebooks/SolveMathProblems/1 - GroundwaterFlow-LectureNotes.ipynb".
The first task is:
So, it seems we can calculate reasonably accurate gradients with our little-boxes approximation. We can now try to solve the time-evolution of the pressure with the same function and see what happens.
Note: In the previous plots, errors are less than 1% in the second derivative away from the boundary but nearer 5% there. On the other hand, we haven't even tried to do a clever job of building the interpolation / derivatives.
Can you write Python code for it?

xP = linspace(0,math.pi,100)
hP = numpy.sin(xP)
hP2 = zeros(len(xP))

# random initial wavelengths

for k in range(1,25):
    hP2 = hP2 + numpy.random.rand() * numpy.sin(xP * float(k))

hP2 = hP2 / max(hP2)

gradx_hP = gradx(xP,hP)
gradx_hP2 = gradx(xP,hP2)
grad2x_hP = gradx(xP,gradx_hP)
grad2x_hP2 = gradx(xP,gradx_hP2)

deltat = 0.002

f, (ax1, ax2) = plt.subplots(1, 2, sharex=True)
f.set_size_inches(16,6)
ax1.set_title( "Smoothly varying")
ax2.set_title( "Wildly varying")

## Timestepping loop

for time in range(0,500):
    if(time%50==0):
        ax1.plot(xP / math.pi,hP)
        ax2.plot(xP / math.pi,hP2)

    hP = hP + deltat * grad2x_hP
    hP2 = hP2 + deltat * grad2x_hP2

    # Boundary conditions

    hP[0] = hP[-1] = 0.0
    hP2[0] = hP2[-1] = 0.0

    # compute new gradients
    gradx_hP = gradx(xP,hP)
    gradx_hP2 = gradx(xP,hP2)
    grad2x_hP = gradx(xP,gradx_hP)
    grad2x_hP2 = gradx(xP,gradx_hP2)


I am working on the file "Notebooks/SolveMathProblems/2 - FiniteDifferences.ipynb".
The first task is:
1. Finite difference approximations
Ideally, an analytical solution would be obtained by integrating this equation with a set of boundary conditions.
Unfortunately finding a solution is not a trivial task and may only satisfy a very specific topic you are interested in solving.
The finite difference method approximates solutions to differential equations across a discreet domain with a set of boundary conditions along the edges of this domain.
<img src="images/fd.png" width="600">
As you can gather from the above image, resolution is important.
If $h$ is too large the solution is not very accurate, and with time time-dependence it could become unstable.
Lets take a simple function, \(f(x) = \sin (x)\). We can calculate its derivatives analytically:
$$\begin{align}
f'(x) &= \cos (x) \
f''(x) &= -\sin (x)
\end{align}$$
or we could use finite differences to approximate the derivatives...
$$\begin{align}
f'(x) &= \lim_{h\to0} \frac{f(x+h) - f(x)}{h} \
f''(x)&= \lim_{h\to0} \frac{f(x+2h) - 2f(x+h) + f(x)}{h^2}
\end{align}$$

EXERCISE 1 Play around with the code below to see what happens when you change $f(x)$ and vary $h$.
Can you write Python code for it?

# "Resolution"
#  Try a few different values

number_of_points = 150

# Data

x = np.linspace(0,2*np.pi,number_of_points)
xh = np.linspace(0,2*np.pi,1000) # 1000 is more than enough to plot

f = np.sin(x)
fh = np.sin(xh)
dfh = np.cos(xh)
d2fh = -fh

# Normalization
h = x[1] - x[0] # use np.diff(x) if x is not uniform

# First derivatives
df = np.diff(f, 1) / h # numpy version
for i in range(x.size-1):
    df[i] = (f[i+1]-f[i]) / h

# Second derivatives
ddf = np.diff(f, 2) / h**2 # numpy version
for i in range(x.size-2):
    ddf[i] = (f[i+2]-2*f[i+1]+f[i]) / h**2

# Plotting
fig = plt.figure(1)
ax1 = fig.add_subplot(111)
ax1.plot(x, f, 'black', linewidth=0.0, marker="+", markersize=12, label="f (x)")
ax1.plot(x[:-1], df, 'red', linewidth=0.5, marker="+", markersize=12, label="f ' (x)")
ax1.plot(x[:-2], ddf, 'green', linewidth=0.5, marker="+", markersize=12, label="f '' (x)")

ax1.plot(xh, fh, 'black', lw=2, label="f (x)")
ax1.plot(xh, dfh, 'red', lw=2, label="f ' (x)")
ax1.plot(xh, d2fh, 'green', lw=2, label="f '' (x)")

ax1.legend()
plt.show()


I am working on the file "Notebooks/SolveMathProblems/2 - FiniteDifferences.ipynb".
The first task is:
4. Explicit finite difference approximation
So far we have an implicit approximation to the heat equation (great!) but what about an explicit approximation? Each have their own advantages.

Implicit approximations are numerically stable and can calculate a steady state solution in one solve.
Explicit approximations iterate to a steady-state solution and are only stable if the timestep size is suitably small.
But it is easy to implement time-dependent solutions.

The time-dependent heat equation can be approximated using a first-order forward finite difference in time, and second-order central finite difference scheme in space:
$$
\begin{align}
    \frac{\partial T}{\partial t} &= \kappa \frac{\partial^2 T}{\partial x^2} \
    \frac{T^{n+1}i - T^n_i}{\Delta t} &= \kappa \frac{T^n{i+1} - 2T^n_i + T^n_{i-1}}{\Delta x^2}
\end{align}
$$
The temperature solution is updated iteratively by rearranging the above equation:
$$
T^{n+1}i = T^n_i + \kappa \Delta t \frac{T^n{i+1} - 2T^n_i + T^n_{i-1}}{\Delta x^2}
$$
We start with an initial condition of zero everywhere except for two Dirichlet boundary conditions at the top and bottom of the domain.
Can you write Python code for it?

T = np.zeros((ny,nx))
# Initial conditions
T[0,:] = 300.
T[-1,:] = 800.

k = 1.0

# 1 timestep
time = 0.0
gradTx, gradTy = np.gradient(T, dx, dy)
flux_x = k*gradTx
flux_y = k*gradTy

gradTxx, gradTxy = np.gradient(flux_x, dx, dy)
gradTyx, gradTyy = np.gradient(flux_y, dx, dy)

divT = gradTxx + gradTyy
dt = (dx*dy)/k
time += dt

T_new = T + dt*divT

fig, (ax1, ax2) = plt.subplots(1,2, sharey=True, figsize=(10,4))
ax1.imshow(T)
ax2.imshow(T_new)


I am working on the file "Notebooks/SolveMathProblems/2 - FiniteDifferences.ipynb".
The first task is:
Above we used numpy's linear algebra solver and plot the temperature field.

EXERCISE 2 Change the boundary conditions, heat production, and conductivity above then plot the result below.

Matrix $\mathbf{A}$ is a banded diagonal matrix, which means that there are a lot of zeros.
Since the data only takes up a fraction of the whole matrix, we could use scipy's sparse module to conserve memory:
from scipy import sparse

The coo_matrix is a common sparse matrix format that accepts a vector of row indices, column indices, and a vector of the same size for the values.
coo_matrix((data, (row, col))

where
$$
\mathrm{row} =
\begin{bmatrix}
r_{0} \ r_{0} \ r_{1} \ \vdots \ r_{n}
\end{bmatrix}
\quad \mathrm{col} =
\begin{bmatrix}
c_{0} \ c_{1} \ c_{0} \ \vdots \ c_{n}
\end{bmatrix}
\quad \mathrm{val} =
\begin{bmatrix}
v_{0,0} \ v_{0,1} \ v_{1,0} \ \vdots \ v_{n,n}
\end{bmatrix}
$$
Now we can achieve much higher resolutions using a fraction of the memory.
3. Boundary conditions
In the previous exercise we used constant temperature boundary conditions on each wall in the model domain.
These are Dirichelet boundary conditions:
$$T(n) = T_{\text{boundary}}$$
The other boundary condition we want to use is Neumann, or flux, boundary conditions:
$$\frac{\partial T}{\partial y}(n) = -\mathbf{q} = -\kappa \frac{\partial T}{\partial y}$$
in the \(y\) direction for example, where \(\mathbf{q}\) is the flux vector assigned to a wall of the domain.
For insulated boundary conditions, \(\mathbf{q}=0 \).
This means that no heat enters or escapes from that boundary.
For example, the finite difference form for this on the left wall of our domain would be:
$$ \kappa \frac{T_{i,j}-T_{i+1,j}}{\Delta x^2} = \frac{\mathbf{q}}{\Delta x} - H$$
which reduces to
$$ \kappa \frac{T_{i,j}-T_{i+1,j}}{\Delta x^2} = - H$$
when \( \mathbf{q}=0 \)
3.1 Periodic boundary conditions
In the next exercise you will need to assign Neumann boundary conditions to all walls of the domain; except the top wall where you will assign a periodic Dirichlet...
Can you write Python code for it?

# Empty space for your code
# Copy the code you made above as a template


I am working on the file "Notebooks/SolveMathProblems/2 - FiniteDifferences.ipynb".
The first task is:
Lucky there is an analytical solution to test if your code is working correctly...
$$T(x,y) = T_0 + \Delta T \cos \frac{2 \pi x}{\lambda} e^{-2\pi y/\lambda}$$
Set your Neumann boundary conditions to zero and use this to benchmark your code.
Plot the results using matplotlib.
Can you write Python code for it?

T_analytical = np.zeros((ny,nx)) # write analytical solution

fig, (ax1, ax2) = plt.subplots(1,2)
fig.set_size_inches(16,4)

# Analytical solution
im1 = ax1.imshow(T_analytical.reshape(ny,nx))
fig.colorbar(im1, ax=ax1)

# Numerical solution
## YOUR CODE GOES HERE

plt.show()


I am working on the file "Notebooks/SolveMathProblems/2 - FiniteDifferences.ipynb".
The first task is:
The useful part of this is that we can derive an equation without knowing any calculus!
(Not that we recommend that!)
Finite difference is just one of many techniques that fall under the umbrella of numerical modelling.
Finite difference works by taking the average of neighbouring nodes within the domain to calculate the value on a specific node, \(N_{i,j}\).
In 2D these neighbouring nodes would be \(N_{i-1,j}, N_{i,j+1}, N_{i+1,j}, N_{i,j-1} \).
<img src="images/fd_ij.png" width="500">
2. Finite difference approximations to the heat equation (implicit scheme)
The 2D heat equation is given as:
$$\rho c_p \frac{\partial T}{\partial t} = \kappa \left( \frac{\partial^2 T}{\partial x^2} + \frac{\partial^2 T}{\partial y^2} \right) + H$$
where \(\rho\) is density, \(c_p\) is specific heat capacity, \(\kappa\) is the thermal diffusivity coefficient, and \(H\) are heat sources.
There are a few different ways to average - forward, backward, and central.
For the heat equation we are going to use the 2nd order central difference, which applied to the heat equation is:
$$\kappa \left( \frac{T_{i,j-1}-2T_{i,j}+T_{i,j+1}}{\Delta x^2} + \frac{T_{i-1,j}-2T_{i,j}+T_{i+1,j}}{\Delta y^2} \right) = -H$$
Note that we have made \(\rho c_p \frac{\partial T}{\partial t} = 0\) because initially we are only going to solve this in steady-state.
Expanding the brackets and collecting like terms ( \(T_{i,j-1}, T_{i-1,j}, T_{i,j}, T_{i+1,j}, T_{i,j+1}\) ) we get,
$$\left[\kappa\frac{T_{i,j-1}}{\Delta y^2}\right] + \left[\kappa\frac{T_{i-1,j}}{\Delta x^2}\right] - \left[\kappa\frac{2T_{i,j}}{\Delta x^2} - \kappa\frac{2T_{i,j}}{\Delta y^2}\right] + \left[\kappa\frac{T_{i+1,j}}{\Delta x^2}\right] + \left[\kappa\frac{T_{i,j+1}}{\Delta y^2}\right] = -H_{i,j}$$
\(H\) can be constant or spatially variable, \(H_{i,j}\), it doesn't matter.
2.1 Solving a system of linear equations
You may have noticed that finite differences are linear approximations of a derivative.
Linear systems of equations are, it just so happens, very easy to solve using a...
Can you write Python code for it?

nx, ny = 27, 25 # No more than nx=100, ny=100
nodes = np.arange(nx*ny).reshape(ny,nx)
dx, dy = 1., 1.

# Create matrix structures
A_matrix = np.zeros((nx*ny,nx*ny)) # square matrix
b_matrix = np.zeros(nx*ny)

# field variables
H = 2e-6
k = 3.0

# boundary conditions (constant temperature)
topBC = 300.0
bottomBC = 800.0
leftBC = 500.0
rightBC = 500.0

# boundary nodes
top_nodes = nodes[0,:]
bottom_nodes = nodes[-1,:]
left_nodes = nodes[1:-1,0]
right_nodes = nodes[1:-1,-1]

for idx in top_nodes:
    A_matrix[idx, idx] = 1.0
    b_matrix[idx] = topBC
for idx in bottom_nodes:
    A_matrix[idx, idx] = 1.0
    b_matrix[idx] = bottomBC
for idx in left_nodes:
    A_matrix[idx, idx] = 1.0
    b_matrix[idx] = leftBC
for idx in right_nodes:
    A_matrix[idx, idx] = 1.0
    b_matrix[idx] = rightBC

bmask = np.zeros_like(nodes, dtype=bool)
bmask[1:-1,1:-1] = True # these are nodes that do not intersect the boundary

for idx in nodes[bmask]:
    A_matrix[idx, idx-nx] = k/dy**2
    A_matrix[idx, idx-1]  = k/dx**2
    A_matrix[idx, idx]    = -2*k/dx**2 -2*k/dy**2
    A_matrix[idx, idx+1]  = k/dx**2
    A_matrix[idx, idx+nx] = k/dy**2

    b_matrix[idx] = -H

print A_matrix

temperature = np.linalg.solve(A_matrix, b_matrix) # solve x matrix

fig = plt.figure(1, figsize=(10,4))
ax1 = fig.add_subplot(111)

im = ax1.imshow(temperature.reshape(ny,nx))
ax1.set_title('Temperature (Kelvin)')
ax1.contour(temperature.reshape(ny,nx)) # Lets plot some contours

fig.colorbar(im)
plt.show()


I am working on the file "Notebooks/Spatial Exploration.ipynb".
The first task is:
Building Animated films
Can you write Python code for it?

data_path = Path('./data/')
map_path = Path("./maps/")

os.makedirs(data_path, exist_ok=True)
os.makedirs(map_path, exist_ok=True)


I am working on the file "Notebooks/Spatial Exploration.ipynb".
The first task is:
Downloading data
We will start by Downloading the full alerta table for all diseases.
Can you write Python code for it?

from infodenguepredict.data.infodengue import get_full_alerta_table

diseases = ['dengue','chik','zika']
for dis in diseases:
    os.makedirs(data_path/dis, exist_ok=True)

for dis in diseases:
    get_full_alerta_table(dis, output_dir=data_path/dis, chunksize=50000, start_SE=202140)

brmunis = geobr.read_municipality(code_muni='all')
brmunis.plot();

def merge(munis, df):
    munis['code_muni'] = munis.code_muni.astype('int')
    dados = pd.merge(df.reset_index(), munis,how='left', left_on='municipio_geocodigo', right_on='code_muni')
    dados = dados.sort_values('SE')
    return gpd.GeoDataFrame(dados)

def create_frames(dados, doenca='dengue', variable='casos_est'):
    vnames = {'casos_est': 'Casos Estimados', 'casos': 'Casos Notificados', 'p_inc100k': 'Incidência por 100 mil hab.'}
    leg = vnames[variable]
    if doenca == 'dengue':
        bins = {'casos_est':[20,50,100,500,1000],'p_inc100k':[50,500,1000,2500] }
    elif doenca == 'chik':
        bins = {'casos_est':[5,15,50,120,300],'p_inc100k':[50,100,500,1000] }
    elif doenca == 'zika':
        bins = {'casos_est':[5,15,50,120,300],'p_inc100k':[50,100,500,1000] }
    acumulados = 0
    ews = sorted(list(set(dados.SE)))
    for i,se in enumerate(ews):
        fig = dados[dados.SE==se].plot(figsize=(10,10),
                                       column=variable,
                                       scheme="user_defined",
                                       cmap='plasma',
                                       classification_kwds={'bins':bins[variable]},
                                       legend=True,
                                       legend_kwds={'title': f"{leg}",'loc':'lower right'}
                                       );
        acumulados += dados[dados.SE==se].casos_est.sum()
        fig.set_axis_off();
        fig.text(-50,2, f'Casos: {int(acumulados)}', fontsize=24)
        fig.set_title(f'{leg} de {doenca}\nna semana {str(se)[-2:]} de {str(se)[:-2]}', fontdict={'fontsize': 14});
        opath = map_path/variable
       ...


I am working on the file "Notebooks/Spatial Exploration.ipynb".
The first task is:
Fetching data from Infodengue
We can download the data from a full state. Let's pick Goiás.
Can you write Python code for it?

go = get_alerta_table(state='GO', doenca='dengue')

go

municipios = geobr.read_municipality(code_muni='GO')
municipios

municipios['code_muni'] = municipios.code_muni.astype('int')
municipios.plot(figsize=(10,10));

goias = pd.merge(go.reset_index(), municipios,how='left', left_on='municipio_geocodigo', right_on='code_muni')
goias

goias = gpd.GeoDataFrame(goias)

ax = goias[goias.SE==202144].plot(figsize=(10,10),
                             column='casos_est',
                             scheme="naturalbreaks",
                             legend=True,
                             legend_kwds={'title': "Casos estimados"},

                             );
ax.set_axis_off();


I am working on the file "Notebooks/Spatial Exploration.ipynb".
The first task is:
loading data from disk
we can load all chunks at once,into a single dataframe, since they are parquet files.doenca
Can you write Python code for it?

dengue = pd.read_parquet(data_path/'dengue')
dengue.sort_values('SE',inplace=True)
chik = pd.read_parquet(data_path/'chik')
chik.sort_values('SE',inplace=True)
zika = pd.read_parquet(data_path/'zika')
zika.sort_values('SE',inplace=True)
dengue

dmdf = merge(brmunis,dengue)
cmdf = merge(brmunis, chik)
zmdf = merge(brmunis, zika)

dmdf[dmdf.SE==202208].plot(column='casos_est',scheme="naturalbreaks");

os.getcwd()

create_frames(dmdf)
create_frames(dmdf, variable='p_inc100k')

create_frames(cmdf, doenca='chik')
create_frames(cmdf, doenca='chik', variable='p_inc100k')

create_frames(zmdf, doenca='zika')
create_frames(zmdf, doenca='zika', variable='p_inc100k')


I am working on the file "Notebooks/Spectrum_Normalizations.ipynb".
The first task is:
As you can see here my observations are above the continuum most of the time.
What I have noticed is this drastically affects the chisquared result as the mix model is the one with the least amount of alpha.
I am thinking of renormalizing my observations by implementing equation (1) from Passegger 2016 (Fundamental M-dwarf parameters from high-resolution spectra using PHOENIX ACES modesl)
        F_obs = F_obs * (continuum_fit model / continuum_fit observation)

They fit a linear function to the continuum of the observation and computed spectra to account for "slight differences in the continuum level and possible linear trends between the already noramlized spectra."

One difference is that they say they normalize the average flux of the spectra to unity. Would this make a difference in this method.

Questions

Would this be the correct approach to take to solve this?
Should I renomalize the observations first as well?
Am I treating the cooler M-dwarf spectra correctly in this approach?

Attempting the Passegger method
Can you write Python code for it?

from scipy.interpolate import interp1d
# mix1_norm = continuum(wav_model, mix1, splits=50, method="linear", plot=False)
# mix2_norm = local_normalization(wav_model, mix2, splits=50, method="linear", plot=False)
obs_continuum = continuum(obs["wavelength"], obs["flux"], splits=20, method="linear", plot=True)

linear1 = continuum(wav_model, mix1, splits=50, method="linear", plot=True)
linear2 = continuum(wav_model, mix2, splits=50, method="linear", plot=False)

obs_renorm1 = obs["flux"]  * (interp1d(wav_model, linear1)(obs["wavelength"]) / obs_continuum)
obs_renorm2 = obs["flux"]  * (interp1d(wav_model, linear2)(obs["wavelength"]) / obs_continuum)

# Just a scalar
# mix1_norm = local_normalization(wav_model, mix1, splits=50, method="scalar", plot=False)
# mix2_norm = local_normalization(wav_model, mix2, splits=50, method="scalar", plot=False)
obs_scalar = continuum(obs["wavelength"], obs["flux"], splits=20, method="scalar", plot=False)
scalar1 = continuum(wav_model, mix1, splits=50, method="scalar", plot=True)
scalar2 = continuum(wav_model, mix2, splits=50, method="scalar", plot=False)
print(scalar2)
obs_renorm_scalar1 = obs["flux"] * (interp1d(wav_model, scalar1)(obs["wavelength"]) / obs_scalar)
obs_renorm_scalar2 = obs["flux"] * (interp1d(wav_model, scalar2)(obs["wavelength"]) / obs_scalar)

plt.plot(obs["wavelength"], obs_scalar, label="scalar observed")
plt.plot(obs["wavelength"], obs_continuum, label="linear observed")

plt.plot(obs["wavelength"], interp1d(wav_model, scalar1)(obs["wavelength"]), label="scalar 1%")
plt.plot(obs["wavelength"], interp1d(wav_model, linear1)(obs["wavelength"]), label="linear 1%")

plt.plot(obs["wavelength"], interp1d(wav_model, scalar2)(obs["wavelength"]), label="scalar 5%")
plt.plot(obs["wavelength"], interp1d(wav_model, linear2)(obs["wavelength"]), label="linear 5%")

plt.title("Linear and Scalar continuum renormalizations.")
plt.legend()
plt.show()

plt.plot(obs["wavelength"], obs["flux"],  label="obs", alpha =0.6)
plt.plot(obs["wavelength"], obs_renorm1, label="linear...


I am working on the file "Notebooks/Spectrum_Normalizations.ipynb".
The first task is:
Combining Spectra
I then mix the models using a combination of the two spectra.
In this case with NO RV shifts.
Can you write Python code for it?

def mix(h, c, alpha):
    return (h + c * alpha) / (1 + alpha)

mix1 = mix(host_cont, comp_cont, 0.01)   # 1% of the companion spectra
mix2 = mix(host_cont, comp_cont, 0.05)   # 5% of the companion spectra

# plt.plot(wav_model[20:100], comp_cont[20:100], label="comp")
plt.plot(wav_model[20:100], host_cont[20:100], label="host")
plt.plot(wav_model[20:100], mix1[20:100], label="mix 1%")
plt.plot(wav_model[20:100], mix2[20:100], label="mix 5%")
plt.xlabel("Wavelength (nm)")
plt.legend()
plt.show()


I am working on the file "Notebooks/Spectrum_Normalizations.ipynb".
The first task is:
In this example for the 5% companion spectra there is a bit of difference between the linear and scalar normalizations. With a larger difference at the longer wavelength. (more orange visible above the red.)  Faint blue is the spectrum before the renormalization.
Range of phoenix spectra
Can you write Python code for it?

wav_model = fits.getdata("/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/WAVE_PHOENIX-ACES-AGSS-COND-2011.fits")
wav_model /= 10   # nm
temps = [2300, 3000, 4000, 5000]

mask1 = (1000 < wav_model) & (wav_model < 3300)
masked_wav1 = wav_model[mask1]
for temp in temps[::-1]:
    file = "/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/Z-0.0/lte0{0}-4.50-0.0.PHOENIX-ACES-AGSS-COND-2011-HiRes.fits".format(temp)
    host_f = fits.getdata(file)

    plt.plot(masked_wav1, host_f[mask1], label="Teff={}".format(temp))

plt.title("Phoenix spectra")
plt.xlabel("Wavelength (nm)")
plt.legend()

plt.show()

mask = (2000 < wav_model) & (wav_model < 2300)
masked_wav = wav_model[mask]

for temp in temps[::-1]:
    file = "/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/Z-0.0/lte0{0}-4.50-0.0.PHOENIX-ACES-AGSS-COND-2011-HiRes.fits".format(temp)
    host_f = fits.getdata(file)

    host_f = host_f[mask]

    plt.plot(masked_wav, host_f, label="Teff={}".format(temp))

plt.title("Phoenix spectra")
plt.xlabel("Wavelength (nm)")
plt.legend()

plt.show()

# Observations
for chip in range(1,5):
    obs = fits.getdata("/home/jneal/.handy_spectra/HD211847-1-mixavg-tellcorr_{}.fits".format(chip))

    plt.plot(obs["wavelength"], obs["flux"], label="chip {}".format(chip))
plt.hlines(1, 2111, 2165, linestyle="--")
plt.title("CRIRES spectrum HD211847")
plt.xlabel("Wavelength (nm)")
plt.legend()
plt.show()

# Observations
for chip in range(1,5):
    obs = fits.getdata("/home/jneal/.handy_spectra/HD30501-1-mixavg-tellcorr_{}.fits".format(chip))

    plt.plot(obs["wavelength"], obs["flux"], label="chip {}".format(chip))
plt.hlines(1, 2111, 2165, linestyle="--")
plt.title("CRIRES spectrum HD30501")
plt.xlabel("Wavelength (nm)")
plt.legend()
plt.show()


I am working on the file "Notebooks/Spectrum_Normalizations.ipynb".
The first task is:
The obeservatios were originally automatically continuum normalized in the iraf extraction pipeline.
I believe the continuum is not quite at 1 here anymore due to the divsion by the telluric spectra.
Can you write Python code for it?

# Observation
obs = fits.getdata("/home/jneal/.handy_spectra/HD211847-1-mixavg-tellcorr_1.fits")

plt.plot(obs["wavelength"], obs["flux"])
plt.hlines(1, 2111, 2124, linestyle="--")
plt.title("CRIRES spectra")
plt.xlabel("Wavelength (nm)")
plt.show()


I am working on the file "Notebooks/Spectrum_Normalizations.ipynb".
The first task is:
The two PHOENIX ACES spectra here are the first best guess of the two spectral components.
Can you write Python code for it?

# Models
wav_model = fits.getdata("/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/WAVE_PHOENIX-ACES-AGSS-COND-2011.fits")
wav_model /= 10   # nm
host = "/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/Z-0.0/lte05700-4.50-0.0.PHOENIX-ACES-AGSS-COND-2011-HiRes.fits"
old_companion = "/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/Z-0.0/lte02600-4.50-0.0.PHOENIX-ACES-AGSS-COND-2011-HiRes.fits"
companion = "/home/jneal/Phd/data/PHOENIX-ALL/PHOENIX/Z-0.0/lte02300-4.50-0.0.PHOENIX-ACES-AGSS-COND-2011-HiRes.fits"

host_f = fits.getdata(host)
comp_f = fits.getdata(companion)
plt.plot(wav_model, host_f, label="Host")
plt.plot(wav_model, comp_f, label="Companion")
plt.title("Phoenix spectra")
plt.xlabel("Wavelength (nm)")
plt.legend()

plt.show()

mask = (2000 < wav_model) & (wav_model < 2200)
wav_model = wav_model[mask]
host_f = host_f[mask]
comp_f = comp_f[mask]

plt.plot(wav_model, host_f, label="Host")
plt.plot(wav_model, comp_f, label="Companion")
plt.title("Phoenix spectra")
plt.legend()
plt.xlabel("Wavelength (nm)")
plt.show()


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex1-Cartesian-Triangulations.ipynb".
The first task is:
Making a plot of the triangulation
We can make a plot of the two grids and the most straightforward way to display the information
is through a standard map projection of the sphere to the plane.
(Here we superimpose the points on a global map of coastlines using the cartopy map library and use the Mollweide projection.
 Other projections to try include Robinson, Orthographic, PlateCarree)
Can you write Python code for it?

%matplotlib inline

import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(1,2, figsize=(20, 10), facecolor="none", sharey=True)

## Plot the vertices and the edges for the original mesh
x = triangulation.x
y = triangulation.y
simplices = triangulation.simplices

ax1.triplot(x, y, simplices, linewidth=0.5, color='black')
ax1.scatter(x, y, color='Red', alpha=0.5, marker='o')

## Plot the vertices and the edges for the refined mesh
x = refined_triangulation.x
y = refined_triangulation.y
simplices = refined_triangulation.simplices

ax2.triplot(x, y, simplices, linewidth=0.5, color='black')
ax2.scatter(x, y, color='Red', alpha=0.5, marker='o')

plt.show()


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex2-CartesianGrids.ipynb".
The first task is:
Analysis of the characteristics of the triangulations
We plot a histogram of the (spherical) areas of the triangles in each of the triangulations normalised by the average area. This is one
measure of the uniformity of each mesh.
Can you write Python code for it?

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

def area_histo(mesh):

    freq, area_bin = np.histogram(mesh.areas(), bins=20, normed=True)
    area = 0.5 * (area_bin[1:] + area_bin[:-1])
    norm_area = area / mesh.areas().mean()

    return norm_area, 0.25 * freq*area / np.pi**2

def add_plot(axis, mesh, xlim, ylim):
    u, v = area_histo(mesh)
    width = (u.max() - u.min()) / 30.
    axis.bar(u, v, width=width)
    axis.set_ylim(ylim)
    axis.plot([1.0,1.0], [0.0,1.5], linewidth=1.0, linestyle="-.", color="Black")

    return

fig, ax = plt.subplots(1,3, figsize=(14,4))

xlim=(0.75,1.5)
ylim=(0.0,0.05)

# square

add_plot(ax[0], squareR, xlim, ylim)

# elliptical

add_plot(ax[1], ellipR, xlim, ylim)

# random (this one is very different from the others ... )

add_plot(ax[2], randR, xlim, ylim)

fig.savefig("AreaDistributionsByMesh.png", dpi=250, transparent=True)


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex3-Interpolation.ipynb".
The first task is:
Analytic function
Define a relatively smooth function that we can interpolate from the coarse mesh to the fine mesh and analyse
Can you write Python code for it?

def analytic(xs, ys, k1, k2):
     return np.cos(k1*xs) * np.sin(k2*ys)

coarse_afn = analytic(cmesh.x, cmesh.y, 0.1, 1.0)
fine_afn   = analytic(fmesh.x, fmesh.y, 0.1, 1.0)


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex4-Gradients.ipynb".
The first task is:
Analytic function
Define a relatively smooth function that we can interpolate from the coarse mesh to the fine mesh and analyse
Can you write Python code for it?

import numpy as np

def analytic(xs, ys, k1, k2):
     return np.cos(k1*xs) * np.sin(k2*ys)

def analytic_ddx(xs, ys, k1, k2):
     return -k1 * np.sin(k1*xs) * np.sin(k2*ys) / np.cos(ys)

def analytic_ddy(xs, ys, k1, k2):
     return k2 * np.cos(k1*xs) * np.cos(k2*ys)

analytic_sol = analytic(mesh.x, mesh.y, 0.1, 1.0)
analytic_sol_ddx = analytic_ddx(mesh.x, mesh.y, 0.1, 1.0)
analytic_sol_ddy = analytic_ddy(mesh.x, mesh.y, 0.1, 1.0)

%matplotlib inline
import matplotlib.pyplot as plt

def axis_mesh_field(fig, ax, mesh, field, label):

    ax.axis('off')

    x0 = mesh.x
    y0 = mesh.y

    trip = ax.tripcolor(x0, y0, mesh.simplices, field, cmap=plt.cm.RdBu)
    fig.colorbar(trip, ax=ax)

    ax.set_title(str(label))
    return

fig = plt.figure(figsize=(10, 8), facecolor="none")
ax = fig.add_subplot(111)
axis_mesh_field(fig, ax, mesh, analytic_sol, "analytic solution")


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex5-Smoothing.ipynb".
The first task is:
Analytic function with noise and short wavelengths
Define a relatively smooth function that we can interpolate from the coarse mesh to the fine mesh and analyse
Can you write Python code for it?

import numpy as np

def analytic(xs, ys, k1, k2):
     return  np.cos(k1*xs) * np.sin(k2*ys)

def analytic_noisy(xs, ys, k1, k2, noise, short):
     return  np.cos(k1*xs) * np.sin(k2*ys) + \
             short * (np.cos(k1*5.0*xs) * np.sin(k2*5.0*ys)) + \
             noise * np.random.random(xs.shape)

# def analytic_ddlon(xs, ys, k1, k2):
#      return -k1 * np.sin(k1*xs) * np.sin(k2*ys) / np.cos(ys)

# def analytic_ddlat(xs, ys, k1, k2):
#      return k2 * np.cos(k1*xs) * np.cos(k2*ys)

analytic_sol   = analytic(mesh.x, mesh.y, 0.1, 1.0)
analytic_sol_n = analytic_noisy(mesh.x, mesh.y, 0.1, 1.0, 0.2, 0.0)

%matplotlib inline
import matplotlib.pyplot as plt

def axis_mesh_field(fig, ax, mesh, field, label):

    ax.axis('off')

    x0 = mesh.x
    y0 = mesh.y

    trip = ax.tripcolor(x0, y0, mesh.simplices, field, cmap=plt.cm.RdBu)
    fig.colorbar(trip, ax=ax)

    ax.set_title(str(label))
    return

fig = plt.figure(figsize=(10, 8), facecolor="none")
ax = fig.add_subplot(111)
axis_mesh_field(fig, ax, mesh, analytic_sol-analytic_sol_n, "noisy solution")


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex5-Smoothing.ipynb".
The first task is:
Smoothing operations
The Triangulation.smoothing method directly wraps the SRFPACK smoother that smooths a surface f described
by values on the mesh vertices to find a new surface f' (also described on the mesh vertices) by choosing nodal function values and gradients to minimize the linearized curvature of F subject to a bound on the deviation from the data values.
Can you write Python code for it?

help(mesh.smoothing)

stripy_smoothed, dds  = mesh.smoothing(analytic_sol_n, np.ones_like(analytic_sol_n), 10.0, 0.1, 0.01)
stripy_smoothed2, dds = mesh.smoothing(analytic_sol_n, np.ones_like(analytic_sol_n), 1.0, 0.1, 0.01)
stripy_smoothed3, dds = mesh.smoothing(analytic_sol_n, np.ones_like(analytic_sol_n), 50.0, 0.1, 0.01)

delta_n  = analytic_sol_n - stripy_smoothed
delta_ns = analytic_sol   - stripy_smoothed

delta_n2  = analytic_sol_n - stripy_smoothed2
delta_ns2 = analytic_sol   - stripy_smoothed2

delta_n3  = analytic_sol_n - stripy_smoothed3
delta_ns3 = analytic_sol   - stripy_smoothed3

stripy_smoothed, dds


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex6-Scattered-Data.ipynb".
The first task is:
Count earthquakes per vertex
The Triangulation.nearest_vertices method uses a k-d tree to find the nearest vertices to a set of x,y points. It returns the nearest vertices and euclidean distance. This requires the k-d tree to have been built when the mesh was initialised (tree=True)
Can you write Python code for it?

distances, vertices = mesh.nearest_vertices(eastings, northings, k=1)
nodes, ncounts = np.unique(vertices, return_counts=True)

hit_countn = np.zeros(mesh.npoints)
hit_countn[nodes] = ncounts

fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111, projection=ccrs.PlateCarree())
ax.coastlines(resolution='10m')
ax.set_extent([135, 148, -39, -30])

ax.scatter(mesh.x, mesh.y,
           marker="o", cmap=plt.cm.Reds, s=100, c=hit_countn, alpha=0.33, transform=proj)

ax.gridlines(draw_labels=True)
plt.show()


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex6-Scattered-Data.ipynb".
The first task is:
Count heat flow points per triangle
This is a numpy wrapper around the TRIPACK routine which operates by retriangulation and is therefore not particularly fast.
Can you write Python code for it?

triangles = mesh.containing_triangle(eastings, northings)
tris, counts = np.unique(triangles, return_counts=True)

print("number of unique triangles = {}".format(tris.shape[0]))

## map to nodes so we can plot this

hit_count = np.zeros(mesh.npoints)

for i in range(0, tris.shape[0]):
    hit_count[mesh.simplices[tris[i]]] += counts[i]

hit_count /= 3.0

print("mean number of hits = {}".format(hit_count.mean()))

fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111, projection=ccrs.PlateCarree())
ax.coastlines(resolution='10m')
ax.set_extent([135, 148, -39, -30])

ax.scatter(mesh.x, mesh.y,
           marker="o", cmap=plt.cm.Reds, s=100, c=hit_count, alpha=0.33, transform=proj)

ax.gridlines(draw_labels=True)
plt.show()


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex6-Scattered-Data.ipynb".
The first task is:
Define a regular computational mesh
Use the (usual) icosahedron with face points included.
Can you write Python code for it?

import stripy as stripy

xmin = eastings.min()
xmax = eastings.max()
ymin = northings.min()
ymax = northings.max()
extent = [xmin, xmax, ymin, ymax]

# define a mesh with 20km x 20km resolution
spacingX = 10000.0
spacingY = 10000.0

mesh = stripy.cartesian_meshes.square_mesh(extent, spacingX, spacingY, refinement_levels=0, tree=True)

print("number of points = {}".format(mesh.npoints))


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex6-Scattered-Data.ipynb".
The first task is:
Inverse distance weighted number of earthquakes
The k-d tree method provides a specified number of neighbours and the distance to those neighbours. This can be used in a number of ways to smooth or amalgamate data. Here for example is a weighted average of each earthquake to nearby nodes.
We compute the distances to $N$ nearby vertices and distribute information to those vertices in inverse proportion to their distance.
$$ w i = \frac{d _i}{\sum{i=1}^N d _i} $$
Alternatively, we might map information to the vertices by applying a radially symmetric kernel to the point data without normalising.
Can you write Python code for it?

distances, vertices = mesh.nearest_vertices(eastings, northings, k=100)
norm = distances.sum(axis=1)

# distances, vertices are arrays of shape (data_size, 10)

hit_countid = np.zeros(mesh.npoints)

## numpy shouldn't try to vectorise this reduction operation

for i in range(0,distances.shape[0]):
    hit_countid[vertices[i,:]] += distances[i,:] / norm[i]

hit_countidr = np.zeros(mesh.npoints)

## numpy shouldn't try to vectorise this reduction operation

for i in range(0,distances.shape[0]):
    hit_countidr[vertices[i,:]] += np.exp( -distances[i,:] / 0.02 )

fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111, projection=ccrs.PlateCarree())
ax.coastlines(resolution='10m')
ax.set_extent([135, 148, -39, -30])

ax.scatter(mesh.x, mesh.y,
           marker="o", cmap=plt.cm.Reds, s=100, c=hit_countid, alpha=0.33, transform=proj)

ax.gridlines(draw_labels=True)
plt.show()


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex7-Refinement-of-Triangulations.ipynb".
The first task is:
Refinement strategies
Five refinement strategies:

Bisect all segments connected to a given node
Refine all triangles connected to a given node by adding a point at the centroid or bisecting all edges
Refine a given triangle by adding a point at the centroid or bisecting all edges

These are provided as follows:
Can you write Python code for it?

mx, my = ellip2.midpoint_refine_triangulation_by_vertices(vertices=[1,2,3,4,5,6,7,8,9,10])
ellip2mv = stripy.Triangulation(mx, my)

mx, my = ellip2.edge_refine_triangulation_by_vertices(vertices=[1,2,3,4,5,6,7,8,9,10])
ellip2ev = stripy.Triangulation(mx, my)

mx, my = ellip2.centroid_refine_triangulation_by_vertices(vertices=[1,2,3,4,5,6,7,8,9,10])
ellip2cv = stripy.Triangulation(mx, my)

mx, my = ellip2.edge_refine_triangulation_by_triangles(triangles=[1,2,3,4,5,6,7,8,9,10])
ellip2et = stripy.Triangulation(mx, my)

mx, my = ellip2.centroid_refine_triangulation_by_triangles(triangles=[1,2,3,4,5,6,7,8,9,10])
ellip2ct = stripy.Triangulation(mx, my)

str_fmt = "refinement --- {} points, {} simplices"
print(str_fmt.format(ellip2mv.npoints, ellip2mv.simplices.shape[0]))
print(str_fmt.format(ellip2ev.npoints, ellip2ev.simplices.shape[0]))
print(str_fmt.format(ellip2cv.npoints, ellip2cv.simplices.shape[0]))
print(str_fmt.format(ellip2et.npoints, ellip2et.simplices.shape[0]))
print(str_fmt.format(ellip2ct.npoints, ellip2ct.simplices.shape[0]))


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex7-Refinement-of-Triangulations.ipynb".
The first task is:
Uniform meshes by refinement
The refinement_level parameter of the stripy meshes makes repeated loops determining the bisection points of all the existing edges in the triangulation and then creating a new triangulation that includes these points and the original ones. These refinement operations can also be used for non-uniform refinement.
Can you write Python code for it?

ellip0 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=0)
ellip1 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=1)
ellip2 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=2)
ellip3 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=3)
ellip4 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=4)
ellip5 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=5)
ellip6 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=6)
ellip7 = stripy.cartesian_meshes.elliptical_mesh(extent, spacingX, spacingY, refinement_levels=7)

print("Size of mesh - 1  {}".format(ellip1.points.shape[0]))
print("Size of mesh - 2  {}".format(ellip2.points.shape[0]))
print("Size of mesh - 3  {}".format(ellip3.points.shape[0]))
print("Size of mesh - 4  {}".format(ellip4.points.shape[0]))
print("Size of mesh - 5  {}".format(ellip5.points.shape[0]))
print("Size of mesh - 6  {}".format(ellip6.points.shape[0]))
print("Size of mesh - 7  {}".format(ellip7.points.shape[0]))


I am working on the file "Notebooks/SphericalMeshing/CartesianTriangulations/Ex7-Refinement-of-Triangulations.ipynb".
The first task is:
Visualisation of refinement strategies
Can you write Python code for it?

%matplotlib inline
import matplotlib.pyplot as plt

def mesh_fig(mesh, meshR, name):

    fig = plt.figure(figsize=(10, 10), facecolor="none")
    ax  = plt.subplot(111)
    ax.axis('off')

    generator = mesh
    refined   = meshR

    x0 = generator.x
    y0 = generator.y

    xR = refined.x
    yR = refined.y

    ax.scatter(x0, y0, color="Red", marker="o", s=50)
    ax.scatter(xR, yR, color="DarkBlue", marker="o", s=10)

    ax.triplot(xR, yR, refined.simplices, color="black", linewidth=0.5)

    fig.savefig(name, dpi=250, transparent=True)

    return

mesh_fig(ellip2,  ellip2mv,  "EdgeByVertex1to10" )
mesh_fig(ellip2,  ellip2ev,  "EdgeByVertexT1to10" )
mesh_fig(ellip2,  ellip2cv,  "CentroidByVertexT1to10" )
mesh_fig(ellip2,  ellip2et,  "EdgeByTriangle1to10" )
mesh_fig(ellip2,  ellip2ct,  "CentroidByTriangle1to10" )


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex1-Spherical-Triangulations.ipynb".
The first task is:
Lavavu to view spherical information
We can view the same triangulation in an interactive form using the lavavu package (pip install lavavu).
The list of simplices of the triangulation (spherical_triangulation.simplices) is compatible with the format expected by Lavavu.
Can you write Python code for it?

import lavavu

lv = lavavu.Viewer(border=False, resolution=[666,666], background="#FFFFFF")
lv["axis"]=False
lv['specular'] = 0.5

ghost = lv.triangles("ghost",  wireframe=False, colour="#777777", opacity=0.1)
ghost.vertices(refined_spherical_triangulation.points*0.99)
ghost.indices(refined_spherical_triangulation.simplices)

tris = lv.triangles("coarse",  wireframe=False, colour="#4444FF", opacity=0.8)
tris.vertices(spherical_triangulation.points)
tris.indices(spherical_triangulation.simplices)

trisw = lv.triangles("coarsew",  wireframe=True, colour="#000000", opacity=0.8, linewidth=3.0)
trisw.vertices(spherical_triangulation.points)
trisw.indices(spherical_triangulation.simplices)

nodes = lv.points("coarse_nodes", pointsize=10.0, pointtype="shiny", colour="#4444FF", opacity=0.95)
nodes.vertices(spherical_triangulation.points)

tris2 = lv.triangles("fine",  wireframe=False, colour="#007f00", opacity=0.25)
tris2.vertices(refined_spherical_triangulation.points)
tris2.indices(refined_spherical_triangulation.simplices)

tris2w = lv.triangles("finew",  wireframe=True, colour="#444444", opacity=0.25, linewidth=0.5)
tris2w.vertices(refined_spherical_triangulation.points)
tris2w.indices(refined_spherical_triangulation.simplices)

nodes2 = lv.points("fine_nodes", pointsize=3.0, pointtype="shiny", colour="FF0000", opacity=0.95)
nodes2.vertices(refined_spherical_triangulation.points)

lv.hide("fine")
lv.hide("finew")

lv.control.Panel()
lv.control.Button(command="hide triangles; hide points; show ghost; show fine_nodes; show coarse; show coarsew; show coarse_nodes; redraw", label="Coarse")
lv.control.Button(command="hide triangles; hide points; show ghost; show coarse_nodes; show fine; show finew; show fine_nodes; redraw", label="Fine")

lv.control.show()


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex1-Spherical-Triangulations.ipynb".
The first task is:
Making a plot of the triangulation
We can make a plot of the two grids and the most straightforward way to display the information
is through a standard map projection of the sphere to the plane.
(Here we superimpose the points on a global map of coastlines using the cartopy map library and use the Mollweide projection.
 Other projections to try include Robinson, Orthographic, PlateCarree)
Can you write Python code for it?

%matplotlib inline

import gdal
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(20, 10), facecolor="none")

ax  = plt.subplot(121, projection=ccrs.Mollweide(central_longitude=0.0, globe=None))
ax.coastlines(color="#777777")
ax.set_global()

ax2 = plt.subplot(122, projection=ccrs.Mollweide(central_longitude=0.0,  globe=None))
ax2.coastlines(color="#777777")
ax2.set_global()

## Plot the vertices and the edges for the original isocahedron

lons = np.degrees(spherical_triangulation.lons)
lats = np.degrees(spherical_triangulation.lats)

ax.scatter(lons, lats, color="Red",
                 marker="o", s=150.0, transform=ccrs.Geodetic())

segs = spherical_triangulation.identify_segments()

for s1, s2 in segs:
    ax.plot( [lons[s1], lons[s2]],
             [lats[s1], lats[s2]],
              linewidth=0.5, color="black", transform=ccrs.Geodetic())

## Plot the vertices and the edges for the refined isocahedron

lons = np.degrees(refined_spherical_triangulation.lons)
lats = np.degrees(refined_spherical_triangulation.lats)

ax2.scatter(lons, lats, color="Red", alpha=0.5,
                 marker="o", s=50.0, transform=ccrs.Geodetic())

segs = refined_spherical_triangulation.identify_segments()

for s1, s2 in segs:
    ax2.plot( [lons[s1], lons[s2]],
              [lats[s1], lats[s2]],
              linewidth=0.5, color="black", transform=ccrs.Geodetic())


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex1-Spherical-Triangulations.ipynb".
The first task is:
This creates a triangulation object constructed using the wrapped fortran code of Renka (1997). The triangulation object has a number of
useful methods and attached data which can be listed with
``` python
help(spherical_triangulation)
```
Can you write Python code for it?

print(spherical_triangulation.areas())
print(spherical_triangulation.npoints)

refined_spherical_triangulation = stripy.sTriangulation(lons=vertices_lon, lats=vertices_lat, refinement_levels=2)

print(refined_spherical_triangulation.npoints)


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex2-SphericalGrids.ipynb".
The first task is:
Analysis of the characteristics of the triangulations
We plot a histogram of the (spherical) areas of the triangles in each of the triangulations normalised by the average area. This is one
measure of the uniformity of each mesh.
Can you write Python code for it?

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

def area_histo(mesh):

    freq, area_bin = np.histogram(mesh.areas(), bins=20)
    area = 0.5 * (area_bin[1:] + area_bin[:-1])
    (area * freq)
    norm_area = area / mesh.areas().mean()

    return norm_area, 0.25 * freq*area / np.pi**2

def add_plot(axis, mesh, xlim, ylim):
    u, v = area_histo(mesh)
    axis.bar(u, v, width=0.025)
    axis.set_xlim(xlim)
    axis.set_ylim(ylim)
    axis.plot([1.0,1.0], [0.0,1.5], linewidth=1.0, linestyle="-.", color="Black")

    return

fig, ax = plt.subplots(4,2, sharey=True, figsize=(8,16))

xlim=(0.75,1.5)
ylim=(0.0,0.125)

# octahedron

add_plot(ax[0,0], octoR, xlim, ylim)

# octahedron + faces

add_plot(ax[0,1], octoFR, xlim, ylim)

# icosahedron

add_plot(ax[1,0], icoR, xlim, ylim)

# icosahedron + faces

add_plot(ax[1,1], icoFR, xlim, ylim)

# cube

add_plot(ax[2,0], cubeR, xlim, ylim)

# C60

add_plot(ax[2,1], soccR, xlim, ylim)

# ring

add_plot(ax[3,0], ringR, xlim, ylim)

# random (this one is very different from the others ... )

axis=ax[3,1]
u, v = area_histo(randR)
axis.bar(u, v, width=0.5)
axis.set_xlim(0.0,11.0)
axis.set_ylim(0,0.125)
axis.plot([1.0,1.0], [0.0,1.5], linewidth=1.0, linestyle="-.", color="Black")

fig.savefig("AreaDistributionsByMesh.png", dpi=250, transparent=True)

#ax.bar(norm_area, area*freq, width=0.01)


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex2-SphericalGrids.ipynb".
The first task is:
Plot and compare the predefined meshes
Can you write Python code for it?

def mesh_fig(mesh, meshR, name):

    fig = plt.figure(figsize=(10, 10), facecolor="none")
    ax  = plt.subplot(111, projection=ccrs.Orthographic(central_longitude=0.0, central_latitude=0.0, globe=None))
    ax.coastlines(color="lightgrey")
    ax.set_global()

    generator = mesh
    refined   = meshR

    lons0 = np.degrees(generator.lons)
    lats0 = np.degrees(generator.lats)

    lonsR = np.degrees(refined.lons)
    latsR = np.degrees(refined.lats)

    lst = refined.lst
    lptr = refined.lptr

    ax.scatter(lons0, lats0, color="Red",
                marker="o", s=150.0, transform=ccrs.Geodetic())

    ax.scatter(lonsR, latsR, color="DarkBlue",
                marker="o", s=50.0, transform=ccrs.Geodetic())

    segs = refined.identify_segments()

    for s1, s2 in segs:
        ax.plot( [lonsR[s1], lonsR[s2]],
                 [latsR[s1], latsR[s2]],
                 linewidth=0.5, color="black", transform=ccrs.Geodetic())

    fig.savefig(name, dpi=250, transparent=True)

    return

mesh_fig(octo0,  octo2, "Octagon" )
mesh_fig(octoF0, octoF2, "OctagonF" )

mesh_fig(ico0, ico2, "Icosahedron" )
mesh_fig(icoF0, icoF2, "IcosahedronF" )

mesh_fig(cube0, cube2, "Cube")
mesh_fig(socc0, socc2, "SoccerBall")

mesh_fig(ring0, ring2, "Ring")
mesh_fig(rand0, rand2, "Random")


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex2-SphericalGrids.ipynb".
The first task is:
The icosahedron with faces looks like this
It is helpful to be able to view a mesh in 3D to verify that it is an appropriate choice. Here, for example, is the icosahedron with additional points in the centroid of the faces.
This produces triangles with a narrow area distribution. In three dimensions it is easy to see the origin of the size variations.
Can you write Python code for it?

## The icosahedron with faces in 3D view

import lavavu

## or smesh = icoF0
smesh = icoFR

lv = lavavu.Viewer(border=False, background="#FFFFFF", resolution=[1000,600], near=-10.0)

tris = lv.triangles("triangulation",  wireframe=True, colour="#444444", opacity=0.8)
tris.vertices(smesh.points)
tris.indices(smesh.simplices)

tris2 = lv.triangles("triangles",  wireframe=False, colour="#77ff88", opacity=0.8)
tris2.vertices(smesh.points)
tris2.indices(smesh.simplices)

nodes = lv.points("nodes", pointsize=2.0, pointtype="shiny", colour="#448080", opacity=0.75)
nodes.vertices(smesh.points)

lv.control.Panel()
lv.control.Range('specular', range=(0,1), step=0.1, value=0.4)
lv.control.Checkbox(property='axis')
lv.control.ObjectList()
lv.control.show()

%matplotlib inline

import gdal
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

global_extent     = [-180.0, 180.0, -90.0, 90.0]

projection1 = ccrs.Orthographic(central_longitude=0.0, central_latitude=0.0, globe=None)
projection2 = ccrs.Mollweide(central_longitude=-120)
projection3 = ccrs.PlateCarree()
base_projection = ccrs.PlateCarree()


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex3-Interpolation.ipynb".
The first task is:
Analytic function
Define a relatively smooth function that we can interpolate from the coarse mesh to the fine mesh and analyse
Can you write Python code for it?

def analytic(lons, lats, k1, k2):
     return np.cos(k1*lons) * np.sin(k2*lats)

coarse_afn = analytic(cmesh.lons, cmesh.lats, 5.0, 2.0)
fine_afn   = analytic(fmesh.lons, fmesh.lats, 5.0, 2.0)


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex4-Gradients.ipynb".
The first task is:
Analytic function
Define a relatively smooth function that we can interpolate from the coarse mesh to the fine mesh and analyse
Can you write Python code for it?

import numpy as np

def analytic(lons, lats, k1, k2):
     return np.cos(k1*lons) * np.sin(k2*lats)

def analytic_ddlon(lons, lats, k1, k2):
     return -k1 * np.sin(k1*lons) * np.sin(k2*lats) / np.cos(lats)

def analytic_ddlat(lons, lats, k1, k2):
     return k2 * np.cos(k1*lons) * np.cos(k2*lats)

analytic_sol = analytic(mesh.lons, mesh.lats, 5.0, 2.0)
analytic_sol_ddlon = analytic_ddlon(mesh.lons, mesh.lats, 5.0, 2.0)
analytic_sol_ddlat = analytic_ddlat(mesh.lons, mesh.lats, 5.0, 2.0)

%matplotlib inline

import gdal
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10, 10), facecolor="none")
ax  = plt.subplot(111, projection=ccrs.Orthographic(central_longitude=0.0, central_latitude=0.0, globe=None))
ax.coastlines(color="lightgrey")
ax.set_global()

lons0 = np.degrees(mesh.lons)
lats0 = np.degrees(mesh.lats)

ax.scatter(lons0, lats0,
            marker="o", s=10.0, transform=ccrs.Geodetic(), c=analytic_sol, cmap=plt.cm.RdBu)

pass


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex4-Gradients.ipynb".
The first task is:
Derivatives of solution compared to analytic values
The gradient_lonlat method of the sTriangulation takes a data array reprenting values on the mesh vertices and returns the lon and lat derivatives. There is an equivalent gradient_xyz method which returns the raw derivatives in Cartesian form. Although this is generally less useful, if you are computing the slope (for example) that can be computed in either coordinate system and may cross the pole, consider using the Cartesian form.
Can you write Python code for it?

stripy_ddlon, stripy_ddlat = mesh.gradient_lonlat(analytic_sol)

import lavavu

lv = lavavu.Viewer(border=False, background="#FFFFFF", resolution=[1000,600], near=-10.0)

nodes = lv.points("nodes", pointsize=3.0, pointtype="shiny", colour="#448080", opacity=0.75)
nodes.vertices(mesh.points)

tris = lv.triangles("triangles",  wireframe=False, colour="#77ff88", opacity=1.0)
tris.vertices(mesh.points)
tris.indices(mesh.simplices)
tris.values(analytic_sol, label="original")
tris.values(stripy_ddlon, label="ddlon")
tris.values(stripy_ddlat, label="ddlat")
tris.values(stripy_ddlon-analytic_sol_ddlon, label="ddlonerr")
tris.values(stripy_ddlat-analytic_sol_ddlat, label="ddlaterr")

tris.colourmap("#990000 #FFFFFF #000099")
cb = tris.colourbar()

# view the pole

lv.translation(0.0, 0.0, -3.0)
lv.rotation(-20, 0.0, 0.0)

lv.control.Panel()
lv.control.Range('specular', range=(0,1), step=0.1, value=0.4)
lv.control.Checkbox(property='axis')
lv.control.ObjectList()
tris.control.List(["original", "ddlon", "ddlat", "ddlonerr", "ddlaterr"], property="colourby", value="orginal", command="redraw", label="Display:")
lv.control.show()


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex5-Smoothing.ipynb".
The first task is:
Analytic function with noise and short wavelengths
Define a relatively smooth function that we can interpolate from the coarse mesh to the fine mesh and analyse
Can you write Python code for it?

import numpy as np

def analytic(lons, lats, k1, k2):
     return  np.cos(k1*lons) * np.sin(k2*lats)

def analytic_noisy(lons, lats, k1, k2, noise, short):
     return  np.cos(k1*lons) * np.sin(k2*lats) + short * (np.cos(k1*5.0*lons) * np.sin(k2*5.0*lats)) +  noise * np.random.random(lons.shape)

# def analytic_ddlon(lons, lats, k1, k2):
#      return -k1 * np.sin(k1*lons) * np.sin(k2*lats) / np.cos(lats)

# def analytic_ddlat(lons, lats, k1, k2):
#      return k2 * np.cos(k1*lons) * np.cos(k2*lats)

analytic_sol   = analytic(mesh.lons, mesh.lats, 5.0, 2.0)
analytic_sol_n = analytic_noisy(mesh.lons, mesh.lats, 5.0, 2.0, 0.1, 0.0)

%matplotlib inline

import gdal
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10, 10), facecolor="none")
ax  = plt.subplot(111, projection=ccrs.Orthographic(central_longitude=0.0, central_latitude=0.0, globe=None))
ax.coastlines(color="#999999", linewidth=2.0)
ax.set_global()

lons0 = np.degrees(mesh.lons)
lats0 = np.degrees(mesh.lats)

ax.scatter(lons0, lats0,
            marker="o", s=10.0, transform=ccrs.Geodetic(), c=analytic_sol_n-analytic_sol, cmap=plt.cm.RdBu)

pass


I am working on the file "Notebooks/SphericalMeshing/SphericalTriangulations/Ex5-Smoothing.ipynb".
The first task is:
Results of smoothing with different value of sm
Can you write Python code for it?

import lavavu

lv = lavavu.Viewer(border=False, background="#FFFFFF", resolution=[666,666], near=-10.0)

nodes = lv.points("nodes", pointsize=3.0, pointtype="shiny", colour="#448080", opacity=0.75)
nodes.vertices(mesh.points)

tris = lv.triangles("triangles",  wireframe=False, colour="#77ff88", opacity=1.0)
tris.vertices(mesh.points)
tris.indices(mesh.simplices)
tris.values(analytic_sol_n, label="original")
tris.values(stripy_smoothed, label="smoothed")
tris.values(stripy_smoothed2, label="smoothed2")
tris.values(stripy_smoothed3, label="smoothed3")

tris.values(delta_n, label="delta_n")
tris.values(delta_ns, label="delta_ns")

tris.values(delta_n2, label="delta_n2")
tris.values(delta_ns2, label="delta_ns2")

tris.values(delta_n3, label="delta_n3")
tris.values(delta_ns3, label="delta_ns3")

# and the errors

tris.colourmap("#990000 #FFFFFF #000099")

cb = tris.colourbar()

# view the pole

lv.translation(0.0, 0.0, -3.0)
lv.rotation(-20, 0.0, 0.0)

lv.control.Panel()
lv.control.Range('specular', range=(0,1), step=0.1, value=0.4)
lv.control.Checkbox(property='axis')
lv.control.ObjectList()
tris.control.List(["original", "smoothed", "smoothed2", "smoothed3",
                   "delta_n", "delta_ns",
                   "delta_n2", "delta_ns2",
                   "delta_n3", "delta_ns3"], property="colourby", value="orginal", command="redraw")
lv.control.show()