pyreduce-astro 0.6.0b1__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.
Files changed (151) hide show
  1. pyreduce/__init__.py +58 -0
  2. pyreduce/__main__.py +106 -0
  3. pyreduce/clib/__init__.py +0 -0
  4. pyreduce/clib/_slitfunc_2d.cpython-313-darwin.so +0 -0
  5. pyreduce/clib/_slitfunc_bd.cpython-313-darwin.so +0 -0
  6. pyreduce/clib/build_extract.py +75 -0
  7. pyreduce/clib/slit_func_2d_xi_zeta_bd.c +1313 -0
  8. pyreduce/clib/slit_func_2d_xi_zeta_bd.h +55 -0
  9. pyreduce/clib/slit_func_bd.c +362 -0
  10. pyreduce/clib/slit_func_bd.h +17 -0
  11. pyreduce/clipnflip.py +147 -0
  12. pyreduce/combine_frames.py +855 -0
  13. pyreduce/configuration.py +186 -0
  14. pyreduce/continuum_normalization.py +329 -0
  15. pyreduce/cwrappers.py +404 -0
  16. pyreduce/datasets.py +231 -0
  17. pyreduce/echelle.py +413 -0
  18. pyreduce/estimate_background_scatter.py +129 -0
  19. pyreduce/extract.py +1359 -0
  20. pyreduce/extraction_width.py +77 -0
  21. pyreduce/instruments/__init__.py +0 -0
  22. pyreduce/instruments/andes.json +59 -0
  23. pyreduce/instruments/andes.py +100 -0
  24. pyreduce/instruments/common.json +46 -0
  25. pyreduce/instruments/common.py +675 -0
  26. pyreduce/instruments/crires_plus.json +63 -0
  27. pyreduce/instruments/crires_plus.py +103 -0
  28. pyreduce/instruments/filters.py +195 -0
  29. pyreduce/instruments/harpn.json +136 -0
  30. pyreduce/instruments/harpn.py +201 -0
  31. pyreduce/instruments/harps.json +155 -0
  32. pyreduce/instruments/harps.py +310 -0
  33. pyreduce/instruments/instrument_info.py +140 -0
  34. pyreduce/instruments/instrument_schema.json +221 -0
  35. pyreduce/instruments/jwst_miri.json +53 -0
  36. pyreduce/instruments/jwst_miri.py +29 -0
  37. pyreduce/instruments/jwst_niriss.json +52 -0
  38. pyreduce/instruments/jwst_niriss.py +98 -0
  39. pyreduce/instruments/lick_apf.json +53 -0
  40. pyreduce/instruments/lick_apf.py +35 -0
  41. pyreduce/instruments/mcdonald.json +59 -0
  42. pyreduce/instruments/mcdonald.py +123 -0
  43. pyreduce/instruments/metis_ifu.json +63 -0
  44. pyreduce/instruments/metis_ifu.py +45 -0
  45. pyreduce/instruments/metis_lss.json +65 -0
  46. pyreduce/instruments/metis_lss.py +45 -0
  47. pyreduce/instruments/micado.json +53 -0
  48. pyreduce/instruments/micado.py +45 -0
  49. pyreduce/instruments/neid.json +51 -0
  50. pyreduce/instruments/neid.py +154 -0
  51. pyreduce/instruments/nirspec.json +56 -0
  52. pyreduce/instruments/nirspec.py +215 -0
  53. pyreduce/instruments/nte.json +47 -0
  54. pyreduce/instruments/nte.py +42 -0
  55. pyreduce/instruments/uves.json +59 -0
  56. pyreduce/instruments/uves.py +46 -0
  57. pyreduce/instruments/xshooter.json +66 -0
  58. pyreduce/instruments/xshooter.py +39 -0
  59. pyreduce/make_shear.py +606 -0
  60. pyreduce/masks/mask_crires_plus_det1.fits.gz +0 -0
  61. pyreduce/masks/mask_crires_plus_det2.fits.gz +0 -0
  62. pyreduce/masks/mask_crires_plus_det3.fits.gz +0 -0
  63. pyreduce/masks/mask_ctio_chiron.fits.gz +0 -0
  64. pyreduce/masks/mask_elodie.fits.gz +0 -0
  65. pyreduce/masks/mask_feros3.fits.gz +0 -0
  66. pyreduce/masks/mask_flames_giraffe.fits.gz +0 -0
  67. pyreduce/masks/mask_harps_blue.fits.gz +0 -0
  68. pyreduce/masks/mask_harps_red.fits.gz +0 -0
  69. pyreduce/masks/mask_hds_blue.fits.gz +0 -0
  70. pyreduce/masks/mask_hds_red.fits.gz +0 -0
  71. pyreduce/masks/mask_het_hrs_2x5.fits.gz +0 -0
  72. pyreduce/masks/mask_jwst_miri_lrs_slitless.fits.gz +0 -0
  73. pyreduce/masks/mask_jwst_niriss_gr700xd.fits.gz +0 -0
  74. pyreduce/masks/mask_lick_apf_.fits.gz +0 -0
  75. pyreduce/masks/mask_mcdonald.fits.gz +0 -0
  76. pyreduce/masks/mask_nes.fits.gz +0 -0
  77. pyreduce/masks/mask_nirspec_nirspec.fits.gz +0 -0
  78. pyreduce/masks/mask_sarg.fits.gz +0 -0
  79. pyreduce/masks/mask_sarg_2x2a.fits.gz +0 -0
  80. pyreduce/masks/mask_sarg_2x2b.fits.gz +0 -0
  81. pyreduce/masks/mask_subaru_hds_red.fits.gz +0 -0
  82. pyreduce/masks/mask_uves_blue.fits.gz +0 -0
  83. pyreduce/masks/mask_uves_blue_binned_2_2.fits.gz +0 -0
  84. pyreduce/masks/mask_uves_middle.fits.gz +0 -0
  85. pyreduce/masks/mask_uves_middle_2x2_split.fits.gz +0 -0
  86. pyreduce/masks/mask_uves_middle_binned_2_2.fits.gz +0 -0
  87. pyreduce/masks/mask_uves_red.fits.gz +0 -0
  88. pyreduce/masks/mask_uves_red_2x2.fits.gz +0 -0
  89. pyreduce/masks/mask_uves_red_2x2_split.fits.gz +0 -0
  90. pyreduce/masks/mask_uves_red_binned_2_2.fits.gz +0 -0
  91. pyreduce/masks/mask_xshooter_nir.fits.gz +0 -0
  92. pyreduce/rectify.py +138 -0
  93. pyreduce/reduce.py +2205 -0
  94. pyreduce/settings/settings_CRIRES_PLUS.json +89 -0
  95. pyreduce/settings/settings_HARPN.json +73 -0
  96. pyreduce/settings/settings_HARPS.json +69 -0
  97. pyreduce/settings/settings_JWST_MIRI.json +55 -0
  98. pyreduce/settings/settings_JWST_NIRISS.json +55 -0
  99. pyreduce/settings/settings_LICK_APF.json +62 -0
  100. pyreduce/settings/settings_MCDONALD.json +58 -0
  101. pyreduce/settings/settings_METIS_IFU.json +77 -0
  102. pyreduce/settings/settings_METIS_LSS.json +77 -0
  103. pyreduce/settings/settings_MICADO.json +78 -0
  104. pyreduce/settings/settings_NEID.json +73 -0
  105. pyreduce/settings/settings_NIRSPEC.json +58 -0
  106. pyreduce/settings/settings_NTE.json +60 -0
  107. pyreduce/settings/settings_UVES.json +54 -0
  108. pyreduce/settings/settings_XSHOOTER.json +78 -0
  109. pyreduce/settings/settings_pyreduce.json +178 -0
  110. pyreduce/settings/settings_schema.json +827 -0
  111. pyreduce/tools/__init__.py +0 -0
  112. pyreduce/tools/combine.py +117 -0
  113. pyreduce/trace_orders.py +645 -0
  114. pyreduce/util.py +1288 -0
  115. pyreduce/wavecal/MICADO_HK_3arcsec_chip5.npz +0 -0
  116. pyreduce/wavecal/atlas/thar.fits +4946 -13
  117. pyreduce/wavecal/atlas/thar_list.txt +4172 -0
  118. pyreduce/wavecal/atlas/une.fits +0 -0
  119. pyreduce/wavecal/convert.py +38 -0
  120. pyreduce/wavecal/crires_plus_J1228_Open_det1.npz +0 -0
  121. pyreduce/wavecal/crires_plus_J1228_Open_det2.npz +0 -0
  122. pyreduce/wavecal/crires_plus_J1228_Open_det3.npz +0 -0
  123. pyreduce/wavecal/harpn_harpn_2D.npz +0 -0
  124. pyreduce/wavecal/harps_blue_2D.npz +0 -0
  125. pyreduce/wavecal/harps_blue_pol_2D.npz +0 -0
  126. pyreduce/wavecal/harps_red_2D.npz +0 -0
  127. pyreduce/wavecal/harps_red_pol_2D.npz +0 -0
  128. pyreduce/wavecal/mcdonald.npz +0 -0
  129. pyreduce/wavecal/metis_lss_l_2D.npz +0 -0
  130. pyreduce/wavecal/metis_lss_m_2D.npz +0 -0
  131. pyreduce/wavecal/nirspec_K2.npz +0 -0
  132. pyreduce/wavecal/uves_blue_360nm_2D.npz +0 -0
  133. pyreduce/wavecal/uves_blue_390nm_2D.npz +0 -0
  134. pyreduce/wavecal/uves_blue_437nm_2D.npz +0 -0
  135. pyreduce/wavecal/uves_middle_2x2_2D.npz +0 -0
  136. pyreduce/wavecal/uves_middle_565nm_2D.npz +0 -0
  137. pyreduce/wavecal/uves_middle_580nm_2D.npz +0 -0
  138. pyreduce/wavecal/uves_middle_600nm_2D.npz +0 -0
  139. pyreduce/wavecal/uves_middle_665nm_2D.npz +0 -0
  140. pyreduce/wavecal/uves_middle_860nm_2D.npz +0 -0
  141. pyreduce/wavecal/uves_red_580nm_2D.npz +0 -0
  142. pyreduce/wavecal/uves_red_600nm_2D.npz +0 -0
  143. pyreduce/wavecal/uves_red_665nm_2D.npz +0 -0
  144. pyreduce/wavecal/uves_red_760nm_2D.npz +0 -0
  145. pyreduce/wavecal/uves_red_860nm_2D.npz +0 -0
  146. pyreduce/wavecal/xshooter_nir.npz +0 -0
  147. pyreduce/wavelength_calibration.py +1873 -0
  148. pyreduce_astro-0.6.0b1.dist-info/METADATA +112 -0
  149. pyreduce_astro-0.6.0b1.dist-info/RECORD +151 -0
  150. pyreduce_astro-0.6.0b1.dist-info/WHEEL +4 -0
  151. pyreduce_astro-0.6.0b1.dist-info/licenses/LICENSE +674 -0
