|
5 | 5 |
|
6 | 6 | class NRMDefinition(): |
7 | 7 |
|
8 | | - def __init__(self, nrm_model, maskname='jwst_ami', chooseholes=None): |
9 | | - """ |
10 | | - Set attributes of NRMDefinition class. |
11 | | -
|
12 | | - Get hole centers and other mask geometry details from NRMModel, apply rotations/flips |
13 | | - as necessary and set them as attributes. |
14 | | -
|
15 | | - Parameters |
16 | | - ---------- |
17 | | - nrm_model: NRMModel |
18 | | - datamodel containing NRM reference file data |
19 | | - maskname: string |
20 | | - Identifier for mask geometry; default 'jwst_ami', optional |
21 | | - chooseholes: list |
22 | | - None, or e.g. ['B2', 'B4', 'B5', 'B6'] for a four-hole mask, optional |
23 | | - If None, use real seven-hole mask |
24 | | - """ |
25 | | - |
26 | | - if maskname not in ['jwst_ami','jwst_g7s6c']: |
27 | | - raise ValueError("Mask name not supported") |
28 | | - |
29 | | - self.maskname = maskname # there's only one mask but this is used in oifits |
30 | | - self.hdia = nrm_model.flat_to_flat |
31 | | - self.activeD = nrm_model.diameter |
32 | | - self.OD = nrm_model.pupil_circumscribed |
33 | | - self.ctrs = [] |
34 | | - |
35 | | - self.read_nrm_model(nrm_model, chooseholes=chooseholes) |
36 | | - |
37 | | - def read_nrm_model(self, nrm_model, chooseholes=None): |
38 | | - """ |
39 | | - Calculate hole centers with appropriate rotation. |
40 | | -
|
41 | | - Parameters |
42 | | - ---------- |
43 | | - nrm_model: NRMModel |
44 | | - datamodel containing NRM reference file data |
45 | | - chooseholes: list |
46 | | - None, or e.g. ['B2', 'B4', 'B5', 'B6'] for a four-hole mask |
47 | | -
|
48 | | - Returns |
49 | | - ------- |
50 | | - f2f: float |
51 | | - flat-to-flat distance of mask holes |
52 | | - ctrs_asbuilt: array |
53 | | - Actual hole centers [meters] |
54 | | - """ |
55 | | - |
56 | | - ctrs_asdesigned = np.array([[nrm_model.x_a1, nrm_model.y_a1], # B4 -> B4 |
57 | | - [nrm_model.x_a2, nrm_model.y_a2], # C5 -> C2 |
58 | | - [nrm_model.x_a3, nrm_model.y_a3], # B3 -> B5 |
59 | | - [nrm_model.x_a4, nrm_model.y_a4], # B6 -> B2 |
60 | | - [nrm_model.x_a5, nrm_model.y_a5], # C6 -> C1 |
61 | | - [nrm_model.x_a6, nrm_model.y_a6], # B2 -> B6 |
62 | | - [nrm_model.x_a7, nrm_model.y_a7]]) # C1 -> C6 |
63 | | - |
64 | | - |
65 | | - |
66 | | - holedict = {} # as_built names, C2 open, C5 closed, but as designed coordinates |
67 | | - # Assemble holes by actual open segment names (as_built). Either the full mask or the |
68 | | - # subset-of-holes mask will be V2-reversed after the as_designed centers are defined |
69 | | - # Debug orientations with b4,c6,[c2] |
70 | | - allholes = ('b4', 'c2', 'b5', 'b2', 'c1', 'b6', 'c6') |
71 | | - |
72 | | - for hole, coords in zip(allholes,ctrs_asdesigned): |
73 | | - holedict[hole] = coords |
74 | | - |
75 | | - if chooseholes: # holes B4 B5 C6 asbuilt for orientation testing |
76 | | - holelist = [] |
77 | | - for h in allholes: |
78 | | - if h in chooseholes: |
79 | | - holelist.append(holedict[h]) |
80 | | - ctrs_asdesigned = np.array(holelist) |
81 | | - |
82 | | - ctrs_asbuilt = ctrs_asdesigned.copy() |
83 | | - |
84 | | - # create 'live' hole centers in an ideal, orthogonal undistorted xy pupil space, |
85 | | - # eg maps open hole C5 in as_designed to C2 as_built, eg C4 unaffected.... |
86 | | - ctrs_asbuilt[:, 0] *= -1 |
87 | | - |
88 | | - # LG++ rotate hole centers by 90 deg to match MAST o/p DMS PSF with |
89 | | - # no affine2d transformations 8/2018 AS |
90 | | - # LG++ The above aligns the hole pattern with the hex analytic FT, |
91 | | - # flat top & bottom as seen in DMS data. 8/2018 AS |
92 | | - ctrs_asbuilt = rotate2dccw(ctrs_asbuilt, np.pi / 2.0) # overwrites attributes |
93 | | - |
94 | | - # create 'live' hole centers in an ideal, orthogonal undistorted xy pupil space, |
95 | | - self.ctrs = ctrs_asbuilt |
96 | | - |
97 | | - def showmask(self): |
98 | | - """ |
99 | | - Calculate the diameter of the smallest centered circle (D) |
100 | | - enclosing the live mask area |
101 | | -
|
102 | | - Returns |
103 | | - ------- |
104 | | - Diameter of the smallest centered circle |
105 | | -
|
106 | | - """ |
107 | | - radii = [] |
108 | | - for ctr in self.ctrs: |
109 | | - radii.append(math.sqrt(ctr[0] * ctr[0] + ctr[1] * ctr[1])) |
110 | | - |
111 | | - return 2.0 * (max(radii) + 0.5 * self.hdia) |
| 8 | + def __init__(self, nrm_model, maskname='jwst_ami', chooseholes=None): |
| 9 | + """ |
| 10 | + Set attributes of NRMDefinition class. |
| 11 | +
|
| 12 | + Get hole centers and other mask geometry details from NRMModel, apply rotations/flips |
| 13 | + as necessary and set them as attributes. |
| 14 | +
|
| 15 | + Parameters |
| 16 | + ---------- |
| 17 | + nrm_model: NRMModel |
| 18 | + datamodel containing NRM reference file data |
| 19 | + maskname: string |
| 20 | + Identifier for mask geometry; default 'jwst_ami', optional |
| 21 | + chooseholes: list |
| 22 | + None, or e.g. ['B2', 'B4', 'B5', 'B6'] for a four-hole mask, optional |
| 23 | + If None, use real seven-hole mask |
| 24 | + """ |
| 25 | + |
| 26 | + if maskname not in ['jwst_ami','jwst_g7s6c']: |
| 27 | + raise ValueError("Mask name not supported") |
| 28 | + |
| 29 | + self.maskname = maskname # there's only one mask but this is used in oifits |
| 30 | + self.hdia = nrm_model.flat_to_flat |
| 31 | + self.activeD = nrm_model.diameter |
| 32 | + self.OD = nrm_model.pupil_circumscribed |
| 33 | + self.ctrs = [] |
| 34 | + |
| 35 | + self.read_nrm_model(nrm_model, chooseholes=chooseholes) |
| 36 | + |
| 37 | + def read_nrm_model(self, nrm_model, chooseholes=None): |
| 38 | + """ |
| 39 | + Calculate hole centers with appropriate rotation. |
| 40 | +
|
| 41 | + Parameters |
| 42 | + ---------- |
| 43 | + nrm_model: NRMModel |
| 44 | + datamodel containing NRM reference file data |
| 45 | + chooseholes: list |
| 46 | + None, or e.g. ['B2', 'B4', 'B5', 'B6'] for a four-hole mask |
| 47 | +
|
| 48 | + Returns |
| 49 | + ------- |
| 50 | + f2f: float |
| 51 | + flat-to-flat distance of mask holes |
| 52 | + ctrs_asbuilt: array |
| 53 | + Actual hole centers [meters] |
| 54 | + """ |
| 55 | + |
| 56 | + ctrs_asdesigned = np.array([[nrm_model.x_a1, nrm_model.y_a1], # B4 -> B4 |
| 57 | + [nrm_model.x_a2, nrm_model.y_a2], # C5 -> C2 |
| 58 | + [nrm_model.x_a3, nrm_model.y_a3], # B3 -> B5 |
| 59 | + [nrm_model.x_a4, nrm_model.y_a4], # B6 -> B2 |
| 60 | + [nrm_model.x_a5, nrm_model.y_a5], # C6 -> C1 |
| 61 | + [nrm_model.x_a6, nrm_model.y_a6], # B2 -> B6 |
| 62 | + [nrm_model.x_a7, nrm_model.y_a7]]) # C1 -> C6 |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | + holedict = {} # as_built names, C2 open, C5 closed, but as designed coordinates |
| 67 | + # Assemble holes by actual open segment names (as_built). Either the full mask or the |
| 68 | + # subset-of-holes mask will be V2-reversed after the as_designed centers are defined |
| 69 | + # Debug orientations with b4,c6,[c2] |
| 70 | + allholes = ('b4', 'c2', 'b5', 'b2', 'c1', 'b6', 'c6') |
| 71 | + |
| 72 | + for hole, coords in zip(allholes,ctrs_asdesigned): |
| 73 | + holedict[hole] = coords |
| 74 | + |
| 75 | + if chooseholes: # holes B4 B5 C6 asbuilt for orientation testing |
| 76 | + holelist = [] |
| 77 | + for h in allholes: |
| 78 | + if h in chooseholes: |
| 79 | + holelist.append(holedict[h]) |
| 80 | + ctrs_asdesigned = np.array(holelist) |
| 81 | + |
| 82 | + ctrs_asbuilt = ctrs_asdesigned.copy() |
| 83 | + |
| 84 | + # create 'live' hole centers in an ideal, orthogonal undistorted xy pupil space, |
| 85 | + # eg maps open hole C5 in as_designed to C2 as_built, eg C4 unaffected.... |
| 86 | + ctrs_asbuilt[:, 0] *= -1 |
| 87 | + |
| 88 | + # LG++ rotate hole centers by 90 deg to match MAST o/p DMS PSF with |
| 89 | + # no affine2d transformations 8/2018 AS |
| 90 | + # LG++ The above aligns the hole pattern with the hex analytic FT, |
| 91 | + # flat top & bottom as seen in DMS data. 8/2018 AS |
| 92 | + ctrs_asbuilt = rotate2dccw(ctrs_asbuilt, np.pi / 2.0) # overwrites attributes |
| 93 | + |
| 94 | + # create 'live' hole centers in an ideal, orthogonal undistorted xy pupil space, |
| 95 | + self.ctrs = ctrs_asbuilt |
| 96 | + |
| 97 | + def showmask(self): |
| 98 | + """ |
| 99 | + Calculate the diameter of the smallest centered circle (D) |
| 100 | + enclosing the live mask area |
| 101 | +
|
| 102 | + Returns |
| 103 | + ------- |
| 104 | + Diameter of the smallest centered circle |
| 105 | +
|
| 106 | + """ |
| 107 | + radii = [] |
| 108 | + for ctr in self.ctrs: |
| 109 | + radii.append(math.sqrt(ctr[0] * ctr[0] + ctr[1] * ctr[1])) |
| 110 | + |
| 111 | + return 2.0 * (max(radii) + 0.5 * self.hdia) |
112 | 112 |
|
0 commit comments