SpecProc 1.0.0__tar.gz → 1.0.2__tar.gz

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 (89) hide show
  1. {specproc-1.0.0 → specproc-1.0.2}/PKG-INFO +262 -94
  2. {specproc-1.0.0 → specproc-1.0.2}/README.md +256 -88
  3. specproc-1.0.2/pyproject.toml +72 -0
  4. {specproc-1.0.0 → specproc-1.0.2}/src/SpecProc.egg-info/PKG-INFO +262 -94
  5. {specproc-1.0.0 → specproc-1.0.2}/src/SpecProc.egg-info/SOURCES.txt +22 -8
  6. specproc-1.0.2/src/SpecProc.egg-info/entry_points.txt +5 -0
  7. {specproc-1.0.0 → specproc-1.0.2}/src/SpecProc.egg-info/requires.txt +0 -1
  8. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/__init__.py +1 -1
  9. specproc-1.0.2/src/specproc/__main__.py +8 -0
  10. specproc-1.0.2/src/specproc/calib_data/linelists/fear.fits +0 -0
  11. specproc-1.0.0/src/specproc/calib_data/telescopes/lijiang24hrs/lijiang24_hrs_thar_lines.csv → specproc-1.0.2/src/specproc/calib_data/telescopes/lijiang24hrs/lijiang24_hrs_thar_anchors.csv +563 -550
  12. specproc-1.0.2/src/specproc/calib_data/telescopes/mstg193slit/mstg193slit_anchors_B.csv +35 -0
  13. specproc-1.0.2/src/specproc/calib_data/telescopes/mstg193slit/mstg193slit_anchors_R.csv +39 -0
  14. specproc-1.0.2/src/specproc/calib_data/telescopes/nanshan12/nanshan-thar-highres.txt +69896 -0
  15. specproc-1.0.2/src/specproc/calib_data/telescopes/nanshan12/nanshan-thar-lowres.txt +71 -0
  16. specproc-1.0.2/src/specproc/calib_data/telescopes/nanshan12/nanshan-thar-medres.txt +42429 -0
  17. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/config/config_manager.py +33 -8
  18. specproc-1.0.2/src/specproc/core/anchor_matching.py +1085 -0
  19. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/basic_reduction.py +54 -28
  20. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/data_structures.py +17 -1
  21. specproc-1.0.2/src/specproc/core/line_identification.py +612 -0
  22. specproc-1.0.2/src/specproc/core/nanshan12.py +253 -0
  23. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/order_tracing.py +167 -21
  24. specproc-1.0.2/src/specproc/core/peak_fitting.py +126 -0
  25. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/processing_pipeline.py +76 -88
  26. specproc-1.0.2/src/specproc/core/slit_pipeline.py +1936 -0
  27. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/wave_calibration.py +425 -74
  28. specproc-1.0.2/src/specproc/gui/line_identifier.py +15 -0
  29. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/gui/main_window.py +77 -95
  30. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/gui/settings_dialog.py +54 -71
  31. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/main.py +212 -27
  32. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/plotting/spectra_plotter.py +105 -2
  33. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/utils/airvac.py +38 -20
  34. specproc-1.0.2/src/specproc/utils/completion.py +189 -0
  35. specproc-1.0.2/src/specproc/utils/identify.py +2328 -0
  36. specproc-1.0.2/src/specproc/utils/tool_registry.py +107 -0
  37. specproc-1.0.2/tests/test_anchor_matching.py +212 -0
  38. specproc-1.0.2/tests/test_cli_tools.py +188 -0
  39. specproc-1.0.2/tests/test_identify_auto.py +535 -0
  40. specproc-1.0.2/tests/test_nanshan12.py +160 -0
  41. specproc-1.0.2/tests/test_slit_curvature.py +106 -0
  42. specproc-1.0.0/pyproject.toml +0 -50
  43. specproc-1.0.0/src/SpecProc.egg-info/entry_points.txt +0 -5
  44. specproc-1.0.0/src/specproc/calib_data/telescopes/xinglong216bfosc/BFOSC/345/256/232/346/240/207/347/201/257/350/260/261/350/256/244/350/257/201/346/211/213/345/206/214v171118.pdf +0 -0
  45. specproc-1.0.0/src/specproc/calib_data/telescopes/xinglong216bfosc//346/212/245/345/221/212/345/233/276.docx +0 -0
  46. specproc-1.0.0/src/specproc/calib_data/telescopes/xinglong216hrs/216HRS /347/201/257/350/260/261/350/257/201/350/256/244/346/226/207/344/273/266.pdf +0 -0
  47. specproc-1.0.0/src/specproc/calib_data/telescopes/xinglong216hrs/wlcalib_20211123011_A.png +0 -0
  48. specproc-1.0.0/src/specproc/core/line_identification.py +0 -302
  49. specproc-1.0.0/src/specproc/core/slit_pipeline.py +0 -762
  50. specproc-1.0.0/src/specproc/gui/line_identifier.py +0 -731
  51. {specproc-1.0.0 → specproc-1.0.2}/LICENSE +0 -0
  52. {specproc-1.0.0 → specproc-1.0.2}/setup.cfg +0 -0
  53. {specproc-1.0.0 → specproc-1.0.2}/src/SpecProc.egg-info/dependency_links.txt +0 -0
  54. {specproc-1.0.0 → specproc-1.0.2}/src/SpecProc.egg-info/top_level.txt +0 -0
  55. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/README +0 -0
  56. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/airvac.cl +0 -0
  57. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/argon.dat +0 -0
  58. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/ctiohear.dat +0 -0
  59. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/ctiohenear.dat +0 -0
  60. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/cuar.dat +0 -0
  61. /specproc-1.0.0/src/specproc/calib_data/linelists/FeAr.dat → /specproc-1.0.2/src/specproc/calib_data/linelists/fear.dat +0 -0
  62. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/henear.dat +0 -0
  63. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/henearhres.dat +0 -0
  64. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/idhenear.dat +0 -0
  65. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/krypton.dat +0 -0
  66. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/lowskylines.dat +0 -0
  67. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/ohlines.dat +0 -0
  68. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/skylines.dat +0 -0
  69. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/thar-noao.dat +0 -0
  70. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/thar.dat +0 -0
  71. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/thorium.dat +0 -0
  72. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/vacidhenear.dat +0 -0
  73. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/vacthar.dat +0 -0
  74. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/vacthorium.dat +0 -0
  75. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/calib_data/linelists/xenon.dat +0 -0
  76. /specproc-1.0.0/src/specproc/calib_data/telescopes/xinglong216hrs/xinglong216_thar_lines.csv → /specproc-1.0.2/src/specproc/calib_data/telescopes/xinglong216hrs/xinglong216_thar_anchors.csv +0 -0
  77. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/config/__init__.py +0 -0
  78. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/__init__.py +0 -0
  79. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/de_blazing.py +0 -0
  80. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/extraction.py +0 -0
  81. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/flat_correction.py +0 -0
  82. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/order_stitching.py +0 -0
  83. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/core/scattered_light.py +0 -0
  84. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/gui/__init__.py +0 -0
  85. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/plotting/__init__.py +0 -0
  86. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/utils/__init__.py +0 -0
  87. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/utils/fits_io.py +0 -0
  88. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/utils/image_processing.py +0 -0
  89. {specproc-1.0.0 → specproc-1.0.2}/src/specproc/utils/overscan.py +0 -0
