From 8ae5707130d597872df467486db09ed54bba74bb Mon Sep 17 00:00:00 2001 From: a_anand Date: Thu, 1 Aug 2024 23:31:01 -0700 Subject: [PATCH] docs updated --- README.md | 25 +- docs/_build/doctrees/environment.pickle | Bin 125808 -> 134913 bytes docs/_build/doctrees/fileformat.doctree | Bin 12367 -> 15136 bytes docs/_build/doctrees/index.doctree | Bin 12287 -> 11708 bytes docs/_build/doctrees/installation.doctree | Bin 6938 -> 12052 bytes docs/_build/doctrees/qsoabsfind.doctree | Bin 280828 -> 312310 bytes docs/_build/html/.buildinfo | 2 +- docs/_build/html/_modules/index.html | 2 +- .../html/_modules/qsoabsfind/absfinder.html | 155 +++++++++--- .../_modules/qsoabsfind/absorberutils.html | 87 ++++--- docs/_build/html/_modules/qsoabsfind/ew.html | 15 +- docs/_build/html/_modules/qsoabsfind/io.html | 22 +- .../qsoabsfind/parallel_convolution.html | 88 ++++--- .../_build/html/_modules/qsoabsfind/spec.html | 28 ++- .../html/_modules/qsoabsfind/utils.html | 74 ++++-- docs/_build/html/_sources/fileformat.rst.txt | 27 ++- docs/_build/html/_sources/index.rst.txt | 30 +-- .../_build/html/_sources/installation.rst.txt | 23 +- docs/_build/html/fileformat.html | 29 ++- docs/_build/html/genindex.html | 16 +- docs/_build/html/index.html | 35 +-- docs/_build/html/installation.html | 27 ++- docs/_build/html/modules.html | 4 +- docs/_build/html/objects.inv | Bin 865 -> 856 bytes docs/_build/html/py-modindex.html | 2 +- docs/_build/html/qsoabsfind.html | 228 ++++++++++++------ docs/_build/html/search.html | 2 +- docs/_build/html/searchindex.js | 2 +- docs/fileformat.rst | 25 +- docs/index.rst | 7 +- docs/installation.rst | 23 +- qsoabsfind/spec.py | 8 +- 32 files changed, 638 insertions(+), 348 deletions(-) diff --git a/README.md b/README.md index ad95a72..4ec59bb 100644 --- a/README.md +++ b/README.md @@ -55,21 +55,34 @@ python -m unittest discover -s tests Instructions ------------- -Before you run, please read the `data/datamodel.rst` file. The instructions about the input and output file are provided there. +Before running the program, please read the `data/datamodel.rst` file. The instructions for the input and output files are provided there. I have also provided an example QSO spectra FITS file, `data/qso_test.fits`, which contains 500 continuum-normalized SDSS QSO spectra. You can use this file to test an example run as described below. Running example: ---------------- ```sh -qsoabsfind --input-fits-file path_to_input_fits_file.fits \ - --n-qso 1-1000:10 \ +qsoabsfind --input-fits-file data/qso_test.fits \ + --n-qso 500 \ --absorber MgII \ - --output path_to_output_fits_file.fits \ - --headers KEY1=VALUE1 KEY2=VALUE2 \ + --output test_MgII.fits \ + --headers SURVEY=SDSS AUTHOR=YOUR_NAME \ --n-tasks 16 \ --ncpus 4 ``` +Useful notes: +------------- + +Parallel mode can be memory-intensive if the input FITS file is large in size. As the code accesses the FITS file to read QSO spectra when running in parallel, it can become a bottleneck for memory, and the code may fail. Currently, I suggest the following: + + - **Divide your file into smaller chunks:** Split the FITS file into several smaller files, each containing approximately `N` spectra. Then run the code on these smaller files. + + - **Use a rule of thumb for file size:** Ensure that the size of each individual file is no larger than `total_memory/ncpu` of your node or system. Based on this idea you can decide your `N`. I would suggest `N = 1000`. + + - **Merge results at the end:** After processing, you can merge your results. + +In order to decide the right size of the FITS file, consider the total available memory and the number of CPUs in your system. + Contribution ------------ @@ -93,4 +106,4 @@ Thanks, Abhijeet Anand Lawrence Berkeley National Lab -If you have any questions/suggestions, please feel free to write to abhijeetanand2011@gmail.com +If you have any questions/suggestions, please feel free to write to abhijeetanand2011@gmail.com or, preferably, open a GitHub issue.. diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index 77c4be119c0b1735e3f200b82b033f717ba4d8ed..10eecfff99f88f06c23a330ad189b584a71814eb 100644 GIT binary patch literal 134913 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

