dkist-processing-visp 3.3.0__py3-none-any.whl → 5.1.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 (71) hide show
  1. dkist_processing_visp/__init__.py +1 -0
  2. dkist_processing_visp/config.py +1 -0
  3. dkist_processing_visp/models/constants.py +52 -21
  4. dkist_processing_visp/models/fits_access.py +20 -0
  5. dkist_processing_visp/models/metric_code.py +10 -0
  6. dkist_processing_visp/models/parameters.py +129 -19
  7. dkist_processing_visp/models/tags.py +1 -0
  8. dkist_processing_visp/models/task_name.py +1 -0
  9. dkist_processing_visp/parsers/map_repeats.py +1 -0
  10. dkist_processing_visp/parsers/modulator_states.py +1 -0
  11. dkist_processing_visp/parsers/polarimeter_mode.py +3 -1
  12. dkist_processing_visp/parsers/raster_step.py +4 -1
  13. dkist_processing_visp/parsers/spectrograph_configuration.py +75 -0
  14. dkist_processing_visp/parsers/time.py +15 -7
  15. dkist_processing_visp/parsers/visp_l0_fits_access.py +19 -8
  16. dkist_processing_visp/parsers/visp_l1_fits_access.py +1 -0
  17. dkist_processing_visp/tasks/__init__.py +1 -0
  18. dkist_processing_visp/tasks/assemble_movie.py +1 -0
  19. dkist_processing_visp/tasks/background_light.py +2 -1
  20. dkist_processing_visp/tasks/dark.py +5 -4
  21. dkist_processing_visp/tasks/geometric.py +132 -20
  22. dkist_processing_visp/tasks/instrument_polarization.py +13 -12
  23. dkist_processing_visp/tasks/l1_output_data.py +203 -0
  24. dkist_processing_visp/tasks/lamp.py +53 -93
  25. dkist_processing_visp/tasks/make_movie_frames.py +8 -6
  26. dkist_processing_visp/tasks/mixin/beam_access.py +1 -0
  27. dkist_processing_visp/tasks/mixin/corrections.py +54 -4
  28. dkist_processing_visp/tasks/mixin/downsample.py +1 -0
  29. dkist_processing_visp/tasks/parse.py +34 -4
  30. dkist_processing_visp/tasks/quality_metrics.py +5 -4
  31. dkist_processing_visp/tasks/science.py +126 -46
  32. dkist_processing_visp/tasks/solar.py +896 -456
  33. dkist_processing_visp/tasks/visp_base.py +2 -0
  34. dkist_processing_visp/tasks/write_l1.py +25 -5
  35. dkist_processing_visp/tests/conftest.py +99 -35
  36. dkist_processing_visp/tests/header_models.py +92 -20
  37. dkist_processing_visp/tests/local_trial_workflows/l0_cals_only.py +4 -23
  38. dkist_processing_visp/tests/local_trial_workflows/l0_polcals_as_science.py +421 -0
  39. dkist_processing_visp/tests/local_trial_workflows/l0_solar_gain_as_science.py +10 -29
  40. dkist_processing_visp/tests/local_trial_workflows/l0_to_l1.py +1 -21
  41. dkist_processing_visp/tests/local_trial_workflows/local_trial_helpers.py +98 -14
  42. dkist_processing_visp/tests/test_assemble_movie.py +2 -3
  43. dkist_processing_visp/tests/test_assemble_quality.py +89 -4
  44. dkist_processing_visp/tests/test_background_light.py +8 -5
  45. dkist_processing_visp/tests/test_dark.py +4 -3
  46. dkist_processing_visp/tests/test_fits_access.py +43 -0
  47. dkist_processing_visp/tests/test_geometric.py +45 -4
  48. dkist_processing_visp/tests/test_instrument_polarization.py +4 -3
  49. dkist_processing_visp/tests/test_lamp.py +22 -26
  50. dkist_processing_visp/tests/test_make_movie_frames.py +4 -4
  51. dkist_processing_visp/tests/test_map_repeats.py +3 -1
  52. dkist_processing_visp/tests/test_parameters.py +122 -21
  53. dkist_processing_visp/tests/test_parse.py +98 -14
  54. dkist_processing_visp/tests/test_quality.py +2 -3
  55. dkist_processing_visp/tests/test_science.py +113 -15
  56. dkist_processing_visp/tests/test_solar.py +318 -99
  57. dkist_processing_visp/tests/test_visp_constants.py +36 -8
  58. dkist_processing_visp/tests/test_workflows.py +1 -0
  59. dkist_processing_visp/tests/test_write_l1.py +17 -3
  60. dkist_processing_visp/workflows/__init__.py +1 -0
  61. dkist_processing_visp/workflows/l0_processing.py +8 -2
  62. dkist_processing_visp/workflows/trial_workflows.py +8 -2
  63. dkist_processing_visp-5.1.1.dist-info/METADATA +552 -0
  64. dkist_processing_visp-5.1.1.dist-info/RECORD +94 -0
  65. docs/conf.py +5 -1
  66. docs/gain_correction.rst +50 -42
  67. dkist_processing_visp/tasks/mixin/line_zones.py +0 -115
  68. dkist_processing_visp-3.3.0.dist-info/METADATA +0 -459
  69. dkist_processing_visp-3.3.0.dist-info/RECORD +0 -90
  70. {dkist_processing_visp-3.3.0.dist-info → dkist_processing_visp-5.1.1.dist-info}/WHEEL +0 -0
  71. {dkist_processing_visp-3.3.0.dist-info → dkist_processing_visp-5.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,94 @@
1
+ changelog/.gitempty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ dkist_processing_visp/__init__.py,sha256=LC8o31oTIro4F7IgwoWalX1W3KcPU27yJhlDUeGqcwA,351
3
+ dkist_processing_visp/config.py,sha256=GMr0CreW4qavbueTtsH_Gx5P52v4yZd2PNKyPmxBKQE,478
4
+ dkist_processing_visp/fonts/Lato-Regular.ttf,sha256=1jbkaDIx-THtoiLViOlE0IK_0726AvkovuRhwPGFslE,656568
5
+ dkist_processing_visp/models/__init__.py,sha256=z2nFVvvIzirxklQ9i5-F1nR-WOgcDttYtog_jx4yN5I,12
6
+ dkist_processing_visp/models/constants.py,sha256=TP9ZefMdJxu-JWePICMZ6riC4bH1Mz4NJY0hAcWAPQ0,6749
7
+ dkist_processing_visp/models/fits_access.py,sha256=8uKaUgtapyED-WgJCeswrIqEGy4Ob6ekBmiyBqF6yIE,573
8
+ dkist_processing_visp/models/metric_code.py,sha256=L_VJ-l5RXsYgcEIOO6hsez1a5oL5FqTnoVKZ0z7NKng,266
9
+ dkist_processing_visp/models/parameters.py,sha256=ynPzU9Clv15tuI_h7OFH4bgngeGP-WJ0I3814lnaKMw,15070
10
+ dkist_processing_visp/models/tags.py,sha256=RKtDlNA9O3LMinUP7BJ3tXWn6CWAARaKhXIVB1EHtg0,3055
11
+ dkist_processing_visp/models/task_name.py,sha256=ykLXcmCBWYguopdBlg_G0X_u-0o_Ugh2117XrCqdbFk,187
12
+ dkist_processing_visp/parsers/__init__.py,sha256=z2nFVvvIzirxklQ9i5-F1nR-WOgcDttYtog_jx4yN5I,12
13
+ dkist_processing_visp/parsers/map_repeats.py,sha256=YuO1VROQLuE-Hn9hSzityjNhIDe-EgQ4kjZV6l9xF2Q,5468
14
+ dkist_processing_visp/parsers/modulator_states.py,sha256=dHAZZaG3i_UUT5FjTg1oJdCBiOKCqkrx1jiQnzp2t2o,3006
15
+ dkist_processing_visp/parsers/polarimeter_mode.py,sha256=vOE8IYlBrgAFGSrDbpUDfHnI3OTPBDpd3U_j5totZb8,625
16
+ dkist_processing_visp/parsers/raster_step.py,sha256=tCmXPhG99z54YVX3X-kLOGDKJRTDJHnDbjNev4An7Pg,3142
17
+ dkist_processing_visp/parsers/spectrograph_configuration.py,sha256=YpMX1NhE7xySx6XB3-0etfzfT_oSiGDphNnxhaW_C3c,3203
18
+ dkist_processing_visp/parsers/time.py,sha256=uudQ5manYdL7SgxqABfFPDzW2iTNrTYF0klqCRsP0CI,4812
19
+ dkist_processing_visp/parsers/visp_l0_fits_access.py,sha256=WDAgMp_70AKmzxGqboKA3McSGgF_mvgsGiihYmK1Nus,1973
20
+ dkist_processing_visp/parsers/visp_l1_fits_access.py,sha256=1MrFfsJjT_7fd1cj8tFr5rHX2JdRSrlwiMCzu-Q8ejY,860
21
+ dkist_processing_visp/tasks/__init__.py,sha256=qlPlahiM9_sCsaIj_wzQpzWkMITJ1dPdT93iV9q-fgg,713
22
+ dkist_processing_visp/tasks/assemble_movie.py,sha256=8UujniXlV_sSGeuISud8wMHihLy6Gc5fKZpwkXLUQB8,3330
23
+ dkist_processing_visp/tasks/background_light.py,sha256=qQ3r1LR5qaOz2qNHnO5_QK8l1zbVP0GaCS3aLqJfNYY,16201
24
+ dkist_processing_visp/tasks/dark.py,sha256=VVitrat08U7e5L1-NVnNNJI_KIx791_DvKEJokvCqXE,4334
25
+ dkist_processing_visp/tasks/geometric.py,sha256=FL9LVnI9XvAQeDFXnD1nwj67ExosuZjBSW2M3CrlCB4,48893
26
+ dkist_processing_visp/tasks/instrument_polarization.py,sha256=uj7iyzM3CiJcbQeF4eKpk_KCoheXaM4FpDI83GYDld4,25854
27
+ dkist_processing_visp/tasks/l1_output_data.py,sha256=vl_c52noozeu4N-BbfpsIHFc5q6JATQ9r4iLa3MDtDI,8347
28
+ dkist_processing_visp/tasks/lamp.py,sha256=HTBob-4Am1ps5ucmX8nSzxV3BqX2ytMcHZ5iyDrljq0,5132
29
+ dkist_processing_visp/tasks/make_movie_frames.py,sha256=fw25ksKiJJNS57XV5a7rHpYGcSkYxS2Qf13Fb1UGNpE,7544
30
+ dkist_processing_visp/tasks/parse.py,sha256=Fe_2svvMSKBup--Ulxbu0uaNW3dzPxQreafMEw0CY6E,7897
31
+ dkist_processing_visp/tasks/quality_metrics.py,sha256=Pw55-PXW0cl39FuNkEQCGGhvI_zMDimwmh-swVPVBD4,8133
32
+ dkist_processing_visp/tasks/science.py,sha256=eQZ5MDJhOD8hhp2huksOkl8Btm8EL15no-LX3o6zBXE,34550
33
+ dkist_processing_visp/tasks/solar.py,sha256=YJFHmpmdV-FSIrjFKMH3eLXZ8KTdZWcZo-_XFf-u9Gs,47624
34
+ dkist_processing_visp/tasks/visp_base.py,sha256=-yC-PVP9AqFeZJshJ_nqZpSyRsZyHWUlugWvkeWkPKA,1412
35
+ dkist_processing_visp/tasks/write_l1.py,sha256=bsDZ0BwoqpTtS_f_rAzUn7Ra8UvYb-kINQhX6BwwFQw,8796
36
+ dkist_processing_visp/tasks/mixin/__init__.py,sha256=z2nFVvvIzirxklQ9i5-F1nR-WOgcDttYtog_jx4yN5I,12
37
+ dkist_processing_visp/tasks/mixin/beam_access.py,sha256=1VSJkH6yMxCiZWdWOp_RJ37fX5ULMYmB_0_ulT7YJpI,870
38
+ dkist_processing_visp/tasks/mixin/corrections.py,sha256=FhLFgD9ZYLZd3SaC3PFF-szrcs-zmdrUYNDUEK-h7JA,7145
39
+ dkist_processing_visp/tasks/mixin/downsample.py,sha256=SvKzY6HJRn-FeyG7O6HPvyOS5dmMu6uPoWkfnpPXpVw,1344
40
+ dkist_processing_visp/tests/README.rst,sha256=rnedwwg25c0lB9Me7cT7QNZA17FYlqCu9ZnjQxR5hi0,12502
41
+ dkist_processing_visp/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ dkist_processing_visp/tests/conftest.py,sha256=h5K8OyKFKmV6emjDywrS_ZTeWburIyBnZw_3L8uJmnY,18652
43
+ dkist_processing_visp/tests/header_models.py,sha256=80IZgVsEoGbWOG8kvh7BjC2gHqZq9QSEDcjcmW5B4gA,21126
44
+ dkist_processing_visp/tests/test_assemble_movie.py,sha256=T5EZzdB3sNY4HcSkN2W1ZBDaI4a68ZUNqPB-JpANSQ0,2247
45
+ dkist_processing_visp/tests/test_assemble_quality.py,sha256=C5djCoi2aHUCUiaMnyIOB3DVDSCAT1gUx_Q19c_-Q8Q,4280
46
+ dkist_processing_visp/tests/test_background_light.py,sha256=Zvm8s38qx_ybviEhnKqPI4s36VFBJKtsNrp31-o8lEQ,17553
47
+ dkist_processing_visp/tests/test_dark.py,sha256=iKp12bHOOKPf7GAB8iKYpZu1AXFaESAW6C0ua1nVFXA,5552
48
+ dkist_processing_visp/tests/test_downsample.py,sha256=iSmb4PwpZtnVU06tmlko1wwepWueQ3KJ459XYgNIpws,2211
49
+ dkist_processing_visp/tests/test_fits_access.py,sha256=jOaSHDydzPl48SSBxt3z3CtCzBgCmSCc3rZ92CpoAaY,1822
50
+ dkist_processing_visp/tests/test_geometric.py,sha256=H3oqFPHSPfgJVRZUqD1DIs7DanIVei9-oTsJuiHA4SY,13850
51
+ dkist_processing_visp/tests/test_instrument_polarization.py,sha256=ZsYSyXUKfs0dvTwjzssdoHGiJLgQgkc5tnlfs6q4zOo,11833
52
+ dkist_processing_visp/tests/test_lamp.py,sha256=19mRN8drAg0tqQGwSbSUDlpryqYjMvmfv1DCsttxuXk,5124
53
+ dkist_processing_visp/tests/test_make_movie_frames.py,sha256=huQ5n0YneHByKumM_Ye9tekqKeh-F-e6MQoudOP3S-g,2628
54
+ dkist_processing_visp/tests/test_map_repeats.py,sha256=9g3NnvSfn1OqxxYYxTFoOIi1UsCOa6mZjiuGkbxUvTg,7611
55
+ dkist_processing_visp/tests/test_parameters.py,sha256=MBSddKsFmRC4zDZEgpA3y3_sRKriETiPEIhcVoSchTo,8053
56
+ dkist_processing_visp/tests/test_parse.py,sha256=XyH8oCk5C0CWl4ndNIyVjgXLoMg0679s4dj1MGlJs0c,23363
57
+ dkist_processing_visp/tests/test_quality.py,sha256=YW24VjEHoILseFIXZBp4-o7egT26mfT1lafzajVjXu8,6905
58
+ dkist_processing_visp/tests/test_science.py,sha256=KpOYvL86xhSnTCOcVDveE-enDxcj_G4IrUw_wa375tI,23893
59
+ dkist_processing_visp/tests/test_solar.py,sha256=xuKeUrnAeTQoWbL6pUTiRr09jw0O4jYL6-MSCmyF_k4,16789
60
+ dkist_processing_visp/tests/test_trial_create_quality_report.py,sha256=t3de9LMJOqrRaFXAvKV_5sotAfzDR8fZVIrFNRB2I_A,2779
61
+ dkist_processing_visp/tests/test_visp_constants.py,sha256=y2x42Y-dK2lrCPufLAV1KHpu2fQ-FRpe8tSIhfHJEw8,3134
62
+ dkist_processing_visp/tests/test_workflows.py,sha256=qyWxagIDv-MmVN0u3KFswa5HdaHC6uGeJpvgxvPE30E,287
63
+ dkist_processing_visp/tests/test_write_l1.py,sha256=ORNKUvF4RPjXc24HgOzyVsP0BCQ9izi54EqXpjLzHXQ,6574
64
+ dkist_processing_visp/tests/local_trial_workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ dkist_processing_visp/tests/local_trial_workflows/l0_cals_only.py,sha256=1TmvdAn80WKW-2DsuSg9iK6yQ3Urwm9yt5HlVv1dGWE,10649
66
+ dkist_processing_visp/tests/local_trial_workflows/l0_polcals_as_science.py,sha256=geU6Q8ULfIq4Jmj6ORq8mgXYlF8SYrvgZP-0u-4Uz24,17567
67
+ dkist_processing_visp/tests/local_trial_workflows/l0_solar_gain_as_science.py,sha256=cRrLklazesLBHPPbGzVjBXbEQKaCxQfgy1_AgWyZRyo,15820
68
+ dkist_processing_visp/tests/local_trial_workflows/l0_to_l1.py,sha256=cwEdvUGqqSpp4htrxlmyRN2sZBBvVOjomd66DEqTmTA,15191
69
+ dkist_processing_visp/tests/local_trial_workflows/local_trial_helpers.py,sha256=UYGDwvCqzyCzyp44T-vys_JdKuMVRVS7bpWG9gvwnSE,28250
70
+ dkist_processing_visp/workflows/__init__.py,sha256=1-GP9tOzjCxLJtyq0ry_x4dPdArfSso8Hxu65ydPpXQ,103
71
+ dkist_processing_visp/workflows/l0_processing.py,sha256=bzjvoxwjAwUz-k0ebr6dOt9agpMqbfz2RlH11iN2ia4,3333
72
+ dkist_processing_visp/workflows/single_task_workflows.py,sha256=LK4dsshM0-lwy79WaMoTplyCxUyINnP9RU74MG_dhyc,33
73
+ dkist_processing_visp/workflows/trial_workflows.py,sha256=3F7LTsjMmL68F8rmFst9tRFWWEBJVSy_F4-a8KnVzfE,3802
74
+ docs/Makefile,sha256=qnlVz6PuBqE39NfHWuUnHhNEA-EFgT2-WJNNNy9ttfk,4598
75
+ docs/background_light.rst,sha256=FWj8KH7H51BtoqPCJ1A_VIWJkjaXD8-dwM9RdY1rkIc,5147
76
+ docs/changelog.rst,sha256=ZpZPJIyl4nI0Eicku6uSrLdiinNOF2GcZwrvTEsb-Zs,346
77
+ docs/conf.py,sha256=qgWzWK98wj5QHHnNW52fzjCyfibFM_g1DkjB8m2WMAk,2151
78
+ docs/gain_correction.rst,sha256=rQA51C2ZwUAk1lwCbSUpjs1SjhE2HpT-ik1C5UO9XrU,7148
79
+ docs/geometric.rst,sha256=VsAWefgJ1j64Uo1TQ-ltAQ6INgsdS7-_FSvOtm0i17s,7301
80
+ docs/index.rst,sha256=pl8VhwISd-kb1IQi2h7gOySfOhQQl2C71pjTatShGNI,319
81
+ docs/l0_to_l1_visp.rst,sha256=wE1TT7DD93r3kByaFAaT2HO907pjV4YrJ_fzvJFTchw,623
82
+ docs/l0_to_l1_visp_full-trial.rst,sha256=Y6YLkRA5b0tgui5l_WdthCx2wrXjLD8U97XKZHXVVBk,558
83
+ docs/landing_page.rst,sha256=tdxWtmGjO7OUPYvRjgBAI461nubEE61HrtBwPdBeawI,1052
84
+ docs/make.bat,sha256=mBAhtURwhQ7yc95pqwJzlhqBSvRknr1aqZ5s8NKvdKs,4513
85
+ docs/polarization_calibration.rst,sha256=fYdB_FYB7NjvknuQIa3EGc4ZWjeUaBkkeRb8Y1bGihk,5068
86
+ docs/requirements.txt,sha256=Kbl_X4c7RQZw035YTeNB63We6I7pvXFU4T0Uflp2yDY,29
87
+ docs/requirements_table.rst,sha256=_HIbwFpDooM5n0JjiDAbFozGfJuX13smtcoujLFN4Gk,292
88
+ docs/science_calibration.rst,sha256=VN_g7xSjN-nbXhlBaFnPCbNcsc_Qu0207jEUfRAjnBE,2939
89
+ docs/scientific_changelog.rst,sha256=01AWBSHg8zElnodCgAq-hMxhk9CkX5rtEENx4iz0sjI,300
90
+ licenses/LICENSE.rst,sha256=piZaQplkzOMmH1NXg6QIdo9wwo9pPCoHkvm2-DmH76E,1462
91
+ dkist_processing_visp-5.1.1.dist-info/METADATA,sha256=JyDZCiBUnefmBb4TxfqDwyK4USdhKAwhDQo-PcsgZtU,29917
92
+ dkist_processing_visp-5.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
93
+ dkist_processing_visp-5.1.1.dist-info/top_level.txt,sha256=9GHSn-ZMGQxaRNGrPP3HNc5ZkE7ftzluO74Jz5vUSTE,46
94
+ dkist_processing_visp-5.1.1.dist-info/RECORD,,
docs/conf.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Configuration file for the Sphinx documentation builder."""
2
+
2
3
  # -- stdlib imports ------------------------------------------------------------
3
4
  import importlib
4
5
  import sys
@@ -32,7 +33,10 @@ autoapi_dirs = [Path(package.__file__).parent]
32
33
  # autoapi_keep_files = True
33
34
 
34
35
  # -- Options for intersphinx extension -----------------------------------------
35
- intersphinx_mapping = create_intersphinx_mapping(repo_name)
36
+ intersphinx_mapping = create_intersphinx_mapping(repo_name) | {
37
+ "lmfit": ("https://lmfit.github.io/lmfit-py", None),
38
+ "sklearn": ("https://scikit-learn.org/stable/", None),
39
+ }
36
40
  # Remaining sphinx settings are in dkist-sphinx-theme conf.py
37
41
 
38
42
  # -- Project information -------------------------------------------------------
docs/gain_correction.rst CHANGED
@@ -4,8 +4,8 @@ Gain Calibration
4
4
  Introduction
5
5
  ------------
6
6
 
7
- NOTE: The usage of the term "gain" throughout this document refers to total system response of the DKIST/ViSP optical
8
- train; it does NOT refer to the detector gain that has units of ADU / electron. Sometimes the term "flat" is used in
7
+ NOTE: The usage of the term "gain" throughout this document refers to the total system response of the DKIST/ViSP optical
8
+ train; it does NOT refer to the detector gain that has units of ADU / electron. Often the term "flat" is used in
9
9
  a way that is interchangeable with the usage of "gain" in this document.
10
10
 
11
11
  The ViSP gain calibration is broken down into the following steps across two pipeline tasks
@@ -13,20 +13,21 @@ The ViSP gain calibration is broken down into the following steps across two pip
13
13
 
14
14
  #. Subtract dark and :doc:`background <background_light>` signals from all input gain images.
15
15
 
16
- #. Compute an average, equalized lamp gain and mask the hairlines.
16
+ #. Compute an average lamp gain and mask the hairlines.
17
17
 
18
- #. Divide the solar gain by the resulting lamp image and correct for :doc:`geometric </geometric>` rotation/shifts and
18
+ #. Divide the solar gain by the resulting lamp image and correct for :doc:`geometric </geometric>` rotation and
19
19
  spectral curvature.
20
20
 
21
- #. Mask hairlines and compute 2D characteristic solar spectra with spatial median filter.
21
+ #. Separate the true solar spectrum from vignetting effects by fitting a solar atlas to the solar gain data.
22
22
 
23
- #. Re-curve/shift/rotate the characteristic spectra into the same coordinates as the input frames.
23
+ #. Mask hairlines and compute a 2D characteristic solar spectra with a spatial median filter over the vignette-corrected solar gain data.
24
+
25
+ #. Re-curve and rotate the characteristic spectra into the same coordinates as the input frames.
24
26
 
25
27
  #. Remove the characteristic spectra from solar gain images that have NOT had a lamp correction applied.
26
28
 
27
- The result is a final gain image that can be applied to science data. Note that all steps happen separately for every
28
- modulator state and beam. This is because the geometric x/y shifts have been found to be significantly different for each
29
- modulator state and beam.
29
+ The result is a final gain image that can be applied to science data. Note that all steps happen separately for each
30
+ beam to capture the differences in optical response between the two beams.
30
31
 
31
32
  Important Features
32
33
  ------------------
@@ -49,40 +50,53 @@ from all input frames.
49
50
  Average Lamp Frames and Mask Hairlines
50
51
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51
52
 
52
- All lamp frames for a particular modulator state and beam are averaged into a single array. The slit hairlines are then
53
- identified by smoothing the image in the spatial dimension and then computing the relative difference between this smoothed
54
- image and the original image. Any pixels that deviate by a large amount (set by the ``hairline_fraction`` parameter) are
55
- considered to be hairline pixels. These hairline pixels are masked by replacing them with values from the smoothed array.
56
-
57
- Lamp gains for all modulator states are then compared and equalized so each individual modulator state has the same
58
- median as the median of all (pre-equalized) modulator states. This step helps to mitigate any residual polarization that
59
- may exist in input gain images that would otherwise affect the residual continuum polarization in the processed
60
- science frames.
61
-
62
- Finally, all lamp gain images have any spatial intensity gradients removed by normalizing each spatial position by its
63
- median. This removes known gradients caused by the different input illumination of the lamp compared to the Sun.
53
+ All lamp frames for a single beam are averaged into a single array. The slit hairlines are then identified by smoothing
54
+ the image in the spatial dimension and then computing the relative difference between this smoothed image and the
55
+ original image. Any pixels that deviate by a large amount (set by the ``hairline_fraction`` parameter) are considered to
56
+ be hairline pixels. These hairline pixels are masked by replacing them with values from the smoothed array.
64
57
 
65
58
  Prepare and Rectify Solar Frames
66
59
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67
60
 
68
- The averaged modulated lamp frames from the previous step are applied to dark/background subtracted solar gain frames through
69
- division. Then the pre-computed :doc:`geometric </geometric>` correction removes any spectral rotation, x/y shifts, and
70
- spectral curvature (in that order). At the end of this step the dispersion axis will be parallel to a pixel axis and a
71
- single spectral pixel will have the same physical wavelength value for all spatial pixels.
61
+ The averaged lamp frames from the previous step are applied to dark/background subtracted solar gain frames through
62
+ division. Then the pre-computed :doc:`geometric </geometric>` correction removes any spectral rotation and spectral
63
+ curvature (in that order). Note that at this point we do NOT correct for X/Y offsets for two reasons: 1). a separate gain
64
+ is computed for each beam so applying the beam offsets is not necessary, and 2). it has been found that the
65
+ modstate-to-modstate offsets are small enough to ignore when making gain frames. At the end of this step the dispersion
66
+ axis will be parallel to a pixel axis and a single spectral pixel will have the same physical wavelength value for all
67
+ spatial pixels.
68
+
69
+ Separate Solar and Vignette Signals
70
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71
+
72
+ Aperture masks in ViSP cause known vignetting in both the spatial and spectral dimensions and we need to capture this
73
+ vignetting in our final gain images so it can be correctly removed from science data. To separate the spectral vignette
74
+ signature from the true solar spectrum we fit a representative spectrum to a solar atlas with a parameterized continuum.
75
+ The representative spectrum is a spatial median of the rectified solar gain array, and the continuum is parameterized as
76
+ a polynomial with an order set by the ``solar_vignette_initial_continuum_poly_fit_order`` parameter. Atlas fits are
77
+ done with the `solar-wavelength-calibration <https://docs.dkist.nso.edu/projects/solar-wavelength-calibration/en/latest/>`_
78
+ package. We take the fit continuum as a first estimate of the vignette signal in the spectral dimension.
79
+
80
+ This first vignette estimate is then removed from the representative spectrum, thus producing an estimate of the true
81
+ solar signal, and that spectrum is divided from every spatial pixel of the gain array. The residuals capture how the
82
+ vignette signal varies with spatial and spectral position across the chip. We fit these residuals for each spatial pixel
83
+ to compute a fully 2D estimate of the true vignette signal. The order of this polynomial fit is set by the
84
+ ``solar_vignette_spectral_poly_fit_order`` parameter.
72
85
 
73
86
  Compute Characteristic Spectra
74
87
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
75
88
 
76
- First, the slit hairlines are masked using the same method as :ref:`above <hairline-description>`.
89
+ First, the 2D vignette signal is divided from the solar gain array and the slit hairlines are masked using the same
90
+ method as :ref:`above <hairline-description>`.
77
91
 
78
92
  The goal of this step is to derive pure solar spectra, free from any optical effects of the DKIST/ViSP system. By applying
79
- lamp gain frames to our solar images we have already removed a lot of optical effects, but some spatial variations still
80
- remain. Thus, the characteristic spectra is computed by applying a median filter (with width controlled by the
81
- ``solar_spectral_avg_window`` parameter) in the spatial direction. Previously, a single, median spectrum had been used,
82
- but it did not accurately capture small, but important variations in spectral shape along the slit.
93
+ lamp gain and vignette corrections to our solar images we have already removed a lot of optical effects, but some spatial
94
+ variations still remain. Thus, the characteristic spectra is computed by applying a median filter (with width controlled
95
+ by the ``solar_spatial_median_filter_width_px`` parameter) in the spatial direction. Previously, a single, median spectrum had been
96
+ used, but it did not accurately capture small, but important variations in spectral shape along the slit.
83
97
 
84
- Finally, the smooth characteristic spectra has any spatial gradients removed by normalizing each spatial positions by its
85
- median. This ensures that the characteristic spectra contain *only* pure solar spectra, and thus any real spatial
98
+ Finally, the smooth characteristic spectra have any spatial gradients removed by normalizing each spatial position by its
99
+ continuum level. This ensures that the characteristic spectra contain *only* pure solar spectra, and thus any real spatial
86
100
  gradients are preserved in the final gain image. This normalization also ensures the absolute flux of the final
87
101
  gain images is preserved so that science frames will have values relative to average disk center (where the solar images
88
102
  are taken).
@@ -90,21 +104,15 @@ are taken).
90
104
  Un-rectify Characteristic Spectra
91
105
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92
106
 
93
- The characteristic spectra have spectral shifts, x/y offsets, and spectral rotation re-applied to bring them back into
94
- raw input pixel coordinates.
95
-
96
- The spectral curvature is NOT applied using the precomputed curvature. Instead, for each spatial position a new spectral
97
- shift is computed that minimizes the residual of the final gain image at that position. This step is needed because the
98
- characteristic spectra have *slightly* different spectral shapes than the input solar image (see above) and any small
99
- misalignment causes large, sharp residuals in the line wings. By explicitly minimizing final gain residuals we ensure
100
- that the new spectral shifts remove the solar signal as much as possible.
107
+ The characteristic spectra have spectral shifts and spectral rotation re-applied to bring them back into raw input pixel
108
+ coordinates.
101
109
 
102
110
  Remove Characteristic Solar Spectra from Input Solar Frames
103
111
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
104
112
 
105
113
  The dark/background corrected solar gain image is simply divided by the re-distorted characteristic spectra. Because we
106
- do NOT use a solar image with a lamp correction applied, the resulting gain image includes the full optical response of
107
- the system and can be applied directly to the science data.
114
+ do NOT use a solar image with a lamp or vignette correction applied, the resulting gain image includes the full optical
115
+ response of the system and can be applied directly to the science data.
108
116
 
109
117
  As mentioned above, these gain calibration images are not normalized. The result is that L1 science data will have
110
118
  values that are relative to solar disk center (where the solar gain images are observed).
@@ -1,115 +0,0 @@
1
- """Helper functions for line zone determination."""
2
- import numpy as np
3
- import peakutils
4
- import scipy.signal as sps
5
- from dkist_service_configuration.logging import logger
6
-
7
-
8
- class LineZonesMixin:
9
- """Helper functions for line zone determination."""
10
-
11
- def compute_line_zones(
12
- self,
13
- spec_2d: np.ndarray,
14
- prominence: float = 0.2,
15
- width: float = 2,
16
- bg_order: int = 22,
17
- normalization_percentile: int = 99,
18
- rel_height=0.97,
19
- ) -> list[tuple[int, int]]:
20
- """
21
- Identify spectral regions around strong spectra features.
22
-
23
- Parameters
24
- ----------
25
- spec_2d : np.ndarray
26
- Data
27
-
28
- prominence : float
29
- Zone prominence threshold used to identify strong spectral features
30
-
31
- width : float
32
- Zone width
33
-
34
- bg_order : int
35
- Order of polynomial fit used to remove continuum when identifying strong spectral features
36
-
37
- normalization_percentile : int
38
- Compute this percentile of the data along a specified axis
39
-
40
-
41
-
42
- Returns
43
- -------
44
- List
45
- List of regions to remove
46
-
47
- """
48
- logger.info(
49
- f"Finding zones using {prominence=}, {width=}, {bg_order=}, {normalization_percentile=}, and {rel_height=}"
50
- )
51
- # Compute average along slit to improve signal. Line smearing isn't important here
52
- avg_1d = np.mean(spec_2d, axis=1)
53
-
54
- # Convert to an emission spectrum and remove baseline continuum so peakutils has an easier time
55
- em_spec = -1 * avg_1d + avg_1d.max()
56
- em_spec /= np.nanpercentile(em_spec, normalization_percentile)
57
- baseline = peakutils.baseline(em_spec, bg_order)
58
- em_spec -= baseline
59
-
60
- # Find indices of peaks
61
- peak_idxs = sps.find_peaks(em_spec, prominence=prominence, width=width)[0]
62
-
63
- # Find the rough width based only on the height of the peak
64
- # rips and lips are the right and left borders of the region around the peak
65
- _, _, rips, lips = sps.peak_widths(em_spec, peak_idxs, rel_height=rel_height)
66
-
67
- # Convert to ints so they can be used as indices
68
- rips = np.floor(rips).astype(int)
69
- lips = np.ceil(lips).astype(int)
70
-
71
- # Remove any regions that are contained within another region
72
- ranges_to_remove = self.identify_overlapping_zones(rips, lips)
73
- rips = np.delete(rips, ranges_to_remove)
74
- lips = np.delete(lips, ranges_to_remove)
75
-
76
- return list(zip(rips, lips))
77
-
78
- @staticmethod
79
- def identify_overlapping_zones(rips: np.ndarray, lips: np.ndarray) -> list[int]:
80
- """
81
- Identify line zones that overlap with other zones. Any overlap greater than 1 pixel is flagged.
82
-
83
- Parameters
84
- ----------
85
- rips : np.ndarray
86
- Right borders of the region around the peak
87
-
88
- lips : np.ndarray
89
- Left borders of the region around the peak
90
-
91
- Returns
92
- -------
93
- List
94
- List of ranges to be removed
95
- """
96
- all_ranges = [np.arange(zmin, zmax) for zmin, zmax in zip(rips, lips)]
97
- ranges_to_remove = []
98
- for i in range(len(all_ranges)):
99
- target_range = all_ranges[i]
100
- for j in range(i + 1, len(all_ranges)):
101
- if (
102
- np.intersect1d(target_range, all_ranges[j]).size > 1
103
- ): # Allow for a single overlap just to be nice
104
- if target_range.size > all_ranges[j].size:
105
- ranges_to_remove.append(j)
106
- logger.info(
107
- f"Zone ({all_ranges[j][0]}, {all_ranges[j][-1]}) inside zone ({target_range[0]}, {target_range[-1]})"
108
- )
109
- else:
110
- ranges_to_remove.append(i)
111
- logger.info(
112
- f"Zone ({target_range[0]}, {target_range[-1]}) inside zone ({all_ranges[j][0]}, {all_ranges[j][-1]})"
113
- )
114
-
115
- return ranges_to_remove