@@ -1,15 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SpecProc
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: A spectral processing tool
5
5
  Author-email: "Niu, Hubiao" <niuhubiao@xao.ac.cn>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/yourusername/specproc
8
- Project-URL: Repository, https://github.com/yourusername/specproc
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/abiao-github/SpecProc
8
+ Project-URL: Repository, https://github.com/abiao-github/SpecProc
9
+ Project-URL: Releases, https://github.com/abiao-github/SpecProc/releases
9
10
  Keywords: spectroscopy,FITS,data-reduction
10
11
  Classifier: Programming Language :: Python :: 3
11
12
  Classifier: Operating System :: OS Independent
12
- Requires-Python: >=3.6
13
+ Requires-Python: >=3.7
13
14
  Description-Content-Type: text/markdown
14
15
  License-File: LICENSE
15
16
  Requires-Dist: numpy
@@ -17,12 +18,13 @@ Requires-Dist: scipy
17
18
  Requires-Dist: astropy
18
19
  Requires-Dist: matplotlib
19
20
  Requires-Dist: PyQt5
20
- Requires-Dist: configparser
21
21
  Dynamic: license-file
22
22
 
23
23
  # SpecProc: PyQt GUI for Spectrograph Data Reduction
24
24
 
25
- ![SpecProc GUI](docs/SpecProc.png)
25
+ **English** | [简体中文](README_CN.md)
26
+
27
+ ![SpecProc GUI](docs/SpecProcGUI.png)
26
28
 
27
29
  A complete PyQt-based graphical interface for reducing slit/chelle spectrograph FITS data.
28
30
 
@@ -48,9 +50,9 @@ A complete PyQt-based graphical interface for reducing slit/chelle spectrograph
48
50
  2. **Apertures Tracing** - Master flat generation and echelle aperture tracing
49
51
  3. **Scattered Light Subtraction** - Inter-aperture background modeling and removal (astropy convolution or spline)
50
52
  4. **2D Flat-Field Correction** - 2D pixel flat correction
51
- 5. **1D Spectrum Extraction** - 1D spectrum extraction for each aperture (sum or optimal)
53
+ 5. **1D Spectrum Extraction** - optimal extraction for each aperture
52
54
  6. **De-blazing** - Blaze function correction
53
- 7. **Wavelength Calibration** - Wavelength calibration applied to both sum and optimal de-blazed 1D spectra
55
+ 7. **Wavelength Calibration** - Wavelength calibration applied to the optimal de-blazed 1D spectra
54
56
  8. **Order Stitching** - Merge overlapping neighboring orders into a continuous 1D spectrum
55
57
 
56
58
  ### Interactive GUI
@@ -91,7 +93,7 @@ specproc
91
93
 
92
94
  ### Method 2: Using conda
93
95
 
94
- Conda provides a complete environment with all dependencies. Two installation options:
96
+ conda is a good fit when you want an isolated environment. SpecProc is **not published on conda-forge**, so the recipe is: create the conda environment, then `pip install` the package into it.
95
97
 
96
98
  #### Option 2.1: Install in existing conda environment
97
99
 
@@ -99,8 +101,8 @@ Conda provides a complete environment with all dependencies. Two installation op
99
101
  # Activate your conda environment
