<jupyter_start><jupyter_text>Testing the aperture generation for PASTIS For a first introduction to the PASTIS model, its motivation and basics, watch this SPIE talk if you have access:https://www.spiedigitallibrary.org/conference-proceedings-of-spie/10400/2274347/Sensitivity-analysis-for-high-contrast-missions-with-segmented-telescopes/10.1117/12.2274347.full?SSO=1Generating the correct aperture for the telescope you want to apply PASTIS on and finding the non-redundant pairs of the aperture is the first step for the application of the PASTIS contrast estimation. This notebook provides a succession of steps to check whether that worked correctly and ckecks the script "**aperture_definition.py**" in the PASTIS repo.<jupyter_code>import os
import numpy as np
from astropy.io import fits
import matplotlib.pyplot as plt

# Path to all the outputs from "aperture_definition.py".
dir = '/Users/ilaginja/Documents/data_from_repos/pastis_data/segmentation'
# Change into that directory
os.chdir(dir)

n_seg = 18<jupyter_output><empty_output><jupyter_text>Open up the file "JWST_aperture.pdf" when it gets created, so that we can do cross-checks. For The first testing output is "seg_position.txt", which gives you all the x- and y-coordinates of all segments with respect to the center of the aperture. Run the cell below and see whether this matches the aperture (please open the PDF file manually, I didn't have the time to figure out how to include PDF images in a Jupyter notebook.) What you're looking at are the center coordinates of all segments.<jupyter_code>seg = np.loadtxt('seg_position.txt')
print('Segment x and y positions in meters:')
print(seg)<jupyter_output>Segment x and y positions in meters:
[[ 0.   -1.33]
 [ 1.15 -0.67]
 [ 1.15  0.66]
 [ 0.    1.33]
 [-1.15  0.67]
 [-1.15 -0.66]
 [ 0.   -2.66]
 [ 1.15 -2.  ]
 [ 2.3  -1.33]
 [ 2.3  -0.  ]
 [ 2.3   1.33]
 [ 1.15  2.  ]
 [ 0.    2.66]
 [-1.15  2.  ]
 [-2.3   1.33]
 [-2.3   0.  ]
 [-2.3  -1.33]
 [-1.15 -1.99]]<jupyter_text>Next are the distances between all segments instead of the individual positions. Load both the x- and the y-coordinate distances and display them.I just realized that if I do that, I can't get the image values by hovering over them. We need that though, so go for it in an ipython session or something. Then do the same as above, figure out by comparison with the aperture whether the values make sense. One of the things you can check is whether the diagonals are zero, because the distance from a segment to itself will always be zero.The "extent" keyword fixes the segment numbering in the images, which is now the same like in the numbered pupil.<jupyter_code>vx = np.loadtxt('vec_list_x.txt')
vy = np.loadtxt('vec_list_y.txt')

plt.figure(figsize=(15,5))
plt.subplot(1, 2, 1)
plt.imshow(vx, origin='lower', extent=[1, n_seg+1, 1, n_seg+1], interpolation=None)
plt.title('x distances')

plt.subplot(1, 2, 2)
plt.imshow(vy, origin='lower', extent=[1, n_seg+1, 1, n_seg+1], interpolation=None)
plt.title('y distances')

plt.show()<jupyter_output><empty_output><jupyter_text>Helping checklist for left plot showing **x-distances** between two segments:- diagonal is zero- there's an area of 3x3 pixels in the center of the array that has all zero values. those correspond to the segments 9, 10 and 11 with each other. These entries are zero because those three segments are aligned on the x-axis, hence the x-distance between them is zero.- there's a very bright area of 3x3 pixels (yellow) towards the right of the image. They correspond to the segment pairs between (9, 10, 11) with (15, 16, 17). Those should be the larges values in the array because the largest x-distance in the pupil will be from the far left to the far right edge of the pupil.- you can go through more pairs individually and cross-checkHelping checklist for right plot showing **y-distances** between two segments:- diagonal is zero- start at the bottom left: seg 1 with 1 will be zero- move one to the right: seg 2 is slightly higher than seg 1 in the exit pupil, so the (absolute) value of the distance between the two segments gets bigger.- move one more to the right: seg 3 is even lower than seg 1 in the pupil, hence this value will be even lower than the previous one- move one more to the right: seg 4 is even lower than seg 3- move one more to the right: seg 5 has the same y-dsitance from seg 1 like seg 3- ... and so on Next thing is "vec_flat.txt". Load and print, I don't think there's much to check here actually.<jupyter_code>flat = np.loadtxt('vec_flat.txt')
print(flat)<jupyter_output>[[  0.00000000e+00   0.00000000e+00]
 [ -1.15181379e+00  -6.65000000e-01]
 [ -1.15181379e+00  -1.99500000e+00]
 [ -1.62878024e-16  -2.66000000e+00]
 [  1.15181379e+00  -1.99500000e+00]
 [  1.15181379e+00  -6.65000000e-01]
 [  0.00000000e+00   1.33000000e+00]
 [ -1.15181379e+00   6.65000000e-01]
 [ -2.30362757e+00   2.22044605e-16]
 [ -2.30362757e+00  -1.33000000e+00]
 [ -2.30362757e+00  -2.66000000e+00]
 [ -1.15181379e+00  -3.32500000e+00]
 [ -3.25756049e-16  -3.99000000e+00]
 [  1.15181379e+00  -3.32500000e+00]
 [  2.30362757e+00  -2.66000000e+00]
 [  2.30362757e+00  -1.33000000e+00]
 [  2.30362757e+00  -1.99840144e-15]
 [  1.15181379e+00   6.65000000e-01]
 [  1.15181379e+00   6.65000000e-01]
 [  0.00000000e+00   0.00000000e+00]
 [ -2.22044605e-16  -1.33000000e+00]
 [  1.15181379e+00  -1.99500000e+00]
 [  2.30362757e+00  -1.33000000e+00]
 [  2.30362757e+00  -1.11022302e-15]
 [  1.15181379e+00   1.99500000e+00]
 [  0.00000000e+00   1.33000000e+00]
 [ -1.15181379e+00   6.65000000e-01]
 [...]<jupyter_text>The nulled vector list "vec_nulled" is next, and that's kind of an important one.<jupyter_code>nullx = np.loadtxt('vec_list_nulled_x.txt')
nully = np.loadtxt('vec_list_nulled_y.txt')<jupyter_output><empty_output><jupyter_text>Since we're working separately in x and in y, if we add these two arrays up, we will only be left with zeros where we really nulled everything - both the x- and the y-axis. If you then display that, you can basically count the non-redundant pairs (NRP) by hand (except that our eyes fool us 90% of the time and we should *actually count* them in the code).**Again: Remember that our segment numbering actually starts at 1!**<jupyter_code>tot = nullx + nully
plt.figure(figsize=(20, 10))
plt.imshow(tot, origin='lower', extent=[1, n_seg+1, 1, n_seg+1])
plt.show()<jupyter_output><empty_output><jupyter_text>Next is "NR_distance_list", which holds the unique distances of each NRP. Note that distances itself can repeat, since the NRP also have to differ in vector orientation in order to be non-redundant.<jupyter_code>nrp_dist = np.loadtxt('NR_distance_list.txt')
print(nrp_dist)
print('Number of NRP:', nrp_dist.shape[0])<jupyter_output>[  1.77   5.31   7.08   5.31   1.77   1.77   5.31   7.08  12.38  12.38
  15.92  12.38  12.38   7.08  15.92  12.38  12.38  15.92  21.23  23.    28.3
  23.    21.23  23.    28.3   23.    21.23  23.    28.3   23.  ]
Number of NRP: 30<jupyter_text>Next is our list of NRPs themselves, which has the form [NRP number, seg1, seg2]. Note that the **numbering of the NRP in principle starts at 1!** But we don't have any actual labels for the NRPs, so when we index this array, the numbering starts at 0 because that's how Python works. **The segment numbering starts at 1 too!!!** Except for the cases where we index them... you get my point.<jupyter_code>nrp_list = np.loadtxt('NR_pairs_list.txt', dtype='int')
print(nrp_list)<jupyter_output>[[ 1  2]
 [ 1  3]
 [ 1  4]
 [ 1  5]
 [ 1  6]
 [ 1  7]
 [ 1  9]
 [ 1 10]
 [ 1 11]
 [ 1 12]
 [ 1 13]
 [ 1 14]
 [ 1 15]
 [ 1 16]
 [ 2 15]
 [ 2 16]
 [ 2 17]
 [ 3 17]
 [ 7 11]
 [ 7 12]
 [ 7 13]
 [ 7 14]
 [ 7 15]
 [ 8 15]
 [ 9 15]
 [ 9 16]
 [ 9 17]
 [10 17]
 [11 17]
 [11 18]]<jupyter_text>Next we have "vec_list2_x" and "vec_list2_y" which are actually useless, as explained in the script we're following here. So I'll skip these.The final and most important one is the projection matrix. It holds the infromation about which NRP each segment pair corresponds to and has the shape: [nb_seg, nb_seg, 3].First plane: Projection_Matrix[i,j,0] = n means that the segment pair formed by the segments i and j is equivalent to the pair n of the non-redundant-pair basis (n = 1, 2, ...). Second and third planes: Projection_Matrix[i,j,1] = m and Projection_Matrix[i,j,2] = n means that the segment pair formed by the segments i and j is equivalent to the non-redundant pair formed by the segments m and n. Only the FIRST plane is useful for later (Projection_Matrix[:, :, 0]).<jupyter_code># Load the projection matrix
m = fits.getdata('Projection_Matrix.fits')

plt.figure(figsize=(20,5))
plt.subplot(1, 3, 1)
plt.imshow(m[:,:,0], origin='lower', extent=[1, n_seg+1, 1, n_seg+1])
plt.title('NRP number')
plt.subplot(1, 3, 2)
plt.imshow(m[:,:,1], origin='lower', extent=[1, n_seg+1, 1, n_seg+1])
plt.title('segment 1')
plt.subplot(1, 3, 3)
plt.imshow(m[:,:,2], origin='lower', extent=[1, n_seg+1, 1, n_seg+1])
plt.title('segment 2')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11282843894899536, 'fraction_numerical': 0.10984764848752485, 'mean_word_length': 3.9584017515051997, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '279421', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 3871, 'n_tokens_neox': 3225, 'n_words': 1178, 'path': 'Jupyter Notebooks/.ipynb_checkpoints/1_Testing the aperture generation-checkpoint.ipynb', 'repo_name': 'ivalaginja/PASTIS', 'size': '9058'}