L)hW>g 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 diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree index 7ba7a003b8bc4573aea926ddb791771b5549fd59..734206cc50fe4a4b1b54b3435755039e4ff3fa17 100644 GIT binary patch literal 11708 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 literal 12287 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 diff --git a/docs/_build/doctrees/installation.doctree b/docs/_build/doctrees/installation.doctree index f27bae4a6d9edccac5da5422c94108305e2c95c6..bea179bb7d3808c8c117e03d82fcf36807f4883d 100644 GIT binary patch literal 12052 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 delta 431 zcmbOdH_ME*fpsds^hVZNUZx(~$rJfxCNJhy+}zH$iIIs>Z*rc1^yEGcwaF(0rCB35 z85tNR-xZP-FGwuOh%d>H&&(?*Es0OdEGY&OIjNKRg`_zQbqx&+46F<%>j;@jz!c_} zmY}N?om?-(A@1!OX=oef=o9K{r~qUeLD)u^7BjbHlNh>W&{A{ CkbqwR diff --git a/docs/_build/doctrees/qsoabsfind.doctree b/docs/_build/doctrees/qsoabsfind.doctree index efeb7177f9dd2bb993b3c8ba4f7e8fb2e9748501..9fce607ef94c2ac809fd599ae5545d1708ae7a35 100644 GIT binary patch literal 312310 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 literal 280828 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 modules for which code is available

diff --git a/docs/_build/html/_modules/qsoabsfind/absfinder.html b/docs/_build/html/_modules/qsoabsfind/absfinder.html index fb23ccc..fad8e8e 100644 --- a/docs/_build/html/_modules/qsoabsfind/absfinder.html +++ b/docs/_build/html/_modules/qsoabsfind/absfinder.html @@ -73,21 +73,28 @@

Source code for qsoabsfind.absfinder

-import numpy as np
+"""
+This script contains a function to run convolution based absorber finder on a single spectrum.
+"""
+
+import numpy as np
 from functools import reduce
 from operator import add
 from .utils import convolution_fun, vel_dispersion
 from .absorberutils import (
     estimate_local_sigma_conv_array, group_and_weighted_mean_selection_function,
     median_selection_after_combining,
-    remove_Mg_falsely_identified_as_Fe_absorber, z_abs_from_same_metal_absorber,
-    contiguous_pixel_remover, check_error_on_residual, absorber_search_window
+    remove_Mg_falsely_come_from_Fe_absorber, z_abs_from_same_metal_absorber,
+    contiguous_pixel_remover, estimate_snr_for_lines, absorber_search_window
 )
 from .ew import measure_absorber_properties_double_gaussian
-from .config import lines, speed_of_light, oscillator_parameters
+from .config import load_constants
 from .spec import QSOSpecRead
 from numba import jit
 
+constants = load_constants()
+lines, oscillator_parameters, speed_of_light = constants.lines, constants.oscillator_parameters, constants.speed_of_light
+
 
[docs] @jit(nopython=True) @@ -136,9 +143,82 @@

Source code for qsoabsfind.absfinder

     return new_our_z, new_res_arr
+
+[docs] +def read_single_spectrum_and_find_absorber(fits_file, spec_index, absorber, **kwargs): + """ + This function retrieves a single QSO spectrum from a FITS file, processes the data to remove NaNs, + and prepares the spectrum for absorber search within specified wavelength regions + and runs the convolution based adaptive S/N method to detect absorbers in the spectrum. + + Args: + fits_file (str): Path to the FITS file containing normalized QSO spectra. + The file must include extensions for FLUX, ERROR, WAVELENGTH + and METADATA which must contain keyword Z_QSO. + spec_index (int): Index of the quasar spectrum to retrieve from the FITS file. + absorber (str): Name of the absorber to search for (e.g., 'MgII', 'CIV'). + kwargs (dictionary): search parameters used in convolution_method_absorber_finder_in_QSO_spectra() + + Returns: + tuple: Contains lists of various parameters related to detected absorbers. + - index (list): QSO spec index searched + - zabs (list of floats): redshifts of absorbers detected + - params (list of arrays): gaussian fit parameters for each absorber + - errror params (list of arrays): errors on gaussian fit parameters for each absorber + - EW1 (list of floats): Equivalent width of line 1 for each absorber + - EW2 (list of floats): Equivalent width of line 2 for each absorber + - EW total (list of floats): Total Equivalent width of line 1 and line 2 for each absorber + - errors EW1 (list of floats): errors on Equivalent width of line 1 for each absorber + - errors EW2 (list of floats): errors on Equivalent width of line 2 for each absorber + - errors EW total (list of floats): errors on Total Equivalent width of line 1 and line 2 for each absorber + + Raises: + AssertionError: If the sizes of `lam_search`, `unmsk_residual`, and `unmsk_error` do not match. + + Notes: + - This function assumes that the input spectra are already normalized (i.e., flux divided by continuum). + - The wavelength search region is determined dynamically based on the observed wavelength range. + """ + + # Read the specified QSO spectrum from the FITS file + spectra = QSOSpecRead(fits_file, spec_index) + z_qso = spectra.metadata['Z_QSO'] + lam_obs = spectra.wavelength + + # Define the wavelength range for searching the absorber + min_wave, max_wave = lam_obs.min() + 500, lam_obs.max() - 500 + + # Retrieve flux and error data, ensuring consistent dtype for Numba compatibility + residual, error = spectra.flux.astype('float64'), spectra.error.astype('float64') + lam_obs = lam_obs.astype('float64') + + # Remove NaN values from the arrays + non_nan_indices = ~np.isnan(residual) + lam_obs, residual, error = lam_obs[non_nan_indices], residual[non_nan_indices], error[non_nan_indices] + + # Identify the wavelength region for searching the specified absorber + lam_search, unmsk_residual, unmsk_error = absorber_search_window( + lam_obs, residual, error, z_qso, absorber, min_wave, max_wave, verbose=kwargs['verbose']) + + # Verify that the arrays are of equal size + assert lam_search.size == unmsk_residual.size == unmsk_error.size, "Mismatch in array sizes of lam_search, unmsk_residual, and unmsk_error" + + # Print progress for every 5000th spectrum processed + if spec_index % 5000 == 0: + print(f'Detection finished up to spec index = {spec_index}', flush=True) + + + (index_spec, pure_z_abs, pure_gauss_fit, pure_gauss_fit_std, pure_ew_first_line_mean, pure_ew_second_line_mean, pure_ew_total_mean, pure_ew_first_line_error, pure_ew_second_line_error, pure_ew_total_error, redshift_err, sn1_all, sn2_all) = convolution_method_absorber_finder_in_QSO_spectra(spec_index, absorber, lam_obs, residual, error, lam_search, unmsk_residual, unmsk_error, **kwargs) + + return (index_spec, pure_z_abs, pure_gauss_fit, pure_gauss_fit_std, pure_ew_first_line_mean, pure_ew_second_line_mean, pure_ew_total_mean, pure_ew_first_line_error, pure_ew_second_line_error, pure_ew_total_error, redshift_err, sn1_all, sn2_all)
+ + +
[docs] -def convolution_method_absorber_finder_in_QSO_spectra(fits_file, spec_index, absorber='MgII', ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True): +def convolution_method_absorber_finder_in_QSO_spectra(spec_index, absorber='MgII', lam_obs=None, residual=None, error=None, +lam_search=None, unmsk_residual=None, unmsk_error=None, ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, +mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True, verbose=False): """ Detect absorbers with doublet properties in SDSS quasar spectra using a convolution method. This function identifies potential absorbers based on @@ -147,21 +227,37 @@

Source code for qsoabsfind.absfinder

     the redshifts, EWs, and fitting parameters.
 
     Args:
-        fits_file (str): Path to the FITS file containing Normalized QSO spectra (i.e. flux/continuum), must contain FLUX, ERROR (i.e. error/continuum), WAVELENGTH, and TGTDETAILS extensions. In TGTDETAILS, must contain keywords like RA_QSO, DEC_QSO, Z_QSO.
-        spec_index (int): Index of quasar in the spectra matrix.
+        spec_index (int): Index of quasar in the spectra 2D array.
         absorber (str): Absorber name for searching doublets (MgII, CIV). Default is 'MgII'.
+        lam_obs (numpy.array): observed wavelength array.
+        residual (numpy.array): residual (i.e. flux/continuum) array
+        error (numpy.array): error on residuals
+        lam_search (numpy.array): search observed wavelength array (i.e. region where absorber will be looked for).
+        unmsk_residual (numpy.array): search residual array (residuals at search wavelength pixels)
+        unmsk_error (numpy.array): error on residuals array in search wavelength region
         ker_width_pix (list): List of kernel widths in pixels. Default is [3, 4, 5, 6, 7, 8].
         coeff_sigma (float): Coefficient for sigma to apply threshold in the convolved array. Default is 2.5.
         mult_resi (float): Factor to shift the residual up or down. Default is 1.
         d_pix (float): Pixel distance for line separation during Gaussian fitting. Default is 0.6.
         pm_pixel (int): Pixel parameter for local noise estimation (default 200).
-        sn_line1 (float): Signal-to-noise ratio for thresholding for line1.
-        sn_line2 (float): Signal-to-noise ratio for thresholding for line2.
+        sn_line1 (float): Signal-to-noise ratio for thresholding for line1 (default 3).
+        sn_line2 (float): Signal-to-noise ratio for thresholding for line2 (default 3).
         use_covariance (bool): if want to use full covariance of scipy curvey_fit for EW error calculation (default is False)
-        logwave (bool): if wavelength on log scale
+        logwave (bool): if wavelength on log scale (default True for SDSS)
+        verbose (bool): if want to print a lot of outputs for debugging (default False)
 
     Returns:
         tuple: Contains lists of various parameters related to detected absorbers.
+            - index (list): QSO spec index searched
+            - zabs (list): redshifts of absorbers detected
+            - params (list of arrays): gaussian fit parameters for each absorber
+            - errror params (list of arrays): errors on gaussian fit parameters for each absorber
+            - EW1 (list): Equivalent width of line 1 for each absorber
+            - EW2 (list): Equivalent width of line 2 for each absorber
+            - EW total (list): Total Equivalent width of line 1 and line 2 for each absorber
+            - errors EW1 (list): errors on Equivalent width of line 1 for each absorber
+            - errors EW2 (list): errors on Equivalent width of line 2 for each absorber
+            - errors EW total (list): errors on Total Equivalent width of line 1 and line 2 for each absorber
     """
 
     # Constants
@@ -174,11 +270,6 @@ 

Source code for qsoabsfind.absfinder

     else:
         raise ValueError(f"No support for {absorber}, only supports MgII and CIV")
 
-    spectra = QSOSpecRead(fits_file, spec_index)
-    z_qso = spectra.tgtdetails['Z_QSO']
-    lam_obs = spectra.wavelength
-    min_wave, max_wave = lam_obs.min() + 500, lam_obs.max() - 500
-
     line_sep = line2 - line1
     resolution = 69  # km/s for SDSS or DESI
 
@@ -189,23 +280,6 @@ 

Source code for qsoabsfind.absfinder

     bound = ((np.array([2e-2, line1 - bd_ct * d_pix, del_sigma-0.1, 2e-2, line2 - bd_ct * d_pix, del_sigma-0.1])),
              (np.array([1.11, line1 + bd_ct * d_pix, x_sep * del_sigma, 1.11, line2 + bd_ct * d_pix, x_sep * del_sigma])))
 
-    # Print progress
-    if spec_index % 5000 == 0:
-        print(f'Detection finished up to spec index = {spec_index}', flush=True)
-
-    # Retrieve quasar data
-    residual, error = spectra.flux, spectra.error
-    lam_obs, residual, error = lam_obs.astype('float64'), residual.astype('float64'), error.astype('float64') # to  make consistent with numba dtype
-    ind_nonan = ~np.isnan(residual)
-    residual, error = residual[ind_nonan], error[ind_nonan]
-    lam_obs = lam_obs[ind_nonan]
-
-    lam_search, unmsk_residual, unmsk_error = absorber_search_window(
-        lam_obs, residual, error, z_qso, absorber, min_wave, max_wave, verbose=False)
-
-    # Assert that the sizes of the arrays are equal
-    assert lam_search.size == unmsk_residual.size == unmsk_error.size, "Mismatch in array sizes of lam_search, unmsk_residual and unmsk_error"
-
     # Kernel width computation
     width_kernel = np.array([ker * resolution * ((f1 * line1 + f2 * line2) / (f1 + f2)) / (speed_of_light * 2.35) for ker in ker_width_pixels])
 
@@ -219,7 +293,6 @@ 

Source code for qsoabsfind.absfinder

             sigma_cr = estimate_local_sigma_conv_array(conv_arr, pm_pixel=pm_pixel)
             thr = np.nanmedian(conv_arr) - coeff_sigma * sigma_cr
 
-
             conv_arr[np.isnan(conv_arr)] = 1e5
             our_z_ind = conv_arr < thr
             conv_arr[conv_arr == 1e5] = np.nan
@@ -266,7 +339,7 @@ 

Source code for qsoabsfind.absfinder

                     lower_del_lam = line_sep - d_pix
                     upper_del_lam = line_sep + d_pix
 
-                    _, _, fit_param_temp, fit_param_std_temp, EW_first_temp_mean, EW_second_temp_mean, EW_total_temp_mean, EW_first_error_temp, EW_second_error_temp, EW_total_error_temp = measure_absorber_properties_double_gaussian(
+                    z_new, z_new_error, fit_param_temp, fit_param_std_temp, EW_first_temp_mean, EW_second_temp_mean, EW_total_temp_mean, EW_first_error_temp, EW_second_error_temp, EW_total_error_temp = measure_absorber_properties_double_gaussian(
                         index=spec_index, wavelength=lam_obs, flux=residual, error=error, absorber_redshift=[z_abs[m]], bound=bound, use_kernel=absorber, d_pix=d_pix)
 
                     if len(fit_param_temp[0]) > 0 and not np.all(np.isnan(fit_param_temp[0])):
@@ -275,12 +348,12 @@ 

Source code for qsoabsfind.absfinder

                         c0 = gaussian_parameters[1]
                         c1 = gaussian_parameters[4]
                         #S/N estimation
-                        sn1, sn2 = check_error_on_residual(c0, c1, lam_rest, residual, error, logwave)
+                        sn1, sn2 = estimate_snr_for_lines(c0, c1, lam_rest, residual, error, logwave)
                         # resolution corrected velocity dispersion (should be greater than 0)
                         vel1, vel2 = vel_dispersion(c0, c1, gaussian_parameters[2], gaussian_parameters[5], resolution)
 
                         if (gaussian_parameters > bound[0] + 0.01).all() and (gaussian_parameters < bound[1] - 0.01).all() and lower_del_lam <= c1 - c0 <= upper_del_lam and sn1 > sn_line1 and sn2 > sn_line2 and vel1 > 0 and vel2 > 0:
-                            pure_z_abs[m] = z_abs[m]
+                            pure_z_abs[m] = z_new
                             pure_gauss_fit[m] = fit_param_temp[0]
                             pure_gauss_fit_std[m] = fit_param_std_temp[0]
                             pure_ew_first_line_mean[m] = EW_first_temp_mean[0]
@@ -289,7 +362,7 @@ 

Source code for qsoabsfind.absfinder

                             pure_ew_first_line_error[m] = EW_first_error_temp[0]
                             pure_ew_second_line_error[m] = EW_second_error_temp[0]
                             pure_ew_total_error[m] = EW_total_error_temp[0]
-                            redshift_err[m] = z_err[m]
+                            redshift_err[m] = z_new_error
                             sn1_all[m] = sn1
                             sn2_all[m] = sn2
 
@@ -309,10 +382,10 @@ 

Source code for qsoabsfind.absfinder

             sn2_all = sn2_all[valid_indices]
             if len(pure_z_abs) > 0:
                 if absorber=='MgII':
-                    match_abs1 = remove_Mg_falsely_identified_as_Fe_absorber(spec_index, pure_z_abs, lam_obs, residual, error, d_pix=d_pix)
+                    match_abs1 = remove_Mg_falsely_come_from_Fe_absorber(spec_index, pure_z_abs, lam_obs, residual, error, d_pix, logwave)
                 else:
                     match_abs1 = -1*np.ones(len(pure_z_abs))
-                match_abs2 = z_abs_from_same_metal_absorber(pure_z_abs, lam_obs, residual, error, d_pix, use_kernel=absorber)
+                match_abs2 = z_abs_from_same_metal_absorber(pure_z_abs, lam_obs, residual, error, d_pix, absorber, logwave)
                 ind_z = contiguous_pixel_remover(pure_z_abs, sn1_all, sn2_all)
                 sel_indices = (match_abs1 == -1) & (match_abs2 == -1) & (ind_z == -1)  # pure final absorber candidates
 
@@ -355,7 +428,9 @@ 

Source code for qsoabsfind.absfinder

   
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_modules/qsoabsfind/absorberutils.html b/docs/_build/html/_modules/qsoabsfind/absorberutils.html index ec309a6..27157d0 100644 --- a/docs/_build/html/_modules/qsoabsfind/absorberutils.html +++ b/docs/_build/html/_modules/qsoabsfind/absorberutils.html @@ -78,10 +78,13 @@

Source code for qsoabsfind.absorberutils

 """
 
 import numpy as np
-from .config import speed_of_light, lines
+from .config import load_constants
 from .utils import elapsed
 from numba import jit
 
+constants = load_constants()
+lines, speed_of_light = constants.lines, constants.speed_of_light
+
 
[docs] @jit(nopython=True) @@ -109,12 +112,12 @@

Source code for qsoabsfind.absorberutils

     return sigma_cr
-
-[docs] +
+[docs] @jit(nopython=True) -def check_error_on_residual(l1, l2, lam_rest, residual, error, log): +def estimate_snr_for_lines(l1, l2, lam_rest, residual, error, log): """ - Check the error on residuals around specified wavelengths. + Estimate S/N of the doublet lines. Args: l1 (float): First wavelength to check around. @@ -168,40 +171,49 @@

Source code for qsoabsfind.absorberutils

 
 
[docs] -@jit(nopython=False) def group_contiguous_pixel(data, resi, avg): """ - Arrange data into groups where successive elements differ by less than a - given average difference. + Arrange data into groups where successive elements differ by less than the average difference. Args: - data (numpy.ndarray): Array of absorber values for each spectrum. - resi (numpy.ndarray): Corresponding residual values. - avg (float): Average difference threshold for grouping contiguous pixels. + data (np.ndarray): List of absorbers for each spectrum. + resi (np.ndarray): Corresponding residual. + avg (float): Maximum allowed difference to group data. Returns: - tuple: A tuple containing: - - list of grouped data - - list of grouped residuals + tuple: Final list with contiguous pixels grouped, and corresponding residuals if provided. """ + # Check if resi is provided as an array + if resi is not None: + has_residuals = True + else: + has_residuals = False + + # Sort the input data ind_srt = np.argsort(data) sorted_data = data[ind_srt] - sorted_resi = resi[ind_srt] if isinstance(resi, np.ndarray) else None - groups = [[sorted_data[0]]] - resi_groups = [[sorted_resi[0]]] if sorted_resi is not None else None + if has_residuals: + sorted_resi = resi[ind_srt] + + groups = [] + resi_groups = [] + + groups.append([sorted_data[0]]) + if has_residuals: + resi_groups.append([sorted_resi[0]]) for i in range(1, len(sorted_data)): if sorted_data[i] - groups[-1][-1] < avg: groups[-1].append(sorted_data[i]) - if resi_groups is not None: + if has_residuals: resi_groups[-1].append(sorted_resi[i]) else: groups.append([sorted_data[i]]) - if resi_groups is not None: + if has_residuals: resi_groups.append([sorted_resi[i]]) - if resi_groups is not None: + if has_residuals: return groups, resi_groups else: return groups
@@ -316,13 +328,12 @@

Source code for qsoabsfind.absorberutils

 
 
 #@jit(nopython=False)
-
-[docs] -def remove_Mg_falsely_identified_as_Fe_absorber(index, z_after_grouping, lam_obs, residual, error, d_pix): +
+[docs] +def remove_Mg_falsely_come_from_Fe_absorber(index, z_after_grouping, lam_obs, residual, error, d_pix, logwave): """ - Remove any absorber that arises due to Fe 2586, 2600 or vice-versa case - of 2796, 2803 when using Fe kernel line but has already been detected for - the 2796 line, i.e., false positive due to Fe lines. + Remove any MgII absorber that arises falsley due to Fe 2586, 2600 doublet, + i.e., false positive due to Fe lines. Args: z_after_grouping (list): List of absorbers after grouping. @@ -330,6 +341,7 @@

Source code for qsoabsfind.absorberutils

         residual (numpy.ndarray): Residual values.
         error (numpy.ndarray): Error values corresponding to the residuals.
         d_pix (float): Delta pixel value.
+        logwave (bool): if wavelength on log scale (default True for SDSS)
 
     Returns:
         numpy.ndarray: Updated list of absorbers with false positives removed.
@@ -367,10 +379,10 @@ 

Source code for qsoabsfind.absorberutils

 
                 if n_new > 0:
                     lam_rest = lam_obs / (1 + z[p])
-                    sn_fe1, sn_fe2 = check_error_on_residual(fe1, fe2, lam_rest, residual, error)
+                    sn_fe1, sn_fe2 = estimate_snr_for_lines(fe1, fe2, lam_rest, residual, error, logwave)
                     for k in range(n_new):
                         lam_rest = lam_obs / (1 + z[ind_fin[k]])
-                        sn_mg1, sn_mg2 = check_error_on_residual(mg1, mg2, lam_rest, residual, error)
+                        sn_mg1, sn_mg2 = estimate_snr_for_lines(mg1, mg2, lam_rest, residual, error, logwave)
                         if (sn_fe1 > sn_mg1) or (sn_fe1 > sn_mg2) or (sn_fe2 > sn_mg1) or (sn_fe2 > sn_mg2):
                             match_abs[ind_fin[k]] = 1  # False positive MgII absorber due to FeII lines
                         else:
@@ -388,10 +400,10 @@ 

Source code for qsoabsfind.absorberutils

 #@jit(nopython=False)
 
[docs] -def z_abs_from_same_metal_absorber(first_list_z, lam_obs, residual, error, d_pix=0.6, use_kernel='MgII'): +def z_abs_from_same_metal_absorber(first_list_z, lam_obs, residual, error, d_pix=0.6, use_kernel='MgII', logwave=None): """ - Remove any absorber that arises due to the 2803 line but has already - been detected for the 2796 line, exploiting the doublet property of MgII to + Remove any absorber that arises due to the MgII2803 or CIV1550 line but has already + been detected for the MgII2796 or CIV1548 line, exploiting the doublet property of MgII/CIV to remove false positives. Args: @@ -401,6 +413,7 @@

Source code for qsoabsfind.absorberutils

         error (numpy.ndarray): Error values corresponding to the residuals.
         d_pix (float): Pixel distance for line separation during Gaussian fitting. Default is 0.6.
         use_kernel (str, optional): Kernel type (MgII, CIV). Default is 'MgII'.
+        logwave (bool): if wavelength bins are on log scale
 
     Returns:
         numpy.ndarray: Updated list of absorbers with false positives removed.
@@ -426,11 +439,11 @@ 

Source code for qsoabsfind.absorberutils

 
                 if ind_del.size > 0:
                     lam_rest = lam_obs / (1 + z[p])
-                    sn_mg0, _ = check_error_on_residual(mg1, mg2, lam_rest, residual, error)
+                    sn_mg0, _ = estimate_snr_for_lines(mg1, mg2, lam_rest, residual, error, logwave)
 
                     for k in ind_del:
                         lam_rest1 = lam_obs / (1 + z[k])
-                        sn_mg1, _ = check_error_on_residual(mg1, mg2, lam_rest1, residual, error)
+                        sn_mg1, _ = estimate_snr_for_lines(mg1, mg2, lam_rest1, residual, error, logwave)
 
                         if sn_mg0 > sn_mg1:
                             match_abs[k] = 1  # Matched within limits, not true absorbers
@@ -511,8 +524,8 @@ 

Source code for qsoabsfind.absorberutils

     z1 = (fitted_obs_l1 / line1) - 1
     z2 = (fitted_obs_l2 / line2) - 1
 
-    err1 = (std_fitted_obs_l1 / line1) * z1
-    err2 = (std_fitted_obs_l2 / line2) * z2
+    err1 = (std_fitted_obs_l1 / line1)
+    err2 = (std_fitted_obs_l2 / line2)
 
     z_corr = 0.5 * (z1 + z2)  # New redshifts computed using line centers of the first and second Gaussian
     z_err = np.sqrt(0.25 * (err1**2 + err2**2))
@@ -598,7 +611,9 @@ 

Source code for qsoabsfind.absorberutils

   
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_modules/qsoabsfind/ew.html b/docs/_build/html/_modules/qsoabsfind/ew.html index 5f8adb9..9b266c8 100644 --- a/docs/_build/html/_modules/qsoabsfind/ew.html +++ b/docs/_build/html/_modules/qsoabsfind/ew.html @@ -73,11 +73,18 @@

Source code for qsoabsfind.ew

-import numpy as np
+"""
+This script contains a function to fit a given absorption profile with a double gaussian and measure equivalent widths.
+"""
+
+import numpy as np
 from scipy.optimize import curve_fit
-from .config import lines
 from .utils import double_gaussian
 from .absorberutils import redshift_estimate
+from .config import load_constants
+
+constants = load_constants()
+lines = constants.lines
 
 # Example usage within double_curve_fit
 
@@ -350,7 +357,9 @@

Source code for qsoabsfind.ew

   
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_modules/qsoabsfind/io.html b/docs/_build/html/_modules/qsoabsfind/io.html index eceedf2..3becac7 100644 --- a/docs/_build/html/_modules/qsoabsfind/io.html +++ b/docs/_build/html/_modules/qsoabsfind/io.html @@ -73,14 +73,18 @@

Source code for qsoabsfind.io

-import astropy.io.fits as fits
+"""
+This script contains a functions to read and write files.
+"""
+
+import astropy.io.fits as fits
 import numpy as np
 
 
[docs] def read_fits_file(fits_file, index=None): """ - Reads the FLUX, ERROR, WAVELENGTH, and TGTDETAILS extensions from the + Reads the FLUX, ERROR, WAVELENGTH, and METADATA extensions from the FITS file. Args: @@ -88,25 +92,25 @@

Source code for qsoabsfind.io

         index (int, list, or np.ndarray, optional): Index or indices of the rows to load. Default is None.
 
     Returns:
-        tuple: A tuple containing the flux, error, wavelength, and tgtdetails data.
+        tuple: A tuple containing the flux, error, wavelength, and metadata data.
     """
     with fits.open(fits_file, memmap=True) as hdul:
         if index is None:
             flux = hdul['FLUX'].data
             error = hdul['ERROR'].data
             wavelength = hdul['WAVELENGTH'].data
-            tgtdetails = hdul['TGTDETAILS'].data
+            metadata = hdul['METADATA'].data
         else:
             if isinstance(index, int):
                 flux = hdul['FLUX'].data[index].flatten()
                 error = hdul['ERROR'].data[index].flatten()
-                tgtdetails = {name: hdul['TGTDETAILS'].data[index][name] for name in hdul['TGTDETAILS'].data.names}
+                metadata = {name: hdul['METADATA'].data[index][name] for name in hdul['METADATA'].data.names}
             else:
                 flux = hdul['FLUX'].data[index]
                 error = hdul['ERROR'].data[index]
-                tgtdetails = hdul['TGTDETAILS'].data[index]
+                metadata = hdul['METADATA'].data[index]
             wavelength = hdul['WAVELENGTH'].data  # Assuming wavelength is common for all spectra
-    return flux, error, wavelength, tgtdetails
+ return flux, error, wavelength, metadata
@@ -167,7 +171,9 @@

Source code for qsoabsfind.io

   
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_modules/qsoabsfind/parallel_convolution.html b/docs/_build/html/_modules/qsoabsfind/parallel_convolution.html index 62d0177..d825fb0 100644 --- a/docs/_build/html/_modules/qsoabsfind/parallel_convolution.html +++ b/docs/_build/html/_modules/qsoabsfind/parallel_convolution.html @@ -73,21 +73,20 @@

Source code for qsoabsfind.parallel_convolution

-#!/usr/bin/env python
+"""
+This script contains a function that runs the absorber finder in parallel for many spectra.
+"""
 
 import numpy as np
 import argparse
 import time
 from multiprocessing import Pool
-from .absfinder import convolution_method_absorber_finder_in_QSO_spectra
+from .absfinder import read_single_spectrum_and_find_absorber
 from .io import save_results_to_fits
 import re
 import os
 import pkg_resources
-import qsoabsfind
-
-# Ensure config is imported first to set up the environment
-import qsoabsfind.config as config
+from .config import load_constants
 
 def get_package_versions():
     """
@@ -101,14 +100,21 @@ 

Source code for qsoabsfind.parallel_convolution

< return versions -def run_convolution_method_absorber_finder_QSO_spectra(fits_file, spec_index, absorber, ker_width_pixels, coeff_sigma, mult_resi, d_pix, - pm_pixel, sn_line1, sn_line2, use_covariance, logwave): +def run_convolution_method_absorber_finder_QSO_spectra(fits_file, spec_index, absorber, kwargs): """ - Wrapper function to unpack parameters and call the main convolution - method. + Wrapper function to unpack parameters and call the main convolution method. + + Args: + fits_file (str): Path to the FITS file containing Normalized QSO spectra. + spec_indices (list or numpy.array): Indices of quasars in the data matrix. + absorber (str): Absorber name for searching doublets (MgII, CIV). Default is 'MgII'. + kwargs (dictionary): search parameters as described in qsoabsfind.constants() + + Returns: + tuples containing detected absorber details + """ - return convolution_method_absorber_finder_in_QSO_spectra(fits_file, spec_index, absorber, ker_width_pixels, coeff_sigma, mult_resi, d_pix, - pm_pixel, sn_line1, sn_line2, use_covariance, logwave) + return read_single_spectrum_and_find_absorber(fits_file, spec_index, absorber, **kwargs) def parse_qso_sequence(qso_sequence): """ @@ -140,7 +146,7 @@

Source code for qsoabsfind.parallel_convolution

<
[docs] -def parallel_convolution_method_absorber_finder_QSO_spectra(fits_file, spec_indices, absorber='MgII', ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True, n_jobs=1): +def parallel_convolution_method_absorber_finder_QSO_spectra(fits_file, spec_indices, absorber='MgII', ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True, verbose=False, n_jobs=1): """ Run convolution_method_absorber_finder_in_QSO_spectra in parallel using multiprocessing. @@ -158,13 +164,16 @@

Source code for qsoabsfind.parallel_convolution

< sn_line2 (float): Signal-to-noise ratio for thresholding for line2. use_covariance (bool): If want to use full covariance of scipy curve_fit for EW error calculation (default is False). logwave (bool): If wavelength on logscale (default True for SDSS). + verbose (bool): if True will print lots of output for debugging n_jobs (int): Number of parallel jobs to run. Returns: dict: A dictionary containing combined results from all parallel runs. """ - params_list = [(fits_file, spec_index, absorber, ker_width_pixels, coeff_sigma, mult_resi, d_pix, - pm_pixel, sn_line1, sn_line2, use_covariance, logwave) for spec_index in spec_indices] + + kwargs = {'ker_width_pixels': ker_width_pixels, 'coeff_sigma': coeff_sigma, 'mult_resi': mult_resi, 'd_pix': d_pix, 'pm_pixel': pm_pixel, 'sn_line1': sn_line1, 'sn_line2': sn_line2, 'use_covariance': use_covariance, 'logwave': logwave, 'verbose': verbose} + + params_list = [(fits_file, spec_index, absorber, kwargs) for spec_index in spec_indices] # Run the jobs in parallel with Pool(processes=n_jobs) as pool: @@ -227,7 +236,14 @@

Source code for qsoabsfind.parallel_convolution

< # Set the environment variable for the constants file if args.constant_file: - os.environ['QSO_CONSTANTS_FILE'] = args.constant_file + if not os.path.isabs(args.constant_file): + args.constant_file = os.path.abspath(os.path.join(os.getcwd(), args.constant_file)) + os.environ['QSO_CONSTANTS_FILE'] = args.constant_file + print(f"INFO: Using user-provided constants from: {args.constant_file}") + + print(f"INFO: QSO_CONSTANTS_FILE: {os.environ['QSO_CONSTANTS_FILE']}") + # set the new constants + constants = load_constants() # Prepare headers headers = {} @@ -238,15 +254,15 @@

Source code for qsoabsfind.parallel_convolution

< # Add search parameters and package versions to headers headers.update({ 'ABSORBER': {"value": args.absorber, "comment": 'Absorber name'}, - 'KERWIDTH': {"value": str(config.search_parameters[args.absorber]["ker_width_pixels"]), "comment": 'Kernel width in pixels'}, - 'COEFFSIG': {"value": config.search_parameters[args.absorber]["coeff_sigma"], "comment": 'Coefficient for sigma threshold'}, - 'MULTRE': {"value": config.search_parameters[args.absorber]["mult_resi"], "comment": 'Multiplicative factor for residuals'}, - 'D_PIX': {"value": config.search_parameters[args.absorber]["d_pix"], "comment": 'toloerance for line separation (in Ang)'}, - 'PM_PIXEL': {"value": config.search_parameters[args.absorber]["pm_pixel"], "comment": 'Pixel parameter for local noise estimation'}, - 'SN_LINE1': {"value": config.search_parameters[args.absorber]["sn_line1"], "comment": 'S/N threshold for first line'}, - 'SN_LINE2': {"value": config.search_parameters[args.absorber]["sn_line2"], "comment": 'S/N threshold for second line'}, - 'EWCOVAR': {"value": config.search_parameters[args.absorber]["use_covariance"], "comment": 'Use covariance for EW error calculation'}, - 'LOGWAVE': {"value": config.search_parameters[args.absorber]["logwave"], "comment": 'Use log wavelength scaling'} + 'KERWIDTH': {"value": str(constants.search_parameters[args.absorber]["ker_width_pixels"]), "comment": 'Kernel width in pixels'}, + 'COEFFSIG': {"value": constants.search_parameters[args.absorber]["coeff_sigma"], "comment": 'Coefficient for sigma threshold'}, + 'MULTRE': {"value": constants.search_parameters[args.absorber]["mult_resi"], "comment": 'Multiplicative factor for residuals'}, + 'D_PIX': {"value": constants.search_parameters[args.absorber]["d_pix"], "comment": 'toloerance for line separation (in Ang)'}, + 'PM_PIXEL': {"value": constants.search_parameters[args.absorber]["pm_pixel"], "comment": 'Pixel parameter for local noise estimation'}, + 'SN_LINE1': {"value": constants.search_parameters[args.absorber]["sn_line1"], "comment": 'S/N threshold for first line'}, + 'SN_LINE2': {"value": constants.search_parameters[args.absorber]["sn_line2"], "comment": 'S/N threshold for second line'}, + 'EWCOVAR': {"value": constants.search_parameters[args.absorber]["use_covariance"], "comment": 'Use covariance for EW error calculation'}, + 'LOGWAVE': {"value": constants.search_parameters[args.absorber]["logwave"], "comment": 'Use log wavelength scaling'} }) package_versions = get_package_versions() @@ -264,15 +280,15 @@

Source code for qsoabsfind.parallel_convolution

< # Run the convolution method in parallel results = parallel_convolution_method_absorber_finder_QSO_spectra( args.input_fits_file, spec_indices, absorber=args.absorber, - ker_width_pixels=config.search_parameters[args.absorber]["ker_width_pixels"], - coeff_sigma=config.search_parameters[args.absorber]["coeff_sigma"], - mult_resi=config.search_parameters[args.absorber]["mult_resi"], - d_pix=config.search_parameters[args.absorber]["d_pix"], - pm_pixel=config.search_parameters[args.absorber]["pm_pixel"], - sn_line1=config.search_parameters[args.absorber]["sn_line1"], - sn_line2=config.search_parameters[args.absorber]["sn_line2"], - use_covariance=config.search_parameters[args.absorber]["use_covariance"], - logwave=config.search_parameters[args.absorber]["logwave"], n_jobs=args.n_tasks * args.ncpus + ker_width_pixels=constants.search_parameters[args.absorber]["ker_width_pixels"], + coeff_sigma=constants.search_parameters[args.absorber]["coeff_sigma"], + mult_resi=constants.search_parameters[args.absorber]["mult_resi"], + d_pix=constants.search_parameters[args.absorber]["d_pix"], + pm_pixel=constants.search_parameters[args.absorber]["pm_pixel"], + sn_line1=constants.search_parameters[args.absorber]["sn_line1"], + sn_line2=constants.search_parameters[args.absorber]["sn_line2"], + use_covariance=constants.search_parameters[args.absorber]["use_covariance"], + logwave=constants.search_parameters[args.absorber]["logwave"], verbose=constants.search_parameters[args.absorber]["verbose"], n_jobs=args.n_tasks * args.ncpus ) # Save the results to a FITS file @@ -295,7 +311,9 @@

Source code for qsoabsfind.parallel_convolution

<
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_modules/qsoabsfind/spec.html b/docs/_build/html/_modules/qsoabsfind/spec.html index 2b137fd..879eb37 100644 --- a/docs/_build/html/_modules/qsoabsfind/spec.html +++ b/docs/_build/html/_modules/qsoabsfind/spec.html @@ -73,7 +73,11 @@

Source code for qsoabsfind.spec

-from .io import read_fits_file
+"""
+This script contains a classes and functions to read a given spectra fits files.
+"""
+
+from .io import read_fits_file
 from .utils import elapsed
 import time
 
@@ -81,7 +85,7 @@ 

Source code for qsoabsfind.spec

 [docs]
 class QSOSpecRead:
     """
-    A class to read and handle QSO spectra from a FITS file containing FLUX, ERROR, WAVELENGTH, and TGTDETAILS extensions."""
+    A class to read and handle QSO spectra from a FITS file containing FLUX, ERROR, WAVELENGTH, and METADATA extensions."""
 
 
[docs] @@ -97,7 +101,7 @@

Source code for qsoabsfind.spec

         self.flux = None
         self.error = None
         self.wavelength = None
-        self.tgtdetails = None
+        self.metadata = None
         self.index = index
         self.read_fits()
@@ -110,20 +114,20 @@

Source code for qsoabsfind.spec

         operation.
         """
         start_time = time.time()
-        self.flux, self.error, self.wavelength, self.tgtdetails = read_fits_file(self.fits_file, self.index)
+        self.flux, self.error, self.wavelength, self.metadata = read_fits_file(self.fits_file, self.index)
         elapsed(start_time, "\nTime taken to read FITS file")
-
-[docs] - def get_tgtdetails(self): +
+[docs] + def get_metadata(self): """ - Returns the TGTDETAILS data with keyword handling. + Returns the METADATA data with keyword handling. Returns: - dict: The tgtdetails data with keywords. + dict: The metadata data with keywords. """ - details_dict = {key: self.tgtdetails[key] for key in self.tgtdetails.dtype.names} + details_dict = {key: self.metadata[key] for key in self.metadata.dtype.names} return details_dict
@@ -136,7 +140,9 @@

Source code for qsoabsfind.spec

   
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_modules/qsoabsfind/utils.html b/docs/_build/html/_modules/qsoabsfind/utils.html index 05e6873..a4cd041 100644 --- a/docs/_build/html/_modules/qsoabsfind/utils.html +++ b/docs/_build/html/_modules/qsoabsfind/utils.html @@ -73,10 +73,14 @@

Source code for qsoabsfind.utils

-import time
+"""
+This script contains some utility functions.
+"""
+
+import time
 #import logging
 import numpy as np
-from .config import lines, amplitude_dict, speed_of_light
+from .config import load_constants
 import matplotlib.pyplot as plt
 import os
 
@@ -86,6 +90,9 @@ 

Source code for qsoabsfind.utils

 # Set the logging level for Matplotlib to WARNING to suppress DEBUG messages
 #logging.getLogger('matplotlib').setLevel(logging.WARNING)
 
+constants = load_constants()
+lines, amplitude_dict, speed_of_light = constants.lines, constants.amplitude_dict, constants.speed_of_light
+
 
[docs] def elapsed(start, msg): @@ -322,37 +329,64 @@

Source code for qsoabsfind.utils

 
 
[docs] -def plot_absorber(lam, residual, absorber, zabs, xlabel='obs wave (ang)', ylabel='residual', title='QSO', plot_filename=None): +def plot_absorber(lam, residual, absorber, zabs, xlabel='obs wave (ang)', ylabel='residual', title='QSO', plot_filename=None, zoom=False): """ Saves a plot of spectra with absorber in the current working directory. Args: - lam (array-like): observed wavelength. - residual (array-like): residual. - absorber (str): e.g. MgII, CIV - zabs(list): list of absorbers - xlabel (str): The label for the x-axis. Default is 'X-axis'. - ylabel (str): The label for the y-axis. Default is 'Y-axis'. - title (str): The title of the plot. Default is 'Plot Title'. - plot_filename (str): if provided, will save the plot + lam (array-like): Observed wavelength. + residual (array-like): Residual flux. + absorber (str): Type of absorber, e.g., 'MgII', 'CIV'. + zabs (list): List of absorber redshifts. + xlabel (str): The label for the x-axis. Default is 'obs wave (ang)'. + ylabel (str): The label for the y-axis. Default is 'residual'. + title (str): The title of the plot. Default is 'QSO'. + plot_filename (str): If provided, will save the plot to the given filename. + zoom (bool): If True, adds an inset plot to show a zoomed-in version of the absorber lines. """ - # Create the plot - plt.figure(figsize=(12,4)) + # Create the main plot + plt.figure(figsize=(12, 4)) plt.plot(lam, residual, ls='-', lw=1.5) - if absorber=='MgII': + + # Determine the absorber line labels + if absorber == 'MgII': l1, l2 = 'MgII_2796', 'MgII_2803' - if absorber=='CIV': + elif absorber == 'CIV': l1, l2 = 'CIV_1548', 'CIV_1550' + else: + raise ValueError(f"Unsupported absorber type: {absorber}") + + # Plot vertical lines for the absorber lines for z in zabs: - x1, x2 = lines[l1]*(1+z), lines[l2]*(1+z) - plt.axvline(x = x1, color='r', ls='--') - plt.axvline(x = x2, color='r', ls='--') + x1, x2 = lines[l1] * (1 + z), lines[l2] * (1 + z) + plt.axvline(x=x1, color='r', ls='--', label=f'{l1} z={z:.3f}') + plt.axvline(x=x2, color='r', ls='--', label=f'{l2} z={z:.3f}') + plt.xlabel(xlabel) plt.ylabel(ylabel) plt.title(title) plt.grid(True) plt.ylim(-1, 2) + # Add inset zoomed plot if requested + if zoom: + sep = 25 + ax_inset = plt.gca().inset_axes([0.6, 0.15, 0.35, 0.4]) # position: [x0, y0, width, height] + for z in zabs: + x1, x2 = lines[l1] * (1 + z), lines[l2] * (1 + z) + mask = (lam > x1 - sep) & (lam < x2 + sep) # zoom range around the lines + ax_inset.plot(lam[mask], residual[mask], ls='-', lw=1.5) + ax_inset.axvline(x=x1, color='r', ls='--') + ax_inset.axvline(x=x2, color='r', ls='--') + ax_inset.set_xlim([x1 - sep, x2 + sep]) + #Determine appropriate y-limits for inset based on data + y_min, y_max = residual[mask].min(), residual[mask].max() + y_margin = 0.2 * (y_max - y_min) # Add a margin for better visibility + ax_inset.set_ylim(y_min - y_margin, y_max + y_margin) + ax_inset.set_title(f'Zoomed-In {absorber} Lines') + ax_inset.grid(True) + + # Save or display the plot if plot_filename is not None: # Get the current working directory current_dir = os.getcwd() @@ -377,7 +411,9 @@

Source code for qsoabsfind.utils

   
-

© Copyright .

+

© Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:18:45.166774. +

Built with Sphinx using a diff --git a/docs/_build/html/_sources/fileformat.rst.txt b/docs/_build/html/_sources/fileformat.rst.txt index 6203820..e6a107a 100644 --- a/docs/_build/html/_sources/fileformat.rst.txt +++ b/docs/_build/html/_sources/fileformat.rst.txt @@ -9,18 +9,29 @@ The input `fits file` must have the following HDU extensions: - **FLUX**: Should ideally contain the residual spectra (usually the flux/continuum, i.e., the continuum normalized spectra). - **WAVELENGTH**: Observed wavelength (in Angstroms). - **ERROR**: Error on residuals. -- **TGTDETAILS**: Spectral details (such as Z_QSO, RA_QSO, DEC_QSO). +- **METADATA**: Spectral details (such as Z_QSO, RA_QSO, DEC_QSO). + +I have also provided an example QSO spectra FITS file, `data/qso_test.fits`, which contains 500 continuum-normalized SDSS QSO spectra. You can use this file to test an example run as described below. Constant File (Optional) ------------------------ -The user-defined **constant-file** must follow the same structure as the `qsoabsfind.constants` file, otherwise, the code will fail. If you want to use the default search parameters, you can run the tool without the `constant-file` option. +Before using your own constants file, please set an environment variable `QSO_CONSTANTS_FILE` in your `bashrc` or `zshrc` file, and point it to the `qsoabsfind.constants` file. Since the code dynamically loads constants from a new file, it is important to define this environment variable. + +The user-defined **constants file** must follow the same structure as the `qsoabsfind.constants `_ file; otherwise, the code will fail. If you want to use the default search parameters, you can run the tool without specifying the `constant-file` option. Then run `qsoabsfind` with the required FITS file. If using a custom constant file, include it in the command: :: - qsoabsfind --input [--constant-file ] --output + qsoabsfind --input-fits-file data/qso_test.fits \ + --n-qso 500 \ + --absorber MgII \ + --output test_MgII.fits \ + --headers SURVEY=SDSS AUTHOR=YOUR_NAME \ + --n-tasks 16 \ + --ncpus 4 + --constant-file path_to_your_file Output FITS File Structure -------------------------- @@ -29,11 +40,11 @@ The **output** `fits file` will have the `ABSORBER` HDU, containing arrays such - **INDEX_SPEC**: Index of quasar (can be used to read the RA, DEC, and Z of QSOs). - **Z_ABS**: Redshift of absorber. -- **${METAL}_${line}_EW**: Rest-frame equivalent widths (EWs) of absorber lines (e.g., MgII 2796, 2803 or CIV 1548, 1550) in Angstroms. -- **${METAL}_${line}_EW_ERROR**: Uncertainties in rest-frame EWs of absorber lines in Angstroms. +- **${METAL}_${LINE}_EW**: Rest-frame equivalent widths (EWs) of absorber lines (e.g., MgII 2796, 2803 or CIV 1548, 1550) in Angstroms. +- **${METAL}_${LINE}_EW_ERROR**: Uncertainties in rest-frame EWs of absorber lines in Angstroms. - **Z_ABS_ERR**: Measured error in the redshift of the absorber. - **GAUSS_FIT**: Rest-frame fitting parameters of double Gaussian to the absorber doublet (the width can be used to measure the velocity dispersion). - **GAUSS_FIT_STD**: Uncertainties in rest-frame fitting parameters of double Gaussian to the absorber doublet. -- **SN_${METAL}_${line}**: Signal-to-noise ratio of the lines. -- **${metal}_EW_TOTAL**: Total EW of the lines in Angstroms. -- **${metal}_EW_TOTAL_ERROR**: Uncertainties in total EW of the lines in Angstroms. +- **SN_${METAL}_${LINE}**: Signal-to-noise ratio of the lines. +- **${METAL}_EW_TOTAL**: Total EW of the lines in Angstroms. +- **${METAL}_EW_TOTAL_ERROR**: Uncertainties in total EW of the lines in Angstroms. diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt index 050a37e..d7ddaa2 100644 --- a/docs/_build/html/_sources/index.rst.txt +++ b/docs/_build/html/_sources/index.rst.txt @@ -26,38 +26,22 @@ Features GitHub repository ----------------- -The source code is available at Please see the `qsoabsfind repo `_. +The source code is available on GitHub. Please see the `qsoabsfind `_ repo. Citation -------- -Please cite `Anand, Nelson & Kauffmann 2021 `_ if you find this code useful in your research. The BibTeX entry for the paper is: - -.. code-block:: sh - - @ARTICLE{2021MNRAS.504...65A, - author = {{Anand}, Abhijeet and {Nelson}, Dylan and {Kauffmann}, Guinevere}, - title = "{Characterizing the abundance, properties, and kinematics of the cool circumgalactic medium of galaxies in absorption with SDSS DR16}", - journal = {\mnras}, - keywords = {galaxies: evolution, galaxies: formation, large-scale structure of Universe, Astrophysics - Astrophysics of Galaxies}, - year = 2021, - month = jun, - volume = {504}, - number = {1}, - pages = {65-88}, - doi = {10.1093/mnras/stab871}, - archivePrefix = {arXiv}, - eprint = {2103.15842}, - primaryClass = {astro-ph.GA}, - adsurl = {https://ui.adsabs.harvard.edu/abs/2021MNRAS.504...65A}, - adsnote = {Provided by the SAO/NASA Astrophysics Data System} - } +Please cite `Anand, Nelson & Kauffmann 2021 `_ if you find this code useful in your research. The BibTeX entry for the paper is can be found `here `_. + Contact ------- -If you have any questions/suggestions, please feel free to write to abhijeetanand2011 [at] gmail.com +| Abhijeet Anand +| Lawrence Berkeley National Lab + +If you have any questions/suggestions, please feel free to write to abhijeetanand2011 [at] gmail.com or, preferably, open a GitHub issue. Indices and tables diff --git a/docs/_build/html/_sources/installation.rst.txt b/docs/_build/html/_sources/installation.rst.txt index b9f11b5..c5d1c35 100644 --- a/docs/_build/html/_sources/installation.rst.txt +++ b/docs/_build/html/_sources/installation.rst.txt @@ -27,14 +27,27 @@ First, clone the repository to your local machine: Running example: ---------------- -Before running, please read :doc:`File formats `. +Before running, please read :doc:`File formats `. I have provided an example QSO spectra FITS file, `data/qso_test.fits`, which contains 500 continuum-normalized SDSS QSO spectra. You can use this file to test an example run as described below. .. code-block:: bash - qsoabsfind --input-fits-file path_to_input_fits_file.fits \ - --n-qso 1-1000:10 \ + qsoabsfind --input-fits-file data/qso_test.fits \ + --n-qso 500 \ --absorber MgII \ - --output path_to_output_fits_file.fits \ - --headers KEY1=VALUE1 KEY2=VALUE2 \ + --output test_MgII.fits \ + --headers SURVEY=SDSS AUTHOR=YOUR_NAME \ --n-tasks 16 \ --ncpus 4 + +Useful notes: +------------- + +Parallel mode can be memory-intensive if the input FITS file is large in size. As the code accesses the FITS file to read QSO spectra when running in parallel, it can become a bottleneck for memory, and the code may fail. Currently, I suggest the following: + + - **Divide your file into smaller chunks:** Split the FITS file into several smaller files, each containing approximately `N` spectra. Then run the code on these smaller files. + + - **Use a rule of thumb for file size:** Ensure that the size of each individual file is no larger than `total_memory/ncpu` of your node or system. Based on this idea you can decide your `N`. I would suggest `N = 1000`. + + - **Merge results at the end:** After processing, you can merge your results. + +In order to decide the right size of the FITS file, consider the total available memory and the number of CPUs in your system. diff --git a/docs/_build/html/fileformat.html b/docs/_build/html/fileformat.html index fea2d2a..046f785 100644 --- a/docs/_build/html/fileformat.html +++ b/docs/_build/html/fileformat.html @@ -72,7 +72,7 @@
  • - Edit on GitHub + Edit on GitHub

  • @@ -89,14 +89,23 @@

    Input FITS File Structure

    Constant File (Optional)

    -

    The user-defined constant-file must follow the same structure as the qsoabsfind.constants file, otherwise, the code will fail. If you want to use the default search parameters, you can run the tool without the constant-file option.

    +

    Before using your own constants file, please set an environment variable QSO_CONSTANTS_FILE in your bashrc or zshrc file, and point it to the qsoabsfind.constants file. Since the code dynamically loads constants from a new file, it is important to define this environment variable.

    +

    The user-defined constants file must follow the same structure as the qsoabsfind.constants file; otherwise, the code will fail. If you want to use the default search parameters, you can run the tool without specifying the constant-file option.

    Then run qsoabsfind with the required FITS file. If using a custom constant file, include it in the command:

    -
    qsoabsfind --input <input_fits_file> [--constant-file <constant_file>] --output <output_fits_file>
    +
    qsoabsfind --input-fits-file data/qso_test.fits \
    +           --n-qso 500 \
    +           --absorber MgII \
    +           --output test_MgII.fits \
    +           --headers SURVEY=SDSS AUTHOR=YOUR_NAME \
    +           --n-tasks 16 \
    +           --ncpus 4
    +           --constant-file path_to_your_file
     
    @@ -106,14 +115,14 @@

    Output FITS File Structure
  • INDEX_SPEC: Index of quasar (can be used to read the RA, DEC, and Z of QSOs).

  • Z_ABS: Redshift of absorber.

  • -
  • ${METAL}_${line}_EW: Rest-frame equivalent widths (EWs) of absorber lines (e.g., MgII 2796, 2803 or CIV 1548, 1550) in Angstroms.

  • -
  • ${METAL}_${line}_EW_ERROR: Uncertainties in rest-frame EWs of absorber lines in Angstroms.

  • +
  • ${METAL}_${LINE}_EW: Rest-frame equivalent widths (EWs) of absorber lines (e.g., MgII 2796, 2803 or CIV 1548, 1550) in Angstroms.

  • +
  • ${METAL}_${LINE}_EW_ERROR: Uncertainties in rest-frame EWs of absorber lines in Angstroms.

  • Z_ABS_ERR: Measured error in the redshift of the absorber.

  • GAUSS_FIT: Rest-frame fitting parameters of double Gaussian to the absorber doublet (the width can be used to measure the velocity dispersion).

  • GAUSS_FIT_STD: Uncertainties in rest-frame fitting parameters of double Gaussian to the absorber doublet.

  • -
  • SN_${METAL}_${line}: Signal-to-noise ratio of the lines.

  • -
  • ${metal}_EW_TOTAL: Total EW of the lines in Angstroms.

  • -
  • ${metal}_EW_TOTAL_ERROR: Uncertainties in total EW of the lines in Angstroms.

  • +
  • SN_${METAL}_${LINE}: Signal-to-noise ratio of the lines.

  • +
  • ${METAL}_EW_TOTAL: Total EW of the lines in Angstroms.

  • +
  • ${METAL}_EW_TOTAL_ERROR: Uncertainties in total EW of the lines in Angstroms.

  • @@ -130,7 +139,7 @@

    Output FITS File Structure

    © Copyright 2021-2024, Abhijeet Anand. - Last updated on True. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html index a9c92f6..162346e 100644 --- a/docs/_build/html/genindex.html +++ b/docs/_build/html/genindex.html @@ -64,7 +64,7 @@
  • - Edit on GitHub + Edit on GitHub

  • @@ -114,12 +114,10 @@

    C

    @@ -168,7 +168,7 @@

    G

      @@ -299,9 +299,11 @@

      R

    @@ -358,7 +360,7 @@

    Z

    © Copyright 2021-2024, Abhijeet Anand. - Last updated on True. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html index 2112da9..09cb3ce 100644 --- a/docs/_build/html/index.html +++ b/docs/_build/html/index.html @@ -66,7 +66,7 @@
  • - Edit on GitHub + Edit on GitHub

  • @@ -96,34 +96,19 @@

    Features

    GitHub repository

    -

    The source code is available at Please see the qsoabsfind repo.

    +

    The source code is available on GitHub. Please see the qsoabsfind repo.

    Citation

    -

    Please cite Anand, Nelson & Kauffmann 2021 if you find this code useful in your research. The BibTeX entry for the paper is:

    -
    @ARTICLE{2021MNRAS.504...65A,
    -   author = {{Anand}, Abhijeet and {Nelson}, Dylan and {Kauffmann}, Guinevere},
    -    title = "{Characterizing the abundance, properties, and kinematics of the cool circumgalactic medium of galaxies in absorption with SDSS DR16}",
    -  journal = {\mnras},
    - keywords = {galaxies: evolution, galaxies: formation, large-scale structure of Universe, Astrophysics - Astrophysics of Galaxies},
    -     year = 2021,
    -    month = jun,
    -   volume = {504},
    -   number = {1},
    -    pages = {65-88},
    -      doi = {10.1093/mnras/stab871},
    -archivePrefix = {arXiv},
    -   eprint = {2103.15842},
    -primaryClass = {astro-ph.GA},
    -   adsurl = {https://ui.adsabs.harvard.edu/abs/2021MNRAS.504...65A},
    -  adsnote = {Provided by the SAO/NASA Astrophysics Data System}
    -}
    -
    -
    +

    Please cite Anand, Nelson & Kauffmann 2021 if you find this code useful in your research. The BibTeX entry for the paper is can be found here.

    Contact

    -

    If you have any questions/suggestions, please feel free to write to abhijeetanand2011 [at] gmail.com

    +
    +
    Abhijeet Anand
    +
    Lawrence Berkeley National Lab
    +
    +

    If you have any questions/suggestions, please feel free to write to abhijeetanand2011 [at] gmail.com or, preferably, open a GitHub issue.

    @@ -145,8 +130,8 @@

    Indices and tables -

    © Copyright 2021-2025 Abhijeet Anand 2021-2024, Abhijeet Anand. - Last updated on True. +

    © Copyright 2021-2024, Abhijeet Anand. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/installation.html b/docs/_build/html/installation.html index 94f0151..014cacb 100644 --- a/docs/_build/html/installation.html +++ b/docs/_build/html/installation.html @@ -50,6 +50,7 @@
  • Prerequisites
  • Clone the Repository
  • Running example:
  • +
  • Useful notes:
  • File formats
  • @@ -72,7 +73,7 @@
  • - Edit on GitHub + Edit on GitHub

  • @@ -106,17 +107,29 @@

    Clone the Repository

    Running example:

    -

    Before running, please read File formats.

    -
    qsoabsfind --input-fits-file path_to_input_fits_file.fits \
    -           --n-qso 1-1000:10 \
    +

    Before running, please read File formats. I have provided an example QSO spectra FITS file, data/qso_test.fits, which contains 500 continuum-normalized SDSS QSO spectra. You can use this file to test an example run as described below.

    +
    qsoabsfind --input-fits-file data/qso_test.fits \
    +           --n-qso 500 \
                --absorber MgII \
    -           --output path_to_output_fits_file.fits \
    -           --headers KEY1=VALUE1 KEY2=VALUE2 \
    +           --output test_MgII.fits \
    +           --headers SURVEY=SDSS AUTHOR=YOUR_NAME \
                --n-tasks 16 \
                --ncpus 4
     
    +
    +

    Useful notes:

    +

    Parallel mode can be memory-intensive if the input FITS file is large in size. As the code accesses the FITS file to read QSO spectra when running in parallel, it can become a bottleneck for memory, and the code may fail. Currently, I suggest the following:

    +
    +
      +
    • Divide your file into smaller chunks: Split the FITS file into several smaller files, each containing approximately N spectra. Then run the code on these smaller files.

    • +
    • Use a rule of thumb for file size: Ensure that the size of each individual file is no larger than total_memory/ncpu of your node or system. Based on this idea you can decide your N. I would suggest N = 1000.

    • +
    • Merge results at the end: After processing, you can merge your results.

    • +
    +
    +

    In order to decide the right size of the FITS file, consider the total available memory and the number of CPUs in your system.

    +
    @@ -131,7 +144,7 @@

    Running example:

    © Copyright 2021-2024, Abhijeet Anand. - Last updated on True. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/modules.html b/docs/_build/html/modules.html index 84a7229..6854779 100644 --- a/docs/_build/html/modules.html +++ b/docs/_build/html/modules.html @@ -65,7 +65,7 @@
  • - Edit on GitHub + Edit on GitHub

  • @@ -87,7 +87,7 @@

    © Copyright 2021-2024, Abhijeet Anand. - Last updated on True. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv index 74dcee537a23bf0f40bdfefdc015dbbbb67197b1..d195e46f62d1b93b13db77021bc475799bcc8c00 100644 GIT binary patch delta 748 zcmV-|OK#gR5Z&t(0@|&GW}96%0kR01HU}7t#gR;uA{BnDIICWx z*Xv0-BxPGp6Eu>tk~QSKd78f;ox!bZq!wj=xbBPyipnqL<4IiYe5XF;gU#o1Q%sJ= zC)qW+Rc-X%sNkj1(2?I60eooemMr8eAT@k{_y(@0+FOj)nt!0{s8L@1WA9Bv@d0~O zQZS&9HMylomQa9`x>Yoi3LPM$Clg2Zv(b|lJ3_f-4n6Ci-oO#sdItkvF~bT*F-%^z z!2}1rd?E#wIzp-)jB zNVYpqg3}c>dw*C_0)!LtYAY|Dy#}!(AuniR<2f;E(`}{Z9A1NMNw}SCJRIG<4lE`V z+_li4V!DUOk)W}rgB$vYvZ^j3w+84r(#g~uGD&V+oWRQ{(y*Z1X{fkl>Y!qd(*R_x zv2L#6N|>H0`QZpo;z4GQm>3(*y=Mt>I@NOk#b%; z*LX4Qz-c#<&vSR85rHdSNX|>^-nZ|>4$4~?uLz~{;#!!x++3AsX}Ve7#6Ft^u4qZe zzVVb46mB_Kta6lQh1>YEIA0raCpXSy{`~swN@czfI?^5^S5|a9wpDt$)IZCQhR%|L z>*N(?{b6%F$U1kq&N9bbTW)G)6usm*>J<~b{}{SIa0k$r_9l1}lP^M3-thFEn*Mr! eTUu(!63_A?|97}Fo@H74A)nu4OT}NBAxRG~LTi!$ delta 757 zcmVl=L2}zL47~dlnrW}rG}qjE$xIHJru73bv&6KKa&-EDwUC0bGogq3>vd9+4Eq|55Cr)(!%z0w%tsY z`X{V|kTHa#Y6^ioWfW;G_bJhXJ(jh4sgkA+{jaOB$ zfuK<@s2Q}j$CU7;m`GmL!Xs!~2o0pFT0krU5YCCy8tBT|(174Hx2URvN68f>42M`_ z2M7c5YL@HJtbakQQK}1>qV!xDg{}9>C{wM$b|~qfN)P9_uLFzehldJEp;_(;lthk0 zsW{Yv;0}kgyN2c>duxDRqZ}xmt${?1vA=N1Et81tf-{e8&P84X9Sa`YbUJA+aV~Ax zYlI>=j((~9Y=AOo&GmE?jti|=BZX5!!Hs!_#@Pm)SAR&*%dA8oQgbt>?1K0z%QY!v zj0xviX`IWMli-kYuMC~dk}dd@w_x&GD6?M8o5uHs?czxrofdp| zbjz7^$Il;}%Lq|uLG&@kscQ~A*_8+AWOSdm0Hi_>zVecL#d**#g&Jye4$9K|#W1pm z40G=0rGGF%tUAX1kk_IiluKMYTJWs}tqeDnCv;}+cuh!+wtiu=PXJwSh$xGkd2p|c zVs}}MlY`Xj+}mo8z-L}6u1iNByY<8#T3W{!g^awsmA1&XH`!?Ic4l|6(^WKNa<(Ri`}lJ+ZtHO;J4P|TfBvG3H*SQQuNER|Wk=${t-F^?|IvOX8Z8?> zCvPZgPTTWB@_9(-ENM(55S=~`#+x0&Gmhv@Od9l%`jP4Fg^SEPython Module Index

    © Copyright 2021-2024, Abhijeet Anand. - Last updated on True. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/qsoabsfind.html b/docs/_build/html/qsoabsfind.html index ff86752..3232fa7 100644 --- a/docs/_build/html/qsoabsfind.html +++ b/docs/_build/html/qsoabsfind.html @@ -56,18 +56,19 @@
  • qsoabsfind.absfinder module
  • qsoabsfind.absorberutils module @@ -87,7 +88,7 @@
  • qsoabsfind.spec module
    @@ -138,6 +139,7 @@

    Full qsoabsfind API reference

    qsoabsfind.parallel_convolution module

    +

    This script contains a function that runs the absorber finder in parallel for many spectra.

    qsoabsfind.parallel_convolution.main()[source]
    @@ -145,7 +147,7 @@

    Full qsoabsfind API reference
    -qsoabsfind.parallel_convolution.parallel_convolution_method_absorber_finder_QSO_spectra(fits_file, spec_indices, absorber='MgII', ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True, n_jobs=1)[source]
    +qsoabsfind.parallel_convolution.parallel_convolution_method_absorber_finder_QSO_spectra(fits_file, spec_indices, absorber='MgII', ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True, verbose=False, n_jobs=1)[source]

    Run convolution_method_absorber_finder_in_QSO_spectra in parallel using multiprocessing.

    @@ -163,6 +165,7 @@

    Full qsoabsfind API reference

    qsoabsfind.absfinder module

    +

    This script contains a function to run convolution based absorber finder on a single spectrum.

    -qsoabsfind.absfinder.convolution_method_absorber_finder_in_QSO_spectra(fits_file, spec_index, absorber='MgII', ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True)[source]
    +qsoabsfind.absfinder.convolution_method_absorber_finder_in_QSO_spectra(spec_index, absorber='MgII', lam_obs=None, residual=None, error=None, lam_search=None, unmsk_residual=None, unmsk_error=None, ker_width_pixels=[3, 4, 5, 6, 7, 8], coeff_sigma=2.5, mult_resi=1, d_pix=0.6, pm_pixel=200, sn_line1=3, sn_line2=2, use_covariance=False, logwave=True, verbose=False)[source]

    Detect absorbers with doublet properties in SDSS quasar spectra using a convolution method. This function identifies potential absorbers based on user-defined threshold criteria, applies Gaussian fitting to reject false @@ -189,22 +193,43 @@

    Full qsoabsfind API reference
    Parameters:
      -
    • fits_file (str) – Path to the FITS file containing Normalized QSO spectra (i.e. flux/continuum), must contain FLUX, ERROR (i.e. error/continuum), WAVELENGTH, and TGTDETAILS extensions. In TGTDETAILS, must contain keywords like RA_QSO, DEC_QSO, Z_QSO.

    • -
    • spec_index (int) – Index of quasar in the spectra matrix.

    • +
    • spec_index (int) – Index of quasar in the spectra 2D array.

    • absorber (str) – Absorber name for searching doublets (MgII, CIV). Default is ‘MgII’.

    • +
    • lam_obs (numpy.array) – observed wavelength array.

    • +
    • residual (numpy.array) – residual (i.e. flux/continuum) array

    • +
    • error (numpy.array) – error on residuals

    • +
    • lam_search (numpy.array) – search observed wavelength array (i.e. region where absorber will be looked for).

    • +
    • unmsk_residual (numpy.array) – search residual array (residuals at search wavelength pixels)

    • +
    • unmsk_error (numpy.array) – error on residuals array in search wavelength region

    • ker_width_pix (list) – List of kernel widths in pixels. Default is [3, 4, 5, 6, 7, 8].

    • coeff_sigma (float) – Coefficient for sigma to apply threshold in the convolved array. Default is 2.5.

    • mult_resi (float) – Factor to shift the residual up or down. Default is 1.

    • d_pix (float) – Pixel distance for line separation during Gaussian fitting. Default is 0.6.

    • pm_pixel (int) – Pixel parameter for local noise estimation (default 200).

    • -
    • sn_line1 (float) – Signal-to-noise ratio for thresholding for line1.

    • -
    • sn_line2 (float) – Signal-to-noise ratio for thresholding for line2.

    • +
    • sn_line1 (float) – Signal-to-noise ratio for thresholding for line1 (default 3).

    • +
    • sn_line2 (float) – Signal-to-noise ratio for thresholding for line2 (default 3).

    • use_covariance (bool) – if want to use full covariance of scipy curvey_fit for EW error calculation (default is False)

    • -
    • logwave (bool) – if wavelength on log scale

    • +
    • logwave (bool) – if wavelength on log scale (default True for SDSS)

    • +
    • verbose (bool) – if want to print a lot of outputs for debugging (default False)

    Returns:
    -

    Contains lists of various parameters related to detected absorbers.

    +

    +
    Contains lists of various parameters related to detected absorbers.
      +
    • index (list): QSO spec index searched

    • +
    • zabs (list): redshifts of absorbers detected

    • +
    • params (list of arrays): gaussian fit parameters for each absorber

    • +
    • errror params (list of arrays): errors on gaussian fit parameters for each absorber

    • +
    • EW1 (list): Equivalent width of line 1 for each absorber

    • +
    • EW2 (list): Equivalent width of line 2 for each absorber

    • +
    • EW total (list): Total Equivalent width of line 1 and line 2 for each absorber

    • +
    • errors EW1 (list): errors on Equivalent width of line 1 for each absorber

    • +
    • errors EW2 (list): errors on Equivalent width of line 2 for each absorber

    • +
    • errors EW total (list): errors on Total Equivalent width of line 1 and line 2 for each absorber

    • +
    +
    +
    +

    Return type:

    tuple

    @@ -240,6 +265,55 @@

    Full qsoabsfind API reference +
    +qsoabsfind.absfinder.read_single_spectrum_and_find_absorber(fits_file, spec_index, absorber, **kwargs)[source]
    +

    This function retrieves a single QSO spectrum from a FITS file, processes the data to remove NaNs, +and prepares the spectrum for absorber search within specified wavelength regions +and runs the convolution based adaptive S/N method to detect absorbers in the spectrum.

    +
    +
    Parameters:
    +
      +
    • fits_file (str) – Path to the FITS file containing normalized QSO spectra. +The file must include extensions for FLUX, ERROR, WAVELENGTH +and METADATA which must contain keyword Z_QSO.

    • +
    • spec_index (int) – Index of the quasar spectrum to retrieve from the FITS file.

    • +
    • absorber (str) – Name of the absorber to search for (e.g., ‘MgII’, ‘CIV’).

    • +
    • kwargs (dictionary) – search parameters used in convolution_method_absorber_finder_in_QSO_spectra()

    • +
    +
    +
    Returns:
    +

    +
    Contains lists of various parameters related to detected absorbers.
      +
    • index (list): QSO spec index searched

    • +
    • zabs (list of floats): redshifts of absorbers detected

    • +
    • params (list of arrays): gaussian fit parameters for each absorber

    • +
    • errror params (list of arrays): errors on gaussian fit parameters for each absorber

    • +
    • EW1 (list of floats): Equivalent width of line 1 for each absorber

    • +
    • EW2 (list of floats): Equivalent width of line 2 for each absorber

    • +
    • EW total (list of floats): Total Equivalent width of line 1 and line 2 for each absorber

    • +
    • errors EW1 (list of floats): errors on Equivalent width of line 1 for each absorber

    • +
    • errors EW2 (list of floats): errors on Equivalent width of line 2 for each absorber

    • +
    • errors EW total (list of floats): errors on Total Equivalent width of line 1 and line 2 for each absorber

    • +
    +
    +
    +

    +
    +
    Return type:
    +

    tuple

    +
    +
    Raises:
    +

    AssertionError – If the sizes of lam_search, unmsk_residual, and unmsk_error do not match.

    +
    +
    +

    Notes

    +
      +
    • This function assumes that the input spectra are already normalized (i.e., flux divided by continuum).

    • +
    • The wavelength search region is determined dynamically based on the observed wavelength range.

    • +
    +

    +

    qsoabsfind.absorberutils module

    @@ -271,34 +345,6 @@

    Full qsoabsfind API reference -
    -qsoabsfind.absorberutils.check_error_on_residual(l1, l2, lam_rest, residual, error, log)[source]
    -

    Check the error on residuals around specified wavelengths.

    -
    -
    Parameters:
    -
      -
    • l1 (float) – First wavelength to check around.

    • -
    • l2 (float) – Second wavelength to check around.

    • -
    • lam_rest (numpy.ndarray) – Rest-frame wavelengths.

    • -
    • residual (numpy.ndarray) – Residual flux values.

    • -
    • error (numpy.ndarray) – Error values corresponding to the residuals.

    • -
    • log (bool) – if wavelength bins are on log scale

    • -
    -
    -
    Returns:
    -

    -
    Mean signal-to-noise ratios (SNR) around the specified wavelengths.

    Returns (mean_sn1, mean_sn2).

    -
    -
    -

    -
    -
    Return type:
    -

    tuple

    -
    -
    -
    -
    qsoabsfind.absorberutils.contiguous_pixel_remover(abs_z, sn1_all, sn2_all, use_kernel='MgII')[source]
    @@ -343,6 +389,34 @@

    Full qsoabsfind API reference +
    +qsoabsfind.absorberutils.estimate_snr_for_lines(l1, l2, lam_rest, residual, error, log)[source]
    +

    Estimate S/N of the doublet lines.

    +
    +
    Parameters:
    +
      +
    • l1 (float) – First wavelength to check around.

    • +
    • l2 (float) – Second wavelength to check around.

    • +
    • lam_rest (numpy.ndarray) – Rest-frame wavelengths.

    • +
    • residual (numpy.ndarray) – Residual flux values.

    • +
    • error (numpy.ndarray) – Error values corresponding to the residuals.

    • +
    • log (bool) – if wavelength bins are on log scale

    • +
    +
    +
    Returns:
    +

    +
    Mean signal-to-noise ratios (SNR) around the specified wavelengths.

    Returns (mean_sn1, mean_sn2).

    +
    +
    +

    +
    +
    Return type:
    +

    tuple

    +
    +
    +

    +
    qsoabsfind.absorberutils.group_and_weighted_mean_selection_function(master_list_of_pot_absorber, residual, gamma=4)[source]
    @@ -368,25 +442,17 @@

    Full qsoabsfind API reference
    qsoabsfind.absorberutils.group_contiguous_pixel(data, resi, avg)[source]
    -

    Arrange data into groups where successive elements differ by less than a -given average difference.

    +

    Arrange data into groups where successive elements differ by less than the average difference.

    Parameters:
      -
    • data (numpy.ndarray) – Array of absorber values for each spectrum.

    • -
    • resi (numpy.ndarray) – Corresponding residual values.

    • -
    • avg (float) – Average difference threshold for grouping contiguous pixels.

    • +
    • data (np.ndarray) – List of absorbers for each spectrum.

    • +
    • resi (np.ndarray) – Corresponding residual.

    • +
    • avg (float) – Maximum allowed difference to group data.

    Returns:
    -

    -
    A tuple containing:
      -
    • list of grouped data

    • -
    • list of grouped residuals

    • -
    -
    -
    -

    +

    Final list with contiguous pixels grouped, and corresponding residuals if provided.

    Return type:

    tuple

    @@ -453,11 +519,10 @@

    Full qsoabsfind API reference -
    -qsoabsfind.absorberutils.remove_Mg_falsely_identified_as_Fe_absorber(index, z_after_grouping, lam_obs, residual, error, d_pix)[source]
    -

    Remove any absorber that arises due to Fe 2586, 2600 or vice-versa case -of 2796, 2803 when using Fe kernel line but has already been detected for -the 2796 line, i.e., false positive due to Fe lines.

    +
    +qsoabsfind.absorberutils.remove_Mg_falsely_come_from_Fe_absorber(index, z_after_grouping, lam_obs, residual, error, d_pix, logwave)[source]
    +

    Remove any MgII absorber that arises falsley due to Fe 2586, 2600 doublet, +i.e., false positive due to Fe lines.

    Parameters:

  • diff --git a/docs/_build/html/search.html b/docs/_build/html/search.html index 2306a5d..4a68067 100644 --- a/docs/_build/html/search.html +++ b/docs/_build/html/search.html @@ -95,7 +95,7 @@

    © Copyright 2021-2024, Abhijeet Anand. - Last updated on True. + Last updated on 2024-08-01 23:30:26.821787.

    diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js index 28eb2ce..35d0b50 100644 --- a/docs/_build/html/searchindex.js +++ b/docs/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles": {"Citation": [[1, "citation"]], "Clone the Repository": [[2, "clone-the-repository"]], "Constant File (Optional)": [[0, "constant-file-optional"]], "Contact": [[1, "contact"]], "Contents:": [[1, null]], "Features": [[1, "features"]], "File formats": [[0, null]], "Full qsoabsfind API reference": [[4, null]], "GitHub repository": [[1, "github-repository"]], "Indices and tables": [[1, "indices-and-tables"]], "Input FITS File Structure": [[0, "input-fits-file-structure"]], "Installation": [[2, null]], "Module contents": [[4, "module-qsoabsfind"]], "Output FITS File Structure": [[0, "output-fits-file-structure"]], "Prerequisites": [[2, "prerequisites"]], "Running example:": [[2, "running-example"]], "qsoabsfind Module": [[3, null]], "qsoabsfind.absfinder module": [[4, "module-qsoabsfind.absfinder"]], "qsoabsfind.absorberutils module": [[4, "module-qsoabsfind.absorberutils"]], "qsoabsfind.ew module": [[4, "module-qsoabsfind.ew"]], "qsoabsfind.io module": [[4, "module-qsoabsfind.io"]], "qsoabsfind.parallel_convolution module": [[4, "module-qsoabsfind.parallel_convolution"]], "qsoabsfind.spec module": [[4, "module-qsoabsfind.spec"]], "qsoabsfind.utils module": [[4, "module-qsoabsfind.utils"]], "qsoabsfind\u2019s documentation": [[1, null]]}, "docnames": ["fileformat", "index", "installation", "modules", "qsoabsfind"], "envversion": {"sphinx": 62, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1}, "filenames": ["fileformat.rst", "index.rst", "installation.rst", "modules.rst", "qsoabsfind.rst"], "indexentries": {"__init__() (qsoabsfind.spec.qsospecread method)": [[4, "qsoabsfind.spec.QSOSpecRead.__init__", false]], "absorber_search_window() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.absorber_search_window", false]], "calculate_ew_errors() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.calculate_ew_errors", false]], "check_error_on_residual() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.check_error_on_residual", false]], "contiguous_pixel_remover() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.contiguous_pixel_remover", false]], "convolution_fun() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.convolution_fun", false]], "convolution_method_absorber_finder_in_qso_spectra() (in module qsoabsfind.absfinder)": [[4, "qsoabsfind.absfinder.convolution_method_absorber_finder_in_QSO_spectra", false]], "double_curve_fit() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.double_curve_fit", false]], "double_gaussian() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.double_gaussian", false]], "elapsed() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.elapsed", false]], "estimate_local_sigma_conv_array() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.estimate_local_sigma_conv_array", false]], "find_valid_indices() (in module qsoabsfind.absfinder)": [[4, "qsoabsfind.absfinder.find_valid_indices", false]], "full_covariance_ew_errors() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.full_covariance_ew_errors", false]], "gauss_two_lines_kernel() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.gauss_two_lines_kernel", false]], "get_tgtdetails() (qsoabsfind.spec.qsospecread method)": [[4, "qsoabsfind.spec.QSOSpecRead.get_tgtdetails", false]], "group_and_weighted_mean_selection_function() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.group_and_weighted_mean_selection_function", false]], "group_contiguous_pixel() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.group_contiguous_pixel", false]], "main() (in module qsoabsfind.parallel_convolution)": [[4, "qsoabsfind.parallel_convolution.main", false]], "measure_absorber_properties_double_gaussian() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.measure_absorber_properties_double_gaussian", false]], "median_selection_after_combining() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.median_selection_after_combining", false]], "module": [[3, "module-qsoabsfind", false], [4, "module-qsoabsfind", false], [4, "module-qsoabsfind.absfinder", false], [4, "module-qsoabsfind.absorberutils", false], [4, "module-qsoabsfind.ew", false], [4, "module-qsoabsfind.io", false], [4, "module-qsoabsfind.parallel_convolution", false], [4, "module-qsoabsfind.spec", false], [4, "module-qsoabsfind.utils", false]], "parallel_convolution_method_absorber_finder_qso_spectra() (in module qsoabsfind.parallel_convolution)": [[4, "qsoabsfind.parallel_convolution.parallel_convolution_method_absorber_finder_QSO_spectra", false]], "plot_absorber() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.plot_absorber", false]], "qsoabsfind": [[3, "module-qsoabsfind", false], [4, "module-qsoabsfind", false]], "qsoabsfind.absfinder": [[4, "module-qsoabsfind.absfinder", false]], "qsoabsfind.absorberutils": [[4, "module-qsoabsfind.absorberutils", false]], "qsoabsfind.ew": [[4, "module-qsoabsfind.ew", false]], "qsoabsfind.io": [[4, "module-qsoabsfind.io", false]], "qsoabsfind.parallel_convolution": [[4, "module-qsoabsfind.parallel_convolution", false]], "qsoabsfind.spec": [[4, "module-qsoabsfind.spec", false]], "qsoabsfind.utils": [[4, "module-qsoabsfind.utils", false]], "qsospecread (class in qsoabsfind.spec)": [[4, "qsoabsfind.spec.QSOSpecRead", false]], "read_fits() (qsoabsfind.spec.qsospecread method)": [[4, "qsoabsfind.spec.QSOSpecRead.read_fits", false]], "read_fits_file() (in module qsoabsfind.io)": [[4, "qsoabsfind.io.read_fits_file", false]], "redshift_estimate() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.redshift_estimate", false]], "remove_mg_falsely_identified_as_fe_absorber() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.remove_Mg_falsely_identified_as_Fe_absorber", false]], "save_plot() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.save_plot", false]], "save_results_to_fits() (in module qsoabsfind.io)": [[4, "qsoabsfind.io.save_results_to_fits", false]], "single_gaussian() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.single_gaussian", false]], "validate_sizes() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.validate_sizes", false]], "vel_dispersion() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.vel_dispersion", false]], "weighted_mean() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.weighted_mean", false]], "z_abs_from_same_metal_absorber() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.z_abs_from_same_metal_absorber", false]]}, "objects": {"": [[4, 0, 0, "-", "qsoabsfind"]], "qsoabsfind": [[4, 0, 0, "-", "absfinder"], [4, 0, 0, "-", "absorberutils"], [4, 0, 0, "-", "ew"], [4, 0, 0, "-", "io"], [4, 0, 0, "-", "parallel_convolution"], [4, 0, 0, "-", "spec"], [4, 0, 0, "-", "utils"]], "qsoabsfind.absfinder": [[4, 1, 1, "", "convolution_method_absorber_finder_in_QSO_spectra"], [4, 1, 1, "", "find_valid_indices"]], "qsoabsfind.absorberutils": [[4, 1, 1, "", "absorber_search_window"], [4, 1, 1, "", "check_error_on_residual"], [4, 1, 1, "", "contiguous_pixel_remover"], [4, 1, 1, "", "estimate_local_sigma_conv_array"], [4, 1, 1, "", "group_and_weighted_mean_selection_function"], [4, 1, 1, "", "group_contiguous_pixel"], [4, 1, 1, "", "median_selection_after_combining"], [4, 1, 1, "", "redshift_estimate"], [4, 1, 1, "", "remove_Mg_falsely_identified_as_Fe_absorber"], [4, 1, 1, "", "weighted_mean"], [4, 1, 1, "", "z_abs_from_same_metal_absorber"]], "qsoabsfind.ew": [[4, 1, 1, "", "calculate_ew_errors"], [4, 1, 1, "", "double_curve_fit"], [4, 1, 1, "", "full_covariance_ew_errors"], [4, 1, 1, "", "measure_absorber_properties_double_gaussian"]], "qsoabsfind.io": [[4, 1, 1, "", "read_fits_file"], [4, 1, 1, "", "save_results_to_fits"]], "qsoabsfind.parallel_convolution": [[4, 1, 1, "", "main"], [4, 1, 1, "", "parallel_convolution_method_absorber_finder_QSO_spectra"]], "qsoabsfind.spec": [[4, 2, 1, "", "QSOSpecRead"]], "qsoabsfind.spec.QSOSpecRead": [[4, 3, 1, "", "__init__"], [4, 3, 1, "", "get_tgtdetails"], [4, 3, 1, "", "read_fits"]], "qsoabsfind.utils": [[4, 1, 1, "", "convolution_fun"], [4, 1, 1, "", "double_gaussian"], [4, 1, 1, "", "elapsed"], [4, 1, 1, "", "gauss_two_lines_kernel"], [4, 1, 1, "", "plot_absorber"], [4, 1, 1, "", "save_plot"], [4, 1, 1, "", "single_gaussian"], [4, 1, 1, "", "validate_sizes"], [4, 1, 1, "", "vel_dispersion"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method"}, "terms": {"": [2, 4], "0": 4, "0001": 4, "1": [1, 2, 4], "10": [1, 2], "1000": 2, "1093": 1, "1548": [0, 1], "1550": [0, 1], "15842": 1, "16": 2, "2": 4, "200": 4, "2021": 1, "2021mnra": 1, "2103": 1, "2586": 4, "2600": 4, "2796": [0, 1, 4], "2803": [0, 1, 4], "3": [2, 4], "4": [2, 4], "5": 4, "504": 1, "6": [2, 4], "65": 1, "65a": 1, "6a": 4, "7": 4, "8": 4, "88": 1, "A": 4, "If": [0, 1, 4], "In": 4, "The": [0, 1, 4], "Then": 0, "With": 4, "_": 0, "__init__": 4, "_ew": 0, "_ew_error": 0, "_ew_tot": 0, "_ew_total_error": 0, "ab": 1, "abhi0395": 2, "abhijeet": 1, "abhijeetanand2011": 1, "abs_z": 4, "absorb": [0, 1, 2, 4], "absorber_redshift": 4, "absorber_search_window": 4, "absorpt": [1, 4], "abund": 1, "accur": 1, "adapt": 1, "adsab": 1, "adsnot": 1, "adsurl": 1, "after": 4, "algorithm": 4, "all": 4, "alreadi": 4, "amp": 4, "amp1": 4, "amp2": 4, "amp_ratio": 4, "amplitud": 4, "anand": 1, "ang": 4, "angstrom": 0, "ani": [1, 4], "api": 1, "appli": [1, 4], "approach": 1, "ar": 4, "archiveprefix": 1, "aris": 4, "around": 4, "arrai": [0, 4], "arrang": 4, "articl": 1, "arxiv": 1, "assert": 4, "astro": 1, "astrophys": 1, "astropi": 2, "author": 1, "avail": 1, "averag": 4, "avg": 4, "axi": 4, "base": [1, 4], "basic": 4, "been": 4, "befor": 2, "being": 4, "beta": 4, "bibtex": 1, "bin": 4, "bool": 4, "both": 4, "bound": 4, "c1": 4, "c2": 4, "calcul": 4, "calculate_ew_error": 4, "callabl": 4, "can": 0, "case": 4, "cd": 2, "center": [1, 4], "centr": 4, "character": 1, "check": [1, 4], "check_error_on_residu": 4, "circumgalact": 1, "cite": 1, "civ": [0, 1, 4], "class": 4, "code": [0, 1], "coeff_sigma": 4, "coeffici": 4, "com": [1, 2], "combin": 4, "combined_final_our_z": 4, "command": 0, "common": 4, "comput": [1, 4], "condit": 4, "constant_fil": 0, "contain": [0, 4], "contigu": 4, "contiguous_pixel_remov": 4, "continuum": [0, 4], "conv_arr": 4, "conv_arrai": 4, "convolut": [1, 4], "convolution_fun": 4, "convolution_method_absorber_finder_in_qso_spectra": 4, "convolv": 4, "cool": 1, "correct": 4, "correspond": 4, "covari": 4, "criteria": 4, "current": [1, 4], "curv": 4, "curve_fit": 4, "curvey_fit": 4, "custom": 0, "d_pix": 4, "data": [1, 4], "dec": 0, "dec_qso": [0, 4], "decid": 4, "default": [0, 4], "defin": [0, 4], "delta": 4, "desi": 1, "design": 1, "detail": 0, "detect": [1, 4], "deviat": 4, "dict": 4, "dictionari": 4, "differ": 4, "directori": 4, "discov": 2, "dispers": [0, 4], "distanc": 4, "dlam": 4, "doi": 1, "doubl": [0, 1, 4], "double_curve_fit": 4, "double_gaussian": 4, "doublet": [0, 1, 4], "down": 4, "dr16": 1, "due": 4, "dupon": 4, "dure": 4, "dylan": 1, "e": [0, 4], "each": 4, "edg": 4, "edu": 1, "effici": 1, "elaps": 4, "element": 4, "entri": 1, "eprint": 1, "equival": [0, 1, 4], "err_residu": 4, "error": [0, 4], "error_fit": 4, "estim": 4, "estimate_local_sigma_conv_arrai": 4, "evalu": 4, "evolut": 1, "ew": [0, 1], "ew1_error": 4, "ew2_error": 4, "ew_first": 4, "ew_first_lin": 4, "ew_first_line_error": 4, "ew_second": 4, "ew_second_lin": 4, "ew_second_line_error": 4, "ew_tot": 4, "ew_total_error": 4, "exploit": 4, "expon": 4, "extens": [0, 1, 4], "factor": 4, "fail": 0, "fals": [1, 4], "fe": 4, "featur": 4, "feel": 1, "feii": 4, "file": [1, 2, 4], "filenam": 4, "final": 4, "find": [1, 4], "find_valid_indic": 4, "first": [2, 4], "first_list_z": 4, "fit": [1, 2, 4], "fits_fil": 4, "fitted_obs_l1": 4, "fitted_obs_l2": 4, "fitting_param_for_spectrum": 4, "fitting_param_std_for_spectrum": 4, "float": 4, "flux": [0, 4], "follow": [0, 4], "format": [1, 2], "frame": [0, 4], "free": 1, "from": 4, "full": 1, "full_covariance_ew_error": 4, "fun_to_run": 4, "function": 4, "g": [0, 4], "ga": 1, "galaxi": 1, "gamma": 4, "gauss_fit": 0, "gauss_fit_std": 0, "gauss_two_lines_kernel": 4, "gaussian": [0, 1, 4], "gener": 4, "get_tgtdetail": 4, "git": 2, "github": 2, "given": 4, "gmail": 1, "group": 4, "group_and_weighted_mean_selection_funct": 4, "group_contiguous_pixel": 4, "guinever": 1, "ha": 4, "handl": 4, "harvard": 1, "have": [0, 1, 4], "hdu": 0, "header": [2, 4], "higher": 2, "http": [1, 2], "i": [0, 1, 4], "ideal": 0, "identifi": [1, 4], "includ": [0, 4], "index": [0, 1, 4], "index_spec": 0, "indic": 4, "info": 4, "init_cond": 4, "initi": [3, 4], "input": [2, 4], "input_fits_fil": 0, "instal": 1, "instrument": 4, "int": 4, "iter": 4, "iter_n": 4, "its": 4, "job": 4, "journal": 1, "jun": 1, "kauffmann": 1, "ker_width_pix": 4, "ker_width_pixel": 4, "kernel": 4, "key1": 2, "key2": 2, "keyword": [1, 4], "kinemat": 1, "km": 4, "l1": 4, "l2": 4, "label": 4, "lam": 4, "lam_fit_rang": 4, "lam_ob": 4, "lam_rest": 4, "lam_search": 4, "lambda": 4, "larg": 1, "less": 4, "like": 4, "line": [0, 1, 4], "line1": 4, "line2": 4, "list": 4, "load": 4, "local": [2, 4], "log": 4, "logscal": 4, "logwav": 4, "m": 2, "machin": 2, "main": 4, "mask": 4, "master_list_of_pot_absorb": 4, "matplotlib": 2, "matrix": 4, "max_wav": 4, "maximum": 4, "mean": 4, "mean1": 4, "mean2": 4, "mean_sn1": 4, "mean_sn2": 4, "measur": [0, 1, 4], "measure_absorber_properties_double_gaussian": 4, "median": 4, "median_selection_after_combin": 4, "medium": 1, "messag": 4, "metal": [0, 4], "method": 4, "mg": 4, "mgii": [0, 1, 2, 4], "min_wav": 4, "minimum": 4, "mnra": 1, "model": 4, "modul": 1, "month": 1, "most": 4, "msg": 4, "mult_resi": 4, "multiprocess": 4, "must": [0, 4], "n": [1, 2], "n_job": 4, "name": 4, "nasa": 1, "ncpu": 2, "ndarrai": 4, "nelson": 1, "new": 4, "nmf_resi_fit": 4, "nois": [0, 4], "none": 4, "normal": [0, 4], "np": 4, "numba": 2, "number": [1, 4], "numpi": [2, 4], "ob": 4, "object": 4, "observ": [0, 4], "onli": [1, 4], "oper": 4, "optim": 4, "option": 4, "oscil": 4, "otherwis": 0, "our_z": 4, "output": [2, 4], "output_fil": 4, "output_fits_fil": 0, "over": 4, "packag": 1, "page": 1, "paper": 1, "parallel": [1, 4], "parallel_convolution_method_absorber_finder_qso_spectra": 4, "param": 4, "paramet": [0, 4], "path": 4, "path_to_input_fits_fil": 2, "path_to_output_fits_fil": 2, "pcov": 4, "perform": 4, "perr": 4, "ph": 1, "pip": 2, "pixel": 4, "pleas": [1, 2], "plot": 4, "plot_absorb": 4, "plot_filenam": 4, "pm_pixel": 4, "png": 4, "point": 4, "popt": 4, "posit": [1, 4], "potenti": [1, 4], "power": 4, "previous": 4, "primaryclass": 1, "print": 4, "process": 1, "profil": 4, "properti": [1, 4], "provid": [1, 4], "pytest": 2, "python": [1, 2], "qso": [0, 1, 2, 4], "qsoabsfind": [0, 2], "qsoabsfind_plot": 4, "qsospecread": 4, "quadratur": 4, "quasar": [0, 1, 4], "question": 1, "ra": 0, "ra_qso": [0, 4], "rais": 4, "rang": 4, "ratio": [0, 4], "read": [0, 2, 4], "read_fit": 4, "read_fits_fil": 4, "real": 4, "redshift": [0, 4], "redshift_estim": 4, "refer": 1, "reject": [1, 4], "relat": 4, "remov": 4, "remove_mg_falsely_identified_as_fe_absorb": 4, "repo": 1, "requir": 0, "research": 1, "resi": 4, "residu": [0, 4], "residual_arr_after_mask": 4, "residual_our_z": 4, "resolut": 4, "resoult": 4, "rest": [0, 4], "result": 4, "return": 4, "row": 4, "run": [0, 4], "same": [0, 4], "sao": 1, "save": 4, "save_param_arrai": 4, "save_param_error": 4, "save_plot": 4, "save_results_to_fit": 4, "scale": [1, 4], "scheme": 4, "scipi": [2, 4], "script": 4, "sdss": [1, 4], "search": [0, 1, 4], "second": 4, "see": 1, "select": 4, "separ": 4, "shift": 4, "should": [0, 4], "sigma": 4, "sigma1": 4, "sigma2": 4, "sigma_cr": 4, "signal": [0, 4], "simpl": 1, "sinc": 4, "singl": 4, "single_gaussian": 4, "size": 4, "sn1_all": 4, "sn2_all": 4, "sn_": 0, "sn_line1": 4, "sn_line2": 4, "snr": 4, "sourc": [1, 4], "spec_index": 4, "spec_indic": 4, "specifi": 4, "spectra": [0, 1, 4], "spectral": [0, 4], "spectrum": 4, "split": 4, "stab871": 1, "standard": 4, "start": 4, "std_fitted_obs_l1": 4, "std_fitted_obs_l2": 4, "str": 4, "strength": 4, "structur": 1, "success": 4, "suggest": 1, "system": 1, "taken": 4, "task": 2, "test": 2, "tgtdetail": [0, 4], "than": 4, "thi": [1, 4], "threshold": 4, "time": 4, "titl": [1, 4], "toler": 4, "toloer": 4, "tool": [0, 1], "total": [0, 4], "true": 4, "tupl": 4, "two": 4, "type": 4, "ui": 1, "uncertainti": 0, "uniqu": 4, "unittest": 2, "univers": 1, "unmask": 4, "unmsk_residu": 4, "up": 4, "updat": 4, "us": [0, 1, 4], "use_covari": 4, "use_kernel": 4, "user": [0, 4], "usual": 0, "v": 4, "valid": 4, "validate_s": 4, "valu": 4, "value1": 2, "value2": 2, "variou": 4, "vel_dispers": 4, "veloc": [0, 4], "verbos": 4, "versa": 4, "vice": 4, "volum": 1, "want": [0, 4], "wave": 4, "wavelength": [0, 4], "weight": 4, "weighted_mean": 4, "when": 4, "where": 4, "which": 4, "width": [0, 1, 4], "window": 4, "without": 0, "work": [1, 4], "wrapper": 4, "write": 1, "x": 4, "xlabel": 4, "y": 4, "year": 1, "ylabel": 4, "you": [0, 1], "your": [1, 2], "z": [0, 4], "z_ab": 0, "z_abs_arrai": 4, "z_abs_err": 0, "z_abs_from_same_metal_absorb": 4, "z_after_group": 4, "z_corr": 4, "z_err": 4, "z_qso": [0, 4], "z_valu": 4, "zab": 4, "zqso": 4}, "titles": ["File formats", "qsoabsfind\u2019s documentation", "Installation", "qsoabsfind Module", "Full qsoabsfind API reference"], "titleterms": {"": 1, "absfind": 4, "absorberutil": 4, "api": 4, "citat": 1, "clone": 2, "constant": 0, "contact": 1, "content": [1, 4], "document": 1, "ew": 4, "exampl": 2, "featur": 1, "file": 0, "fit": 0, "format": 0, "full": 4, "github": 1, "indic": 1, "input": 0, "instal": 2, "io": 4, "modul": [3, 4], "option": 0, "output": 0, "parallel_convolut": 4, "prerequisit": 2, "qsoabsfind": [1, 3, 4], "refer": 4, "repositori": [1, 2], "run": 2, "spec": 4, "structur": 0, "tabl": 1, "util": 4}}) \ No newline at end of file +Search.setIndex({"alltitles": {"Citation": [[1, "citation"]], "Clone the Repository": [[2, "clone-the-repository"]], "Constant File (Optional)": [[0, "constant-file-optional"]], "Contact": [[1, "contact"]], "Contents:": [[1, null]], "Features": [[1, "features"]], "File formats": [[0, null]], "Full qsoabsfind API reference": [[4, null]], "GitHub repository": [[1, "github-repository"]], "Indices and tables": [[1, "indices-and-tables"]], "Input FITS File Structure": [[0, "input-fits-file-structure"]], "Installation": [[2, null]], "Module contents": [[4, "module-qsoabsfind"]], "Output FITS File Structure": [[0, "output-fits-file-structure"]], "Prerequisites": [[2, "prerequisites"]], "Running example:": [[2, "running-example"]], "Useful notes:": [[2, "useful-notes"]], "qsoabsfind Module": [[3, null]], "qsoabsfind.absfinder module": [[4, "module-qsoabsfind.absfinder"]], "qsoabsfind.absorberutils module": [[4, "module-qsoabsfind.absorberutils"]], "qsoabsfind.ew module": [[4, "module-qsoabsfind.ew"]], "qsoabsfind.io module": [[4, "module-qsoabsfind.io"]], "qsoabsfind.parallel_convolution module": [[4, "module-qsoabsfind.parallel_convolution"]], "qsoabsfind.spec module": [[4, "module-qsoabsfind.spec"]], "qsoabsfind.utils module": [[4, "module-qsoabsfind.utils"]], "qsoabsfind\u2019s documentation": [[1, null]]}, "docnames": ["fileformat", "index", "installation", "modules", "qsoabsfind"], "envversion": {"sphinx": 62, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1}, "filenames": ["fileformat.rst", "index.rst", "installation.rst", "modules.rst", "qsoabsfind.rst"], "indexentries": {"__init__() (qsoabsfind.spec.qsospecread method)": [[4, "qsoabsfind.spec.QSOSpecRead.__init__", false]], "absorber_search_window() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.absorber_search_window", false]], "calculate_ew_errors() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.calculate_ew_errors", false]], "contiguous_pixel_remover() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.contiguous_pixel_remover", false]], "convolution_fun() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.convolution_fun", false]], "convolution_method_absorber_finder_in_qso_spectra() (in module qsoabsfind.absfinder)": [[4, "qsoabsfind.absfinder.convolution_method_absorber_finder_in_QSO_spectra", false]], "double_curve_fit() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.double_curve_fit", false]], "double_gaussian() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.double_gaussian", false]], "elapsed() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.elapsed", false]], "estimate_local_sigma_conv_array() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.estimate_local_sigma_conv_array", false]], "estimate_snr_for_lines() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.estimate_snr_for_lines", false]], "find_valid_indices() (in module qsoabsfind.absfinder)": [[4, "qsoabsfind.absfinder.find_valid_indices", false]], "full_covariance_ew_errors() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.full_covariance_ew_errors", false]], "gauss_two_lines_kernel() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.gauss_two_lines_kernel", false]], "get_metadata() (qsoabsfind.spec.qsospecread method)": [[4, "qsoabsfind.spec.QSOSpecRead.get_metadata", false]], "group_and_weighted_mean_selection_function() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.group_and_weighted_mean_selection_function", false]], "group_contiguous_pixel() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.group_contiguous_pixel", false]], "main() (in module qsoabsfind.parallel_convolution)": [[4, "qsoabsfind.parallel_convolution.main", false]], "measure_absorber_properties_double_gaussian() (in module qsoabsfind.ew)": [[4, "qsoabsfind.ew.measure_absorber_properties_double_gaussian", false]], "median_selection_after_combining() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.median_selection_after_combining", false]], "module": [[3, "module-qsoabsfind", false], [4, "module-qsoabsfind", false], [4, "module-qsoabsfind.absfinder", false], [4, "module-qsoabsfind.absorberutils", false], [4, "module-qsoabsfind.ew", false], [4, "module-qsoabsfind.io", false], [4, "module-qsoabsfind.parallel_convolution", false], [4, "module-qsoabsfind.spec", false], [4, "module-qsoabsfind.utils", false]], "parallel_convolution_method_absorber_finder_qso_spectra() (in module qsoabsfind.parallel_convolution)": [[4, "qsoabsfind.parallel_convolution.parallel_convolution_method_absorber_finder_QSO_spectra", false]], "plot_absorber() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.plot_absorber", false]], "qsoabsfind": [[3, "module-qsoabsfind", false], [4, "module-qsoabsfind", false]], "qsoabsfind.absfinder": [[4, "module-qsoabsfind.absfinder", false]], "qsoabsfind.absorberutils": [[4, "module-qsoabsfind.absorberutils", false]], "qsoabsfind.ew": [[4, "module-qsoabsfind.ew", false]], "qsoabsfind.io": [[4, "module-qsoabsfind.io", false]], "qsoabsfind.parallel_convolution": [[4, "module-qsoabsfind.parallel_convolution", false]], "qsoabsfind.spec": [[4, "module-qsoabsfind.spec", false]], "qsoabsfind.utils": [[4, "module-qsoabsfind.utils", false]], "qsospecread (class in qsoabsfind.spec)": [[4, "qsoabsfind.spec.QSOSpecRead", false]], "read_fits() (qsoabsfind.spec.qsospecread method)": [[4, "qsoabsfind.spec.QSOSpecRead.read_fits", false]], "read_fits_file() (in module qsoabsfind.io)": [[4, "qsoabsfind.io.read_fits_file", false]], "read_single_spectrum_and_find_absorber() (in module qsoabsfind.absfinder)": [[4, "qsoabsfind.absfinder.read_single_spectrum_and_find_absorber", false]], "redshift_estimate() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.redshift_estimate", false]], "remove_mg_falsely_come_from_fe_absorber() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.remove_Mg_falsely_come_from_Fe_absorber", false]], "save_plot() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.save_plot", false]], "save_results_to_fits() (in module qsoabsfind.io)": [[4, "qsoabsfind.io.save_results_to_fits", false]], "single_gaussian() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.single_gaussian", false]], "validate_sizes() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.validate_sizes", false]], "vel_dispersion() (in module qsoabsfind.utils)": [[4, "qsoabsfind.utils.vel_dispersion", false]], "weighted_mean() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.weighted_mean", false]], "z_abs_from_same_metal_absorber() (in module qsoabsfind.absorberutils)": [[4, "qsoabsfind.absorberutils.z_abs_from_same_metal_absorber", false]]}, "objects": {"": [[4, 0, 0, "-", "qsoabsfind"]], "qsoabsfind": [[4, 0, 0, "-", "absfinder"], [4, 0, 0, "-", "absorberutils"], [4, 0, 0, "-", "ew"], [4, 0, 0, "-", "io"], [4, 0, 0, "-", "parallel_convolution"], [4, 0, 0, "-", "spec"], [4, 0, 0, "-", "utils"]], "qsoabsfind.absfinder": [[4, 1, 1, "", "convolution_method_absorber_finder_in_QSO_spectra"], [4, 1, 1, "", "find_valid_indices"], [4, 1, 1, "", "read_single_spectrum_and_find_absorber"]], "qsoabsfind.absorberutils": [[4, 1, 1, "", "absorber_search_window"], [4, 1, 1, "", "contiguous_pixel_remover"], [4, 1, 1, "", "estimate_local_sigma_conv_array"], [4, 1, 1, "", "estimate_snr_for_lines"], [4, 1, 1, "", "group_and_weighted_mean_selection_function"], [4, 1, 1, "", "group_contiguous_pixel"], [4, 1, 1, "", "median_selection_after_combining"], [4, 1, 1, "", "redshift_estimate"], [4, 1, 1, "", "remove_Mg_falsely_come_from_Fe_absorber"], [4, 1, 1, "", "weighted_mean"], [4, 1, 1, "", "z_abs_from_same_metal_absorber"]], "qsoabsfind.ew": [[4, 1, 1, "", "calculate_ew_errors"], [4, 1, 1, "", "double_curve_fit"], [4, 1, 1, "", "full_covariance_ew_errors"], [4, 1, 1, "", "measure_absorber_properties_double_gaussian"]], "qsoabsfind.io": [[4, 1, 1, "", "read_fits_file"], [4, 1, 1, "", "save_results_to_fits"]], "qsoabsfind.parallel_convolution": [[4, 1, 1, "", "main"], [4, 1, 1, "", "parallel_convolution_method_absorber_finder_QSO_spectra"]], "qsoabsfind.spec": [[4, 2, 1, "", "QSOSpecRead"]], "qsoabsfind.spec.QSOSpecRead": [[4, 3, 1, "", "__init__"], [4, 3, 1, "", "get_metadata"], [4, 3, 1, "", "read_fits"]], "qsoabsfind.utils": [[4, 1, 1, "", "convolution_fun"], [4, 1, 1, "", "double_gaussian"], [4, 1, 1, "", "elapsed"], [4, 1, 1, "", "gauss_two_lines_kernel"], [4, 1, 1, "", "plot_absorber"], [4, 1, 1, "", "save_plot"], [4, 1, 1, "", "single_gaussian"], [4, 1, 1, "", "validate_sizes"], [4, 1, 1, "", "vel_dispersion"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method"}, "terms": {"": [2, 4], "0": 4, "0001": 4, "1": 4, "10": [], "1000": 2, "1093": [], "1548": [0, 1], "1550": [0, 1], "15842": [], "16": [0, 2], "2": 4, "200": 4, "2021": 1, "2021mnra": [], "2103": [], "2586": 4, "2600": 4, "2796": [0, 1], "2803": [0, 1], "2d": 4, "3": [2, 4], "4": [0, 2, 4], "5": 4, "500": [0, 2], "504": [], "6": [2, 4], "65": [], "65a": [], "6a": 4, "7": 4, "8": 4, "88": [], "A": 4, "As": 2, "If": [0, 1, 4], "In": 2, "The": [0, 1, 4], "Then": [0, 2], "With": 4, "_": 0, "__init__": 4, "_ew": 0, "_ew_error": 0, "_ew_tot": 0, "_ew_total_error": 0, "ab": [], "abhi0395": 2, "abhijeet": 1, "abhijeetanand2011": 1, "abs_z": 4, "absorb": [0, 1, 2, 4], "absorber_redshift": 4, "absorber_search_window": 4, "absorpt": 4, "abund": [], "access": 2, "accur": 1, "adapt": [1, 4], "add": 4, "adsab": [], "adsnot": [], "adsurl": [], "after": [2, 4], "algorithm": 4, "all": 4, "allow": 4, "alreadi": 4, "also": 0, "amp": 4, "amp1": 4, "amp2": 4, "amp_ratio": 4, "amplitud": 4, "an": [0, 2, 4], "anand": 1, "ang": 4, "angstrom": 0, "ani": [1, 4], "api": 1, "appli": [1, 4], "approach": 1, "approxim": 2, "ar": 4, "archiveprefix": [], "aris": 4, "around": 4, "arrai": [0, 4], "arrang": 4, "articl": [], "arxiv": [], "assert": 4, "assertionerror": 4, "assum": 4, "astro": [], "astrophys": [], "astropi": 2, "author": [0, 2], "avail": [1, 2], "averag": 4, "avg": 4, "axi": 4, "base": [1, 2, 4], "bashrc": 0, "basic": 4, "becom": 2, "been": 4, "befor": [0, 2], "being": 4, "below": [0, 2], "berkelei": 1, "beta": 4, "bibtex": 1, "bin": 4, "blob": [], "bool": 4, "both": 4, "bottleneck": 2, "bound": 4, "br": [], "c1": 4, "c2": 4, "calcul": 4, "calculate_ew_error": 4, "callabl": 4, "can": [0, 1, 2], "case": [], "cd": 2, "center": [1, 4], "centr": 4, "character": [], "check": [1, 4], "check_error_on_residu": [], "chunk": 2, "circumgalact": [], "cite": 1, "civ": [0, 1, 4], "civ1548": 4, "civ1550": 4, "class": 4, "code": [0, 1, 2], "coeff_sigma": 4, "coeffici": 4, "com": [1, 2], "combin": 4, "combined_final_our_z": 4, "command": 0, "common": 4, "comput": [1, 4], "condit": 4, "consid": 2, "constant_fil": [], "contain": [0, 2, 4], "contigu": 4, "contiguous_pixel_remov": 4, "continuum": [0, 2, 4], "conv_arr": 4, "conv_arrai": 4, "convolut": [1, 4], "convolution_fun": 4, "convolution_method_absorber_finder_in_qso_spectra": 4, "convolv": 4, "cool": [], "correct": 4, "correspond": 4, "covari": 4, "cpu": 2, "criteria": 4, "current": [1, 2, 4], "curv": 4, "curve_fit": 4, "curvey_fit": 4, "custom": 0, "d_pix": 4, "data": [0, 2, 4], "debug": 4, "dec": 0, "dec_qso": 0, "decid": [2, 4], "default": [0, 4], "defin": [0, 4], "delta": 4, "describ": [0, 2], "desi": 1, "design": 1, "detail": 0, "detect": [1, 4], "determin": 4, "deviat": 4, "dict": 4, "dictionari": 4, "differ": 4, "directori": 4, "discov": 2, "dispers": [0, 4], "distanc": 4, "divid": [2, 4], "dlam": 4, "do": 4, "doi": [], "doubl": [0, 1, 4], "double_curve_fit": 4, "double_gaussian": 4, "doublet": [0, 1, 4], "down": 4, "dr16": [], "due": 4, "dupon": 4, "dure": 4, "dylan": [], "dynam": [0, 4], "e": [0, 4], "each": [2, 4], "edg": 4, "edu": [], "effici": 1, "elaps": 4, "element": 4, "end": 2, "ensur": 2, "entri": 1, "environ": 0, "eprint": [], "equival": [0, 1, 4], "err_residu": 4, "error": [0, 4], "error_fit": 4, "errror": 4, "estim": 4, "estimate_local_sigma_conv_arrai": 4, "estimate_snr_for_lin": 4, "evalu": 4, "evolut": [], "ew": [0, 1], "ew1": 4, "ew1_error": 4, "ew2": 4, "ew2_error": 4, "ew_first": 4, "ew_first_lin": 4, "ew_first_line_error": 4, "ew_second": 4, "ew_second_lin": 4, "ew_second_line_error": 4, "ew_tot": 4, "ew_total_error": 4, "exampl": 0, "exploit": 4, "expon": 4, "extens": [0, 1, 4], "factor": 4, "fail": [0, 2], "fals": [1, 4], "falslei": 4, "fe": 4, "featur": 4, "feel": 1, "feii": 4, "file": [1, 2, 4], "filenam": 4, "final": 4, "find": [1, 4], "find_valid_indic": 4, "finder": 4, "first": [2, 4], "first_list_z": 4, "fit": [1, 2, 4], "fits_fil": 4, "fitted_obs_l1": 4, "fitted_obs_l2": 4, "fitting_param_for_spectrum": 4, "fitting_param_std_for_spectrum": 4, "float": 4, "flux": [0, 4], "follow": [0, 2, 4], "format": [1, 2], "found": 1, "frame": [0, 4], "free": 1, "from": [0, 4], "full": 1, "full_covariance_ew_error": 4, "fun_to_run": 4, "function": 4, "g": [0, 4], "ga": [], "galaxi": [], "gamma": 4, "gauss_fit": 0, "gauss_fit_std": 0, "gauss_two_lines_kernel": 4, "gaussian": [0, 1, 4], "gener": 4, "get_metadata": 4, "get_tgtdetail": [], "git": 2, "github": 2, "given": 4, "gmail": 1, "group": 4, "group_and_weighted_mean_selection_funct": 4, "group_contiguous_pixel": 4, "guinever": [], "ha": 4, "handl": 4, "harvard": [], "have": [0, 1, 2, 4], "hdu": 0, "header": [0, 2, 4], "here": 1, "higher": 2, "html": [], "http": 2, "i": [0, 1, 2, 4], "idea": 2, "ideal": 0, "identifi": [1, 4], "import": 0, "includ": [0, 4], "index": [0, 1, 4], "index_spec": 0, "indic": 4, "individu": 2, "info": 4, "init_cond": 4, "initi": [3, 4], "input": [2, 4], "input_fits_fil": [], "inset": 4, "instal": 1, "instrument": 4, "int": 4, "intens": 2, "issu": 1, "iter": 4, "iter_n": 4, "its": 4, "job": 4, "journal": [], "jun": [], "kauffmann": 1, "ker_width_pix": 4, "ker_width_pixel": 4, "kernel": 4, "key1": [], "key2": [], "keyword": 4, "kinemat": [], "km": 4, "kwarg": 4, "l1": 4, "l2": 4, "lab": 1, "label": 4, "lam": 4, "lam_fit_rang": 4, "lam_ob": 4, "lam_rest": 4, "lam_search": 4, "lambda": 4, "larg": [1, 2], "larger": 2, "lawrenc": 1, "lbnl": [], "less": 4, "like": 4, "line": [0, 1, 4], "line1": 4, "line2": 4, "list": 4, "load": [0, 4], "local": [2, 4], "log": 4, "logscal": 4, "logwav": 4, "look": 4, "lot": 4, "m": 2, "machin": 2, "mai": 2, "main": 4, "mani": 4, "mask": 4, "master_list_of_pot_absorb": 4, "match": 4, "matplotlib": 2, "matrix": 4, "max_wav": 4, "maximum": 4, "mean": 4, "mean1": 4, "mean2": 4, "mean_sn1": 4, "mean_sn2": 4, "measur": [0, 1, 4], "measure_absorber_properties_double_gaussian": 4, "median": 4, "median_selection_after_combin": 4, "medium": [], "memori": 2, "merg": 2, "messag": 4, "metadata": [0, 4], "metal": [0, 4], "method": 4, "mg": 4, "mgii": [0, 1, 2, 4], "mgii2796": 4, "mgii2803": 4, "min_wav": 4, "minimum": 4, "mnra": [], "mode": 2, "model": 4, "modul": 1, "month": [], "most": 4, "msg": 4, "mult_resi": 4, "multiprocess": 4, "must": [0, 4], "n": [0, 1, 2, 4], "n_job": 4, "name": 4, "nan": 4, "nasa": [], "nation": 1, "ncpu": [0, 2], "ndarrai": 4, "nelson": 1, "new": [0, 4], "nmf_resi_fit": 4, "node": 2, "nois": [0, 4], "none": 4, "normal": [0, 2, 4], "note": 4, "np": 4, "numba": 2, "number": [1, 2, 4], "numpi": [2, 4], "ob": 4, "object": 4, "observ": [0, 4], "onli": [1, 4], "open": 1, "oper": 4, "optim": 4, "option": 4, "order": 2, "oscil": 4, "otherwis": 0, "our_z": 4, "output": [2, 4], "output_fil": 4, "output_fits_fil": [], "over": 4, "own": 0, "packag": 1, "page": 1, "paper": 1, "parallel": [1, 2, 4], "parallel_convolution_method_absorber_finder_qso_spectra": 4, "param": 4, "paramet": [0, 4], "path": 4, "path_to_input_fits_fil": [], "path_to_output_fits_fil": [], "path_to_your_fil": 0, "pcov": 4, "perform": 4, "perr": 4, "ph": [], "pip": 2, "pixel": 4, "pleas": [0, 1, 2], "plot": 4, "plot_absorb": 4, "plot_filenam": 4, "pm_pixel": 4, "png": 4, "point": [0, 4], "popt": 4, "posit": [1, 4], "potenti": [1, 4], "power": 4, "prefer": 1, "prepar": 4, "previous": 4, "primaryclass": [], "print": 4, "process": [1, 2, 4], "profil": 4, "properti": [1, 4], "provid": [0, 2, 4], "py": [], "pytest": 2, "python": [1, 2], "qso": [0, 1, 2, 4], "qso_constants_fil": 0, "qso_test": [0, 2], "qsoabsfind": [0, 2], "qsoabsfind_plot": 4, "qsospecread": 4, "quadratur": 4, "quasar": [0, 1, 4], "question": 1, "ra": 0, "ra_qso": 0, "rais": 4, "rang": 4, "ratio": [0, 4], "raw": [], "read": [0, 2, 4], "read_fit": 4, "read_fits_fil": 4, "read_single_spectrum_and_find_absorb": 4, "real": 4, "redshift": [0, 4], "redshift_estim": 4, "refer": 1, "region": 4, "reject": [1, 4], "relat": 4, "remov": 4, "remove_mg_falsely_come_from_fe_absorb": 4, "remove_mg_falsely_identified_as_fe_absorb": [], "repo": 1, "requir": 0, "research": 1, "resi": 4, "residu": [0, 4], "residual_arr_after_mask": 4, "residual_our_z": 4, "resolut": 4, "resoult": 4, "rest": [0, 4], "result": [2, 4], "retriev": 4, "return": 4, "right": 2, "row": 4, "rule": 2, "run": [0, 4], "same": [0, 4], "sao": [], "save": 4, "save_param_arrai": 4, "save_param_error": 4, "save_plot": 4, "save_results_to_fit": 4, "scale": 4, "scheme": 4, "scipi": [2, 4], "script": 4, "sdss": [0, 1, 2, 4], "search": [0, 1, 4], "second": 4, "see": 1, "select": 4, "separ": 4, "set": 0, "sever": 2, "shift": 4, "should": [0, 4], "show": 4, "sigma": 4, "sigma1": 4, "sigma2": 4, "sigma_cr": 4, "signal": [0, 4], "simpl": 1, "sinc": [0, 4], "singl": 4, "single_gaussian": 4, "size": [2, 4], "smaller": 2, "sn1_all": 4, "sn2_all": 4, "sn_": 0, "sn_line1": 4, "sn_line2": 4, "snr": 4, "some": 4, "sourc": [1, 4], "spec_index": 4, "spec_indic": 4, "specifi": [0, 4], "spectra": [0, 1, 2, 4], "spectral": [0, 4], "spectrum": 4, "split": [2, 4], "stab871": [], "standard": 4, "start": 4, "std_fitted_obs_l1": 4, "std_fitted_obs_l2": 4, "str": 4, "strength": 4, "structur": [], "success": 4, "suggest": [1, 2], "survei": [0, 2], "system": 2, "taken": 4, "task": [0, 2], "test": [0, 2], "test_mgii": [0, 2], "tgtdetail": [], "than": [2, 4], "thi": [0, 1, 2, 4], "threshold": 4, "thumb": 2, "time": 4, "titl": 4, "toler": 4, "toloer": 4, "tool": [0, 1], "total": [0, 2, 4], "total_memori": 2, "true": 4, "tupl": 4, "two": 4, "type": 4, "ui": [], "uncertainti": 0, "uniqu": 4, "unittest": 2, "univers": [], "unmask": 4, "unmsk_error": 4, "unmsk_residu": 4, "up": 4, "updat": 4, "us": [0, 1, 4], "use_covari": 4, "use_kernel": 4, "user": [0, 4], "usual": 0, "v": 4, "valid": 4, "validate_s": 4, "valu": 4, "value1": [], "value2": [], "variabl": 0, "variou": 4, "vel_dispers": 4, "veloc": [0, 4], "verbos": 4, "versa": [], "version": 4, "vice": [], "volum": [], "want": [0, 4], "wave": 4, "wavelength": [0, 4], "weight": 4, "weighted_mean": 4, "when": 2, "where": 4, "which": [0, 2, 4], "width": [0, 1, 4], "window": 4, "within": 4, "without": 0, "work": [1, 4], "would": 2, "wrapper": 4, "write": [1, 4], "x": 4, "xlabel": 4, "y": 4, "year": [], "ylabel": 4, "you": [0, 1, 2], "your": [0, 1, 2], "your_nam": [0, 2], "z": [0, 4], "z_ab": 0, "z_abs_arrai": 4, "z_abs_err": 0, "z_abs_from_same_metal_absorb": 4, "z_after_group": 4, "z_corr": 4, "z_err": 4, "z_qso": [0, 4], "z_valu": 4, "zab": 4, "zoom": 4, "zqso": 4, "zshrc": 0}, "titles": ["File formats", "qsoabsfind\u2019s documentation", "Installation", "qsoabsfind Module", "Full qsoabsfind API reference"], "titleterms": {"": 1, "absfind": 4, "absorberutil": 4, "api": 4, "citat": 1, "clone": 2, "constant": 0, "contact": 1, "content": [1, 4], "document": 1, "ew": 4, "exampl": 2, "featur": 1, "file": 0, "fit": 0, "format": 0, "full": 4, "github": 1, "indic": 1, "input": 0, "instal": 2, "io": 4, "modul": [3, 4], "note": 2, "option": 0, "output": 0, "parallel_convolut": 4, "prerequisit": 2, "qsoabsfind": [1, 3, 4], "refer": 4, "repositori": [1, 2], "run": 2, "spec": 4, "structur": 0, "tabl": 1, "us": 2, "util": 4}}) \ No newline at end of file diff --git a/docs/fileformat.rst b/docs/fileformat.rst index e9fb60a..e6a107a 100644 --- a/docs/fileformat.rst +++ b/docs/fileformat.rst @@ -11,18 +11,27 @@ The input `fits file` must have the following HDU extensions: - **ERROR**: Error on residuals. - **METADATA**: Spectral details (such as Z_QSO, RA_QSO, DEC_QSO). +I have also provided an example QSO spectra FITS file, `data/qso_test.fits`, which contains 500 continuum-normalized SDSS QSO spectra. You can use this file to test an example run as described below. + Constant File (Optional) ------------------------ -Before using your own constant file, please set an environment variable `QSO_CONSTANTS_FILE` in your bashrc or zshrc file and point it to the qsoabsfind.constants file. As the code loads the constants from new file dynamically, it is important to define this environment variable. +Before using your own constants file, please set an environment variable `QSO_CONSTANTS_FILE` in your `bashrc` or `zshrc` file, and point it to the `qsoabsfind.constants` file. Since the code dynamically loads constants from a new file, it is important to define this environment variable. -The user-defined **constant-file** must follow the same structure as the `qsoabsfind.constants` file, otherwise, the code will fail. If you want to use the default search parameters, you can run the tool without the `constant-file` option. +The user-defined **constants file** must follow the same structure as the `qsoabsfind.constants `_ file; otherwise, the code will fail. If you want to use the default search parameters, you can run the tool without specifying the `constant-file` option. Then run `qsoabsfind` with the required FITS file. If using a custom constant file, include it in the command: :: - qsoabsfind --input [--constant-file ] --output + qsoabsfind --input-fits-file data/qso_test.fits \ + --n-qso 500 \ + --absorber MgII \ + --output test_MgII.fits \ + --headers SURVEY=SDSS AUTHOR=YOUR_NAME \ + --n-tasks 16 \ + --ncpus 4 + --constant-file path_to_your_file Output FITS File Structure -------------------------- @@ -31,11 +40,11 @@ The **output** `fits file` will have the `ABSORBER` HDU, containing arrays such - **INDEX_SPEC**: Index of quasar (can be used to read the RA, DEC, and Z of QSOs). - **Z_ABS**: Redshift of absorber. -- **${METAL}_${line}_EW**: Rest-frame equivalent widths (EWs) of absorber lines (e.g., MgII 2796, 2803 or CIV 1548, 1550) in Angstroms. -- **${METAL}_${line}_EW_ERROR**: Uncertainties in rest-frame EWs of absorber lines in Angstroms. +- **${METAL}_${LINE}_EW**: Rest-frame equivalent widths (EWs) of absorber lines (e.g., MgII 2796, 2803 or CIV 1548, 1550) in Angstroms. +- **${METAL}_${LINE}_EW_ERROR**: Uncertainties in rest-frame EWs of absorber lines in Angstroms. - **Z_ABS_ERR**: Measured error in the redshift of the absorber. - **GAUSS_FIT**: Rest-frame fitting parameters of double Gaussian to the absorber doublet (the width can be used to measure the velocity dispersion). - **GAUSS_FIT_STD**: Uncertainties in rest-frame fitting parameters of double Gaussian to the absorber doublet. -- **SN_${METAL}_${line}**: Signal-to-noise ratio of the lines. -- **${metal}_EW_TOTAL**: Total EW of the lines in Angstroms. -- **${metal}_EW_TOTAL_ERROR**: Uncertainties in total EW of the lines in Angstroms. +- **SN_${METAL}_${LINE}**: Signal-to-noise ratio of the lines. +- **${METAL}_EW_TOTAL**: Total EW of the lines in Angstroms. +- **${METAL}_EW_TOTAL_ERROR**: Uncertainties in total EW of the lines in Angstroms. diff --git a/docs/index.rst b/docs/index.rst index 9671708..d7ddaa2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,7 +26,7 @@ Features GitHub repository ----------------- -The source code is available on GitHub. Please see the `qsoabsfind repo `_. +The source code is available on GitHub. Please see the `qsoabsfind `_ repo. Citation @@ -38,9 +38,10 @@ Please cite `Anand, Nelson & Kauffmann 2021 `_ Contact ------- -Abhijeet Anand, LBNL +| Abhijeet Anand +| Lawrence Berkeley National Lab -If you have any questions/suggestions, please feel free to write to abhijeetanand2011 [at] gmail.com +If you have any questions/suggestions, please feel free to write to abhijeetanand2011 [at] gmail.com or, preferably, open a GitHub issue. Indices and tables diff --git a/docs/installation.rst b/docs/installation.rst index b9f11b5..c5d1c35 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -27,14 +27,27 @@ First, clone the repository to your local machine: Running example: ---------------- -Before running, please read :doc:`File formats `. +Before running, please read :doc:`File formats `. I have provided an example QSO spectra FITS file, `data/qso_test.fits`, which contains 500 continuum-normalized SDSS QSO spectra. You can use this file to test an example run as described below. .. code-block:: bash - qsoabsfind --input-fits-file path_to_input_fits_file.fits \ - --n-qso 1-1000:10 \ + qsoabsfind --input-fits-file data/qso_test.fits \ + --n-qso 500 \ --absorber MgII \ - --output path_to_output_fits_file.fits \ - --headers KEY1=VALUE1 KEY2=VALUE2 \ + --output test_MgII.fits \ + --headers SURVEY=SDSS AUTHOR=YOUR_NAME \ --n-tasks 16 \ --ncpus 4 + +Useful notes: +------------- + +Parallel mode can be memory-intensive if the input FITS file is large in size. As the code accesses the FITS file to read QSO spectra when running in parallel, it can become a bottleneck for memory, and the code may fail. Currently, I suggest the following: + + - **Divide your file into smaller chunks:** Split the FITS file into several smaller files, each containing approximately `N` spectra. Then run the code on these smaller files. + + - **Use a rule of thumb for file size:** Ensure that the size of each individual file is no larger than `total_memory/ncpu` of your node or system. Based on this idea you can decide your `N`. I would suggest `N = 1000`. + + - **Merge results at the end:** After processing, you can merge your results. + +In order to decide the right size of the FITS file, consider the total available memory and the number of CPUs in your system. diff --git a/qsoabsfind/spec.py b/qsoabsfind/spec.py index b1adde0..bdca700 100644 --- a/qsoabsfind/spec.py +++ b/qsoabsfind/spec.py @@ -8,7 +8,7 @@ class QSOSpecRead: """ - A class to read and handle QSO spectra from a FITS file containing FLUX, ERROR, WAVELENGTH, and TGTDETAILS extensions.""" + A class to read and handle QSO spectra from a FITS file containing FLUX, ERROR, WAVELENGTH, and METADATA extensions.""" def __init__(self, fits_file, index=None): """ @@ -35,12 +35,12 @@ def read_fits(self): self.flux, self.error, self.wavelength, self.metadata = read_fits_file(self.fits_file, self.index) elapsed(start_time, "\nTime taken to read FITS file") - def get_tgtdetails(self): + def get_metadata(self): """ - Returns the TGTDETAILS data with keyword handling. + Returns the METADATA data with keyword handling. Returns: - dict: The tgtdetails data with keywords. + dict: The metadata data with keywords. """ details_dict = {key: self.metadata[key] for key in self.metadata.dtype.names} return details_dict