AnisoCADO 0.3.0__py3-none-any.whl → 0.4.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.

Potentially problematic release.


This version of AnisoCADO might be problematic. Click here for more details.

anisocado/pupil_utils.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  # -*- coding: utf-8 -*-
3
2
  """
4
3
  Created on Fri Jun 8 15:38:32 2018
@@ -7,18 +6,14 @@ Created on Fri Jun 8 15:38:32 2018
7
6
 
8
7
  Original Title : make_ricoPupil.py
9
8
 
10
- """
11
-
12
- import numpy as np
13
- # import matplotlib.pyplot as plt
14
- # plt.ion()
9
+ =====================================================
10
+ CONVENTIONS : Ce fichier est ecrit en convention X, Y
11
+ =====================================================
15
12
 
16
- """
17
- CONVENTIONS : Ce fichier est ecrit en convention X,Y
13
+ 1.0 Convention X, Y
14
+ -------------------
18
15
 
19
- ...................................................... 1.0 Convention X,Y
20
-
21
- Dans la convention d'axes (x,y), tous les tableaux representant des images
16
+ Dans la convention d'axes (x, y), tous les tableaux representant des images
22
17
  s'adressent par
23
18
  tab[ix, iy]
24
19
  Les indices s'utilisent alors classiquement
@@ -30,18 +25,18 @@ où ind[0] porte X. On fera donc appel a
30
25
  tab[ix, iy]
31
26
 
32
27
  La fonction meshgrid fait chier, et doit s'appeler par
33
- X,Y = meshgrid(x,y, indexing='ij')
28
+ X, Y = meshgrid(x, y, indexing="ij")
34
29
  pour creer des tableaux conformes a un appel en X[ix, iy].
35
30
 
36
31
  Dans les tableaux qui stockent des coord en x,y on utilise
37
- x = tab[:,0]
38
- y = tab[:,1]
32
+ x = tab[:, 0]
33
+ y = tab[:, 1]
39
34
  pour que l'utilisation de flatten() mette X en premier. Cette facon de proceder
40
35
  est logique/compatible avec les indices.
41
36
 
42
37
  Dans les fonctions on place x d'abord, y ensuite, dans les arguments comme
43
38
  dans le retour de fonction
44
- def toto(...,x,y,...)
39
+ def toto(..., x, y, ...)
45
40
  return x, y
46
41
  et
47
42
  x, y = toto(...)
@@ -49,24 +44,26 @@ et
49
44
  Graphisme: Pour afficher un tel tableau et avoir une representation
50
45
  'naturelle' avec x "a droite" et y "en haut" il faut par contre
51
46
  utiliser une transposition et retournement d'axe
52
- plt.imshow(tab.T, origin='lower')
47
+ plt.imshow(tab.T, origin="lower")
53
48
  et qui offre une utilisation classique de
54
49
  plt.plot(x, y, ...)
55
50
  qui placera un overlay d'un plot de façon coherente sur l'image affichee.
56
51
 
57
52
 
58
- Une sortie FITS d'un tableau tab[x,y] va generer un fichier qui contient des
53
+ Une sortie FITS d'un tableau tab[x, y] va generer un fichier qui contient des
59
54
  data avec un axe rapide NAXIS1 dirige selon Y. Attention car de nombreux
60
- logiciels considerent axe rapide = axe x (par exemple ds9), ou representent
55
+ logiciels considerent axe rapide = axe x (par exemple ds9), ou representent
61
56
  l'axe rapide souvent horizontal en natif (ds9, python, yorick, idl, ...)
62
57
  Donc, pour les entrees/sorties on transposera les data
63
- pf.writeto('monfichier.fits', tab.T)
58
+ pf.writeto("monfichier.fits", tab.T)
64
59
  et
65
- tab = pf.getdata('monfichier.fits').T
60
+ tab = pf.getdata("monfichier.fits").T
61
+
66
62
 
63
+ 2.0 Convention Y, X
64
+ -------------------
67
65
 
68
- ...................................................... 2.0 Convention Y,X
69
- Dans la convention d'axe (y,x), tous les tableaux d'images sont
66
+ Dans la convention d'axe (y, x), tous les tableaux d'images sont
70
67
  adresses par
71
68
  tab[iy, ix]
72
69
 
@@ -90,67 +87,68 @@ et a l'appel de la fonction et recup des coordonnees on garde
90
87
  x, y = toto(args, ax, ay, ..)
91
88
 
92
89
  La fonction meshgrid doit s'appeler par
93
- X,Y = meshgrid(x,y)
90
+ X, Y = meshgrid(x, y)
94
91
  pour creer des tableaux conformes a un appel en X[iy, ix].
95
92
 
96
- Dans les tableaux qui stockent des coord en x,y on utilise
97
- x = tab[:,0]
98
- y = tab[:,1]
93
+ Dans les tableaux qui stockent des coord en x, y on utilise
94
+ x = tab[:, 0]
95
+ y = tab[:, 1]
99
96
  pour que l'utilisation de flatten() mette X en premier. Cependant cette
100
97
  notation est en conflit avec le traitement des indices (fonction where()) qui
101
98
  placent Y d'abord.
102
99
 
103
100
  Graphisme: Pour afficher un tel tableau et avoir une representation
104
- 'naturelle' avec x "a droite" et y "en haut" il faut juste utiliser le
101
+ "naturelle" avec x "a droite" et y "en haut" il faut juste utiliser le
105
102
  retournement d'axe
106
- plt.imshow(tab, origin='lower')
103
+ plt.imshow(tab, origin="lower")
107
104
  suivi d'une utilisation classique de
108
105
  plt.plot(x, y, ...)
109
106
  qui placera un overlay d'un plot de façon coherente sur l'image affichee.
110
107
 
111
108
 
112
- Une sortie FITS d'un tableau tab[x,y] cree un fichier qui aura un axe
109
+ Une sortie FITS d'un tableau tab[x, y] cree un fichier qui aura un axe
113
110
  rapide NAXIS1 selon X, coherent avec la plupart des logiciels (ds9, python,
114
111
  yorick, idl, ...)
115
112
 
116
113
 
117
- ............................................................ 3.0 Meshgrid
114
+ 3.0 Meshgrid
115
+ ------------
118
116
 
119
117
  Quand on definit
120
118
  x = ...
121
119
  y = ...
122
- et qu'on utilise np.meshgrid(), on a
120
+ et qu'on utilise np.meshgrid(), on a
123
121
 
124
- code convention d'appel mat/imshow
125
- X,Y = meshgrid(x,y) [y,x] X horizontal
126
- X,Y = meshgrid(x,y,indexing='ij') [x,y] X vertical :-(
127
- Y,X = meshgrid(y,x) [x,y] X vertical :-(
128
- Y,X = meshgrid(y,x,indexing='ij') [y,x] X horizontal
129
- X,Y = meshgrid(y,x) incoherent
122
+ code convention d'appel mat/imshow
123
+ X, Y = meshgrid(x, y) [y, x] X horizontal
124
+ X, Y = meshgrid(x, y, indexing="ij") [x, y] X vertical
125
+ Y, X = meshgrid(y, x) [x, y] X vertical
126
+ Y, X = meshgrid(y, x, indexing="ij") [y, x] X horizontal
127
+ X, Y = meshgrid(y, x) incoherent
130
128
 
131
- meshgrid(x,y) equivaut a indexing='xy' (default).
132
- Indexing 'ij' ou 'xy' affecte la transposition des X,Y de sortie.
129
+ meshgrid(x, y) equivaut a indexing="xy" (default).
130
+ Indexing "ij" ou "xy" affecte la transposition des X,Y de sortie.
133
131
  L'interversion x/y dans les parametres d'appel et de sortie affecte la
134
132
  transposition des X/Y.
135
133
 
136
134
 
137
- Donc
138
- - soit on utilise meshgrid(x,y) sans option d'indexing, ce qui donne des
135
+ Donc
136
+ - soit on utilise meshgrid(x, y) sans option d'indexing, ce qui donne des
139
137
  plot 2D plutot user-friendly sans pencher la tete et sans transposee, mais
140
138
  la notation d'appel dans les tableaux doit etre [iy,ix]
141
- - soit on utilise meshgrid(..,indexing='ij'), on aura avec imshow() sans
142
- option des plots a regarder avec la tete 90° a droite, et une notation [x,y]
139
+ - soit on utilise meshgrid(..,indexing="ij"), on aura avec imshow() sans
140
+ option des plots a regarder avec la tete 90° a droite, et une notation [x, y]
143
141
  partout dans le code.
144
- Pour avoir les plots python "dans le bon sens" avec une notation [x,y] il faut
145
- plt.imshow(p.T,origin='lower').
142
+ Pour avoir les plots python "dans le bon sens" avec une notation [x, y] il faut
143
+ plt.imshow(p.T, origin="lower").
146
144
 
147
145
 
148
146
  L'utilisation
149
- X,Y = meshgrid(y,x)
147
+ X, Y = meshgrid(y, x)
150
148
  ou
151
- Y,X = meshgrid(x,y)
152
- n'a de sens que si x==y (par exemple x=y=np.linspace(-1,1,n) ...) et permet
153
- le meme rendu que indexing='ij'. Mais c'est un joli hasard. Des que les
149
+ Y, X = meshgrid(x, y)
150
+ n'a de sens que si x==y (par exemple x=y=np.linspace(-1, 1, n) ...) et permet
151
+ le meme rendu que indexing="ij". Mais c'est un joli hasard. Des que les
154
152
  axes x et y se distinguent, soit par le nbre de points, soit par les
155
153
  valeurs (soit le range, le step, l'offset, etc.) alors inverser x et y est
156
154
  juste purement incoherent.
@@ -159,7 +157,19 @@ juste purement incoherent.
159
157
  """