100
102
  conda activate your_environment
101
103
 
102
- # Install SpecProc from conda-forge
103
- conda install -c conda-forge specproc
104
+ # Install SpecProc with pip
105
+ pip install specproc
104
106
 
105
107
  # Launch application
106
108
  specproc
@@ -110,11 +112,12 @@ specproc
110
112
 
111
113
  ```bash
112
114
  # Create new conda environment for SpecProc
113
- conda create -n specproc python=3.8
115
+ conda create -n specproc python=3.11
114
116
  conda activate specproc
115
117
 
116
- # Install SpecProc and all dependencies
117
- conda install -c conda-forge specproc
118
+ # Scientific/GUI dependencies from conda, SpecProc itself from pip
119
+ conda install -c conda-forge numpy scipy astropy matplotlib pyqt -y
120
+ pip install specproc
118
121
 
119
122
  # Launch application
120
123
  specproc
@@ -122,7 +125,7 @@ specproc
122
125
 
123
126
  **Notes:**
124
127
  - Recommended for users who want an isolated environment
125
- - All dependencies are managed by conda
128
+ - Core dependencies are managed by conda; SpecProc itself is installed with pip
126
129
  - Python 3.7-3.11 are supported
127
130
 
128
131
  ### Method 3: Installing from Source
@@ -193,8 +196,8 @@ specproc --config ./specproc.cfg
193
196
  │ │ ├── overscan_corrected/ # Overscan-corrected images and diagnostic plots
194
197
  │ │ ├── bias_subtracted/ # Master bias and bias-corrected images
195
198
  │ │ └── cosmic_corrected/ # Cosmic ray corrected science images (if enabled)
196
- │ ├── step2_flat/ # Step 2: Master flat field, blaze profiles, and diagnostic plots
197
- │ ├── step3_background/ # Step 3: Background model and diagnostic plots
199
+ │ ├── step2_trace/ # Step 2: Master flat field, blaze profiles, and diagnostic plots
200
+ │ ├── step3_scatterlight/ # Step 3: Background model and diagnostic plots
198
201
  │ ├── step5_extraction/ # Step 5: Extracted 1D spectra and diagnostic plots
199
202
  │ ├── step6_deblazing/ # Step 6: De-blazed spectra and diagnostic plots (if saved)
200
203
  │ └── step7_wavelength/ # Step 7: Final wavelength calibrated 1D spectra and plots
@@ -206,7 +209,7 @@ specproc --config ./specproc.cfg
206
209
  **Note**:
207
210
  - ❌ Do NOT run `specproc` in SpecProc source directory (`/path/to/SpecProc`)
208
211
  - ✅ Run `specproc` in your working directory
209
- - ✅ `rawdata` and `output` will be created in your working directory
212
+ - ✅ `output` will be created in your working directory
210
213
 
211
214
  ## Configuration
212
215
 
@@ -272,12 +275,13 @@ rawdata_path = ./20241102_hrs
272
275
  # │ ├── overscan_corrected/ # Overscan-corrected images
273
276
  # │ ├── bias_subtracted/ # Master bias and bias-corrected images
274
277
  # │ └── cosmic_corrected/ # Cosmic ray corrected science images (if enabled)
275
- # ├── step2_flat/ # Step 2: Master flat field with blaze profiles
276
- # ├── step3_background/ # Step 3: Background model
278
+ # ├── step2_trace/ # Step 2: Master flat field with blaze profiles
279
+ # ├── step3_scatterlight/ # Step 3: Background model
277
280
  # ├── step5_extraction/ # Step 5: Extracted 1D spectra (pixel space)
278
281
  # ├── step6_deblazing/ # Step 6: De-blazed spectra (if saved)
279
282
  # └── step7_wavelength/ # Step 7: Final wavelength calibrated 1D spectra
280
283
  output_path = output
284
+ ```
281
285
 
282
286
  #### Path Examples
283
287
 
@@ -317,8 +321,8 @@ Control which processing steps to save intermediate results:
317
321
  # Default is 'yes' for all steps
318
322
  save_overscan = yes # Step 1: Overscan correction (saves to output/step1_basic/overscan_corrected/)
319
323
  save_bias = yes # Step 1: Bias correction (saves to output/step1_basic/bias_subtracted/)
320
- save_flat = yes # Step 2: Flat fielding (saves master flat to output/step2_flat/)
321
- save_background = yes # Step 3: Background subtraction (saves model to output/step3_background/)
324
+ save_flat = yes # Step 2: Flat fielding (saves master flat to output/step2_trace/)
325
+ save_background = yes # Step 3: Background subtraction (saves model to output/step3_scatterlight/)
322
326
  save_cosmic = yes # Step 1: Cosmic ray correction (saves to output/step1_basic/cosmic_corrected/)
323
327
  save_extraction = yes # Step 5: Spectrum extraction (saves to output/step5_extraction/)
324
328
  save_deblaze = yes # Step 6: De-blazing (saves to output/step6_deblazing/)
@@ -327,7 +331,7 @@ save_wlcalib = yes # Step 7: Wavelength calibration (saves solution to
327
331
 
328
332
  **Effect**:
329
333
  - If a step is set to `no`, the corresponding output subdirectory will NOT be created
