foscat 3.1.6__py3-none-any.whl → 3.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
foscat/alm.py ADDED
@@ -0,0 +1,134 @@
1
+ import healpy as hp
2
+ import numpy as np
3
+
4
+ class alm():
5
+
6
+ def __init__(self,backend=None,lmax=24,limit_range=1E7):
7
+ self._logtab={}
8
+ self.lmax=0
9
+ for k in range(1,2*lmax+1):
10
+ self._logtab[k]=np.log(k)
11
+ self._limit_range=1/limit_range
12
+ self._log_limit_range=np.log(limit_range)
13
+ if backend is None:
14
+ import foscat.scat_cov as sc
15
+ self.sc=sc.funct()
16
+ self.backend=self.sc.backend
17
+ else:
18
+ self.backend=backend.backend
19
+
20
+ def log(self,v):
21
+ #return np.log(v)
22
+ if isinstance(v,np.ndarray):
23
+ return np.array([self.log(k) for k in v])
24
+ if v<self.lmax*2+1:
25
+ return self._logtab[v]
26
+ else:
27
+ self._logtab[v]=np.log(v)
28
+ return self._logtab[v]
29
+
30
+ # Fonction pour calculer la double factorielle
31
+ def double_factorial_log(self,n):
32
+ if n <= 0:
33
+ return 0.0
34
+ result = 0.0
35
+ for i in range(n, 0, -2):
36
+ result += self.log(i)
37
+ return result
38
+
39
+ # Calcul des P_{lm}(x) pour tout l inclus dans [m,lmax]
40
+ def compute_legendre_m(self,x,m,lmax):
41
+ # Étape 1 : Calcul de P_{mm}(x)
42
+ if m == 0:
43
+ Pmm = 1.0
44
+ else:
45
+ Pmm = (-1)**m * (1 - x**2)**(m/2)
46
+
47
+ result=np.zeros([lmax-m+1,x.shape[0]])
48
+ ratio=np.zeros([lmax-m+1,1])
49
+
50
+ # Si l == m, c'est directement P_{mm}
51
+ result[0]=Pmm
52
+ ratio[0,0]= self.double_factorial_log(2*m - 1)-0.5*np.sum(self.log(1+np.arange(2*m)))
53
+
54
+ if m == lmax:
55
+ return result*np.exp(ratio)*np.sqrt((2*(np.arange(lmax-m+1)-m))/(4*np.pi)).reshape(lmax+1-m,1)
56
+
57
+ # Étape 2 : Calcul de P_{l+1, m}(x)
58
+ result[1] = x * (2*m + 1) * result[0]
59
+
60
+ ratio[1,0]=ratio[0,0]-0.5*self.log(2*m+1)
61
+
62
+ # Étape 3 : Récurence pour l > m + 1
63
+ for l in range(m + 2, lmax+1):
64
+ result[l-m] = ((2*l - 1) * x * result[l-m-1] - (l + m - 1) * result[l-m-2]) / (l - m)
65
+ ratio[l-m,0] = 0.5*self.log(l-m)-0.5*self.log(l+m)+ratio[l-m-1,0]
66
+ if np.max(abs(result[l-m]))>self._limit_range:
67
+ result[l-m-1]*=self._limit_range
68
+ result[l-m]*=self._limit_range
69
+ ratio[l-m-1,0]+=self._log_limit_range
70
+ ratio[l-m,0]+=self._log_limit_range
71
+
72
+ return result*np.exp(ratio)*(np.sqrt(4*np.pi*(2*(np.arange(lmax-m+1)+m)+1))).reshape(lmax+1-m,1)
73
+
74
+ def comp_tf(self,im,ph):
75
+ nside=int(np.sqrt(im.shape[0]//12))
76
+ n=0
77
+ ii=0
78
+ ft_im=[]
79
+ for k in range(nside-1):
80
+ N=4*(k+1)
81
+ ft_im.append(self.backend.bk_fft(im[n:n+N])[:N//2+1]*np.exp(-1J*np.arange(N//2+1)/N*ph[n]))
82
+ ft_im.append(self.backend.bk_zeros((3*nside-N//2-1),dtype=self.backend.all_cbk_type))
83
+ n+=N
84
+ ii+=1
85
+ for k in range(2*nside+1):
86
+ N=4*nside
87
+ ft_im.append(self.backend.bk_fft(im[n:n+N])[:N//2+1]*np.exp(-1J*np.arange(N//2+1)/N*ph[n]))
88
+ ft_im.append(self.backend.bk_zeros((3*nside-N//2-1),dtype=self.backend.all_cbk_type))
89
+ n+=N
90
+ ii+=1
91
+ for k in range(nside-1):
92
+ N=4*(nside-1-k)
93
+ ft_im.append(self.backend.bk_fft(im[n:n+N])[:N//2+1]*np.exp(-1J*np.arange(N//2+1)/N*ph[n]))
94
+ ft_im.append(self.backend.bk_zeros((3*nside-N//2-1),dtype=self.backend.all_cbk_type))
95
+ n+=N
96
+ ii+=1
97
+ return self.backend.bk_reshape(self.backend.bk_concat(ft_im,axis=0),[4*nside-1,3*nside])
98
+
99
+ def anafast(self,im,map2=None):
100
+ nside=int(np.sqrt(im.shape[0]//12))
101
+ th,ph=hp.pix2ang(nside,np.arange(12*nside*nside))
102
+ ft_im=self.comp_tf(self.backend.bk_complex(im,0*im),ph)
103
+ if map2 is not None:
104
+ ft_im2=self.comp_tf(self.backend.bk_complex(map2,0*im),ph)
105
+
106
+ co_th=np.cos(np.unique(th))
107
+
108
+ lmax=3*nside-1
109
+
110
+ cl2=None
111
+ cl2_L1=None
112
+ for m in range(lmax+1):
113
+ plm=self.compute_legendre_m(co_th,m,3*nside-1)/(12*nside**2)
114
+
115
+ tmp=self.backend.bk_reduce_sum(plm*ft_im[:,m],1)
116
+
117
+ if map2 is not None:
118
+ tmp2=self.backend.bk_reduce_sum(plm*ft_im2[:,m],1)
119
+ else:
120
+ tmp2=tmp
121
+
122
+ tmp=self.backend.bk_real((tmp*self.backend.bk_conjugate(tmp2)))
123
+ if cl2 is None:
124
+ cl2=tmp
125
+ cl2_l1=self.backend.bk_L1(tmp)
126
+ else:
127
+ tmp=self.backend.bk_concat([self.backend.bk_zeros((m),dtype=self.backend.all_bk_type),tmp],axis=0)
128
+ cl2+=2*tmp
129
+ cl2_l1+=2*self.backend.bk_L1(tmp)
130
+ cl2=cl2*(1+np.clip((np.arange(cl2.shape[0])-2*nside)/(3*nside),0,1))/(2*np.arange(cl2.shape[0])+1)* \
131
+ (1+np.clip((np.arange(cl2.shape[0])-2.4*nside)/(2.5*nside),0,1))
132
+ cl2_l1=cl2_l1*(1+np.clip((np.arange(cl2.shape[0])-2*nside)/(3*nside),0,1))/(2*np.arange(cl2.shape[0])+1)* \
133
+ (1+np.clip((np.arange(cl2.shape[0])-2.4*nside)/(2.5*nside),0,1))
134
+ return cl2,cl2_l1