160
158
 
161
159
 
162
- def fillPolygon(x, y, i0, j0, scale, gap, N, index=0):
160
+ import numpy as np
161
+
162
+
163
+ def fillPolygon(
164
+ x: float,
165
+ y: float,
166
+ i0: float,
167
+ j0: float,
168
+ scale: float,
169
+ gap: float,
170
+ N: int,
171
+ index: int = 0,
172
+ ) -> np.ndarray:
163
173
  """
164
174
  From a list of points defined by their 2 coordinates list
165
175
  x and y, creates a filled polygon with sides joining the points.
@@ -169,28 +179,43 @@ def fillPolygon(x, y, i0, j0, scale, gap, N, index=0):
169
179
  Arrays x and y are supposed to be in unit U, and scale is the
170
180
  pixel size in U units.
171
181
 
172
- :returns: filled polygon (N, N), boolean
173
- :param float x, y: list of points defining the polygon
174
- :param float i0, j0: index of pixels where the pupil should be centred.
175
- Can be floating-point indexes.
176
- :param float scale: size of a pixel of the image, in same unit as x and y.
177
- :param float N: size of output image.
178
-
179
- :Example:
180
- x = np.array([1,-1,-1.5,0,1.1])
181
- y = np.array([1,1.5,-0.2,-2,0])
182
- N = 200
183
- i0 = N/2
184
- j0 = N/2
185
- gap = 0.
186
- scale = 0.03
187
- pol = fillPolygon(x, y, i0, j0, scale, gap, N, index=2)
182
+ Parameters
183
+ ----------
184
+ x, y : float
185
+ List of points defining the polygon.
186
+ i0, j0 : float
187
+ Indices of pixels where the pupil should be centred.
188
+ May be floating-point indices.
189
+ scale : float
190
+ Size of a pixel of the image, in same unit as x and y.
191
+ gap : float
192
+ Half-space between segments in meters.
193
+ N : int
194
+ Size of output image.
195
+ index : int, optional
196
+ DESCRIPTION. The default is 0.
197
+
198
+ Returns
199
+ -------
200
+ np.ndarray
201
+ Filled polygon (N, N), boolean.
202
+
203
+ Examples
204
+ --------
205
+ >>> x = np.array([1,-1,-1.5,0,1.1])
206
+ >>> y = np.array([1,1.5,-0.2,-2,0])
207
+ >>> N = 200
208
+ >>> i0 = N/2
209
+ >>> j0 = N/2
210
+ >>> gap = 0.
211
+ >>> scale = 0.03
212
+ >>> pol = fillPolygon(x, y, i0, j0, scale, gap, N, index=2)
188
213
 
189
214
  """
