sotodlib 0.6.9.1__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 (256) hide show
  1. sotodlib/__init__.py +30 -0
  2. sotodlib/_version.py +21 -0
  3. sotodlib/coords/__init__.py +11 -0
  4. sotodlib/coords/demod.py +238 -0
  5. sotodlib/coords/det_match.py +1014 -0
  6. sotodlib/coords/fp_containers.py +836 -0
  7. sotodlib/coords/healpix_utils.py +152 -0
  8. sotodlib/coords/helpers.py +704 -0
  9. sotodlib/coords/local.py +501 -0
  10. sotodlib/coords/optics.py +712 -0
  11. sotodlib/coords/planets.py +849 -0
  12. sotodlib/coords/plotting.py +175 -0
  13. sotodlib/coords/pmat.py +745 -0
  14. sotodlib/coords/pointing_model.py +366 -0
  15. sotodlib/core/__init__.py +20 -0
  16. sotodlib/core/axisman.py +1065 -0
  17. sotodlib/core/axisman_io.py +377 -0
  18. sotodlib/core/axisman_util.py +48 -0
  19. sotodlib/core/context.py +610 -0
  20. sotodlib/core/flagman.py +376 -0
  21. sotodlib/core/g3_core.py +109 -0
  22. sotodlib/core/hardware.py +347 -0
  23. sotodlib/core/metadata/__init__.py +22 -0
  24. sotodlib/core/metadata/cli.py +212 -0
  25. sotodlib/core/metadata/common.py +78 -0
  26. sotodlib/core/metadata/detdb.py +593 -0
  27. sotodlib/core/metadata/loader.py +1166 -0
  28. sotodlib/core/metadata/manifest.py +960 -0
  29. sotodlib/core/metadata/obsdb.py +521 -0
  30. sotodlib/core/metadata/obsfiledb.py +911 -0
  31. sotodlib/core/metadata/resultset.py +363 -0
  32. sotodlib/core/resources.py +101 -0
  33. sotodlib/core/util.py +101 -0
  34. sotodlib/flag_utils.py +245 -0
  35. sotodlib/g3_condition.py +127 -0
  36. sotodlib/g3_filter.py +66 -0
  37. sotodlib/g3_sim.py +204 -0
  38. sotodlib/hwp/__init__.py +12 -0
  39. sotodlib/hwp/g3thwp.py +2044 -0
  40. sotodlib/hwp/hwp.py +697 -0
  41. sotodlib/hwp/hwp_angle_model.py +108 -0
  42. sotodlib/hwp/sim_hwp.py +182 -0
  43. sotodlib/io/__init__.py +7 -0
  44. sotodlib/io/bookbinder.py +1680 -0
  45. sotodlib/io/check_book.py +402 -0
  46. sotodlib/io/datapkg_completion.py +725 -0
  47. sotodlib/io/datapkg_utils.py +97 -0
  48. sotodlib/io/g3thk_db.py +624 -0
  49. sotodlib/io/g3thk_utils.py +138 -0
  50. sotodlib/io/g3tsmurf_db.py +565 -0
  51. sotodlib/io/g3tsmurf_utils.py +627 -0
  52. sotodlib/io/hk_utils.py +468 -0
  53. sotodlib/io/hkdb.py +738 -0
  54. sotodlib/io/imprinter.py +2158 -0
  55. sotodlib/io/imprinter_cli.py +372 -0
  56. sotodlib/io/imprinter_utils.py +361 -0
  57. sotodlib/io/load.py +605 -0
  58. sotodlib/io/load_book.py +1013 -0
  59. sotodlib/io/load_smurf.py +3179 -0
  60. sotodlib/io/load_toast_h5.py +207 -0
  61. sotodlib/io/metadata.py +304 -0
  62. sotodlib/io/so_ufm.py +265 -0
  63. sotodlib/mapmaking/__init__.py +8 -0
  64. sotodlib/mapmaking/bench.py +141 -0
  65. sotodlib/mapmaking/demod_mapmaker.py +746 -0
  66. sotodlib/mapmaking/log.py +91 -0
  67. sotodlib/mapmaking/ml_mapmaker.py +792 -0
  68. sotodlib/mapmaking/noise_model.py +398 -0
  69. sotodlib/mapmaking/obs_grouping.py +234 -0
  70. sotodlib/mapmaking/pointing_matrix.py +23 -0
  71. sotodlib/mapmaking/utils.py +800 -0
  72. sotodlib/obs_ops/__init__.py +3 -0
  73. sotodlib/obs_ops/sources.py +70 -0
  74. sotodlib/obs_ops/splits.py +177 -0
  75. sotodlib/obs_ops/utils.py +84 -0
  76. sotodlib/preprocess/__init__.py +3 -0
  77. sotodlib/preprocess/pcore.py +622 -0
  78. sotodlib/preprocess/preprocess_plot.py +597 -0
  79. sotodlib/preprocess/preprocess_util.py +1224 -0
  80. sotodlib/preprocess/processes.py +2550 -0
  81. sotodlib/qa/__init__.py +1 -0
  82. sotodlib/qa/metrics.py +600 -0
  83. sotodlib/qa/quality_reports/__init__.py +1 -0
  84. sotodlib/qa/quality_reports/plots.py +409 -0
  85. sotodlib/qa/quality_reports/report_data.py +538 -0
  86. sotodlib/scripts/__init__.py +8 -0
  87. sotodlib/scripts/hardware_info.py +31 -0
  88. sotodlib/scripts/hardware_plot.py +104 -0
  89. sotodlib/scripts/hardware_sim.py +53 -0
  90. sotodlib/scripts/hardware_trim.py +112 -0
  91. sotodlib/scripts/so_batch_control.py +230 -0
  92. sotodlib/sim_flags.py +185 -0
  93. sotodlib/sim_hardware.py +604 -0
  94. sotodlib/site_pipeline/__init__.py +2 -0
  95. sotodlib/site_pipeline/analyze_bright_ptsrc.py +1299 -0
  96. sotodlib/site_pipeline/calibration/__init__.py +0 -0
  97. sotodlib/site_pipeline/calibration/wiregrid.py +445 -0
  98. sotodlib/site_pipeline/check_book.py +194 -0
  99. sotodlib/site_pipeline/cleanup_level2.py +224 -0
  100. sotodlib/site_pipeline/cli.py +122 -0
  101. sotodlib/site_pipeline/finalize_focal_plane.py +1077 -0
  102. sotodlib/site_pipeline/generate_reports.py +213 -0
  103. sotodlib/site_pipeline/jobdb.py +552 -0
  104. sotodlib/site_pipeline/make_atomic_filterbin_map.py +509 -0
  105. sotodlib/site_pipeline/make_book.py +118 -0
  106. sotodlib/site_pipeline/make_cosamp_hk.py +289 -0
  107. sotodlib/site_pipeline/make_det_info_wafer.py +117 -0
  108. sotodlib/site_pipeline/make_hwp_solutions.py +363 -0
  109. sotodlib/site_pipeline/make_ml_map.py +327 -0
  110. sotodlib/site_pipeline/make_read_det_match.py +163 -0
  111. sotodlib/site_pipeline/make_source_flags.py +132 -0
  112. sotodlib/site_pipeline/make_uncal_beam_map.py +396 -0
  113. sotodlib/site_pipeline/monitor.py +235 -0
  114. sotodlib/site_pipeline/multilayer_preprocess_tod.py +421 -0
  115. sotodlib/site_pipeline/preprocess_obs.py +289 -0
  116. sotodlib/site_pipeline/preprocess_tod.py +437 -0
  117. sotodlib/site_pipeline/record_qa.py +133 -0
  118. sotodlib/site_pipeline/update_book_plan.py +248 -0
  119. sotodlib/site_pipeline/update_det_cal.py +900 -0
  120. sotodlib/site_pipeline/update_det_match.py +450 -0
  121. sotodlib/site_pipeline/update_g3thk_database.py +58 -0
  122. sotodlib/site_pipeline/update_g3tsmurf_db.py +154 -0
  123. sotodlib/site_pipeline/update_hkdb.py +115 -0
  124. sotodlib/site_pipeline/update_hwp_angle.py +139 -0
  125. sotodlib/site_pipeline/update_librarian.py +59 -0
  126. sotodlib/site_pipeline/update_obsdb.py +365 -0
  127. sotodlib/site_pipeline/update_preprocess_plots.py +241 -0
  128. sotodlib/site_pipeline/update_smurf_caldbs.py +557 -0
  129. sotodlib/site_pipeline/util.py +414 -0
  130. sotodlib/toast/__init__.py +35 -0
  131. sotodlib/toast/instrument.py +507 -0
  132. sotodlib/toast/io/__init__.py +16 -0
  133. sotodlib/toast/io/load_book.py +684 -0
  134. sotodlib/toast/io/save_book.py +711 -0
  135. sotodlib/toast/ops/__init__.py +26 -0
  136. sotodlib/toast/ops/act_sign.py +63 -0
  137. sotodlib/toast/ops/corotator.py +180 -0
  138. sotodlib/toast/ops/data/hwpss_per_chi.pck +0 -0
  139. sotodlib/toast/ops/data/planet_data.h5 +0 -0
  140. sotodlib/toast/ops/h_n.py +332 -0
  141. sotodlib/toast/ops/load_books.py +317 -0
  142. sotodlib/toast/ops/load_context.py +1439 -0
  143. sotodlib/toast/ops/load_context_utils.py +826 -0
  144. sotodlib/toast/ops/mlmapmaker.py +782 -0
  145. sotodlib/toast/ops/mumux_crosstalk_util.py +227 -0
  146. sotodlib/toast/ops/readout_filter.py +130 -0
  147. sotodlib/toast/ops/save_books.py +297 -0
  148. sotodlib/toast/ops/sim_catalog.py +488 -0
  149. sotodlib/toast/ops/sim_hwpss.py +372 -0
  150. sotodlib/toast/ops/sim_mumux_crosstalk.py +341 -0
  151. sotodlib/toast/ops/sim_readout.py +687 -0
  152. sotodlib/toast/ops/sim_source.py +1316 -0
  153. sotodlib/toast/ops/sim_sso.py +641 -0
  154. sotodlib/toast/ops/sim_stimulator.py +324 -0
  155. sotodlib/toast/ops/sim_wiregrid.py +279 -0
  156. sotodlib/toast/ops/splits.py +643 -0
  157. sotodlib/toast/ops/utils.py +68 -0
  158. sotodlib/toast/scripts/__init__.py +5 -0
  159. sotodlib/toast/scripts/get_wafer_offset.py +193 -0
  160. sotodlib/toast/scripts/make_hardware_maps.py +105 -0
  161. sotodlib/toast/scripts/mapmaker_test.py +339 -0
  162. sotodlib/toast/scripts/so_convert.py +153 -0
  163. sotodlib/toast/scripts/so_map.py +245 -0
  164. sotodlib/toast/scripts/so_sim.py +306 -0
  165. sotodlib/toast/scripts/so_transfer.py +412 -0
  166. sotodlib/toast/sim_focalplane.py +764 -0
  167. sotodlib/toast/workflows/__init__.py +142 -0
  168. sotodlib/toast/workflows/data.py +211 -0
  169. sotodlib/toast/workflows/job.py +200 -0
  170. sotodlib/toast/workflows/pointing.py +178 -0
  171. sotodlib/toast/workflows/proc_act.py +46 -0
  172. sotodlib/toast/workflows/proc_characterize.py +196 -0
  173. sotodlib/toast/workflows/proc_demodulation.py +136 -0
  174. sotodlib/toast/workflows/proc_filters.py +300 -0
  175. sotodlib/toast/workflows/proc_flagging.py +347 -0
  176. sotodlib/toast/workflows/proc_intervals.py +53 -0
  177. sotodlib/toast/workflows/proc_mapmaker.py +382 -0
  178. sotodlib/toast/workflows/proc_mapmaker_filterbin.py +84 -0
  179. sotodlib/toast/workflows/proc_mapmaker_madam.py +51 -0
  180. sotodlib/toast/workflows/proc_mapmaker_ml.py +54 -0
  181. sotodlib/toast/workflows/proc_noise_est.py +260 -0
  182. sotodlib/toast/workflows/scripting.py +125 -0
  183. sotodlib/toast/workflows/sim_atm.py +175 -0
  184. sotodlib/toast/workflows/sim_calibrator.py +82 -0
  185. sotodlib/toast/workflows/sim_detector_readout.py +199 -0
  186. sotodlib/toast/workflows/sim_gain_error.py +49 -0
  187. sotodlib/toast/workflows/sim_noise_model.py +83 -0
  188. sotodlib/toast/workflows/sim_observe.py +244 -0
  189. sotodlib/toast/workflows/sim_optical_pickup.py +88 -0
  190. sotodlib/toast/workflows/sim_sky.py +226 -0
  191. sotodlib/toast/workflows/sim_sources.py +127 -0
  192. sotodlib/tod_ops/__init__.py +14 -0
  193. sotodlib/tod_ops/apodize.py +115 -0
  194. sotodlib/tod_ops/azss.py +453 -0
  195. sotodlib/tod_ops/binning.py +116 -0
  196. sotodlib/tod_ops/demodulation.py +276 -0
  197. sotodlib/tod_ops/deproject.py +122 -0
  198. sotodlib/tod_ops/detrend.py +95 -0
  199. sotodlib/tod_ops/fft_ops.py +1190 -0
  200. sotodlib/tod_ops/filters.py +690 -0
  201. sotodlib/tod_ops/flags.py +1163 -0
  202. sotodlib/tod_ops/gapfill.py +463 -0
  203. sotodlib/tod_ops/jumps.py +800 -0
  204. sotodlib/tod_ops/pca.py +369 -0
  205. sotodlib/tod_ops/sub_polyf.py +208 -0
  206. sotodlib/tod_ops/t2pleakage.py +331 -0
  207. sotodlib/tod_ops/utils.py +73 -0
  208. sotodlib/utils/__init__.py +5 -0
  209. sotodlib/utils/procs_pool.py +142 -0
  210. sotodlib/vis_hardware.py +509 -0
  211. sotodlib-0.6.9.1.dist-info/METADATA +60 -0
  212. sotodlib-0.6.9.1.dist-info/RECORD +256 -0
  213. sotodlib-0.6.9.1.dist-info/WHEEL +5 -0
  214. sotodlib-0.6.9.1.dist-info/entry_points.txt +14 -0
  215. sotodlib-0.6.9.1.dist-info/licenses/LICENSE +21 -0
  216. sotodlib-0.6.9.1.dist-info/top_level.txt +2 -0
  217. tests/__init__.py +7 -0
  218. tests/_helpers.py +435 -0
  219. tests/test_azss.py +113 -0
  220. tests/test_bookbinder.py +100 -0
  221. tests/test_context.py +853 -0
  222. tests/test_coords.py +255 -0
  223. tests/test_core.py +721 -0
  224. tests/test_core_resources.py +36 -0
  225. tests/test_data.py +84 -0
  226. tests/test_demod_map.py +128 -0
  227. tests/test_demod_mapmaker.py +90 -0
  228. tests/test_detdb.py +112 -0
  229. tests/test_flags.py +63 -0
  230. tests/test_hardware.py +136 -0
  231. tests/test_hkdb.py +120 -0
  232. tests/test_hwp.py +108 -0
  233. tests/test_hwp_solution.py +71 -0
  234. tests/test_imprinter.py +153 -0
  235. tests/test_jobdb.py +126 -0
  236. tests/test_mapmaker_pointing.py +246 -0
  237. tests/test_metadata.py +280 -0
  238. tests/test_obsdb.py +105 -0
  239. tests/test_obsfiledb.py +162 -0
  240. tests/test_pmat.py +81 -0
  241. tests/test_pointing_model.py +149 -0
  242. tests/test_preprocess.py +110 -0
  243. tests/test_proddb.py +49 -0
  244. tests/test_psd.py +117 -0
  245. tests/test_sim_hwpss.py +198 -0
  246. tests/test_sim_mumux_crosstalk.py +119 -0
  247. tests/test_sim_readout.py +56 -0
  248. tests/test_sim_stimulator.py +47 -0
  249. tests/test_sim_wiregrid.py +66 -0
  250. tests/test_subpolyf.py +108 -0
  251. tests/test_t2pleakage.py +86 -0
  252. tests/test_toast_books.py +158 -0
  253. tests/test_toast_context.py +61 -0
  254. tests/test_toast_splits.py +129 -0
  255. tests/test_toast_workflow.py +68 -0
  256. tests/test_tod_ops.py +319 -0
