dkist-processing-cryonirsp 1.9.0__py3-none-any.whl → 1.10.0rc1__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.
- changelog/167.feature.rst +1 -0
- dkist_processing_cryonirsp/config.py +4 -1
- dkist_processing_cryonirsp/models/constants.py +14 -1
- dkist_processing_cryonirsp/models/parameters.py +11 -19
- dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py +3 -2
- dkist_processing_cryonirsp/tasks/__init__.py +1 -1
- dkist_processing_cryonirsp/tasks/parse.py +15 -3
- dkist_processing_cryonirsp/tasks/sp_wavelength_calibration.py +300 -0
- dkist_processing_cryonirsp/tasks/write_l1.py +6 -16
- dkist_processing_cryonirsp/tests/conftest.py +13 -20
- dkist_processing_cryonirsp/tests/header_models.py +12 -0
- dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py +17 -17
- dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py +17 -19
- dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py +3 -3
- dkist_processing_cryonirsp/tests/test_cryo_constants.py +4 -1
- dkist_processing_cryonirsp/tests/test_parameters.py +4 -0
- dkist_processing_cryonirsp/tests/test_parse.py +28 -2
- dkist_processing_cryonirsp/tests/{test_sp_dispersion_axis_correction.py → test_sp_wavelength_calibration.py} +6 -23
- dkist_processing_cryonirsp/tests/test_write_l1.py +15 -15
- dkist_processing_cryonirsp/workflows/sp_l0_processing.py +3 -3
- dkist_processing_cryonirsp/workflows/trial_workflows.py +3 -3
- {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0rc1.dist-info}/METADATA +14 -13
- {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0rc1.dist-info}/RECORD +27 -25
- docs/index.rst +1 -0
- docs/wavelength_calibration.rst +62 -0
- dkist_processing_cryonirsp/tasks/sp_dispersion_axis_correction.py +0 -465
- {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0rc1.dist-info}/WHEEL +0 -0
- {dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0rc1.dist-info}/top_level.txt +0 -0
{dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0rc1.dist-info}/RECORD
RENAMED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
changelog/.gitempty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
changelog/167.feature.rst,sha256=UDCWFhNjmut91SbtIICb3Y5_MiPJ4zSPc0chd6y8AJU,142
|
|
2
3
|
dkist_processing_cryonirsp/__init__.py,sha256=Z6-kB7fXXUI-F7Vz1HnEaja2h8qgH9IZExRl1lUxvZg,350
|
|
3
|
-
dkist_processing_cryonirsp/config.py,sha256=
|
|
4
|
+
dkist_processing_cryonirsp/config.py,sha256=DlU2dr_oORrwytQVmEUSg3IRPXxE4vhAWiCiw7ykvzo,641
|
|
4
5
|
dkist_processing_cryonirsp/codecs/__init__.py,sha256=du1iitvsudSSOMENSywXmXSLOlvIocJsPbvfEcyqFNc,159
|
|
5
6
|
dkist_processing_cryonirsp/codecs/fits.py,sha256=EAdPcqWXMEWtWnRDLH_LX20giPoLVfmKBawb9J2z0wM,1718
|
|
6
7
|
dkist_processing_cryonirsp/models/__init__.py,sha256=m6UekKftTahNJ3W5K3mZSz4Y4ZZpHRxF_ZAxuaKYL7o,12
|
|
7
8
|
dkist_processing_cryonirsp/models/beam_boundaries.py,sha256=FyiLd2iCWA6TUojeGaqQ_ULxvakDY13VxqUJVlmYvV0,1159
|
|
8
|
-
dkist_processing_cryonirsp/models/constants.py,sha256=
|
|
9
|
+
dkist_processing_cryonirsp/models/constants.py,sha256=rFCkE-bZhbCABKVtQom5iTfPgDqDzsKkrtTnngZExkM,11528
|
|
9
10
|
dkist_processing_cryonirsp/models/exposure_conditions.py,sha256=slFq5-Qz4fRpJKDBabbm4evPWLQVYmT-Uf9rk7nI734,813
|
|
10
|
-
dkist_processing_cryonirsp/models/parameters.py,sha256=
|
|
11
|
+
dkist_processing_cryonirsp/models/parameters.py,sha256=Yn6GPEGnMiQyEL9n2BPx9LIVWPSdVXmcIX9OzzDOvPc,13144
|
|
11
12
|
dkist_processing_cryonirsp/models/tags.py,sha256=ac0MnYlsn8-w7IioOvWeo7mBaDKE9o9TlRpxCH1OsRc,5743
|
|
12
13
|
dkist_processing_cryonirsp/models/task_name.py,sha256=xK4AKwgOx2uANbjhr0Q5Q3R9iPxLfkVKxWYY8wWjKhE,439
|
|
13
14
|
dkist_processing_cryonirsp/parsers/__init__.py,sha256=m6UekKftTahNJ3W5K3mZSz4Y4ZZpHRxF_ZAxuaKYL7o,12
|
|
14
15
|
dkist_processing_cryonirsp/parsers/check_for_gains.py,sha256=v-eD1LG0dlFoZXz5Y-2ZyPvRL2TZ8gWfr5cN6YNYqvo,2341
|
|
15
|
-
dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py,sha256=
|
|
16
|
+
dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py,sha256=rMB4mrUGQnQ6nHEZVegkdGpnW4Q2iXG5YRAaAq9tOW4,5608
|
|
16
17
|
dkist_processing_cryonirsp/parsers/cryonirsp_l1_fits_access.py,sha256=sc8MzxYMc8E1eFrL5KguAGHViCMJhaDfiBtZPml4ELg,886
|
|
17
18
|
dkist_processing_cryonirsp/parsers/exposure_conditions.py,sha256=Mcud-0PQK0oJSxbqtQUtVk0t8b6YBEFSyGsGbG5UqGg,8445
|
|
18
19
|
dkist_processing_cryonirsp/parsers/map_repeats.py,sha256=PjZ986bqkCdii-EOzU045cWqadxQC_nyyqwWYIpYdls,1566
|
|
@@ -23,7 +24,7 @@ dkist_processing_cryonirsp/parsers/polarimetric_check.py,sha256=HBzg9Zi9-M1M2jh4
|
|
|
23
24
|
dkist_processing_cryonirsp/parsers/scan_step.py,sha256=7XNUq48qbdpV8GeaBeG9XFRDkYlgw8Fjd6ByFZ24OAc,18972
|
|
24
25
|
dkist_processing_cryonirsp/parsers/time.py,sha256=dpajm3tfrih-8pjlOWOvZVJVP2FihR87HFQSjR_KPYI,2543
|
|
25
26
|
dkist_processing_cryonirsp/parsers/wavelength.py,sha256=Ay5hZiDNV25-N_QXZINTCgn1ToiP2jvwumkbirBiJGk,883
|
|
26
|
-
dkist_processing_cryonirsp/tasks/__init__.py,sha256=
|
|
27
|
+
dkist_processing_cryonirsp/tasks/__init__.py,sha256=iSODAESNU6zBZo_t44LeTmS1oj_l6EVF7k8xSNtppnk,1057
|
|
27
28
|
dkist_processing_cryonirsp/tasks/assemble_movie.py,sha256=UrxfKSsT3mBkV2LYvnePzKr9nXlvjpoa5amY5C3ftFI,7350
|
|
28
29
|
dkist_processing_cryonirsp/tasks/bad_pixel_map.py,sha256=z-ACCwHqiRANsR7gkkCIycPpgOdR04Mo85WLAPiAJno,3961
|
|
29
30
|
dkist_processing_cryonirsp/tasks/beam_boundaries_base.py,sha256=-sKmBDuNq22QZBe6Vdu5aaiOxeikM6bICpkZ4lBP--g,9688
|
|
@@ -36,21 +37,21 @@ dkist_processing_cryonirsp/tasks/instrument_polarization.py,sha256=xS2jcngnibDCL
|
|
|
36
37
|
dkist_processing_cryonirsp/tasks/l1_output_data.py,sha256=3RFt493MEJxdpF81gcp8FDlQ8vGZ0GXEDYQFWIufumI,1554
|
|
37
38
|
dkist_processing_cryonirsp/tasks/linearity_correction.py,sha256=n9vK9cT7NWkpAM9J6wOYDj95Kh0va_ot-hdncd7ye0Y,24199
|
|
38
39
|
dkist_processing_cryonirsp/tasks/make_movie_frames.py,sha256=I7s3Tml6AevHci0kTPF71mNjXNl3wlG57Jh7ghnndeg,13928
|
|
39
|
-
dkist_processing_cryonirsp/tasks/parse.py,sha256=
|
|
40
|
+
dkist_processing_cryonirsp/tasks/parse.py,sha256=8efntsSPkNl_sokRU2SEStZBCRJvnXDsCelVumOUwH8,13824
|
|
40
41
|
dkist_processing_cryonirsp/tasks/quality_metrics.py,sha256=jyx2YZzLb5sVxbJ_H6PaKQqZbyZy9QuuLqu18jsnncQ,11447
|
|
41
42
|
dkist_processing_cryonirsp/tasks/science_base.py,sha256=YYUQUfLeuzDb6E5TecOH22orTN4-hWocoYaGOq6Zoro,18637
|
|
42
43
|
dkist_processing_cryonirsp/tasks/sp_beam_boundaries.py,sha256=XI3iepNe04xaU4ilqxrlOgYDkv5I5rUc0RXEE1Rwt0o,10296
|
|
43
|
-
dkist_processing_cryonirsp/tasks/sp_dispersion_axis_correction.py,sha256=w3DHEWEJwl3zuKuUB6kzG3vuBWJM84cZGbfeFQKWwJE,18279
|
|
44
44
|
dkist_processing_cryonirsp/tasks/sp_geometric.py,sha256=_M_e_blz4mKDIUWSasonnOzbZ6EUbHp9pAZXQx4zY7U,24387
|
|
45
45
|
dkist_processing_cryonirsp/tasks/sp_science.py,sha256=QWyAEkXYamAcWxi62-tVD6ptuQ6vt8yIzuCKzCIYW20,13643
|
|
46
46
|
dkist_processing_cryonirsp/tasks/sp_solar_gain.py,sha256=d4UABsMxyzCMduVxptHY_TCGqS-l-W5iuhW7HJwVPkA,21024
|
|
47
|
-
dkist_processing_cryonirsp/tasks/
|
|
47
|
+
dkist_processing_cryonirsp/tasks/sp_wavelength_calibration.py,sha256=E9HBmlzvvUEgoAamlO-E0MngYKjuUVq3WwK0DRDLvPk,12843
|
|
48
|
+
dkist_processing_cryonirsp/tasks/write_l1.py,sha256=Jzg09WUYi8uY5o6By7JOsFP0CHpfPCVC4M2UvLSO2PA,41169
|
|
48
49
|
dkist_processing_cryonirsp/tasks/mixin/__init__.py,sha256=m6UekKftTahNJ3W5K3mZSz4Y4ZZpHRxF_ZAxuaKYL7o,12
|
|
49
50
|
dkist_processing_cryonirsp/tasks/mixin/corrections.py,sha256=rcKmckBJkoExcX0XW1i3OZzuMu1i7tX5Hgwy15chU50,6566
|
|
50
51
|
dkist_processing_cryonirsp/tasks/mixin/shift_measurements.py,sha256=EbU3VQ_1QLbENHO_SfhWc7d573UwbofKU-PpbfBPKI8,11620
|
|
51
52
|
dkist_processing_cryonirsp/tests/__init__.py,sha256=m6UekKftTahNJ3W5K3mZSz4Y4ZZpHRxF_ZAxuaKYL7o,12
|
|
52
|
-
dkist_processing_cryonirsp/tests/conftest.py,sha256=
|
|
53
|
-
dkist_processing_cryonirsp/tests/header_models.py,sha256=
|
|
53
|
+
dkist_processing_cryonirsp/tests/conftest.py,sha256=ThhhNZ61a-qRMiPEM7PgLwKTw9L4C5nh0IHLDnwtTRo,18016
|
|
54
|
+
dkist_processing_cryonirsp/tests/header_models.py,sha256=eQWRwJzWCIK8-ak1oLWf88u7eo7ERxPMrmQHuphUfX8,21115
|
|
54
55
|
dkist_processing_cryonirsp/tests/test_assemble_movie.py,sha256=YNZINIFXR9kZBlE1AIvjlVmwwhZJeVYOOPk7Q8IVkcI,6222
|
|
55
56
|
dkist_processing_cryonirsp/tests/test_assemble_qualilty.py,sha256=upk-oUqVBHGK3F0eemshLpAPrnfh9mbeuZXow4E1Rmc,16859
|
|
56
57
|
dkist_processing_cryonirsp/tests/test_bad_pixel_maps.py,sha256=TsUIaCWQolOJCU2YOhxxmXWby6j3NhCkB2W2jDgb9OM,4855
|
|
@@ -58,33 +59,33 @@ dkist_processing_cryonirsp/tests/test_ci_beam_boundaries.py,sha256=h-v79qi4VohcX
|
|
|
58
59
|
dkist_processing_cryonirsp/tests/test_ci_science.py,sha256=PryW50DZaKiTcLaSvhfaolrosXObj7-O1jweCJeLM_Y,14403
|
|
59
60
|
dkist_processing_cryonirsp/tests/test_corrections.py,sha256=Q_prvaXKdmpebEa5d05s86pcGB9VTjsGB0g5AfEB2Ks,4536
|
|
60
61
|
dkist_processing_cryonirsp/tests/test_cryo_base.py,sha256=9dSQ_3j_n04NX-nbdAFWhdHGwMe720Vyx0Jxof9eySo,6647
|
|
61
|
-
dkist_processing_cryonirsp/tests/test_cryo_constants.py,sha256=
|
|
62
|
+
dkist_processing_cryonirsp/tests/test_cryo_constants.py,sha256=WP3cHUF7g9urUt_BuchkbG6ldjM07QltClxRPLnmjsw,3008
|
|
62
63
|
dkist_processing_cryonirsp/tests/test_dark.py,sha256=9WQDoVw1qwaqK-iaVfjOKbIusr4SJrR1rGiPZAWhNIU,11669
|
|
63
64
|
dkist_processing_cryonirsp/tests/test_gain.py,sha256=KAkIXJnifVx7CHnKBY-7EhhUi5b8t5U8wBOL9F8M0gM,11260
|
|
64
65
|
dkist_processing_cryonirsp/tests/test_instrument_polarization.py,sha256=COiopx4ueVPeyQO12eVP125nqBrgsnCa0ddo8y6Qrxs,19711
|
|
65
66
|
dkist_processing_cryonirsp/tests/test_linearity_correction.py,sha256=r1EwZsW1yO0B0ERGn1kDciZKvjipN_LVHFXR-XIJmP0,9350
|
|
66
67
|
dkist_processing_cryonirsp/tests/test_make_movie_frames.py,sha256=WznHp9dV2-jbJYzRniCAIbSHCGNc0SpSzyVDSrZkYd4,4904
|
|
67
|
-
dkist_processing_cryonirsp/tests/test_parameters.py,sha256=
|
|
68
|
-
dkist_processing_cryonirsp/tests/test_parse.py,sha256=
|
|
68
|
+
dkist_processing_cryonirsp/tests/test_parameters.py,sha256=hy0ssu2OJmkHFKlGd0_d6EW10YjWsqGb68rOFlPqGuo,11105
|
|
69
|
+
dkist_processing_cryonirsp/tests/test_parse.py,sha256=Ejullo7r7vR0zYRCd714z4berKwXrwSnv8xMVRVqNd4,57090
|
|
69
70
|
dkist_processing_cryonirsp/tests/test_quality.py,sha256=qrJBYjnZOhmQ4vjDcDV3FVSUAdktFgs-pRaHX4cf2G0,8129
|
|
70
71
|
dkist_processing_cryonirsp/tests/test_sp_beam_boundaries.py,sha256=tLQToWStb4Yu2jEHkzv2FyifO_QPwegzttyNKjX8JPk,4880
|
|
71
|
-
dkist_processing_cryonirsp/tests/test_sp_dispersion_axis_correction.py,sha256=Z0t_v85ATh9ntlngUa8v_hqs0ZCd4nkakpHNeCVRwiE,6141
|
|
72
72
|
dkist_processing_cryonirsp/tests/test_sp_geometric.py,sha256=ZnusZvxsJ8YX-rg0R1azg7-DPr4vz5q2NE030bsuWXo,15691
|
|
73
73
|
dkist_processing_cryonirsp/tests/test_sp_make_movie_frames.py,sha256=Kn8U_HzaaHW2bHmBxsotdjmpBhd_Ft6pLWhVsMWIJE8,5322
|
|
74
74
|
dkist_processing_cryonirsp/tests/test_sp_science.py,sha256=fCmyXh27nxKU_N90yW1WqPGq1mZ6ODrw0UvtMB1elHI,19835
|
|
75
75
|
dkist_processing_cryonirsp/tests/test_sp_solar.py,sha256=IdZZ2RvCwKk6_q_JKo93nFFk0HJ74yUxHxq9W1LppJE,10008
|
|
76
|
+
dkist_processing_cryonirsp/tests/test_sp_wavelength_calibration.py,sha256=SZMixYxMnIksvQpTiXt8MiwLbyZiDyKE6CW2vjl4af8,5666
|
|
76
77
|
dkist_processing_cryonirsp/tests/test_trial_create_quality_report.py,sha256=x8dRAMyawQVYZQGsuO36DMZxK4L13hZBUn86qbhJiNk,2805
|
|
77
78
|
dkist_processing_cryonirsp/tests/test_workflows.py,sha256=2a-TUMbVEyNjHYNyzo2UQMLg5PSaEx6iV9hOsGp-Mck,291
|
|
78
|
-
dkist_processing_cryonirsp/tests/test_write_l1.py,sha256=
|
|
79
|
+
dkist_processing_cryonirsp/tests/test_write_l1.py,sha256=Ijf1Dxa-jCkMjEcPuSRbtCsFzfHH-nifn2AQ84qg1zg,17644
|
|
79
80
|
dkist_processing_cryonirsp/tests/local_trial_workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
|
-
dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py,sha256=
|
|
81
|
-
dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py,sha256=
|
|
81
|
+
dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py,sha256=jUC6EnzBLwso7DBCtmhTdPJw3zlrIJYW0KTKNlWgGAM,20088
|
|
82
|
+
dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py,sha256=Ab1IeXfys130jkRs0iNIPv2rZFXg-IDCNkK4Z_wdOuI,23909
|
|
82
83
|
dkist_processing_cryonirsp/tests/local_trial_workflows/linearize_only.py,sha256=kl9yrE1EbgxNn__x4q0WYoZIvS8zefcOPbQQdxB4_ZE,3280
|
|
83
|
-
dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py,sha256=
|
|
84
|
+
dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py,sha256=DQDpjc6_I5o6dIPv5hK65oBKG0vksp9lY4k9A0hu1D4,20953
|
|
84
85
|
dkist_processing_cryonirsp/workflows/__init__.py,sha256=iEbV3oiKmkfmdZjeNJxqw08IIZnYSroq-2b-ARpkLFQ,112
|
|
85
86
|
dkist_processing_cryonirsp/workflows/ci_l0_processing.py,sha256=8-96ZWi_hnzsashkFaaK6YjO0CUk_2iO_gCoHTmGow8,3823
|
|
86
|
-
dkist_processing_cryonirsp/workflows/sp_l0_processing.py,sha256=
|
|
87
|
-
dkist_processing_cryonirsp/workflows/trial_workflows.py,sha256=
|
|
87
|
+
dkist_processing_cryonirsp/workflows/sp_l0_processing.py,sha256=TFycCbC_N3MhM0rEHpEPmKtfJLNaVY3csR6uDrRCKI4,4245
|
|
88
|
+
dkist_processing_cryonirsp/workflows/trial_workflows.py,sha256=eLrROaZiyZwn8ta34oSO06aH_D9VPoqWinjDMN-9VN4,8079
|
|
88
89
|
docs/Makefile,sha256=qnlVz6PuBqE39NfHWuUnHhNEA-EFgT2-WJNNNy9ttfk,4598
|
|
89
90
|
docs/bad_pixel_calibration.rst,sha256=bHRclUItBA1QbGlek36B1yN5WHN53WkfjKUvZaq_j2I,2452
|
|
90
91
|
docs/beam_angle_calculation.rst,sha256=-yUPFRl6SbPBIj-wOwylEymQDMQnkay7kAIAiubpQT8,2941
|
|
@@ -92,7 +93,7 @@ docs/beam_boundary_computation.rst,sha256=khyc_uW5zII6c0vN1lOvrwMAr5WO1XFFIou3QB
|
|
|
92
93
|
docs/changelog.rst,sha256=S2jPASsWlQxSlAPqdvNrYvhk9k3FcFWNXFNDYXBSjl4,120
|
|
93
94
|
docs/ci_science_calibration.rst,sha256=6HLt4ljL49sYH_iFU-Nz8KSWLyS8h_SSkzgUv-LsfqM,1704
|
|
94
95
|
docs/conf.py,sha256=cv1Gct6NbY_kxJEKqw-mMIoauxtWVZeNzRLFqX1_GUw,2038
|
|
95
|
-
docs/index.rst,sha256=
|
|
96
|
+
docs/index.rst,sha256=l6vH2FhWpuz0X1SbgfaMBoCACMPRuhHCs9dTxW1Hcaw,472
|
|
96
97
|
docs/l0_to_l1_cryonirsp_ci-full-trial.rst,sha256=-uhtnd51ttJYw9T5hs5A9HQWpXJkOJmvfXf1INFT3MI,582
|
|
97
98
|
docs/l0_to_l1_cryonirsp_ci.rst,sha256=OhGTy9CBTqQJ04XhThTws8KBnGLFiP5vBX0DlX6NXKA,458
|
|
98
99
|
docs/l0_to_l1_cryonirsp_sp-full-trial.rst,sha256=cKdRI7qVEVYsqqgYuL9nzqFP3uTR4cu305WfjmmyetY,582
|
|
@@ -104,8 +105,9 @@ docs/requirements.txt,sha256=Kbl_X4c7RQZw035YTeNB63We6I7pvXFU4T0Uflp2yDY,29
|
|
|
104
105
|
docs/requirements_table.rst,sha256=FaqSag9kPi77gWPhzeo_tFEhRFjb3qUuNqqQe1K76NM,297
|
|
105
106
|
docs/scientific_changelog.rst,sha256=01AWBSHg8zElnodCgAq-hMxhk9CkX5rtEENx4iz0sjI,300
|
|
106
107
|
docs/sp_science_calibration.rst,sha256=XL-H_hyzqwPHYNW3j-muItX_hGqMi-gjFRQbHp60LlU,2997
|
|
108
|
+
docs/wavelength_calibration.rst,sha256=s7ds_QKlVJ68fdONSY3DOBvHHaQC0JR_D4goG_VVKWw,3457
|
|
107
109
|
licenses/LICENSE.rst,sha256=piZaQplkzOMmH1NXg6QIdo9wwo9pPCoHkvm2-DmH76E,1462
|
|
108
|
-
dkist_processing_cryonirsp-1.
|
|
109
|
-
dkist_processing_cryonirsp-1.
|
|
110
|
-
dkist_processing_cryonirsp-1.
|
|
111
|
-
dkist_processing_cryonirsp-1.
|
|
110
|
+
dkist_processing_cryonirsp-1.10.0rc1.dist-info/METADATA,sha256=aYUp1rzLQuMN0qnC4k9OdBurJb_iO0fLG_zfemf40hQ,22111
|
|
111
|
+
dkist_processing_cryonirsp-1.10.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
112
|
+
dkist_processing_cryonirsp-1.10.0rc1.dist-info/top_level.txt,sha256=Sm9b1ddKnsF9Bh3mqDOct1Sm7k8I9aN7vGHgpmu-MlQ,51
|
|
113
|
+
dkist_processing_cryonirsp-1.10.0rc1.dist-info/RECORD,,
|
docs/index.rst
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Wavelength Calibration
|
|
2
|
+
============================
|
|
3
|
+
|
|
4
|
+
Overview
|
|
5
|
+
--------
|
|
6
|
+
|
|
7
|
+
The `~dkist_processing_cryonirsp.tasks.sp_wavelength_calibration` task provides an absolute wavelength calibration of
|
|
8
|
+
Cryo-NIRSP solar spectra by using the routines provided by the
|
|
9
|
+
`solar-wavelength-calibration <https://docs.dkist.nso.edu/projects/solar-wavelength-calibration/en/latest/>`_ library.
|
|
10
|
+
|
|
11
|
+
Workflow
|
|
12
|
+
--------
|
|
13
|
+
|
|
14
|
+
#. **Input Spectrum**: Compute a spatially averaged input spectrum from solar gain images.
|
|
15
|
+
#. **Initial Guess**: Use Level 0 headers to generate a first-guess wavelength solution.
|
|
16
|
+
#. **Fitting**: Fit the representative spectrum using the `solar-wavelength-calibration <https://docs.dkist.nso.edu/projects/solar-wavelength-calibration/en/latest/>`_ library, refining the wavelength solution.
|
|
17
|
+
#. **Header Encoding**: Save the fit results as FITS header keywords, parameterizing the solution for downstream use.
|
|
18
|
+
|
|
19
|
+
Wavelength Solution Encoding
|
|
20
|
+
----------------------------
|
|
21
|
+
|
|
22
|
+
The wavelength solution is stored in FITS headers using the following keywords (see `Greisen et al (2006) <https://ui.adsabs.harvard.edu/abs/2006A%26A...446..747G/abstract>`_, Section 5 and Table 6):
|
|
23
|
+
|
|
24
|
+
+---------+--------------------------+----------------+
|
|
25
|
+
| Keyword | Description | Units |
|
|
26
|
+
+=========+==========================+================+
|
|
27
|
+
| `CTYPE1`| Spectral coordinate type | "AWAV-GRA" |
|
|
28
|
+
+---------+--------------------------+----------------+
|
|
29
|
+
| `CUNIT1`| Wavelength unit | "nm" |
|
|
30
|
+
+---------+--------------------------+----------------+
|
|
31
|
+
| `CRPIX1`| Reference pixel | |
|
|
32
|
+
+---------+--------------------------+----------------+
|
|
33
|
+
| `CRVAL1`| Reference wavelength | nm |
|
|
34
|
+
+---------+--------------------------+----------------+
|
|
35
|
+
| `CDELT1`| Linear dispersion | nm / px |
|
|
36
|
+
+---------+--------------------------+----------------+
|
|
37
|
+
| `PV1_0` | Grating constant | 1 / m |
|
|
38
|
+
+---------+--------------------------+----------------+
|
|
39
|
+
| `PV1_1` | Spectral order | |
|
|
40
|
+
+---------+--------------------------+----------------+
|
|
41
|
+
| `PV1_1` | Incident light angle | deg |
|
|
42
|
+
+---------+--------------------------+----------------+
|
|
43
|
+
|
|
44
|
+
Note: The units of `PV1_0` are always 1 / m.
|
|
45
|
+
|
|
46
|
+
Fitted Parameters
|
|
47
|
+
-----------------
|
|
48
|
+
|
|
49
|
+
The fitting process can optimize several parameters. The parameters that are free in Cryo-NIRSP fits are:
|
|
50
|
+
|
|
51
|
+
- **crval**: Wavelength zero-point.
|
|
52
|
+
- **dispersion**: Linear dispersion, allowed to vary within a few percent of the nominal value.
|
|
53
|
+
- **opacity_factor**: Atmospheric absorption scaling, to match telluric line strengths.
|
|
54
|
+
- **continuum_level**: Overall spectrum scaling, to match the observed continuum.
|
|
55
|
+
- **straylight_fraction**: Fraction of stray or scattered light added to the observed spectrum, affecting line depths and continuum.
|
|
56
|
+
- **resolving_power**: Spectral resolving power (:math:`R = \frac{\lambda}{\Delta\lambda}`), characterizing the instrument's ability to distinguish close spectral features.
|
|
57
|
+
- **incident_light_angle**: Angle at which light enters the grating, influencing the wavelength solution through the grating equation.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
For more details on the fitting algorithms and parameterization, see the
|
|
61
|
+
`solar-wavelength-calibration documentation <https://docs.dkist.nso.edu/projects/solar-wavelength-calibration/en/latest/>`_
|
|
62
|
+
and `Greisen et al. (2006) <https://ui.adsabs.harvard.edu/abs/2006A%26A...446..747G/abstract>`_.
|
|
@@ -1,465 +0,0 @@
|
|
|
1
|
-
"""Cryonirsp SP dispersion axis calibration task."""
|
|
2
|
-
import warnings
|
|
3
|
-
|
|
4
|
-
import numpy as np
|
|
5
|
-
from astropy import constants as const
|
|
6
|
-
from astropy import units as u
|
|
7
|
-
from astropy.coordinates import EarthLocation
|
|
8
|
-
from astropy.coordinates.spectral_coordinate import SpectralCoord
|
|
9
|
-
from astropy.io import fits
|
|
10
|
-
from astropy.time import Time
|
|
11
|
-
from astropy.wcs import WCS
|
|
12
|
-
from dkist_processing_common.codecs.asdf import asdf_encoder
|
|
13
|
-
from dkist_processing_common.models.dkist_location import location_of_dkist
|
|
14
|
-
from dkist_service_configuration.logging import logger
|
|
15
|
-
from scipy.ndimage import gaussian_filter1d
|
|
16
|
-
from scipy.optimize import differential_evolution
|
|
17
|
-
from scipy.optimize import OptimizeResult
|
|
18
|
-
from sunpy.coordinates import HeliocentricInertial
|
|
19
|
-
|
|
20
|
-
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_access_decoder
|
|
21
|
-
from dkist_processing_cryonirsp.codecs.fits import cryo_fits_array_decoder
|
|
22
|
-
from dkist_processing_cryonirsp.models.tags import CryonirspTag
|
|
23
|
-
from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import CryonirspL0FitsAccess
|
|
24
|
-
from dkist_processing_cryonirsp.tasks.cryonirsp_base import CryonirspTaskBase
|
|
25
|
-
|
|
26
|
-
__all__ = ["SPDispersionAxisCorrection"]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class SPDispersionAxisCorrection(CryonirspTaskBase):
|
|
30
|
-
"""Task class for correcting the dispersion axis wavelength values.
|
|
31
|
-
|
|
32
|
-
Parameters
|
|
33
|
-
----------
|
|
34
|
-
recipe_run_id : int
|
|
35
|
-
id of the recipe run used to identify the workflow run this task is part of
|
|
36
|
-
workflow_name : str
|
|
37
|
-
name of the workflow to which this instance of the task belongs
|
|
38
|
-
workflow_version : str
|
|
39
|
-
version of the workflow to which this instance of the task belongs
|
|
40
|
-
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
record_provenance = True
|
|
44
|
-
|
|
45
|
-
def run(self):
|
|
46
|
-
"""
|
|
47
|
-
Run method for the task.
|
|
48
|
-
|
|
49
|
-
For each beam
|
|
50
|
-
- Gather 1D characteristic spectrum.
|
|
51
|
-
- Compute the theoretical dispersion.
|
|
52
|
-
- Load the telluric and non-telluric FTS atlases and grab only the portion of the atlases that pertain to the current observation.
|
|
53
|
-
- Shift the preliminary wavelength vector (from the data) so that it generally aligns with the FTS atlas data.
|
|
54
|
-
- Account for the speed at which DKIST was moving relative to the sun's center at the time of observation.
|
|
55
|
-
- Define fitting bounds and fit the profile using scipy.optimize.differential_evolution.
|
|
56
|
-
- Write results to disk.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Returns
|
|
60
|
-
-------
|
|
61
|
-
None
|
|
62
|
-
"""
|
|
63
|
-
spectrum = self.load_1d_char_spectrum()
|
|
64
|
-
|
|
65
|
-
solar_header = self.load_header()
|
|
66
|
-
|
|
67
|
-
dispersion, order, alpha = self.get_theoretical_dispersion()
|
|
68
|
-
|
|
69
|
-
expected_wavelength_vector = self.compute_expected_wavelength_vector(spectrum, solar_header)
|
|
70
|
-
|
|
71
|
-
(
|
|
72
|
-
telluric_atlas_wave,
|
|
73
|
-
telluric_atlas_trans,
|
|
74
|
-
solar_atlas_wave_air,
|
|
75
|
-
solar_atlas_trans_flipped,
|
|
76
|
-
) = self.load_and_resample_fts_atlas(expected_wavelength_vector)
|
|
77
|
-
|
|
78
|
-
(fts_wave, fts_solar, fts_telluric) = self.initial_alignment(
|
|
79
|
-
spectrum,
|
|
80
|
-
expected_wavelength_vector,
|
|
81
|
-
solar_atlas_wave_air,
|
|
82
|
-
solar_atlas_trans_flipped,
|
|
83
|
-
telluric_atlas_wave,
|
|
84
|
-
telluric_atlas_trans,
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
doppler_shift = self.get_doppler_shift()
|
|
88
|
-
|
|
89
|
-
fit_result = self.fit_dispersion_axis_to_FTS(
|
|
90
|
-
fts_wave,
|
|
91
|
-
fts_telluric,
|
|
92
|
-
fts_solar,
|
|
93
|
-
dispersion,
|
|
94
|
-
alpha,
|
|
95
|
-
doppler_shift,
|
|
96
|
-
spectrum,
|
|
97
|
-
order,
|
|
98
|
-
self.constants.grating_constant,
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
self.write_fit_results(spectrum, order, fit_result)
|
|
102
|
-
|
|
103
|
-
def write_fit_results(
|
|
104
|
-
self, spectrum: np.ndarray, order: int, fit_result: OptimizeResult
|
|
105
|
-
) -> None:
|
|
106
|
-
"""Save the fit results to disk to later be used to update the l1 headers."""
|
|
107
|
-
updated_headers = {
|
|
108
|
-
"CRPIX1": np.size(spectrum) // 2 + 1,
|
|
109
|
-
"CRVAL1": fit_result.x[0],
|
|
110
|
-
"CDELT1": fit_result.x[1],
|
|
111
|
-
"PV1_0": self.constants.grating_constant,
|
|
112
|
-
"PV1_1": order,
|
|
113
|
-
"PV1_2": fit_result.x[2],
|
|
114
|
-
"CRPIX1A": np.size(spectrum) // 2 + 1,
|
|
115
|
-
"CRVAL1A": fit_result.x[0],
|
|
116
|
-
"CDELT1A": fit_result.x[1],
|
|
117
|
-
"PV1_0A": self.constants.grating_constant,
|
|
118
|
-
"PV1_1A": order,
|
|
119
|
-
"PV1_2A": fit_result.x[2],
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
self.write(
|
|
123
|
-
data=updated_headers,
|
|
124
|
-
tags=[CryonirspTag.task_spectral_fit(), CryonirspTag.intermediate()],
|
|
125
|
-
encoder=asdf_encoder,
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
def load_1d_char_spectrum(self) -> np.ndarray:
|
|
129
|
-
"""Load intermediate 1d characteristic measured_spectra for beam 1."""
|
|
130
|
-
# Only fitting with the left beam.
|
|
131
|
-
beam = 1
|
|
132
|
-
array_generator = self.read(
|
|
133
|
-
tags=[CryonirspTag.intermediate_frame(beam=beam), CryonirspTag.task("SOLAR_CHAR_SPEC")],
|
|
134
|
-
decoder=cryo_fits_array_decoder,
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
return next(array_generator)
|
|
138
|
-
|
|
139
|
-
def load_header(self) -> fits.header.Header:
|
|
140
|
-
"""Grab a header from a random solar gain frame to be used to find a rough initial wavelength estimate."""
|
|
141
|
-
# Only fitting with the left beam.
|
|
142
|
-
beam = 1
|
|
143
|
-
solar_tags = [CryonirspTag.linearized_frame(), CryonirspTag.task("SOLAR_GAIN")]
|
|
144
|
-
solar_obj = next(
|
|
145
|
-
self.read(
|
|
146
|
-
tags=solar_tags,
|
|
147
|
-
decoder=cryo_fits_access_decoder,
|
|
148
|
-
fits_access_class=CryonirspL0FitsAccess,
|
|
149
|
-
)
|
|
150
|
-
)
|
|
151
|
-
solar_header = solar_obj.header
|
|
152
|
-
return solar_header
|
|
153
|
-
|
|
154
|
-
def get_theoretical_dispersion(self) -> tuple[u.Quantity, int, float]:
|
|
155
|
-
"""Compute theoretical dispersion value using the following grating equation.
|
|
156
|
-
|
|
157
|
-
m = d/lambda * (sin(alpha) + sin(beta))
|
|
158
|
-
|
|
159
|
-
where
|
|
160
|
-
m = order
|
|
161
|
-
d = grating spacing
|
|
162
|
-
lambda = wavelength
|
|
163
|
-
alpha = incident angle
|
|
164
|
-
beta = diffraction angle
|
|
165
|
-
|
|
166
|
-
"""
|
|
167
|
-
wavelength = self.constants.wavelength * u.nanometer
|
|
168
|
-
grating_position_angle_phi = np.deg2rad(self.constants.grating_position_deg)
|
|
169
|
-
grating_littrow_angle_theta = np.deg2rad(self.constants.grating_littrow_angle_deg)
|
|
170
|
-
alpha = grating_position_angle_phi + grating_littrow_angle_theta
|
|
171
|
-
beta = grating_position_angle_phi - grating_littrow_angle_theta
|
|
172
|
-
grating_spacing_distance = (1.0 / self.constants.grating_constant) * u.m
|
|
173
|
-
order = int(grating_spacing_distance / wavelength * (np.sin(alpha) + np.sin(beta)))
|
|
174
|
-
camera_mirror_focal_length = self.parameters.camera_mirror_focal_length_mm
|
|
175
|
-
pixpitch = self.parameters.pixel_pitch_micron
|
|
176
|
-
linear_disp = order / (grating_spacing_distance * np.cos(beta)) * camera_mirror_focal_length
|
|
177
|
-
theoretical_dispersion = (pixpitch / linear_disp).to(u.nanometer)
|
|
178
|
-
|
|
179
|
-
return theoretical_dispersion, order, alpha
|
|
180
|
-
|
|
181
|
-
def compute_expected_wavelength_vector(
|
|
182
|
-
self, spectrum: np.ndarray, header: fits.header.Header
|
|
183
|
-
) -> u.Quantity:
|
|
184
|
-
"""Compute the expected wavelength vector based on the header information.""" ""
|
|
185
|
-
# resample atlases
|
|
186
|
-
number_of_wave_pix = np.size(spectrum)
|
|
187
|
-
header["CRPIX1"] = number_of_wave_pix // 2 + 1
|
|
188
|
-
with warnings.catch_warnings():
|
|
189
|
-
warnings.simplefilter("ignore") ## TO ELIMINATE datafix warnings
|
|
190
|
-
wcs = WCS(header)
|
|
191
|
-
# get wavelength based on header info (not fully accurate)
|
|
192
|
-
expected_wavelength_vector = wcs.spectral.pixel_to_world(
|
|
193
|
-
np.arange(number_of_wave_pix)
|
|
194
|
-
).to(u.nm)
|
|
195
|
-
|
|
196
|
-
return expected_wavelength_vector
|
|
197
|
-
|
|
198
|
-
def load_and_resample_fts_atlas(
|
|
199
|
-
self, expected_wavelength_vector: u.Quantity
|
|
200
|
-
) -> tuple[u.Quantity, np.ndarray, u.Quantity, np.ndarray]:
|
|
201
|
-
"""Load telluric and non-telluric FTS atlas data, resample both atlases to be on the same, linear wavelength grid, select the portion of atlas that pertains to bandpass used."""
|
|
202
|
-
solar_atlas_wavelength, solar_atlas_transmission = self.parameters.solar_atlas
|
|
203
|
-
solar_atlas_wavelength = solar_atlas_wavelength * u.nm
|
|
204
|
-
telluric_atlas_wavelength, telluric_atlas_transmission = self.parameters.telluric_atlas
|
|
205
|
-
telluric_atlas_wavelength = telluric_atlas_wavelength * u.nm
|
|
206
|
-
|
|
207
|
-
expected_wavelength_range = (
|
|
208
|
-
expected_wavelength_vector.max() - expected_wavelength_vector.min()
|
|
209
|
-
)
|
|
210
|
-
min_wavelength = expected_wavelength_vector.min() - 0.25 * expected_wavelength_range
|
|
211
|
-
max_wavelength = expected_wavelength_vector.max() + 0.25 * expected_wavelength_range
|
|
212
|
-
|
|
213
|
-
cropped_telluric_mask = (telluric_atlas_wavelength > min_wavelength) * (
|
|
214
|
-
telluric_atlas_wavelength < max_wavelength
|
|
215
|
-
)
|
|
216
|
-
telluric_atlas_wavelength = telluric_atlas_wavelength[cropped_telluric_mask]
|
|
217
|
-
telluric_atlas_transmission = telluric_atlas_transmission[cropped_telluric_mask]
|
|
218
|
-
|
|
219
|
-
cropped_solar_mask = (solar_atlas_wavelength > min_wavelength) * (
|
|
220
|
-
solar_atlas_wavelength < max_wavelength
|
|
221
|
-
)
|
|
222
|
-
solar_atlas_wavelength = solar_atlas_wavelength[cropped_solar_mask]
|
|
223
|
-
solar_atlas_transmission = solar_atlas_transmission[cropped_solar_mask]
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
telluric_atlas_wavelength,
|
|
227
|
-
telluric_atlas_transmission,
|
|
228
|
-
solar_atlas_wavelength,
|
|
229
|
-
solar_atlas_transmission,
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
def get_doppler_shift(self) -> u.Quantity:
|
|
233
|
-
"""Find the speed at which DKIST is moving relative to the Sun's center.
|
|
234
|
-
|
|
235
|
-
Positive values refer to when DKIST is moving away from the sun.
|
|
236
|
-
"""
|
|
237
|
-
coord = location_of_dkist.get_gcrs(obstime=Time(self.constants.solar_gain_ip_start_time))
|
|
238
|
-
heliocentric_coord = coord.transform_to(
|
|
239
|
-
HeliocentricInertial(obstime=Time(self.constants.solar_gain_ip_start_time))
|
|
240
|
-
)
|
|
241
|
-
obs_vr_kms = heliocentric_coord.d_distance
|
|
242
|
-
return obs_vr_kms
|
|
243
|
-
|
|
244
|
-
def initial_alignment(
|
|
245
|
-
self,
|
|
246
|
-
spectrum: np.ndarray,
|
|
247
|
-
expected_wavelength_vector: SpectralCoord,
|
|
248
|
-
solar_atlas_wave_air: u.Quantity,
|
|
249
|
-
solar_atlas_trans_flipped: np.ndarray,
|
|
250
|
-
telluric_atlas_wave: u.Quantity,
|
|
251
|
-
telluric_atlas_trans: np.ndarray,
|
|
252
|
-
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
253
|
-
"""Determine a shift of the preliminary wavelength vector so that it generally aligns with the data itself."""
|
|
254
|
-
shifts = np.linspace(-2, 2, 550) * u.nm
|
|
255
|
-
merit = np.zeros(len(shifts))
|
|
256
|
-
for n, shift in enumerate(shifts):
|
|
257
|
-
preliminary_wavelength = expected_wavelength_vector + shift
|
|
258
|
-
fts_solar = np.interp(
|
|
259
|
-
preliminary_wavelength, solar_atlas_wave_air, solar_atlas_trans_flipped
|
|
260
|
-
)
|
|
261
|
-
fts_telluric = np.interp(
|
|
262
|
-
preliminary_wavelength, telluric_atlas_wave, telluric_atlas_trans
|
|
263
|
-
)
|
|
264
|
-
# calculate a merit value to be minimized
|
|
265
|
-
merit[n] = np.std(spectrum - fts_solar * fts_telluric)
|
|
266
|
-
|
|
267
|
-
# get minimum
|
|
268
|
-
shift = shifts[np.argmin(merit)]
|
|
269
|
-
|
|
270
|
-
# recalculate spectral axis and atlas spectrum for the best shift value
|
|
271
|
-
fts_wave = expected_wavelength_vector + shift
|
|
272
|
-
fts_solar = np.interp(fts_wave, solar_atlas_wave_air, solar_atlas_trans_flipped)
|
|
273
|
-
fts_telluric = np.interp(fts_wave, telluric_atlas_wave, telluric_atlas_trans)
|
|
274
|
-
|
|
275
|
-
return fts_wave.value, fts_solar, fts_telluric
|
|
276
|
-
|
|
277
|
-
@staticmethod
|
|
278
|
-
def fitness(
|
|
279
|
-
parameters: np.ndarray,
|
|
280
|
-
spectrum: np.ndarray,
|
|
281
|
-
fts_wave: np.ndarray,
|
|
282
|
-
fts_telluric: np.ndarray,
|
|
283
|
-
fts_solar: np.ndarray,
|
|
284
|
-
order: int,
|
|
285
|
-
grating_constant: float,
|
|
286
|
-
doppler_shift: float,
|
|
287
|
-
) -> float:
|
|
288
|
-
"""
|
|
289
|
-
Model function for profile fitting.
|
|
290
|
-
|
|
291
|
-
Parameters
|
|
292
|
-
----------
|
|
293
|
-
crval1
|
|
294
|
-
Wavelength at crpix1
|
|
295
|
-
|
|
296
|
-
cdelt1
|
|
297
|
-
Spectral dispersion at crpix1
|
|
298
|
-
|
|
299
|
-
incident_light_angle
|
|
300
|
-
Incident angle in degrees
|
|
301
|
-
|
|
302
|
-
resolving_power
|
|
303
|
-
Resolving power -- used to estimate the line spread function (may not be correct off limb)
|
|
304
|
-
|
|
305
|
-
opacity
|
|
306
|
-
Opacity scaling applied to telluric absorption
|
|
307
|
-
|
|
308
|
-
stray_light_frac
|
|
309
|
-
Inferred straylight fraction in the spectrograph --> This scales the lines non-linearly.
|
|
310
|
-
|
|
311
|
-
continuum_amplitude
|
|
312
|
-
Amplitude of the scattered light continuum
|
|
313
|
-
"""
|
|
314
|
-
(
|
|
315
|
-
crval1,
|
|
316
|
-
cdelt1,
|
|
317
|
-
incident_light_angle,
|
|
318
|
-
resolving_power,
|
|
319
|
-
opacity,
|
|
320
|
-
stray_light_frac,
|
|
321
|
-
continuum_amplitude,
|
|
322
|
-
) = parameters
|
|
323
|
-
|
|
324
|
-
# calculate the spectral axis
|
|
325
|
-
# Representations of spectral coordinates in FITS
|
|
326
|
-
# https://ui.adsabs.harvard.edu/abs/2006A%26A...446..747G/abstract
|
|
327
|
-
# https://specreduce.readthedocs.io/en/latest/api/specreduce.utils.synth_data.make_2d_arc_image.html
|
|
328
|
-
|
|
329
|
-
number_of_wave_pix = np.size(spectrum)
|
|
330
|
-
|
|
331
|
-
non_linear_header = {
|
|
332
|
-
"CTYPE1": "AWAV-GRA", # Grating dispersion function with air wavelengths
|
|
333
|
-
"CUNIT1": "nm", # Dispersion units
|
|
334
|
-
"CRPIX1": number_of_wave_pix // 2 + 1, # Reference pixel [pix]
|
|
335
|
-
"PV1_0": grating_constant, # Grating density
|
|
336
|
-
"PV1_1": order, # Diffraction order
|
|
337
|
-
"CRVAL1": crval1, # Reference value [nm] (<<<< TO BE OPTMIZED <<<<<<)
|
|
338
|
-
"CDELT1": cdelt1, # Linear dispersion [nm/pix] (<<<< TO BE OPTMIZED <<<<<<)
|
|
339
|
-
"PV1_2": incident_light_angle, # Incident angle [deg] (<<<< TO BE OPTMIZED <<<<<<)
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
non_linear_wcs = WCS(non_linear_header)
|
|
343
|
-
wavelength_vector = (
|
|
344
|
-
(non_linear_wcs.spectral.pixel_to_world(np.arange(number_of_wave_pix))).to(u.nm).value
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
# Gaussian convolution of the FTS atlas
|
|
348
|
-
fwhm_wavelength = np.divide(crval1, resolving_power)
|
|
349
|
-
sigma_wavelength = fwhm_wavelength / (2.0 * np.sqrt(2.0 * np.log(2)))
|
|
350
|
-
kern_pix = sigma_wavelength / np.abs(cdelt1)
|
|
351
|
-
|
|
352
|
-
# interpolate the telluric spectral atlas onto the new wavelength axis and scale by the opacity value that is being optimized
|
|
353
|
-
fts_atmosphere_interp = np.interp(wavelength_vector, fts_wave, fts_telluric)
|
|
354
|
-
fts_telluric_interp = np.exp(opacity * np.log(fts_atmosphere_interp))
|
|
355
|
-
|
|
356
|
-
# interpolate the solar spectral atlas onto the new wavelength axis and apply a shift according to the Doppler shift due to orbital motions
|
|
357
|
-
fts_solar_interp = np.interp(
|
|
358
|
-
wavelength_vector,
|
|
359
|
-
fts_wave + doppler_shift / (const.c.to("km/s")).value * crval1,
|
|
360
|
-
fts_solar,
|
|
361
|
-
)
|
|
362
|
-
|
|
363
|
-
# apply telluric absorption spectrum to solar spectrum
|
|
364
|
-
fts_modulated = fts_telluric_interp * fts_solar_interp
|
|
365
|
-
# add flat value of straylight contamination
|
|
366
|
-
fts_modulated_with_straylight = (fts_modulated + stray_light_frac) / (
|
|
367
|
-
1.0 + stray_light_frac
|
|
368
|
-
)
|
|
369
|
-
# scale for total intensity of the continuum
|
|
370
|
-
fit_amplitude = fts_modulated_with_straylight * continuum_amplitude
|
|
371
|
-
|
|
372
|
-
# convolution for spectrograph line spread function
|
|
373
|
-
fit_amplitude = gaussian_filter1d(fit_amplitude, kern_pix)
|
|
374
|
-
|
|
375
|
-
# chisquare calculation for fit metric
|
|
376
|
-
res_amplitude = np.sum((spectrum - fit_amplitude) ** 2)
|
|
377
|
-
|
|
378
|
-
return res_amplitude
|
|
379
|
-
|
|
380
|
-
def fit_dispersion_axis_to_FTS(
|
|
381
|
-
self,
|
|
382
|
-
fts_wave: np.ndarray,
|
|
383
|
-
fts_telluric: np.ndarray,
|
|
384
|
-
fts_solar: np.ndarray,
|
|
385
|
-
dispersion: u.Quantity,
|
|
386
|
-
alpha: float,
|
|
387
|
-
doppler_shift: u.Quantity,
|
|
388
|
-
spectrum: np.ndarray,
|
|
389
|
-
order: int,
|
|
390
|
-
grating_constant: float,
|
|
391
|
-
) -> OptimizeResult:
|
|
392
|
-
"""Define the bounds and send the fitting model on its way."""
|
|
393
|
-
parameter_names = (
|
|
394
|
-
"crval1 (wavelength at crpix1)",
|
|
395
|
-
"cdelt1 (spectral dispersion at crpix1)",
|
|
396
|
-
"incident_light_angle",
|
|
397
|
-
"resolving_power",
|
|
398
|
-
"opacity",
|
|
399
|
-
"stray_light_frac",
|
|
400
|
-
"continuum_amplitude",
|
|
401
|
-
)
|
|
402
|
-
crpix1_updated = np.size(spectrum) // 2 + 1
|
|
403
|
-
crval1 = fts_wave[crpix1_updated] # initial guess
|
|
404
|
-
bounds = [
|
|
405
|
-
# [nm[ +\- 0.5 nm range used for finding CRVAL1
|
|
406
|
-
(crval1 - 0.5, crval1 + 0.5),
|
|
407
|
-
# [nm/pix] 5% bounds on the dispersion at CRPIX1
|
|
408
|
-
(
|
|
409
|
-
dispersion.value - 0.05 * dispersion.value,
|
|
410
|
-
dispersion.value + 0.05 * dispersion.value,
|
|
411
|
-
),
|
|
412
|
-
# [radian] Incident angle range is +/- 5 degree from value in header
|
|
413
|
-
(np.rad2deg(alpha) - 5, np.rad2deg(alpha) + 5),
|
|
414
|
-
# resolving power range
|
|
415
|
-
(20000, 125000),
|
|
416
|
-
# opacity factor bounds
|
|
417
|
-
(0.0, 10),
|
|
418
|
-
# straylight fraction
|
|
419
|
-
(0.0, 0.5),
|
|
420
|
-
# continuum intensity correction
|
|
421
|
-
(0.8 * np.nanpercentile(spectrum, 75), 1.2 * np.nanpercentile(spectrum, 75)),
|
|
422
|
-
]
|
|
423
|
-
|
|
424
|
-
for repeat_fit in range(5): # repeat just in case the fitting gets stuck in a local minimum
|
|
425
|
-
fit_result = differential_evolution(
|
|
426
|
-
SPDispersionAxisCorrection.fitness,
|
|
427
|
-
args=(
|
|
428
|
-
spectrum,
|
|
429
|
-
fts_wave,
|
|
430
|
-
fts_telluric,
|
|
431
|
-
fts_solar,
|
|
432
|
-
order,
|
|
433
|
-
grating_constant,
|
|
434
|
-
doppler_shift.value,
|
|
435
|
-
),
|
|
436
|
-
popsize=2,
|
|
437
|
-
maxiter=300,
|
|
438
|
-
bounds=bounds,
|
|
439
|
-
disp=True,
|
|
440
|
-
polish=True,
|
|
441
|
-
tol=1.0e-9,
|
|
442
|
-
)
|
|
443
|
-
if fit_result.fun < 0.03:
|
|
444
|
-
logger.info(" Convergence good based on fit func value")
|
|
445
|
-
break
|
|
446
|
-
|
|
447
|
-
logger.info("Fitted Values:")
|
|
448
|
-
logger.info(" ")
|
|
449
|
-
for p in range(len(parameter_names)):
|
|
450
|
-
logger.info(
|
|
451
|
-
f"Parameter: {parameter_names[p]}, Fit Result: {fit_result.x[p]}, Bounds: {bounds[p]}"
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
fit_amplitude = SPDispersionAxisCorrection.fitness(
|
|
455
|
-
fit_result.x,
|
|
456
|
-
spectrum,
|
|
457
|
-
fts_wave,
|
|
458
|
-
fts_telluric,
|
|
459
|
-
fts_solar,
|
|
460
|
-
order,
|
|
461
|
-
grating_constant,
|
|
462
|
-
doppler_shift.value,
|
|
463
|
-
)
|
|
464
|
-
|
|
465
|
-
return fit_result
|
{dkist_processing_cryonirsp-1.9.0.dist-info → dkist_processing_cryonirsp-1.10.0rc1.dist-info}/WHEEL
RENAMED
|
File without changes
|