190
215
  # define coordinates map centred on (i0,j0) with same units as x,y.
191
216
  X = (np.arange(N) - i0) * scale
192
217
  Y = (np.arange(N) - j0) * scale
193
- X, Y = np.meshgrid(X, Y, indexing='ij') # indexage [x,y]
218
+ X, Y = np.meshgrid(X, Y, indexing="ij") # indexage [x,y]
194
219
 
195
220
  # define centre of polygon x0, y0
196
221
  x0 = np.mean(x)
@@ -273,7 +298,7 @@ def centrePourVidal(N, i0, j0, centerMark):
273
298
  res = 0
274
299
  X = (np.arange(N) - i0) * scale
275
300
  Y = (np.arange(N) - j0) * scale
276
- X, Y = np.meshgrid(X, Y, indexing='ij') # convention d'appel [x,y]
301
+ X, Y = np.meshgrid(X, Y, indexing="ij") # convention d'appel [x,y]
277
302
  if centerMark == 1:
278
303
  res = (X ** 2 + Y ** 2) < 1
279
304
  if centerMark == 2:
@@ -299,7 +324,7 @@ def fillSpider(N, nspider, dspider, i0, j0, scale, rot):
299
324
  a = np.ones((N, N), dtype=np.bool_)
300
325
  X = (np.arange(N) - i0) * scale