pyreduce/rectify.py ADDED
@@ -0,0 +1,138 @@
1
+ import numpy as np
2
+ from scipy.interpolate import interp1d
3
+ from tqdm import tqdm
4
+
5
+ from . import util
6
+ from .extract import correct_for_curvature, fix_parameters
7
+
8
+
9
+ def rectify_image(
10
+ img, orders, column_range, extraction_width, order_range, tilt=None, shear=None
11
+ ):
12
+ nord, _ = orders.shape
13
+ nrow, ncol = img.shape
14
+ x = np.arange(ncol)
15
+
16
+ extraction_width, column_range, orders = fix_parameters(
17
+ extraction_width, column_range, orders, nrow, ncol, nord
18
+ )
19
+
20
+ nord = order_range[1] - order_range[0]
21
+ orders = orders[order_range[0] : order_range[1]]
22
+ column_range = column_range[order_range[0] : order_range[1]]
23
+ extraction_width = extraction_width[order_range[0] : order_range[1]]
24
+
25
+ images = {}
26
+ for i in tqdm(range(nord), desc="Order"):
27
+ x_left_lim = column_range[i, 0]
28
+ x_right_lim = column_range[i, 1]
29
+
30
+ # Rectify the image, i.e. remove the shape of the order
31
+ # Then the center of the order is within one pixel variations
32
+ ycen = np.polyval(orders[i], x).astype(int)
33
+ yb, yt = ycen - extraction_width[i, 0], ycen + extraction_width[i, 1]
34
+ extraction_width[i, 0] + extraction_width[i, 1] + 1
35
+ index = util.make_index(yb, yt, x_left_lim, x_right_lim)
36
+ img_order = img[index]
37
+
38
+ # Correct for tilt and shear
39
+ # For each row of the rectified order, interpolate onto the shifted row
40
+ # Masked pixels are set to 0, similar to the summation
41
+ if tilt is not None and shear is not None:
42
+ img_order = correct_for_curvature(
43
+ img_order,
44
+ tilt[i, x_left_lim:x_right_lim],
45
+ shear[i, x_left_lim:x_right_lim],
46
+ extraction_width[i],
47
+ )
48
+ images[i] = img_order
49
+
50
+ return images, column_range, extraction_width
51
+
52
+
53
+ def merge_images(images, wave, column_range, extraction_width):
54
+ x_total = sum(img.shape[1] for img in images.values())
55
+ y_max = max(*[img.shape[0] for img in images.values()])
56
+ y_mid = y_max // 2
57
+
58
+ combined_img = np.zeros((y_max, x_total))
59
+ wavelength = np.zeros(x_total)
60
+
61
+ idx = 0
62
+ x_low = 0
63
+ for iord0, iord1 in zip(range(len(wave) - 1), range(1, len(wave)), strict=False):
64
+ img0 = images[iord0]
65
+ img1 = images[iord1]
66
+
67
+ xwd0, xwd1 = extraction_width[iord0], extraction_width[iord1]
68
+ y0_low = y_mid - xwd0[0]
69
+ y0_high = y_mid + xwd0[1] + 1
70
+
71
+ y1_low = y_mid - xwd1[0]
72
+ y1_high = y_mid + xwd1[1] + 1
73
+
74
+ # Calculate Overlap
75
+ cr0, cr1 = column_range[iord0], column_range[iord1]
76
+ w0 = wave[iord0][cr0[0] : cr0[1]]
77
+ w1 = wave[iord1][cr1[0] : cr1[1]]
78
+
79
+ i0 = np.ma.where((w0 >= np.ma.min(w1)) & (w0 <= np.ma.max(w1)))
80
+ i1 = np.ma.where((w1 >= np.ma.min(w0)) & (w1 <= np.ma.max(w0)))
81
+
82
+ if i0[0].size > 0 and i1[0].size > 0:
83
+ # The non overlapping part is just the image
84
+ x_high = i0[0].min()
85
+ combined_img[y0_low:y0_high, idx : idx + x_high - x_low] = img0[
86
+ :, x_low:x_high
87
+ ]
88
+ wavelength[idx : idx + x_high - x_low] = w0[x_low:x_high]
89
+
90
+ # for the overlap region use a common wavelength grid
91
+ n_points = (len(i0[0]) + len(i1[0])) // 2
92
+ w_common = np.geomspace(w0[i0][0], w1[i1][-1], num=n_points)
93
+
94
+ img0_common = interp1d(
95
+ w0[i0], img0[:, i0[0]], kind="linear", fill_value="extrapolate"
96
+ )(w_common)
97
+ img1_common = interp1d(
98
+ w1[i1], img1[:, i1[0]], kind="linear", fill_value="extrapolate"
99
+ )(w_common)
100
+
101
+ # And then simply take the average between the two
102
+ counter_common = np.zeros((y_max, n_points), dtype=int)
103
+ img_common = np.zeros((y_max, n_points))
104
+ img_common[y0_low:y0_high] += img0_common
105
+ counter_common[y0_low:y0_high] += 1
106
+ img_common[y1_low:y1_high] += img1_common
107
+ counter_common[y1_low:y1_high] += 1
108
+ counter_common[counter_common == 0] = 1
109
+ img_common /= counter_common
110
+
111
+ combined_img[:, idx + x_low : idx + x_low + n_points] = img_common
112
+ wavelength[idx + x_low : idx + x_low + n_points] = w_common
113
+
114
+ idx += x_low + n_points
115
+ x_low = i1[0].max()
116
+ else:
117
+ x_high = img0.shape[1]
118
+ combined_img[y0_low:y0_high, idx : idx + x_high] = img0
119
+ wavelength[idx : idx + x_high] = w0
120
+ idx += x_high
121
+ x_low = 0
122
+
123
+ img0 = images[len(wave) - 1]
124
+ y0 = img0.shape[0]
125
+ y0_low = (y_max - y0) // 2
126
+ y0_high = y0 + y0_low
127
+ cr0 = column_range[iord0]
128
+ w0 = wave[iord0][cr0[0] : cr0[1]]
129
+
130
+ x_high = img0.shape[1]
131
+ combined_img[y0_low:y0_high, idx : idx + x_high - x_low] = img0[:, x_low:x_high]
132
+ wavelength[idx : idx + x_high - x_low] = w0[x_low:x_high]
133
+
134
+ idx += x_high - x_low
135
+ combined_img = combined_img[:, :idx]
136
+ wavelength = wavelength[:idx]
137
+
138
+ return wavelength, combined_img