330
- - Final spectra are always saved to `output/step8_final_spectra/` regardless of these settings
334
+ - Final spectra are always saved to `output/step8_stitching/` regardless of these settings
331
335
  - Diagnostic plots can be saved in corresponding step subdirectories
332
336
  - In GUI, there should be corresponding checkboxes to enable/disable saving
333
337
  - Default: All steps save intermediate results
@@ -353,13 +357,11 @@ linelist_path = calib_data/linelists/
353
357
  # For Xinglong 2.16m HRS: thar-noao.dat is recommended
354
358
  linelist_file = thar-noao.dat
355
359
 
356
- # Use pre-identified calibration files (optional)
357
- use_precomputed_calibration = yes
358
- calibration_path = calib_data/telescopes/xinglong216hrs/
360
+ # Use pre-identified anchor lines (optional)
361
+ anchor_file = calib_data/telescopes/xinglong216hrs/xinglong216_thar_anchors.csv
359
362
 
360
- # Specific calibration file to use (optional)
361
- # Use latest: wlcalib_20211123011_A.fits
362
- calibration_file = wlcalib_20211123011_A.fits
363
+ # Full lamp catalogue used for the final wavelength fit
364
+ full_linelist = calib_data/linelists/thar-noao.dat
363
365
  ```
364
366
 
365
367
  ## Processing Pipeline
@@ -437,16 +439,20 @@ calibration_file = wlcalib_20211123011_A.fits
437
439
  - **Output**: Wavelength-calibrated 1D spectra
438
440
  - **Note**: Establishes the physical wavelength scale for each order.
439
441
 
442
+ #### STEP 8: Order Stitching
443
+ - **Input**: Wavelength-calibrated spectra of all orders
444
+ - **Processing**:
445
+ - Overlap neighbouring orders in the common wavelength range
446
+ - Combine them with an SNR-weighted average
447
+ - **Output**: One continuous, stitched 1D spectrum
448
+ - **Note**: Produces the final science-ready 1D spectrum for absorption-line analysis.
440
449
 
441
450
  ## Usage
442
451
 
443
- ### GUI Mode (Default)
452
+ ### GUI Mode
444
453
 
445
454
  ```bash
446
- # Launch GUI (default mode)
447
- specproc
448
-
449
- # Or explicitly specify GUI mode
455
+ # Launch GUI (must be requested explicitly; the default is CLI)
450
456
  specproc --mode gui
451
457
 
452
458
  # With custom config file
@@ -465,8 +471,8 @@ specproc --config /path/to/config.cfg
465
471
  ### CLI Mode (Command Line)
466
472
 
467
473
  ```bash
468
- # Run CLI mode
469
- specproc --mode cli
474
+ # CLI is the default: process FITS files in the current directory
475
+ specproc
470
476
 
471
477
  # Or with custom config file
472
478
  specproc --mode cli --config /path/to/config.cfg
@@ -474,8 +480,8 @@ specproc --mode cli --config /path/to/config.cfg
474
480
  # Or select a packaged telescope profile by name, and process data with it
475
481
  specproc --mode cli --config XL216_hrs 20241102_hrs
476
482
 
477
- # Without input data, the named profile is copied to ./specproc.cfg instead
478
- # of being used directly, so it can be reviewed/customized first
483
+ # Without input data, the profile config is copied with its packaged filename
484
+ # so it can be reviewed/customized first
479
485
  specproc --config MSTG193_slit
480
486
  ```
481
487
 