301
326
  Y = (np.arange(N) - j0) * scale
302
- X, Y = np.meshgrid(X, Y, indexing='ij') # convention d'appel [x,y]
327
+ X, Y = np.meshgrid(X, Y, indexing="ij") # convention d'appel [x,y]
303
328
  w = 2 * np.pi / nspider
304
329
  # rot += np.pi/2 # parce que c'est comme ca !!
305
330
  for i in range(nspider):
@@ -311,7 +336,7 @@ def fillSpider(N, nspider, dspider, i0, j0, scale, rot):
311
336
 
312
337
  def generateEeltPupil_slow(npt, dspider, i0, j0, pixscale, rotdegree):
313
338
  """
314
- Computes the binary EELT pupil on a map of size (npt, npt).
339
+ Computes the binary ELT pupil on a map of size (npt, npt).
315
340
  This is the original function, that builds the pupil shape according to
316
341
  hardcoded contours.
317
342
  This function is now obsolete, because it's been replaced by the faster
@@ -324,7 +349,8 @@ def generateEeltPupil_slow(npt, dspider, i0, j0, pixscale, rotdegree):
324
349
  :param float pixscale: size of a pixel of the image, in meters.
325
350
  :param float rotdegree: rotation angle of the pupil, in degrees.
326
351
 
327
- :Example:
352
+ Examples
353
+ --------
328
354
  >>> pup = generateEeltPupil_slow(800, 0.6, 400, 400, 0.1, 3.0)
329
355
 
330
356
  """
@@ -495,7 +521,7 @@ def createHexaPattern(pitch, supportSize):
495
521
  x = pitch * (np.arange(2 * nx + 1) - nx)
496
522
  ny = int(np.ceil((supportSize / 2.0) / pitch / V3) + 1)
497
523
  y = (V3 * pitch) * (np.arange(2 * ny + 1) - ny)
498
- x, y = np.meshgrid(x, y, indexing='ij')
524
+ x, y = np.meshgrid(x, y, indexing="ij")
499
525
  x = x.flatten()
500
526
  y = y.flatten()
501
527
  peak_axis = np.append(x, x + pitch / 2.) # axe dirige selon sommet
@@ -510,7 +536,7 @@ def generateCoordSegments(D, rot):
510
536
  Result is a tuple of arrays(6, 798).
511
537
 
512
538
  :param float D: D is the pupil diameter in meters, it must be set to 40.0 m
513
- for the nominal EELT.
539
+ for the nominal ELT.
514
540
  :param float rot: pupil rotation angle in radians
515
541
 