sotodlib/__init__.py ADDED
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2018-2021 Simons Observatory.
2
+ # Full license can be found in the top level "LICENSE" file.
3
+
4
+ """Simons Observatory TOD Simulation and Processing.
5
+
6
+ This package contains tools for simulating and analyzing data from the
7
+ Simons Observatory. It uses multiple external dependencies (some optional).
8
+ See documentation of the various sub-modules for more details.
9
+
10
+ Contents:
11
+
12
+ * core: Container classes for data, metadata, etc.
13
+ * io: Code for reading / writing data.
14
+ * utils: General utility functions and data helper functions.
15
+ * scripts: Commandline entry points.
16
+ * Top level packages for actual data processing.
17
+
18
+ """
19
+
20
+ from . import _version
21
+ __version__ = _version.get_versions()['version']
22
+
23
+
24
+ import logging
25
+ logger = logging.getLogger(__name__)
26
+ _log_fmt = '%(levelname)s: %(name)s: %(message)s'
27
+ _ch = logging.StreamHandler()
28
+ _ch.setLevel(logging.INFO)
29
+ _ch.setFormatter(logging.Formatter(_log_fmt))
30
+ logger.addHandler(_ch)
sotodlib/_version.py ADDED
@@ -0,0 +1,21 @@
1
+
2
+ # This file was generated by 'versioneer.py' (0.29) from
3
+ # revision-control system data, or from the parent directory name of an
4
+ # unpacked source archive. Distribution tarballs contain a pre-generated copy
5
+ # of this file.
6
+
7
+ import json
8
+
9
+ version_json = '''
10
+ {
11
+ "date": "2025-08-20T17:31:40-0400",
12
+ "dirty": false,
13
+ "error": null,
14
+ "full-revisionid": "1de526e011503cc9e78ec85ac7b0e64209b7a30b",
15
+ "version": "0.6.9.1"
16
+ }
17
+ ''' # END VERSION_JSON
18
+
19
+
20
+ def get_versions():
21
+ return json.loads(version_json)
@@ -0,0 +1,11 @@
1
+ from .pmat import P
2
+ from .helpers import (
3
+ get_radec, get_horiz, get_footprint, get_wcs_kernel, get_supergeom,
4
+ Timer, DEG, ScalarLastQuat
5
+ )
6
+ from . import planets
7
+ from . import local
8
+ from .plotting import *
9
+ from . import demod
10
+ from . import pointing_model
11
+ from . import healpix_utils
@@ -0,0 +1,238 @@
1
+ import numpy as np
2
+ import so3g
3
+ from pixell import enmap
4
+
5
+ from .. import core, tod_ops, coords
6
+
7
+
8
+ def make_map(tod,
9
+ P=None, wcs_kernel=None,
10
+ res=0.1 * coords.DEG,
11
+ dsT=None, demodQ=None, demodU=None,
12
+ cuts=None,
13
+ det_weights=None, det_weights_demod=None,
14
+ center_on=None, flip_gamma=True):
15
+ """Generates maps of temperature and polarization from demodulated HWP
16
+ data. It is assumed that each detector contributes a T signal
17
+ (which has been low-pass filtered to avoid the modulated signal)
18
+ stored in dsT, as well as separate Q and U timestreams,
19
+ corresponding to the cosine-phase (demodQ = Q cos 4 chi) and
20
+ sine-phase (demodU = U sin 4 chi) response of the HWP.
21
+
22
+ The demodQ and demodU signals are assumed to have been computed
23
+ without regard for the polarization angle of the detector, nor the
24
+ on-sky parallactic angle. The impact of these is handled by the
25
+ projection routines in this function.
26
+
27
+ Parameters
28
+ ----------
29
+ tod : sotodlib.core.AxisManager
30
+ An AxisManager object
31
+ P : sotodlib.coords.pmat
32
+ Projection Matrix to be used for mapmaking. If None, it is
33
+ generated from `wcs_kernel` or `center_on`.
34
+ wcs_kernel : enlib.wcs.WCS or None, optional
35
+ The WCS object used to generate the output map.
36
+ If None, a new WCS object with a Cartesian projection and a resolution of `res` will be created.
37
+ center_on: None or str
38
+ Name of point source. If specified, Source-centered map with a tangent projection will be made.
39
+ If None, wcs_kernel will be used to generate a projection matrix.
40
+ size: float or None
41
+ If specified, trim source-centored map to a local square with `size`, in radian.
42
+ If None, not trimming will be applied. Only valid when `centor_on` is specified.
43
+ res : float, optional
44
+ The resolution of the output map, in radian.
45
+ dsT : array-like or None, optional
46
+ The input dsT timestream data. If None, the 'dsT' field of `tod` will be used.
47
+ demodQ : array-like or None, optional
48
+ The input demodulated Q timestream data. If None, the 'demodQ' field of `tod` will be used.
49
+ demodU : array-like or None, optional
50
+ The input demodulated U timestream data. If None, the 'demodU' field of `tod` will be used.
51
+ cuts : RangesMatrix or None, optional
52
+ A RangesMatrix that identifies samples that should be excluded from projection operations.
53
+ If None, no cuts will be applied.
54
+ det_weights : array-like or None, optional
55
+ The detector weights to use in the map-making for the dsT timestream.
56
+ det_weights_demod : array-like or None, optional
57
+ The detector weights to use in the map-making for the demodulated Q and U timestreams.
58
+ If both of `det_weights` and `det_weights_demod` are None, uniform detector weights will be used.
59
+ If only one of two are provided, the other weight is provided by `det_weights` = 2 * `det_weights_demod`.
60
+ flip_gamma : bool or None
61
+ Defaults to True. When constructing the pointing matrix,
62
+ reflect the nominal focal plane polarization angles about zero
63
+ (gamma -> -gamma). If you pass in your own P, make sure it
64
+ was constructed with hwp=True.
65
+
66
+ Returns
67
+ -------
68
+ A dictionary which contains:
69
+ 'map' : enmap.ndmap
70
+ map of temperature and polarization
71
+ 'weighted_map' : enmap.ndmap
72
+ The inverse variance weighted map of temperature and polarization
73
+ 'weight' : enmap.ndmap
74
+ The map of inverse variance weights used in the map-making process.
75
+
76
+ """
77
+ if dsT is None:
78
+ dsT = tod['dsT']
79
+ if demodQ is None:
80
+ demodQ = tod['demodQ']
81
+ if demodU is None:
82
+ demodU = tod['demodU']
83
+
84
+ if flip_gamma is None:
85
+ flip_gamma = True
86
+
87
+ if P is None:
88
+ if center_on is None:
89
+ if wcs_kernel is None:
90
+ wcs_kernel = coords.get_wcs_kernel('car', 0, 0, res)
91
+ P = coords.P.for_tod(
92
+ tod=tod, wcs_kernel=wcs_kernel, cuts=cuts, comps='QU', hwp=flip_gamma)
93
+ else:
94
+ P, X = coords.planets.get_scan_P(tod, planet=center_on, res=res, hwp=flip_gamma)
95
+
96
+
97
+ if det_weights is None:
98
+ if det_weights_demod is None:
99
+ det_weights_demod = np.ones(tod.dets.count, dtype='float32')
100
+ det_weights = det_weights_demod * 2.
101
+ else:
102
+ if det_weights_demod is None:
103
+ det_weights_demod = det_weights / 2.
104
+
105
+ # T map and weight
106
+ mT_weighted = P.to_map(
107
+ tod=tod, signal=dsT, comps='T', det_weights=det_weights)
108
+ wT = P.to_weights(tod, signal=dsT, comps='T', det_weights=det_weights)
109
+
110
+ # Q/U maps and weights
111
+ mQ_weighted = P.to_map(tod=tod, signal=demodQ, comps='QU',
112
+ det_weights=det_weights_demod)
113
+ mU_weighted = P.to_map(tod=tod, signal=demodU, comps='QU',
114
+ det_weights=det_weights_demod)
115
+
116
+ mQU_weighted = P.zeros()
117
+ mQU_weighted[0][:] = mQ_weighted[0] - mU_weighted[1]
118
+ mQU_weighted[1][:] = mQ_weighted[1] + mU_weighted[0]
119
+ del mQ_weighted, mU_weighted
120
+
121
+ wQU = P.to_weights(tod, signal=demodQ, comps='T',
122
+ det_weights=det_weights_demod)
123
+
124
+ # combine mT_weighted and mQU_weighted into mTQU_weighted
125
+ mTQU_weighted = P.zeros(super_shape=3)
126
+ mTQU_weighted[0] = mT_weighted
127
+ mTQU_weighted[1] = mQU_weighted[0]
128
+ mTQU_weighted[2] = mQU_weighted[1]
129
+
130
+ # combine wT and wQU into wTQU
131
+ wTQU = enmap.zeros((3, 3) + P.geom.shape, wcs=P.geom.wcs)
132
+ wTQU[0][0] = wT
133
+ wTQU[1][1] = wQU
134
+ wTQU[2][2] = wQU
135
+
136
+ # remove weights
137
+ mTQU = P.remove_weights(signal_map=mTQU_weighted,
138
+ weights_map=wTQU, comps='TQU')
139
+
140
+ output = {'map': mTQU,
141
+ 'weighted_map': mTQU_weighted,
142
+ 'weight': wTQU}
143
+ return output
144
+
145
+ def from_map(tod, signal_map, cuts=None, flip_gamma=True, wrap=False, modulated=False):
146
+ """
147
+ Generate simulated TOD with HWP from a given signal map.
148
+
149
+ Args:
150
+ tod : an axisManager object
151
+ signal_map: pixell.enmap.ndmap containing (Tmap, Qmap, Umap) representing the signal.
152
+ cuts (RangesMatrix, optional): Cuts to apply to the data. Default is None.
153
+ flip_gamma (bool, optional): Whether to flip detector coordinate. If you use the HWP, keep it `True`. Default is True.
154
+ wrap (bool, optional): Whether to wrap the simulated data. Default is False.
155
+ modulated (bool, optional): If True, return modulated signal. If False, return the demodulated signal
156
+ (`dsT`, `demodQ`, and `demodU`). Default is False.
157
+
158
+ Returns:
159
+ `modulate==False`: A tuple containing the TOD (np.array) of dsT, demodQ and demodU.
160
+ `modulate==True` : The modulated TOD (np.array)
161
+
162
+ """
163
+ Tmap, Qmap, Umap = signal_map
164
+
165
+ P = coords.P.for_tod(tod=tod, geom=signal_map.geometry, cuts=cuts,
166
+ comps='QU', hwp=flip_gamma)
167
+ dsT_sim = P.from_map(Tmap, comps='T')
168
+ demodQ_sim = P.from_map(enmap.enmap([Qmap, Umap]), comps='QU')
169
+ demodU_sim = P.from_map(enmap.enmap([Umap, -Qmap]), comps='QU')
170
+
171
+ if modulated is False:
172
+ if wrap:
173
+ tod.wrap('dsT', dsT_sim, [(0, 'dets'), (1, 'samps')])
174
+ tod.wrap('demodQ', demodQ_sim, [(0, 'dets'), (1, 'samps')])
175
+ tod.wrap('demodU', demodU_sim, [(0, 'dets'), (1, 'samps')])
176
+ return dsT_sim, demodQ_sim, demodU_sim
177
+ else:
178
+ assert 'hwp_angle' in tod._fields
179
+ signal_sim = dsT_sim + demodQ_sim*np.cos(4*tod.hwp_angle) + demodU_sim*np.sin(4*tod.hwp_angle)
180
+ if wrap:
181
+ tod.wrap('signal', signal_sim, [(0, 'dets'), (1, 'samps')])
182
+ return signal_sim
183
+
184
+
185
+ def rotate_focal_plane(tod, hwp=True):
186
+ """ Interpret the boresight rotation effect as a focal plane rotation and update them accordingly.
187
+ This applies constant rotation to focal plane. If hwp=True, rotations of gamma are reflected.
188
+ This updates tod.boresight.roll and tod.focal_plane, in place.
189
+ """
190
+ sign = -1. if hwp else 1.
191
+ avg_roll = np.average(tod.boresight.roll)
192
+ tod.boresight.roll -= avg_roll
193
+ fp = so3g.proj.quat.rotation_xieta(tod.focal_plane.xi, tod.focal_plane.eta, sign * tod.focal_plane.gamma)
194
+ fp = so3g.proj.quat.euler(2, avg_roll) * fp
195
+ xi, eta, gamma = so3g.proj.quat.decompose_xieta(fp)
196
+ # boresight is float64 but signal and focal_plane are float32
197
+ tod.focal_plane.xi = np.float32(xi)
198
+ tod.focal_plane.eta = np.float32(eta)
199
+ tod.focal_plane.gamma = sign * np.float32(gamma)
200
+
201
+
202
+ def rotate_demodQU(tod, sign=1, offset=0, radial=False, update_focal_plane=True):
203
+ """
204
+ Apply detectors' polarization angle calibration to the HWP demodulated Q and U timestreams to
205
+ place all detectors' Q and U timestreams in a common telescope frame. This updates tod.demodQ
206
+ and tod.demodU, in place.
207
+ To get Qr Ur timestreams, run `rotate_demodQU(tod)` and then `rotate_demodQU(tod, radial=True)`.
208
+ To restore the Q U timestreams, run `rotate_demodQU(tod, sign=-1, radial=True)`.
209
+
210
+
211
+ Args:
212
+ tod : an axisManager object
213
+ update_focal_plane (bool, optional): Whether to update focal_plane.gamma angles consistent with new coordinate reference.
214
+ Make this True for polarization mapmaking using make_map.
215
+ offset : float, optional
216
+ The rotation angle in degrees to apply (default is 0).
217
+ sign : int, optional
218
+ A sign factor to control the direction of the rotation (default is +1).
219
+ radial : bool, optional
220
+ If True and the Q U timestreams in tod are in a common telescope flame, this function turns Q U
221
+ into Qr Ur.
222
+
223
+
224
+ """
225
+ if radial:
226
+ theta_fp = np.arctan2(tod.focal_plane.xi, tod.focal_plane.eta)
227
+ demodC = ((tod.demodQ + 1j*tod.demodU).T * np.exp( sign*(-2j*theta_fp) )).T
228
+ if update_focal_plane:
229
+ tod.focal_plane.gamma -= sign * theta_fp
230
+
231
+ else:
232
+ demodC = ((tod.demodQ + 1j*tod.demodU).T * np.exp( sign*(-2j*tod.focal_plane.gamma + 1j*np.deg2rad(offset)) )).T
233
+ if update_focal_plane:
234
+ tod.focal_plane.gamma *= 0
235
+ tod.demodQ = demodC.real
236
+ tod.demodU = demodC.imag
237
+ del demodC
238
+