@@ -486,23 +492,84 @@ per supported telescope/instrument under `src/specproc/config/` (e.g.
486
492
  to that packaged file automatically — no need to type the full path. Run
487
493
  `specproc --help` to see the list of available profiles.
488
494
 
495
+ When no `--config` is given, CLI processing reads `TELESCOP`/`INSTRUME` from the
496
+ input FITS headers, selects the matching packaged profile, copies it to
497
+ `./specproc.cfg` if that file does not already exist, and uses that working copy.
498
+ The combined profile names currently reserved are `mstg193slit`,
499
+ `xinglong216hrs`, `xinglong216bfosc` and `lijiang24hrs`. The profile can also
500
+ be forced explicitly:
501
+
502
+ ```bash
503
+ specproc --profile mstg193slit raw_dir
504
+ ```
505
+
506
+ If no telescope/instrument metadata is available, create an editable working
507
+ config with `specproc --config` and adjust it for the observation.
508
+ For MSTG data the slit pipeline also selects `mstg193slit_anchors_R.csv` or
509
+ `mstg193slit_anchors_B.csv` from `INSTRUME` when the corresponding file exists.
510
+
511
+ **Nanshan 1.2m fibre echelle** (`--profile nanshan12`, auto-detected from
512
+ `SWOWNER = 'nanshan'`; config `NS12_hrs`): the spectrograph has high, mid and low
513
+ resolution modes that the FITS headers do not distinguish, so with
514
+ `[data] auto_resolution = yes` the input frames are split automatically and each
515
+ group is reduced separately into `output/<high|mid|low>/`:
516
+
517
+ - flat / target / standard frames: by the order spacing of the bright bands
518
+ (autocorrelation of the cross-dispersion profile: about 10-12 px high, 16-17 px mid,
519
+ 85-100 px low);
520
+ - ThAr lamps: by cross-correlating every extracted order with the calibrated,
521
+ flux-normalised reference lamp spectra `nanshan-thar-{high,mid}res.txt` in
522
+ `calib_data/telescopes/nanshan12/` (columns: order, wavelength, normalised flux);
523
+ a lamp matching neither is taken as low resolution;
524
+ - bias frames: by the `high` token in the file name.
525
+
526
+ Step 1 can crop the images (`trim_x_start/end`, `trim_y_start/end`, DS9 1-based, applied
527
+ after `flip_vertical`; a bound < 1 leaves that side open). Cropped frames are written to
528
+ `step1_basic/cropped/` and used by all later steps; the Nanshan profile keeps rows 600-1300.
529
+ Order tracing drops false traces (`reject_false_traces`): traces leaving the image, crossing
530
+ a neighbour, or bending differently from the neighbouring orders (`curvature_tolerance`).
531
+ `seed_columns` / `side_min_coverage` / `max_search_half` let the tracer find orders visible on
532
+ one side only and follow widely spaced curved orders (used automatically for the low mode).
533
+ `exclude_lowest_apertures` / `exclude_highest_apertures` (`[reduce.trace]`, default 0) skip the
534
+ N lowest / highest traces so noise-only orders are not extracted (set to 1 automatically for the Nanshan low mode).
535
+
536
+ The initial wavelength solution of the high/mid groups is not obtained from an anchor
537
+ line table: each extracted lamp order is cross-correlated with the reference spectrum
538
+ (giving the order offset and pixel shift), then the full catalog `thar-noao.dat` is
539
+ matched for the final fit. `nanshan-thar-lowres.txt` lists identified lines
540
+ (order, X, wavelength) and is used as an anchor table. Nanshan frames have the
541
+ orders ascending in the opposite vertical sense, so `[data] flip_vertical = yes` flips
542
+ them in Step 1.
543
+
544
+ **Per-order wavelength fit** (`[reduce.wlcalib] fit_mode = per_order`): by default
545
+ (`global`) one 2D polynomial f(order, x) is fitted to all lines. With `per_order`
546
+ the 2D fit is still made first (outlier rejection, fallback for orders with fewer than
547
+ `order_min_lines` lines or covering less than 60 % of the detector), then every
548
+ well-constrained order is refitted independently with a 1D Chebyshev polynomial of
549
+ degree `order_degree`. The catalog is then rematched with `refine_tolerance` for these
550
+ orders (`refine_iterations` passes) before the final fit.
551
+
489
552
  **Slit mode** (`[telescope] instrument = slit`, used by `MSTG193_slit`): a
490
553
  separate single-aperture pipeline (`core/slit_pipeline.py`) replaces the echelle
491
554
  stages: overscan/bias → pixel flat → cosmic rays → star trace + sky subtraction →
492
- sum/optimal extraction → 1-D wavelength solution. Frame types are taken from file
555
+ optimal extraction → 1-D wavelength solution. Frame types are taken from file
493
556
  names (`frame_type_source = filename`; bias / flat / FeAr / dark, rest = science).
494
557
  Run the red and blue cameras separately (one directory each). Wavelength
495
- calibration needs `[slit] identification_file` (pixel, wavelength rows; candidate
496
- pixels are written to `step7_wavelength/<lamp frame>_peaks.csv`) or `wave_start`/`wave_end`
497
- hints; otherwise spectra are saved on a pixel axis.
558
+ calibration needs `[slit] identification_file` (pixel, wavelength rows; generate it
559
+ with `specproc identify`) or `wave_start`/`wave_end` hints; otherwise
560
+ spectra are saved on a pixel axis. The final 1-D solution uses
561
+ `[slit] wave_poly_type` (`legendre` by default, `chebyshev` or `polynomial` also
562
+ accepted) and `wave_poly_order` (default 5 when enough well-spread lines are available).
498
563
 
499
564
  Slit-mode output layout (same numbering as HRS; steps not needed are omitted):
500
- `step1_basic/{overscan_corrected,bias_subtracted,cosmic_corrected}`, `step2_trace` (slit trace of the master flat: centre and both edges, plus each
501
- science frame's trace = flat centre line + a constant star offset; the same trace
502
- is applied to the science and lamp frames),
503
- `step4_flat_corrected` (master/pixel flat and flat-fielded images), `step5_extraction`
504
- (sky-subtracted images and 1-D spectra of the targets, every lamp frame and the master flat,
505
- all extracted along the master-flat trace), `step7_wavelength`. No scattered-light
565
+ `step1_basic/{overscan_corrected,bias_subtracted,cosmic_corrected}` (each FITS image
566
+ has a matching PDF diagnostic plus `master_bias.pdf`), `step2_trace` (independent traces of the master flat, each lamp frame and each
567
+ science frame, with a per-frame `*_trace.txt` and `*_trace.pdf`),`step4_flat_corrected` (master/pixel flat and flat-fielded images), `step5_extraction`
568
+ (sky-subtracted images, 1-D spectra and an extraction-aperture/sky-region
569
+ diagnostic PDF for each science frame, extracted along its own trace),
570
+ `step7_wavelength` (calibrated target and lamp spectra `*_wave.fits`/`*_wave.pdf`,
571
+ residual plots and a two-page `*_arc.pdf` containing the arc spectrum + matched
572
+ lines/residuals and the R(λ) diagnostic). No scattered-light
506
573
  (step3) or de-blazing (step6) directories are created.
507
574
 
508
575
  **Extraction aperture (slit mode)**: with `[slit] aperture_mode = auto` the spatial FWHM of each
@@ -516,8 +583,72 @@ science frame is measured from the profile stacked along the whole dispersion ax
516
583
  range (window ±`snr_half_window` px; signal = median flux, noise = standard deviation
517
584
  of the residual to a quadratic fit). SNR is a dimensionless ratio, labelled
518
585
  `SNR=xx@position`: the position is in pixels before wavelength calibration
519
- (`step5_extraction/*_spec_pixel.pdf`) and in Å after it (`step7_wavelength/*_spec_wave.pdf`).
520
- Values are annotated on the plots and stored as `SNRPxx`/`SNRWxx` keywords in the `*_spec.fits` table.
586
+ (`step5_extraction/*_pixel.pdf`) and in Å after it (`step7_wavelength/*_wave.pdf`).
587
+ Values are annotated on the plots and stored as `SNRPxx`/`SNRWxx` keywords in the `*_pixel.fits` / `*_wave.fits` table.
588
+
589
+ **Anchor lines (slit mode)**: `specproc identify` identifies the emission lines of an
590
+ extracted lamp spectrum against a reference atlas (the NOIRLAB/KPNO FeAr atlas
591
+ `calib_data/linelists/fear.fits` is bundled) or a text line list. The top panel
592
+ shows the normalized measured lamp spectrum in the upper half (pixel axis on top,
593
+ only peaks above the SNR threshold marked with red inverted triangles) and the
594
+ reference atlas/line list in the lower half (blue, wavelength axis at the bottom);
595
+ the reference is mapped through the current dispersion model. The
596
+ bottom panel shows the residuals of a Legendre or Chebyshev series fitted to the
597
+ identified lines. The resolving power is estimated from the Gaussian FWHM of the
598
+ clean arc lines, R = λ/FWHM, and is shown in a separate R(λ) tab and in the saved diagnostic PDF. The spectrum panel keeps the pixel axis while the residual panel uses wavelength; the two tabs are saved as two PDF pages. The basis, degree and residual-clip threshold are adjustable in
599
+ the window. Press
600
+ **Auto identify** to match all strong peaks, adjust the result by hand if needed
601
+ (click a lamp peak, then the matching reference line; right-click removes a line),
602
+ and save. **Flip x** reverses the displayed pixel axis when wavelength decreases
603
+ with pixel; automatic identification sets it from the fitted dispersion. Saving
604
+ writes a clean anchor CSV — the first two columns (0-based pixel, wavelength in Å)
605
+ are exactly the `[slit] identification_file` format — plus a diagnostic figure
606
+ (spectrum, zoomed observed/reference overlay and residuals). The pipeline then
607
+ extends these anchors to the full `full_linelist` catalogue for the final wavelength
608
+ solution.
609
+
610
+ The final dispersion fit basis is selectable: `--poly-type legendre|chebyshev|polynomial`
611
+ (default `legendre`) and `--poly-order` (default 5, up to 9); the interactive window
612
+ exposes the same basis and degree controls. The slit pipeline reads
613
+ `[slit] wave_poly_type` and `wave_poly_order`.
614
+
615
+ The same engine runs headless with `--auto`:
616
+
617
+ ```bash
618
+ # Interactive: reference atlas + measured lamp; adjust by hand, then save.
619
+ specproc identify \
620
+ --lamp output/step5_extraction/RR2000V_FeAr_0.8silt_0.2s_1_pixel.fits \
621
+ --ref src/specproc/calib_data/linelists/fear.fits \
622
+ --linelist src/specproc/calib_data/linelists/fear.dat \
623
+ --output src/specproc/calib_data/telescopes/mstg193slit/mstg193slit_anchors_R.csv \
624
+ --plot docs/mstg193slit_R_anchor_match.pdf
625
+ # MSTG arm is read from the FITS header (TELESCOP=MOST and
626
+ # INSTRUME=Camera Spectrum-R/B); --arm B is only an explicit override.
627
+
628
+ # Fully automatic, no window (same options; writes both files).
629
+ specproc identify --auto --lamp <lamp.fits> --ref <atlas.fits> \
630
+ --output <ids.csv> --plot <diagnostic.pdf>
631
+ ```
632
+
633
+ `identify` accepts FITS, CSV and TXT inputs. Its residual fit defaults to 3σ clipping based on the inlier RMS; an absolute-Å clipping mode is also available. Anchor and diagnostic outputs default to
634
+ the current working directory (use `--output`/`--plot` to override); anchor CSV columns are
635
+ `pixel, wavelength, snr`. The search scans
636
+ the dispersion curvature and matches the strongest reference lines,
637
+ so it works without manual pairs and without a `wave_start`/`wave_end` hint. Both
638
+ pixel directions are tried, so a spectrum whose wavelength decreases with pixel is
639
+ matched as well; the window then flips its displayed pixel axis to keep wavelength
640
+ increasing to the right. In the
641
+ window, any manual pairs seed the solution and the automatic match then extends them.
642
+ Supplying
643
+ `--config` or `--wave-range` only adds a soft preference for that range; it never cuts the
644
+ reference catalogue, so a slightly wrong hint cannot force a wrong alias. For a
645
+ typical RR2000V frame the cubic extrapolates to ≈3976–11677 Å, while the anchors
646
+ themselves span ≈5912–9784 Å; the selected anchors leave ≈0.3 Å residuals. The blue
647
+ extrapolation has been checked against the night-sky spectrum ([OI] 5577/6300/6363,
648
+ Na I and Hα agree within 0.4 Å); the red end beyond 9800 Å remains approximate.
649
+ Always inspect the two-page diagnostic PDF (spectrum/reference match and residuals; R(λ)) before using the file, and re-run the tool if the grating, slit or camera
650
+ focus changes. The reference atlas is matched to the same number of brightest peaks
651
+ as the observed lamp; lower `--min-snr` if the lamp itself has too few strong peaks.
521
652
 
522
653
  **CLI Workflow**:
523
654
  1. Follow prompts to select files
@@ -525,24 +656,58 @@ Values are annotated on the plots and stored as `SNRPxx`/`SNRWxx` keywords in th
525
656
  3. Monitor console progress
526
657
  4. Check results in output directory
527
658
 
659
+ ### Command-line tools (not part of the pipeline)
660
+
661
+ SpecProc also ships a few small, self-contained commands for preparing and
662
+ inspecting data. They are not part of the reduction pipeline. Each one is
663
+ invoked as a standalone `specproc.<tool>` command (type `specproc.` and press
664
+ Tab to list all three; `specproc <tool> ...` also works):
665
+
666
+ | Command | Purpose |
667
+ |---|---|
668
+ | `specproc.air2vac INPUT OUTPUT` | Convert line-list wavelengths from air to vacuum (Å) |
669
+ | `specproc.vac2air INPUT OUTPUT` | Convert line-list wavelengths from vacuum to air (Å) |
670
+ | `specproc.identify` | Interactive/automatic lamp-line identification: reference atlas + lamp spectrum → anchor CSV + diagnostic figure |
671
+ | `specproc tools` | List the tools above |
672
+
673
+ Run `specproc <tool> --help` for the full option list; `specproc --help` also
674
+ lists the available tools. If the first argument names an existing file or
675
+ directory it is always treated as pipeline input, so a data directory is never
676
+ mistaken for a tool.
677
+
678
+ **Shell completion** (completes tool names, their options and choice values;
679
+ positional file arguments fall back to the shell's filename completion):
680
+
681
+ ```bash
682
+ # bash: add to ~/.bashrc
683
+ eval "$(specproc --completion bash)"
684
+
685
+ # zsh: add to ~/.zshrc
686
+ eval "$(specproc --completion zsh)"
687
+ ```
688
+
528
689
  ## Calibration Data
529
690
 
530
691
  ### Directory Structure
531
692
 
532
- ```
693
+ Calibration data ships with the package under `src/specproc/calib_data/`:
694
+
695
+ ```text
533
696
  calib_data/
534
- ├── linelists/ # Lamp emission line catalogs
535
- │ ├── thar-noao.dat # ThAr lamp lines (Xinglong 2.16m HRS recommended)
536
- │ ├── thar.dat # Standard ThAr lamp lines
537
- │ ├── FeAr.dat # FeAr lamp lines
538
- └── ...
539
- └── telescopes/ # Telescope-specific calibration files
540
- ├── generic/ # Generic configuration template
541
- └── xinglong216hrs/ # Xinglong 2.16m telescope
542
- ├── wlcalib_20141103049.fits
543
- ├── wlcalib_20171202012.fits
544
- ├── wlcalib_20190905028_A.fits
545
- └── wlcalib_20211123011_A.fits
697
+ ├── linelists/ # Lamp emission line lists / atlases
698
+ │ ├── thar-noao.dat # ThAr lamp lines (Xinglong 2.16m HRS recommended)
699
+ │ ├── thar.dat # Standard ThAr lamp lines
700
+ │ ├── fear.dat # FeAr lamp line list (Willmarth)
701
+ │ ├── fear.fits # NOIRLAB/KPNO FeAr atlas spectrum (used by `specproc identify`)
702
+ │ ├── argon.dat / xenon.dat / krypton.dat / thorium.dat
703
+ │ └── skylines.dat / ohline.dat and other auxiliary lists
704
+ └── telescopes/ # Telescope-specific calibration files
705
+ ├── generic/ # Generic configuration template
706
+ ├── xinglong216hrs/ # Xinglong 2.16m HRS: xinglong216_thar_anchors.csv
707
+ ├── xinglong216bfosc/ # Xinglong 2.16m BFOSC
708
+ ├── lijiang24hrs/ # Lijiang 2.4m HRS: lijiang24_hrs_thar_anchors.csv
709
+ ├── mstg193slit/ # Muztagh-Ata 1.93m slit: mstg193slit_anchors_{R,B}.csv
710
+ └── nanshan12/ # Nanshan 1.2m fibre: nanshan-thar-{high,mid,low}res.txt
546
711
  ```
547
712
 
548
713
  ### Lamp Line Lists
@@ -550,7 +715,8 @@ calib_data/
550
715
  **Available linelist files**:
551
716
  - `thar-noao.dat` - ThAr lamp lines (Xinglong 2.16m HRS recommended)
552
717
  - `thar.dat` - Standard ThAr lamp lines
553
- - `FeAr.dat` - FeAr lamp lines
718
+ - `fear.dat` - FeAr lamp lines (Willmarth 3000-10,000 Å)
719
+ - `fear.fits` - NOIRLAB/KPNO FeAr atlas spectrum used by `specproc identify`
554
720
 
555
721
  **Supported lamp types**:
556
722
  - `ThAr` - Thorium-Argon (most common for echelle spectrographs)
@@ -562,11 +728,15 @@ calib_data/
562
728
 
563
729
  ### Telescope Calibrations
564
730
 
565
- **Available calibration files for Xinglong 2.16m HRS**:
566
- - `wlcalib_20141103049.fits` - 2014-11-03 04:50
567
- - `wlcalib_20171202012.fits` - 2017-12-02 01:20
568
- - `wlcalib_20190905028_A.fits` - 2019-09-05 02:50 (version A)
569
- - `wlcalib_20211123011_A.fits` - 2021-11-23 01:10 (version A) - **Latest**
731
+ Each telescope directory holds the **anchor tables** (already-identified pixel/wavelength
732
+ pairs) plus the matching identification notes:
733
+
734
+ | Telescope | Files |
735
+ |---|---|
736
+ | Xinglong 2.16m HRS | `xinglong216_thar_anchors.csv` (+ 216HRS lamp identification PDF) |
737
+ | Lijiang 2.4m HRS | `lijiang24_hrs_thar_anchors.csv` (+ Lijiang 2.4m lamp calibration PDF) |
738
+ | Muztagh-Ata 1.93m slit | `mstg193slit_anchors_R.csv` / `mstg193slit_anchors_B.csv` (each with a PDF) |
739
+ | Nanshan 1.2m fibre | `nanshan-thar-highres.txt` / `-medres.txt` / `-lowres.txt` (order, wavelength, normalised flux) |
570
740
 
571
741
  ### Configuration
572
742
 
@@ -579,9 +749,8 @@ instrument = hrs
579
749
  linelist_type = ThAr
580
750
  linelist_path = calib_data/linelists/
581
751
  linelist_file = thar-noao.dat
582
- use_precomputed_calibration = yes
583
- calibration_path = calib_data/telescopes/xinglong216hrs/
584
- calibration_file = wlcalib_20211123011_A.fits
752
+ full_linelist = calib_data/linelists/thar-noao.dat
753
+ anchor_file = calib_data/telescopes/xinglong216hrs/xinglong216_thar_anchors.csv
585
754
  ```
586
755
 
587
756
  ## Troubleshooting
@@ -619,35 +788,34 @@ cp /path/to/SpecProc/src/specproc/config/default_config.cfg ./specproc.cfg
619
788
 
620
789
  ## Documentation
621
790
 
622
- - See [calib_data/README.md](calib_data/README.md) for calibration data configuration
623
- - See [README_CN.md](README_CN.md) for Chinese documentation
624
- - See [PIPELINE_FLOWCHART.md](PIPELINE_FLOWCHART.md) for detailed processing workflow
791
+ - See [README_CN.md](README_CN.md) for the Chinese documentation(中文文档)
792
+ - See [calib_data/README.md](src/specproc/calib_data/README.md) for calibration data configuration
793
+ - See [docs/](docs/) for screenshots and software evaluation reports
625
794
 
626
795
  ## Project Structure
627
796
 
628
797
  ```
629
798
  SpecProc/
630
799
  ├── README.md # Main documentation
631
- ├── README_CN.md # Main documentation (Chinese)
632
- ├── specproc.cfg.example # Example user configuration
800
+ ├── pyproject.toml # Packaging and console-script entry points
633
801
  ├── install.sh # Installation script
634
- ├── requirements.txt # Python dependencies
635
- ├── run.py # Main entry point
636
- ├── setup.py # Installation configuration
637
802
  ├── LICENSE # License
638
- ├── .gitignore # Git ignore rules
639
- ├── src/
640
- │ └── specproc/ # Source code
641
- │ ├── calib_data/ # Calibration data
642
- │ │ ├── linelists/
643
- │ │ └── telescopes/
644
- │ ├── default_config.cfg # Default configuration
645
- │ ├── gui/ # GUI modules
646
- │ ├── core/ # Core processing
647
- │ ├── config/ # Configuration management
648
- │ ├── utils/ # Utility functions
649
- │ └── plotting/ # Plotting functions
650
- └── test_*.py # Test files
803
+ ├── .gitignore # Git ignore rules
804
+ ├── docs/ # Screenshots, reports and the Chinese manual
805
+ ├── tests/ # pytest tests
806
+ └── src/
807
+ └── specproc/ # Source code
808
+ ├── calib_data/ # Calibration data (line lists, telescope profiles)
809
+ ├── config/ # Configuration management & default configs
810
+ ├── core/ # Reduction pipeline (echelle and long-slit)
811
+ ├── gui/ # Main GUI (main window, settings dialog)
812
+ ├── plotting/ # Plotting helpers
813
+ ├── utils/ # Shared helpers + standalone CLI tools
814
+ │ ├── airvac.py # air <-> vacuum wavelength conversion
815
+ │ ├── identify.py # interactive/automatic line identification (`specproc identify`)
816
+ │ ├── tool_registry.py # registry behind `specproc tools`
817
+ │ └── completion.py # bash/zsh completion support
818
+ └── main.py # `specproc` entry point (GUI + CLI + tools)
651
819
  ```
652
820
 
653
821
  ## License