516
542
  """
@@ -526,7 +552,7 @@ def generateCoordSegments(D, rot):
526
552
  # Elimination des segments non valides grace a 2 nombres parfaitement
527
553
  # empiriques ajustes a-la-mano.
528
554
  inner_rad, outer_rad = 4.1, 15.4 # nominal, 798 segments
529
- nn = (ll > inner_rad * pitch) & (ll < outer_rad * pitch);
555
+ nn = (ll > inner_rad * pitch) & (ll < outer_rad * pitch)
530
556
  lx = lx[nn]
531
557
  ly = ly[nn]
532
558
  lx, ly = reorganizeSegmentsOrderESO(lx, ly)
@@ -592,7 +618,7 @@ def reorganizeSegmentsOrderESO(x, y):
592
618
  sector = (t > k * pi_3) & (t < (k + 1) * pi_3)
593
619
  u = k * pi_3
594
620
  distance = (A * np.cos(u) - np.sin(u)) * x[sector] + (
595
- np.cos(u) + A * np.sin(u)) * y[sector]
621
+ np.cos(u) + A * np.sin(u)) * y[sector]
596
622
  indsort = np.argsort(distance)
597
623
  X = np.append(X, x[sector][indsort])
598
624
  Y = np.append(Y, y[sector][indsort])
@@ -642,7 +668,7 @@ def generateSegmentProperties(attribute, hx, hy, i0, j0, scale, gap, N, D,
642
668
  :param float scale: size of a pixel of the image, in meters.
643
669
  :param float gap: half-space between segments in meters
644
670
  :param int N: size of the output array (N,N)
645
- :param float D: diameter of the pupil. For the nominal EELT, D shall
671
+ :param float D: diameter of the pupil. For the nominal ELT, D shall
646
672
  be set to 40.0
647
673
  :param bool softGap: if False, the gap between segments is binary 0/1
648
674
  depending if the pixel is within the gap or not. If True, the gap
@@ -688,8 +714,8 @@ def generateSegmentProperties(attribute, hx, hy, i0, j0, scale, gap, N, D,
688
714
  # the width of the impulse response, chosen 2-pixel wide to be
689
715
  # well sampled.
690
716
  # The "depth" is related to the gap width. The integral of a
691
- # Lorentzian of 2 pix wide is PI. Integral of a gap of width 'gap'
692
- # in pixels is 'gap'.
717
+ # Lorentzian of 2 pix wide is PI. Integral of a gap of width "gap"
718
+ # in pixels is "gap".
693
719
  # So the depth equals to gap/scale/np.pi.
694
720
  for i in range(nseg):
695
721
  indx, indy, distedge = fillPolygon(hx[:, i], hy[:, i],
@@ -697,8 +723,8 @@ def generateSegmentProperties(attribute, hx, hy, i0, j0, scale, gap, N, D,
697
723
  scale, gap * 0., segdiam,
698
724
  index=1)
699
725
  pupil[indx + ix0[i], indy + iy0[i]] = attribute[i] * (
700
- 1. - (gap / scale / np.pi) / (
701
- 1 + (distedge / scale) ** 2))
726
+ 1. - (gap / scale / np.pi) / (
727
+ 1 + (distedge / scale) ** 2))
702
728
  else:
703
729
  # Hard gaps
704
730
  for i in range(nseg):
@@ -710,7 +736,7 @@ def generateSegmentProperties(attribute, hx, hy, i0, j0, scale, gap, N, D,
710
736
  # attribute is [piston, tip, tilt]
711
737
  minimap = np.zeros((segdiam, segdiam))
712
738
  xmap = np.arange(segdiam) - segdiam / 2
713
- xmap, ymap = np.meshgrid(xmap, xmap, indexing='ij') # [x,y] convention
739
+ xmap, ymap = np.meshgrid(xmap, xmap, indexing="ij") # [x,y] convention
714
740
  pitch = 1.244683637214 # diameter of inscribed circle
715
741
  diamseg = pitch * 2 / np.sqrt(3) # diameter of circumscribed circle
716
742
  diamfrizou = (pitch + diamseg) / 2 * D / 40. # average diameter
@@ -724,61 +750,82 @@ def generateSegmentProperties(attribute, hx, hy, i0, j0, scale, gap, N, D,
724
750
  j0 - iy0[i], scale, 0., segdiam,
725
751
  index=1)
726
752
  minimap = attribute[0, i] + (factunit * attribute[1, i]) * xmap + (
727
- factunit * attribute[2, i]) * ymap
753
+ factunit * attribute[2, i]) * ymap
728
754
  pupil[indx + ix0[i], indy + iy0[i]] = minimap[indx, indy]
729
755
 
730
756
  return pupil
731
757
 
732
758
 
733
- # _ _ ___ ____ _ _ _ _______ _______ _
734
- # | | | |_ _/ ___| | | | | | | ____\ \ / / ____| |
735
- # | |_| || | | _| |_| |_____| | | _| \ \ / /| _| | |
736
- # | _ || | |_| | _ |_____| |___| |___ \ V / | |___| |___
737
- # |_| |_|___\____|_| |_| |_____|_____| \_/ |_____|_____|
738
-
759
+ # High-level functions (whatever that's supposed to mean here...)
739
760
 
740
761
  def getEeltSegmentNumber():
741
762
  """
742
- Just returns the number of segments of the EELT nominal pupil, in order
743
- to be able to generate either reflectivities, or phase errors, or else.
763
+ Return the number of segments of the ELT nominal pupil.
744
764
 
765
+ In order to be able to generate either reflectivities, or phase errors,
766
+ or else.
745
767
  """
746
768
  hx, hy = generateCoordSegments(40., 0.)
747
769
  n = hx.shape[-1]
748
770
  return n
749
771
 
750
772
 
751
- def generateEeltPupilMask(npt, dspider, i0, j0, pixscale, gap, rotdegree,
752
- D=40.0, centerMark=0):
773
+ def generateEeltPupilMask(
774
+ npt: int,
775
+ dspider: float,
776
+ i0: float,
777
+ j0: float,
778
+ pixscale: float,
779
+ gap: float,
780
+ rotdegree: float,
781
+ D: float = 40.0,
782
+ centerMark: int = 0,
783
+ ) -> np.ndarray:
753
784
  """
754
- Generates a boolean pupil mask of the binary EELT pupil
755
- on a map of size (npt, npt).
756
-
757
-
758
- :returns: pupil image (npt, npt), boolean
759
- :param int npt: size of the output array
760
- :param float dspider: width of spiders in meters
761
- :param float i0, j0: index of pixels where the pupil should be centred.
762
- Can be floating-point indexes.
763
- :param float pixscale: size of a pixel of the image, in meters.
764
- :param float gap: half-space between segments in meters
765
- :param float rotdegree: rotation angle of the pupil, in degrees.
766
- :param float D: diameter of the pupil. For the nominal EELT, D shall
767
- be set to 40.0
768
- :param int centerMark: when centerMark!=0, a pixel is added at the centre of
769
- symmetry of the pupil in order to debug things using compass.
770
- centerMark==1 draws a point
771
- centerMark==2 draws 2 lines
772
-
773
- :Example:
774
- npt = 752
775
- i0 = npt/2+0.5
776
- j0 = npt/2+0.5
777
- rotdegree = 90.0
778
- pixscale = 40./npt
779
- dspider = 0.53
780
- gap = 0.02
781
- pup = generateEeltPupilMask(npt, dspider, i0, j0, pixscale, gap, rotdegree)
785
+ Generate a boolean pupil mask of the binary ELT pupil.
786
+
787
+ On a map of size (npt, npt).
788
+
789
+ Parameters
790
+ ----------
791
+ npt : int
792
+ Size of the output array.
793
+ dspider : float
794
+ Width of spiders in meters.
795
+ i0, j0 : float
796
+ Indices of pixels where the pupil should be centred
797
+ Can be floating-point indicess.
798
+ pixscale : float
799
+ Size of a pixel of the image, in meters.
800
+ gap : float
801
+ Half-space between segments in meters.
802
+ rotdegree : float
803
+ Rotation angle of the pupil, in degrees.
804
+ D : float, optional
805
+ Diameter of the pupil in meter. The default is 40.0 (ELT).
806
+ centerMark : int, optional
807
+ when centerMark!=0, a pixel is added at the centre of
808
+ symmetry of the pupil in order to debug things using compass.
809
+ centerMark==1 draws a point
810
+ centerMark==2 draws 2 lines.
811
+ The default is 0.
812
+
813
+ Returns
814
+ -------
815
+ pup : np.ndarray
816
+ Pupil image (npt, npt), boolean.
817
+
818
+ Examples
819
+ --------
820
+ >>> npt = 752
821
+ >>> i0 = npt/2+0.5
822
+ >>> j0 = npt/2+0.5
823
+ >>> rotdegree = 90.0
824
+ >>> pixscale = 40./npt
825
+ >>> dspider = 0.53
826
+ >>> gap = 0.02
827
+ >>> pup = generateEeltPupilMask(
828
+ ... npt, dspider, i0, j0, pixscale, gap, rotdegree)
782
829
 
783
830
  """
784
831
  rot = rotdegree * np.pi / 180
@@ -790,10 +837,11 @@ def generateEeltPupilMask(npt, dspider, i0, j0, pixscale, gap, rotdegree,
790
837
 
791
838
  # From the data of hex mirrors, we build the pupil image using
792
839
  # boolean
793
- pup = generateSegmentProperties(True, hx, hy, i0, j0, pixscale, gap, npt, D)
840
+ pup = generateSegmentProperties(
841
+ True, hx, hy, i0, j0, pixscale, gap, npt, D)
794
842
 
795
- # SPIDERS ............................................
796
- nspider = 3 # for the day where we have more/less spiders ;-)
843
+ # SPIDERS
844
+ nspider = 3 # for the day where we have more/less spiders
797
845
  if (dspider > 0 and nspider > 0):
798
846
  pup = pup & fillSpider(npt, nspider, dspider, i0, j0, pixscale, rot)
799
847
 
@@ -808,7 +856,7 @@ def generateEeltPupilMask(npt, dspider, i0, j0, pixscale, gap, rotdegree,
808
856
  def generateEeltPupilReflectivity(refl, npt, dspider, i0, j0, pixscale, gap,
809
857
  rotdegree, D=40.0, softGap=False):
810
858
  """
811
- Generates a map of the reflectivity of the EELT pupil, on an array
859
+ Generates a map of the reflectivity of the ELT pupil, on an array
812
860
  of size (npt, npt).
813
861
 
814
862
  :returns: pupil image (npt, npt), with the same type of input argument refl
@@ -825,7 +873,7 @@ def generateEeltPupilReflectivity(refl, npt, dspider, i0, j0, pixscale, gap,
825
873
  :param float pixscale: size of a pixel of the image, in meters.
826
874
  :param float gap: half-space between segments in meters
827
875
  :param float rotdegree: rotation angle of the pupil, in degrees.
828
- :param float D: diameter of the pupil. For the nominal EELT, D shall
876
+ :param float D: diameter of the pupil. For the nominal ELT, D shall
829
877
  be set to 40.0
830
878
  :param bool softGap: if False, the gap between segments is binary 0/1
831
879
  depending if the pixel is within the gap or not. If True, the gap
@@ -833,20 +881,21 @@ def generateEeltPupilReflectivity(refl, npt, dspider, i0, j0, pixscale, gap,
833
881
  gap width.
834
882
 
835
883
 
836
- :Example:
837
-
838
- refl = np.ones(798)+np.random.randn(798)/20.
839
- dead = 3
840
- refl[(np.random.rand(dead)*797).astype(int)] = 0.
841
- npt = 1200
842
- i0 = npt/2+0.5
843
- j0 = npt/2+0.5
844
- rotdegree = 14.0
845
- pixscale = 44./npt
846
- dspider = 0.53
847
- gap = 0.02
848
- pup = generateEeltPupilReflectivity(refl, npt, dspider, i0, j0, pixscale,
849
- gap, rotdegree, softGap=True)
884
+ Examples
885
+ --------
886
+ >>> refl = np.ones(798)+np.random.randn(798)/20.
887
+ >>> dead = 3
888
+ >>> refl[(np.random.rand(dead)*797).astype(int)] = 0.
889
+ >>> npt = 1200
890
+ >>> i0 = npt/2+0.5
891
+ >>> j0 = npt/2+0.5
892
+ >>> rotdegree = 14.0
893
+ >>> pixscale = 44./npt
894
+ >>> dspider = 0.53
895
+ >>> gap = 0.02
896
+ >>> pup = generateEeltPupilReflectivity(
897
+ ... refl, npt, dspider, i0, j0,
898
+ ... pixscale, gap, rotdegree, softGap=True)
850
899
 
851
900
  """
852
901
  rot = rotdegree * np.pi / 180
@@ -858,8 +907,8 @@ def generateEeltPupilReflectivity(refl, npt, dspider, i0, j0, pixscale, gap,
858
907
 
859
908
  # From the data of hex mirrors, we build the pupil image according
860
909
  # to the properties defined by input argument <refl>
861
- pup = generateSegmentProperties(refl, hx, hy, i0, j0, pixscale, gap, npt, D,
862
- softGap=softGap)
910
+ pup = generateSegmentProperties(
911
+ refl, hx, hy, i0, j0, pixscale, gap, npt, D, softGap=softGap)
863
912
 
864
913
  # SPIDERS ............................................
865
914
  nspider = 3 # for the day where we have more/less spiders ;-)
@@ -872,7 +921,7 @@ def generateEeltPupilReflectivity(refl, npt, dspider, i0, j0, pixscale, gap,
872
921
  def generateEeltPupilPhase(phase, npt, dspider, i0, j0, pixscale, rotdegree,
873
922
  D=40.0):
874
923
  """
875
- Generates a map of the segments phase errors of the EELT pupil, on an array
924
+ Generates a map of the segments phase errors of the ELT pupil, on an array
876
925
  of size (npt, npt).
877
926
 
878
927
  :returns: phase image (npt, npt), with the same type of input argument phase
@@ -885,21 +934,21 @@ def generateEeltPupilPhase(phase, npt, dspider, i0, j0, pixscale, rotdegree,
885
934
  Can be floating-point indexes.
886
935
  :param float pixscale: size of a pixel of the image, in meters.
887
936
  :param float rotdegree: rotation angle of the pupil, in degrees.
888
- :param float D: diameter of the pupil. For the nominal EELT, D shall
937
+ :param float D: diameter of the pupil. For the nominal ELT, D shall
889
938
  be set to 40.0
890
939
 
891
- :Example:
892
-
893
- phase = np.random.randn(3,798)
894
- phase = np.zeros((3,798)); phase[1,:]=1.
895
- npt = 752
896
- i0 = npt/2+0.5
897
- j0 = npt/2+0.5
898
- rotdegree = 90.0
899
- pixscale = 41./npt
900
- dspider = 0.51
901
- pup = generateEeltPupilPhase(phase, npt, dspider, i0, j0, pixscale,
902
- rotdegree)
940
+ Examples
941
+ --------
942
+ >>> phase = np.random.randn(3,798)
943
+ >>> phase = np.zeros((3,798)); phase[1,:]=1.
944
+ >>> npt = 752
945
+ >>> i0 = npt/2+0.5
946
+ >>> j0 = npt/2+0.5
947
+ >>> rotdegree = 90.0
948
+ >>> pixscale = 41./npt
949
+ >>> dspider = 0.51
950
+ >>> pup = generateEeltPupilPhase(
951
+ ... phase, npt, dspider, i0, j0, pixscale, rotdegree)
903
952
 
904
953
  """
905
954
  rot = rotdegree * np.pi / 180
@@ -911,12 +960,14 @@ def generateEeltPupilPhase(phase, npt, dspider, i0, j0, pixscale, rotdegree,
911
960
 
912
961
  # From the data of hex mirrors, we build the pupil phase image according
913
962
  # to the properties defined by input argument <phase>
914
- pup = generateSegmentProperties(phase, hx, hy, i0, j0, pixscale, 0.0, npt,
915
- D)
963
+ pup = generateSegmentProperties(
964
+ phase, hx, hy, i0, j0, pixscale, 0.0, npt, D)
916
965
 
917
966
  return pup
918
967
 
919
968
 
969
+ # TODO: What's this? Module-level example? Test case? Anyway, figure out where
970
+ # it belongs an put it there!
920
971
  """
921
972
  refl = np.ones(798)+np.random.randn(798)/10.
922
973
  N = npt = 800
@@ -933,12 +984,12 @@ p = generateEeltPupilMask(N, dspider, i0, j0+10, scale, rotdegree)
933
984
  plt.clf()
934
985
  plt.matshow(p, fignum=1)
935
986
 
936
- #p = generateEeltPupilReflectivity(refl, N, dspider, i0, j0, pixscale,
987
+ #p = generateEeltPupilReflectivity(refl, N, dspider, i0, j0, pixscale,
937
988
  rotdegree, D=40.0)
938
989
 
939
990
  phase = np.zeros((3,798)); phase[1,:]=1.
940
991
  phase = np.random.randn(3,798)
941
- p = generateEeltPupilPhase(phase, N, dspider, i0, j0, pixscale, rotdegree,
992
+ p = generateEeltPupilPhase(phase, N, dspider, i0, j0, pixscale, rotdegree,
942
993
  D=40.0)
943
994
 
944
995
  plt.matshow(p, fignum=1)
@@ -0,0 +1 @@
1
+